diff --git a/src/Generator/Generators/QuickJS/QuickJSModule.cs b/src/Generator/Generators/QuickJS/QuickJSModule.cs
index 13da86a8..b918bf3a 100644
--- a/src/Generator/Generators/QuickJS/QuickJSModule.cs
+++ b/src/Generator/Generators/QuickJS/QuickJSModule.cs
@@ -23,14 +23,11 @@ namespace CppSharp.Generators.Cpp
public override void Process()
{
GenerateFilePreamble(CommentKind.BCPL);
+ NewLine();
PushBlock(BlockKind.Includes);
{
- WriteInclude(new CInclude()
- {
- File = "quickjs.h",
- Kind = CInclude.IncludeKind.Angled
- });
+ WriteInclude("CppSharp_QuickJS.h", CInclude.IncludeKind.Angled);
foreach (var unit in TranslationUnits)
{
diff --git a/src/Generator/Generators/QuickJS/QuickJSSources.cs b/src/Generator/Generators/QuickJS/QuickJSSources.cs
index 7c6551b2..2b184795 100644
--- a/src/Generator/Generators/QuickJS/QuickJSSources.cs
+++ b/src/Generator/Generators/QuickJS/QuickJSSources.cs
@@ -27,7 +27,7 @@ namespace CppSharp.Generators.Cpp
PushBlock(BlockKind.Includes);
{
- WriteInclude("quickjs.h", CInclude.IncludeKind.Angled);
+ WriteInclude("CppSharp_QuickJS.h", CInclude.IncludeKind.Angled);
WriteInclude("assert.h", CInclude.IncludeKind.Angled);
foreach (var unit in TranslationUnits)
diff --git a/src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.cpp b/src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.cpp
new file mode 100644
index 00000000..4798f8dd
--- /dev/null
+++ b/src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.cpp
@@ -0,0 +1,13 @@
+#include "CppSharp_QuickJS.h"
+
+extern "C"
+{
+
+extern void register_signal(JSContext *ctx, JSModuleDef *m, bool set, int phase);
+
+void register_CppSharp_QuickJS(JSContext *ctx, JSModuleDef *m, bool set, int phase)
+{
+ register_signal(ctx, m, set, phase);
+}
+
+} // extern "C"
diff --git a/src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.h b/src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.h
new file mode 100644
index 00000000..0860be71
--- /dev/null
+++ b/src/Generator/Generators/QuickJS/Runtime/CppSharp_QuickJS.h
@@ -0,0 +1,257 @@
+// ----------------------------------------------------------------------------
+//
+// This is autogenerated code by CppSharp.
+// Do not edit this file or all your changes will be lost after re-generation.
+//
+// ----------------------------------------------------------------------------
+
+extern "C"
+{
+
+#include
+#include
+
+#if defined(__GNUC__) || defined(__clang__)
+#define js_force_inline inline __attribute__((always_inline))
+#else
+#define js_force_inline inline
+#endif
+
+#define countof(x) (sizeof(x) / sizeof((x)[0]))
+
+enum
+{
+ __JS_ATOM_NULL = JS_ATOM_NULL,
+#define DEF(name, str) JS_ATOM_ ## name,
+#include
+#undef DEF
+ JS_ATOM_END,
+};
+
+struct JS_SignalContext
+{
+ // TODO: List
+ JSValue function;
+ JSValue link;
+ JSContext *ctx;
+};
+
+typedef int JS_EventId;
+typedef int JS_ClassId;
+typedef DynBuf JS_EventMap;
+
+struct JS_EventEntry
+{
+ JS_EventId eventId;
+ JSValue value;
+};
+
+static JS_EventMap* JS_Interop_InitEventMap(JS_EventMap* map)
+{
+ dbuf_init(map);
+ return map;
+}
+
+static void JS_Interop_FreeEventMap(JSContext* ctx, JS_EventMap* map)
+{
+ JS_EventEntry* events = (JS_EventEntry*) map->buf;
+ int numEvents = (map->size / sizeof(JS_EventEntry));
+ for (int i = 0; i < numEvents; i++)
+ if (!JS_IsUndefined(events[i].value))
+ JS_FreeValue(ctx, events[i].value);
+
+ dbuf_free(map);
+}
+
+static int JS_Interop_BinarySearch(JS_EventEntry* arr, int l, int r, JS_EventId id)
+{
+ if (r >= l) {
+ int mid = l + (r - l) / 2;
+
+ // If the element is present at the middle itself
+ if (arr[mid].eventId == id)
+ return mid;
+
+ // If element is smaller than mid, then it can only be present in left subarray
+ if (arr[mid].eventId > id)
+ return JS_Interop_BinarySearch(arr, l, mid - 1, id);
+
+ // Else the element can only be present in right subarray
+ return JS_Interop_BinarySearch(arr, mid + 1, r, id);
+ }
+
+ // We reach here when element is not present in array
+ return -1;
+}
+
+static JSValue JS_Interop_FindEvent(JS_EventMap* map, JS_EventId eventId)
+{
+ JS_EventEntry* events = (JS_EventEntry*) map->buf;
+ int numEvents = (map->size / sizeof(JS_EventEntry));
+ if (numEvents == 0)
+ return JS_UNDEFINED;
+
+ int index = JS_Interop_BinarySearch(events, 0, numEvents, eventId);
+ return index >= 0 ? events[index].value : JS_UNDEFINED;
+}
+
+static int JS_Interop_InsertEvent(JS_EventMap* map, JS_EventId eventId,
+ JSValue value)
+{
+ JS_EventEntry* events = (JS_EventEntry*) map->buf;
+ int numEvents = (map->size / sizeof(JS_EventEntry));
+
+ int index = 0;
+ for (int i = 0; i < numEvents; i++)
+ {
+ if (events[i].eventId == eventId) { index=-1; break; }
+ if (events[i].eventId > eventId) { index = i; break; }
+ index++;
+ }
+
+ if (index == -1)
+ return -1;
+
+ JS_EventEntry entry;
+ entry.eventId = eventId;
+ entry.value = value;
+
+ dbuf_write(map, index * sizeof(JS_EventEntry), (const uint8_t*) &entry,
+ sizeof(JS_EventEntry));
+
+ return 0;
+}
+
+static JSValue JS_Interop_InvokeConstructor(JSContext *ctx, JS_ClassId eventId,
+ JSValue argv[], int argc)
+{
+ // TODO: Error handling.
+ JSValue proto = JS_GetClassProto(ctx, eventId);
+ JSValue ctor = JS_GetProperty(ctx, proto, JS_ATOM_constructor);
+ JSValue instance = JS_CallConstructor(ctx, ctor, argc, argv);
+ JS_FreeValue(ctx, ctor);
+ JS_FreeValue(ctx, proto);
+
+ return instance;
+}
+
+enum JS_Interop_InstanceKind
+{
+ JS_INTEROP_INSTANCE_RAW_POINTER = 1,
+ JS_INTEROP_INSTANCE_SIGNAL_CONTEXT,
+};
+
+struct JS_Interop_ClassData
+{
+ void* instance;
+ JSContext* ctx;
+ JS_EventMap events;
+};
+
+static JSValue JS_Interop_InitObject(JSContext *ctx, JSValue obj, JS_Interop_InstanceKind kind,
+ void* instance)
+{
+ switch (kind)
+ {
+ case JS_INTEROP_INSTANCE_RAW_POINTER:
+ JS_SetOpaque(obj, instance);
+ return obj;
+ case JS_INTEROP_INSTANCE_SIGNAL_CONTEXT:
+ JS_Interop_ClassData* data = (JS_Interop_ClassData*) js_mallocz(ctx, \
+ sizeof(JS_Interop_ClassData));
+ data->ctx = ctx;
+ data->instance = instance;
+ JS_Interop_InitEventMap(&data->events);
+ JS_SetOpaque(obj, data);
+ return obj;
+ }
+
+ return JS_UNDEFINED;
+}
+
+static JSValue JS_Interop_CleanupObject(JSValue obj, JS_Interop_InstanceKind kind)
+{
+ switch (kind)
+ {
+ case JS_INTEROP_INSTANCE_SIGNAL_CONTEXT:
+ JS_Interop_ClassData* data = (JS_Interop_ClassData*) JS_GetOpaque(obj, 0);
+ JS_Interop_FreeEventMap(data->ctx, &data->events);
+ js_free(data->ctx, data);
+ }
+
+ return JS_UNDEFINED;
+}
+
+static void* JS_Interop_GetInstance(JSValue obj, JS_ClassId classId, JS_Interop_InstanceKind kind)
+{
+ switch (kind)
+ {
+ case JS_INTEROP_INSTANCE_RAW_POINTER:
+ return JS_GetOpaque(obj, classId);
+ case JS_INTEROP_INSTANCE_SIGNAL_CONTEXT:
+ JS_Interop_ClassData* data = (JS_Interop_ClassData*) JS_GetOpaque(obj, classId);
+ return data != nullptr ? data->instance : nullptr;
+ }
+
+ return nullptr;
+}
+
+static JSValue JS_Interop_CreateFromInstance(JSContext* ctx, JS_ClassId classId,
+ JS_Interop_InstanceKind kind, void* instance)
+{
+ if (instance == nullptr)
+ return JS_NULL;
+
+ // TODO: Error handling.
+ JSValue obj = JS_NewObjectClass(ctx, classId);
+ JS_Interop_InitObject(ctx, obj, kind, instance);
+
+ return obj;
+}
+
+static inline JS_BOOL JS_IsInt(JSValueConst v)
+{
+ return JS_IsNumber(v);
+}
+
+static inline JS_BOOL JS_IsInt8(JSValueConst v)
+{
+ return JS_IsInt(v);
+}
+
+static inline JS_BOOL JS_IsUInt8(JSValueConst v)
+{
+ return JS_IsInt(v);
+}
+
+static inline JS_BOOL JS_IsInt16(JSValueConst v)
+{
+ return JS_IsInt(v);
+}
+
+static inline JS_BOOL JS_IsUInt16(JSValueConst v)
+{
+ return JS_IsInt(v);
+}
+
+static inline JS_BOOL JS_IsInt32(JSValueConst v)
+{
+ return JS_IsInt(v);
+}
+
+static inline JS_BOOL JS_IsUInt32(JSValueConst v)
+{
+ return JS_IsInt(v);
+}
+
+static inline JS_BOOL JS_IsFloat(JSValueConst v)
+{
+ int tag = JS_VALUE_GET_TAG(v);
+ return JS_TAG_IS_FLOAT64(tag);
+}
+
+void register_CppSharp_QuickJS(JSContext *ctx, JSModuleDef *m, bool set, int phase);
+
+#undef js_force_inline
+
+} // extern "C"
\ No newline at end of file
diff --git a/src/Generator/Generators/QuickJS/Runtime/Signal.cpp b/src/Generator/Generators/QuickJS/Runtime/Signal.cpp
new file mode 100644
index 00000000..79059df5
--- /dev/null
+++ b/src/Generator/Generators/QuickJS/Runtime/Signal.cpp
@@ -0,0 +1,202 @@
+// ----------------------------------------------------------------------------
+//
+// This is autogenerated code by CppSharp.
+// Do not edit this file or all your changes will be lost after re-generation.
+//
+// ----------------------------------------------------------------------------
+#include
+#include
+
+extern "C" {
+
+JSClassID classId__Signal;
+
+// Signal::Signal
+static JSValue callback_method_Signal_Signal(JSContext* ctx, JSValueConst this_val,
+ int argc, JSValueConst* argv)
+{
+ // if (argc != 1)
+ // {
+ // return JS_ThrowRangeError(ctx, "Unsupported number of arguments");
+ // }
+
+wrap:
+ JSValue proto;
+ if (JS_IsUndefined(this_val))
+ proto = JS_GetClassProto(ctx, classId__Signal);
+ else
+ proto = JS_GetPropertyStr(ctx, this_val, "prototype");
+
+ if (JS_IsException(proto))
+ return proto;
+
+ JSValue __obj = JS_NewObjectProtoClass(ctx, proto, classId__Signal);
+ JS_FreeValue(ctx, proto);
+
+ JS_SignalContext* signalCtx = new JS_SignalContext;
+ signalCtx->ctx = ctx;
+ signalCtx->function = JS_UNDEFINED;
+ signalCtx->link = JS_UNDEFINED;
+
+ if (argc >= 1)
+ {
+ JSValue link = argv[0];
+ assert(JS_IsObject(link));
+ //JS_FreeValue(ctx, link);
+ signalCtx->link = link;
+ }
+
+ JS_SetOpaque(__obj, signalCtx);
+
+ return __obj;
+}
+
+// Signal::connect
+static JSValue callback_method_Signal_connect(JSContext* ctx, JSValueConst this_val,
+ int argc, JSValueConst* argv)
+{
+ if (argc < 1 || argc > 1)
+ {
+ return JS_ThrowRangeError(ctx, "Expected one argument of function type");
+ }
+
+ // Signal* instance = (Signal*) JS_GetOpaque(this_val, classId__Signal);
+
+ if (!JS_IsFunction(ctx, argv[0]))
+ return JS_ThrowTypeError(ctx, "Unsupported argument type");
+
+ // Connect logic
+
+ auto signalCtx = (JS_SignalContext*) JS_GetOpaque(this_val, classId__Signal);
+ if (signalCtx == nullptr)
+ return JS_ThrowTypeError(ctx, "Could not find signal context");
+
+ assert(JS_IsObject(signalCtx->link));
+
+ if (!JS_IsUndefined(signalCtx->function))
+ return JS_ThrowRangeError(ctx, "Signal already contains a connected function");
+
+ signalCtx->function = JS_DupValue(ctx, argv[0]);
+
+ JSValue ____ret = JS_NewInt32(ctx, 0);
+
+ return ____ret;
+}
+
+// Signal::disconnect
+static JSValue callback_method_Signal_disconnect(JSContext* ctx, JSValueConst this_val,
+ int argc, JSValueConst* argv)
+{
+ if (argc < 1 || argc > 1)
+ {
+ return JS_ThrowRangeError(ctx, "Unsupported number of arguments");
+ }
+
+ // Signal* instance = (Signal*) JS_GetOpaque(this_val, classId__Signal);
+
+ if (JS_IsNumber(argv[0]))
+ goto overload0;
+
+ goto error;
+
+error:
+ return JS_ThrowTypeError(ctx, "Unsupported argument type");
+
+ // bool disconnect(Slot slot) { return 0; }
+overload0:
+ {
+ int slot;
+ if (JS_ToInt32(ctx, (int32_t*) &slot, argv[0]))
+ return JS_EXCEPTION;
+
+ // auto __arg0 = (::Slot)slot;
+ // bool __ret = instance->disconnect(__arg0);
+
+ JSValue ____ret = JS_NewBool(ctx, 0);
+
+ return ____ret;
+ }
+}
+
+// Signal::isEmpty
+static JSValue callback_method_Signal_isEmpty(JSContext* ctx, JSValueConst this_val,
+ int argc, JSValueConst* argv)
+{
+ if (argc > 0)
+ {
+ return JS_ThrowRangeError(ctx, "Unsupported number of arguments");
+ }
+
+ auto signalCtx = (JS_SignalContext*) JS_GetOpaque(this_val, classId__Signal);
+
+ JSValue ____ret = JS_NewBool(ctx, JS_IsUndefined(signalCtx->function));
+
+ return ____ret;
+}
+
+static JSValue callback_class__Signal_toString(JSContext* ctx, JSValueConst this_val,
+ int argc, JSValueConst* argv)
+{
+ return JS_NewString(ctx, "Signal");
+}
+
+void finalizer__Signal(JSRuntime *rt, JSValue val)
+{
+ auto signalCtx = (JS_SignalContext*) JS_GetOpaque(val, classId__Signal);
+ if (signalCtx == nullptr)
+ return;
+
+ if (!JS_IsUndefined(signalCtx->function))
+ return JS_FreeValue(signalCtx->ctx, signalCtx->function);
+
+ delete signalCtx;
+
+ JS_SetOpaque(val, nullptr);
+
+}
+
+static JSClassDef classDef__Signal
+{
+ "Signal",
+ .finalizer = finalizer__Signal
+};
+
+static JSCFunctionListEntry funcDef__Signal[]
+{
+ JS_CFUNC_DEF("connect", 1, callback_method_Signal_connect),
+ JS_CFUNC_DEF("disconnect", 1, callback_method_Signal_disconnect),
+ JS_CFUNC_DEF("isEmpty", 0, callback_method_Signal_isEmpty),
+ JS_CFUNC_DEF("toString", 0, callback_class__Signal_toString),
+};
+
+static void register_class__Signal(JSContext *ctx, JSModuleDef *m, bool set, int phase)
+{
+ if (!set)
+ {
+ JS_AddModuleExport(ctx, m, "Signal");
+ return;
+ }
+
+ if (phase == 0)
+ {
+ JS_NewClassID(&classId__Signal);
+
+ JS_NewClass(JS_GetRuntime(ctx), classId__Signal, &classDef__Signal);
+
+ JSValue proto = JS_NewObject(ctx);
+ JS_SetPropertyFunctionList(ctx, proto, funcDef__Signal, sizeof(funcDef__Signal) / sizeof(funcDef__Signal[0]));
+ JS_SetClassProto(ctx, classId__Signal, proto);
+
+ JSValue ctor = JS_NewCFunction2(ctx, callback_method_Signal_Signal, "Signal", 1, JS_CFUNC_constructor, 0);
+ JS_SetConstructor(ctx, ctor, proto);
+
+ JS_SetModuleExport(ctx, m, "Signal", ctor);
+ }
+}
+
+void register_signal(JSContext *ctx, JSModuleDef *m, bool set, int phase)
+{
+ register_class__Signal(ctx, m, set, phase);
+}
+
+} // extern "C"
diff --git a/src/Generator/Generators/QuickJS/Runtime/Signal.h b/src/Generator/Generators/QuickJS/Runtime/Signal.h
new file mode 100644
index 00000000..a4490fb8
--- /dev/null
+++ b/src/Generator/Generators/QuickJS/Runtime/Signal.h
@@ -0,0 +1,24 @@
+// ----------------------------------------------------------------------------
+//
+// This is autogenerated code by CppSharp.
+// Do not edit this file or all your changes will be lost after re-generation.
+//
+// ----------------------------------------------------------------------------
+#pragma once
+
+#include
+
+class Signal
+{
+public:
+
+ Signal();
+
+ ~Signal();
+
+ int connect(void (*function)());
+
+ bool disconnect(int slot);
+
+ bool isEmpty();
+};
diff --git a/src/Generator/Generators/QuickJS/Runtime/premake5.lua b/src/Generator/Generators/QuickJS/Runtime/premake5.lua
new file mode 100644
index 00000000..db431351
--- /dev/null
+++ b/src/Generator/Generators/QuickJS/Runtime/premake5.lua
@@ -0,0 +1,2 @@
+project "cppsharp-quickjs-runtime"
+ files { "" }
\ No newline at end of file