koffi 2.3.4 → 2.3.6-beta.1

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 (206) hide show
  1. package/CHANGELOG.md +25 -2
  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 +5 -5
  6. package/src/cnoke/cnoke.js +40 -834
  7. package/src/cnoke/package.json +1 -0
  8. package/src/cnoke/src/builder.js +447 -0
  9. package/src/cnoke/src/index.js +20 -0
  10. package/src/cnoke/src/tools.js +401 -0
  11. package/src/core/libcc/libcc.cc +2 -2
  12. package/src/koffi/build/2.3.6-beta.1/koffi_darwin_arm64/koffi.node +0 -0
  13. package/src/koffi/build/2.3.6-beta.1/koffi_darwin_x64/koffi.node +0 -0
  14. package/src/koffi/build/2.3.6-beta.1/koffi_freebsd_arm64/koffi.node +0 -0
  15. package/src/koffi/build/2.3.6-beta.1/koffi_freebsd_ia32/koffi.node +0 -0
  16. package/src/koffi/build/2.3.6-beta.1/koffi_freebsd_x64/koffi.node +0 -0
  17. package/src/koffi/build/2.3.6-beta.1/koffi_linux_arm32hf/koffi.node +0 -0
  18. package/src/koffi/build/2.3.6-beta.1/koffi_linux_arm64/koffi.node +0 -0
  19. package/src/koffi/build/2.3.6-beta.1/koffi_linux_ia32/koffi.node +0 -0
  20. package/src/koffi/build/2.3.6-beta.1/koffi_linux_riscv64hf64/koffi.node +0 -0
  21. package/src/koffi/build/2.3.6-beta.1/koffi_linux_x64/koffi.node +0 -0
  22. package/src/koffi/build/2.3.6-beta.1/koffi_openbsd_ia32/koffi.node +0 -0
  23. package/src/koffi/build/2.3.6-beta.1/koffi_openbsd_x64/koffi.node +0 -0
  24. package/src/koffi/build/2.3.6-beta.1/koffi_win32_arm64/koffi.exp +0 -0
  25. package/src/koffi/build/2.3.6-beta.1/koffi_win32_arm64/koffi.lib +0 -0
  26. package/src/koffi/build/2.3.6-beta.1/koffi_win32_arm64/koffi.node +0 -0
  27. package/src/koffi/build/2.3.6-beta.1/koffi_win32_arm64/koffi.pdb +0 -0
  28. package/src/koffi/build/2.3.6-beta.1/koffi_win32_ia32/koffi.exp +0 -0
  29. package/src/koffi/build/2.3.6-beta.1/koffi_win32_ia32/koffi.lib +0 -0
  30. package/src/koffi/build/2.3.6-beta.1/koffi_win32_ia32/koffi.node +0 -0
  31. package/src/koffi/build/2.3.6-beta.1/koffi_win32_ia32/koffi.pdb +0 -0
  32. package/src/koffi/build/2.3.6-beta.1/koffi_win32_x64/koffi.exp +0 -0
  33. package/src/koffi/build/2.3.6-beta.1/koffi_win32_x64/koffi.lib +0 -0
  34. package/src/koffi/build/2.3.6-beta.1/koffi_win32_x64/koffi.node +0 -0
  35. package/src/koffi/build/2.3.6-beta.1/koffi_win32_x64/koffi.pdb +0 -0
  36. package/src/koffi/src/abi_arm32.cc +43 -14
  37. package/src/koffi/src/abi_arm64.cc +95 -21
  38. package/src/koffi/src/abi_riscv64.cc +125 -64
  39. package/src/koffi/src/abi_x64_sysv.cc +38 -20
  40. package/src/koffi/src/abi_x64_win.cc +11 -5
  41. package/src/koffi/src/abi_x86.cc +14 -7
  42. package/src/koffi/src/call.cc +114 -44
  43. package/src/koffi/src/call.hh +6 -4
  44. package/src/koffi/src/ffi.cc +172 -147
  45. package/src/koffi/src/ffi.hh +18 -10
  46. package/src/koffi/src/index.d.ts +28 -7
  47. package/src/koffi/src/index.js +23 -4
  48. package/src/koffi/src/util.cc +261 -69
  49. package/src/koffi/src/util.hh +34 -8
  50. package/vendor/node-addon-api/CHANGELOG.md +122 -9
  51. package/vendor/node-addon-api/CONTRIBUTING.md +10 -10
  52. package/vendor/node-addon-api/README.md +36 -12
  53. package/vendor/node-addon-api/benchmark/function_args.cc +95 -62
  54. package/vendor/node-addon-api/benchmark/function_args.js +6 -6
  55. package/vendor/node-addon-api/benchmark/index.js +1 -1
  56. package/vendor/node-addon-api/benchmark/property_descriptor.cc +27 -34
  57. package/vendor/node-addon-api/benchmark/property_descriptor.js +5 -4
  58. package/vendor/node-addon-api/doc/async_operations.md +1 -1
  59. package/vendor/node-addon-api/doc/async_worker_variants.md +23 -2
  60. package/vendor/node-addon-api/doc/cmake-js.md +1 -1
  61. package/vendor/node-addon-api/doc/error_handling.md +3 -3
  62. package/vendor/node-addon-api/doc/external.md +7 -0
  63. package/vendor/node-addon-api/doc/handle_scope.md +14 -0
  64. package/vendor/node-addon-api/doc/hierarchy.md +1 -1
  65. package/vendor/node-addon-api/doc/object.md +27 -0
  66. package/vendor/node-addon-api/index.js +3 -3
  67. package/vendor/node-addon-api/napi-inl.deprecated.h +121 -127
  68. package/vendor/node-addon-api/napi-inl.h +1178 -1144
  69. package/vendor/node-addon-api/napi.h +2786 -2675
  70. package/vendor/node-addon-api/package.json +42 -1
  71. package/vendor/node-addon-api/test/addon.cc +8 -6
  72. package/vendor/node-addon-api/test/addon_build/index.js +9 -9
  73. package/vendor/node-addon-api/test/addon_build/tpl/addon.cc +2 -1
  74. package/vendor/node-addon-api/test/addon_build/tpl/index.js +4 -4
  75. package/vendor/node-addon-api/test/addon_data.cc +12 -13
  76. package/vendor/node-addon-api/test/array_buffer.js +3 -2
  77. package/vendor/node-addon-api/test/async_progress_queue_worker.cc +13 -3
  78. package/vendor/node-addon-api/test/async_progress_queue_worker.js +5 -5
  79. package/vendor/node-addon-api/test/async_progress_worker.cc +65 -9
  80. package/vendor/node-addon-api/test/async_progress_worker.js +14 -9
  81. package/vendor/node-addon-api/test/async_worker.cc +236 -3
  82. package/vendor/node-addon-api/test/async_worker.js +122 -37
  83. package/vendor/node-addon-api/test/async_worker_nocallback.js +9 -3
  84. package/vendor/node-addon-api/test/async_worker_persistent.js +2 -2
  85. package/vendor/node-addon-api/test/basic_types/array.js +3 -4
  86. package/vendor/node-addon-api/test/basic_types/boolean.cc +4 -2
  87. package/vendor/node-addon-api/test/basic_types/boolean.js +1 -2
  88. package/vendor/node-addon-api/test/basic_types/number.cc +12 -6
  89. package/vendor/node-addon-api/test/basic_types/number.js +19 -18
  90. package/vendor/node-addon-api/test/basic_types/value.cc +52 -1
  91. package/vendor/node-addon-api/test/basic_types/value.js +44 -21
  92. package/vendor/node-addon-api/test/bigint.cc +2 -1
  93. package/vendor/node-addon-api/test/binding.cc +11 -5
  94. package/vendor/node-addon-api/test/binding.gyp +3 -1
  95. package/vendor/node-addon-api/test/buffer.cc +46 -38
  96. package/vendor/node-addon-api/test/buffer.js +12 -12
  97. package/vendor/node-addon-api/test/callbackInfo.cc +27 -0
  98. package/vendor/node-addon-api/test/callbackInfo.js +9 -0
  99. package/vendor/node-addon-api/test/callbackscope.cc +19 -2
  100. package/vendor/node-addon-api/test/callbackscope.js +20 -20
  101. package/vendor/node-addon-api/test/common/index.js +37 -4
  102. package/vendor/node-addon-api/test/dataview/dataview.js +5 -5
  103. package/vendor/node-addon-api/test/dataview/dataview_read_write.js +14 -12
  104. package/vendor/node-addon-api/test/date.cc +2 -1
  105. package/vendor/node-addon-api/test/date.js +2 -2
  106. package/vendor/node-addon-api/test/env_cleanup.cc +12 -0
  107. package/vendor/node-addon-api/test/env_cleanup.js +38 -39
  108. package/vendor/node-addon-api/test/error.cc +6 -5
  109. package/vendor/node-addon-api/test/error_terminating_environment.js +64 -60
  110. package/vendor/node-addon-api/test/external.cc +36 -32
  111. package/vendor/node-addon-api/test/external.js +43 -46
  112. package/vendor/node-addon-api/test/function.cc +58 -44
  113. package/vendor/node-addon-api/test/function.js +4 -0
  114. package/vendor/node-addon-api/test/function_reference.cc +15 -13
  115. package/vendor/node-addon-api/test/globalObject/global_object_delete_property.js +50 -53
  116. package/vendor/node-addon-api/test/globalObject/global_object_get_property.js +33 -34
  117. package/vendor/node-addon-api/test/globalObject/global_object_has_own_property.js +38 -40
  118. package/vendor/node-addon-api/test/globalObject/global_object_set_property.js +47 -49
  119. package/vendor/node-addon-api/test/handlescope.cc +29 -3
  120. package/vendor/node-addon-api/test/handlescope.js +5 -3
  121. package/vendor/node-addon-api/test/index.js +1 -5
  122. package/vendor/node-addon-api/test/maybe/check.cc +49 -3
  123. package/vendor/node-addon-api/test/maybe/index.js +19 -7
  124. package/vendor/node-addon-api/test/memory_management.cc +9 -8
  125. package/vendor/node-addon-api/test/memory_management.js +2 -2
  126. package/vendor/node-addon-api/test/movable_callbacks.js +2 -2
  127. package/vendor/node-addon-api/test/name.js +3 -3
  128. package/vendor/node-addon-api/test/napi_child.js +2 -2
  129. package/vendor/node-addon-api/test/object/delete_property.js +7 -7
  130. package/vendor/node-addon-api/test/object/finalizer.cc +13 -12
  131. package/vendor/node-addon-api/test/object/finalizer.js +2 -2
  132. package/vendor/node-addon-api/test/object/get_property.js +6 -6
  133. package/vendor/node-addon-api/test/object/has_own_property.js +3 -3
  134. package/vendor/node-addon-api/test/object/has_property.js +4 -4
  135. package/vendor/node-addon-api/test/object/object.cc +191 -111
  136. package/vendor/node-addon-api/test/object/object.js +53 -52
  137. package/vendor/node-addon-api/test/object/object_deprecated.cc +24 -20
  138. package/vendor/node-addon-api/test/object/object_deprecated.js +3 -8
  139. package/vendor/node-addon-api/test/object/object_freeze_seal.js +54 -54
  140. package/vendor/node-addon-api/test/object/object_type_tag.cc +39 -0
  141. package/vendor/node-addon-api/test/object/object_type_tag.js +55 -0
  142. package/vendor/node-addon-api/test/object/subscript_operator.js +2 -2
  143. package/vendor/node-addon-api/test/object_reference.js +100 -100
  144. package/vendor/node-addon-api/test/objectwrap.cc +41 -34
  145. package/vendor/node-addon-api/test/objectwrap.js +23 -19
  146. package/vendor/node-addon-api/test/objectwrap_constructor_exception.cc +5 -5
  147. package/vendor/node-addon-api/test/objectwrap_constructor_exception.js +1 -1
  148. package/vendor/node-addon-api/test/objectwrap_multiple_inheritance.cc +7 -7
  149. package/vendor/node-addon-api/test/objectwrap_multiple_inheritance.js +1 -1
  150. package/vendor/node-addon-api/test/objectwrap_removewrap.js +24 -32
  151. package/vendor/node-addon-api/test/objectwrap_worker_thread.js +5 -4
  152. package/vendor/node-addon-api/test/promise.cc +7 -0
  153. package/vendor/node-addon-api/test/promise.js +3 -1
  154. package/vendor/node-addon-api/test/reference.cc +1 -1
  155. package/vendor/node-addon-api/test/reference.js +2 -2
  156. package/vendor/node-addon-api/test/run_script.cc +1 -1
  157. package/vendor/node-addon-api/test/symbol.js +59 -66
  158. package/vendor/node-addon-api/test/testUtil.js +6 -6
  159. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function.cc +64 -29
  160. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function.js +71 -34
  161. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ctx.cc +111 -19
  162. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ctx.js +2 -1
  163. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_existing_tsfn.cc +36 -26
  164. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_existing_tsfn.js +5 -5
  165. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ptr.cc +3 -2
  166. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ptr.js +1 -1
  167. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_sum.cc +47 -32
  168. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_sum.js +3 -3
  169. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_unref.cc +22 -9
  170. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_unref.js +76 -31
  171. package/vendor/node-addon-api/test/thunking_manual.cc +61 -74
  172. package/vendor/node-addon-api/test/thunking_manual.js +6 -7
  173. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function.cc +20 -20
  174. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function.js +19 -19
  175. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ctx.cc +57 -5
  176. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ctx.js +2 -0
  177. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_existing_tsfn.js +5 -5
  178. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ptr.cc +5 -1
  179. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ptr.js +4 -3
  180. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_sum.js +3 -3
  181. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_unref.cc +14 -0
  182. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_unref.js +76 -31
  183. package/vendor/node-addon-api/test/typedarray-bigint.js +2 -2
  184. package/vendor/node-addon-api/test/typedarray.cc +263 -70
  185. package/vendor/node-addon-api/test/typedarray.js +44 -10
  186. package/vendor/node-addon-api/test/version_management.cc +16 -15
  187. package/vendor/node-addon-api/test/version_management.js +18 -20
  188. package/vendor/node-addon-api/tools/check-napi.js +13 -14
  189. package/vendor/node-addon-api/tools/conversion.js +161 -169
  190. package/vendor/node-addon-api/tools/eslint-format.js +9 -1
  191. package/vendor/node-addon-api/unit-test/README.md +4 -4
  192. package/src/koffi/build/2.3.4/koffi_darwin_arm64.tar.gz +0 -0
  193. package/src/koffi/build/2.3.4/koffi_darwin_x64.tar.gz +0 -0
  194. package/src/koffi/build/2.3.4/koffi_freebsd_arm64.tar.gz +0 -0
  195. package/src/koffi/build/2.3.4/koffi_freebsd_ia32.tar.gz +0 -0
  196. package/src/koffi/build/2.3.4/koffi_freebsd_x64.tar.gz +0 -0
  197. package/src/koffi/build/2.3.4/koffi_linux_arm32hf.tar.gz +0 -0
  198. package/src/koffi/build/2.3.4/koffi_linux_arm64.tar.gz +0 -0
  199. package/src/koffi/build/2.3.4/koffi_linux_ia32.tar.gz +0 -0
  200. package/src/koffi/build/2.3.4/koffi_linux_riscv64hf64.tar.gz +0 -0
  201. package/src/koffi/build/2.3.4/koffi_linux_x64.tar.gz +0 -0
  202. package/src/koffi/build/2.3.4/koffi_openbsd_ia32.tar.gz +0 -0
  203. package/src/koffi/build/2.3.4/koffi_openbsd_x64.tar.gz +0 -0
  204. package/src/koffi/build/2.3.4/koffi_win32_arm64.tar.gz +0 -0
  205. package/src/koffi/build/2.3.4/koffi_win32_ia32.tar.gz +0 -0
  206. package/src/koffi/build/2.3.4/koffi_win32_x64.tar.gz +0 -0
@@ -1,9 +1,9 @@
1
1
  // Run each test function in sequence,
2
2
  // with an async delay and GC call between each.
3
3
 
4
- function tick(x) {
4
+ function tick (x) {
5
5
  return new Promise((resolve) => {
6
- setImmediate(function ontick() {
6
+ setImmediate(function ontick () {
7
7
  if (--x === 0) {
8
8
  resolve();
9
9
  } else {
@@ -11,9 +11,9 @@ function tick(x) {
11
11
  }
12
12
  });
13
13
  });
14
- };
14
+ }
15
15
 
16
- async function runGCTests(tests) {
16
+ async function runGCTests (tests) {
17
17
  // Break up test list into a list of lists of the form
18
18
  // [ [ 'test name', function() {}, ... ], ..., ].
19
19
  const testList = [];
@@ -27,7 +27,7 @@ async function runGCTests(tests) {
27
27
  }
28
28
 
29
29
  for (const test of testList) {
30
- await (async function(test) {
30
+ await (async function (test) {
31
31
  let title;
32
32
  for (let i = 0; i < test.length; i++) {
33
33
  if (i === 0) {
@@ -50,5 +50,5 @@ async function runGCTests(tests) {
50
50
  }
51
51
 
52
52
  module.exports = {
53
- runGCTests,
53
+ runGCTests
54
54
  };
@@ -12,13 +12,15 @@ constexpr size_t ARRAY_LENGTH = 10;
12
12
  constexpr size_t MAX_QUEUE_SIZE = 2;
13
13
 
14
14
  static std::thread threads[2];
15
- static ThreadSafeFunction tsfn;
15
+ static ThreadSafeFunction s_tsfn;
16
16
 
17
17
  struct ThreadSafeFunctionInfo {
18
18
  enum CallType {
19
19
  DEFAULT,
20
20
  BLOCKING,
21
- NON_BLOCKING
21
+ NON_BLOCKING,
22
+ NON_BLOCKING_DEFAULT,
23
+ NON_BLOCKING_SINGLE_ARG
22
24
  } type;
23
25
  bool abort;
24
26
  bool startSecondary;
@@ -33,44 +35,57 @@ struct ThreadSafeFunctionInfo {
33
35
  static int ints[ARRAY_LENGTH];
34
36
 
35
37
  static void SecondaryThread() {
36
- if (tsfn.Release() != napi_ok) {
38
+ if (s_tsfn.Release() != napi_ok) {
37
39
  Error::Fatal("SecondaryThread", "ThreadSafeFunction.Release() failed");
38
40
  }
39
41
  }
40
42
 
41
43
  // Source thread producing the data
42
44
  static void DataSourceThread() {
43
- ThreadSafeFunctionInfo* info = tsfn.GetContext();
45
+ ThreadSafeFunctionInfo* info = s_tsfn.GetContext();
44
46
 
45
47
  if (info->startSecondary) {
46
- if (tsfn.Acquire() != napi_ok) {
48
+ if (s_tsfn.Acquire() != napi_ok) {
47
49
  Error::Fatal("DataSourceThread", "ThreadSafeFunction.Acquire() failed");
48
50
  }
49
-
50
51
  threads[1] = std::thread(SecondaryThread);
51
52
  }
52
53
 
53
54
  bool queueWasFull = false;
54
55
  bool queueWasClosing = false;
56
+
55
57
  for (int index = ARRAY_LENGTH - 1; index > -1 && !queueWasClosing; index--) {
56
58
  napi_status status = napi_generic_failure;
59
+
57
60
  auto callback = [](Env env, Function jsCallback, int* data) {
58
- jsCallback.Call({ Number::New(env, *data) });
61
+ jsCallback.Call({Number::New(env, *data)});
62
+ };
63
+
64
+ auto noArgCallback = [](Env env, Function jsCallback) {
65
+ jsCallback.Call({Number::New(env, 42)});
59
66
  };
60
67
 
61
68
  switch (info->type) {
62
69
  case ThreadSafeFunctionInfo::DEFAULT:
63
- status = tsfn.BlockingCall();
70
+ status = s_tsfn.BlockingCall();
64
71
  break;
65
72
  case ThreadSafeFunctionInfo::BLOCKING:
66
- status = tsfn.BlockingCall(&ints[index], callback);
73
+ status = s_tsfn.BlockingCall(&ints[index], callback);
67
74
  break;
68
75
  case ThreadSafeFunctionInfo::NON_BLOCKING:
69
- status = tsfn.NonBlockingCall(&ints[index], callback);
76
+ status = s_tsfn.NonBlockingCall(&ints[index], callback);
77
+ break;
78
+ case ThreadSafeFunctionInfo::NON_BLOCKING_DEFAULT:
79
+ status = s_tsfn.NonBlockingCall();
80
+ break;
81
+
82
+ case ThreadSafeFunctionInfo::NON_BLOCKING_SINGLE_ARG:
83
+ status = s_tsfn.NonBlockingCall(noArgCallback);
70
84
  break;
71
85
  }
72
86
 
73
- if (info->abort && info->type != ThreadSafeFunctionInfo::NON_BLOCKING) {
87
+ if (info->abort && (info->type == ThreadSafeFunctionInfo::BLOCKING ||
88
+ info->type == ThreadSafeFunctionInfo::DEFAULT)) {
74
89
  // Let's make this thread really busy to give the main thread a chance to
75
90
  // abort / close.
76
91
  std::unique_lock<std::mutex> lk(info->protect);
@@ -80,20 +95,20 @@ static void DataSourceThread() {
80
95
  }
81
96
 
82
97
  switch (status) {
83
- case napi_queue_full:
84
- queueWasFull = true;
85
- index++;
86
- // fall through
98
+ case napi_queue_full:
99
+ queueWasFull = true;
100
+ index++;
101
+ // fall through
87
102
 
88
- case napi_ok:
89
- continue;
103
+ case napi_ok:
104
+ continue;
90
105
 
91
- case napi_closing:
92
- queueWasClosing = true;
93
- break;
106
+ case napi_closing:
107
+ queueWasClosing = true;
108
+ break;
94
109
 
95
- default:
96
- Error::Fatal("DataSourceThread", "ThreadSafeFunction.*Call() failed");
110
+ default:
111
+ Error::Fatal("DataSourceThread", "ThreadSafeFunction.*Call() failed");
97
112
  }
98
113
  }
99
114
 
@@ -105,7 +120,7 @@ static void DataSourceThread() {
105
120
  Error::Fatal("DataSourceThread", "Queue was never closing");
106
121
  }
107
122
 
108
- if (!queueWasClosing && tsfn.Release() != napi_ok) {
123
+ if (!queueWasClosing && s_tsfn.Release() != napi_ok) {
109
124
  Error::Fatal("DataSourceThread", "ThreadSafeFunction.Release() failed");
110
125
  }
111
126
  }
@@ -114,9 +129,9 @@ static Value StopThread(const CallbackInfo& info) {
114
129
  tsfnInfo.jsFinalizeCallback = Napi::Persistent(info[0].As<Function>());
115
130
  bool abort = info[1].As<Boolean>();
116
131
  if (abort) {
117
- tsfn.Abort();
132
+ s_tsfn.Abort();
118
133
  } else {
119
- tsfn.Release();
134
+ s_tsfn.Release();
120
135
  }
121
136
  {
122
137
  std::lock_guard<std::mutex> _(tsfnInfo.protect);
@@ -140,15 +155,21 @@ static void JoinTheThreads(Env /* env */,
140
155
  }
141
156
 
142
157
  static Value StartThreadInternal(const CallbackInfo& info,
143
- ThreadSafeFunctionInfo::CallType type) {
158
+ ThreadSafeFunctionInfo::CallType type) {
144
159
  tsfnInfo.type = type;
145
160
  tsfnInfo.abort = info[1].As<Boolean>();
146
161
  tsfnInfo.startSecondary = info[2].As<Boolean>();
147
162
  tsfnInfo.maxQueueSize = info[3].As<Number>().Uint32Value();
148
163
  tsfnInfo.closeCalledFromJs = false;
149
164
 
150
- tsfn = ThreadSafeFunction::New(info.Env(), info[0].As<Function>(),
151
- "Test", tsfnInfo.maxQueueSize, 2, &tsfnInfo, JoinTheThreads, threads);
165
+ s_tsfn = ThreadSafeFunction::New(info.Env(),
166
+ info[0].As<Function>(),
167
+ "Test",
168
+ tsfnInfo.maxQueueSize,
169
+ 2,
170
+ &tsfnInfo,
171
+ JoinTheThreads,
172
+ threads);
152
173
 
153
174
  threads[0] = std::thread(DataSourceThread);
154
175
 
@@ -156,7 +177,7 @@ static Value StartThreadInternal(const CallbackInfo& info,
156
177
  }
157
178
 
158
179
  static Value Release(const CallbackInfo& /* info */) {
159
- if (tsfn.Release() != napi_ok) {
180
+ if (s_tsfn.Release() != napi_ok) {
160
181
  Error::Fatal("Release", "ThreadSafeFunction.Release() failed");
161
182
  }
162
183
  return Value();
@@ -174,6 +195,16 @@ static Value StartThreadNoNative(const CallbackInfo& info) {
174
195
  return StartThreadInternal(info, ThreadSafeFunctionInfo::DEFAULT);
175
196
  }
176
197
 
198
+ static Value StartThreadNonblockingNoNative(const CallbackInfo& info) {
199
+ return StartThreadInternal(info,
200
+ ThreadSafeFunctionInfo::NON_BLOCKING_DEFAULT);
201
+ }
202
+
203
+ static Value StartThreadNonBlockingSingleArg(const CallbackInfo& info) {
204
+ return StartThreadInternal(info,
205
+ ThreadSafeFunctionInfo::NON_BLOCKING_SINGLE_ARG);
206
+ }
207
+
177
208
  Object InitThreadSafeFunction(Env env) {
178
209
  for (size_t index = 0; index < ARRAY_LENGTH; index++) {
179
210
  ints[index] = index;
@@ -184,8 +215,12 @@ Object InitThreadSafeFunction(Env env) {
184
215
  exports["MAX_QUEUE_SIZE"] = Number::New(env, MAX_QUEUE_SIZE);
185
216
  exports["startThread"] = Function::New(env, StartThread);
186
217
  exports["startThreadNoNative"] = Function::New(env, StartThreadNoNative);
218
+ exports["startThreadNonblockingNoNative"] =
219
+ Function::New(env, StartThreadNonblockingNoNative);
187
220
  exports["startThreadNonblocking"] =
188
221
  Function::New(env, StartThreadNonblocking);
222
+ exports["startThreadNonblockSingleArg"] =
223
+ Function::New(env, StartThreadNonBlockingSingleArg);
189
224
  exports["stopThread"] = Function::New(env, StopThread);
190
225
  exports["release"] = Function::New(env, Release);
191
226
 
@@ -5,8 +5,9 @@ const common = require('../common');
5
5
 
6
6
  module.exports = common.runTest(test);
7
7
 
8
- async function test(binding) {
9
- const expectedArray = (function(arrayLength) {
8
+ // Main test body
9
+ async function test (binding) {
10
+ const expectedArray = (function (arrayLength) {
10
11
  const result = [];
11
12
  for (let index = 0; index < arrayLength; index++) {
12
13
  result.push(arrayLength - 1 - index);
@@ -14,15 +15,18 @@ async function test(binding) {
14
15
  return result;
15
16
  })(binding.threadsafe_function.ARRAY_LENGTH);
16
17
 
17
- function testWithJSMarshaller({
18
+ const expectedDefaultArray = Array.from({ length: binding.threadsafe_function.ARRAY_LENGTH }, (_, i) => 42);
19
+
20
+ function testWithJSMarshaller ({
18
21
  threadStarter,
19
22
  quitAfter,
20
23
  abort,
21
24
  maxQueueSize,
22
- launchSecondary }) {
25
+ launchSecondary
26
+ }) {
23
27
  return new Promise((resolve) => {
24
28
  const array = [];
25
- binding.threadsafe_function[threadStarter](function testCallback(value) {
29
+ binding.threadsafe_function[threadStarter](function testCallback (value) {
26
30
  array.push(value);
27
31
  if (array.length === quitAfter) {
28
32
  binding.threadsafe_function.stopThread(common.mustCall(() => {
@@ -30,7 +34,7 @@ async function test(binding) {
30
34
  }), !!abort);
31
35
  }
32
36
  }, !!abort, !!launchSecondary, maxQueueSize);
33
- if (threadStarter === 'startThreadNonblocking') {
37
+ if ((threadStarter === 'startThreadNonblocking' || threadStarter === 'startThreadNonblockSingleArg')) {
34
38
  // Let's make this thread really busy for a short while to ensure that
35
39
  // the queue fills and the thread receives a napi_queue_full.
36
40
  const start = Date.now();
@@ -39,23 +43,28 @@ async function test(binding) {
39
43
  });
40
44
  }
41
45
 
42
- await new Promise(function testWithoutJSMarshaller(resolve) {
43
- let callCount = 0;
44
- binding.threadsafe_function.startThreadNoNative(function testCallback() {
45
- callCount++;
46
+ function testWithoutJSMarshallers (nativeFunction) {
47
+ return new Promise((resolve) => {
48
+ let callCount = 0;
49
+ nativeFunction(function testCallback () {
50
+ callCount++;
51
+
52
+ // The default call-into-JS implementation passes no arguments.
53
+ assert.strictEqual(arguments.length, 0);
54
+ if (callCount === binding.threadsafe_function.ARRAY_LENGTH) {
55
+ setImmediate(() => {
56
+ binding.threadsafe_function.stopThread(common.mustCall(() => {
57
+ resolve();
58
+ }), false);
59
+ });
60
+ }
61
+ }, false /* abort */, false /* launchSecondary */,
62
+ binding.threadsafe_function.MAX_QUEUE_SIZE);
63
+ });
64
+ }
46
65
 
47
- // The default call-into-JS implementation passes no arguments.
48
- assert.strictEqual(arguments.length, 0);
49
- if (callCount === binding.threadsafe_function.ARRAY_LENGTH) {
50
- setImmediate(() => {
51
- binding.threadsafe_function.stopThread(common.mustCall(() => {
52
- resolve();
53
- }), false);
54
- });
55
- }
56
- }, false /* abort */, false /* launchSecondary */,
57
- binding.threadsafe_function.MAX_QUEUE_SIZE);
58
- });
66
+ await testWithoutJSMarshallers(binding.threadsafe_function.startThreadNoNative);
67
+ await testWithoutJSMarshallers(binding.threadsafe_function.startThreadNonblockingNoNative);
59
68
 
60
69
  // Start the thread in blocking mode, and assert that all values are passed.
61
70
  // Quit after it's done.
@@ -65,7 +74,7 @@ async function test(binding) {
65
74
  maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
66
75
  quitAfter: binding.threadsafe_function.ARRAY_LENGTH
67
76
  }),
68
- expectedArray,
77
+ expectedArray
69
78
  );
70
79
 
71
80
  // Start the thread in blocking mode with an infinite queue, and assert that
@@ -76,7 +85,7 @@ async function test(binding) {
76
85
  maxQueueSize: 0,
77
86
  quitAfter: binding.threadsafe_function.ARRAY_LENGTH
78
87
  }),
79
- expectedArray,
88
+ expectedArray
80
89
  );
81
90
 
82
91
  // Start the thread in non-blocking mode, and assert that all values are
@@ -87,7 +96,7 @@ async function test(binding) {
87
96
  maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
88
97
  quitAfter: binding.threadsafe_function.ARRAY_LENGTH
89
98
  }),
90
- expectedArray,
99
+ expectedArray
91
100
  );
92
101
 
93
102
  // Start the thread in blocking mode, and assert that all values are passed.
@@ -98,7 +107,7 @@ async function test(binding) {
98
107
  maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
99
108
  quitAfter: 1
100
109
  }),
101
- expectedArray,
110
+ expectedArray
102
111
  );
103
112
 
104
113
  // Start the thread in blocking mode with an infinite queue, and assert that
@@ -109,10 +118,9 @@ async function test(binding) {
109
118
  maxQueueSize: 0,
110
119
  quitAfter: 1
111
120
  }),
112
- expectedArray,
121
+ expectedArray
113
122
  );
114
123
 
115
-
116
124
  // Start the thread in non-blocking mode, and assert that all values are
117
125
  // passed. Quit early, but let the thread finish.
118
126
  assert.deepStrictEqual(
@@ -121,7 +129,16 @@ async function test(binding) {
121
129
  maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
122
130
  quitAfter: 1
123
131
  }),
124
- expectedArray,
132
+ expectedArray
133
+ );
134
+
135
+ assert.deepStrictEqual(
136
+ await testWithJSMarshaller({
137
+ threadStarter: 'startThreadNonblockSingleArg',
138
+ maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
139
+ quitAfter: 1
140
+ }),
141
+ expectedDefaultArray
125
142
  );
126
143
 
127
144
  // Start the thread in blocking mode, and assert that all values are passed.
@@ -134,7 +151,7 @@ async function test(binding) {
134
151
  maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
135
152
  launchSecondary: true
136
153
  }),
137
- expectedArray,
154
+ expectedArray
138
155
  );
139
156
 
140
157
  // Start the thread in non-blocking mode, and assert that all values are
@@ -147,7 +164,17 @@ async function test(binding) {
147
164
  maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
148
165
  launchSecondary: true
149
166
  }),
150
- expectedArray,
167
+ expectedArray
168
+ );
169
+
170
+ assert.deepStrictEqual(
171
+ await testWithJSMarshaller({
172
+ threadStarter: 'startThreadNonblockSingleArg',
173
+ maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
174
+ quitAfter: 1,
175
+ launchSecondary: true
176
+ }),
177
+ expectedDefaultArray
151
178
  );
152
179
 
153
180
  // Start the thread in blocking mode, and assert that it could not finish.
@@ -159,7 +186,7 @@ async function test(binding) {
159
186
  maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
160
187
  abort: true
161
188
  })).indexOf(0),
162
- -1,
189
+ -1
163
190
  );
164
191
 
165
192
  // Start the thread in blocking mode with an infinite queue, and assert that
@@ -171,7 +198,7 @@ async function test(binding) {
171
198
  maxQueueSize: 0,
172
199
  abort: true
173
200
  })).indexOf(0),
174
- -1,
201
+ -1
175
202
  );
176
203
 
177
204
  // Start the thread in non-blocking mode, and assert that it could not finish.
@@ -183,6 +210,16 @@ async function test(binding) {
183
210
  maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
184
211
  abort: true
185
212
  })).indexOf(0),
186
- -1,
213
+ -1
214
+ );
215
+
216
+ assert.strictEqual(
217
+ (await testWithJSMarshaller({
218
+ threadStarter: 'startThreadNonblockSingleArg',
219
+ quitAfter: 1,
220
+ maxQueueSize: binding.threadsafe_function.MAX_QUEUE_SIZE,
221
+ abort: true
222
+ })).indexOf(0),
223
+ -1
187
224
  );
188
225
  }
@@ -1,3 +1,4 @@
1
+ #include <assert.h>
1
2
  #include "napi.h"
2
3
 
3
4
  #if (NAPI_VERSION > 3)
@@ -7,57 +8,148 @@ using namespace Napi;
7
8
  namespace {
8
9
 
9
10
  class TSFNWrap : public ObjectWrap<TSFNWrap> {
10
- public:
11
- static Object Init(Napi::Env env, Object exports);
12
- TSFNWrap(const CallbackInfo &info);
11
+ public:
12
+ static Function Init(Napi::Env env);
13
+ TSFNWrap(const CallbackInfo& info);
13
14
 
14
- Napi::Value GetContext(const CallbackInfo & /*info*/) {
15
- Reference<Napi::Value> *ctx = _tsfn.GetContext();
15
+ Napi::Value GetContext(const CallbackInfo& /*info*/) {
16
+ Reference<Napi::Value>* ctx = _tsfn.GetContext();
16
17
  return ctx->Value();
17
18
  };
18
19
 
19
- Napi::Value Release(const CallbackInfo &info) {
20
+ Napi::Value Release(const CallbackInfo& info) {
20
21
  Napi::Env env = info.Env();
21
22
  _deferred = std::unique_ptr<Promise::Deferred>(new Promise::Deferred(env));
22
23
  _tsfn.Release();
23
24
  return _deferred->Promise();
24
25
  };
25
26
 
26
- private:
27
+ private:
27
28
  ThreadSafeFunction _tsfn;
28
29
  std::unique_ptr<Promise::Deferred> _deferred;
29
30
  };
30
31
 
31
- Object TSFNWrap::Init(Napi::Env env, Object exports) {
32
+ Function TSFNWrap::Init(Napi::Env env) {
32
33
  Function func =
33
- DefineClass(env, "TSFNWrap",
34
+ DefineClass(env,
35
+ "TSFNWrap",
34
36
  {InstanceMethod("getContext", &TSFNWrap::GetContext),
35
37
  InstanceMethod("release", &TSFNWrap::Release)});
36
-
37
- exports.Set("TSFNWrap", func);
38
- return exports;
38
+ return func;
39
39
  }
40
40
 
41
- TSFNWrap::TSFNWrap(const CallbackInfo &info) : ObjectWrap<TSFNWrap>(info) {
41
+ TSFNWrap::TSFNWrap(const CallbackInfo& info) : ObjectWrap<TSFNWrap>(info) {
42
42
  Napi::Env env = info.Env();
43
43
 
44
- Reference<Napi::Value> *_ctx = new Reference<Napi::Value>;
44
+ Reference<Napi::Value>* _ctx = new Reference<Napi::Value>;
45
45
  *_ctx = Persistent(info[0]);
46
46
 
47
47
  _tsfn = ThreadSafeFunction::New(
48
- info.Env(), Function::New(env, [](const CallbackInfo & /*info*/) {}),
49
- Object::New(env), "Test", 1, 1, _ctx,
50
- [this](Napi::Env env, Reference<Napi::Value> *ctx) {
48
+ info.Env(),
49
+ Function::New(env, [](const CallbackInfo& /*info*/) {}),
50
+ Object::New(env),
51
+ "Test",
52
+ 1,
53
+ 1,
54
+ _ctx,
55
+ [this](Napi::Env env, Reference<Napi::Value>* ctx) {
51
56
  _deferred->Resolve(env.Undefined());
52
57
  ctx->Reset();
53
58
  delete ctx;
54
59
  });
55
60
  }
61
+ struct SimpleTestContext {
62
+ SimpleTestContext(int val) : _val(val) {}
63
+ int _val = -1;
64
+ };
65
+
66
+ void AssertGetContextFromVariousTSOverloads(const CallbackInfo& info) {
67
+ Env env = info.Env();
68
+ Function emptyFunc;
69
+
70
+ SimpleTestContext* ctx = new SimpleTestContext(42);
71
+ ThreadSafeFunction fn =
72
+ ThreadSafeFunction::New(env, emptyFunc, "testResource", 1, 1, ctx);
73
+
74
+ assert(fn.GetContext() == ctx);
75
+ delete ctx;
76
+ fn.Release();
77
+
78
+ fn = ThreadSafeFunction::New(env, emptyFunc, "testRes", 1, 1, [](Env) {});
79
+ fn.Release();
80
+
81
+ ctx = new SimpleTestContext(42);
82
+ fn = ThreadSafeFunction::New(env,
83
+ emptyFunc,
84
+ Object::New(env),
85
+ "resStrObj",
86
+ 1,
87
+ 1,
88
+ ctx,
89
+ [](Env, SimpleTestContext*) {});
90
+ assert(fn.GetContext() == ctx);
91
+ delete ctx;
92
+ fn.Release();
93
+
94
+ fn = ThreadSafeFunction::New(
95
+ env, emptyFunc, Object::New(env), "resStrObj", 1, 1);
96
+ fn.Release();
97
+
98
+ ctx = new SimpleTestContext(42);
99
+ fn = ThreadSafeFunction::New(
100
+ env, emptyFunc, Object::New(env), "resStrObj", 1, 1, ctx);
101
+ assert(fn.GetContext() == ctx);
102
+ delete ctx;
103
+ fn.Release();
104
+
105
+ using FinalizerDataType = int;
106
+ FinalizerDataType* finalizerData = new int(42);
107
+ fn = ThreadSafeFunction::New(
108
+ env,
109
+ emptyFunc,
110
+ Object::New(env),
111
+ "resObject",
112
+ 1,
113
+ 1,
114
+ [](Env, FinalizerDataType* data) {
115
+ assert(*data == 42);
116
+ delete data;
117
+ },
118
+ finalizerData);
119
+ fn.Release();
120
+
121
+ ctx = new SimpleTestContext(42);
122
+ FinalizerDataType* finalizerDataB = new int(42);
123
+
124
+ fn = ThreadSafeFunction::New(
125
+ env,
126
+ emptyFunc,
127
+ Object::New(env),
128
+ "resObject",
129
+ 1,
130
+ 1,
131
+ ctx,
132
+ [](Env, FinalizerDataType* _data, SimpleTestContext* _ctx) {
133
+ assert(*_data == 42);
134
+ assert(_ctx->_val == 42);
135
+ delete _data;
136
+ delete _ctx;
137
+ },
138
+ finalizerDataB);
139
+ assert(fn.GetContext() == ctx);
140
+ fn.Release();
141
+ }
56
142
 
57
- } // namespace
143
+ } // namespace
58
144
 
59
145
  Object InitThreadSafeFunctionCtx(Env env) {
60
- return TSFNWrap::Init(env, Object::New(env));
146
+ Object exports = Object::New(env);
147
+ Function tsfnWrap = TSFNWrap::Init(env);
148
+ exports.Set("TSFNWrap", tsfnWrap);
149
+ exports.Set("AssertFnReturnCorrectCxt",
150
+ Function::New(env, AssertGetContextFromVariousTSOverloads));
151
+
152
+ return exports;
61
153
  }
62
154
 
63
155
  #endif
@@ -4,9 +4,10 @@ const assert = require('assert');
4
4
 
5
5
  module.exports = require('../common').runTest(test);
6
6
 
7
- async function test(binding) {
7
+ async function test (binding) {
8
8
  const ctx = { };
9
9
  const tsfn = new binding.threadsafe_function_ctx.TSFNWrap(ctx);
10
10
  assert(tsfn.getContext() === ctx);
11
11
  await tsfn.release();
12
+ binding.threadsafe_function_ctx.AssertFnReturnCorrectCxt();
12
13
  }