diff --git a/scripts/core/engine.js b/scripts/core/engine.js index 6119db66..e9894f4f 100644 --- a/scripts/core/engine.js +++ b/scripts/core/engine.js @@ -24,8 +24,6 @@ prosperon.dispatch = function(type, data) { var os = use_embed('os') var js = use_embed('js') -prosperon.on('exit', _ => { console.log('exiting') }) - prosperon.on('SIGINT', function() { os.exit(1) }) @@ -553,6 +551,7 @@ var util = use('util') var math = use('math') var crypto = use('crypto') var nota = use('nota') +var wota = use('wota') var HEADER = Symbol() @@ -765,7 +764,7 @@ function actor_send(actor, message) { } if (actor.__ACTORDATA__.id && os.mailbox_exist(actor.__ACTORDATA__.id)) { - os.mailbox_push(actor.__ACTORDATA__.id, nota.encode(message)) + os.mailbox_push(actor.__ACTORDATA__.id, wota.encode(message)) return } @@ -851,13 +850,15 @@ function handle_actor_disconnect(id) { delete peers[id] } -function handle_message(msg) { - if (msg instanceof ArrayBuffer) - msg = nota.decode(msg) +function handle_local(msg) { + console.log(`got an arraybuffer of length ${msg.byteLength}`) + handle_message(wota.decode(msg)) +} +function handle_message(msg) { if (msg.target) { if (msg.target !== prosperon.id) { - os.mailbox_push(msg.target, nota.encode(msg)) + os.mailbox_push(msg.target, wota.encode(msg)) return } } @@ -913,7 +914,7 @@ var last_t = os.now() while (1) { if (portal) portal.service(handle_host, hang) if (contactor) contactor.service(handle_host, hang) - os.mailbox_service(prosperon.id, handle_message) + os.mailbox_service(prosperon.id, handle_local) var elapsed = os.now() - last_t last_t = os.now() for (var i in timers) { diff --git a/scripts/modules/wota.js b/scripts/modules/wota.js new file mode 100644 index 00000000..0b4b2b77 --- /dev/null +++ b/scripts/modules/wota.js @@ -0,0 +1,43 @@ +// wota +var wota = this + +var json = use('json') + +var encode = wota.encode + +function wota_tostring() +{ + return json.encode(wota.decode(this)) +} + +var wota_obj = { + toString: wota_tostring +} + +wota.encode = function(obj, replacer) +{ + var result = encode(obj, replacer) + result.toString = wota_tostring + return result +} + +wota.encode[prosperon.DOC] = `Convert a JavaScript value into a WOTA-encoded ArrayBuffer. + +This function serializes JavaScript values (such as numbers, strings, booleans, arrays, objects, or ArrayBuffers) into the WOTA binary format. The resulting ArrayBuffer can be stored or transmitted and later decoded back into a JavaScript value. + +:param value: The JavaScript value to encode (e.g., number, string, boolean, array, object, or ArrayBuffer). +:param replacer: An optional function that alters the encoding behavior for specific values. +:return: An ArrayBuffer containing the WOTA-encoded data. +:throws: An error if no argument is provided or if a cyclic object is encountered. +` + +wota.decode[prosperon.DOC] = `Decode a WOTA-encoded ArrayBuffer into a JavaScript value. + +This function deserializes a WOTA-formatted ArrayBuffer into its corresponding JavaScript representation, such as a number, string, boolean, array, object, or ArrayBuffer. If the input is invalid or empty, it returns undefined. + +:param buffer: An ArrayBuffer containing WOTA-encoded data to decode. +:param reviver: An optional function that transforms the decoded values. +:return: The decoded JavaScript value (e.g., number, string, boolean, array, object, or ArrayBuffer), or undefined if no argument is provided. +` + +return wota diff --git a/source/jsffi.c b/source/jsffi.c index 667838f0..9b085ee4 100644 --- a/source/jsffi.c +++ b/source/jsffi.c @@ -7147,9 +7147,14 @@ JSC_CCALL(os_createthread, SDL_DetachThread(thread); ) +struct message { + void *data; + size_t size; +}; + typedef struct mailbox { SDL_Mutex *mutex; - void **messages; + struct message *messages; } mailbox; static struct { char *key; mailbox value; } *mailboxes = NULL; @@ -7157,78 +7162,81 @@ static SDL_Mutex *mailboxes_mutex = NULL; JSC_CCALL(os_mailbox_push, if (argc < 2) return JS_ThrowInternalError(js, "Need an actor and a message"); - char *id = JS_ToCString(js, argv[0]); - void *data = NULL; - if (JS_IsString(argv[1])) - data = (void*)JS_ToCString(js, argv[1]); - else if (JS_IsArrayBuffer(js, argv[1])) { - size_t size; - uint8_t *buf = JS_GetArrayBuffer(js, &size, argv[1]); - data = malloc(size + 1); - memcpy(data, buf, size); - ((char*)data)[size] = 0; - } else return JS_ThrowTypeError(js, "Message must be string or ArrayBuffer"); - + if (!JS_IsArrayBuffer(js, argv[1])) return JS_ThrowInternalError(js, "Object to push into the mailbox must be an array buffer."); + + const char *id = JS_ToCString(js, argv[0]); int mailbox_index = shgeti(mailboxes, id); - if (mailbox_index == -1) { - if (!JS_IsString(argv[1])) free(data); - JS_FreeCString(js, id); + JS_FreeCString(js, id); + + if (mailbox_index == -1) return JS_ThrowInternalError(js, "No mailbox found for given ID"); - } + + size_t size; + uint8_t *buf = JS_GetArrayBuffer(js, &size, argv[1]); + + if (!buf) return JS_ThrowInternalError(js, "Could not get data from arraybuffer."); + + void *data = malloc(size); + if (!data) return JS_ThrowInternalError(js, "Memory allocation failed."); + + memcpy(data,buf,size); mailbox *mb = &mailboxes[mailbox_index].value; SDL_LockMutex(mb->mutex); - arrput(mb->messages, data); + struct message msg = {data, size}; + arrput(mb->messages, msg); SDL_UnlockMutex(mb->mutex); - - JS_FreeCString(js, id); ) -JSC_CCALL(os_mailbox_service, - char *id = JS_ToCString(js, argv[0]); - JSValue fn = JS_DupValue(js, argv[1]); +void js_dofree(JSRuntime *rt, void *opaque, void *ptr) +{ + js_free_rt(rt, ptr); +} +JSC_CCALL(os_mailbox_service, + if (!JS_IsFunction(js, argv[1])) return JS_ThrowInternalError(js, "Arg 2 must be a function"); + + const char *id = JS_ToCString(js, argv[0]); int mb_index = shgeti(mailboxes, id); - if (mb_index == -1) { - JS_FreeCString(js, id); - JS_FreeValue(js, fn); - return JS_ThrowInternalError(js, "No mailbox found for given ID"); - } + JS_FreeCString(js, id); + + if (mb_index == -1) return JS_ThrowInternalError(js, "No mailbox found for given ID"); mailbox *mb = &mailboxes[mb_index].value; - void **temp = NULL; + struct message *temp = NULL; SDL_LockMutex(mb->mutex); int count = arrlen(mb->messages); if (count > 0) { arrsetlen(temp, count); - memcpy(temp, mb->messages, sizeof(void*) * count); + memcpy(temp, mb->messages, sizeof(*mb->messages) * count); arrsetlen(mb->messages, 0); } SDL_UnlockMutex(mb->mutex); + if (count == 0) return JS_UNDEFINED; + + JSValue fn = JS_DupValue(js, argv[1]); + for (int i = 0; i < count; i++) { - void *data = temp[i]; - JSValue arg = JS_IsString(argv[1]) ? JS_NewString(js, (char*)data) : JS_NewArrayBufferCopy(js, data, strlen(data)); + JSValue arg = JS_NewArrayBuffer(js, temp[i].data, temp[i].size, js_dofree, NULL, 0); JSValue call = JS_Call(js, fn, JS_UNDEFINED, 1, &arg); uncaught_exception(js, call); - JS_FreeValue(js, arg); - free(data); + JS_FreeValue(js,arg); } + arrfree(temp); - - JS_FreeCString(js, id); JS_FreeValue(js, fn); ) JSC_CCALL(os_mailbox_exist, - char *id = JS_ToCString(js, argv[0]); + const char *id = JS_ToCString(js, argv[0]); bool exists = shgeti(mailboxes, id) != -1; JS_FreeCString(js, id); return JS_NewBool(js, exists); ) JSC_CCALL(os_mailbox_start, - char *id = JS_ToCString(js, argv[0]); + const char *id = JS_ToCString(js, argv[0]); mailbox mb; mb.mutex = SDL_CreateMutex(); mb.messages = NULL; @@ -7678,7 +7686,6 @@ static void signal_handler(int sig) { JSContext *js = SDL_GetTLS(&js_id); - printf("dispatching to js %p\n", js); script_evalf(js, "prosperon.dispatch('%s')", str); } diff --git a/source/qjs_wota.c b/source/qjs_wota.c index 5c1979e1..ea8fb132 100644 --- a/source/qjs_wota.c +++ b/source/qjs_wota.c @@ -310,8 +310,8 @@ static JSValue js_wota_decode(JSContext *ctx, JSValueConst this_val, int argc, J } static const JSCFunctionListEntry js_wota_funcs[] = { - JS_CFUNC_DEF("encode", 1, js_wota_encode), - JS_CFUNC_DEF("decode", 1, js_wota_decode), + JS_CFUNC_DEF("encode", 2, js_wota_encode), + JS_CFUNC_DEF("decode", 2, js_wota_decode), }; static int js_wota_init(JSContext *ctx, JSModuleDef *m) diff --git a/source/qjs_wota.h b/source/qjs_wota.h index 569ad2ac..265675b5 100644 --- a/source/qjs_wota.h +++ b/source/qjs_wota.h @@ -5,4 +5,7 @@ JSValue js_wota_use(JSContext*); +void *value2wota(JSContext*, JSValue); +JSValue wota2value(JSContext*, void*); + #endif diff --git a/source/script.c b/source/script.c index 3a102e11..d0f8255f 100644 --- a/source/script.c +++ b/source/script.c @@ -180,6 +180,7 @@ void script_startup(int argc, char **argv) { void script_stop(JSContext *js) { + printf("STOPPING CONTEXT %p\n", js); return; JSValue *onexp = SDL_GetTLS(&on_exception); JS_FreeValue(js,*onexp); diff --git a/tests/overling.js b/tests/overling.js index e8083c73..ec95ca13 100644 --- a/tests/overling.js +++ b/tests/overling.js @@ -1,6 +1,5 @@ var os = use('os') -$_.delay(_ => { $_.start(e => { switch(e.type) { case "actor_started": @@ -15,4 +14,3 @@ $_.start(e => { $_.stop() } }, "tests/underling.js"); -}, 3) diff --git a/tests/portalspawner.js b/tests/portalspawner.js index 350c2fdc..1b24dba2 100644 --- a/tests/portalspawner.js +++ b/tests/portalspawner.js @@ -8,4 +8,5 @@ os.createprocess(["./prosperon", "tests/portal.js"]) $_.delay(_ => { os.createprocess(["./prosperon", "tests/contact.js"]) + $_.stop() }, 0.2)