node-addon-api 1.7.2 → 3.0.0

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 (53) hide show
  1. package/.travis.yml +3 -9
  2. package/CHANGELOG.md +154 -9
  3. package/README.md +58 -9
  4. package/benchmark/README.md +47 -0
  5. package/benchmark/binding.gyp +25 -0
  6. package/benchmark/function_args.cc +153 -0
  7. package/benchmark/function_args.js +52 -0
  8. package/benchmark/index.js +34 -0
  9. package/benchmark/property_descriptor.cc +60 -0
  10. package/benchmark/property_descriptor.js +29 -0
  11. package/common.gypi +21 -0
  12. package/doc/array_buffer.md +1 -1
  13. package/doc/async_context.md +10 -0
  14. package/doc/async_operations.md +1 -1
  15. package/doc/async_worker.md +56 -26
  16. package/doc/async_worker_variants.md +456 -0
  17. package/doc/basic_types.md +8 -0
  18. package/doc/bigint.md +2 -1
  19. package/doc/class_property_descriptor.md +5 -6
  20. package/doc/cmake-js.md +58 -9
  21. package/doc/creating_a_release.md +5 -5
  22. package/doc/date.md +68 -0
  23. package/doc/env.md +14 -0
  24. package/doc/function.md +108 -1
  25. package/doc/object.md +74 -1
  26. package/doc/object_lifetime_management.md +1 -1
  27. package/doc/object_wrap.md +291 -4
  28. package/doc/prebuild_tools.md +1 -1
  29. package/doc/property_descriptor.md +64 -9
  30. package/doc/setup.md +0 -1
  31. package/doc/string.md +1 -1
  32. package/doc/symbol.md +1 -1
  33. package/doc/threadsafe_function.md +18 -1
  34. package/doc/value.md +10 -1
  35. package/except.gypi +16 -0
  36. package/index.js +5 -42
  37. package/napi-inl.h +1048 -147
  38. package/napi.h +424 -49
  39. package/node_api.gyp +9 -0
  40. package/noexcept.gypi +16 -0
  41. package/{src/nothing.c → nothing.c} +0 -0
  42. package/package.json +244 -47
  43. package/tools/README.md +4 -4
  44. package/tools/conversion.js +0 -4
  45. package/external-napi/node_api.h +0 -7
  46. package/src/node_api.cc +0 -3655
  47. package/src/node_api.gyp +0 -21
  48. package/src/node_api.h +0 -588
  49. package/src/node_api_types.h +0 -115
  50. package/src/node_internals.cc +0 -142
  51. package/src/node_internals.h +0 -157
  52. package/src/util-inl.h +0 -38
  53. package/src/util.h +0 -7
package/napi-inl.h CHANGED
@@ -9,7 +9,9 @@
9
9
 
10
10
  // Note: Do not include this file directly! Include "napi.h" instead.
11
11
 
12
+ #include <algorithm>
12
13
  #include <cstring>
14
+ #include <mutex>
13
15
  #include <type_traits>
14
16
 
15
17
  namespace Napi {
@@ -24,16 +26,23 @@ namespace details {
24
26
  template <typename FreeType>
25
27
  static inline napi_status AttachData(napi_env env,
26
28
  napi_value obj,
27
- FreeType* data) {
29
+ FreeType* data,
30
+ napi_finalize finalizer = nullptr,
31
+ void* hint = nullptr) {
32
+ napi_status status;
33
+ if (finalizer == nullptr) {
34
+ finalizer = [](napi_env /*env*/, void* data, void* /*hint*/) {
35
+ delete static_cast<FreeType*>(data);
36
+ };
37
+ }
38
+ #if (NAPI_VERSION < 5)
28
39
  napi_value symbol, external;
29
- napi_status status = napi_create_symbol(env, nullptr, &symbol);
40
+ status = napi_create_symbol(env, nullptr, &symbol);
30
41
  if (status == napi_ok) {
31
42
  status = napi_create_external(env,
32
43
  data,
33
- [](napi_env /*env*/, void* data, void* /*hint*/) {
34
- delete static_cast<FreeType*>(data);
35
- },
36
- nullptr,
44
+ finalizer,
45
+ hint,
37
46
  &external);
38
47
  if (status == napi_ok) {
39
48
  napi_property_descriptor desc = {
@@ -49,6 +58,9 @@ static inline napi_status AttachData(napi_env env,
49
58
  status = napi_define_properties(env, obj, 1, &desc);
50
59
  }
51
60
  }
61
+ #else // NAPI_VERSION >= 5
62
+ status = napi_add_finalizer(env, obj, data, finalizer, hint, nullptr);
63
+ #endif
52
64
  return status;
53
65
  }
54
66
 
@@ -138,9 +150,6 @@ struct ThreadSafeFinalize {
138
150
  ThreadSafeFinalize* finalizeData =
139
151
  static_cast<ThreadSafeFinalize*>(rawFinalizeData);
140
152
  finalizeData->callback(Env(env));
141
- if (finalizeData->tsfn) {
142
- *finalizeData->tsfn = nullptr;
143
- }
144
153
  delete finalizeData;
145
154
  }
146
155
 
@@ -154,9 +163,6 @@ struct ThreadSafeFinalize {
154
163
  ThreadSafeFinalize* finalizeData =
155
164
  static_cast<ThreadSafeFinalize*>(rawFinalizeData);
156
165
  finalizeData->callback(Env(env), finalizeData->data);
157
- if (finalizeData->tsfn) {
158
- *finalizeData->tsfn = nullptr;
159
- }
160
166
  delete finalizeData;
161
167
  }
162
168
 
@@ -170,9 +176,6 @@ struct ThreadSafeFinalize {
170
176
  ThreadSafeFinalize* finalizeData =
171
177
  static_cast<ThreadSafeFinalize*>(rawFinalizeData);
172
178
  finalizeData->callback(Env(env), static_cast<ContextType*>(rawContext));
173
- if (finalizeData->tsfn) {
174
- *finalizeData->tsfn = nullptr;
175
- }
176
179
  delete finalizeData;
177
180
  }
178
181
 
@@ -187,15 +190,11 @@ struct ThreadSafeFinalize {
187
190
  static_cast<ThreadSafeFinalize*>(rawFinalizeData);
188
191
  finalizeData->callback(Env(env), finalizeData->data,
189
192
  static_cast<ContextType*>(rawContext));
190
- if (finalizeData->tsfn) {
191
- *finalizeData->tsfn = nullptr;
192
- }
193
193
  delete finalizeData;
194
194
  }
195
195
 
196
196
  FinalizerDataType* data;
197
197
  Finalizer callback;
198
- napi_threadsafe_function* tsfn;
199
198
  };
200
199
  #endif
201
200
 
@@ -307,6 +306,64 @@ inline Error Env::GetAndClearPendingException() {
307
306
  return Error(_env, value);
308
307
  }
309
308
 
309
+ inline Value Env::RunScript(const char* utf8script) {
310
+ String script = String::New(_env, utf8script);
311
+ return RunScript(script);
312
+ }
313
+
314
+ inline Value Env::RunScript(const std::string& utf8script) {
315
+ return RunScript(utf8script.c_str());
316
+ }
317
+
318
+ inline Value Env::RunScript(String script) {
319
+ napi_value result;
320
+ napi_status status = napi_run_script(_env, script, &result);
321
+ NAPI_THROW_IF_FAILED(_env, status, Undefined());
322
+ return Value(_env, result);
323
+ }
324
+
325
+ #if NAPI_VERSION > 5
326
+ template <typename T, Env::Finalizer<T> fini>
327
+ inline void Env::SetInstanceData(T* data) {
328
+ napi_status status =
329
+ napi_set_instance_data(_env, data, [](napi_env env, void* data, void*) {
330
+ fini(env, static_cast<T*>(data));
331
+ }, nullptr);
332
+ NAPI_THROW_IF_FAILED_VOID(_env, status);
333
+ }
334
+
335
+ template <typename DataType,
336
+ typename HintType,
337
+ Napi::Env::FinalizerWithHint<DataType, HintType> fini>
338
+ inline void Env::SetInstanceData(DataType* data, HintType* hint) {
339
+ napi_status status =
340
+ napi_set_instance_data(_env, data,
341
+ [](napi_env env, void* data, void* hint) {
342
+ fini(env, static_cast<DataType*>(data), static_cast<HintType*>(hint));
343
+ }, hint);
344
+ NAPI_THROW_IF_FAILED_VOID(_env, status);
345
+ }
346
+
347
+ template <typename T>
348
+ inline T* Env::GetInstanceData() {
349
+ void* data = nullptr;
350
+
351
+ napi_status status = napi_get_instance_data(_env, &data);
352
+ NAPI_THROW_IF_FAILED(_env, status, nullptr);
353
+
354
+ return static_cast<T*>(data);
355
+ }
356
+
357
+ template <typename T> void Env::DefaultFini(Env, T* data) {
358
+ delete data;
359
+ }
360
+
361
+ template <typename DataType, typename HintType>
362
+ void Env::DefaultFiniWithHint(Env, DataType* data, HintType*) {
363
+ delete data;
364
+ }
365
+ #endif // NAPI_VERSION > 5
366
+
310
367
  ////////////////////////////////////////////////////////////////////////////////
311
368
  // Value class
312
369
  ////////////////////////////////////////////////////////////////////////////////
@@ -371,13 +428,24 @@ inline bool Value::IsNumber() const {
371
428
  return Type() == napi_number;
372
429
  }
373
430
 
374
- // currently experimental guard with version of NAPI_VERSION that it is
375
- // released in once it is no longer experimental
376
- #if (NAPI_VERSION > 2147483646)
431
+ #if NAPI_VERSION > 5
377
432
  inline bool Value::IsBigInt() const {
378
433
  return Type() == napi_bigint;
379
434
  }
380
- #endif // NAPI_EXPERIMENTAL
435
+ #endif // NAPI_VERSION > 5
436
+
437
+ #if (NAPI_VERSION > 4)
438
+ inline bool Value::IsDate() const {
439
+ if (IsEmpty()) {
440
+ return false;
441
+ }
442
+
443
+ bool result;
444
+ napi_status status = napi_is_date(_env, _value, &result);
445
+ NAPI_THROW_IF_FAILED(_env, status, false);
446
+ return result;
447
+ }
448
+ #endif
381
449
 
382
450
  inline bool Value::IsString() const {
383
451
  return Type() == napi_string;
@@ -595,9 +663,7 @@ inline double Number::DoubleValue() const {
595
663
  return result;
596
664
  }
597
665
 
598
- // currently experimental guard with version of NAPI_VERSION that it is
599
- // released in once it is no longer experimental
600
- #if (NAPI_VERSION > 2147483646)
666
+ #if NAPI_VERSION > 5
601
667
  ////////////////////////////////////////////////////////////////////////////////
602
668
  // BigInt Class
603
669
  ////////////////////////////////////////////////////////////////////////////////
@@ -658,7 +724,38 @@ inline void BigInt::ToWords(int* sign_bit, size_t* word_count, uint64_t* words)
658
724
  _env, _value, sign_bit, word_count, words);
659
725
  NAPI_THROW_IF_FAILED_VOID(_env, status);
660
726
  }
661
- #endif // NAPI_EXPERIMENTAL
727
+ #endif // NAPI_VERSION > 5
728
+
729
+ #if (NAPI_VERSION > 4)
730
+ ////////////////////////////////////////////////////////////////////////////////
731
+ // Date Class
732
+ ////////////////////////////////////////////////////////////////////////////////
733
+
734
+ inline Date Date::New(napi_env env, double val) {
735
+ napi_value value;
736
+ napi_status status = napi_create_date(env, val, &value);
737
+ NAPI_THROW_IF_FAILED(env, status, Date());
738
+ return Date(env, value);
739
+ }
740
+
741
+ inline Date::Date() : Value() {
742
+ }
743
+
744
+ inline Date::Date(napi_env env, napi_value value) : Value(env, value) {
745
+ }
746
+
747
+ inline Date::operator double() const {
748
+ return ValueOf();
749
+ }
750
+
751
+ inline double Date::ValueOf() const {
752
+ double result;
753
+ napi_status status = napi_get_date_value(
754
+ _env, _value, &result);
755
+ NAPI_THROW_IF_FAILED(_env, status, 0);
756
+ return result;
757
+ }
758
+ #endif
662
759
 
663
760
  ////////////////////////////////////////////////////////////////////////////////
664
761
  // Name class
@@ -1126,6 +1223,40 @@ inline bool Object::InstanceOf(const Function& constructor) const {
1126
1223
  return result;
1127
1224
  }
1128
1225
 
1226
+ template <typename Finalizer, typename T>
1227
+ inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) {
1228
+ details::FinalizeData<T, Finalizer>* finalizeData =
1229
+ new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
1230
+ napi_status status =
1231
+ details::AttachData(_env,
1232
+ *this,
1233
+ data,
1234
+ details::FinalizeData<T, Finalizer>::Wrapper,
1235
+ finalizeData);
1236
+ if (status != napi_ok) {
1237
+ delete finalizeData;
1238
+ NAPI_THROW_IF_FAILED_VOID(_env, status);
1239
+ }
1240
+ }
1241
+
1242
+ template <typename Finalizer, typename T, typename Hint>
1243
+ inline void Object::AddFinalizer(Finalizer finalizeCallback,
1244
+ T* data,
1245
+ Hint* finalizeHint) {
1246
+ details::FinalizeData<T, Finalizer, Hint>* finalizeData =
1247
+ new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
1248
+ napi_status status =
1249
+ details::AttachData(_env,
1250
+ *this,
1251
+ data,
1252
+ details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
1253
+ finalizeData);
1254
+ if (status != napi_ok) {
1255
+ delete finalizeData;
1256
+ NAPI_THROW_IF_FAILED_VOID(_env, status);
1257
+ }
1258
+ }
1259
+
1129
1260
  ////////////////////////////////////////////////////////////////////////////////
1130
1261
  // External class
1131
1262
  ////////////////////////////////////////////////////////////////////////////////
@@ -1238,7 +1369,7 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env, size_t byteLength) {
1238
1369
  napi_status status = napi_create_arraybuffer(env, byteLength, &data, &value);
1239
1370
  NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
1240
1371
 
1241
- return ArrayBuffer(env, value, data, byteLength);
1372
+ return ArrayBuffer(env, value);
1242
1373
  }
1243
1374
 
1244
1375
  inline ArrayBuffer ArrayBuffer::New(napi_env env,
@@ -1249,7 +1380,7 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
1249
1380
  env, externalData, byteLength, nullptr, nullptr, &value);
1250
1381
  NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
1251
1382
 
1252
- return ArrayBuffer(env, value, externalData, byteLength);
1383
+ return ArrayBuffer(env, value);
1253
1384
  }
1254
1385
 
1255
1386
  template <typename Finalizer>
@@ -1272,7 +1403,7 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
1272
1403
  NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
1273
1404
  }
1274
1405
 
1275
- return ArrayBuffer(env, value, externalData, byteLength);
1406
+ return ArrayBuffer(env, value);
1276
1407
  }
1277
1408
 
1278
1409
  template <typename Finalizer, typename Hint>
@@ -1296,38 +1427,28 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
1296
1427
  NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
1297
1428
  }
1298
1429
 
1299
- return ArrayBuffer(env, value, externalData, byteLength);
1430
+ return ArrayBuffer(env, value);
1300
1431
  }
1301
1432
 
1302
- inline ArrayBuffer::ArrayBuffer() : Object(), _data(nullptr), _length(0) {
1433
+ inline ArrayBuffer::ArrayBuffer() : Object() {
1303
1434
  }
1304
1435
 
1305
1436
  inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value)
1306
- : Object(env, value), _data(nullptr), _length(0) {
1307
- }
1308
-
1309
- inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value, void* data, size_t length)
1310
- : Object(env, value), _data(data), _length(length) {
1437
+ : Object(env, value) {
1311
1438
  }
1312
1439
 
1313
1440
  inline void* ArrayBuffer::Data() {
1314
- EnsureInfo();
1315
- return _data;
1441
+ void* data;
1442
+ napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr);
1443
+ NAPI_THROW_IF_FAILED(_env, status, nullptr);
1444
+ return data;
1316
1445
  }
1317
1446
 
1318
1447
  inline size_t ArrayBuffer::ByteLength() {
1319
- EnsureInfo();
1320
- return _length;
1321
- }
1322
-
1323
- inline void ArrayBuffer::EnsureInfo() const {
1324
- // The ArrayBuffer instance may have been constructed from a napi_value whose
1325
- // length/data are not yet known. Fetch and cache these values just once,
1326
- // since they can never change during the lifetime of the ArrayBuffer.
1327
- if (_data == nullptr) {
1328
- napi_status status = napi_get_arraybuffer_info(_env, _value, &_data, &_length);
1329
- NAPI_THROW_IF_FAILED_VOID(_env, status);
1330
- }
1448
+ size_t length;
1449
+ napi_status status = napi_get_arraybuffer_info(_env, _value, nullptr, &length);
1450
+ NAPI_THROW_IF_FAILED(_env, status, 0);
1451
+ return length;
1331
1452
  }
1332
1453
 
1333
1454
  ////////////////////////////////////////////////////////////////////////////////
@@ -1543,6 +1664,10 @@ inline uint8_t TypedArray::ElementSize() const {
1543
1664
  case napi_float32_array:
1544
1665
  return 4;
1545
1666
  case napi_float64_array:
1667
+ #if (NAPI_VERSION > 5)
1668
+ case napi_bigint64_array:
1669
+ case napi_biguint64_array:
1670
+ #endif // (NAPI_VERSION > 5)
1546
1671
  return 8;
1547
1672
  default:
1548
1673
  return 0;
@@ -1674,6 +1799,51 @@ CreateFunction(napi_env env,
1674
1799
  return status;
1675
1800
  }
1676
1801
 
1802
+ template <Function::VoidCallback cb>
1803
+ inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1804
+ napi_value result = nullptr;
1805
+ napi_status status = napi_create_function(
1806
+ env, utf8name, NAPI_AUTO_LENGTH,
1807
+ [](napi_env env, napi_callback_info info) {
1808
+ CallbackInfo callbackInfo(env, info);
1809
+ return details::WrapCallback([&] {
1810
+ cb(callbackInfo);
1811
+ return nullptr;
1812
+ });
1813
+ }, data, &result);
1814
+ NAPI_THROW_IF_FAILED(env, status, Function());
1815
+ return Function(env, result);
1816
+ }
1817
+
1818
+ template <Function::Callback cb>
1819
+ inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1820
+ napi_value result = nullptr;
1821
+ napi_status status = napi_create_function(
1822
+ env, utf8name, NAPI_AUTO_LENGTH,
1823
+ [](napi_env env, napi_callback_info info) {
1824
+ CallbackInfo callbackInfo(env, info);
1825
+ return details::WrapCallback([&] {
1826
+ return cb(callbackInfo);
1827
+ });
1828
+ }, data, &result);
1829
+ NAPI_THROW_IF_FAILED(env, status, Function());
1830
+ return Function(env, result);
1831
+ }
1832
+
1833
+ template <Function::VoidCallback cb>
1834
+ inline Function Function::New(napi_env env,
1835
+ const std::string& utf8name,
1836
+ void* data) {
1837
+ return Function::New<cb>(env, utf8name.c_str(), data);
1838
+ }
1839
+
1840
+ template <Function::Callback cb>
1841
+ inline Function Function::New(napi_env env,
1842
+ const std::string& utf8name,
1843
+ void* data) {
1844
+ return Function::New<cb>(env, utf8name.c_str(), data);
1845
+ }
1846
+
1677
1847
  template <typename Callable>
1678
1848
  inline Function Function::New(napi_env env,
1679
1849
  Callable cb,
@@ -1945,52 +2115,46 @@ inline void Buffer<T>::EnsureInfo() const {
1945
2115
  inline Error Error::New(napi_env env) {
1946
2116
  napi_status status;
1947
2117
  napi_value error = nullptr;
1948
-
2118
+ bool is_exception_pending;
1949
2119
  const napi_extended_error_info* info;
2120
+
2121
+ // We must retrieve the last error info before doing anything else, because
2122
+ // doing anything else will replace the last error info.
1950
2123
  status = napi_get_last_error_info(env, &info);
1951
2124
  NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info");
1952
2125
 
1953
- if (status == napi_ok) {
1954
- if (info->error_code == napi_pending_exception) {
1955
- status = napi_get_and_clear_last_exception(env, &error);
1956
- NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
1957
- }
1958
- else {
1959
- const char* error_message = info->error_message != nullptr ?
1960
- info->error_message : "Error in native callback";
1961
-
1962
- bool isExceptionPending;
1963
- status = napi_is_exception_pending(env, &isExceptionPending);
1964
- NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
1965
-
1966
- if (isExceptionPending) {
1967
- status = napi_get_and_clear_last_exception(env, &error);
1968
- NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
1969
- }
2126
+ status = napi_is_exception_pending(env, &is_exception_pending);
2127
+ NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
1970
2128
 
1971
- napi_value message;
1972
- status = napi_create_string_utf8(
1973
- env,
1974
- error_message,
1975
- std::strlen(error_message),
1976
- &message);
1977
- NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_string_utf8");
1978
-
1979
- if (status == napi_ok) {
1980
- switch (info->error_code) {
1981
- case napi_object_expected:
1982
- case napi_string_expected:
1983
- case napi_boolean_expected:
1984
- case napi_number_expected:
1985
- status = napi_create_type_error(env, nullptr, message, &error);
1986
- break;
1987
- default:
1988
- status = napi_create_error(env, nullptr, message, &error);
1989
- break;
1990
- }
1991
- NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
1992
- }
2129
+ // A pending exception takes precedence over any internal error status.
2130
+ if (is_exception_pending) {
2131
+ status = napi_get_and_clear_last_exception(env, &error);
2132
+ NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
2133
+ }
2134
+ else {
2135
+ const char* error_message = info->error_message != nullptr ?
2136
+ info->error_message : "Error in native callback";
2137
+
2138
+ napi_value message;
2139
+ status = napi_create_string_utf8(
2140
+ env,
2141
+ error_message,
2142
+ std::strlen(error_message),
2143
+ &message);
2144
+ NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_string_utf8");
2145
+
2146
+ switch (info->error_code) {
2147
+ case napi_object_expected:
2148
+ case napi_string_expected:
2149
+ case napi_boolean_expected:
2150
+ case napi_number_expected:
2151
+ status = napi_create_type_error(env, nullptr, message, &error);
2152
+ break;
2153
+ default:
2154
+ status = napi_create_error(env, nullptr, message, &error);
2155
+ break;
1993
2156
  }
2157
+ NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
1994
2158
  }
1995
2159
 
1996
2160
  return Error(env, error);
@@ -2032,7 +2196,7 @@ inline Error& Error::operator =(Error&& other) {
2032
2196
  inline Error::Error(const Error& other) : ObjectReference(other) {
2033
2197
  }
2034
2198
 
2035
- inline Error& Error::operator =(Error& other) {
2199
+ inline Error& Error::operator =(const Error& other) {
2036
2200
  Reset();
2037
2201
 
2038
2202
  _env = other.Env();
@@ -2644,6 +2808,108 @@ inline void CallbackInfo::SetData(void* data) {
2644
2808
  // PropertyDescriptor class
2645
2809
  ////////////////////////////////////////////////////////////////////////////////
2646
2810
 
2811
+ template <typename PropertyDescriptor::GetterCallback Getter>
2812
+ PropertyDescriptor
2813
+ PropertyDescriptor::Accessor(const char* utf8name,
2814
+ napi_property_attributes attributes,
2815
+ void* data) {
2816
+ napi_property_descriptor desc = napi_property_descriptor();
2817
+
2818
+ desc.utf8name = utf8name;
2819
+ desc.getter = &GetterCallbackWrapper<Getter>;
2820
+ desc.attributes = attributes;
2821
+ desc.data = data;
2822
+
2823
+ return desc;
2824
+ }
2825
+
2826
+ template <typename PropertyDescriptor::GetterCallback Getter>
2827
+ PropertyDescriptor
2828
+ PropertyDescriptor::Accessor(const std::string& utf8name,
2829
+ napi_property_attributes attributes,
2830
+ void* data) {
2831
+ return Accessor<Getter>(utf8name.c_str(), attributes, data);
2832
+ }
2833
+
2834
+ template <typename PropertyDescriptor::GetterCallback Getter>
2835
+ PropertyDescriptor
2836
+ PropertyDescriptor::Accessor(Name name,
2837
+ napi_property_attributes attributes,
2838
+ void* data) {
2839
+ napi_property_descriptor desc = napi_property_descriptor();
2840
+
2841
+ desc.name = name;
2842
+ desc.getter = &GetterCallbackWrapper<Getter>;
2843
+ desc.attributes = attributes;
2844
+ desc.data = data;
2845
+
2846
+ return desc;
2847
+ }
2848
+
2849
+ template <
2850
+ typename PropertyDescriptor::GetterCallback Getter,
2851
+ typename PropertyDescriptor::SetterCallback Setter>
2852
+ PropertyDescriptor
2853
+ PropertyDescriptor::Accessor(const char* utf8name,
2854
+ napi_property_attributes attributes,
2855
+ void* data) {
2856
+
2857
+ napi_property_descriptor desc = napi_property_descriptor();
2858
+
2859
+ desc.utf8name = utf8name;
2860
+ desc.getter = &GetterCallbackWrapper<Getter>;
2861
+ desc.setter = &SetterCallbackWrapper<Setter>;
2862
+ desc.attributes = attributes;
2863
+ desc.data = data;
2864
+
2865
+ return desc;
2866
+ }
2867
+
2868
+ template <
2869
+ typename PropertyDescriptor::GetterCallback Getter,
2870
+ typename PropertyDescriptor::SetterCallback Setter>
2871
+ PropertyDescriptor
2872
+ PropertyDescriptor::Accessor(const std::string& utf8name,
2873
+ napi_property_attributes attributes,
2874
+ void* data) {
2875
+ return Accessor<Getter, Setter>(utf8name.c_str(), attributes, data);
2876
+ }
2877
+
2878
+ template <
2879
+ typename PropertyDescriptor::GetterCallback Getter,
2880
+ typename PropertyDescriptor::SetterCallback Setter>
2881
+ PropertyDescriptor
2882
+ PropertyDescriptor::Accessor(Name name,
2883
+ napi_property_attributes attributes,
2884
+ void* data) {
2885
+ napi_property_descriptor desc = napi_property_descriptor();
2886
+
2887
+ desc.name = name;
2888
+ desc.getter = &GetterCallbackWrapper<Getter>;
2889
+ desc.setter = &SetterCallbackWrapper<Setter>;
2890
+ desc.attributes = attributes;
2891
+ desc.data = data;
2892
+
2893
+ return desc;
2894
+ }
2895
+
2896
+ template <typename PropertyDescriptor::GetterCallback Getter>
2897
+ napi_value
2898
+ PropertyDescriptor::GetterCallbackWrapper(napi_env env,
2899
+ napi_callback_info info) {
2900
+ CallbackInfo cbInfo(env, info);
2901
+ return Getter(cbInfo);
2902
+ }
2903
+
2904
+ template <typename PropertyDescriptor::SetterCallback Setter>
2905
+ napi_value
2906
+ PropertyDescriptor::SetterCallbackWrapper(napi_env env,
2907
+ napi_callback_info info) {
2908
+ CallbackInfo cbInfo(env, info);
2909
+ Setter(cbInfo);
2910
+ return nullptr;
2911
+ }
2912
+
2647
2913
  template <typename Getter>
2648
2914
  inline PropertyDescriptor
2649
2915
  PropertyDescriptor::Accessor(Napi::Env env,
@@ -2880,14 +3146,27 @@ inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
2880
3146
  napi_value wrapper = callbackInfo.This();
2881
3147
  napi_status status;
2882
3148
  napi_ref ref;
2883
- T* instance = static_cast<T*>(this);
2884
- status = napi_wrap(env, wrapper, instance, FinalizeCallback, nullptr, &ref);
3149
+ status = napi_wrap(env, wrapper, this, FinalizeCallback, nullptr, &ref);
2885
3150
  NAPI_THROW_IF_FAILED_VOID(env, status);
2886
3151
 
2887
- Reference<Object>* instanceRef = instance;
3152
+ Reference<Object>* instanceRef = this;
2888
3153
  *instanceRef = Reference<Object>(env, ref);
2889
3154
  }
2890
3155
 
3156
+ template <typename T>
3157
+ inline ObjectWrap<T>::~ObjectWrap() {
3158
+ // If the JS object still exists at this point, remove the finalizer added
3159
+ // through `napi_wrap()`.
3160
+ if (!IsEmpty()) {
3161
+ Object object = Value();
3162
+ // It is not valid to call `napi_remove_wrap()` with an empty `object`.
3163
+ // This happens e.g. during garbage collection.
3164
+ if (!object.IsEmpty() && _construction_failed) {
3165
+ napi_remove_wrap(Env(), object, nullptr);
3166
+ }
3167
+ }
3168
+ }
3169
+
2891
3170
  template<typename T>
2892
3171
  inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
2893
3172
  T* unwrapped;
@@ -3075,6 +3354,62 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3075
3354
  return desc;
3076
3355
  }
3077
3356
 
3357
+ template <typename T>
3358
+ template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3359
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3360
+ const char* utf8name,
3361
+ napi_property_attributes attributes,
3362
+ void* data) {
3363
+ napi_property_descriptor desc = napi_property_descriptor();
3364
+ desc.utf8name = utf8name;
3365
+ desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3366
+ desc.data = data;
3367
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3368
+ return desc;
3369
+ }
3370
+
3371
+ template <typename T>
3372
+ template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3373
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3374
+ Symbol name,
3375
+ napi_property_attributes attributes,
3376
+ void* data) {
3377
+ napi_property_descriptor desc = napi_property_descriptor();
3378
+ desc.name = name;
3379
+ desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3380
+ desc.data = data;
3381
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3382
+ return desc;
3383
+ }
3384
+
3385
+ template <typename T>
3386
+ template <typename ObjectWrap<T>::StaticMethodCallback method>
3387
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3388
+ const char* utf8name,
3389
+ napi_property_attributes attributes,
3390
+ void* data) {
3391
+ napi_property_descriptor desc = napi_property_descriptor();
3392
+ desc.utf8name = utf8name;
3393
+ desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3394
+ desc.data = data;
3395
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3396
+ return desc;
3397
+ }
3398
+
3399
+ template <typename T>
3400
+ template <typename ObjectWrap<T>::StaticMethodCallback method>
3401
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3402
+ Symbol name,
3403
+ napi_property_attributes attributes,
3404
+ void* data) {
3405
+ napi_property_descriptor desc = napi_property_descriptor();
3406
+ desc.name = name;
3407
+ desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3408
+ desc.data = data;
3409
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3410
+ return desc;
3411
+ }
3412
+
3078
3413
  template <typename T>
3079
3414
  inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3080
3415
  const char* utf8name,
@@ -3113,6 +3448,38 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3113
3448
  return desc;
3114
3449
  }
3115
3450
 
3451
+ template <typename T>
3452
+ template <typename ObjectWrap<T>::StaticGetterCallback getter,
3453
+ typename ObjectWrap<T>::StaticSetterCallback setter>
3454
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3455
+ const char* utf8name,
3456
+ napi_property_attributes attributes,
3457
+ void* data) {
3458
+ napi_property_descriptor desc = napi_property_descriptor();
3459
+ desc.utf8name = utf8name;
3460
+ desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
3461
+ desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3462
+ desc.data = data;
3463
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3464
+ return desc;
3465
+ }
3466
+
3467
+ template <typename T>
3468
+ template <typename ObjectWrap<T>::StaticGetterCallback getter,
3469
+ typename ObjectWrap<T>::StaticSetterCallback setter>
3470
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3471
+ Symbol name,
3472
+ napi_property_attributes attributes,
3473
+ void* data) {
3474
+ napi_property_descriptor desc = napi_property_descriptor();
3475
+ desc.name = name;
3476
+ desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
3477
+ desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3478
+ desc.data = data;
3479
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3480
+ return desc;
3481
+ }
3482
+
3116
3483
  template <typename T>
3117
3484
  inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3118
3485
  const char* utf8name,
@@ -3179,6 +3546,62 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3179
3546
  return desc;
3180
3547
  }
3181
3548
 
3549
+ template <typename T>
3550
+ template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3551
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3552
+ const char* utf8name,
3553
+ napi_property_attributes attributes,
3554
+ void* data) {
3555
+ napi_property_descriptor desc = napi_property_descriptor();
3556
+ desc.utf8name = utf8name;
3557
+ desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3558
+ desc.data = data;
3559
+ desc.attributes = attributes;
3560
+ return desc;
3561
+ }
3562
+
3563
+ template <typename T>
3564
+ template <typename ObjectWrap<T>::InstanceMethodCallback method>
3565
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3566
+ const char* utf8name,
3567
+ napi_property_attributes attributes,
3568
+ void* data) {
3569
+ napi_property_descriptor desc = napi_property_descriptor();
3570
+ desc.utf8name = utf8name;
3571
+ desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3572
+ desc.data = data;
3573
+ desc.attributes = attributes;
3574
+ return desc;
3575
+ }
3576
+
3577
+ template <typename T>
3578
+ template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3579
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3580
+ Symbol name,
3581
+ napi_property_attributes attributes,
3582
+ void* data) {
3583
+ napi_property_descriptor desc = napi_property_descriptor();
3584
+ desc.name = name;
3585
+ desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3586
+ desc.data = data;
3587
+ desc.attributes = attributes;
3588
+ return desc;
3589
+ }
3590
+
3591
+ template <typename T>
3592
+ template <typename ObjectWrap<T>::InstanceMethodCallback method>
3593
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3594
+ Symbol name,
3595
+ napi_property_attributes attributes,
3596
+ void* data) {
3597
+ napi_property_descriptor desc = napi_property_descriptor();
3598
+ desc.name = name;
3599
+ desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3600
+ desc.data = data;
3601
+ desc.attributes = attributes;
3602
+ return desc;
3603
+ }
3604
+
3182
3605
  template <typename T>
3183
3606
  inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3184
3607
  const char* utf8name,
@@ -3217,6 +3640,38 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3217
3640
  return desc;
3218
3641
  }
3219
3642
 
3643
+ template <typename T>
3644
+ template <typename ObjectWrap<T>::InstanceGetterCallback getter,
3645
+ typename ObjectWrap<T>::InstanceSetterCallback setter>
3646
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3647
+ const char* utf8name,
3648
+ napi_property_attributes attributes,
3649
+ void* data) {
3650
+ napi_property_descriptor desc = napi_property_descriptor();
3651
+ desc.utf8name = utf8name;
3652
+ desc.getter = This::WrapGetter(This::GetterTag<getter>());
3653
+ desc.setter = This::WrapSetter(This::SetterTag<setter>());
3654
+ desc.data = data;
3655
+ desc.attributes = attributes;
3656
+ return desc;
3657
+ }
3658
+
3659
+ template <typename T>
3660
+ template <typename ObjectWrap<T>::InstanceGetterCallback getter,
3661
+ typename ObjectWrap<T>::InstanceSetterCallback setter>
3662
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3663
+ Symbol name,
3664
+ napi_property_attributes attributes,
3665
+ void* data) {
3666
+ napi_property_descriptor desc = napi_property_descriptor();
3667
+ desc.name = name;
3668
+ desc.getter = This::WrapGetter(This::GetterTag<getter>());
3669
+ desc.setter = This::WrapSetter(This::SetterTag<setter>());
3670
+ desc.data = data;
3671
+ desc.attributes = attributes;
3672
+ return desc;
3673
+ }
3674
+
3220
3675
  template <typename T>
3221
3676
  inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(const char* utf8name,
3222
3677
  Napi::Value value, napi_property_attributes attributes) {
@@ -3261,6 +3716,9 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
3261
3716
  return desc;
3262
3717
  }
3263
3718
 
3719
+ template <typename T>
3720
+ inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}
3721
+
3264
3722
  template <typename T>
3265
3723
  inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
3266
3724
  napi_env env,
@@ -3275,10 +3733,21 @@ inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
3275
3733
  return nullptr;
3276
3734
  }
3277
3735
 
3278
- T* instance;
3279
3736
  napi_value wrapper = details::WrapCallback([&] {
3280
3737
  CallbackInfo callbackInfo(env, info);
3281
- instance = new T(callbackInfo);
3738
+ T* instance = new T(callbackInfo);
3739
+ #ifdef NAPI_CPP_EXCEPTIONS
3740
+ instance->_construction_failed = false;
3741
+ #else
3742
+ if (callbackInfo.Env().IsExceptionPending()) {
3743
+ // We need to clear the exception so that removing the wrap might work.
3744
+ Error e = callbackInfo.Env().GetAndClearPendingException();
3745
+ delete instance;
3746
+ e.ThrowAsJavaScriptException();
3747
+ } else {
3748
+ instance->_construction_failed = false;
3749
+ }
3750
+ # endif // NAPI_CPP_EXCEPTIONS
3282
3751
  return callbackInfo.This();
3283
3752
  });
3284
3753
 
@@ -3402,11 +3871,71 @@ inline napi_value ObjectWrap<T>::InstanceSetterCallbackWrapper(
3402
3871
  }
3403
3872
 
3404
3873
  template <typename T>
3405
- inline void ObjectWrap<T>::FinalizeCallback(napi_env /*env*/, void* data, void* /*hint*/) {
3406
- T* instance = reinterpret_cast<T*>(data);
3874
+ inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hint*/) {
3875
+ ObjectWrap<T>* instance = static_cast<ObjectWrap<T>*>(data);
3876
+ instance->Finalize(Napi::Env(env));
3407
3877
  delete instance;
3408
3878
  }
3409
3879
 
3880
+ template <typename T>
3881
+ template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3882
+ inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3883
+ return details::WrapCallback([&] {
3884
+ method(CallbackInfo(env, info));
3885
+ return nullptr;
3886
+ });
3887
+ }
3888
+
3889
+ template <typename T>
3890
+ template <typename ObjectWrap<T>::StaticMethodCallback method>
3891
+ inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3892
+ return details::WrapCallback([&] {
3893
+ return method(CallbackInfo(env, info));
3894
+ });
3895
+ }
3896
+
3897
+ template <typename T>
3898
+ template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3899
+ inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3900
+ return details::WrapCallback([&] {
3901
+ const CallbackInfo cbInfo(env, info);
3902
+ T* instance = Unwrap(cbInfo.This().As<Object>());
3903
+ (instance->*method)(cbInfo);
3904
+ return nullptr;
3905
+ });
3906
+ }
3907
+
3908
+ template <typename T>
3909
+ template <typename ObjectWrap<T>::InstanceMethodCallback method>
3910
+ inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3911
+ return details::WrapCallback([&] {
3912
+ const CallbackInfo cbInfo(env, info);
3913
+ T* instance = Unwrap(cbInfo.This().As<Object>());
3914
+ return (instance->*method)(cbInfo);
3915
+ });
3916
+ }
3917
+
3918
+ template <typename T>
3919
+ template <typename ObjectWrap<T>::StaticSetterCallback method>
3920
+ inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3921
+ return details::WrapCallback([&] {
3922
+ const CallbackInfo cbInfo(env, info);
3923
+ method(cbInfo, cbInfo[0]);
3924
+ return nullptr;
3925
+ });
3926
+ }
3927
+
3928
+ template <typename T>
3929
+ template <typename ObjectWrap<T>::InstanceSetterCallback method>
3930
+ inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3931
+ return details::WrapCallback([&] {
3932
+ const CallbackInfo cbInfo(env, info);
3933
+ T* instance = Unwrap(cbInfo.This().As<Object>());
3934
+ (instance->*method)(cbInfo, cbInfo[0]);
3935
+ return nullptr;
3936
+ });
3937
+ }
3938
+
3410
3939
  ////////////////////////////////////////////////////////////////////////////////
3411
3940
  // HandleScope class
3412
3941
  ////////////////////////////////////////////////////////////////////////////////
@@ -3421,7 +3950,10 @@ inline HandleScope::HandleScope(Napi::Env env) : _env(env) {
3421
3950
  }
3422
3951
 
3423
3952
  inline HandleScope::~HandleScope() {
3424
- napi_close_handle_scope(_env, _scope);
3953
+ napi_status status = napi_close_handle_scope(_env, _scope);
3954
+ NAPI_FATAL_IF_FAILED(status,
3955
+ "HandleScope::~HandleScope",
3956
+ "napi_close_handle_scope");
3425
3957
  }
3426
3958
 
3427
3959
  inline HandleScope::operator napi_handle_scope() const {
@@ -3446,7 +3978,10 @@ inline EscapableHandleScope::EscapableHandleScope(Napi::Env env) : _env(env) {
3446
3978
  }
3447
3979
 
3448
3980
  inline EscapableHandleScope::~EscapableHandleScope() {
3449
- napi_close_escapable_handle_scope(_env, _scope);
3981
+ napi_status status = napi_close_escapable_handle_scope(_env, _scope);
3982
+ NAPI_FATAL_IF_FAILED(status,
3983
+ "EscapableHandleScope::~EscapableHandleScope",
3984
+ "napi_close_escapable_handle_scope");
3450
3985
  }
3451
3986
 
3452
3987
  inline EscapableHandleScope::operator napi_escapable_handle_scope() const {
@@ -3482,7 +4017,10 @@ inline CallbackScope::CallbackScope(napi_env env, napi_async_context context)
3482
4017
  }
3483
4018
 
3484
4019
  inline CallbackScope::~CallbackScope() {
3485
- napi_close_callback_scope(_env, _scope);
4020
+ napi_status status = napi_close_callback_scope(_env, _scope);
4021
+ NAPI_FATAL_IF_FAILED(status,
4022
+ "CallbackScope::~CallbackScope",
4023
+ "napi_close_callback_scope");
3486
4024
  }
3487
4025
 
3488
4026
  inline CallbackScope::operator napi_callback_scope() const {
@@ -3542,6 +4080,10 @@ inline AsyncContext::operator napi_async_context() const {
3542
4080
  return _context;
3543
4081
  }
3544
4082
 
4083
+ inline Napi::Env AsyncContext::Env() const {
4084
+ return Napi::Env(_env);
4085
+ }
4086
+
3545
4087
  ////////////////////////////////////////////////////////////////////////////////
3546
4088
  // AsyncWorker class
3547
4089
  ////////////////////////////////////////////////////////////////////////////////
@@ -3591,8 +4133,8 @@ inline AsyncWorker::AsyncWorker(const Object& receiver,
3591
4133
  _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
3592
4134
  NAPI_THROW_IF_FAILED_VOID(_env, status);
3593
4135
 
3594
- status = napi_create_async_work(_env, resource, resource_id, OnExecute,
3595
- OnWorkComplete, this, &_work);
4136
+ status = napi_create_async_work(_env, resource, resource_id, OnAsyncWorkExecute,
4137
+ OnAsyncWorkComplete, this, &_work);
3596
4138
  NAPI_THROW_IF_FAILED_VOID(_env, status);
3597
4139
  }
3598
4140
 
@@ -3617,8 +4159,8 @@ inline AsyncWorker::AsyncWorker(Napi::Env env,
3617
4159
  _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
3618
4160
  NAPI_THROW_IF_FAILED_VOID(_env, status);
3619
4161
 
3620
- status = napi_create_async_work(_env, resource, resource_id, OnExecute,
3621
- OnWorkComplete, this, &_work);
4162
+ status = napi_create_async_work(_env, resource, resource_id, OnAsyncWorkExecute,
4163
+ OnAsyncWorkComplete, this, &_work);
3622
4164
  NAPI_THROW_IF_FAILED_VOID(_env, status);
3623
4165
  }
3624
4166
 
@@ -3705,40 +4247,51 @@ inline void AsyncWorker::SetError(const std::string& error) {
3705
4247
  inline std::vector<napi_value> AsyncWorker::GetResult(Napi::Env /*env*/) {
3706
4248
  return {};
3707
4249
  }
4250
+ // The OnAsyncWorkExecute method receives an napi_env argument. However, do NOT
4251
+ // use it within this method, as it does not run on the JavaScript thread and
4252
+ // must not run any method that would cause JavaScript to run. In practice,
4253
+ // this means that almost any use of napi_env will be incorrect.
4254
+ inline void AsyncWorker::OnAsyncWorkExecute(napi_env env, void* asyncworker) {
4255
+ AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
4256
+ self->OnExecute(env);
4257
+ }
3708
4258
  // The OnExecute method receives an napi_env argument. However, do NOT
3709
- // use it within this method, as it does not run on the main thread and must
3710
- // not run any method that would cause JavaScript to run. In practice, this
3711
- // means that almost any use of napi_env will be incorrect.
3712
- inline void AsyncWorker::OnExecute(napi_env /*DO_NOT_USE*/, void* this_pointer) {
3713
- AsyncWorker* self = static_cast<AsyncWorker*>(this_pointer);
4259
+ // use it within this method, as it does not run on the JavaScript thread and
4260
+ // must not run any method that would cause JavaScript to run. In practice,
4261
+ // this means that almost any use of napi_env will be incorrect.
4262
+ inline void AsyncWorker::OnExecute(Napi::Env /*DO_NOT_USE*/) {
3714
4263
  #ifdef NAPI_CPP_EXCEPTIONS
3715
4264
  try {
3716
- self->Execute();
4265
+ Execute();
3717
4266
  } catch (const std::exception& e) {
3718
- self->SetError(e.what());
4267
+ SetError(e.what());
3719
4268
  }
3720
4269
  #else // NAPI_CPP_EXCEPTIONS
3721
- self->Execute();
4270
+ Execute();
3722
4271
  #endif // NAPI_CPP_EXCEPTIONS
3723
4272
  }
3724
4273
 
3725
- inline void AsyncWorker::OnWorkComplete(
3726
- napi_env /*env*/, napi_status status, void* this_pointer) {
3727
- AsyncWorker* self = static_cast<AsyncWorker*>(this_pointer);
4274
+ inline void AsyncWorker::OnAsyncWorkComplete(napi_env env,
4275
+ napi_status status,
4276
+ void* asyncworker) {
4277
+ AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
4278
+ self->OnWorkComplete(env, status);
4279
+ }
4280
+ inline void AsyncWorker::OnWorkComplete(Napi::Env /*env*/, napi_status status) {
3728
4281
  if (status != napi_cancelled) {
3729
- HandleScope scope(self->_env);
4282
+ HandleScope scope(_env);
3730
4283
  details::WrapCallback([&] {
3731
- if (self->_error.size() == 0) {
3732
- self->OnOK();
4284
+ if (_error.size() == 0) {
4285
+ OnOK();
3733
4286
  }
3734
4287
  else {
3735
- self->OnError(Error::New(self->_env, self->_error));
4288
+ OnError(Error::New(_env, _error));
3736
4289
  }
3737
4290
  return nullptr;
3738
4291
  });
3739
4292
  }
3740
- if (!self->_suppress_destruct) {
3741
- self->Destroy();
4293
+ if (!_suppress_destruct) {
4294
+ Destroy();
3742
4295
  }
3743
4296
  }
3744
4297
 
@@ -3919,35 +4472,28 @@ inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
3919
4472
  }
3920
4473
 
3921
4474
  inline ThreadSafeFunction::ThreadSafeFunction()
3922
- : _tsfn(new napi_threadsafe_function(nullptr)) {
4475
+ : _tsfn() {
3923
4476
  }
3924
4477
 
3925
4478
  inline ThreadSafeFunction::ThreadSafeFunction(
3926
4479
  napi_threadsafe_function tsfn)
3927
- : _tsfn(new napi_threadsafe_function(tsfn)) {
4480
+ : _tsfn(tsfn) {
3928
4481
  }
3929
4482
 
3930
- inline ThreadSafeFunction::ThreadSafeFunction(ThreadSafeFunction&& other)
3931
- : _tsfn(std::move(other._tsfn)) {
3932
- other._tsfn.reset();
3933
- }
3934
-
3935
- inline ThreadSafeFunction& ThreadSafeFunction::operator =(
3936
- ThreadSafeFunction&& other) {
3937
- if (*_tsfn != nullptr) {
3938
- Error::Fatal("ThreadSafeFunction::operator =",
3939
- "You cannot assign a new TSFN because existing one is still alive.");
3940
- return *this;
3941
- }
3942
- _tsfn = std::move(other._tsfn);
3943
- other._tsfn.reset();
3944
- return *this;
4483
+ inline ThreadSafeFunction::operator napi_threadsafe_function() const {
4484
+ return _tsfn;
3945
4485
  }
3946
4486
 
3947
4487
  inline napi_status ThreadSafeFunction::BlockingCall() const {
3948
4488
  return CallInternal(nullptr, napi_tsfn_blocking);
3949
4489
  }
3950
4490
 
4491
+ template <>
4492
+ inline napi_status ThreadSafeFunction::BlockingCall(
4493
+ void* data) const {
4494
+ return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_blocking);
4495
+ }
4496
+
3951
4497
  template <typename Callback>
3952
4498
  inline napi_status ThreadSafeFunction::BlockingCall(
3953
4499
  Callback callback) const {
@@ -3967,6 +4513,12 @@ inline napi_status ThreadSafeFunction::NonBlockingCall() const {
3967
4513
  return CallInternal(nullptr, napi_tsfn_nonblocking);
3968
4514
  }
3969
4515
 
4516
+ template <>
4517
+ inline napi_status ThreadSafeFunction::NonBlockingCall(
4518
+ void* data) const {
4519
+ return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_nonblocking);
4520
+ }
4521
+
3970
4522
  template <typename Callback>
3971
4523
  inline napi_status ThreadSafeFunction::NonBlockingCall(
3972
4524
  Callback callback) const {
@@ -3982,22 +4534,37 @@ inline napi_status ThreadSafeFunction::NonBlockingCall(
3982
4534
  return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_nonblocking);
3983
4535
  }
3984
4536
 
4537
+ inline void ThreadSafeFunction::Ref(napi_env env) const {
4538
+ if (_tsfn != nullptr) {
4539
+ napi_status status = napi_ref_threadsafe_function(env, _tsfn);
4540
+ NAPI_THROW_IF_FAILED_VOID(env, status);
4541
+ }
4542
+ }
4543
+
4544
+ inline void ThreadSafeFunction::Unref(napi_env env) const {
4545
+ if (_tsfn != nullptr) {
4546
+ napi_status status = napi_unref_threadsafe_function(env, _tsfn);
4547
+ NAPI_THROW_IF_FAILED_VOID(env, status);
4548
+ }
4549
+ }
4550
+
3985
4551
  inline napi_status ThreadSafeFunction::Acquire() const {
3986
- return napi_acquire_threadsafe_function(*_tsfn);
4552
+ return napi_acquire_threadsafe_function(_tsfn);
3987
4553
  }
3988
4554
 
3989
4555
  inline napi_status ThreadSafeFunction::Release() {
3990
- return napi_release_threadsafe_function(*_tsfn, napi_tsfn_release);
4556
+ return napi_release_threadsafe_function(_tsfn, napi_tsfn_release);
3991
4557
  }
3992
4558
 
3993
4559
  inline napi_status ThreadSafeFunction::Abort() {
3994
- return napi_release_threadsafe_function(*_tsfn, napi_tsfn_abort);
4560
+ return napi_release_threadsafe_function(_tsfn, napi_tsfn_abort);
3995
4561
  }
3996
4562
 
3997
4563
  inline ThreadSafeFunction::ConvertibleContext
3998
4564
  ThreadSafeFunction::GetContext() const {
3999
4565
  void* context;
4000
- napi_get_threadsafe_function_context(*_tsfn, &context);
4566
+ napi_status status = napi_get_threadsafe_function_context(_tsfn, &context);
4567
+ NAPI_FATAL_IF_FAILED(status, "ThreadSafeFunction::GetContext", "napi_get_threadsafe_function_context");
4001
4568
  return ConvertibleContext({ context });
4002
4569
  }
4003
4570
 
@@ -4020,10 +4587,10 @@ inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
4020
4587
 
4021
4588
  ThreadSafeFunction tsfn;
4022
4589
  auto* finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
4023
- FinalizerDataType>({ data, finalizeCallback, tsfn._tsfn.get() });
4590
+ FinalizerDataType>({ data, finalizeCallback });
4024
4591
  napi_status status = napi_create_threadsafe_function(env, callback, resource,
4025
4592
  Value::From(env, resourceName), maxQueueSize, initialThreadCount,
4026
- finalizeData, wrapper, context, CallJS, tsfn._tsfn.get());
4593
+ finalizeData, wrapper, context, CallJS, &tsfn._tsfn);
4027
4594
  if (status != napi_ok) {
4028
4595
  delete finalizeData;
4029
4596
  NAPI_THROW_IF_FAILED(env, status, ThreadSafeFunction());
@@ -4036,7 +4603,7 @@ inline napi_status ThreadSafeFunction::CallInternal(
4036
4603
  CallbackWrapper* callbackWrapper,
4037
4604
  napi_threadsafe_function_call_mode mode) const {
4038
4605
  napi_status status = napi_call_threadsafe_function(
4039
- *_tsfn, callbackWrapper, mode);
4606
+ _tsfn, callbackWrapper, mode);
4040
4607
  if (status != napi_ok && callbackWrapper != nullptr) {
4041
4608
  delete callbackWrapper;
4042
4609
  }
@@ -4061,6 +4628,340 @@ inline void ThreadSafeFunction::CallJS(napi_env env,
4061
4628
  Function(env, jsCallback).Call({});
4062
4629
  }
4063
4630
  }
4631
+
4632
+ ////////////////////////////////////////////////////////////////////////////////
4633
+ // Async Progress Worker Base class
4634
+ ////////////////////////////////////////////////////////////////////////////////
4635
+ template <typename DataType>
4636
+ inline AsyncProgressWorkerBase<DataType>::AsyncProgressWorkerBase(const Object& receiver,
4637
+ const Function& callback,
4638
+ const char* resource_name,
4639
+ const Object& resource,
4640
+ size_t queue_size)
4641
+ : AsyncWorker(receiver, callback, resource_name, resource) {
4642
+ // Fill all possible arguments to work around ambiguous ThreadSafeFunction::New signatures.
4643
+ _tsfn = ThreadSafeFunction::New(callback.Env(),
4644
+ callback,
4645
+ resource,
4646
+ resource_name,
4647
+ queue_size,
4648
+ /** initialThreadCount */ 1,
4649
+ /** context */ this,
4650
+ OnThreadSafeFunctionFinalize,
4651
+ /** finalizeData */ this);
4652
+ }
4653
+
4654
+ #if NAPI_VERSION > 4
4655
+ template <typename DataType>
4656
+ inline AsyncProgressWorkerBase<DataType>::AsyncProgressWorkerBase(Napi::Env env,
4657
+ const char* resource_name,
4658
+ const Object& resource,
4659
+ size_t queue_size)
4660
+ : AsyncWorker(env, resource_name, resource) {
4661
+ // TODO: Once the changes to make the callback optional for threadsafe
4662
+ // functions are available on all versions we can remove the dummy Function here.
4663
+ Function callback;
4664
+ // Fill all possible arguments to work around ambiguous ThreadSafeFunction::New signatures.
4665
+ _tsfn = ThreadSafeFunction::New(env,
4666
+ callback,
4667
+ resource,
4668
+ resource_name,
4669
+ queue_size,
4670
+ /** initialThreadCount */ 1,
4671
+ /** context */ this,
4672
+ OnThreadSafeFunctionFinalize,
4673
+ /** finalizeData */ this);
4674
+ }
4675
+ #endif
4676
+
4677
+ template<typename DataType>
4678
+ inline AsyncProgressWorkerBase<DataType>::~AsyncProgressWorkerBase() {
4679
+ // Abort pending tsfn call.
4680
+ // Don't send progress events after we've already completed.
4681
+ // It's ok to call ThreadSafeFunction::Abort and ThreadSafeFunction::Release duplicated.
4682
+ _tsfn.Abort();
4683
+ }
4684
+
4685
+ template <typename DataType>
4686
+ inline void AsyncProgressWorkerBase<DataType>::OnAsyncWorkProgress(Napi::Env /* env */,
4687
+ Napi::Function /* jsCallback */,
4688
+ void* data) {
4689
+ ThreadSafeData* tsd = static_cast<ThreadSafeData*>(data);
4690
+ tsd->asyncprogressworker()->OnWorkProgress(tsd->data());
4691
+ }
4692
+
4693
+ template <typename DataType>
4694
+ inline napi_status AsyncProgressWorkerBase<DataType>::NonBlockingCall(DataType* data) {
4695
+ auto tsd = new AsyncProgressWorkerBase::ThreadSafeData(this, data);
4696
+ return _tsfn.NonBlockingCall(tsd, OnAsyncWorkProgress);
4697
+ }
4698
+
4699
+ template <typename DataType>
4700
+ inline void AsyncProgressWorkerBase<DataType>::OnWorkComplete(Napi::Env /* env */, napi_status status) {
4701
+ _work_completed = true;
4702
+ _complete_status = status;
4703
+ _tsfn.Release();
4704
+ }
4705
+
4706
+ template <typename DataType>
4707
+ inline void AsyncProgressWorkerBase<DataType>::OnThreadSafeFunctionFinalize(Napi::Env env, void* /* data */, AsyncProgressWorkerBase* context) {
4708
+ if (context->_work_completed) {
4709
+ context->AsyncWorker::OnWorkComplete(env, context->_complete_status);
4710
+ }
4711
+ }
4712
+
4713
+ ////////////////////////////////////////////////////////////////////////////////
4714
+ // Async Progress Worker class
4715
+ ////////////////////////////////////////////////////////////////////////////////
4716
+ template<class T>
4717
+ inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback)
4718
+ : AsyncProgressWorker(callback, "generic") {
4719
+ }
4720
+
4721
+ template<class T>
4722
+ inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
4723
+ const char* resource_name)
4724
+ : AsyncProgressWorker(callback, resource_name, Object::New(callback.Env())) {
4725
+ }
4726
+
4727
+ template<class T>
4728
+ inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
4729
+ const char* resource_name,
4730
+ const Object& resource)
4731
+ : AsyncProgressWorker(Object::New(callback.Env()),
4732
+ callback,
4733
+ resource_name,
4734
+ resource) {
4735
+ }
4736
+
4737
+ template<class T>
4738
+ inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
4739
+ const Function& callback)
4740
+ : AsyncProgressWorker(receiver, callback, "generic") {
4741
+ }
4742
+
4743
+ template<class T>
4744
+ inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
4745
+ const Function& callback,
4746
+ const char* resource_name)
4747
+ : AsyncProgressWorker(receiver,
4748
+ callback,
4749
+ resource_name,
4750
+ Object::New(callback.Env())) {
4751
+ }
4752
+
4753
+ template<class T>
4754
+ inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
4755
+ const Function& callback,
4756
+ const char* resource_name,
4757
+ const Object& resource)
4758
+ : AsyncProgressWorkerBase(receiver, callback, resource_name, resource),
4759
+ _asyncdata(nullptr),
4760
+ _asyncsize(0) {
4761
+ }
4762
+
4763
+ #if NAPI_VERSION > 4
4764
+ template<class T>
4765
+ inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env)
4766
+ : AsyncProgressWorker(env, "generic") {
4767
+ }
4768
+
4769
+ template<class T>
4770
+ inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
4771
+ const char* resource_name)
4772
+ : AsyncProgressWorker(env, resource_name, Object::New(env)) {
4773
+ }
4774
+
4775
+ template<class T>
4776
+ inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
4777
+ const char* resource_name,
4778
+ const Object& resource)
4779
+ : AsyncProgressWorkerBase(env, resource_name, resource),
4780
+ _asyncdata(nullptr),
4781
+ _asyncsize(0) {
4782
+ }
4783
+ #endif
4784
+
4785
+ template<class T>
4786
+ inline AsyncProgressWorker<T>::~AsyncProgressWorker() {
4787
+ {
4788
+ std::lock_guard<std::mutex> lock(this->_mutex);
4789
+ _asyncdata = nullptr;
4790
+ _asyncsize = 0;
4791
+ }
4792
+ }
4793
+
4794
+ template<class T>
4795
+ inline void AsyncProgressWorker<T>::Execute() {
4796
+ ExecutionProgress progress(this);
4797
+ Execute(progress);
4798
+ }
4799
+
4800
+ template<class T>
4801
+ inline void AsyncProgressWorker<T>::OnWorkProgress(void*) {
4802
+ T* data;
4803
+ size_t size;
4804
+ {
4805
+ std::lock_guard<std::mutex> lock(this->_mutex);
4806
+ data = this->_asyncdata;
4807
+ size = this->_asyncsize;
4808
+ this->_asyncdata = nullptr;
4809
+ this->_asyncsize = 0;
4810
+ }
4811
+
4812
+ this->OnProgress(data, size);
4813
+ delete[] data;
4814
+ }
4815
+
4816
+ template<class T>
4817
+ inline void AsyncProgressWorker<T>::SendProgress_(const T* data, size_t count) {
4818
+ T* new_data = new T[count];
4819
+ std::copy(data, data + count, new_data);
4820
+
4821
+ T* old_data;
4822
+ {
4823
+ std::lock_guard<std::mutex> lock(this->_mutex);
4824
+ old_data = _asyncdata;
4825
+ _asyncdata = new_data;
4826
+ _asyncsize = count;
4827
+ }
4828
+ this->NonBlockingCall(nullptr);
4829
+
4830
+ delete[] old_data;
4831
+ }
4832
+
4833
+ template<class T>
4834
+ inline void AsyncProgressWorker<T>::Signal() const {
4835
+ this->NonBlockingCall(static_cast<T*>(nullptr));
4836
+ }
4837
+
4838
+ template<class T>
4839
+ inline void AsyncProgressWorker<T>::ExecutionProgress::Signal() const {
4840
+ _worker->Signal();
4841
+ }
4842
+
4843
+ template<class T>
4844
+ inline void AsyncProgressWorker<T>::ExecutionProgress::Send(const T* data, size_t count) const {
4845
+ _worker->SendProgress_(data, count);
4846
+ }
4847
+
4848
+ ////////////////////////////////////////////////////////////////////////////////
4849
+ // Async Progress Queue Worker class
4850
+ ////////////////////////////////////////////////////////////////////////////////
4851
+ template<class T>
4852
+ inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback)
4853
+ : AsyncProgressQueueWorker(callback, "generic") {
4854
+ }
4855
+
4856
+ template<class T>
4857
+ inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback,
4858
+ const char* resource_name)
4859
+ : AsyncProgressQueueWorker(callback, resource_name, Object::New(callback.Env())) {
4860
+ }
4861
+
4862
+ template<class T>
4863
+ inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback,
4864
+ const char* resource_name,
4865
+ const Object& resource)
4866
+ : AsyncProgressQueueWorker(Object::New(callback.Env()),
4867
+ callback,
4868
+ resource_name,
4869
+ resource) {
4870
+ }
4871
+
4872
+ template<class T>
4873
+ inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
4874
+ const Function& callback)
4875
+ : AsyncProgressQueueWorker(receiver, callback, "generic") {
4876
+ }
4877
+
4878
+ template<class T>
4879
+ inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
4880
+ const Function& callback,
4881
+ const char* resource_name)
4882
+ : AsyncProgressQueueWorker(receiver,
4883
+ callback,
4884
+ resource_name,
4885
+ Object::New(callback.Env())) {
4886
+ }
4887
+
4888
+ template<class T>
4889
+ inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
4890
+ const Function& callback,
4891
+ const char* resource_name,
4892
+ const Object& resource)
4893
+ : AsyncProgressWorkerBase<std::pair<T*, size_t>>(receiver, callback, resource_name, resource, /** unlimited queue size */0) {
4894
+ }
4895
+
4896
+ #if NAPI_VERSION > 4
4897
+ template<class T>
4898
+ inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env)
4899
+ : AsyncProgressQueueWorker(env, "generic") {
4900
+ }
4901
+
4902
+ template<class T>
4903
+ inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env,
4904
+ const char* resource_name)
4905
+ : AsyncProgressQueueWorker(env, resource_name, Object::New(env)) {
4906
+ }
4907
+
4908
+ template<class T>
4909
+ inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env,
4910
+ const char* resource_name,
4911
+ const Object& resource)
4912
+ : AsyncProgressWorkerBase<std::pair<T*, size_t>>(env, resource_name, resource, /** unlimited queue size */0) {
4913
+ }
4914
+ #endif
4915
+
4916
+ template<class T>
4917
+ inline void AsyncProgressQueueWorker<T>::Execute() {
4918
+ ExecutionProgress progress(this);
4919
+ Execute(progress);
4920
+ }
4921
+
4922
+ template<class T>
4923
+ inline void AsyncProgressQueueWorker<T>::OnWorkProgress(std::pair<T*, size_t>* datapair) {
4924
+ if (datapair == nullptr) {
4925
+ return;
4926
+ }
4927
+
4928
+ T *data = datapair->first;
4929
+ size_t size = datapair->second;
4930
+
4931
+ this->OnProgress(data, size);
4932
+ delete datapair;
4933
+ delete[] data;
4934
+ }
4935
+
4936
+ template<class T>
4937
+ inline void AsyncProgressQueueWorker<T>::SendProgress_(const T* data, size_t count) {
4938
+ T* new_data = new T[count];
4939
+ std::copy(data, data + count, new_data);
4940
+
4941
+ auto pair = new std::pair<T*, size_t>(new_data, count);
4942
+ this->NonBlockingCall(pair);
4943
+ }
4944
+
4945
+ template<class T>
4946
+ inline void AsyncProgressQueueWorker<T>::Signal() const {
4947
+ this->NonBlockingCall(nullptr);
4948
+ }
4949
+
4950
+ template<class T>
4951
+ inline void AsyncProgressQueueWorker<T>::OnWorkComplete(Napi::Env env, napi_status status) {
4952
+ // Draining queued items in TSFN.
4953
+ AsyncProgressWorkerBase<std::pair<T*, size_t>>::OnWorkComplete(env, status);
4954
+ }
4955
+
4956
+ template<class T>
4957
+ inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Signal() const {
4958
+ _worker->Signal();
4959
+ }
4960
+
4961
+ template<class T>
4962
+ inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Send(const T* data, size_t count) const {
4963
+ _worker->SendProgress_(data, count);
4964
+ }
4064
4965
  #endif
4065
4966
 
4066
4967
  ////////////////////////////////////////////////////////////////////////////////