koffi 2.4.2 → 2.5.0-beta.2

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 (63) hide show
  1. package/build/2.5.0-beta.2/koffi_darwin_arm64/koffi.node +0 -0
  2. package/build/2.5.0-beta.2/koffi_darwin_x64/koffi.node +0 -0
  3. package/build/2.5.0-beta.2/koffi_freebsd_arm64/koffi.node +0 -0
  4. package/build/2.5.0-beta.2/koffi_freebsd_ia32/koffi.node +0 -0
  5. package/build/2.5.0-beta.2/koffi_freebsd_x64/koffi.node +0 -0
  6. package/build/2.5.0-beta.2/koffi_linux_arm32hf/koffi.node +0 -0
  7. package/build/2.5.0-beta.2/koffi_linux_arm64/koffi.node +0 -0
  8. package/build/2.5.0-beta.2/koffi_linux_ia32/koffi.node +0 -0
  9. package/build/2.5.0-beta.2/koffi_linux_riscv64hf64/koffi.node +0 -0
  10. package/build/2.5.0-beta.2/koffi_linux_x64/koffi.node +0 -0
  11. package/build/2.5.0-beta.2/koffi_openbsd_ia32/koffi.node +0 -0
  12. package/build/{2.4.2 → 2.5.0-beta.2}/koffi_openbsd_x64/koffi.node +0 -0
  13. package/build/2.5.0-beta.2/koffi_win32_arm64/koffi.node +0 -0
  14. package/build/{2.4.2 → 2.5.0-beta.2}/koffi_win32_ia32/koffi.node +0 -0
  15. package/build/{2.4.2 → 2.5.0-beta.2}/koffi_win32_x64/koffi.node +0 -0
  16. package/build/2.5.0-beta.2/koffi_win32_x64/koffi.pdb +0 -0
  17. package/doc/callbacks.md +1 -1
  18. package/doc/conf.py +1 -1
  19. package/doc/functions.md +1 -1
  20. package/doc/index.rst +1 -0
  21. package/doc/parameters.md +1 -1
  22. package/doc/pointers.md +1 -1
  23. package/doc/unions.md +187 -0
  24. package/package.json +1 -1
  25. package/src/core/libcc/libcc.cc +58 -54
  26. package/src/core/libcc/libcc.hh +33 -19
  27. package/src/koffi/src/abi_x86.cc +31 -4
  28. package/src/koffi/src/call.cc +42 -22
  29. package/src/koffi/src/ffi.cc +259 -311
  30. package/src/koffi/src/ffi.hh +3 -1
  31. package/src/koffi/src/util.cc +20 -13
  32. package/src/koffi/src/util.hh +5 -2
  33. package/vendor/node-addon-api/CHANGELOG.md +31 -0
  34. package/vendor/node-addon-api/README.md +3 -2
  35. package/vendor/node-addon-api/doc/async_worker.md +1 -0
  36. package/vendor/node-addon-api/doc/creating_a_release.md +21 -0
  37. package/vendor/node-addon-api/doc/value.md +7 -0
  38. package/vendor/node-addon-api/napi-inl.h +23 -7
  39. package/vendor/node-addon-api/package.json +9 -1
  40. package/vendor/node-addon-api/test/async_progress_queue_worker.cc +155 -0
  41. package/vendor/node-addon-api/test/async_progress_queue_worker.js +134 -0
  42. package/vendor/node-addon-api/test/async_progress_worker.cc +155 -0
  43. package/vendor/node-addon-api/test/async_progress_worker.js +134 -0
  44. package/vendor/node-addon-api/test/common/index.js +45 -0
  45. package/vendor/node-addon-api/test/objectwrap.js +9 -0
  46. package/build/2.4.2/koffi_darwin_arm64/koffi.node +0 -0
  47. package/build/2.4.2/koffi_darwin_x64/koffi.node +0 -0
  48. package/build/2.4.2/koffi_freebsd_arm64/koffi.node +0 -0
  49. package/build/2.4.2/koffi_freebsd_ia32/koffi.node +0 -0
  50. package/build/2.4.2/koffi_freebsd_x64/koffi.node +0 -0
  51. package/build/2.4.2/koffi_linux_arm32hf/koffi.node +0 -0
  52. package/build/2.4.2/koffi_linux_arm64/koffi.node +0 -0
  53. package/build/2.4.2/koffi_linux_ia32/koffi.node +0 -0
  54. package/build/2.4.2/koffi_linux_riscv64hf64/koffi.node +0 -0
  55. package/build/2.4.2/koffi_linux_x64/koffi.node +0 -0
  56. package/build/2.4.2/koffi_openbsd_ia32/koffi.node +0 -0
  57. package/build/2.4.2/koffi_win32_arm64/koffi.node +0 -0
  58. /package/build/{2.4.2 → 2.5.0-beta.2}/koffi_win32_arm64/koffi.exp +0 -0
  59. /package/build/{2.4.2 → 2.5.0-beta.2}/koffi_win32_arm64/koffi.lib +0 -0
  60. /package/build/{2.4.2 → 2.5.0-beta.2}/koffi_win32_ia32/koffi.exp +0 -0
  61. /package/build/{2.4.2 → 2.5.0-beta.2}/koffi_win32_ia32/koffi.lib +0 -0
  62. /package/build/{2.4.2 → 2.5.0-beta.2}/koffi_win32_x64/koffi.exp +0 -0
  63. /package/build/{2.4.2 → 2.5.0-beta.2}/koffi_win32_x64/koffi.lib +0 -0
@@ -198,7 +198,7 @@ struct ParameterInfo {
198
198
  int8_t vec_bytes; // ARM64
199
199
  #elif defined(__i386__) || defined(_M_IX86)
200
200
  bool trivial; // Only matters for return value
201
- bool fast;
201
+ int8_t fast;
202
202
  #elif __riscv_xlen == 64
203
203
  bool use_memory;
204
204
  int8_t gpr_count;
@@ -273,6 +273,8 @@ struct InstanceData {
273
273
  const TypeInfo *char_type;
274
274
  const TypeInfo *char16_type;
275
275
 
276
+ Napi::Symbol active_symbol;
277
+
276
278
  std::mutex memories_mutex;
277
279
  LocalArray<InstanceMemory *, 9> memories;
278
280
  int temporaries = 0;
@@ -58,14 +58,19 @@ Napi::Function MagicUnion::InitClass(Napi::Env env, const TypeInfo *type)
58
58
  MagicUnion::MagicUnion(const Napi::CallbackInfo &info)
59
59
  : Napi::ObjectWrap<MagicUnion>(info), type((const TypeInfo *)info.Data())
60
60
  {
61
+ Napi::Env env = info.Env();
62
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
63
+
64
+ active_symbol = instance->active_symbol;
61
65
  }
62
66
 
63
67
  void MagicUnion::SetRaw(const uint8_t *ptr)
64
68
  {
65
- raw = ptr;
69
+ raw.RemoveFrom(0);
70
+ raw.Append(MakeSpan(ptr, type->size));
66
71
 
72
+ Value().Set(active_symbol, Env().Undefined());
67
73
  active_idx = -1;
68
- Value().Set("__active", Env().Undefined());
69
74
  }
70
75
 
71
76
  Napi::Value MagicUnion::Getter(const Napi::CallbackInfo &info)
@@ -76,18 +81,18 @@ Napi::Value MagicUnion::Getter(const Napi::CallbackInfo &info)
76
81
  Napi::Value value;
77
82
 
78
83
  if (idx == active_idx) {
79
- value = Value().Get("__active");
84
+ value = Value().Get(active_symbol);
80
85
  } else {
81
86
  Napi::Env env = info.Env();
82
87
 
83
- if (RG_UNLIKELY(!raw)) {
88
+ if (RG_UNLIKELY(!raw.len)) {
84
89
  ThrowError<Napi::Error>(env, "Cannont convert %1 union value", active_idx < 0 ? "empty" : "assigned");
85
90
  return env.Null();
86
91
  }
87
92
 
88
- value = Decode(env, raw, member.type);
93
+ value = Decode(env, raw.ptr, member.type);
89
94
 
90
- Value().Set("__active", value);
95
+ Value().Set(active_symbol, value);
91
96
  active_idx = idx;
92
97
  }
93
98
 
@@ -99,10 +104,10 @@ void MagicUnion::Setter(const Napi::CallbackInfo &info, const Napi::Value &value
99
104
  {
100
105
  Size idx = (Size)info.Data();
101
106
 
102
- Value().Set("__active", value);
107
+ Value().Set(active_symbol, value);
103
108
  active_idx = idx;
104
109
 
105
- raw = nullptr;
110
+ raw.Clear();
106
111
  }
107
112
 
108
113
  const TypeInfo *ResolveType(Napi::Value value, int *out_directions)
@@ -272,10 +277,11 @@ const TypeInfo *MakePointerType(InstanceData *instance, const TypeInfo *ref, int
272
277
  char name_buf[256];
273
278
  Fmt(name_buf, "%1%2*", ref->name, EndsWith(ref->name, "*") ? "" : " ");
274
279
 
275
- TypeInfo *type = (TypeInfo *)instance->types_map.FindValue(name_buf, nullptr);
280
+ bool inserted;
281
+ auto bucket = instance->types_map.TrySetDefault(name_buf, &inserted);
276
282
 
277
- if (!type) {
278
- type = instance->types.AppendDefault();
283
+ if (inserted) {
284
+ TypeInfo *type = instance->types.AppendDefault();
279
285
 
280
286
  type->name = DuplicateString(name_buf, &instance->str_alloc).ptr;
281
287
 
@@ -291,10 +297,11 @@ const TypeInfo *MakePointerType(InstanceData *instance, const TypeInfo *ref, int
291
297
  type->ref.proto = ref->ref.proto;
292
298
  }
293
299
 
294
- instance->types_map.Set(type->name, type);
300
+ bucket->key = type->name;
301
+ bucket->value = type;
295
302
  }
296
303
 
297
- ref = type;
304
+ ref = bucket->value;
298
305
  }
299
306
 
300
307
  return ref;
@@ -38,18 +38,21 @@ extern const int MagicUnionMarker;
38
38
  class MagicUnion: public Napi::ObjectWrap<MagicUnion> {
39
39
  const TypeInfo *type;
40
40
 
41
+ napi_value active_symbol;
41
42
  Size active_idx = -1;
42
- const uint8_t *raw = nullptr;
43
+
44
+ HeapArray<uint8_t> raw;
43
45
 
44
46
  public:
45
47
  static Napi::Function InitClass(Napi::Env env, const TypeInfo *type);
46
48
 
47
49
  MagicUnion(const Napi::CallbackInfo &info);
48
50
 
51
+ const TypeInfo *GetType() { return type; }
49
52
  const RecordMember *GetMember() const { return (active_idx >= 0) ? &type->members[active_idx] : nullptr; }
50
53
 
51
54
  void SetRaw(const uint8_t *ptr);
52
- const uint8_t *GetRaw() const { return raw; }
55
+ const uint8_t *GetRaw() const { return raw.ptr; }
53
56
 
54
57
  private:
55
58
  Napi::Value Getter(const Napi::CallbackInfo &info);
@@ -1,5 +1,36 @@
1
1
  # node-addon-api Changelog
2
2
 
3
+ ## 2023-06-13 Version 7.0.0, @KevinEady
4
+
5
+ ### Notable changes
6
+
7
+ #### API
8
+
9
+ - Drop support for Node.js v14.x and v19.x.
10
+ - Ensure native receiver exists when calling instance methods and properties.
11
+ - Fix issue when creating `Napi::Error` instances that wrap primitives values.
12
+
13
+ #### TEST
14
+
15
+ - Added tests for `Napi::AsyncProgressQueueWorker<T>` class.
16
+ - Added tests for `Napi::AsyncProgressWorker<T>` class.
17
+
18
+ ### Documentation
19
+
20
+ - Added documentation for `Napi::Value::IsBigInt()`.
21
+
22
+ ### Commits
23
+
24
+ * \[[`de5c899400`](https://github.com/nodejs/node-addon-api/commit/de5c899400)] - **doc,chore**: drop support for Node.js v14, v19 (Kevin Eady) [#1324](https://github.com/nodejs/node-addon-api/pull/1324)
25
+ * \[[`3083b7f148`](https://github.com/nodejs/node-addon-api/commit/3083b7f148)] - \[StepSecurity] Apply security best practices (StepSecurity Bot) [#1308](https://github.com/nodejs/node-addon-api/pull/1308)
26
+ * \[[`a198e24a15`](https://github.com/nodejs/node-addon-api/commit/a198e24a15)] - \[Test] Add tests for async progress queue worker (Jack) [#1316](https://github.com/nodejs/node-addon-api/pull/1316)
27
+ * \[[`665f4aa845`](https://github.com/nodejs/node-addon-api/commit/665f4aa845)] - **doc**: add missing Value::IsBigInt (Kevin Eady) [#1319](https://github.com/nodejs/node-addon-api/pull/1319)
28
+ * \[[`358b2d3b4f`](https://github.com/nodejs/node-addon-api/commit/358b2d3b4f)] - **doc**: complete code curly braces in async\_worker.md (wanlu) [#1317](https://github.com/nodejs/node-addon-api/pull/1317)
29
+ * \[[`858942ce31`](https://github.com/nodejs/node-addon-api/commit/858942ce31)] - **src**: avoid calling into C++ with a null this (Caleb Hearon) [#1313](https://github.com/nodejs/node-addon-api/pull/1313)
30
+ * \[[`64f6515331`](https://github.com/nodejs/node-addon-api/commit/64f6515331)] - **src**: handle failure during error wrap of primitive (Gabriel Schulhof) [#1310](https://github.com/nodejs/node-addon-api/pull/1310)
31
+ * \[[`dfad6b45fe`](https://github.com/nodejs/node-addon-api/commit/dfad6b45fe)] - \[test] Add test coverage for AsyncProgressWorker (Jack) [#1307](https://github.com/nodejs/node-addon-api/pull/1307)
32
+ * \[[`0e34f22839`](https://github.com/nodejs/node-addon-api/commit/0e34f22839)] - **release**: v6.1.0. (Nicola Del Gobbo)
33
+
3
34
  ## 2023-04-20 Version 6.1.0, @NickNaso
4
35
 
5
36
  ### Notable changes
@@ -70,7 +70,7 @@ and node-addon-api.
70
70
  - **[Contributors](#contributors)**
71
71
  - **[License](#license)**
72
72
 
73
- ## **Current version: 6.1.0**
73
+ ## **Current version: 7.0.0**
74
74
 
75
75
  (See [CHANGELOG.md](CHANGELOG.md) for complete Changelog)
76
76
 
@@ -83,7 +83,7 @@ This allows addons built with it to run with Node.js versions which support the
83
83
  **However** the node-addon-api support model is to support only the active LTS Node.js versions. This means that
84
84
  every year there will be a new major which drops support for the Node.js LTS version which has gone out of service.
85
85
 
86
- The oldest Node.js version supported by the current version of node-addon-api is Node.js 14.x.
86
+ The oldest Node.js version supported by the current version of node-addon-api is Node.js 16.x.
87
87
 
88
88
  ## Setup
89
89
  - [Installation and usage](doc/setup.md)
@@ -275,6 +275,7 @@ available:
275
275
  ![Node-API v6 Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20v6%20Badge.svg)
276
276
  ![Node-API v7 Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20v7%20Badge.svg)
277
277
  ![Node-API v8 Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20v8%20Badge.svg)
278
+ ![Node-API v9 Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20v9%20Badge.svg)
278
279
  ![Node-API Experimental Version Badge](https://github.com/nodejs/abi-stable-node/blob/doc/assets/Node-API%20Experimental%20Version%20Badge.svg)
279
280
 
280
281
  ## **Contributing**
@@ -418,6 +418,7 @@ Value Echo(const CallbackInfo& info) {
418
418
  EchoWorker* wk = new EchoWorker(cb, in);
419
419
  wk->Queue();
420
420
  return info.Env().Undefined();
421
+ }
421
422
  ```
422
423
 
423
424
  Using the implementation of a `Napi::AsyncWorker` is straight forward. You only
@@ -60,3 +60,24 @@ and that the correct version is installed.
60
60
  and close the issue.
61
61
 
62
62
  * Tweet that the release has been created.
63
+
64
+ ## Optional Steps
65
+
66
+ Depending on circumstances for the release, additional steps may be required to
67
+ support the release process.
68
+
69
+ ### Major Releases to Drop Support Node.js Versions
70
+
71
+ `node-addon-api` provides support for Node.js versions following the same
72
+ [release schedule](https://nodejs.dev/en/about/releases/): once a Node.js
73
+ version leaves maintenance mode, the next major version of `node-addon-api`
74
+ published will drop support for that version. These are the steps to follow to
75
+ drop support for a Node.js version:
76
+
77
+ * Update minimum version supported in documentation ([README.md](../README.md))
78
+
79
+ * Remove from GitHub actions ([ci.yml](../.github/workflows/ci.yml) and
80
+ [ci-win.yml](../.github/workflows/ci-win.yml))
81
+
82
+ * Remove from Jenkins CI ([node-test-node-addon-api-LTS versions
83
+ [Jenkins]](https://ci.nodejs.org/view/x%20-%20Abi%20stable%20module%20API/job/node-test-node-addon-api-LTS%20versions/))
@@ -141,6 +141,13 @@ bool Napi::Value::IsArrayBuffer() const;
141
141
  Returns `true` if the underlying value is a JavaScript `Napi::ArrayBuffer` or
142
142
  `false` otherwise.
143
143
 
144
+ ```cpp
145
+ bool Napi::Value::IsBigInt() const;
146
+ ```
147
+
148
+ Returns `true` if the underlying value is a JavaScript `Napi::BigInt` or `false`
149
+ otherwise.
150
+
144
151
  ### IsBoolean
145
152
 
146
153
  ```cpp
@@ -165,7 +165,7 @@ napi_value TemplatedInstanceCallback(napi_env env,
165
165
  return details::WrapCallback([&] {
166
166
  CallbackInfo cbInfo(env, info);
167
167
  T* instance = T::Unwrap(cbInfo.This().As<Object>());
168
- return (instance->*UnwrapCallback)(cbInfo);
168
+ return instance ? (instance->*UnwrapCallback)(cbInfo) : Napi::Value();
169
169
  });
170
170
  }
171
171
 
@@ -175,7 +175,7 @@ napi_value TemplatedInstanceVoidCallback(napi_env env, napi_callback_info info)
175
175
  return details::WrapCallback([&] {
176
176
  CallbackInfo cbInfo(env, info);
177
177
  T* instance = T::Unwrap(cbInfo.This().As<Object>());
178
- (instance->*UnwrapCallback)(cbInfo);
178
+ if (instance) (instance->*UnwrapCallback)(cbInfo);
179
179
  return nullptr;
180
180
  });
181
181
  }
@@ -2937,6 +2937,22 @@ inline Error::Error(napi_env env, napi_value value)
2937
2937
  nullptr};
2938
2938
 
2939
2939
  status = napi_define_properties(env, wrappedErrorObj, 1, &wrapObjFlag);
2940
+ #ifdef NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS
2941
+ if (status == napi_pending_exception) {
2942
+ // Test if the pending exception was reported because the environment is
2943
+ // shutting down. We assume that a status of napi_pending_exception
2944
+ // coupled with the absence of an actual pending exception means that
2945
+ // the environment is shutting down. If so, we replace the
2946
+ // napi_pending_exception status with napi_ok.
2947
+ bool is_exception_pending = false;
2948
+ status = napi_is_exception_pending(env, &is_exception_pending);
2949
+ if (status == napi_ok && !is_exception_pending) {
2950
+ status = napi_ok;
2951
+ } else {
2952
+ status = napi_pending_exception;
2953
+ }
2954
+ }
2955
+ #endif // NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS
2940
2956
  NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_define_properties");
2941
2957
 
2942
2958
  // Create a reference on the newly wrapped object
@@ -4340,7 +4356,7 @@ inline napi_value InstanceWrap<T>::InstanceVoidMethodCallbackWrapper(
4340
4356
  callbackInfo.SetData(callbackData->data);
4341
4357
  T* instance = T::Unwrap(callbackInfo.This().As<Object>());
4342
4358
  auto cb = callbackData->callback;
4343
- (instance->*cb)(callbackInfo);
4359
+ if (instance) (instance->*cb)(callbackInfo);
4344
4360
  return nullptr;
4345
4361
  });
4346
4362
  }
@@ -4355,7 +4371,7 @@ inline napi_value InstanceWrap<T>::InstanceMethodCallbackWrapper(
4355
4371
  callbackInfo.SetData(callbackData->data);
4356
4372
  T* instance = T::Unwrap(callbackInfo.This().As<Object>());
4357
4373
  auto cb = callbackData->callback;
4358
- return (instance->*cb)(callbackInfo);
4374
+ return instance ? (instance->*cb)(callbackInfo) : Napi::Value();
4359
4375
  });
4360
4376
  }
4361
4377
 
@@ -4369,7 +4385,7 @@ inline napi_value InstanceWrap<T>::InstanceGetterCallbackWrapper(
4369
4385
  callbackInfo.SetData(callbackData->data);
4370
4386
  T* instance = T::Unwrap(callbackInfo.This().As<Object>());
4371
4387
  auto cb = callbackData->getterCallback;
4372
- return (instance->*cb)(callbackInfo);
4388
+ return instance ? (instance->*cb)(callbackInfo) : Napi::Value();
4373
4389
  });
4374
4390
  }
4375
4391
 
@@ -4383,7 +4399,7 @@ inline napi_value InstanceWrap<T>::InstanceSetterCallbackWrapper(
4383
4399
  callbackInfo.SetData(callbackData->data);
4384
4400
  T* instance = T::Unwrap(callbackInfo.This().As<Object>());
4385
4401
  auto cb = callbackData->setterCallback;
4386
- (instance->*cb)(callbackInfo, callbackInfo[0]);
4402
+ if (instance) (instance->*cb)(callbackInfo, callbackInfo[0]);
4387
4403
  return nullptr;
4388
4404
  });
4389
4405
  }
@@ -4395,7 +4411,7 @@ inline napi_value InstanceWrap<T>::WrappedMethod(
4395
4411
  return details::WrapCallback([&] {
4396
4412
  const CallbackInfo cbInfo(env, info);
4397
4413
  T* instance = T::Unwrap(cbInfo.This().As<Object>());
4398
- (instance->*method)(cbInfo, cbInfo[0]);
4414
+ if (instance) (instance->*method)(cbInfo, cbInfo[0]);
4399
4415
  return nullptr;
4400
4416
  });
4401
4417
  }
@@ -399,6 +399,14 @@
399
399
  {
400
400
  "name": "Feng Yu",
401
401
  "url": "https://github.com/F3n67u"
402
+ },
403
+ {
404
+ "name": "wanlu wang",
405
+ "url": "https://github.com/wanlu"
406
+ },
407
+ {
408
+ "name": "Caleb Hearon",
409
+ "url": "https://github.com/chearon"
402
410
  }
403
411
  ],
404
412
  "description": "Node.js API (Node-API)",
@@ -459,6 +467,6 @@
459
467
  "lint:fix": "node tools/clang-format --fix && node tools/eslint-format --fix"
460
468
  },
461
469
  "pre-commit": "lint",
462
- "version": "6.1.0",
470
+ "version": "7.0.0",
463
471
  "support": true
464
472
  }
@@ -15,6 +15,158 @@ struct ProgressData {
15
15
  int32_t progress;
16
16
  };
17
17
 
18
+ class TestWorkerWithNoCb : public AsyncProgressQueueWorker<ProgressData> {
19
+ public:
20
+ static void DoWork(const CallbackInfo& info) {
21
+ switch (info.Length()) {
22
+ case 1: {
23
+ Function cb = info[0].As<Function>();
24
+ TestWorkerWithNoCb* worker = new TestWorkerWithNoCb(info.Env(), cb);
25
+ worker->Queue();
26
+ } break;
27
+
28
+ case 2: {
29
+ std::string resName = info[0].As<String>();
30
+ Function cb = info[1].As<Function>();
31
+ TestWorkerWithNoCb* worker =
32
+ new TestWorkerWithNoCb(info.Env(), resName.c_str(), cb);
33
+ worker->Queue();
34
+ } break;
35
+
36
+ case 3: {
37
+ std::string resName = info[0].As<String>();
38
+ Object resObject = info[1].As<Object>();
39
+ Function cb = info[2].As<Function>();
40
+ TestWorkerWithNoCb* worker =
41
+ new TestWorkerWithNoCb(info.Env(), resName.c_str(), resObject, cb);
42
+ worker->Queue();
43
+ } break;
44
+
45
+ default:
46
+
47
+ break;
48
+ }
49
+ }
50
+
51
+ protected:
52
+ void Execute(const ExecutionProgress& progress) override {
53
+ ProgressData data{1};
54
+ progress.Send(&data, 1);
55
+ }
56
+
57
+ void OnProgress(const ProgressData*, size_t /* count */) override {
58
+ _cb.Call({});
59
+ }
60
+
61
+ private:
62
+ TestWorkerWithNoCb(Napi::Env env, Function cb)
63
+ : AsyncProgressQueueWorker(env) {
64
+ _cb.Reset(cb, 1);
65
+ }
66
+ TestWorkerWithNoCb(Napi::Env env, const char* resourceName, Function cb)
67
+ : AsyncProgressQueueWorker(env, resourceName) {
68
+ _cb.Reset(cb, 1);
69
+ }
70
+ TestWorkerWithNoCb(Napi::Env env,
71
+ const char* resourceName,
72
+ const Object& resourceObject,
73
+ Function cb)
74
+ : AsyncProgressQueueWorker(env, resourceName, resourceObject) {
75
+ _cb.Reset(cb, 1);
76
+ }
77
+ FunctionReference _cb;
78
+ };
79
+
80
+ class TestWorkerWithRecv : public AsyncProgressQueueWorker<ProgressData> {
81
+ public:
82
+ static void DoWork(const CallbackInfo& info) {
83
+ switch (info.Length()) {
84
+ case 2: {
85
+ Object recv = info[0].As<Object>();
86
+ Function cb = info[1].As<Function>();
87
+ TestWorkerWithRecv* worker = new TestWorkerWithRecv(recv, cb);
88
+ worker->Queue();
89
+ } break;
90
+
91
+ case 3: {
92
+ Object recv = info[0].As<Object>();
93
+ Function cb = info[1].As<Function>();
94
+ std::string resName = info[2].As<String>();
95
+ TestWorkerWithRecv* worker =
96
+ new TestWorkerWithRecv(recv, cb, resName.c_str());
97
+ worker->Queue();
98
+ } break;
99
+
100
+ case 4: {
101
+ Object recv = info[0].As<Object>();
102
+ Function cb = info[1].As<Function>();
103
+ std::string resName = info[2].As<String>();
104
+ Object resObject = info[3].As<Object>();
105
+ TestWorkerWithRecv* worker =
106
+ new TestWorkerWithRecv(recv, cb, resName.c_str(), resObject);
107
+ worker->Queue();
108
+ } break;
109
+
110
+ default:
111
+
112
+ break;
113
+ }
114
+ }
115
+
116
+ protected:
117
+ void Execute(const ExecutionProgress&) override {}
118
+
119
+ void OnProgress(const ProgressData*, size_t /* count */) override {}
120
+
121
+ private:
122
+ TestWorkerWithRecv(const Object& recv, const Function& cb)
123
+ : AsyncProgressQueueWorker(recv, cb) {}
124
+ TestWorkerWithRecv(const Object& recv,
125
+ const Function& cb,
126
+ const char* resourceName)
127
+ : AsyncProgressQueueWorker(recv, cb, resourceName) {}
128
+ TestWorkerWithRecv(const Object& recv,
129
+ const Function& cb,
130
+ const char* resourceName,
131
+ const Object& resourceObject)
132
+ : AsyncProgressQueueWorker(recv, cb, resourceName, resourceObject) {}
133
+ };
134
+
135
+ class TestWorkerWithCb : public AsyncProgressQueueWorker<ProgressData> {
136
+ public:
137
+ static void DoWork(const CallbackInfo& info) {
138
+ switch (info.Length()) {
139
+ case 1: {
140
+ Function cb = info[0].As<Function>();
141
+ TestWorkerWithCb* worker = new TestWorkerWithCb(cb);
142
+ worker->Queue();
143
+ } break;
144
+
145
+ case 2: {
146
+ Function cb = info[0].As<Function>();
147
+ std::string asyncResName = info[1].As<String>();
148
+ TestWorkerWithCb* worker =
149
+ new TestWorkerWithCb(cb, asyncResName.c_str());
150
+ worker->Queue();
151
+ } break;
152
+
153
+ default:
154
+
155
+ break;
156
+ }
157
+ }
158
+
159
+ protected:
160
+ void Execute(const ExecutionProgress&) override {}
161
+
162
+ void OnProgress(const ProgressData*, size_t /* count */) override {}
163
+
164
+ private:
165
+ TestWorkerWithCb(Function cb) : AsyncProgressQueueWorker(cb) {}
166
+ TestWorkerWithCb(Function cb, const char* res_name)
167
+ : AsyncProgressQueueWorker(cb, res_name) {}
168
+ };
169
+
18
170
  class TestWorker : public AsyncProgressQueueWorker<ProgressData> {
19
171
  public:
20
172
  static Napi::Value CreateWork(const CallbackInfo& info) {
@@ -87,6 +239,9 @@ Object InitAsyncProgressQueueWorker(Env env) {
87
239
  Object exports = Object::New(env);
88
240
  exports["createWork"] = Function::New(env, TestWorker::CreateWork);
89
241
  exports["queueWork"] = Function::New(env, TestWorker::QueueWork);
242
+ exports["runWorkerNoCb"] = Function::New(env, TestWorkerWithNoCb::DoWork);
243
+ exports["runWorkerWithRecv"] = Function::New(env, TestWorkerWithRecv::DoWork);
244
+ exports["runWorkerWithCb"] = Function::New(env, TestWorkerWithCb::DoWork);
90
245
  return exports;
91
246
  }
92
247
 
@@ -4,10 +4,144 @@ const common = require('./common');
4
4
  const assert = require('assert');
5
5
 
6
6
  module.exports = common.runTest(test);
7
+ const nodeVersion = process.versions.node.split('.')[0];
8
+
9
+ let asyncHooks;
10
+ function checkAsyncHooks () {
11
+ if (nodeVersion >= 8) {
12
+ if (asyncHooks === undefined) {
13
+ asyncHooks = require('async_hooks');
14
+ }
15
+ return true;
16
+ }
17
+ return false;
18
+ }
7
19
 
8
20
  async function test ({ asyncprogressqueueworker }) {
9
21
  await success(asyncprogressqueueworker);
10
22
  await fail(asyncprogressqueueworker);
23
+
24
+ await asyncProgressWorkerCallbackOverloads(asyncprogressqueueworker.runWorkerWithCb);
25
+ await asyncProgressWorkerRecvOverloads(asyncprogressqueueworker.runWorkerWithRecv);
26
+ await asyncProgressWorkerNoCbOverloads(asyncprogressqueueworker.runWorkerNoCb);
27
+ }
28
+
29
+ async function asyncProgressWorkerCallbackOverloads (bindingFunction) {
30
+ bindingFunction(common.mustCall());
31
+ if (!checkAsyncHooks()) {
32
+ return;
33
+ }
34
+
35
+ const hooks = common.installAysncHooks('cbResources');
36
+
37
+ const triggerAsyncId = asyncHooks.executionAsyncId();
38
+ await new Promise((resolve, reject) => {
39
+ bindingFunction(common.mustCall(), 'cbResources');
40
+ hooks.then(actual => {
41
+ assert.deepStrictEqual(actual, [
42
+ {
43
+ eventName: 'init',
44
+ type: 'cbResources',
45
+ triggerAsyncId: triggerAsyncId,
46
+ resource: {}
47
+ },
48
+ { eventName: 'before' },
49
+ { eventName: 'after' },
50
+ { eventName: 'destroy' }
51
+ ]);
52
+ resolve();
53
+ }).catch((err) => reject(err));
54
+ });
55
+ }
56
+
57
+ async function asyncProgressWorkerRecvOverloads (bindingFunction) {
58
+ const recvObject = {
59
+ a: 4
60
+ };
61
+
62
+ function cb () {
63
+ assert.strictEqual(this.a, recvObject.a);
64
+ }
65
+
66
+ bindingFunction(recvObject, common.mustCall(cb));
67
+ if (!checkAsyncHooks()) {
68
+ return;
69
+ }
70
+ const asyncResources = [
71
+ { resName: 'cbRecvResources', resObject: {} },
72
+ { resName: 'cbRecvResourcesObject', resObject: { foo: 'bar' } }
73
+ ];
74
+
75
+ for (const asyncResource of asyncResources) {
76
+ const asyncResName = asyncResource.resName;
77
+ const asyncResObject = asyncResource.resObject;
78
+
79
+ const hooks = common.installAysncHooks(asyncResource.resName);
80
+ const triggerAsyncId = asyncHooks.executionAsyncId();
81
+ await new Promise((resolve, reject) => {
82
+ if (Object.keys(asyncResObject).length === 0) {
83
+ bindingFunction(recvObject, common.mustCall(cb), asyncResName);
84
+ } else {
85
+ bindingFunction(recvObject, common.mustCall(cb), asyncResName, asyncResObject);
86
+ }
87
+
88
+ hooks.then(actual => {
89
+ assert.deepStrictEqual(actual, [
90
+ {
91
+ eventName: 'init',
92
+ type: asyncResName,
93
+ triggerAsyncId: triggerAsyncId,
94
+ resource: asyncResObject
95
+ },
96
+ { eventName: 'before' },
97
+ { eventName: 'after' },
98
+ { eventName: 'destroy' }
99
+ ]);
100
+ resolve();
101
+ }).catch((err) => reject(err));
102
+ });
103
+ }
104
+ }
105
+
106
+ async function asyncProgressWorkerNoCbOverloads (bindingFunction) {
107
+ bindingFunction(common.mustCall());
108
+ if (!checkAsyncHooks()) {
109
+ return;
110
+ }
111
+ const asyncResources = [
112
+ { resName: 'noCbResources', resObject: {} },
113
+ { resName: 'noCbResourcesObject', resObject: { foo: 'bar' } }
114
+ ];
115
+
116
+ for (const asyncResource of asyncResources) {
117
+ const asyncResName = asyncResource.resName;
118
+ const asyncResObject = asyncResource.resObject;
119
+
120
+ const hooks = common.installAysncHooks(asyncResource.resName);
121
+ const triggerAsyncId = asyncHooks.executionAsyncId();
122
+ await new Promise((resolve, reject) => {
123
+ if (Object.keys(asyncResObject).length === 0) {
124
+ bindingFunction(asyncResName, common.mustCall(() => {}));
125
+ } else {
126
+ bindingFunction(asyncResName, asyncResObject, common.mustCall(() => {}));
127
+ }
128
+
129
+ hooks.then(actual => {
130
+ assert.deepStrictEqual(actual, [
131
+ {
132
+ eventName: 'init',
133
+ type: asyncResName,
134
+ triggerAsyncId: triggerAsyncId,
135
+ resource: asyncResObject
136
+ },
137
+ { eventName: 'before' },
138
+ { eventName: 'after' },
139
+ { eventName: 'destroy' }
140
+ ]);
141
+ resolve();
142
+ }).catch((err) => reject(err));
143
+ });
144
+ }
11
145
  }
12
146
 
13
147
  function success (binding) {