// stub: minimal node:async_hooks implementation // just enough for react to render tree #include #include "ant.h" #include "internal.h" #include "silver/engine.h" #include "descriptors.h" #include "modules/async_hooks.h" #include "modules/symbol.h" static ant_value_t async_hooks_call_with_tail_args( ant_t *js, ant_value_t fn, ant_value_t this_arg, ant_value_t *args, int nargs, int start_idx ) { int call_nargs = nargs - start_idx; if (call_nargs <= 0) return sv_vm_call(js->vm, js, fn, this_arg, NULL, 0, NULL, false); ant_value_t *call_args = (ant_value_t *)malloc((size_t)call_nargs * sizeof(ant_value_t)); if (!call_args) return js_mkerr(js, "Out of memory"); for (int i = 0; i < call_nargs; i++) call_args[i] = args[start_idx + i]; ant_value_t result = sv_vm_call(js->vm, js, fn, this_arg, call_args, call_nargs, NULL, false); free(call_args); return result; } static ant_value_t async_local_storage_run(ant_params_t) { if (nargs < 2 || !is_callable(args[1])) { return js_mkerr(js, "AsyncLocalStorage.run(store, callback, ...args) requires a callback"); } ant_value_t this_obj = js_getthis(js); if (!is_object_type(this_obj)) { return js_mkerr(js, "AsyncLocalStorage.run() requires an AsyncLocalStorage instance"); } ant_value_t prev = js_get_slot(this_obj, SLOT_DATA); js_set_slot_wb(js, this_obj, SLOT_DATA, args[0]); ant_value_t result = async_hooks_call_with_tail_args(js, args[1], js_mkundef(), args, nargs, 2); js_set_slot_wb(js, this_obj, SLOT_DATA, prev); return result; } static ant_value_t async_local_storage_exit(ant_params_t) { if (nargs < 1 || !is_callable(args[0])) { return js_mkerr(js, "AsyncLocalStorage.exit(callback, ...args) requires a callback"); } ant_value_t this_obj = js_getthis(js); if (!is_object_type(this_obj)) { return js_mkerr(js, "AsyncLocalStorage.exit() requires an AsyncLocalStorage instance"); } ant_value_t prev = js_get_slot(this_obj, SLOT_DATA); js_set_slot_wb(js, this_obj, SLOT_DATA, js_mkundef()); ant_value_t result = async_hooks_call_with_tail_args(js, args[0], js_mkundef(), args, nargs, 1); js_set_slot_wb(js, this_obj, SLOT_DATA, prev); return result; } static ant_value_t async_local_storage_enterWith(ant_params_t) { ant_value_t this_obj = js_getthis(js); if (!is_object_type(this_obj)) { return js_mkerr(js, "AsyncLocalStorage.enterWith() requires an AsyncLocalStorage instance"); } js_set_slot_wb(js, this_obj, SLOT_DATA, nargs > 0 ? args[0] : js_mkundef()); return js_mkundef(); } static ant_value_t async_local_storage_getStore(ant_params_t) { ant_value_t this_obj = js_getthis(js); if (!is_object_type(this_obj)) return js_mkundef(); return js_get_slot(this_obj, SLOT_DATA); } static ant_value_t async_local_storage_disable(ant_params_t) { ant_value_t this_obj = js_getthis(js); if (is_object_type(this_obj)) js_set_slot_wb(js, this_obj, SLOT_DATA, js_mkundef()); return js_mkundef(); } static ant_value_t async_resource_runInAsyncScope(ant_params_t) { if (nargs < 1 || !is_callable(args[0])) { return js_mkerr(js, "AsyncResource.runInAsyncScope(fn[, thisArg, ...args]) requires a function"); } ant_value_t this_arg = nargs > 1 ? args[1] : js_mkundef(); return async_hooks_call_with_tail_args(js, args[0], this_arg, args, nargs, 2); } static ant_value_t async_resource_emitDestroy(ant_params_t) { return js_getthis(js); } static ant_value_t async_resource_asyncId(ant_params_t) { return js_mknum(0); } static ant_value_t async_resource_triggerAsyncId(ant_params_t) { return js_mknum(0); } static ant_value_t async_hook_enable(ant_params_t) { return js_getthis(js); } static ant_value_t async_hook_disable(ant_params_t) { return js_getthis(js); } static ant_value_t async_hooks_createHook(ant_params_t) { ant_value_t hook = js_mkobj(js); js_set(js, hook, "enable", js_mkfun(async_hook_enable)); js_set(js, hook, "disable", js_mkfun(async_hook_disable)); return hook; } static ant_value_t async_hooks_executionAsyncId(ant_params_t) { return js_mknum(1); } static ant_value_t async_hooks_triggerAsyncId(ant_params_t) { return js_mknum(0); } static ant_value_t async_hooks_executionAsyncResource(ant_params_t) { return js_mkobj(js); } ant_value_t async_hooks_library(ant_t *js) { ant_value_t lib = js_mkobj(js); ant_value_t als_ctor = js_mkobj(js); ant_value_t als_proto = js_mkobj(js); js_set(js, als_proto, "run", js_mkfun(async_local_storage_run)); js_set(js, als_proto, "exit", js_mkfun(async_local_storage_exit)); js_set(js, als_proto, "enterWith", js_mkfun(async_local_storage_enterWith)); js_set(js, als_proto, "getStore", js_mkfun(async_local_storage_getStore)); js_set(js, als_proto, "disable", js_mkfun(async_local_storage_disable)); js_set_sym(js, als_proto, get_toStringTag_sym(), ANT_STRING("AsyncLocalStorage")); js_mkprop_fast(js, als_ctor, "prototype", 9, als_proto); js_mkprop_fast(js, als_ctor, "name", 4, ANT_STRING("AsyncLocalStorage")); js_set_descriptor(js, als_ctor, "name", 4, 0); js_set(js, lib, "AsyncLocalStorage", js_obj_to_func_ex(als_ctor, SV_CALL_IS_DEFAULT_CTOR)); ant_value_t resource_ctor = js_mkobj(js); ant_value_t resource_proto = js_mkobj(js); js_set(js, resource_proto, "runInAsyncScope", js_mkfun(async_resource_runInAsyncScope)); js_set(js, resource_proto, "emitDestroy", js_mkfun(async_resource_emitDestroy)); js_set(js, resource_proto, "asyncId", js_mkfun(async_resource_asyncId)); js_set(js, resource_proto, "triggerAsyncId", js_mkfun(async_resource_triggerAsyncId)); js_set_sym(js, resource_proto, get_toStringTag_sym(), ANT_STRING("AsyncResource")); js_mkprop_fast(js, resource_ctor, "prototype", 9, resource_proto); js_mkprop_fast(js, resource_ctor, "name", 4, ANT_STRING("AsyncResource")); js_set_descriptor(js, resource_ctor, "name", 4, 0); js_set(js, lib, "AsyncResource", js_obj_to_func_ex(resource_ctor, SV_CALL_IS_DEFAULT_CTOR)); js_set(js, lib, "createHook", js_mkfun(async_hooks_createHook)); js_set(js, lib, "executionAsyncId", js_mkfun(async_hooks_executionAsyncId)); js_set(js, lib, "triggerAsyncId", js_mkfun(async_hooks_triggerAsyncId)); js_set(js, lib, "executionAsyncResource", js_mkfun(async_hooks_executionAsyncResource)); js_set(js, lib, "asyncWrapProviders", js_mkobj(js)); js_set_sym(js, lib, get_toStringTag_sym(), ANT_STRING("async_hooks")); return lib; }