koffi 2.3.3 → 2.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/CHANGELOG.md +19 -3
  2. package/doc/changelog.md +4 -0
  3. package/doc/index.rst +1 -2
  4. package/doc/types.md +3 -3
  5. package/package.json +2 -2
  6. package/src/core/libcc/libcc.cc +2 -2
  7. package/src/koffi/build/2.3.5/koffi_darwin_arm64.tar.gz +0 -0
  8. package/src/koffi/build/2.3.5/koffi_darwin_x64.tar.gz +0 -0
  9. package/src/koffi/build/2.3.5/koffi_freebsd_arm64.tar.gz +0 -0
  10. package/src/koffi/build/2.3.5/koffi_freebsd_ia32.tar.gz +0 -0
  11. package/src/koffi/build/2.3.5/koffi_freebsd_x64.tar.gz +0 -0
  12. package/src/koffi/build/2.3.5/koffi_linux_arm32hf.tar.gz +0 -0
  13. package/src/koffi/build/2.3.5/koffi_linux_arm64.tar.gz +0 -0
  14. package/src/koffi/build/2.3.5/koffi_linux_ia32.tar.gz +0 -0
  15. package/src/koffi/build/2.3.5/koffi_linux_riscv64hf64.tar.gz +0 -0
  16. package/src/koffi/build/2.3.5/koffi_linux_x64.tar.gz +0 -0
  17. package/src/koffi/build/2.3.5/koffi_openbsd_ia32.tar.gz +0 -0
  18. package/src/koffi/build/2.3.5/koffi_openbsd_x64.tar.gz +0 -0
  19. package/src/koffi/build/2.3.5/koffi_win32_arm64.tar.gz +0 -0
  20. package/src/koffi/build/2.3.5/koffi_win32_ia32.tar.gz +0 -0
  21. package/src/koffi/build/2.3.5/koffi_win32_x64.tar.gz +0 -0
  22. package/src/koffi/src/abi_arm32.cc +43 -14
  23. package/src/koffi/src/abi_arm64.cc +95 -21
  24. package/src/koffi/src/abi_riscv64.cc +125 -64
  25. package/src/koffi/src/abi_x64_sysv.cc +38 -20
  26. package/src/koffi/src/abi_x64_win.cc +11 -5
  27. package/src/koffi/src/abi_x86.cc +14 -7
  28. package/src/koffi/src/call.cc +114 -44
  29. package/src/koffi/src/call.hh +6 -4
  30. package/src/koffi/src/ffi.cc +172 -147
  31. package/src/koffi/src/ffi.hh +18 -10
  32. package/src/koffi/src/index.d.ts +28 -7
  33. package/src/koffi/src/util.cc +261 -69
  34. package/src/koffi/src/util.hh +34 -8
  35. package/vendor/node-addon-api/CHANGELOG.md +122 -9
  36. package/vendor/node-addon-api/CONTRIBUTING.md +10 -10
  37. package/vendor/node-addon-api/README.md +36 -12
  38. package/vendor/node-addon-api/benchmark/function_args.cc +95 -62
  39. package/vendor/node-addon-api/benchmark/function_args.js +6 -6
  40. package/vendor/node-addon-api/benchmark/index.js +1 -1
  41. package/vendor/node-addon-api/benchmark/property_descriptor.cc +27 -34
  42. package/vendor/node-addon-api/benchmark/property_descriptor.js +5 -4
  43. package/vendor/node-addon-api/doc/async_operations.md +1 -1
  44. package/vendor/node-addon-api/doc/async_worker_variants.md +23 -2
  45. package/vendor/node-addon-api/doc/cmake-js.md +1 -1
  46. package/vendor/node-addon-api/doc/error_handling.md +3 -3
  47. package/vendor/node-addon-api/doc/external.md +7 -0
  48. package/vendor/node-addon-api/doc/handle_scope.md +14 -0
  49. package/vendor/node-addon-api/doc/hierarchy.md +1 -1
  50. package/vendor/node-addon-api/doc/object.md +27 -0
  51. package/vendor/node-addon-api/index.js +3 -3
  52. package/vendor/node-addon-api/napi-inl.deprecated.h +121 -127
  53. package/vendor/node-addon-api/napi-inl.h +1178 -1144
  54. package/vendor/node-addon-api/napi.h +2786 -2675
  55. package/vendor/node-addon-api/package.json +42 -1
  56. package/vendor/node-addon-api/test/addon.cc +8 -6
  57. package/vendor/node-addon-api/test/addon_build/index.js +9 -9
  58. package/vendor/node-addon-api/test/addon_build/tpl/addon.cc +2 -1
  59. package/vendor/node-addon-api/test/addon_build/tpl/index.js +4 -4
  60. package/vendor/node-addon-api/test/addon_data.cc +12 -13
  61. package/vendor/node-addon-api/test/array_buffer.js +3 -2
  62. package/vendor/node-addon-api/test/async_progress_queue_worker.cc +13 -3
  63. package/vendor/node-addon-api/test/async_progress_queue_worker.js +5 -5
  64. package/vendor/node-addon-api/test/async_progress_worker.cc +65 -9
  65. package/vendor/node-addon-api/test/async_progress_worker.js +14 -9
  66. package/vendor/node-addon-api/test/async_worker.cc +236 -3
  67. package/vendor/node-addon-api/test/async_worker.js +122 -37
  68. package/vendor/node-addon-api/test/async_worker_nocallback.js +9 -3
  69. package/vendor/node-addon-api/test/async_worker_persistent.js +2 -2
  70. package/vendor/node-addon-api/test/basic_types/array.js +3 -4
  71. package/vendor/node-addon-api/test/basic_types/boolean.cc +4 -2
  72. package/vendor/node-addon-api/test/basic_types/boolean.js +1 -2
  73. package/vendor/node-addon-api/test/basic_types/number.cc +12 -6
  74. package/vendor/node-addon-api/test/basic_types/number.js +19 -18
  75. package/vendor/node-addon-api/test/basic_types/value.cc +52 -1
  76. package/vendor/node-addon-api/test/basic_types/value.js +44 -21
  77. package/vendor/node-addon-api/test/bigint.cc +2 -1
  78. package/vendor/node-addon-api/test/binding.cc +11 -5
  79. package/vendor/node-addon-api/test/binding.gyp +3 -1
  80. package/vendor/node-addon-api/test/buffer.cc +46 -38
  81. package/vendor/node-addon-api/test/buffer.js +12 -12
  82. package/vendor/node-addon-api/test/callbackInfo.cc +27 -0
  83. package/vendor/node-addon-api/test/callbackInfo.js +9 -0
  84. package/vendor/node-addon-api/test/callbackscope.cc +19 -2
  85. package/vendor/node-addon-api/test/callbackscope.js +20 -20
  86. package/vendor/node-addon-api/test/common/index.js +37 -4
  87. package/vendor/node-addon-api/test/dataview/dataview.js +5 -5
  88. package/vendor/node-addon-api/test/dataview/dataview_read_write.js +14 -12
  89. package/vendor/node-addon-api/test/date.cc +2 -1
  90. package/vendor/node-addon-api/test/date.js +2 -2
  91. package/vendor/node-addon-api/test/env_cleanup.cc +12 -0
  92. package/vendor/node-addon-api/test/env_cleanup.js +38 -39
  93. package/vendor/node-addon-api/test/error.cc +6 -5
  94. package/vendor/node-addon-api/test/error_terminating_environment.js +64 -60
  95. package/vendor/node-addon-api/test/external.cc +36 -32
  96. package/vendor/node-addon-api/test/external.js +43 -46
  97. package/vendor/node-addon-api/test/function.cc +58 -44
  98. package/vendor/node-addon-api/test/function.js +4 -0
  99. package/vendor/node-addon-api/test/function_reference.cc +15 -13
  100. package/vendor/node-addon-api/test/globalObject/global_object_delete_property.js +50 -53
  101. package/vendor/node-addon-api/test/globalObject/global_object_get_property.js +33 -34
  102. package/vendor/node-addon-api/test/globalObject/global_object_has_own_property.js +38 -40
  103. package/vendor/node-addon-api/test/globalObject/global_object_set_property.js +47 -49
  104. package/vendor/node-addon-api/test/handlescope.cc +29 -3
  105. package/vendor/node-addon-api/test/handlescope.js +5 -3
  106. package/vendor/node-addon-api/test/index.js +1 -5
  107. package/vendor/node-addon-api/test/maybe/check.cc +49 -3
  108. package/vendor/node-addon-api/test/maybe/index.js +19 -7
  109. package/vendor/node-addon-api/test/memory_management.cc +9 -8
  110. package/vendor/node-addon-api/test/memory_management.js +2 -2
  111. package/vendor/node-addon-api/test/movable_callbacks.js +2 -2
  112. package/vendor/node-addon-api/test/name.js +3 -3
  113. package/vendor/node-addon-api/test/napi_child.js +2 -2
  114. package/vendor/node-addon-api/test/object/delete_property.js +7 -7
  115. package/vendor/node-addon-api/test/object/finalizer.cc +13 -12
  116. package/vendor/node-addon-api/test/object/finalizer.js +2 -2
  117. package/vendor/node-addon-api/test/object/get_property.js +6 -6
  118. package/vendor/node-addon-api/test/object/has_own_property.js +3 -3
  119. package/vendor/node-addon-api/test/object/has_property.js +4 -4
  120. package/vendor/node-addon-api/test/object/object.cc +191 -111
  121. package/vendor/node-addon-api/test/object/object.js +53 -52
  122. package/vendor/node-addon-api/test/object/object_deprecated.cc +24 -20
  123. package/vendor/node-addon-api/test/object/object_deprecated.js +3 -8
  124. package/vendor/node-addon-api/test/object/object_freeze_seal.js +54 -54
  125. package/vendor/node-addon-api/test/object/object_type_tag.cc +39 -0
  126. package/vendor/node-addon-api/test/object/object_type_tag.js +55 -0
  127. package/vendor/node-addon-api/test/object/subscript_operator.js +2 -2
  128. package/vendor/node-addon-api/test/object_reference.js +100 -100
  129. package/vendor/node-addon-api/test/objectwrap.cc +41 -34
  130. package/vendor/node-addon-api/test/objectwrap.js +23 -19
  131. package/vendor/node-addon-api/test/objectwrap_constructor_exception.cc +5 -5
  132. package/vendor/node-addon-api/test/objectwrap_constructor_exception.js +1 -1
  133. package/vendor/node-addon-api/test/objectwrap_multiple_inheritance.cc +7 -7
  134. package/vendor/node-addon-api/test/objectwrap_multiple_inheritance.js +1 -1
  135. package/vendor/node-addon-api/test/objectwrap_removewrap.js +24 -32
  136. package/vendor/node-addon-api/test/objectwrap_worker_thread.js +5 -4
  137. package/vendor/node-addon-api/test/promise.cc +7 -0
  138. package/vendor/node-addon-api/test/promise.js +3 -1
  139. package/vendor/node-addon-api/test/reference.cc +1 -1
  140. package/vendor/node-addon-api/test/reference.js +2 -2
  141. package/vendor/node-addon-api/test/run_script.cc +1 -1
  142. package/vendor/node-addon-api/test/symbol.js +59 -66
  143. package/vendor/node-addon-api/test/testUtil.js +6 -6
  144. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function.cc +64 -29
  145. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function.js +71 -34
  146. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ctx.cc +111 -19
  147. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ctx.js +2 -1
  148. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_existing_tsfn.cc +36 -26
  149. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_existing_tsfn.js +5 -5
  150. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ptr.cc +3 -2
  151. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ptr.js +1 -1
  152. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_sum.cc +47 -32
  153. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_sum.js +3 -3
  154. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_unref.cc +22 -9
  155. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_unref.js +76 -31
  156. package/vendor/node-addon-api/test/thunking_manual.cc +61 -74
  157. package/vendor/node-addon-api/test/thunking_manual.js +6 -7
  158. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function.cc +20 -20
  159. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function.js +19 -19
  160. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ctx.cc +57 -5
  161. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ctx.js +2 -0
  162. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_existing_tsfn.js +5 -5
  163. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ptr.cc +5 -1
  164. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ptr.js +4 -3
  165. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_sum.js +3 -3
  166. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_unref.cc +14 -0
  167. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_unref.js +76 -31
  168. package/vendor/node-addon-api/test/typedarray-bigint.js +2 -2
  169. package/vendor/node-addon-api/test/typedarray.cc +263 -70
  170. package/vendor/node-addon-api/test/typedarray.js +44 -10
  171. package/vendor/node-addon-api/test/version_management.cc +16 -15
  172. package/vendor/node-addon-api/test/version_management.js +18 -20
  173. package/vendor/node-addon-api/tools/check-napi.js +13 -14
  174. package/vendor/node-addon-api/tools/conversion.js +161 -169
  175. package/vendor/node-addon-api/tools/eslint-format.js +9 -1
  176. package/vendor/node-addon-api/unit-test/README.md +4 -4
  177. package/koffi-2.3.3.tgz +0 -0
  178. package/src/koffi/build/2.3.3/koffi_darwin_arm64.tar.gz +0 -0
  179. package/src/koffi/build/2.3.3/koffi_darwin_x64.tar.gz +0 -0
  180. package/src/koffi/build/2.3.3/koffi_freebsd_arm64.tar.gz +0 -0
  181. package/src/koffi/build/2.3.3/koffi_freebsd_ia32.tar.gz +0 -0
  182. package/src/koffi/build/2.3.3/koffi_freebsd_x64.tar.gz +0 -0
  183. package/src/koffi/build/2.3.3/koffi_linux_arm32hf.tar.gz +0 -0
  184. package/src/koffi/build/2.3.3/koffi_linux_arm64.tar.gz +0 -0
  185. package/src/koffi/build/2.3.3/koffi_linux_ia32.tar.gz +0 -0
  186. package/src/koffi/build/2.3.3/koffi_linux_riscv64hf64.tar.gz +0 -0
  187. package/src/koffi/build/2.3.3/koffi_linux_x64.tar.gz +0 -0
  188. package/src/koffi/build/2.3.3/koffi_openbsd_ia32.tar.gz +0 -0
  189. package/src/koffi/build/2.3.3/koffi_openbsd_x64.tar.gz +0 -0
  190. package/src/koffi/build/2.3.3/koffi_win32_arm64.tar.gz +0 -0
  191. package/src/koffi/build/2.3.3/koffi_win32_ia32.tar.gz +0 -0
  192. package/src/koffi/build/2.3.3/koffi_win32_x64.tar.gz +0 -0
@@ -1,7 +1,81 @@
1
+ #include <chrono>
2
+ #include <condition_variable>
3
+ #include <mutex>
4
+ #include <thread>
5
+ #include "assert.h"
1
6
  #include "napi.h"
2
7
 
3
8
  using namespace Napi;
4
9
 
10
+ class TestWorkerWithUserDefRecv : public AsyncWorker {
11
+ public:
12
+ static void DoWork(const CallbackInfo& info) {
13
+ Object recv = info[0].As<Object>();
14
+ Function cb = info[1].As<Function>();
15
+
16
+ TestWorkerWithUserDefRecv* worker = new TestWorkerWithUserDefRecv(recv, cb);
17
+ worker->Queue();
18
+ }
19
+
20
+ static void DoWorkWithAsyncRes(const CallbackInfo& info) {
21
+ Object recv = info[0].As<Object>();
22
+ Function cb = info[1].As<Function>();
23
+ Object resource = info[2].As<Object>();
24
+
25
+ TestWorkerWithUserDefRecv* worker = nullptr;
26
+ if (resource == info.Env().Null()) {
27
+ worker = new TestWorkerWithUserDefRecv(recv, cb, "TestResource");
28
+ } else {
29
+ worker =
30
+ new TestWorkerWithUserDefRecv(recv, cb, "TestResource", resource);
31
+ }
32
+
33
+ worker->Queue();
34
+ }
35
+
36
+ protected:
37
+ void Execute() override {}
38
+
39
+ private:
40
+ TestWorkerWithUserDefRecv(const Object& recv, const Function& cb)
41
+ : AsyncWorker(recv, cb) {}
42
+ TestWorkerWithUserDefRecv(const Object& recv,
43
+ const Function& cb,
44
+ const char* resource_name)
45
+ : AsyncWorker(recv, cb, resource_name) {}
46
+ TestWorkerWithUserDefRecv(const Object& recv,
47
+ const Function& cb,
48
+ const char* resource_name,
49
+ const Object& resource)
50
+ : AsyncWorker(recv, cb, resource_name, resource) {}
51
+ };
52
+
53
+ // Using default std::allocator impl, but assuming user can define their own
54
+ // alloc/dealloc methods
55
+ class CustomAllocWorker : public AsyncWorker {
56
+ public:
57
+ CustomAllocWorker(Function& cb) : AsyncWorker(cb){};
58
+ static void DoWork(const CallbackInfo& info) {
59
+ Function cb = info[0].As<Function>();
60
+ std::allocator<CustomAllocWorker> create_alloc;
61
+ CustomAllocWorker* newWorker = create_alloc.allocate(1);
62
+ create_alloc.construct(newWorker, cb);
63
+ newWorker->Queue();
64
+ }
65
+
66
+ protected:
67
+ void Execute() override {}
68
+ void Destroy() override {
69
+ assert(this->_secretVal == 24);
70
+ std::allocator<CustomAllocWorker> deallocer;
71
+ deallocer.destroy(this);
72
+ deallocer.deallocate(this, 1);
73
+ }
74
+
75
+ private:
76
+ int _secretVal = 24;
77
+ };
78
+
5
79
  class TestWorker : public AsyncWorker {
6
80
  public:
7
81
  static void DoWork(const CallbackInfo& info) {
@@ -10,7 +84,13 @@ class TestWorker : public AsyncWorker {
10
84
  Function cb = info[2].As<Function>();
11
85
  Value data = info[3];
12
86
 
13
- TestWorker* worker = new TestWorker(cb, "TestResource", resource);
87
+ TestWorker* worker = nullptr;
88
+ if (resource == info.Env().Null()) {
89
+ worker = new TestWorker(cb, "TestResource");
90
+ } else {
91
+ worker = new TestWorker(cb, "TestResource", resource);
92
+ }
93
+
14
94
  worker->Receiver().Set("data", data);
15
95
  worker->_succeed = succeed;
16
96
  worker->Queue();
@@ -26,6 +106,8 @@ class TestWorker : public AsyncWorker {
26
106
  private:
27
107
  TestWorker(Function cb, const char* resource_name, const Object& resource)
28
108
  : AsyncWorker(cb, resource_name, resource) {}
109
+ TestWorker(Function cb, const char* resource_name)
110
+ : AsyncWorker(cb, resource_name) {}
29
111
  bool _succeed;
30
112
  };
31
113
 
@@ -67,12 +149,25 @@ class TestWorkerWithResult : public AsyncWorker {
67
149
  class TestWorkerNoCallback : public AsyncWorker {
68
150
  public:
69
151
  static Value DoWork(const CallbackInfo& info) {
152
+ bool succeed = info[0].As<Boolean>();
153
+
154
+ TestWorkerNoCallback* worker = new TestWorkerNoCallback(info.Env());
155
+ worker->_succeed = succeed;
156
+ worker->Queue();
157
+ return worker->_deferred.Promise();
158
+ }
159
+
160
+ static Value DoWorkWithAsyncRes(const CallbackInfo& info) {
70
161
  napi_env env = info.Env();
71
162
  bool succeed = info[0].As<Boolean>();
72
163
  Object resource = info[1].As<Object>();
73
164
 
74
- TestWorkerNoCallback* worker =
75
- new TestWorkerNoCallback(env, "TestResource", resource);
165
+ TestWorkerNoCallback* worker = nullptr;
166
+ if (resource == info.Env().Null()) {
167
+ worker = new TestWorkerNoCallback(env, "TestResource");
168
+ } else {
169
+ worker = new TestWorkerNoCallback(env, "TestResource", resource);
170
+ }
76
171
  worker->_succeed = succeed;
77
172
  worker->Queue();
78
173
  return worker->_deferred.Promise();
@@ -86,6 +181,13 @@ class TestWorkerNoCallback : public AsyncWorker {
86
181
  }
87
182
 
88
183
  private:
184
+ TestWorkerNoCallback(Napi::Env env)
185
+ : AsyncWorker(env), _deferred(Napi::Promise::Deferred::New(env)) {}
186
+
187
+ TestWorkerNoCallback(napi_env env, const char* resource_name)
188
+ : AsyncWorker(env, resource_name),
189
+ _deferred(Napi::Promise::Deferred::New(env)) {}
190
+
89
191
  TestWorkerNoCallback(napi_env env,
90
192
  const char* resource_name,
91
193
  const Object& resource)
@@ -95,12 +197,143 @@ class TestWorkerNoCallback : public AsyncWorker {
95
197
  bool _succeed;
96
198
  };
97
199
 
200
+ class EchoWorker : public AsyncWorker {
201
+ public:
202
+ EchoWorker(Function& cb, std::string& echo) : AsyncWorker(cb), echo(echo) {}
203
+ ~EchoWorker() {}
204
+
205
+ void Execute() override {
206
+ // Simulate cpu heavy task
207
+ std::this_thread::sleep_for(std::chrono::milliseconds(30));
208
+ }
209
+
210
+ void OnOK() override {
211
+ HandleScope scope(Env());
212
+ Callback().Call({Env().Null(), String::New(Env(), echo)});
213
+ }
214
+
215
+ private:
216
+ std::string echo;
217
+ };
218
+
219
+ class FailCancelWorker : public AsyncWorker {
220
+ private:
221
+ bool taskIsRunning = false;
222
+ std::mutex mu;
223
+ std::condition_variable taskStartingCv;
224
+ void NotifyJSThreadTaskHasStarted() {
225
+ {
226
+ std::lock_guard<std::mutex> lk(mu);
227
+ taskIsRunning = true;
228
+ taskStartingCv.notify_one();
229
+ }
230
+ }
231
+
232
+ public:
233
+ FailCancelWorker(Function& cb) : AsyncWorker(cb) {}
234
+ ~FailCancelWorker() {}
235
+
236
+ void WaitForWorkerTaskToStart() {
237
+ std::unique_lock<std::mutex> lk(mu);
238
+ taskStartingCv.wait(lk, [this] { return taskIsRunning; });
239
+ taskIsRunning = false;
240
+ }
241
+
242
+ static void DoCancel(const CallbackInfo& info) {
243
+ Function cb = info[0].As<Function>();
244
+
245
+ FailCancelWorker* cancelWorker = new FailCancelWorker(cb);
246
+ cancelWorker->Queue();
247
+ cancelWorker->WaitForWorkerTaskToStart();
248
+
249
+ #ifdef NAPI_CPP_EXCEPTIONS
250
+ try {
251
+ cancelWorker->Cancel();
252
+ } catch (Napi::Error&) {
253
+ Napi::Error::New(info.Env(), "Unable to cancel async worker tasks")
254
+ .ThrowAsJavaScriptException();
255
+ }
256
+ #else
257
+ cancelWorker->Cancel();
258
+ #endif
259
+ }
260
+
261
+ void Execute() override {
262
+ NotifyJSThreadTaskHasStarted();
263
+ std::this_thread::sleep_for(std::chrono::seconds(1));
264
+ }
265
+
266
+ void OnOK() override {}
267
+
268
+ void OnError(const Error&) override {}
269
+ };
270
+
271
+ class CancelWorker : public AsyncWorker {
272
+ public:
273
+ CancelWorker(Function& cb) : AsyncWorker(cb) {}
274
+ ~CancelWorker() {}
275
+
276
+ static void DoWork(const CallbackInfo& info) {
277
+ Function cb = info[0].As<Function>();
278
+ std::string echo = info[1].As<String>();
279
+ int threadNum = info[2].As<Number>().Uint32Value();
280
+
281
+ for (int i = 0; i < threadNum; i++) {
282
+ AsyncWorker* worker = new EchoWorker(cb, echo);
283
+ worker->Queue();
284
+ assert(worker->Env() == info.Env());
285
+ }
286
+
287
+ AsyncWorker* cancelWorker = new CancelWorker(cb);
288
+ cancelWorker->Queue();
289
+
290
+ #ifdef NAPI_CPP_EXCEPTIONS
291
+ try {
292
+ cancelWorker->Cancel();
293
+ } catch (Napi::Error&) {
294
+ Napi::Error::New(info.Env(), "Unable to cancel async worker tasks")
295
+ .ThrowAsJavaScriptException();
296
+ }
297
+ #else
298
+ cancelWorker->Cancel();
299
+ #endif
300
+ }
301
+
302
+ void Execute() override {
303
+ // Simulate cpu heavy task
304
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
305
+ }
306
+
307
+ void OnOK() override {
308
+ Napi::Error::New(this->Env(),
309
+ "OnOk should not be invoked on successful cancellation")
310
+ .ThrowAsJavaScriptException();
311
+ }
312
+
313
+ void OnError(const Error&) override {
314
+ Napi::Error::New(this->Env(),
315
+ "OnError should not be invoked on successful cancellation")
316
+ .ThrowAsJavaScriptException();
317
+ }
318
+ };
319
+
98
320
  Object InitAsyncWorker(Env env) {
99
321
  Object exports = Object::New(env);
322
+ exports["doWorkRecv"] = Function::New(env, TestWorkerWithUserDefRecv::DoWork);
323
+ exports["doWithRecvAsyncRes"] =
324
+ Function::New(env, TestWorkerWithUserDefRecv::DoWorkWithAsyncRes);
100
325
  exports["doWork"] = Function::New(env, TestWorker::DoWork);
326
+ exports["doWorkAsyncResNoCallback"] =
327
+ Function::New(env, TestWorkerNoCallback::DoWorkWithAsyncRes);
101
328
  exports["doWorkNoCallback"] =
102
329
  Function::New(env, TestWorkerNoCallback::DoWork);
103
330
  exports["doWorkWithResult"] =
104
331
  Function::New(env, TestWorkerWithResult::DoWork);
332
+ exports["tryCancelQueuedWork"] = Function::New(env, CancelWorker::DoWork);
333
+
334
+ exports["expectCancelToFail"] =
335
+ Function::New(env, FailCancelWorker::DoCancel);
336
+ exports["expectCustomAllocWorkerToDealloc"] =
337
+ Function::New(env, CustomAllocWorker::DoWork);
105
338
  return exports;
106
339
  }
@@ -4,12 +4,12 @@ const common = require('./common');
4
4
 
5
5
  // we only check async hooks on 8.x an higher were
6
6
  // they are closer to working properly
7
- const nodeVersion = process.versions.node.split('.')[0]
8
- let async_hooks = undefined;
9
- function checkAsyncHooks() {
10
- if (nodeVersion >=8) {
11
- if (async_hooks == undefined) {
12
- async_hooks = require('async_hooks');
7
+ const nodeVersion = process.versions.node.split('.')[0];
8
+ let asyncHooks;
9
+ function checkAsyncHooks () {
10
+ if (nodeVersion >= 8) {
11
+ if (asyncHooks === undefined) {
12
+ asyncHooks = require('async_hooks');
13
13
  }
14
14
  return true;
15
15
  }
@@ -18,7 +18,7 @@ function checkAsyncHooks() {
18
18
 
19
19
  module.exports = common.runTest(test);
20
20
 
21
- function installAsyncHooksForTest() {
21
+ function installAsyncHooksForTest () {
22
22
  return new Promise((resolve, reject) => {
23
23
  let id;
24
24
  const events = [];
@@ -26,34 +26,33 @@ function installAsyncHooksForTest() {
26
26
  * TODO(legendecas): investigate why resolving & disabling hooks in
27
27
  * destroy callback causing crash with case 'callbackscope.js'.
28
28
  */
29
- let hook;
30
- let destroyed = false;
31
- const interval = setInterval(() => {
32
- if (destroyed) {
33
- hook.disable();
34
- clearInterval(interval);
35
- resolve(events);
36
- }
37
- }, 10);
38
-
39
- hook = async_hooks.createHook({
40
- init(asyncId, type, triggerAsyncId, resource) {
29
+ let destroyed = false;
30
+ const interval = setInterval(() => {
31
+ if (destroyed) {
32
+ hook.disable();
33
+ clearInterval(interval);
34
+ resolve(events);
35
+ }
36
+ }, 10);
37
+
38
+ const hook = asyncHooks.createHook({
39
+ init (asyncId, type, triggerAsyncId, resource) {
41
40
  if (id === undefined && type === 'TestResource') {
42
41
  id = asyncId;
43
42
  events.push({ eventName: 'init', type, triggerAsyncId, resource });
44
43
  }
45
44
  },
46
- before(asyncId) {
45
+ before (asyncId) {
47
46
  if (asyncId === id) {
48
47
  events.push({ eventName: 'before' });
49
48
  }
50
49
  },
51
- after(asyncId) {
50
+ after (asyncId) {
52
51
  if (asyncId === id) {
53
52
  events.push({ eventName: 'after' });
54
53
  }
55
54
  },
56
- destroy(asyncId) {
55
+ destroy (asyncId) {
57
56
  if (asyncId === id) {
58
57
  events.push({ eventName: 'destroy' });
59
58
  destroyed = true;
@@ -63,10 +62,34 @@ function installAsyncHooksForTest() {
63
62
  });
64
63
  }
65
64
 
66
- async function test(binding) {
65
+ async function test (binding) {
66
+ const libUvThreadCount = Number(process.env.UV_THREADPOOL_SIZE || 4);
67
+ binding.asyncworker.tryCancelQueuedWork(() => {}, 'echoString', libUvThreadCount);
68
+
69
+ let taskFailed = false;
70
+ try {
71
+ binding.asyncworker.expectCancelToFail(() => {});
72
+ } catch (e) {
73
+ taskFailed = true;
74
+ }
75
+
76
+ assert.equal(taskFailed, true, 'We expect task cancellation to fail');
77
+
67
78
  if (!checkAsyncHooks()) {
79
+ binding.asyncworker.expectCustomAllocWorkerToDealloc(() => {});
80
+
81
+ await new Promise((resolve) => {
82
+ const obj = { data: 'test data' };
83
+ binding.asyncworker.doWorkRecv(obj, function (e) {
84
+ assert.strictEqual(typeof e, 'undefined');
85
+ assert.strictEqual(typeof this, 'object');
86
+ assert.strictEqual(this.data, 'test data');
87
+ resolve();
88
+ });
89
+ });
90
+
68
91
  await new Promise((resolve) => {
69
- binding.asyncworker.doWork(true, {}, function (e) {
92
+ binding.asyncworker.doWork(true, null, function (e) {
70
93
  assert.strictEqual(typeof e, 'undefined');
71
94
  assert.strictEqual(typeof this, 'object');
72
95
  assert.strictEqual(this.data, 'test data');
@@ -86,9 +109,9 @@ async function test(binding) {
86
109
 
87
110
  await new Promise((resolve) => {
88
111
  binding.asyncworker.doWorkWithResult(true, {}, function (succeed, succeedString) {
89
- assert(arguments.length == 2);
112
+ assert(arguments.length === 2);
90
113
  assert(succeed);
91
- assert(succeedString == "ok");
114
+ assert(succeedString === 'ok');
92
115
  assert.strictEqual(typeof this, 'object');
93
116
  assert.strictEqual(this.data, 'test data');
94
117
  resolve();
@@ -100,7 +123,63 @@ async function test(binding) {
100
123
 
101
124
  {
102
125
  const hooks = installAsyncHooksForTest();
103
- const triggerAsyncId = async_hooks.executionAsyncId();
126
+ const triggerAsyncId = asyncHooks.executionAsyncId();
127
+ await new Promise((resolve) => {
128
+ const recvObj = { data: 'test data' };
129
+ binding.asyncworker.doWithRecvAsyncRes(recvObj, function (e) {
130
+ assert.strictEqual(typeof e, 'undefined');
131
+ assert.strictEqual(typeof this, 'object');
132
+ assert.strictEqual(this.data, 'test data');
133
+ resolve();
134
+ }, { foo: 'fooBar' });
135
+ });
136
+
137
+ await hooks.then(actual => {
138
+ assert.deepStrictEqual(actual, [
139
+ {
140
+ eventName: 'init',
141
+ type: 'TestResource',
142
+ triggerAsyncId: triggerAsyncId,
143
+ resource: { foo: 'fooBar' }
144
+ },
145
+ { eventName: 'before' },
146
+ { eventName: 'after' },
147
+ { eventName: 'destroy' }
148
+ ]);
149
+ }).catch(common.mustNotCall());
150
+ }
151
+
152
+ {
153
+ const hooks = installAsyncHooksForTest();
154
+ const triggerAsyncId = asyncHooks.executionAsyncId();
155
+ await new Promise((resolve) => {
156
+ const recvObj = { data: 'test data' };
157
+ binding.asyncworker.doWithRecvAsyncRes(recvObj, function (e) {
158
+ assert.strictEqual(typeof e, 'undefined');
159
+ assert.strictEqual(typeof this, 'object');
160
+ assert.strictEqual(this.data, 'test data');
161
+ resolve();
162
+ }, null);
163
+ });
164
+
165
+ await hooks.then(actual => {
166
+ assert.deepStrictEqual(actual, [
167
+ {
168
+ eventName: 'init',
169
+ type: 'TestResource',
170
+ triggerAsyncId: triggerAsyncId,
171
+ resource: { }
172
+ },
173
+ { eventName: 'before' },
174
+ { eventName: 'after' },
175
+ { eventName: 'destroy' }
176
+ ]);
177
+ }).catch(common.mustNotCall());
178
+ }
179
+
180
+ {
181
+ const hooks = installAsyncHooksForTest();
182
+ const triggerAsyncId = asyncHooks.executionAsyncId();
104
183
  await new Promise((resolve) => {
105
184
  binding.asyncworker.doWork(true, { foo: 'foo' }, function (e) {
106
185
  assert.strictEqual(typeof e, 'undefined');
@@ -112,10 +191,12 @@ async function test(binding) {
112
191
 
113
192
  await hooks.then(actual => {
114
193
  assert.deepStrictEqual(actual, [
115
- { eventName: 'init',
194
+ {
195
+ eventName: 'init',
116
196
  type: 'TestResource',
117
197
  triggerAsyncId: triggerAsyncId,
118
- resource: { foo: 'foo' } },
198
+ resource: { foo: 'foo' }
199
+ },
119
200
  { eventName: 'before' },
120
201
  { eventName: 'after' },
121
202
  { eventName: 'destroy' }
@@ -125,13 +206,13 @@ async function test(binding) {
125
206
 
126
207
  {
127
208
  const hooks = installAsyncHooksForTest();
128
- const triggerAsyncId = async_hooks.executionAsyncId();
209
+ const triggerAsyncId = asyncHooks.executionAsyncId();
129
210
  await new Promise((resolve) => {
130
211
  binding.asyncworker.doWorkWithResult(true, { foo: 'foo' },
131
212
  function (succeed, succeedString) {
132
- assert(arguments.length == 2);
213
+ assert(arguments.length === 2);
133
214
  assert(succeed);
134
- assert(succeedString == "ok");
215
+ assert(succeedString === 'ok');
135
216
  assert.strictEqual(typeof this, 'object');
136
217
  assert.strictEqual(this.data, 'test data');
137
218
  resolve();
@@ -140,10 +221,12 @@ async function test(binding) {
140
221
 
141
222
  await hooks.then(actual => {
142
223
  assert.deepStrictEqual(actual, [
143
- { eventName: 'init',
224
+ {
225
+ eventName: 'init',
144
226
  type: 'TestResource',
145
227
  triggerAsyncId: triggerAsyncId,
146
- resource: { foo: 'foo' } },
228
+ resource: { foo: 'foo' }
229
+ },
147
230
  { eventName: 'before' },
148
231
  { eventName: 'after' },
149
232
  { eventName: 'destroy' }
@@ -153,7 +236,7 @@ async function test(binding) {
153
236
 
154
237
  {
155
238
  const hooks = installAsyncHooksForTest();
156
- const triggerAsyncId = async_hooks.executionAsyncId();
239
+ const triggerAsyncId = asyncHooks.executionAsyncId();
157
240
  await new Promise((resolve) => {
158
241
  binding.asyncworker.doWork(false, { foo: 'foo' }, function (e) {
159
242
  assert.ok(e instanceof Error);
@@ -166,10 +249,12 @@ async function test(binding) {
166
249
 
167
250
  await hooks.then(actual => {
168
251
  assert.deepStrictEqual(actual, [
169
- { eventName: 'init',
252
+ {
253
+ eventName: 'init',
170
254
  type: 'TestResource',
171
255
  triggerAsyncId: triggerAsyncId,
172
- resource: { foo: 'foo' } },
256
+ resource: { foo: 'foo' }
257
+ },
173
258
  { eventName: 'before' },
174
259
  { eventName: 'after' },
175
260
  { eventName: 'destroy' }
@@ -4,10 +4,16 @@ const common = require('./common');
4
4
 
5
5
  module.exports = common.runTest(test);
6
6
 
7
- async function test(binding) {
8
- await binding.asyncworker.doWorkNoCallback(true, {})
7
+ async function test (binding) {
8
+ await binding.asyncworker.doWorkAsyncResNoCallback(true, {})
9
9
  .then(common.mustCall()).catch(common.mustNotCall());
10
10
 
11
- await binding.asyncworker.doWorkNoCallback(false, {})
11
+ await binding.asyncworker.doWorkAsyncResNoCallback(false, {})
12
+ .then(common.mustNotCall()).catch(common.mustCall());
13
+
14
+ await binding.asyncworker.doWorkNoCallback(false)
15
+ .then(common.mustNotCall()).catch(common.mustCall());
16
+
17
+ await binding.asyncworker.doWorkNoCallback(true)
12
18
  .then(common.mustNotCall()).catch(common.mustCall());
13
19
  }
@@ -2,11 +2,11 @@
2
2
 
3
3
  const assert = require('assert');
4
4
 
5
- function test(binding, succeed) {
5
+ function test (binding, succeed) {
6
6
  return new Promise((resolve) =>
7
7
  // Can't pass an arrow function to doWork because that results in an
8
8
  // undefined context inside its body when the function gets called.
9
- binding.doWork(succeed, function(e) {
9
+ binding.doWork(succeed, function (e) {
10
10
  setImmediate(() => {
11
11
  // If the work is supposed to fail, make sure there's an error.
12
12
  assert.strictEqual(succeed || e.message === 'test error', true);
@@ -3,8 +3,7 @@ const assert = require('assert');
3
3
 
4
4
  module.exports = require('../common').runTest(test);
5
5
 
6
- function test(binding) {
7
-
6
+ function test (binding) {
8
7
  // create empty array
9
8
  const array = binding.basic_types_array.createArray();
10
9
  assert.strictEqual(binding.basic_types_array.getLength(array), 0);
@@ -15,7 +14,7 @@ function test(binding) {
15
14
 
16
15
  // set function test
17
16
  binding.basic_types_array.set(array, 0, 10);
18
- binding.basic_types_array.set(array, 1, "test");
17
+ binding.basic_types_array.set(array, 1, 'test');
19
18
  binding.basic_types_array.set(array, 2, 3.0);
20
19
 
21
20
  // check length after set data
@@ -23,7 +22,7 @@ function test(binding) {
23
22
 
24
23
  // get function test
25
24
  assert.strictEqual(binding.basic_types_array.get(array, 0), 10);
26
- assert.strictEqual(binding.basic_types_array.get(array, 1), "test");
25
+ assert.strictEqual(binding.basic_types_array.get(array, 1), 'test');
27
26
  assert.strictEqual(binding.basic_types_array.get(array, 2), 3.0);
28
27
 
29
28
  // overwrite test
@@ -31,8 +31,10 @@ Object InitBasicTypesBoolean(Env env) {
31
31
 
32
32
  exports["createBoolean"] = Function::New(env, CreateBoolean);
33
33
  exports["createEmptyBoolean"] = Function::New(env, CreateEmptyBoolean);
34
- exports["createBooleanFromExistingValue"] = Function::New(env, CreateBooleanFromExistingValue);
35
- exports["createBooleanFromPrimitive"] = Function::New(env, CreateBooleanFromPrimitive);
34
+ exports["createBooleanFromExistingValue"] =
35
+ Function::New(env, CreateBooleanFromExistingValue);
36
+ exports["createBooleanFromPrimitive"] =
37
+ Function::New(env, CreateBooleanFromPrimitive);
36
38
  exports["operatorBool"] = Function::New(env, OperatorBool);
37
39
  return exports;
38
40
  }
@@ -4,7 +4,7 @@ const assert = require('assert');
4
4
 
5
5
  module.exports = require('../common').runTest(test);
6
6
 
7
- function test(binding) {
7
+ function test (binding) {
8
8
  const bool1 = binding.basic_types_boolean.createBoolean(true);
9
9
  assert.strictEqual(bool1, true);
10
10
 
@@ -31,5 +31,4 @@ function test(binding) {
31
31
 
32
32
  const bool8 = binding.basic_types_boolean.operatorBool(false);
33
33
  assert.strictEqual(bool8, false);
34
-
35
34
  }
@@ -43,27 +43,32 @@ Value MaxDouble(const CallbackInfo& info) {
43
43
 
44
44
  Value OperatorInt32(const CallbackInfo& info) {
45
45
  Number number = info[0].As<Number>();
46
- return Boolean::New(info.Env(), number.Int32Value() == static_cast<int32_t>(number));
46
+ return Boolean::New(info.Env(),
47
+ number.Int32Value() == static_cast<int32_t>(number));
47
48
  }
48
49
 
49
50
  Value OperatorUint32(const CallbackInfo& info) {
50
51
  Number number = info[0].As<Number>();
51
- return Boolean::New(info.Env(), number.Uint32Value() == static_cast<uint32_t>(number));
52
+ return Boolean::New(info.Env(),
53
+ number.Uint32Value() == static_cast<uint32_t>(number));
52
54
  }
53
55
 
54
56
  Value OperatorInt64(const CallbackInfo& info) {
55
57
  Number number = info[0].As<Number>();
56
- return Boolean::New(info.Env(), number.Int64Value() == static_cast<int64_t>(number));
58
+ return Boolean::New(info.Env(),
59
+ number.Int64Value() == static_cast<int64_t>(number));
57
60
  }
58
61
 
59
62
  Value OperatorFloat(const CallbackInfo& info) {
60
63
  Number number = info[0].As<Number>();
61
- return Boolean::New(info.Env(), number.FloatValue() == static_cast<float>(number));
64
+ return Boolean::New(info.Env(),
65
+ number.FloatValue() == static_cast<float>(number));
62
66
  }
63
67
 
64
68
  Value OperatorDouble(const CallbackInfo& info) {
65
69
  Number number = info[0].As<Number>();
66
- return Boolean::New(info.Env(), number.DoubleValue() == static_cast<double>(number));
70
+ return Boolean::New(info.Env(),
71
+ number.DoubleValue() == static_cast<double>(number));
67
72
  }
68
73
 
69
74
  Value CreateEmptyNumber(const CallbackInfo& info) {
@@ -93,7 +98,8 @@ Object InitBasicTypesNumber(Env env) {
93
98
  exports["operatorFloat"] = Function::New(env, OperatorFloat);
94
99
  exports["operatorDouble"] = Function::New(env, OperatorDouble);
95
100
  exports["createEmptyNumber"] = Function::New(env, CreateEmptyNumber);
96
- exports["createNumberFromExistingValue"] = Function::New(env, CreateNumberFromExistingValue);
101
+ exports["createNumberFromExistingValue"] =
102
+ Function::New(env, CreateNumberFromExistingValue);
97
103
 
98
104
  return exports;
99
105
  }