• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "../../js-native-api/common.h"
2 
3 #include <node_api.h>
4 #include <uv.h>
5 
6 #include <cassert>
7 #include <memory>
8 #include <utility>
9 
10 template <typename T>
SetImmediate(napi_env env,T && cb)11 void* SetImmediate(napi_env env, T&& cb) {
12   T* ptr = new T(std::move(cb));
13   uv_loop_t* loop = nullptr;
14   uv_check_t* check = new uv_check_t;
15   check->data = ptr;
16   NAPI_ASSERT(env,
17               napi_get_uv_event_loop(env, &loop) == napi_ok,
18               "can get event loop");
19   uv_check_init(loop, check);
20   uv_check_start(check, [](uv_check_t* check) {
21     std::unique_ptr<T> ptr {static_cast<T*>(check->data)};
22     T cb = std::move(*ptr);
23     uv_close(reinterpret_cast<uv_handle_t*>(check), [](uv_handle_t* handle) {
24       delete reinterpret_cast<uv_check_t*>(handle);
25     });
26 
27     assert(cb() != nullptr);
28   });
29   // Idle handle is needed only to stop the event loop from blocking in poll.
30   uv_idle_t* idle = new uv_idle_t;
31   uv_idle_init(loop, idle);
32   uv_idle_start(idle, [](uv_idle_t* idle) {
33     uv_close(reinterpret_cast<uv_handle_t*>(idle), [](uv_handle_t* handle) {
34       delete reinterpret_cast<uv_check_t*>(handle);
35     });
36   });
37 
38   return nullptr;
39 }
40 
41 static char dummy;
42 
SetImmediateBinding(napi_env env,napi_callback_info info)43 napi_value SetImmediateBinding(napi_env env, napi_callback_info info) {
44   size_t argc = 1;
45   napi_value argv[1];
46   napi_value _this;
47   void* data;
48   NAPI_CALL(env,
49     napi_get_cb_info(env, info, &argc, argv, &_this, &data));
50   NAPI_ASSERT(env, argc >= 1, "Not enough arguments, expected 1.");
51 
52   napi_valuetype t;
53   NAPI_CALL(env, napi_typeof(env, argv[0], &t));
54   NAPI_ASSERT(env, t == napi_function,
55       "Wrong first argument, function expected.");
56 
57   napi_ref cbref;
58   NAPI_CALL(env,
59     napi_create_reference(env, argv[0], 1, &cbref));
60 
61   SetImmediate(env, [=]() -> char* {
62     napi_value undefined;
63     napi_value callback;
64     napi_handle_scope scope;
65     NAPI_CALL(env, napi_open_handle_scope(env, &scope));
66     NAPI_CALL(env, napi_get_undefined(env, &undefined));
67     NAPI_CALL(env, napi_get_reference_value(env, cbref, &callback));
68     NAPI_CALL(env, napi_delete_reference(env, cbref));
69     NAPI_CALL(env,
70         napi_call_function(env, undefined, callback, 0, nullptr, nullptr));
71     NAPI_CALL(env, napi_close_handle_scope(env, scope));
72     return &dummy;
73   });
74 
75   return nullptr;
76 }
77 
Init(napi_env env,napi_value exports)78 napi_value Init(napi_env env, napi_value exports) {
79   napi_property_descriptor properties[] = {
80     DECLARE_NAPI_PROPERTY("SetImmediate", SetImmediateBinding)
81   };
82 
83   NAPI_CALL(env, napi_define_properties(
84       env, exports, sizeof(properties) / sizeof(*properties), properties));
85 
86   return exports;
87 }
88 
89 NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
90