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