1#include <stdlib.h> 2#include "node_api.h" 3#include "uv.h" 4#include "../../js-native-api/common.h" 5 6static napi_value RunInCallbackScope(napi_env env, napi_callback_info info) { 7 size_t argc; 8 napi_value args[3]; 9 10 NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL)); 11 NODE_API_ASSERT(env, argc == 3 , "Wrong number of arguments"); 12 13 NODE_API_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); 14 15 napi_valuetype valuetype; 16 NODE_API_CALL(env, napi_typeof(env, args[0], &valuetype)); 17 NODE_API_ASSERT(env, valuetype == napi_object, 18 "Wrong type of arguments. Expects an object as first argument."); 19 20 NODE_API_CALL(env, napi_typeof(env, args[1], &valuetype)); 21 NODE_API_ASSERT(env, valuetype == napi_string, 22 "Wrong type of arguments. Expects a string as second argument."); 23 24 NODE_API_CALL(env, napi_typeof(env, args[2], &valuetype)); 25 NODE_API_ASSERT(env, valuetype == napi_function, 26 "Wrong type of arguments. Expects a function as third argument."); 27 28 napi_async_context context; 29 NODE_API_CALL(env, napi_async_init(env, args[0], args[1], &context)); 30 31 napi_callback_scope scope = NULL; 32 NODE_API_CALL(env, 33 napi_open_callback_scope(env, args[0], context, &scope)); 34 35 // If the function has an exception pending after the call that is ok 36 // so we don't use NODE_API_CALL as we must close the callback scope 37 // regardless. 38 napi_value result = NULL; 39 napi_status function_call_result = 40 napi_call_function(env, args[0], args[2], 0, NULL, &result); 41 if (function_call_result != napi_ok) { 42 GET_AND_THROW_LAST_ERROR((env)); 43 } 44 45 NODE_API_CALL(env, napi_close_callback_scope(env, scope)); 46 NODE_API_CALL(env, napi_async_destroy(env, context)); 47 48 return result; 49} 50 51static napi_env shared_env = NULL; 52static napi_deferred deferred = NULL; 53 54static void Callback(uv_work_t* req, int ignored) { 55 napi_env env = shared_env; 56 57 napi_handle_scope handle_scope = NULL; 58 NODE_API_CALL_RETURN_VOID(env, napi_open_handle_scope(env, &handle_scope)); 59 60 napi_value resource_name; 61 NODE_API_CALL_RETURN_VOID(env, napi_create_string_utf8( 62 env, "test", NAPI_AUTO_LENGTH, &resource_name)); 63 napi_async_context context; 64 NODE_API_CALL_RETURN_VOID(env, 65 napi_async_init(env, NULL, resource_name, &context)); 66 67 napi_value resource_object; 68 NODE_API_CALL_RETURN_VOID(env, napi_create_object(env, &resource_object)); 69 70 napi_value undefined_value; 71 NODE_API_CALL_RETURN_VOID(env, napi_get_undefined(env, &undefined_value)); 72 73 napi_callback_scope scope = NULL; 74 NODE_API_CALL_RETURN_VOID(env, 75 napi_open_callback_scope(env, resource_object, context, &scope)); 76 77 NODE_API_CALL_RETURN_VOID(env, 78 napi_resolve_deferred(env, deferred, undefined_value)); 79 80 NODE_API_CALL_RETURN_VOID(env, napi_close_callback_scope(env, scope)); 81 82 NODE_API_CALL_RETURN_VOID(env, napi_close_handle_scope(env, handle_scope)); 83 NODE_API_CALL_RETURN_VOID(env, napi_async_destroy(env, context)); 84 free(req); 85} 86 87static void NoopWork(uv_work_t* work) { (void) work; } 88 89static napi_value TestResolveAsync(napi_env env, napi_callback_info info) { 90 napi_value promise = NULL; 91 if (deferred == NULL) { 92 shared_env = env; 93 NODE_API_CALL(env, napi_create_promise(env, &deferred, &promise)); 94 95 uv_loop_t* loop = NULL; 96 NODE_API_CALL(env, napi_get_uv_event_loop(env, &loop)); 97 98 uv_work_t* req = malloc(sizeof(*req)); 99 uv_queue_work(loop, 100 req, 101 NoopWork, 102 Callback); 103 } 104 return promise; 105} 106 107static napi_value Init(napi_env env, napi_value exports) { 108 napi_property_descriptor descriptors[] = { 109 DECLARE_NODE_API_PROPERTY("runInCallbackScope", RunInCallbackScope), 110 DECLARE_NODE_API_PROPERTY("testResolveAsync", TestResolveAsync) 111 }; 112 113 NODE_API_CALL(env, napi_define_properties( 114 env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors)); 115 116 return exports; 117} 118 119NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) 120