koffi 2.7.1 → 2.7.3

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 (73) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +2 -2
  3. package/build/koffi/darwin_arm64/koffi.node +0 -0
  4. package/build/koffi/darwin_x64/koffi.node +0 -0
  5. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  6. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  7. package/build/koffi/freebsd_x64/koffi.node +0 -0
  8. package/build/koffi/linux_arm32hf/koffi.node +0 -0
  9. package/build/koffi/linux_arm64/koffi.node +0 -0
  10. package/build/koffi/linux_ia32/koffi.node +0 -0
  11. package/build/koffi/linux_riscv64hf64/koffi.node +0 -0
  12. package/build/koffi/linux_x64/koffi.node +0 -0
  13. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  14. package/build/koffi/openbsd_x64/koffi.node +0 -0
  15. package/build/koffi/win32_arm64/koffi.node +0 -0
  16. package/build/koffi/win32_ia32/koffi.node +0 -0
  17. package/build/koffi/win32_x64/koffi.node +0 -0
  18. package/doc/misc.md +1 -1
  19. package/doc/unions.md +2 -2
  20. package/index.d.ts +2 -1
  21. package/index.js +23 -23
  22. package/indirect.js +23 -23
  23. package/package.json +2 -2
  24. package/src/core/libcc/brotli.cc +16 -24
  25. package/src/core/libcc/libcc.cc +63 -69
  26. package/src/core/libcc/libcc.hh +103 -110
  27. package/src/core/libcc/lz4.cc +18 -25
  28. package/src/core/libcc/miniz.cc +10 -18
  29. package/src/koffi/src/call.cc +1 -1
  30. package/src/koffi/src/util.cc +7 -13
  31. package/src/koffi/src/util.hh +9 -1
  32. package/vendor/node-addon-api/CHANGELOG.md +76 -0
  33. package/vendor/node-addon-api/LICENSE.md +2 -6
  34. package/vendor/node-addon-api/README.md +10 -9
  35. package/vendor/node-addon-api/benchmark/binding.gyp +4 -4
  36. package/vendor/node-addon-api/common.gypi +1 -2
  37. package/vendor/node-addon-api/doc/array.md +1 -1
  38. package/vendor/node-addon-api/doc/async_worker_variants.md +16 -16
  39. package/vendor/node-addon-api/doc/cmake-js.md +1 -1
  40. package/vendor/node-addon-api/doc/env.md +11 -0
  41. package/vendor/node-addon-api/doc/hierarchy.md +2 -0
  42. package/vendor/node-addon-api/doc/setup.md +53 -71
  43. package/vendor/node-addon-api/doc/syntax_error.md +66 -0
  44. package/vendor/node-addon-api/doc/value.md +2 -0
  45. package/vendor/node-addon-api/index.js +2 -1
  46. package/vendor/node-addon-api/napi-inl.h +68 -65
  47. package/vendor/node-addon-api/napi.h +15 -5
  48. package/vendor/node-addon-api/node_addon_api.gyp +32 -0
  49. package/vendor/node-addon-api/package.json +14 -3
  50. package/vendor/node-addon-api/test/addon.cc +7 -1
  51. package/vendor/node-addon-api/test/addon.js +5 -9
  52. package/vendor/node-addon-api/test/addon_data.cc +3 -3
  53. package/vendor/node-addon-api/test/addon_data.js +16 -38
  54. package/vendor/node-addon-api/test/bigint.cc +0 -1
  55. package/vendor/node-addon-api/test/binding.cc +12 -1
  56. package/vendor/node-addon-api/test/binding.gyp +10 -8
  57. package/vendor/node-addon-api/test/child_processes/addon.js +11 -0
  58. package/vendor/node-addon-api/test/child_processes/addon_data.js +24 -0
  59. package/vendor/node-addon-api/test/child_processes/objectwrap_function.js +22 -0
  60. package/vendor/node-addon-api/test/child_processes/threadsafe_function_exception.js +33 -0
  61. package/vendor/node-addon-api/test/child_processes/typed_threadsafe_function_exception.js +19 -0
  62. package/vendor/node-addon-api/test/common/index.js +57 -3
  63. package/vendor/node-addon-api/test/env_misc.cc +25 -0
  64. package/vendor/node-addon-api/test/env_misc.js +12 -0
  65. package/vendor/node-addon-api/test/error.cc +47 -0
  66. package/vendor/node-addon-api/test/error.js +16 -0
  67. package/vendor/node-addon-api/test/index.js +5 -0
  68. package/vendor/node-addon-api/test/objectwrap_function.cc +10 -12
  69. package/vendor/node-addon-api/test/objectwrap_function.js +4 -20
  70. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_exception.cc +50 -0
  71. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_exception.js +20 -0
  72. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_exception.cc +39 -0
  73. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_exception.js +13 -0
@@ -0,0 +1,22 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const testUtil = require('../testUtil');
5
+
6
+ module.exports = {
7
+ runTest: function (binding) {
8
+ return testUtil.runGCTests([
9
+ 'objectwrap function',
10
+ () => {
11
+ const { FunctionTest } = binding.objectwrap_function();
12
+ const newConstructed = new FunctionTest();
13
+ const functionConstructed = FunctionTest();
14
+ assert(newConstructed instanceof FunctionTest);
15
+ assert(functionConstructed instanceof FunctionTest);
16
+ assert.throws(() => (FunctionTest(true)), /an exception/);
17
+ },
18
+ // Do one gc before returning.
19
+ () => {}
20
+ ]);
21
+ }
22
+ };
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const common = require('../common');
5
+
6
+ module.exports = {
7
+ testCall: async binding => {
8
+ const { testCall } = binding.threadsafe_function_exception;
9
+
10
+ await new Promise(resolve => {
11
+ process.once('uncaughtException', common.mustCall(err => {
12
+ assert.strictEqual(err.message, 'test');
13
+ resolve();
14
+ }, 1));
15
+
16
+ testCall(common.mustCall(() => {
17
+ throw new Error('test');
18
+ }, 1));
19
+ });
20
+ },
21
+ testCallWithNativeCallback: async binding => {
22
+ const { testCallWithNativeCallback } = binding.threadsafe_function_exception;
23
+
24
+ await new Promise(resolve => {
25
+ process.once('uncaughtException', common.mustCall(err => {
26
+ assert.strictEqual(err.message, 'test-from-native');
27
+ resolve();
28
+ }, 1));
29
+
30
+ testCallWithNativeCallback();
31
+ });
32
+ }
33
+ };
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const common = require('../common');
5
+
6
+ module.exports = {
7
+ testCall: async binding => {
8
+ const { testCall } = binding.typed_threadsafe_function_exception;
9
+
10
+ await new Promise(resolve => {
11
+ process.once('uncaughtException', common.mustCall(err => {
12
+ assert.strictEqual(err.message, 'test-from-native');
13
+ resolve();
14
+ }, 1));
15
+
16
+ testCall();
17
+ });
18
+ }
19
+ };
@@ -3,6 +3,11 @@
3
3
  const assert = require('assert');
4
4
  const path = require('path');
5
5
  const { access } = require('node:fs/promises');
6
+ const { spawn } = require('child_process');
7
+ const { EOL } = require('os');
8
+ const readline = require('readline');
9
+
10
+ const escapeBackslashes = (pathString) => pathString.split('\\').join('\\\\');
6
11
 
7
12
  const noop = () => {};
8
13
 
@@ -26,7 +31,7 @@ function runCallChecks (exitCode) {
26
31
  context.name,
27
32
  context.messageSegment,
28
33
  context.actual);
29
- console.log(context.stack.split('\n').slice(2).join('\n'));
34
+ console.log(context.stack.split(EOL).slice(2).join(EOL));
30
35
  });
31
36
 
32
37
  if (failed.length) process.exit(1);
@@ -143,7 +148,7 @@ async function whichBuildType () {
143
148
  if (await checkBuildType(envBuildType)) {
144
149
  buildType = envBuildType;
145
150
  } else {
146
- throw new Error(`The ${envBuildType} build doesn't exists.`);
151
+ throw new Error(`The ${envBuildType} build doesn't exist.`);
147
152
  }
148
153
  } else {
149
154
  throw new Error('Invalid value for NODE_API_BUILD_CONFIG environment variable. It should be set to Release or Debug.');
@@ -164,7 +169,7 @@ exports.runTest = async function (test, buildType, buildPathRoot = process.env.B
164
169
  ].map(it => require.resolve(it));
165
170
 
166
171
  for (const item of bindings) {
167
- await Promise.resolve(test(require(item)))
172
+ await Promise.resolve(test(require(item), { bindingPath: item }))
168
173
  .finally(exports.mustCall());
169
174
  }
170
175
  };
@@ -190,3 +195,52 @@ exports.runTestWithBuildType = async function (test, buildType) {
190
195
  await Promise.resolve(test(buildType))
191
196
  .finally(exports.mustCall());
192
197
  };
198
+
199
+ // Some tests have to run in their own process, otherwise they would interfere
200
+ // with each other. Such tests export a factory function rather than the test
201
+ // itself so as to avoid automatic instantiation, and therefore interference,
202
+ // in the main process. Two examples are addon and addon_data, both of which
203
+ // use Napi::Env::SetInstanceData(). This helper function provides a common
204
+ // approach for running such tests.
205
+ exports.runTestInChildProcess = function ({ suite, testName, expectedStderr, execArgv }) {
206
+ return exports.runTestWithBindingPath((bindingName) => {
207
+ return new Promise((resolve) => {
208
+ bindingName = escapeBackslashes(bindingName);
209
+ // Test suites are assumed to be located here.
210
+ const suitePath = escapeBackslashes(path.join(__dirname, '..', 'child_processes', suite));
211
+ const child = spawn(process.execPath, [
212
+ '--expose-gc',
213
+ ...(execArgv ?? []),
214
+ '-e',
215
+ `require('${suitePath}').${testName}(require('${bindingName}'))`
216
+ ]);
217
+ const resultOfProcess = { stderr: [] };
218
+
219
+ // Capture the exit code and signal.
220
+ child.on('close', (code, signal) => resolve(Object.assign(resultOfProcess, { code, signal })));
221
+
222
+ // Capture the stderr as an array of lines.
223
+ readline
224
+ .createInterface({ input: child.stderr })
225
+ .on('line', (line) => {
226
+ resultOfProcess.stderr.push(line);
227
+ });
228
+ }).then(actual => {
229
+ // Back up the stderr in case the assertion fails.
230
+ const fullStderr = actual.stderr.map(item => `from child process: ${item}`);
231
+ const expected = { stderr: expectedStderr, code: 0, signal: null };
232
+
233
+ if (!expectedStderr) {
234
+ // If we don't care about stderr, delete it.
235
+ delete actual.stderr;
236
+ delete expected.stderr;
237
+ } else {
238
+ // Otherwise we only care about expected lines in the actual stderr, so
239
+ // filter out everything else.
240
+ actual.stderr = actual.stderr.filter(line => expectedStderr.includes(line));
241
+ }
242
+
243
+ assert.deepStrictEqual(actual, expected, `Assertion for child process test ${suite}.${testName} failed:${EOL}` + fullStderr.join(EOL));
244
+ });
245
+ });
246
+ };
@@ -0,0 +1,25 @@
1
+ #include "napi.h"
2
+ #include "test_helper.h"
3
+
4
+ #if (NAPI_VERSION > 8)
5
+
6
+ using namespace Napi;
7
+
8
+ namespace {
9
+
10
+ Value GetModuleFileName(const CallbackInfo& info) {
11
+ Env env = info.Env();
12
+ return String::New(env, env.GetModuleFileName());
13
+ }
14
+
15
+ } // end anonymous namespace
16
+
17
+ Object InitEnvMiscellaneous(Env env) {
18
+ Object exports = Object::New(env);
19
+
20
+ exports["get_module_file_name"] = Function::New(env, GetModuleFileName);
21
+
22
+ return exports;
23
+ }
24
+
25
+ #endif
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const { pathToFileURL } = require('url');
5
+
6
+ module.exports = require('./common').runTest(test);
7
+
8
+ function test (binding, { bindingPath } = {}) {
9
+ const path = binding.env_misc.get_module_file_name();
10
+ const bindingFileUrl = pathToFileURL(bindingPath).toString();
11
+ assert(bindingFileUrl === path);
12
+ }
@@ -153,6 +153,27 @@ void ThrowRangeError(const CallbackInfo& info) {
153
153
  throw RangeError::New(info.Env(), message);
154
154
  }
155
155
 
156
+ #if NAPI_VERSION > 8
157
+ void ThrowSyntaxErrorCStr(const CallbackInfo& info) {
158
+ std::string message = info[0].As<String>().Utf8Value();
159
+ ReleaseAndWaitForChildProcess(info, 1);
160
+ throw SyntaxError::New(info.Env(), message.c_str());
161
+ }
162
+
163
+ void ThrowSyntaxErrorCtor(const CallbackInfo& info) {
164
+ Napi::Value js_range_err = info[0];
165
+ ReleaseAndWaitForChildProcess(info, 1);
166
+ throw Napi::SyntaxError(info.Env(), js_range_err);
167
+ }
168
+
169
+ void ThrowSyntaxError(const CallbackInfo& info) {
170
+ std::string message = info[0].As<String>().Utf8Value();
171
+
172
+ ReleaseAndWaitForChildProcess(info, 1);
173
+ throw SyntaxError::New(info.Env(), message);
174
+ }
175
+ #endif // NAPI_VERSION > 8
176
+
156
177
  Value CatchError(const CallbackInfo& info) {
157
178
  Function thrower = info[0].As<Function>();
158
179
  try {
@@ -255,6 +276,27 @@ void ThrowEmptyRangeError(const CallbackInfo& info) {
255
276
  RangeError().ThrowAsJavaScriptException();
256
277
  }
257
278
 
279
+ #if NAPI_VERSION > 8
280
+ void ThrowSyntaxError(const CallbackInfo& info) {
281
+ std::string message = info[0].As<String>().Utf8Value();
282
+
283
+ ReleaseAndWaitForChildProcess(info, 1);
284
+ SyntaxError::New(info.Env(), message).ThrowAsJavaScriptException();
285
+ }
286
+
287
+ void ThrowSyntaxErrorCtor(const CallbackInfo& info) {
288
+ Napi::Value js_range_err = info[0];
289
+ ReleaseAndWaitForChildProcess(info, 1);
290
+ SyntaxError(info.Env(), js_range_err).ThrowAsJavaScriptException();
291
+ }
292
+
293
+ void ThrowSyntaxErrorCStr(const CallbackInfo& info) {
294
+ std::string message = info[0].As<String>().Utf8Value();
295
+ ReleaseAndWaitForChildProcess(info, 1);
296
+ SyntaxError::New(info.Env(), message.c_str()).ThrowAsJavaScriptException();
297
+ }
298
+ #endif // NAPI_VERSION > 8
299
+
258
300
  Value CatchError(const CallbackInfo& info) {
259
301
  Function thrower = info[0].As<Function>();
260
302
  thrower({});
@@ -372,6 +414,11 @@ Object InitError(Env env) {
372
414
  exports["throwRangeErrorCtor"] = Function::New(env, ThrowRangeErrorCtor);
373
415
  exports["throwRangeErrorCStr"] = Function::New(env, ThrowRangeErrorCStr);
374
416
  exports["throwEmptyRangeError"] = Function::New(env, ThrowEmptyRangeError);
417
+ #if NAPI_VERSION > 8
418
+ exports["throwSyntaxError"] = Function::New(env, ThrowSyntaxError);
419
+ exports["throwSyntaxErrorCtor"] = Function::New(env, ThrowSyntaxErrorCtor);
420
+ exports["throwSyntaxErrorCStr"] = Function::New(env, ThrowSyntaxErrorCStr);
421
+ #endif // NAPI_VERSION > 8
375
422
  exports["catchError"] = Function::New(env, CatchError);
376
423
  exports["catchErrorMessage"] = Function::New(env, CatchErrorMessage);
377
424
  exports["doNotCatch"] = Function::New(env, DoNotCatch);
@@ -9,6 +9,8 @@ if (process.argv[2] === 'fatal') {
9
9
 
10
10
  module.exports = require('./common').runTestWithBindingPath(test);
11
11
 
12
+ const napiVersion = Number(process.env.NAPI_VERSION ?? process.versions.napi);
13
+
12
14
  function test (bindingPath) {
13
15
  const binding = require(bindingPath);
14
16
  binding.error.testErrorCopySemantics();
@@ -46,6 +48,20 @@ function test (bindingPath) {
46
48
  return err instanceof RangeError && err.message === 'rangeTypeError';
47
49
  });
48
50
 
51
+ if (napiVersion > 8) {
52
+ assert.throws(() => binding.error.throwSyntaxErrorCStr('test'), function (err) {
53
+ return err instanceof SyntaxError && err.message === 'test';
54
+ });
55
+
56
+ assert.throws(() => binding.error.throwSyntaxError('test'), function (err) {
57
+ return err instanceof SyntaxError && err.message === 'test';
58
+ });
59
+
60
+ assert.throws(() => binding.error.throwSyntaxErrorCtor(new SyntaxError('syntaxTypeError')), function (err) {
61
+ return err instanceof SyntaxError && err.message === 'syntaxTypeError';
62
+ });
63
+ }
64
+
49
65
  assert.throws(
50
66
  () => binding.error.doNotCatch(
51
67
  () => {
@@ -60,6 +60,7 @@ function loadTestModules (currentDirectory = __dirname, pre = '') {
60
60
  file === 'binding.gyp' ||
61
61
  file === 'build' ||
62
62
  file === 'common' ||
63
+ file === 'child_processes' ||
63
64
  file === 'napi_child.js' ||
64
65
  file === 'testUtil.js' ||
65
66
  file === 'thunking_manual.cc' ||
@@ -137,6 +138,10 @@ if (napiVersion < 8 && !filterConditionsProvided) {
137
138
  testModules.splice(testModules.indexOf('type_taggable'), 1);
138
139
  }
139
140
 
141
+ if (napiVersion < 9 && !filterConditionsProvided) {
142
+ testModules.splice(testModules.indexOf('env_misc'), 1);
143
+ }
144
+
140
145
  (async function () {
141
146
  console.log(`Testing with Node-API Version '${napiVersion}'.`);
142
147
 
@@ -18,28 +18,26 @@ class FunctionTest : public Napi::ObjectWrap<FunctionTest> {
18
18
  return MaybeUnwrap(GetConstructor(info.Env()).New(args));
19
19
  }
20
20
 
21
- // Constructor-per-env map in a static member because env.SetInstanceData()
22
- // would interfere with Napi::Addon<T>
23
- static std::unordered_map<napi_env, Napi::FunctionReference> constructors;
24
-
25
21
  static void Initialize(Napi::Env env, Napi::Object exports) {
26
22
  const char* name = "FunctionTest";
27
23
  Napi::Function func = DefineClass(env, name, {});
28
- constructors[env] = Napi::Persistent(func);
29
- env.AddCleanupHook([env] { constructors.erase(env); });
24
+ Napi::FunctionReference* ctor = new Napi::FunctionReference();
25
+ *ctor = Napi::Persistent(func);
26
+ env.SetInstanceData(ctor);
30
27
  exports.Set(name, func);
31
28
  }
32
29
 
33
30
  static Napi::Function GetConstructor(Napi::Env env) {
34
- return constructors[env].Value();
31
+ return env.GetInstanceData<Napi::FunctionReference>()->Value();
35
32
  }
36
33
  };
37
34
 
38
- std::unordered_map<napi_env, Napi::FunctionReference>
39
- FunctionTest::constructors;
35
+ Napi::Value ObjectWrapFunctionFactory(const Napi::CallbackInfo& info) {
36
+ Napi::Object exports = Napi::Object::New(info.Env());
37
+ FunctionTest::Initialize(info.Env(), exports);
38
+ return exports;
39
+ }
40
40
 
41
41
  Napi::Object InitObjectWrapFunction(Napi::Env env) {
42
- Napi::Object exports = Napi::Object::New(env);
43
- FunctionTest::Initialize(env, exports);
44
- return exports;
42
+ return Napi::Function::New<ObjectWrapFunctionFactory>(env, "FunctionFactory");
45
43
  }
@@ -1,22 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const assert = require('assert');
4
- const testUtil = require('./testUtil');
5
-
6
- function test (binding) {
7
- return testUtil.runGCTests([
8
- 'objectwrap function',
9
- () => {
10
- const { FunctionTest } = binding.objectwrap_function;
11
- const newConstructed = new FunctionTest();
12
- const functionConstructed = FunctionTest();
13
- assert(newConstructed instanceof FunctionTest);
14
- assert(functionConstructed instanceof FunctionTest);
15
- assert.throws(() => (FunctionTest(true)), /an exception/);
16
- },
17
- // Do on gc before returning.
18
- () => {}
19
- ]);
20
- }
21
-
22
- module.exports = require('./common').runTest(test);
3
+ module.exports = require('./common').runTestInChildProcess({
4
+ suite: 'objectwrap_function',
5
+ testName: 'runTest'
6
+ });
@@ -0,0 +1,50 @@
1
+ #include <cstdlib>
2
+ #include "napi.h"
3
+ #include "test_helper.h"
4
+
5
+ #if (NAPI_VERSION > 3)
6
+
7
+ using namespace Napi;
8
+
9
+ namespace {
10
+
11
+ void CallJS(napi_env env, napi_value /* callback */, void* /*data*/) {
12
+ Napi::Error error = Napi::Error::New(env, "test-from-native");
13
+ NAPI_THROW_VOID(error);
14
+ }
15
+
16
+ void TestCall(const CallbackInfo& info) {
17
+ Napi::Env env = info.Env();
18
+
19
+ ThreadSafeFunction wrapped =
20
+ ThreadSafeFunction::New(env,
21
+ info[0].As<Napi::Function>(),
22
+ Object::New(env),
23
+ String::New(env, "Test"),
24
+ 0,
25
+ 1);
26
+ wrapped.BlockingCall(static_cast<void*>(nullptr));
27
+ wrapped.Release();
28
+ }
29
+
30
+ void TestCallWithNativeCallback(const CallbackInfo& info) {
31
+ Napi::Env env = info.Env();
32
+
33
+ ThreadSafeFunction wrapped = ThreadSafeFunction::New(
34
+ env, Napi::Function(), Object::New(env), String::New(env, "Test"), 0, 1);
35
+ wrapped.BlockingCall(static_cast<void*>(nullptr), CallJS);
36
+ wrapped.Release();
37
+ }
38
+
39
+ } // namespace
40
+
41
+ Object InitThreadSafeFunctionException(Env env) {
42
+ Object exports = Object::New(env);
43
+ exports["testCall"] = Function::New(env, TestCall);
44
+ exports["testCallWithNativeCallback"] =
45
+ Function::New(env, TestCallWithNativeCallback);
46
+
47
+ return exports;
48
+ }
49
+
50
+ #endif
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ const common = require('../common');
4
+
5
+ module.exports = common.runTest(test);
6
+
7
+ const execArgv = ['--force-node-api-uncaught-exceptions-policy=true'];
8
+ async function test () {
9
+ await common.runTestInChildProcess({
10
+ suite: 'threadsafe_function_exception',
11
+ testName: 'testCall',
12
+ execArgv
13
+ });
14
+
15
+ await common.runTestInChildProcess({
16
+ suite: 'threadsafe_function_exception',
17
+ testName: 'testCallWithNativeCallback',
18
+ execArgv
19
+ });
20
+ }
@@ -0,0 +1,39 @@
1
+ #include <cstdlib>
2
+ #include "napi.h"
3
+ #include "test_helper.h"
4
+
5
+ #if (NAPI_VERSION > 3)
6
+
7
+ using namespace Napi;
8
+
9
+ namespace {
10
+
11
+ void CallJS(Napi::Env env,
12
+ Napi::Function /* callback */,
13
+ std::nullptr_t* /* context */,
14
+ void* /*data*/) {
15
+ Napi::Error error = Napi::Error::New(env, "test-from-native");
16
+ NAPI_THROW_VOID(error);
17
+ }
18
+
19
+ using TSFN = TypedThreadSafeFunction<std::nullptr_t, void, CallJS>;
20
+
21
+ void TestCall(const CallbackInfo& info) {
22
+ Napi::Env env = info.Env();
23
+
24
+ TSFN wrapped = TSFN::New(
25
+ env, Napi::Function(), Object::New(env), String::New(env, "Test"), 0, 1);
26
+ wrapped.BlockingCall(static_cast<void*>(nullptr));
27
+ wrapped.Release();
28
+ }
29
+
30
+ } // namespace
31
+
32
+ Object InitTypedThreadSafeFunctionException(Env env) {
33
+ Object exports = Object::New(env);
34
+ exports["testCall"] = Function::New(env, TestCall);
35
+
36
+ return exports;
37
+ }
38
+
39
+ #endif
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ const common = require('../common');
4
+
5
+ module.exports = common.runTest(test);
6
+
7
+ async function test () {
8
+ await common.runTestInChildProcess({
9
+ suite: 'typed_threadsafe_function_exception',
10
+ testName: 'testCall',
11
+ execArgv: ['--force-node-api-uncaught-exceptions-policy=true']
12
+ });
13
+ }