#include "cell.h" #include "pit_internal.h" #include #include JSC_CCALL(os_createactor, if (js->disrupt) return JS_RaiseDisrupt(js, "Can't start a new actor while disrupting."); void *startup = value2wota(js, argv[0], JS_NULL, NULL); if (!startup) return JS_RaiseDisrupt(js, "Failed to encode startup data"); create_actor(startup); ) JSC_CCALL(os_mailbox_push, if (argc < 2) return JS_RaiseDisrupt(js, "Need an actor and a message"); if (!js_is_blob(js, argv[1])) return JS_RaiseDisrupt(js, "Can only send blobs."); const char *id = JS_ToCString(js, argv[0]); int exist = actor_exists(id); if (!exist) { JS_FreeCString(js, id); return JS_RaiseDisrupt(js, "No mailbox found for given ID"); } size_t size; void *data = js_get_blob_data(js, &size, argv[1]); if (data == (void*)-1) { JS_FreeCString(js, id); return JS_EXCEPTION; } if (size == 0) { JS_FreeCString(js, id); return JS_RaiseDisrupt(js, "No data present in blob"); } blob *msg_blob = blob_new(size * 8); if (!msg_blob) { JS_FreeCString(js, id); return JS_RaiseDisrupt(js, "Could not allocate blob"); } blob_write_bytes(msg_blob, data, size); blob_make_stone(msg_blob); const char *err = send_message(id, msg_blob); JS_FreeCString(js, id); if (err) { blob_destroy(msg_blob); return JS_RaiseDisrupt(js, "Could not send message: %s", err); } ) JSC_CCALL(os_register_actor, const char *id = JS_ToCString(js, argv[0]); double ar; JS_ToFloat64(js, &ar, argv[3]); const char *err = register_actor(id, js, JS_ToBool(js, argv[2]), ar); if (err) return JS_RaiseDisrupt(js, "Could not register actor: %s", err); js->message_handle_ref.val = argv[1]; JS_FreeCString(js, id); ) JSC_CCALL(os_mailbox_exist, const char *id = JS_ToCString(js, argv[0]); int exist = actor_exists(id); JS_FreeCString(js, id); return JS_NewBool(js, exist); ) JSC_CCALL(os_unneeded, double secs; JS_ToFloat64(js, &secs, argv[1]); actor_unneeded(js, argv[0], secs); ) JSC_CCALL(actor_disrupt, actor_disrupt(js); ) JSC_SCALL(actor_setname, js->name = strdup(str); ) JSC_CCALL(actor_on_exception, js->on_exception_ref.val = argv[0]; ) JSC_CCALL(actor_clock, if (!JS_IsFunction(argv[0])) return JS_RaiseDisrupt(js, "Argument must be a function."); actor_clock(js, argv[0]); ) JSC_CCALL(actor_delay, if (!JS_IsFunction(argv[0])) return JS_RaiseDisrupt(js, "Argument must be a function."); double seconds; JS_ToFloat64(js, &seconds, argv[1]); if (seconds <= 0) { actor_clock(js, argv[0]); return JS_NULL; } uint32_t id = actor_delay(js, argv[0], seconds); return JS_NewUint32(js, id); ) JSC_CCALL(actor_removetimer, uint32_t timer_id; JS_ToUint32(js, &timer_id, argv[0]); (void)actor_remove_timer(js, timer_id); ) /* Log callback bridge: called from JS_Log, calls ƿit log(channel, [msg, stack]) Captures the register VM stack trace so the log system can show the real error site. Uses a re-entrancy guard to prevent infinite recursion when JS_Call triggers js_poll_interrupts -> JS_RaiseDisrupt -> JS_Log -> js_log_callback -> ... */ static int js_log_reentrancy = 0; static void js_log_callback(JSContext *ctx, const char *channel, const char *msg) { if (JS_IsNull(ctx->log_callback_js) || js_log_reentrancy) { fprintf(stderr, "%s\n", msg); return; } js_log_reentrancy = 1; JS_FRAME(ctx); JS_ROOT(stack, JS_GetStack(ctx)); JS_ROOT(args_array, JS_NewArray(ctx)); JS_SetPropertyNumber(ctx, args_array.val, 0, JS_NewString(ctx, msg)); JS_SetPropertyNumber(ctx, args_array.val, 1, stack.val); JSValue argv[2]; argv[0] = JS_NewString(ctx, channel); argv[1] = args_array.val; JS_Call(ctx, ctx->log_callback_js, JS_NULL, 2, argv); JS_RestoreFrame(ctx, _js_gc_frame, _js_local_frame); js_log_reentrancy = 0; } JSC_CCALL(actor_set_log, if (argc < 1 || !JS_IsFunction(argv[0])) return JS_RaiseDisrupt(js, "set_log requires a function"); js->log_callback_js = argv[0]; js->log_callback = js_log_callback; ) static const JSCFunctionListEntry js_actor_funcs[] = { MIST_FUNC_DEF(os, createactor, 1), MIST_FUNC_DEF(os, mailbox_push, 2), MIST_FUNC_DEF(os, mailbox_exist, 1), MIST_FUNC_DEF(actor, delay, 2), MIST_FUNC_DEF(actor, removetimer, 1), MIST_FUNC_DEF(os, register_actor, 4), MIST_FUNC_DEF(os, unneeded, 2), MIST_FUNC_DEF(actor, disrupt, 0), MIST_FUNC_DEF(actor, setname, 1), MIST_FUNC_DEF(actor, on_exception, 1), MIST_FUNC_DEF(actor, clock, 1), MIST_FUNC_DEF(actor, set_log, 1), }; JSValue js_core_actor_use(JSContext *js) { JS_FRAME(js); JS_ROOT(mod, JS_NewObject(js)); JS_SetPropertyFunctionList(js, mod.val, js_actor_funcs, countof(js_actor_funcs)); JS_RETURN(mod.val); }