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