#include #include "node_api.h" #include "uv.h" #include "../../js-native-api/common.h" static napi_value RunInCallbackScope(napi_env env, napi_callback_info info) { size_t argc; napi_value args[3]; NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL)); NODE_API_ASSERT(env, argc == 3 , "Wrong number of arguments"); NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); napi_valuetype valuetype; NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); NODE_API_ASSERT(env, valuetype == napi_object, "Wrong type of arguments. Expects an object as first argument."); NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype)); NODE_API_ASSERT(env, valuetype == napi_string, "Wrong type of arguments. Expects a string as second argument."); NODE_API_CALL(env, napi_typeof(env, args[2], &valuetype)); NODE_API_ASSERT(env, valuetype == napi_function, "Wrong type of arguments. Expects a function as third argument."); napi_async_context context; NODE_API_CALL(env, napi_async_init(env, args[0], args[1], &context)); napi_callback_scope scope = NULL; NODE_API_CALL(env, napi_open_callback_scope(env, args[0], context, &scope)); // If the function has an exception pending after the call that is ok // so we don't use NODE_API_CALL as we must close the callback scope // regardless. napi_value result = NULL; napi_status function_call_result = napi_call_function(env, args[0], args[2], 0, NULL, &result); if (function_call_result != napi_ok) { GET_AND_THROW_LAST_ERROR((env)); } NODE_API_CALL(env, napi_close_callback_scope(env, scope)); NODE_API_CALL(env, napi_async_destroy(env, context)); return result; } static napi_env shared_env = NULL; static napi_deferred deferred = NULL; static void Callback(uv_work_t* req, int ignored) { napi_env env = shared_env; napi_handle_scope handle_scope = NULL; NODE_API_CALL_RETURN_VOID(env, napi_open_handle_scope(env, &handle_scope)); napi_value resource_name; NODE_API_CALL_RETURN_VOID(env, napi_create_string_utf8( env, "test", NAPI_AUTO_LENGTH, &resource_name)); napi_async_context context; NODE_API_CALL_RETURN_VOID(env, napi_async_init(env, NULL, resource_name, &context)); napi_value resource_object; NODE_API_CALL_RETURN_VOID(env, napi_create_object(env, &resource_object)); napi_value undefined_value; NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined_value)); napi_callback_scope scope = NULL; NODE_API_CALL_RETURN_VOID(env, napi_open_callback_scope(env, resource_object, context, &scope)); NODE_API_CALL_RETURN_VOID(env, napi_resolve_deferred(env, deferred, undefined_value)); NODE_API_CALL_RETURN_VOID(env, napi_close_callback_scope(env, scope)); NODE_API_CALL_RETURN_VOID(env, napi_close_handle_scope(env, handle_scope)); NODE_API_CALL_RETURN_VOID(env, napi_async_destroy(env, context)); free(req); } static void NoopWork(uv_work_t* work) { (void) work; } static napi_value TestResolveAsync(napi_env env, napi_callback_info info) { napi_value promise = NULL; if (deferred == NULL) { shared_env = env; NODE_API_CALL(env, napi_create_promise(env, &deferred, &promise)); uv_loop_t* loop = NULL; NODE_API_CALL(env, napi_get_uv_event_loop(env, &loop)); uv_work_t* req = malloc(sizeof(*req)); uv_queue_work(loop, req, NoopWork, Callback); } return promise; } static napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { DECLARE_NODE_API_PROPERTY("runInCallbackScope", RunInCallbackScope), DECLARE_NODE_API_PROPERTY("testResolveAsync", TestResolveAsync) }; NODE_API_CALL(env, napi_define_properties( env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); return exports; } NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)