koffi 0.9.30 → 0.9.33

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 (60) hide show
  1. package/package.json +1 -1
  2. package/src/call.hh +2 -1
  3. package/src/call_arm32.cc +27 -15
  4. package/src/call_arm64.cc +4 -9
  5. package/src/call_x64_sysv.cc +4 -9
  6. package/src/call_x64_sysv_fwd.S +13 -3
  7. package/src/call_x64_win.cc +4 -9
  8. package/src/call_x86.cc +18 -16
  9. package/src/ffi.cc +93 -46
  10. package/src/ffi.hh +11 -6
  11. package/src/util.cc +35 -1
  12. package/src/util.hh +2 -0
  13. package/test/tests/misc.c +62 -1
  14. package/test/tests/misc.js +49 -1
  15. package/vendor/node-addon-api/CHANGELOG.md +57 -0
  16. package/vendor/node-addon-api/README.md +3 -3
  17. package/vendor/node-addon-api/doc/array_buffer.md +2 -2
  18. package/vendor/node-addon-api/doc/buffer.md +2 -2
  19. package/vendor/node-addon-api/doc/class_property_descriptor.md +13 -5
  20. package/vendor/node-addon-api/doc/env.md +5 -5
  21. package/vendor/node-addon-api/doc/object.md +12 -33
  22. package/vendor/node-addon-api/doc/object_reference.md +1 -1
  23. package/vendor/node-addon-api/doc/object_wrap.md +27 -0
  24. package/vendor/node-addon-api/doc/reference.md +2 -2
  25. package/vendor/node-addon-api/doc/threadsafe_function.md +3 -3
  26. package/vendor/node-addon-api/doc/typed_threadsafe_function.md +2 -2
  27. package/vendor/node-addon-api/napi-inl.h +111 -61
  28. package/vendor/node-addon-api/napi.h +79 -59
  29. package/vendor/node-addon-api/package.json +22 -6
  30. package/vendor/node-addon-api/test/async_context.cc +15 -0
  31. package/vendor/node-addon-api/test/async_context.js +69 -33
  32. package/vendor/node-addon-api/test/binding.cc +2 -0
  33. package/vendor/node-addon-api/test/binding.gyp +7 -0
  34. package/vendor/node-addon-api/test/common/index.js +23 -22
  35. package/vendor/node-addon-api/test/common/test_helper.h +10 -0
  36. package/vendor/node-addon-api/test/error_terminating_environment.js +1 -0
  37. package/vendor/node-addon-api/test/function.cc +29 -0
  38. package/vendor/node-addon-api/test/function.js +35 -23
  39. package/vendor/node-addon-api/test/index.js +40 -17
  40. package/vendor/node-addon-api/test/object/object.cc +2 -0
  41. package/vendor/node-addon-api/test/object/set_property.cc +8 -0
  42. package/vendor/node-addon-api/test/object/set_property.js +6 -5
  43. package/vendor/node-addon-api/test/object/subscript_operator.cc +19 -3
  44. package/vendor/node-addon-api/test/objectwrap_function.cc +45 -0
  45. package/vendor/node-addon-api/test/objectwrap_function.js +22 -0
  46. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_sum.cc +1 -1
  47. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ctx.js +2 -2
  48. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_sum.cc +1 -1
  49. package/vendor/node-addon-api/tools/clang-format.js +4 -1
  50. package/vendor/node-addon-api/unit-test/README.md +28 -0
  51. package/vendor/node-addon-api/unit-test/binding-file-template.js +39 -0
  52. package/vendor/node-addon-api/unit-test/binding.gyp +72 -0
  53. package/vendor/node-addon-api/unit-test/exceptions.js +32 -0
  54. package/vendor/node-addon-api/unit-test/generate-binding-cc.js +61 -0
  55. package/vendor/node-addon-api/unit-test/injectTestParams.js +101 -0
  56. package/vendor/node-addon-api/unit-test/listOfTestModules.js +88 -0
  57. package/vendor/node-addon-api/unit-test/matchModules.js +65 -0
  58. package/vendor/node-addon-api/unit-test/setup.js +13 -0
  59. package/vendor/node-addon-api/unit-test/spawnTask.js +26 -0
  60. package/vendor/node-addon-api/unit-test/test.js +30 -0
@@ -7,10 +7,10 @@ const noop = () => {};
7
7
 
8
8
  const mustCallChecks = [];
9
9
 
10
- function runCallChecks(exitCode) {
10
+ function runCallChecks (exitCode) {
11
11
  if (exitCode !== 0) return;
12
12
 
13
- const failed = mustCallChecks.filter(function(context) {
13
+ const failed = mustCallChecks.filter(function (context) {
14
14
  if ('minimum' in context) {
15
15
  context.messageSegment = `at least ${context.minimum}`;
16
16
  return context.actual < context.minimum;
@@ -20,25 +20,25 @@ function runCallChecks(exitCode) {
20
20
  }
21
21
  });
22
22
 
23
- failed.forEach(function(context) {
23
+ failed.forEach(function (context) {
24
24
  console.log('Mismatched %s function calls. Expected %s, actual %d.',
25
- context.name,
26
- context.messageSegment,
27
- context.actual);
25
+ context.name,
26
+ context.messageSegment,
27
+ context.actual);
28
28
  console.log(context.stack.split('\n').slice(2).join('\n'));
29
29
  });
30
30
 
31
31
  if (failed.length) process.exit(1);
32
32
  }
33
33
 
34
- exports.mustCall = function(fn, exact) {
34
+ exports.mustCall = function (fn, exact) {
35
35
  return _mustCallInner(fn, exact, 'exact');
36
36
  };
37
- exports.mustCallAtLeast = function(fn, minimum) {
37
+ exports.mustCallAtLeast = function (fn, minimum) {
38
38
  return _mustCallInner(fn, minimum, 'minimum');
39
39
  };
40
40
 
41
- function _mustCallInner(fn, criteria, field) {
41
+ function _mustCallInner (fn, criteria, field) {
42
42
  if (typeof fn === 'number') {
43
43
  criteria = fn;
44
44
  fn = noop;
@@ -49,8 +49,7 @@ function _mustCallInner(fn, criteria, field) {
49
49
  criteria = 1;
50
50
  }
51
51
 
52
- if (typeof criteria !== 'number')
53
- throw new TypeError(`Invalid ${field} value: ${criteria}`);
52
+ if (typeof criteria !== 'number') { throw new TypeError(`Invalid ${field} value: ${criteria}`); }
54
53
 
55
54
  const context = {
56
55
  [field]: criteria,
@@ -64,50 +63,52 @@ function _mustCallInner(fn, criteria, field) {
64
63
 
65
64
  mustCallChecks.push(context);
66
65
 
67
- return function() {
66
+ return function () {
68
67
  context.actual++;
69
68
  return fn.apply(this, arguments);
70
69
  };
71
70
  }
72
71
 
73
- exports.mustNotCall = function(msg) {
74
- return function mustNotCall() {
72
+ exports.mustNotCall = function (msg) {
73
+ return function mustNotCall () {
75
74
  assert.fail(msg || 'function should not have been called');
76
75
  };
77
76
  };
78
77
 
79
- exports.runTest = async function(test, buildType, buildPathRoot = process.env.REL_BUILD_PATH || '') {
78
+ exports.runTest = async function (test, buildType, buildPathRoot = process.env.BUILD_PATH || '') {
80
79
  buildType = buildType || process.config.target_defaults.default_configuration || 'Release';
81
80
 
82
81
  const bindings = [
83
82
  path.join(buildPathRoot, `../build/${buildType}/binding.node`),
84
83
  path.join(buildPathRoot, `../build/${buildType}/binding_noexcept.node`),
85
84
  path.join(buildPathRoot, `../build/${buildType}/binding_noexcept_maybe.node`),
85
+ path.join(buildPathRoot, `../build/${buildType}/binding_custom_namespace.node`)
86
86
  ].map(it => require.resolve(it));
87
87
 
88
88
  for (const item of bindings) {
89
89
  await Promise.resolve(test(require(item)))
90
90
  .finally(exports.mustCall());
91
91
  }
92
- }
92
+ };
93
93
 
94
- exports.runTestWithBindingPath = async function(test, buildType, buildPathRoot = process.env.REL_BUILD_PATH || '') {
94
+ exports.runTestWithBindingPath = async function (test, buildType, buildPathRoot = process.env.BUILD_PATH || '') {
95
95
  buildType = buildType || process.config.target_defaults.default_configuration || 'Release';
96
96
 
97
97
  const bindings = [
98
98
  path.join(buildPathRoot, `../build/${buildType}/binding.node`),
99
99
  path.join(buildPathRoot, `../build/${buildType}/binding_noexcept.node`),
100
100
  path.join(buildPathRoot, `../build/${buildType}/binding_noexcept_maybe.node`),
101
+ path.join(buildPathRoot, `../build/${buildType}/binding_custom_namespace.node`)
101
102
  ].map(it => require.resolve(it));
102
103
 
103
104
  for (const item of bindings) {
104
105
  await test(item);
105
106
  }
106
- }
107
+ };
107
108
 
108
- exports.runTestWithBuildType = async function(test, buildType) {
109
+ exports.runTestWithBuildType = async function (test, buildType) {
109
110
  buildType = buildType || process.config.target_defaults.default_configuration || 'Release';
110
111
 
111
- await Promise.resolve(test(buildType))
112
- .finally(exports.mustCall());
113
- }
112
+ await Promise.resolve(test(buildType))
113
+ .finally(exports.mustCall());
114
+ };
@@ -3,6 +3,12 @@
3
3
 
4
4
  namespace Napi {
5
5
 
6
+ // Needs this here since the MaybeUnwrap() functions need to be in the
7
+ // same namespace as their arguments for C++ argument-dependent lookup
8
+ #ifdef NAPI_CPP_CUSTOM_NAMESPACE
9
+ namespace NAPI_CPP_CUSTOM_NAMESPACE {
10
+ #endif
11
+
6
12
  // Use this when a variable or parameter is unused in order to explicitly
7
13
  // silence a compiler warning about that.
8
14
  template <typename T>
@@ -58,4 +64,8 @@ inline bool MaybeUnwrapTo(MaybeOrValue<T> maybe, T* out) {
58
64
  #endif
59
65
  }
60
66
 
67
+ #ifdef NAPI_CPP_CUSTOM_NAMESPACE
68
+ } // namespace NAPI_CPP_CUSTOM_NAMESPACE
69
+ #endif
70
+
61
71
  } // namespace Napi
@@ -70,6 +70,7 @@ test(`./build/${buildType}/binding.node`, true);
70
70
  test(`./build/${buildType}/binding_noexcept.node`, true);
71
71
  test(`./build/${buildType}/binding_swallowexcept.node`, false);
72
72
  test(`./build/${buildType}/binding_swallowexcept_noexcept.node`, false);
73
+ test(`./build/${buildType}/binding_custom_namespace.node`, true);
73
74
 
74
75
  function test(bindingPath, process_should_abort) {
75
76
  const number_of_test_cases = 5;
@@ -69,6 +69,16 @@ Value CallWithVector(const CallbackInfo& info) {
69
69
  return MaybeUnwrap(func.Call(args));
70
70
  }
71
71
 
72
+ Value CallWithVectorUsingCppWrapper(const CallbackInfo& info) {
73
+ Function func = info[0].As<Function>();
74
+ std::vector<Value> args;
75
+ args.reserve(3);
76
+ args.push_back(info[1]);
77
+ args.push_back(info[2]);
78
+ args.push_back(info[3]);
79
+ return MaybeUnwrap(func.Call(args));
80
+ }
81
+
72
82
  Value CallWithCStyleArray(const CallbackInfo& info) {
73
83
  Function func = info[0].As<Function>();
74
84
  std::vector<napi_value> args;
@@ -108,6 +118,17 @@ Value CallWithReceiverAndVector(const CallbackInfo& info) {
108
118
  return MaybeUnwrap(func.Call(receiver, args));
109
119
  }
110
120
 
121
+ Value CallWithReceiverAndVectorUsingCppWrapper(const CallbackInfo& info) {
122
+ Function func = info[0].As<Function>();
123
+ Value receiver = info[1];
124
+ std::vector<Value> args;
125
+ args.reserve(3);
126
+ args.push_back(info[2]);
127
+ args.push_back(info[3]);
128
+ args.push_back(info[4]);
129
+ return MaybeUnwrap(func.Call(receiver, args));
130
+ }
131
+
111
132
  Value CallWithInvalidReceiver(const CallbackInfo& info) {
112
133
  Function func = info[0].As<Function>();
113
134
  return MaybeUnwrapOr(func.Call(Value(), std::initializer_list<napi_value>{}),
@@ -213,11 +234,15 @@ Object InitFunction(Env env) {
213
234
  Function::New(env, ValueCallbackWithData, nullptr, &testData);
214
235
  exports["callWithArgs"] = Function::New(env, CallWithArgs);
215
236
  exports["callWithVector"] = Function::New(env, CallWithVector);
237
+ exports["callWithVectorUsingCppWrapper"] =
238
+ Function::New(env, CallWithVectorUsingCppWrapper);
216
239
  exports["callWithCStyleArray"] = Function::New(env, CallWithCStyleArray);
217
240
  exports["callWithReceiverAndCStyleArray"] =
218
241
  Function::New(env, CallWithReceiverAndCStyleArray);
219
242
  exports["callWithReceiverAndArgs"] = Function::New(env, CallWithReceiverAndArgs);
220
243
  exports["callWithReceiverAndVector"] = Function::New(env, CallWithReceiverAndVector);
244
+ exports["callWithReceiverAndVectorUsingCppWrapper"] =
245
+ Function::New(env, CallWithReceiverAndVectorUsingCppWrapper);
221
246
  exports["callWithInvalidReceiver"] = Function::New(env, CallWithInvalidReceiver);
222
247
  exports["callConstructorWithArgs"] = Function::New(env, CallConstructorWithArgs);
223
248
  exports["callConstructorWithVector"] = Function::New(env, CallConstructorWithVector);
@@ -246,6 +271,8 @@ Object InitFunction(Env env) {
246
271
  Function::New<ValueCallbackWithData>(env, nullptr, &testData);
247
272
  exports["callWithArgs"] = Function::New<CallWithArgs>(env);
248
273
  exports["callWithVector"] = Function::New<CallWithVector>(env);
274
+ exports["callWithVectorUsingCppWrapper"] =
275
+ Function::New<CallWithVectorUsingCppWrapper>(env);
249
276
  exports["callWithCStyleArray"] = Function::New<CallWithCStyleArray>(env);
250
277
  exports["callWithReceiverAndCStyleArray"] =
251
278
  Function::New<CallWithReceiverAndCStyleArray>(env);
@@ -253,6 +280,8 @@ Object InitFunction(Env env) {
253
280
  Function::New<CallWithReceiverAndArgs>(env);
254
281
  exports["callWithReceiverAndVector"] =
255
282
  Function::New<CallWithReceiverAndVector>(env);
283
+ exports["callWithReceiverAndVectorUsingCppWrapper"] =
284
+ Function::New<CallWithReceiverAndVectorUsingCppWrapper>(env);
256
285
  exports["callWithInvalidReceiver"] =
257
286
  Function::New<CallWithInvalidReceiver>(env);
258
287
  exports["callConstructorWithArgs"] =
@@ -8,71 +8,81 @@ module.exports = require('./common').runTest(binding => {
8
8
  testLambda(binding.function.lambda);
9
9
  });
10
10
 
11
- function test(binding) {
11
+ function test (binding) {
12
12
  assert.strictEqual(binding.emptyConstructor(true), true);
13
13
  assert.strictEqual(binding.emptyConstructor(false), false);
14
14
 
15
15
  let obj = {};
16
16
  assert.deepStrictEqual(binding.voidCallback(obj), undefined);
17
- assert.deepStrictEqual(obj, { "foo": "bar" });
17
+ assert.deepStrictEqual(obj, { foo: 'bar' });
18
18
 
19
- assert.deepStrictEqual(binding.valueCallback(), { "foo": "bar" });
19
+ assert.deepStrictEqual(binding.valueCallback(), { foo: 'bar' });
20
20
 
21
21
  let args = null;
22
22
  let ret = null;
23
23
  let receiver = null;
24
- function testFunction() {
24
+ function testFunction () {
25
25
  receiver = this;
26
26
  args = [].slice.call(arguments);
27
27
  return ret;
28
28
  }
29
- function testConstructor() {
29
+ function testConstructor () {
30
30
  args = [].slice.call(arguments);
31
31
  }
32
32
 
33
- function makeCallbackTestFunction(receiver, expectedOne, expectedTwo, expectedThree) {
34
- return function callback(one, two, three) {
33
+ function makeCallbackTestFunction (receiver, expectedOne, expectedTwo, expectedThree) {
34
+ return function callback (one, two, three) {
35
35
  assert.strictEqual(this, receiver);
36
36
  assert.strictEqual(one, expectedOne);
37
37
  assert.strictEqual(two, expectedTwo);
38
38
  assert.strictEqual(three, expectedThree);
39
- }
39
+ };
40
40
  }
41
41
 
42
42
  ret = 4;
43
43
  assert.strictEqual(binding.callWithArgs(testFunction, 1, 2, 3), 4);
44
44
  assert.strictEqual(receiver, undefined);
45
- assert.deepStrictEqual(args, [ 1, 2, 3 ]);
45
+ assert.deepStrictEqual(args, [1, 2, 3]);
46
46
 
47
47
  ret = 5;
48
48
  assert.strictEqual(binding.callWithVector(testFunction, 2, 3, 4), 5);
49
49
  assert.strictEqual(receiver, undefined);
50
- assert.deepStrictEqual(args, [ 2, 3, 4 ]);
50
+ assert.deepStrictEqual(args, [2, 3, 4]);
51
+
52
+ ret = 5;
53
+ assert.strictEqual(binding.callWithVectorUsingCppWrapper(testFunction, 2, 3, 4), 5);
54
+ assert.strictEqual(receiver, undefined);
55
+ assert.deepStrictEqual(args, [2, 3, 4]);
51
56
 
52
57
  ret = 6;
53
58
  assert.strictEqual(binding.callWithReceiverAndArgs(testFunction, obj, 3, 4, 5), 6);
54
59
  assert.deepStrictEqual(receiver, obj);
55
- assert.deepStrictEqual(args, [ 3, 4, 5 ]);
60
+ assert.deepStrictEqual(args, [3, 4, 5]);
56
61
 
57
62
  ret = 7;
58
63
  assert.strictEqual(binding.callWithReceiverAndVector(testFunction, obj, 4, 5, 6), 7);
59
64
  assert.deepStrictEqual(receiver, obj);
60
- assert.deepStrictEqual(args, [ 4, 5, 6 ]);
65
+ assert.deepStrictEqual(args, [4, 5, 6]);
66
+
67
+ ret = 7;
68
+ assert.strictEqual(binding.callWithReceiverAndVectorUsingCppWrapper(testFunction, obj, 4, 5, 6), 7);
69
+ assert.deepStrictEqual(receiver, obj);
70
+ assert.deepStrictEqual(args, [4, 5, 6]);
61
71
 
62
72
  ret = 8;
63
73
  assert.strictEqual(binding.callWithCStyleArray(testFunction, 5, 6, 7), ret);
64
74
  assert.deepStrictEqual(receiver, undefined);
65
- assert.deepStrictEqual(args, [ 5, 6, 7 ]);
75
+ assert.deepStrictEqual(args, [5, 6, 7]);
66
76
 
67
77
  ret = 9;
68
78
  assert.strictEqual(binding.callWithReceiverAndCStyleArray(testFunction, obj, 6, 7, 8), ret);
69
79
  assert.deepStrictEqual(receiver, obj);
70
- assert.deepStrictEqual(args, [ 6, 7, 8 ]);
80
+ assert.deepStrictEqual(args, [6, 7, 8]);
71
81
 
72
82
  ret = 10;
73
83
  assert.strictEqual(binding.callWithFunctionOperator(testFunction, 7, 8, 9), ret);
74
84
  assert.strictEqual(receiver, undefined);
75
- assert.deepStrictEqual(args, [ 7, 8, 9 ]);
85
+ assert.deepStrictEqual(args, [7, 8, 9]);
76
86
 
77
87
  assert.throws(() => {
78
88
  binding.callWithInvalidReceiver();
@@ -80,33 +90,35 @@ function test(binding) {
80
90
 
81
91
  obj = binding.callConstructorWithArgs(testConstructor, 5, 6, 7);
82
92
  assert(obj instanceof testConstructor);
83
- assert.deepStrictEqual(args, [ 5, 6, 7 ]);
93
+ assert.deepStrictEqual(args, [5, 6, 7]);
84
94
 
85
95
  obj = binding.callConstructorWithVector(testConstructor, 6, 7, 8);
86
96
  assert(obj instanceof testConstructor);
87
- assert.deepStrictEqual(args, [ 6, 7, 8 ]);
97
+ assert.deepStrictEqual(args, [6, 7, 8]);
88
98
 
89
99
  obj = binding.callConstructorWithCStyleArray(testConstructor, 7, 8, 9);
90
100
  assert(obj instanceof testConstructor);
91
- assert.deepStrictEqual(args, [ 7, 8, 9 ]);
101
+ assert.deepStrictEqual(args, [7, 8, 9]);
92
102
 
93
103
  obj = {};
94
104
  assert.deepStrictEqual(binding.voidCallbackWithData(obj), undefined);
95
- assert.deepStrictEqual(obj, { "foo": "bar", "data": 1 });
105
+ assert.deepStrictEqual(obj, { foo: 'bar', data: 1 });
96
106
 
97
- assert.deepStrictEqual(binding.valueCallbackWithData(), { "foo": "bar", "data": 1 });
107
+ assert.deepStrictEqual(binding.valueCallbackWithData(), { foo: 'bar', data: 1 });
98
108
 
99
109
  assert.strictEqual(binding.voidCallback.name, 'voidCallback');
100
110
  assert.strictEqual(binding.valueCallback.name, 'valueCallback');
101
111
 
102
- let testConstructCall = undefined;
112
+ let testConstructCall;
103
113
  binding.isConstructCall((result) => { testConstructCall = result; });
104
114
  assert.ok(!testConstructCall);
115
+ /* eslint-disable no-new, new-cap */
105
116
  new binding.isConstructCall((result) => { testConstructCall = result; });
117
+ /* eslint-enable no-new, new-cap */
106
118
  assert.ok(testConstructCall);
107
119
 
108
120
  obj = {};
109
- binding.makeCallbackWithArgs(makeCallbackTestFunction(obj, "1", "2", "3"), obj, "1", "2", "3");
121
+ binding.makeCallbackWithArgs(makeCallbackTestFunction(obj, '1', '2', '3'), obj, '1', '2', '3');
110
122
  binding.makeCallbackWithVector(makeCallbackTestFunction(obj, 4, 5, 6), obj, 4, 5, 6);
111
123
  binding.makeCallbackWithCStyleArray(makeCallbackTestFunction(obj, 7, 8, 9), obj, 7, 8, 9);
112
124
  assert.throws(() => {
@@ -114,7 +126,7 @@ function test(binding) {
114
126
  });
115
127
  }
116
128
 
117
- function testLambda(binding) {
129
+ function testLambda (binding) {
118
130
  assert.ok(binding.lambdaWithNoCapture());
119
131
  assert.ok(binding.lambdaWithCapture());
120
132
  assert.ok(binding.lambdaWithMoveOnlyCapture());
@@ -4,7 +4,7 @@ const majorNodeVersion = process.versions.node.split('.')[0];
4
4
 
5
5
  if (typeof global.gc !== 'function') {
6
6
  // Construct the correct (version-dependent) command-line args.
7
- let args = ['--expose-gc'];
7
+ const args = ['--expose-gc'];
8
8
  const majorV8Version = process.versions.v8.split('.')[0];
9
9
  if (majorV8Version < 9) {
10
10
  args.push('--no-concurrent-array-buffer-freeing');
@@ -15,7 +15,7 @@ if (typeof global.gc !== 'function') {
15
15
  args.push(__filename);
16
16
 
17
17
  const child = require('./napi_child').spawnSync(process.argv[0], args, {
18
- stdio: 'inherit',
18
+ stdio: 'inherit'
19
19
  });
20
20
 
21
21
  if (child.signal) {
@@ -27,17 +27,36 @@ if (typeof global.gc !== 'function') {
27
27
  process.exit(process.exitCode);
28
28
  }
29
29
 
30
+ const testModules = [];
31
+
30
32
  const fs = require('fs');
31
33
  const path = require('path');
32
34
 
33
- let testModules = [];
35
+ let filterCondition = process.env.npm_config_filter || '';
36
+ let filterConditionFiles = [];
37
+
38
+ if (filterCondition !== '') {
39
+ filterCondition = require('../unit-test/matchModules').matchWildCards(process.env.npm_config_filter);
40
+ filterConditionFiles = filterCondition.split(' ').length > 0 ? filterCondition.split(' ') : [filterCondition];
41
+ }
42
+
43
+ const filterConditionsProvided = filterConditionFiles.length > 0;
44
+
45
+ function checkFilterCondition (fileName, parsedFilepath) {
46
+ let result = false;
47
+
48
+ if (!filterConditionsProvided) return true;
49
+ if (filterConditionFiles.includes(parsedFilepath)) result = true;
50
+ if (filterConditionFiles.includes(fileName)) result = true;
51
+ return result;
52
+ }
34
53
 
35
54
  // TODO(RaisinTen): Update this when the test filenames
36
55
  // are changed into test_*.js.
37
- function loadTestModules(currentDirectory = __dirname, pre = '') {
56
+ function loadTestModules (currentDirectory = __dirname, pre = '') {
38
57
  fs.readdirSync(currentDirectory).forEach((file) => {
39
58
  if (currentDirectory === __dirname && (
40
- file === 'binding.cc' ||
59
+ file === 'binding.cc' ||
41
60
  file === 'binding.gyp' ||
42
61
  file === 'build' ||
43
62
  file === 'common' ||
@@ -50,15 +69,19 @@ function loadTestModules(currentDirectory = __dirname, pre = '') {
50
69
  return;
51
70
  }
52
71
  const absoluteFilepath = path.join(currentDirectory, file);
72
+ const parsedFilepath = path.parse(file);
73
+ const parsedPath = path.parse(currentDirectory);
74
+
53
75
  if (fs.statSync(absoluteFilepath).isDirectory()) {
54
76
  if (fs.existsSync(absoluteFilepath + '/index.js')) {
55
- testModules.push(pre + file);
77
+ if (checkFilterCondition(parsedFilepath.name, parsedPath.base)) {
78
+ testModules.push(pre + file);
79
+ }
56
80
  } else {
57
81
  loadTestModules(absoluteFilepath, pre + file + '/');
58
82
  }
59
83
  } else {
60
- const parsedFilepath = path.parse(file);
61
- if (parsedFilepath.ext === '.js') {
84
+ if (parsedFilepath.ext === '.js' && checkFilterCondition(parsedFilepath.name, parsedPath.base)) {
62
85
  testModules.push(pre + parsedFilepath.name);
63
86
  }
64
87
  }
@@ -69,7 +92,7 @@ loadTestModules();
69
92
 
70
93
  process.config.target_defaults.default_configuration =
71
94
  fs
72
- .readdirSync(path.join(__dirname, 'build'))
95
+ .readdirSync(path.join(__dirname, process.env.REL_BUILD_PATH || '', 'build'))
73
96
  .filter((item) => (item === 'Debug' || item === 'Release'))[0];
74
97
 
75
98
  let napiVersion = Number(process.versions.napi);
@@ -87,7 +110,7 @@ if (napiVersion < 3) {
87
110
  testModules.splice(testModules.indexOf('version_management'), 1);
88
111
  }
89
112
 
90
- if (napiVersion < 4) {
113
+ if (napiVersion < 4 && !filterConditionsProvided) {
91
114
  testModules.splice(testModules.indexOf('asyncprogressqueueworker'), 1);
92
115
  testModules.splice(testModules.indexOf('asyncprogressworker'), 1);
93
116
  testModules.splice(testModules.indexOf('threadsafe_function/threadsafe_function_ctx'), 1);
@@ -98,36 +121,36 @@ if (napiVersion < 4) {
98
121
  testModules.splice(testModules.indexOf('threadsafe_function/threadsafe_function'), 1);
99
122
  }
100
123
 
101
- if (napiVersion < 5) {
124
+ if (napiVersion < 5 && !filterConditionsProvided) {
102
125
  testModules.splice(testModules.indexOf('date'), 1);
103
126
  }
104
127
 
105
- if (napiVersion < 6) {
128
+ if (napiVersion < 6 && !filterConditionsProvided) {
106
129
  testModules.splice(testModules.indexOf('addon'), 1);
107
130
  testModules.splice(testModules.indexOf('addon_data'), 1);
108
131
  testModules.splice(testModules.indexOf('bigint'), 1);
109
132
  testModules.splice(testModules.indexOf('typedarray-bigint'), 1);
110
133
  }
111
134
 
112
- if (majorNodeVersion < 12) {
135
+ if (majorNodeVersion < 12 && !filterConditionsProvided) {
113
136
  testModules.splice(testModules.indexOf('objectwrap_worker_thread'), 1);
114
137
  testModules.splice(testModules.indexOf('error_terminating_environment'), 1);
115
138
  }
116
139
 
117
- if (napiVersion < 8) {
140
+ if (napiVersion < 8 && !filterConditionsProvided) {
118
141
  testModules.splice(testModules.indexOf('object/object_freeze_seal'), 1);
119
142
  }
120
143
 
121
- (async function() {
144
+ (async function () {
122
145
  console.log(`Testing with Node-API Version '${napiVersion}'.`);
123
146
 
124
- console.log('Starting test suite\n');
147
+ if (filterConditionsProvided) { console.log('Starting test suite\n', testModules); } else { console.log('Starting test suite\n'); }
125
148
 
126
149
  // Requiring each module runs tests in the module.
127
150
  for (const name of testModules) {
128
151
  console.log(`Running test '${name}'`);
129
152
  await require('./' + name);
130
- };
153
+ }
131
154
 
132
155
  console.log('\nAll tests passed!');
133
156
  })().catch((error) => {
@@ -11,6 +11,7 @@ Value GetPropertyWithCStyleString(const CallbackInfo& info);
11
11
  Value GetPropertyWithCppStyleString(const CallbackInfo& info);
12
12
 
13
13
  // Native wrappers for testing Object::Set()
14
+ Value SetPropertyWithUint32(const CallbackInfo& info);
14
15
  Value SetPropertyWithNapiValue(const CallbackInfo& info);
15
16
  Value SetPropertyWithNapiWrapperValue(const CallbackInfo& info);
16
17
  Value SetPropertyWithCStyleString(const CallbackInfo& info);
@@ -299,6 +300,7 @@ Object InitObject(Env env) {
299
300
  exports["getPropertyWithCStyleString"] = Function::New(env, GetPropertyWithCStyleString);
300
301
  exports["getPropertyWithCppStyleString"] = Function::New(env, GetPropertyWithCppStyleString);
301
302
 
303
+ exports["setPropertyWithUint32"] = Function::New(env, SetPropertyWithUint32);
302
304
  exports["setPropertyWithNapiValue"] = Function::New(env, SetPropertyWithNapiValue);
303
305
  exports["setPropertyWithNapiWrapperValue"] = Function::New(env, SetPropertyWithNapiWrapperValue);
304
306
  exports["setPropertyWithCStyleString"] = Function::New(env, SetPropertyWithCStyleString);
@@ -19,6 +19,14 @@ Value SetPropertyWithNapiWrapperValue(const CallbackInfo& info) {
19
19
  return Boolean::New(info.Env(), MaybeUnwrapOr(obj.Set(key, value), false));
20
20
  }
21
21
 
22
+ Value SetPropertyWithUint32(const CallbackInfo& info) {
23
+ Object obj = info[0].As<Object>();
24
+ Number key = info[1].As<Number>();
25
+ Value value = info[2];
26
+ return Boolean::New(info.Env(),
27
+ MaybeUnwrapOr(obj.Set(key.Uint32Value(), value), false));
28
+ }
29
+
22
30
  Value SetPropertyWithCStyleString(const CallbackInfo& info) {
23
31
  Object obj = info[0].As<Object>();
24
32
  String jsKey = info[1].As<String>();
@@ -4,14 +4,14 @@ const assert = require('assert');
4
4
 
5
5
  module.exports = require('../common').runTest(test);
6
6
 
7
- function test(binding) {
8
- function testSetProperty(nativeSetProperty) {
7
+ function test (binding) {
8
+ function testSetProperty (nativeSetProperty, key = 'test') {
9
9
  const obj = {};
10
- assert.strictEqual(nativeSetProperty(obj, 'test', 1), true);
11
- assert.strictEqual(obj.test, 1);
10
+ assert.strictEqual(nativeSetProperty(obj, key, 1), true);
11
+ assert.strictEqual(obj[key], 1);
12
12
  }
13
13
 
14
- function testShouldThrowErrorIfKeyIsInvalid(nativeSetProperty) {
14
+ function testShouldThrowErrorIfKeyIsInvalid (nativeSetProperty) {
15
15
  assert.throws(() => {
16
16
  nativeSetProperty(undefined, 'test', 1);
17
17
  }, /Cannot convert undefined or null to object/);
@@ -21,6 +21,7 @@ function test(binding) {
21
21
  testSetProperty(binding.object.setPropertyWithNapiWrapperValue);
22
22
  testSetProperty(binding.object.setPropertyWithCStyleString);
23
23
  testSetProperty(binding.object.setPropertyWithCppStyleString);
24
+ testSetProperty(binding.object.setPropertyWithUint32, 12);
24
25
 
25
26
  testShouldThrowErrorIfKeyIsInvalid(binding.object.setPropertyWithNapiValue);
26
27
  testShouldThrowErrorIfKeyIsInvalid(binding.object.setPropertyWithNapiWrapperValue);
@@ -1,22 +1,38 @@
1
1
  #include "napi.h"
2
+ #include "test_helper.h"
2
3
 
3
4
  using namespace Napi;
4
5
 
5
6
  Value SubscriptGetWithCStyleString(const CallbackInfo& info) {
6
- Object obj = info[0].As<Object>();
7
7
  String jsKey = info[1].As<String>();
8
+
9
+ // make sure const case compiles
10
+ const Object obj2 = info[0].As<Object>();
11
+ MaybeUnwrap(obj2[jsKey.Utf8Value().c_str()]).As<Boolean>();
12
+
13
+ Object obj = info[0].As<Object>();
8
14
  return obj[jsKey.Utf8Value().c_str()];
9
15
  }
10
16
 
11
17
  Value SubscriptGetWithCppStyleString(const CallbackInfo& info) {
12
- Object obj = info[0].As<Object>();
13
18
  String jsKey = info[1].As<String>();
19
+
20
+ // make sure const case compiles
21
+ const Object obj2 = info[0].As<Object>();
22
+ MaybeUnwrap(obj2[jsKey.Utf8Value()]).As<Boolean>();
23
+
24
+ Object obj = info[0].As<Object>();
14
25
  return obj[jsKey.Utf8Value()];
15
26
  }
16
27
 
17
28
  Value SubscriptGetAtIndex(const CallbackInfo& info) {
18
- Object obj = info[0].As<Object>();
19
29
  uint32_t index = info[1].As<Napi::Number>();
30
+
31
+ // make sure const case compiles
32
+ const Object obj2 = info[0].As<Object>();
33
+ MaybeUnwrap(obj2[index]).As<Boolean>();
34
+
35
+ Object obj = info[0].As<Object>();
20
36
  return obj[index];
21
37
  }
22
38
 
@@ -0,0 +1,45 @@
1
+ #include <napi.h>
2
+ #include <unordered_map>
3
+ #include "test_helper.h"
4
+
5
+ class FunctionTest : public Napi::ObjectWrap<FunctionTest> {
6
+ public:
7
+ FunctionTest(const Napi::CallbackInfo& info)
8
+ : Napi::ObjectWrap<FunctionTest>(info) {}
9
+
10
+ static Napi::Value OnCalledAsFunction(const Napi::CallbackInfo& info) {
11
+ // If called with a "true" argument, throw an exeption to test the handling.
12
+ if (!info[0].IsUndefined() && MaybeUnwrap(info[0].ToBoolean())) {
13
+ NAPI_THROW(Napi::Error::New(info.Env(), "an exception"), Napi::Value());
14
+ }
15
+ // Otherwise, act as a factory.
16
+ std::vector<napi_value> args;
17
+ for (size_t i = 0; i < info.Length(); i++) args.push_back(info[i]);
18
+ return MaybeUnwrap(GetConstructor(info.Env()).New(args));
19
+ }
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
+ static void Initialize(Napi::Env env, Napi::Object exports) {
26
+ const char* name = "FunctionTest";
27
+ Napi::Function func = DefineClass(env, name, {});
28
+ constructors[env] = Napi::Persistent(func);
29
+ env.AddCleanupHook([env] { constructors.erase(env); });
30
+ exports.Set(name, func);
31
+ }
32
+
33
+ static Napi::Function GetConstructor(Napi::Env env) {
34
+ return constructors[env].Value();
35
+ }
36
+ };
37
+
38
+ std::unordered_map<napi_env, Napi::FunctionReference>
39
+ FunctionTest::constructors;
40
+
41
+ Napi::Object InitObjectWrapFunction(Napi::Env env) {
42
+ Napi::Object exports = Napi::Object::New(env);
43
+ FunctionTest::Initialize(env, exports);
44
+ return exports;
45
+ }