use wota for on machine message passing

This commit is contained in:
2025-03-13 17:20:04 -05:00
parent 88d5f6455b
commit 38da997069
8 changed files with 105 additions and 51 deletions

View File

@@ -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) {

43
scripts/modules/wota.js Normal file
View File

@@ -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

View File

@@ -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])) {
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);
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]);
data = malloc(size + 1);
memcpy(data, buf, size);
((char*)data)[size] = 0;
} else return JS_ThrowTypeError(js, "Message must be string or ArrayBuffer");
int mailbox_index = shgeti(mailboxes, id);
if (mailbox_index == -1) {
if (!JS_IsString(argv[1])) free(data);
JS_FreeCString(js, id);
return JS_ThrowInternalError(js, "No mailbox found for given ID");
}
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");
}
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);
arrfree(temp);
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);
}

View File

@@ -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)

View File

@@ -5,4 +5,7 @@
JSValue js_wota_use(JSContext*);
void *value2wota(JSContext*, JSValue);
JSValue wota2value(JSContext*, void*);
#endif

View File

@@ -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);

View File

@@ -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)

View File

@@ -8,4 +8,5 @@ os.createprocess(["./prosperon", "tests/portal.js"])
$_.delay(_ => {
os.createprocess(["./prosperon", "tests/contact.js"])
$_.stop()
}, 0.2)