node-addon-api 3.0.0 → 3.2.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 (74) hide show
  1. package/CHANGELOG.md +242 -2
  2. package/README.md +106 -62
  3. package/common.gypi +1 -1
  4. package/index.js +5 -2
  5. package/napi-inl.deprecated.h +8 -8
  6. package/napi-inl.h +1221 -548
  7. package/napi.h +823 -524
  8. package/package-support.json +21 -0
  9. package/package.json +96 -4
  10. package/tools/README.md +8 -2
  11. package/tools/clang-format.js +67 -0
  12. package/tools/conversion.js +4 -4
  13. package/.editorconfig +0 -8
  14. package/.travis.yml +0 -59
  15. package/CODE_OF_CONDUCT.md +0 -4
  16. package/CONTRIBUTING.md +0 -66
  17. package/appveyor.yml +0 -48
  18. package/benchmark/README.md +0 -47
  19. package/benchmark/binding.gyp +0 -25
  20. package/benchmark/function_args.cc +0 -153
  21. package/benchmark/function_args.js +0 -52
  22. package/benchmark/index.js +0 -34
  23. package/benchmark/property_descriptor.cc +0 -60
  24. package/benchmark/property_descriptor.js +0 -29
  25. package/doc/Doxyfile +0 -2450
  26. package/doc/array_buffer.md +0 -129
  27. package/doc/async_context.md +0 -86
  28. package/doc/async_operations.md +0 -31
  29. package/doc/async_worker.md +0 -427
  30. package/doc/async_worker_variants.md +0 -456
  31. package/doc/basic_types.md +0 -423
  32. package/doc/bigint.md +0 -93
  33. package/doc/boolean.md +0 -64
  34. package/doc/buffer.md +0 -140
  35. package/doc/callback_scope.md +0 -54
  36. package/doc/callbackinfo.md +0 -97
  37. package/doc/checker-tool.md +0 -32
  38. package/doc/class_property_descriptor.md +0 -117
  39. package/doc/cmake-js.md +0 -68
  40. package/doc/conversion-tool.md +0 -28
  41. package/doc/creating_a_release.md +0 -62
  42. package/doc/dataview.md +0 -244
  43. package/doc/date.md +0 -68
  44. package/doc/env.md +0 -77
  45. package/doc/error.md +0 -115
  46. package/doc/error_handling.md +0 -186
  47. package/doc/escapable_handle_scope.md +0 -82
  48. package/doc/external.md +0 -59
  49. package/doc/function.md +0 -401
  50. package/doc/function_reference.md +0 -238
  51. package/doc/generator.md +0 -13
  52. package/doc/handle_scope.md +0 -65
  53. package/doc/memory_management.md +0 -27
  54. package/doc/node-gyp.md +0 -82
  55. package/doc/number.md +0 -163
  56. package/doc/object.md +0 -275
  57. package/doc/object_lifetime_management.md +0 -83
  58. package/doc/object_reference.md +0 -117
  59. package/doc/object_wrap.md +0 -833
  60. package/doc/prebuild_tools.md +0 -16
  61. package/doc/promises.md +0 -74
  62. package/doc/property_descriptor.md +0 -286
  63. package/doc/range_error.md +0 -59
  64. package/doc/reference.md +0 -111
  65. package/doc/setup.md +0 -81
  66. package/doc/string.md +0 -89
  67. package/doc/symbol.md +0 -44
  68. package/doc/threadsafe_function.md +0 -320
  69. package/doc/type_error.md +0 -59
  70. package/doc/typed_array.md +0 -74
  71. package/doc/typed_array_of.md +0 -133
  72. package/doc/value.md +0 -278
  73. package/doc/version_management.md +0 -43
  74. package/doc/working_with_javascript_values.md +0 -14
package/napi-inl.h CHANGED
@@ -2,9 +2,10 @@
2
2
  #define SRC_NAPI_INL_H_
3
3
 
4
4
  ////////////////////////////////////////////////////////////////////////////////
5
- // N-API C++ Wrapper Classes
5
+ // Node-API C++ Wrapper Classes
6
6
  //
7
- // Inline header-only implementations for "N-API" ABI-stable C APIs for Node.js.
7
+ // Inline header-only implementations for "Node-API" ABI-stable C APIs for
8
+ // Node.js.
8
9
  ////////////////////////////////////////////////////////////////////////////////
9
10
 
10
11
  // Note: Do not include this file directly! Include "napi.h" instead.
@@ -82,6 +83,24 @@ inline napi_value WrapCallback(Callable callback) {
82
83
  #endif // NAPI_CPP_EXCEPTIONS
83
84
  }
84
85
 
86
+ // For use in JS to C++ void callback wrappers to catch any Napi::Error
87
+ // exceptions and rethrow them as JavaScript exceptions before returning from the
88
+ // callback.
89
+ template <typename Callable>
90
+ inline void WrapVoidCallback(Callable callback) {
91
+ #ifdef NAPI_CPP_EXCEPTIONS
92
+ try {
93
+ callback();
94
+ } catch (const Error& e) {
95
+ e.ThrowAsJavaScriptException();
96
+ }
97
+ #else // NAPI_CPP_EXCEPTIONS
98
+ // When C++ exceptions are disabled, errors are immediately thrown as JS
99
+ // exceptions, so there is no need to catch and rethrow them here.
100
+ callback();
101
+ #endif // NAPI_CPP_EXCEPTIONS
102
+ }
103
+
85
104
  template <typename Callable, typename Return>
86
105
  struct CallbackData {
87
106
  static inline
@@ -117,27 +136,75 @@ struct CallbackData<Callable, void> {
117
136
  void* data;
118
137
  };
119
138
 
139
+ template <void (*Callback)(const CallbackInfo& info)>
140
+ static napi_value
141
+ TemplatedVoidCallback(napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
142
+ return details::WrapCallback([&] {
143
+ CallbackInfo cbInfo(env, info);
144
+ Callback(cbInfo);
145
+ return nullptr;
146
+ });
147
+ }
148
+
149
+ template <Napi::Value (*Callback)(const CallbackInfo& info)>
150
+ static napi_value
151
+ TemplatedCallback(napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
152
+ return details::WrapCallback([&] {
153
+ CallbackInfo cbInfo(env, info);
154
+ return Callback(cbInfo);
155
+ });
156
+ }
157
+
158
+ template <typename T,
159
+ Napi::Value (T::*UnwrapCallback)(const CallbackInfo& info)>
160
+ static napi_value
161
+ TemplatedInstanceCallback(napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
162
+ return details::WrapCallback([&] {
163
+ CallbackInfo cbInfo(env, info);
164
+ T* instance = T::Unwrap(cbInfo.This().As<Object>());
165
+ return (instance->*UnwrapCallback)(cbInfo);
166
+ });
167
+ }
168
+
169
+ template <typename T, void (T::*UnwrapCallback)(const CallbackInfo& info)>
170
+ static napi_value
171
+ TemplatedInstanceVoidCallback(napi_env env,
172
+ napi_callback_info info) NAPI_NOEXCEPT {
173
+ return details::WrapCallback([&] {
174
+ CallbackInfo cbInfo(env, info);
175
+ T* instance = T::Unwrap(cbInfo.This().As<Object>());
176
+ (instance->*UnwrapCallback)(cbInfo);
177
+ return nullptr;
178
+ });
179
+ }
180
+
120
181
  template <typename T, typename Finalizer, typename Hint = void>
121
182
  struct FinalizeData {
122
- static inline
123
- void Wrapper(napi_env env, void* data, void* finalizeHint) {
124
- FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
125
- finalizeData->callback(Env(env), static_cast<T*>(data));
126
- delete finalizeData;
183
+ static inline void Wrapper(napi_env env,
184
+ void* data,
185
+ void* finalizeHint) NAPI_NOEXCEPT {
186
+ WrapVoidCallback([&] {
187
+ FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
188
+ finalizeData->callback(Env(env), static_cast<T*>(data));
189
+ delete finalizeData;
190
+ });
127
191
  }
128
192
 
129
- static inline
130
- void WrapperWithHint(napi_env env, void* data, void* finalizeHint) {
131
- FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
132
- finalizeData->callback(Env(env), static_cast<T*>(data), finalizeData->hint);
133
- delete finalizeData;
193
+ static inline void WrapperWithHint(napi_env env,
194
+ void* data,
195
+ void* finalizeHint) NAPI_NOEXCEPT {
196
+ WrapVoidCallback([&] {
197
+ FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
198
+ finalizeData->callback(Env(env), static_cast<T*>(data), finalizeData->hint);
199
+ delete finalizeData;
200
+ });
134
201
  }
135
202
 
136
203
  Finalizer callback;
137
204
  Hint* hint;
138
205
  };
139
206
 
140
- #if (NAPI_VERSION > 3)
207
+ #if (NAPI_VERSION > 3 && !defined(__wasm32__))
141
208
  template <typename ContextType=void,
142
209
  typename Finalizer=std::function<void(Env, void*, ContextType*)>,
143
210
  typename FinalizerDataType=void>
@@ -196,7 +263,46 @@ struct ThreadSafeFinalize {
196
263
  FinalizerDataType* data;
197
264
  Finalizer callback;
198
265
  };
199
- #endif
266
+
267
+ template <typename ContextType, typename DataType, typename CallJs, CallJs call>
268
+ typename std::enable_if<call != nullptr>::type static inline CallJsWrapper(
269
+ napi_env env, napi_value jsCallback, void* context, void* data) {
270
+ call(env,
271
+ Function(env, jsCallback),
272
+ static_cast<ContextType*>(context),
273
+ static_cast<DataType*>(data));
274
+ }
275
+
276
+ template <typename ContextType, typename DataType, typename CallJs, CallJs call>
277
+ typename std::enable_if<call == nullptr>::type static inline CallJsWrapper(
278
+ napi_env env, napi_value jsCallback, void* /*context*/, void* /*data*/) {
279
+ if (jsCallback != nullptr) {
280
+ Function(env, jsCallback).Call(0, nullptr);
281
+ }
282
+ }
283
+
284
+ #if NAPI_VERSION > 4
285
+
286
+ template <typename CallbackType, typename TSFN>
287
+ napi_value DefaultCallbackWrapper(napi_env /*env*/, std::nullptr_t /*cb*/) {
288
+ return nullptr;
289
+ }
290
+
291
+ template <typename CallbackType, typename TSFN>
292
+ napi_value DefaultCallbackWrapper(napi_env /*env*/, Napi::Function cb) {
293
+ return cb;
294
+ }
295
+
296
+ #else
297
+ template <typename CallbackType, typename TSFN>
298
+ napi_value DefaultCallbackWrapper(napi_env env, Napi::Function cb) {
299
+ if (cb.IsEmpty()) {
300
+ return TSFN::EmptyFunctionFactory(env);
301
+ }
302
+ return cb;
303
+ }
304
+ #endif // NAPI_VERSION > 4
305
+ #endif // NAPI_VERSION > 3 && !defined(__wasm32__)
200
306
 
201
307
  template <typename Getter, typename Setter>
202
308
  struct AccessorCallbackData {
@@ -238,12 +344,26 @@ struct AccessorCallbackData {
238
344
  // Module registration
239
345
  ////////////////////////////////////////////////////////////////////////////////
240
346
 
241
- #define NODE_API_MODULE(modname, regfunc) \
242
- napi_value __napi_ ## regfunc(napi_env env, \
243
- napi_value exports) { \
244
- return Napi::RegisterModule(env, exports, regfunc); \
245
- } \
246
- NAPI_MODULE(modname, __napi_ ## regfunc)
347
+ // Register an add-on based on an initializer function.
348
+ #define NODE_API_MODULE(modname, regfunc) \
349
+ static napi_value __napi_##regfunc(napi_env env, napi_value exports) { \
350
+ return Napi::RegisterModule(env, exports, regfunc); \
351
+ } \
352
+ NAPI_MODULE(modname, __napi_##regfunc)
353
+
354
+ // Register an add-on based on a subclass of `Addon<T>` with a custom Node.js
355
+ // module name.
356
+ #define NODE_API_NAMED_ADDON(modname, classname) \
357
+ static napi_value __napi_ ## classname(napi_env env, \
358
+ napi_value exports) { \
359
+ return Napi::RegisterModule(env, exports, &classname::Init); \
360
+ } \
361
+ NAPI_MODULE(modname, __napi_ ## classname)
362
+
363
+ // Register an add-on based on a subclass of `Addon<T>` with the Node.js module
364
+ // name given by node-gyp from the `target_name` in binding.gyp.
365
+ #define NODE_API_ADDON(classname) \
366
+ NODE_API_NAMED_ADDON(NODE_GYP_MODULE_NAME, classname)
247
367
 
248
368
  // Adapt the NAPI_MODULE registration function:
249
369
  // - Wrap the arguments in NAPI wrappers.
@@ -1116,29 +1236,32 @@ inline Value Object::Get(const std::string& utf8name) const {
1116
1236
  }
1117
1237
 
1118
1238
  template <typename ValueType>
1119
- inline void Object::Set(napi_value key, const ValueType& value) {
1239
+ inline bool Object::Set(napi_value key, const ValueType& value) {
1120
1240
  napi_status status =
1121
1241
  napi_set_property(_env, _value, key, Value::From(_env, value));
1122
- NAPI_THROW_IF_FAILED_VOID(_env, status);
1242
+ NAPI_THROW_IF_FAILED(_env, status, false);
1243
+ return true;
1123
1244
  }
1124
1245
 
1125
1246
  template <typename ValueType>
1126
- inline void Object::Set(Value key, const ValueType& value) {
1247
+ inline bool Object::Set(Value key, const ValueType& value) {
1127
1248
  napi_status status =
1128
1249
  napi_set_property(_env, _value, key, Value::From(_env, value));
1129
- NAPI_THROW_IF_FAILED_VOID(_env, status);
1250
+ NAPI_THROW_IF_FAILED(_env, status, false);
1251
+ return true;
1130
1252
  }
1131
1253
 
1132
1254
  template <typename ValueType>
1133
- inline void Object::Set(const char* utf8name, const ValueType& value) {
1255
+ inline bool Object::Set(const char* utf8name, const ValueType& value) {
1134
1256
  napi_status status =
1135
1257
  napi_set_named_property(_env, _value, utf8name, Value::From(_env, value));
1136
- NAPI_THROW_IF_FAILED_VOID(_env, status);
1258
+ NAPI_THROW_IF_FAILED(_env, status, false);
1259
+ return true;
1137
1260
  }
1138
1261
 
1139
1262
  template <typename ValueType>
1140
- inline void Object::Set(const std::string& utf8name, const ValueType& value) {
1141
- Set(utf8name.c_str(), value);
1263
+ inline bool Object::Set(const std::string& utf8name, const ValueType& value) {
1264
+ return Set(utf8name.c_str(), value);
1142
1265
  }
1143
1266
 
1144
1267
  inline bool Object::Delete(napi_value key) {
@@ -1178,10 +1301,11 @@ inline Value Object::Get(uint32_t index) const {
1178
1301
  }
1179
1302
 
1180
1303
  template <typename ValueType>
1181
- inline void Object::Set(uint32_t index, const ValueType& value) {
1304
+ inline bool Object::Set(uint32_t index, const ValueType& value) {
1182
1305
  napi_status status =
1183
1306
  napi_set_element(_env, _value, index, Value::From(_env, value));
1184
- NAPI_THROW_IF_FAILED_VOID(_env, status);
1307
+ NAPI_THROW_IF_FAILED(_env, status, false);
1308
+ return true;
1185
1309
  }
1186
1310
 
1187
1311
  inline bool Object::Delete(uint32_t index) {
@@ -1198,22 +1322,27 @@ inline Array Object::GetPropertyNames() const {
1198
1322
  return Array(_env, result);
1199
1323
  }
1200
1324
 
1201
- inline void Object::DefineProperty(const PropertyDescriptor& property) {
1325
+ inline bool Object::DefineProperty(const PropertyDescriptor& property) {
1202
1326
  napi_status status = napi_define_properties(_env, _value, 1,
1203
1327
  reinterpret_cast<const napi_property_descriptor*>(&property));
1204
- NAPI_THROW_IF_FAILED_VOID(_env, status);
1328
+ NAPI_THROW_IF_FAILED(_env, status, false);
1329
+ return true;
1205
1330
  }
1206
1331
 
1207
- inline void Object::DefineProperties(const std::initializer_list<PropertyDescriptor>& properties) {
1332
+ inline bool Object::DefineProperties(
1333
+ const std::initializer_list<PropertyDescriptor>& properties) {
1208
1334
  napi_status status = napi_define_properties(_env, _value, properties.size(),
1209
1335
  reinterpret_cast<const napi_property_descriptor*>(properties.begin()));
1210
- NAPI_THROW_IF_FAILED_VOID(_env, status);
1336
+ NAPI_THROW_IF_FAILED(_env, status, false);
1337
+ return true;
1211
1338
  }
1212
1339
 
1213
- inline void Object::DefineProperties(const std::vector<PropertyDescriptor>& properties) {
1340
+ inline bool Object::DefineProperties(
1341
+ const std::vector<PropertyDescriptor>& properties) {
1214
1342
  napi_status status = napi_define_properties(_env, _value, properties.size(),
1215
1343
  reinterpret_cast<const napi_property_descriptor*>(properties.data()));
1216
- NAPI_THROW_IF_FAILED_VOID(_env, status);
1344
+ NAPI_THROW_IF_FAILED(_env, status, false);
1345
+ return true;
1217
1346
  }
1218
1347
 
1219
1348
  inline bool Object::InstanceOf(const Function& constructor) const {
@@ -1226,7 +1355,8 @@ inline bool Object::InstanceOf(const Function& constructor) const {
1226
1355
  template <typename Finalizer, typename T>
1227
1356
  inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) {
1228
1357
  details::FinalizeData<T, Finalizer>* finalizeData =
1229
- new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
1358
+ new details::FinalizeData<T, Finalizer>(
1359
+ {std::move(finalizeCallback), nullptr});
1230
1360
  napi_status status =
1231
1361
  details::AttachData(_env,
1232
1362
  *this,
@@ -1244,7 +1374,8 @@ inline void Object::AddFinalizer(Finalizer finalizeCallback,
1244
1374
  T* data,
1245
1375
  Hint* finalizeHint) {
1246
1376
  details::FinalizeData<T, Finalizer, Hint>* finalizeData =
1247
- new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
1377
+ new details::FinalizeData<T, Finalizer, Hint>(
1378
+ {std::move(finalizeCallback), finalizeHint});
1248
1379
  napi_status status =
1249
1380
  details::AttachData(_env,
1250
1381
  *this,
@@ -1257,6 +1388,20 @@ inline void Object::AddFinalizer(Finalizer finalizeCallback,
1257
1388
  }
1258
1389
  }
1259
1390
 
1391
+ #if NAPI_VERSION >= 8
1392
+ inline bool Object::Freeze() {
1393
+ napi_status status = napi_object_freeze(_env, _value);
1394
+ NAPI_THROW_IF_FAILED(_env, status, false);
1395
+ return true;
1396
+ }
1397
+
1398
+ inline bool Object::Seal() {
1399
+ napi_status status = napi_object_seal(_env, _value);
1400
+ NAPI_THROW_IF_FAILED(_env, status, false);
1401
+ return true;
1402
+ }
1403
+ #endif // NAPI_VERSION >= 8
1404
+
1260
1405
  ////////////////////////////////////////////////////////////////////////////////
1261
1406
  // External class
1262
1407
  ////////////////////////////////////////////////////////////////////////////////
@@ -1276,7 +1421,8 @@ inline External<T> External<T>::New(napi_env env,
1276
1421
  Finalizer finalizeCallback) {
1277
1422
  napi_value value;
1278
1423
  details::FinalizeData<T, Finalizer>* finalizeData =
1279
- new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
1424
+ new details::FinalizeData<T, Finalizer>(
1425
+ {std::move(finalizeCallback), nullptr});
1280
1426
  napi_status status = napi_create_external(
1281
1427
  env,
1282
1428
  data,
@@ -1298,7 +1444,8 @@ inline External<T> External<T>::New(napi_env env,
1298
1444
  Hint* finalizeHint) {
1299
1445
  napi_value value;
1300
1446
  details::FinalizeData<T, Finalizer, Hint>* finalizeData =
1301
- new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
1447
+ new details::FinalizeData<T, Finalizer, Hint>(
1448
+ {std::move(finalizeCallback), finalizeHint});
1302
1449
  napi_status status = napi_create_external(
1303
1450
  env,
1304
1451
  data,
@@ -1390,7 +1537,8 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
1390
1537
  Finalizer finalizeCallback) {
1391
1538
  napi_value value;
1392
1539
  details::FinalizeData<void, Finalizer>* finalizeData =
1393
- new details::FinalizeData<void, Finalizer>({ finalizeCallback, nullptr });
1540
+ new details::FinalizeData<void, Finalizer>(
1541
+ {std::move(finalizeCallback), nullptr});
1394
1542
  napi_status status = napi_create_external_arraybuffer(
1395
1543
  env,
1396
1544
  externalData,
@@ -1414,7 +1562,8 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
1414
1562
  Hint* finalizeHint) {
1415
1563
  napi_value value;
1416
1564
  details::FinalizeData<void, Finalizer, Hint>* finalizeData =
1417
- new details::FinalizeData<void, Finalizer, Hint>({ finalizeCallback, finalizeHint });
1565
+ new details::FinalizeData<void, Finalizer, Hint>(
1566
+ {std::move(finalizeCallback), finalizeHint});
1418
1567
  napi_status status = napi_create_external_arraybuffer(
1419
1568
  env,
1420
1569
  externalData,
@@ -1451,6 +1600,20 @@ inline size_t ArrayBuffer::ByteLength() {
1451
1600
  return length;
1452
1601
  }
1453
1602
 
1603
+ #if NAPI_VERSION >= 7
1604
+ inline bool ArrayBuffer::IsDetached() const {
1605
+ bool detached;
1606
+ napi_status status = napi_is_detached_arraybuffer(_env, _value, &detached);
1607
+ NAPI_THROW_IF_FAILED(_env, status, false);
1608
+ return detached;
1609
+ }
1610
+
1611
+ inline void ArrayBuffer::Detach() {
1612
+ napi_status status = napi_detach_arraybuffer(_env, _value);
1613
+ NAPI_THROW_IF_FAILED_VOID(_env, status);
1614
+ }
1615
+ #endif // NAPI_VERSION >= 7
1616
+
1454
1617
  ////////////////////////////////////////////////////////////////////////////////
1455
1618
  // DataView class
1456
1619
  ////////////////////////////////////////////////////////////////////////////////
@@ -1740,8 +1903,14 @@ inline TypedArrayOf<T>::TypedArrayOf() : TypedArray(), _data(nullptr) {
1740
1903
  template <typename T>
1741
1904
  inline TypedArrayOf<T>::TypedArrayOf(napi_env env, napi_value value)
1742
1905
  : TypedArray(env, value), _data(nullptr) {
1743
- napi_status status = napi_get_typedarray_info(
1744
- _env, _value, &_type, &_length, reinterpret_cast<void**>(&_data), nullptr, nullptr);
1906
+ napi_status status = napi_ok;
1907
+ if (value != nullptr) {
1908
+ status = napi_get_typedarray_info(
1909
+ _env, _value, &_type, &_length, reinterpret_cast<void**>(&_data), nullptr, nullptr);
1910
+ } else {
1911
+ _type = TypedArrayTypeForPrimitiveType<T>();
1912
+ _length = 0;
1913
+ }
1745
1914
  NAPI_THROW_IF_FAILED_VOID(_env, status);
1746
1915
  }
1747
1916
 
@@ -1802,15 +1971,12 @@ CreateFunction(napi_env env,
1802
1971
  template <Function::VoidCallback cb>
1803
1972
  inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1804
1973
  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);
1974
+ napi_status status = napi_create_function(env,
1975
+ utf8name,
1976
+ NAPI_AUTO_LENGTH,
1977
+ details::TemplatedVoidCallback<cb>,
1978
+ data,
1979
+ &result);
1814
1980
  NAPI_THROW_IF_FAILED(env, status, Function());
1815
1981
  return Function(env, result);
1816
1982
  }
@@ -1818,14 +1984,12 @@ inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1818
1984
  template <Function::Callback cb>
1819
1985
  inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1820
1986
  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);
1987
+ napi_status status = napi_create_function(env,
1988
+ utf8name,
1989
+ NAPI_AUTO_LENGTH,
1990
+ details::TemplatedCallback<cb>,
1991
+ data,
1992
+ &result);
1829
1993
  NAPI_THROW_IF_FAILED(env, status, Function());
1830
1994
  return Function(env, result);
1831
1995
  }
@@ -1849,8 +2013,8 @@ inline Function Function::New(napi_env env,
1849
2013
  Callable cb,
1850
2014
  const char* utf8name,
1851
2015
  void* data) {
1852
- typedef decltype(cb(CallbackInfo(nullptr, nullptr))) ReturnType;
1853
- typedef details::CallbackData<Callable, ReturnType> CbData;
2016
+ using ReturnType = decltype(cb(CallbackInfo(nullptr, nullptr)));
2017
+ using CbData = details::CallbackData<Callable, ReturnType>;
1854
2018
  auto callbackData = new CbData({ cb, data });
1855
2019
 
1856
2020
  napi_value value;
@@ -2019,7 +2183,8 @@ inline Buffer<T> Buffer<T>::New(napi_env env,
2019
2183
  Finalizer finalizeCallback) {
2020
2184
  napi_value value;
2021
2185
  details::FinalizeData<T, Finalizer>* finalizeData =
2022
- new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
2186
+ new details::FinalizeData<T, Finalizer>(
2187
+ {std::move(finalizeCallback), nullptr});
2023
2188
  napi_status status = napi_create_external_buffer(
2024
2189
  env,
2025
2190
  length * sizeof (T),
@@ -2043,7 +2208,8 @@ inline Buffer<T> Buffer<T>::New(napi_env env,
2043
2208
  Hint* finalizeHint) {
2044
2209
  napi_value value;
2045
2210
  details::FinalizeData<T, Finalizer, Hint>* finalizeData =
2046
- new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
2211
+ new details::FinalizeData<T, Finalizer, Hint>(
2212
+ {std::move(finalizeCallback), finalizeHint});
2047
2213
  napi_status status = napi_create_external_buffer(
2048
2214
  env,
2049
2215
  length * sizeof (T),
@@ -2523,54 +2689,58 @@ inline Napi::Value ObjectReference::Get(const std::string& utf8name) const {
2523
2689
  return scope.Escape(Value().Get(utf8name));
2524
2690
  }
2525
2691
 
2526
- inline void ObjectReference::Set(const char* utf8name, napi_value value) {
2692
+ inline bool ObjectReference::Set(const char* utf8name, napi_value value) {
2527
2693
  HandleScope scope(_env);
2528
- Value().Set(utf8name, value);
2694
+ return Value().Set(utf8name, value);
2529
2695
  }
2530
2696
 
2531
- inline void ObjectReference::Set(const char* utf8name, Napi::Value value) {
2697
+ inline bool ObjectReference::Set(const char* utf8name, Napi::Value value) {
2532
2698
  HandleScope scope(_env);
2533
- Value().Set(utf8name, value);
2699
+ return Value().Set(utf8name, value);
2534
2700
  }
2535
2701
 
2536
- inline void ObjectReference::Set(const char* utf8name, const char* utf8value) {
2702
+ inline bool ObjectReference::Set(const char* utf8name, const char* utf8value) {
2537
2703
  HandleScope scope(_env);
2538
- Value().Set(utf8name, utf8value);
2704
+ return Value().Set(utf8name, utf8value);
2539
2705
  }
2540
2706
 
2541
- inline void ObjectReference::Set(const char* utf8name, bool boolValue) {
2707
+ inline bool ObjectReference::Set(const char* utf8name, bool boolValue) {
2542
2708
  HandleScope scope(_env);
2543
- Value().Set(utf8name, boolValue);
2709
+ return Value().Set(utf8name, boolValue);
2544
2710
  }
2545
2711
 
2546
- inline void ObjectReference::Set(const char* utf8name, double numberValue) {
2712
+ inline bool ObjectReference::Set(const char* utf8name, double numberValue) {
2547
2713
  HandleScope scope(_env);
2548
- Value().Set(utf8name, numberValue);
2714
+ return Value().Set(utf8name, numberValue);
2549
2715
  }
2550
2716
 
2551
- inline void ObjectReference::Set(const std::string& utf8name, napi_value value) {
2717
+ inline bool ObjectReference::Set(const std::string& utf8name,
2718
+ napi_value value) {
2552
2719
  HandleScope scope(_env);
2553
- Value().Set(utf8name, value);
2720
+ return Value().Set(utf8name, value);
2554
2721
  }
2555
2722
 
2556
- inline void ObjectReference::Set(const std::string& utf8name, Napi::Value value) {
2723
+ inline bool ObjectReference::Set(const std::string& utf8name,
2724
+ Napi::Value value) {
2557
2725
  HandleScope scope(_env);
2558
- Value().Set(utf8name, value);
2726
+ return Value().Set(utf8name, value);
2559
2727
  }
2560
2728
 
2561
- inline void ObjectReference::Set(const std::string& utf8name, std::string& utf8value) {
2729
+ inline bool ObjectReference::Set(const std::string& utf8name,
2730
+ std::string& utf8value) {
2562
2731
  HandleScope scope(_env);
2563
- Value().Set(utf8name, utf8value);
2732
+ return Value().Set(utf8name, utf8value);
2564
2733
  }
2565
2734
 
2566
- inline void ObjectReference::Set(const std::string& utf8name, bool boolValue) {
2735
+ inline bool ObjectReference::Set(const std::string& utf8name, bool boolValue) {
2567
2736
  HandleScope scope(_env);
2568
- Value().Set(utf8name, boolValue);
2737
+ return Value().Set(utf8name, boolValue);
2569
2738
  }
2570
2739
 
2571
- inline void ObjectReference::Set(const std::string& utf8name, double numberValue) {
2740
+ inline bool ObjectReference::Set(const std::string& utf8name,
2741
+ double numberValue) {
2572
2742
  HandleScope scope(_env);
2573
- Value().Set(utf8name, numberValue);
2743
+ return Value().Set(utf8name, numberValue);
2574
2744
  }
2575
2745
 
2576
2746
  inline Napi::Value ObjectReference::Get(uint32_t index) const {
@@ -2578,34 +2748,34 @@ inline Napi::Value ObjectReference::Get(uint32_t index) const {
2578
2748
  return scope.Escape(Value().Get(index));
2579
2749
  }
2580
2750
 
2581
- inline void ObjectReference::Set(uint32_t index, napi_value value) {
2751
+ inline bool ObjectReference::Set(uint32_t index, napi_value value) {
2582
2752
  HandleScope scope(_env);
2583
- Value().Set(index, value);
2753
+ return Value().Set(index, value);
2584
2754
  }
2585
2755
 
2586
- inline void ObjectReference::Set(uint32_t index, Napi::Value value) {
2756
+ inline bool ObjectReference::Set(uint32_t index, Napi::Value value) {
2587
2757
  HandleScope scope(_env);
2588
- Value().Set(index, value);
2758
+ return Value().Set(index, value);
2589
2759
  }
2590
2760
 
2591
- inline void ObjectReference::Set(uint32_t index, const char* utf8value) {
2761
+ inline bool ObjectReference::Set(uint32_t index, const char* utf8value) {
2592
2762
  HandleScope scope(_env);
2593
- Value().Set(index, utf8value);
2763
+ return Value().Set(index, utf8value);
2594
2764
  }
2595
2765
 
2596
- inline void ObjectReference::Set(uint32_t index, const std::string& utf8value) {
2766
+ inline bool ObjectReference::Set(uint32_t index, const std::string& utf8value) {
2597
2767
  HandleScope scope(_env);
2598
- Value().Set(index, utf8value);
2768
+ return Value().Set(index, utf8value);
2599
2769
  }
2600
2770
 
2601
- inline void ObjectReference::Set(uint32_t index, bool boolValue) {
2771
+ inline bool ObjectReference::Set(uint32_t index, bool boolValue) {
2602
2772
  HandleScope scope(_env);
2603
- Value().Set(index, boolValue);
2773
+ return Value().Set(index, boolValue);
2604
2774
  }
2605
2775
 
2606
- inline void ObjectReference::Set(uint32_t index, double numberValue) {
2776
+ inline bool ObjectReference::Set(uint32_t index, double numberValue) {
2607
2777
  HandleScope scope(_env);
2608
- Value().Set(index, numberValue);
2778
+ return Value().Set(index, numberValue);
2609
2779
  }
2610
2780
 
2611
2781
  ////////////////////////////////////////////////////////////////////////////////
@@ -2816,7 +2986,7 @@ PropertyDescriptor::Accessor(const char* utf8name,
2816
2986
  napi_property_descriptor desc = napi_property_descriptor();
2817
2987
 
2818
2988
  desc.utf8name = utf8name;
2819
- desc.getter = &GetterCallbackWrapper<Getter>;
2989
+ desc.getter = details::TemplatedCallback<Getter>;
2820
2990
  desc.attributes = attributes;
2821
2991
  desc.data = data;
2822
2992
 
@@ -2839,7 +3009,7 @@ PropertyDescriptor::Accessor(Name name,
2839
3009
  napi_property_descriptor desc = napi_property_descriptor();
2840
3010
 
2841
3011
  desc.name = name;
2842
- desc.getter = &GetterCallbackWrapper<Getter>;
3012
+ desc.getter = details::TemplatedCallback<Getter>;
2843
3013
  desc.attributes = attributes;
2844
3014
  desc.data = data;
2845
3015
 
@@ -2857,8 +3027,8 @@ PropertyDescriptor::Accessor(const char* utf8name,
2857
3027
  napi_property_descriptor desc = napi_property_descriptor();
2858
3028
 
2859
3029
  desc.utf8name = utf8name;
2860
- desc.getter = &GetterCallbackWrapper<Getter>;
2861
- desc.setter = &SetterCallbackWrapper<Setter>;
3030
+ desc.getter = details::TemplatedCallback<Getter>;
3031
+ desc.setter = details::TemplatedVoidCallback<Setter>;
2862
3032
  desc.attributes = attributes;
2863
3033
  desc.data = data;
2864
3034
 
@@ -2885,31 +3055,14 @@ PropertyDescriptor::Accessor(Name name,
2885
3055
  napi_property_descriptor desc = napi_property_descriptor();
2886
3056
 
2887
3057
  desc.name = name;
2888
- desc.getter = &GetterCallbackWrapper<Getter>;
2889
- desc.setter = &SetterCallbackWrapper<Setter>;
3058
+ desc.getter = details::TemplatedCallback<Getter>;
3059
+ desc.setter = details::TemplatedVoidCallback<Setter>;
2890
3060
  desc.attributes = attributes;
2891
3061
  desc.data = data;
2892
3062
 
2893
3063
  return desc;
2894
3064
  }
2895
3065
 
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
-
2913
3066
  template <typename Getter>
2914
3067
  inline PropertyDescriptor
2915
3068
  PropertyDescriptor::Accessor(Napi::Env env,
@@ -2918,7 +3071,7 @@ PropertyDescriptor::Accessor(Napi::Env env,
2918
3071
  Getter getter,
2919
3072
  napi_property_attributes attributes,
2920
3073
  void* data) {
2921
- typedef details::CallbackData<Getter, Napi::Value> CbData;
3074
+ using CbData = details::CallbackData<Getter, Napi::Value>;
2922
3075
  auto callbackData = new CbData({ getter, data });
2923
3076
 
2924
3077
  napi_status status = AttachData(env, object, callbackData);
@@ -2956,7 +3109,7 @@ inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
2956
3109
  Getter getter,
2957
3110
  napi_property_attributes attributes,
2958
3111
  void* data) {
2959
- typedef details::CallbackData<Getter, Napi::Value> CbData;
3112
+ using CbData = details::CallbackData<Getter, Napi::Value>;
2960
3113
  auto callbackData = new CbData({ getter, data });
2961
3114
 
2962
3115
  napi_status status = AttachData(env, object, callbackData);
@@ -2985,7 +3138,7 @@ inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
2985
3138
  Setter setter,
2986
3139
  napi_property_attributes attributes,
2987
3140
  void* data) {
2988
- typedef details::AccessorCallbackData<Getter, Setter> CbData;
3141
+ using CbData = details::AccessorCallbackData<Getter, Setter>;
2989
3142
  auto callbackData = new CbData({ getter, setter, data });
2990
3143
 
2991
3144
  napi_status status = AttachData(env, object, callbackData);
@@ -3025,7 +3178,7 @@ inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
3025
3178
  Setter setter,
3026
3179
  napi_property_attributes attributes,
3027
3180
  void* data) {
3028
- typedef details::AccessorCallbackData<Getter, Setter> CbData;
3181
+ using CbData = details::AccessorCallbackData<Getter, Setter>;
3029
3182
  auto callbackData = new CbData({ getter, setter, data });
3030
3183
 
3031
3184
  napi_status status = AttachData(env, object, callbackData);
@@ -3137,538 +3290,653 @@ inline PropertyDescriptor::operator const napi_property_descriptor&() const {
3137
3290
  }
3138
3291
 
3139
3292
  ////////////////////////////////////////////////////////////////////////////////
3140
- // ObjectWrap<T> class
3293
+ // InstanceWrap<T> class
3141
3294
  ////////////////////////////////////////////////////////////////////////////////
3142
3295
 
3143
3296
  template <typename T>
3144
- inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
3145
- napi_env env = callbackInfo.Env();
3146
- napi_value wrapper = callbackInfo.This();
3147
- napi_status status;
3148
- napi_ref ref;
3149
- status = napi_wrap(env, wrapper, this, FinalizeCallback, nullptr, &ref);
3150
- NAPI_THROW_IF_FAILED_VOID(env, status);
3151
-
3152
- Reference<Object>* instanceRef = this;
3153
- *instanceRef = Reference<Object>(env, ref);
3154
- }
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
-
3170
- template<typename T>
3171
- inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
3172
- T* unwrapped;
3173
- napi_status status = napi_unwrap(wrapper.Env(), wrapper, reinterpret_cast<void**>(&unwrapped));
3174
- NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
3175
- return unwrapped;
3176
- }
3177
-
3178
- template <typename T>
3179
- inline Function
3180
- ObjectWrap<T>::DefineClass(Napi::Env env,
3181
- const char* utf8name,
3182
- const size_t props_count,
3183
- const napi_property_descriptor* descriptors,
3184
- void* data) {
3297
+ inline void InstanceWrap<T>::AttachPropData(napi_env env,
3298
+ napi_value value,
3299
+ const napi_property_descriptor* prop) {
3185
3300
  napi_status status;
3186
- std::vector<napi_property_descriptor> props(props_count);
3187
-
3188
- // We copy the descriptors to a local array because before defining the class
3189
- // we must replace static method property descriptors with value property
3190
- // descriptors such that the value is a function-valued `napi_value` created
3191
- // with `CreateFunction()`.
3192
- //
3193
- // This replacement could be made for instance methods as well, but V8 aborts
3194
- // if we do that, because it expects methods defined on the prototype template
3195
- // to have `FunctionTemplate`s.
3196
- for (size_t index = 0; index < props_count; index++) {
3197
- props[index] = descriptors[index];
3198
- napi_property_descriptor* prop = &props[index];
3199
- if (prop->method == T::StaticMethodCallbackWrapper) {
3200
- status = CreateFunction(env,
3201
- utf8name,
3202
- prop->method,
3203
- static_cast<StaticMethodCallbackData*>(prop->data),
3204
- &(prop->value));
3205
- NAPI_THROW_IF_FAILED(env, status, Function());
3206
- prop->method = nullptr;
3207
- prop->data = nullptr;
3208
- } else if (prop->method == T::StaticVoidMethodCallbackWrapper) {
3209
- status = CreateFunction(env,
3210
- utf8name,
3211
- prop->method,
3212
- static_cast<StaticVoidMethodCallbackData*>(prop->data),
3213
- &(prop->value));
3214
- NAPI_THROW_IF_FAILED(env, status, Function());
3215
- prop->method = nullptr;
3216
- prop->data = nullptr;
3217
- }
3218
- }
3219
-
3220
- napi_value value;
3221
- status = napi_define_class(env,
3222
- utf8name,
3223
- NAPI_AUTO_LENGTH,
3224
- T::ConstructorCallbackWrapper,
3225
- data,
3226
- props_count,
3227
- props.data(),
3228
- &value);
3229
- NAPI_THROW_IF_FAILED(env, status, Function());
3230
-
3231
- // After defining the class we iterate once more over the property descriptors
3232
- // and attach the data associated with accessors and instance methods to the
3233
- // newly created JavaScript class.
3234
- for (size_t idx = 0; idx < props_count; idx++) {
3235
- const napi_property_descriptor* prop = &props[idx];
3236
-
3237
- if (prop->getter == T::StaticGetterCallbackWrapper ||
3238
- prop->setter == T::StaticSetterCallbackWrapper) {
3301
+ if (!(prop->attributes & napi_static)) {
3302
+ if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
3239
3303
  status = Napi::details::AttachData(env,
3240
- value,
3241
- static_cast<StaticAccessorCallbackData*>(prop->data));
3242
- NAPI_THROW_IF_FAILED(env, status, Function());
3304
+ value,
3305
+ static_cast<InstanceVoidMethodCallbackData*>(prop->data));
3306
+ NAPI_THROW_IF_FAILED_VOID(env, status);
3307
+ } else if (prop->method == T::InstanceMethodCallbackWrapper) {
3308
+ status = Napi::details::AttachData(env,
3309
+ value,
3310
+ static_cast<InstanceMethodCallbackData*>(prop->data));
3311
+ NAPI_THROW_IF_FAILED_VOID(env, status);
3243
3312
  } else if (prop->getter == T::InstanceGetterCallbackWrapper ||
3244
3313
  prop->setter == T::InstanceSetterCallbackWrapper) {
3245
3314
  status = Napi::details::AttachData(env,
3246
3315
  value,
3247
3316
  static_cast<InstanceAccessorCallbackData*>(prop->data));
3248
- NAPI_THROW_IF_FAILED(env, status, Function());
3249
- } else if (prop->method != nullptr && !(prop->attributes & napi_static)) {
3250
- if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
3251
- status = Napi::details::AttachData(env,
3252
- value,
3253
- static_cast<InstanceVoidMethodCallbackData*>(prop->data));
3254
- NAPI_THROW_IF_FAILED(env, status, Function());
3255
- } else if (prop->method == T::InstanceMethodCallbackWrapper) {
3256
- status = Napi::details::AttachData(env,
3257
- value,
3258
- static_cast<InstanceMethodCallbackData*>(prop->data));
3259
- NAPI_THROW_IF_FAILED(env, status, Function());
3260
- }
3317
+ NAPI_THROW_IF_FAILED_VOID(env, status);
3261
3318
  }
3262
3319
  }
3263
-
3264
- return Function(env, value);
3265
- }
3266
-
3267
- template <typename T>
3268
- inline Function ObjectWrap<T>::DefineClass(
3269
- Napi::Env env,
3270
- const char* utf8name,
3271
- const std::initializer_list<ClassPropertyDescriptor<T>>& properties,
3272
- void* data) {
3273
- return DefineClass(env,
3274
- utf8name,
3275
- properties.size(),
3276
- reinterpret_cast<const napi_property_descriptor*>(properties.begin()),
3277
- data);
3278
- }
3279
-
3280
- template <typename T>
3281
- inline Function ObjectWrap<T>::DefineClass(
3282
- Napi::Env env,
3283
- const char* utf8name,
3284
- const std::vector<ClassPropertyDescriptor<T>>& properties,
3285
- void* data) {
3286
- return DefineClass(env,
3287
- utf8name,
3288
- properties.size(),
3289
- reinterpret_cast<const napi_property_descriptor*>(properties.data()),
3290
- data);
3291
3320
  }
3292
3321
 
3293
3322
  template <typename T>
3294
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3323
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3295
3324
  const char* utf8name,
3296
- StaticVoidMethodCallback method,
3325
+ InstanceVoidMethodCallback method,
3297
3326
  napi_property_attributes attributes,
3298
3327
  void* data) {
3299
- StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3328
+ InstanceVoidMethodCallbackData* callbackData =
3329
+ new InstanceVoidMethodCallbackData({ method, data});
3300
3330
 
3301
3331
  napi_property_descriptor desc = napi_property_descriptor();
3302
3332
  desc.utf8name = utf8name;
3303
- desc.method = T::StaticVoidMethodCallbackWrapper;
3333
+ desc.method = T::InstanceVoidMethodCallbackWrapper;
3304
3334
  desc.data = callbackData;
3305
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3335
+ desc.attributes = attributes;
3306
3336
  return desc;
3307
3337
  }
3308
3338
 
3309
3339
  template <typename T>
3310
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3340
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3311
3341
  const char* utf8name,
3312
- StaticMethodCallback method,
3342
+ InstanceMethodCallback method,
3313
3343
  napi_property_attributes attributes,
3314
3344
  void* data) {
3315
- StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3345
+ InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3316
3346
 
3317
3347
  napi_property_descriptor desc = napi_property_descriptor();
3318
3348
  desc.utf8name = utf8name;
3319
- desc.method = T::StaticMethodCallbackWrapper;
3349
+ desc.method = T::InstanceMethodCallbackWrapper;
3320
3350
  desc.data = callbackData;
3321
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3351
+ desc.attributes = attributes;
3322
3352
  return desc;
3323
3353
  }
3324
3354
 
3325
3355
  template <typename T>
3326
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3356
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3327
3357
  Symbol name,
3328
- StaticVoidMethodCallback method,
3358
+ InstanceVoidMethodCallback method,
3329
3359
  napi_property_attributes attributes,
3330
3360
  void* data) {
3331
- StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3361
+ InstanceVoidMethodCallbackData* callbackData =
3362
+ new InstanceVoidMethodCallbackData({ method, data});
3332
3363
 
3333
3364
  napi_property_descriptor desc = napi_property_descriptor();
3334
3365
  desc.name = name;
3335
- desc.method = T::StaticVoidMethodCallbackWrapper;
3366
+ desc.method = T::InstanceVoidMethodCallbackWrapper;
3336
3367
  desc.data = callbackData;
3337
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3368
+ desc.attributes = attributes;
3338
3369
  return desc;
3339
3370
  }
3340
3371
 
3341
3372
  template <typename T>
3342
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3373
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3343
3374
  Symbol name,
3344
- StaticMethodCallback method,
3375
+ InstanceMethodCallback method,
3345
3376
  napi_property_attributes attributes,
3346
3377
  void* data) {
3347
- StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3378
+ InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3348
3379
 
3349
3380
  napi_property_descriptor desc = napi_property_descriptor();
3350
3381
  desc.name = name;
3351
- desc.method = T::StaticMethodCallbackWrapper;
3382
+ desc.method = T::InstanceMethodCallbackWrapper;
3352
3383
  desc.data = callbackData;
3353
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3384
+ desc.attributes = attributes;
3354
3385
  return desc;
3355
3386
  }
3356
3387
 
3357
3388
  template <typename T>
3358
- template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3359
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3389
+ template <typename InstanceWrap<T>::InstanceVoidMethodCallback method>
3390
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3360
3391
  const char* utf8name,
3361
3392
  napi_property_attributes attributes,
3362
3393
  void* data) {
3363
3394
  napi_property_descriptor desc = napi_property_descriptor();
3364
3395
  desc.utf8name = utf8name;
3365
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3396
+ desc.method = details::TemplatedInstanceVoidCallback<T, method>;
3366
3397
  desc.data = data;
3367
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3398
+ desc.attributes = attributes;
3368
3399
  return desc;
3369
3400
  }
3370
3401
 
3371
3402
  template <typename T>
3372
- template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3373
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3374
- Symbol name,
3403
+ template <typename InstanceWrap<T>::InstanceMethodCallback method>
3404
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3405
+ const char* utf8name,
3375
3406
  napi_property_attributes attributes,
3376
3407
  void* data) {
3377
3408
  napi_property_descriptor desc = napi_property_descriptor();
3378
- desc.name = name;
3379
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3409
+ desc.utf8name = utf8name;
3410
+ desc.method = details::TemplatedInstanceCallback<T, method>;
3380
3411
  desc.data = data;
3381
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3412
+ desc.attributes = attributes;
3382
3413
  return desc;
3383
3414
  }
3384
3415
 
3385
3416
  template <typename T>
3386
- template <typename ObjectWrap<T>::StaticMethodCallback method>
3387
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3388
- const char* utf8name,
3417
+ template <typename InstanceWrap<T>::InstanceVoidMethodCallback method>
3418
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3419
+ Symbol name,
3389
3420
  napi_property_attributes attributes,
3390
3421
  void* data) {
3391
3422
  napi_property_descriptor desc = napi_property_descriptor();
3392
- desc.utf8name = utf8name;
3393
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3423
+ desc.name = name;
3424
+ desc.method = details::TemplatedInstanceVoidCallback<T, method>;
3394
3425
  desc.data = data;
3395
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3426
+ desc.attributes = attributes;
3396
3427
  return desc;
3397
3428
  }
3398
3429
 
3399
3430
  template <typename T>
3400
- template <typename ObjectWrap<T>::StaticMethodCallback method>
3401
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3431
+ template <typename InstanceWrap<T>::InstanceMethodCallback method>
3432
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3402
3433
  Symbol name,
3403
3434
  napi_property_attributes attributes,
3404
3435
  void* data) {
3405
3436
  napi_property_descriptor desc = napi_property_descriptor();
3406
3437
  desc.name = name;
3407
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3438
+ desc.method = details::TemplatedInstanceCallback<T, method>;
3408
3439
  desc.data = data;
3409
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3440
+ desc.attributes = attributes;
3410
3441
  return desc;
3411
3442
  }
3412
3443
 
3413
3444
  template <typename T>
3414
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3445
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
3415
3446
  const char* utf8name,
3416
- StaticGetterCallback getter,
3417
- StaticSetterCallback setter,
3447
+ InstanceGetterCallback getter,
3448
+ InstanceSetterCallback setter,
3418
3449
  napi_property_attributes attributes,
3419
3450
  void* data) {
3420
- StaticAccessorCallbackData* callbackData =
3421
- new StaticAccessorCallbackData({ getter, setter, data });
3451
+ InstanceAccessorCallbackData* callbackData =
3452
+ new InstanceAccessorCallbackData({ getter, setter, data });
3422
3453
 
3423
3454
  napi_property_descriptor desc = napi_property_descriptor();
3424
3455
  desc.utf8name = utf8name;
3425
- desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3426
- desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3456
+ desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3457
+ desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3427
3458
  desc.data = callbackData;
3428
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3459
+ desc.attributes = attributes;
3429
3460
  return desc;
3430
3461
  }
3431
3462
 
3432
3463
  template <typename T>
3433
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3464
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
3434
3465
  Symbol name,
3435
- StaticGetterCallback getter,
3436
- StaticSetterCallback setter,
3466
+ InstanceGetterCallback getter,
3467
+ InstanceSetterCallback setter,
3437
3468
  napi_property_attributes attributes,
3438
3469
  void* data) {
3439
- StaticAccessorCallbackData* callbackData =
3440
- new StaticAccessorCallbackData({ getter, setter, data });
3470
+ InstanceAccessorCallbackData* callbackData =
3471
+ new InstanceAccessorCallbackData({ getter, setter, data });
3441
3472
 
3442
3473
  napi_property_descriptor desc = napi_property_descriptor();
3443
3474
  desc.name = name;
3444
- desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3445
- desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3475
+ desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3476
+ desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3446
3477
  desc.data = callbackData;
3447
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3478
+ desc.attributes = attributes;
3448
3479
  return desc;
3449
3480
  }
3450
3481
 
3451
3482
  template <typename T>
3452
- template <typename ObjectWrap<T>::StaticGetterCallback getter,
3453
- typename ObjectWrap<T>::StaticSetterCallback setter>
3454
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3483
+ template <typename InstanceWrap<T>::InstanceGetterCallback getter,
3484
+ typename InstanceWrap<T>::InstanceSetterCallback setter>
3485
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
3455
3486
  const char* utf8name,
3456
3487
  napi_property_attributes attributes,
3457
3488
  void* data) {
3458
3489
  napi_property_descriptor desc = napi_property_descriptor();
3459
3490
  desc.utf8name = utf8name;
3460
- desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
3461
- desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3491
+ desc.getter = details::TemplatedInstanceCallback<T, getter>;
3492
+ desc.setter = This::WrapSetter(This::SetterTag<setter>());
3462
3493
  desc.data = data;
3463
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3494
+ desc.attributes = attributes;
3464
3495
  return desc;
3465
3496
  }
3466
3497
 
3467
3498
  template <typename T>
3468
- template <typename ObjectWrap<T>::StaticGetterCallback getter,
3469
- typename ObjectWrap<T>::StaticSetterCallback setter>
3470
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3499
+ template <typename InstanceWrap<T>::InstanceGetterCallback getter,
3500
+ typename InstanceWrap<T>::InstanceSetterCallback setter>
3501
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
3471
3502
  Symbol name,
3472
3503
  napi_property_attributes attributes,
3473
3504
  void* data) {
3474
3505
  napi_property_descriptor desc = napi_property_descriptor();
3475
3506
  desc.name = name;
3476
- desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
3477
- desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3507
+ desc.getter = details::TemplatedInstanceCallback<T, getter>;
3508
+ desc.setter = This::WrapSetter(This::SetterTag<setter>());
3478
3509
  desc.data = data;
3479
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3510
+ desc.attributes = attributes;
3480
3511
  return desc;
3481
3512
  }
3482
3513
 
3483
3514
  template <typename T>
3484
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3515
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceValue(
3485
3516
  const char* utf8name,
3486
- InstanceVoidMethodCallback method,
3517
+ Napi::Value value,
3518
+ napi_property_attributes attributes) {
3519
+ napi_property_descriptor desc = napi_property_descriptor();
3520
+ desc.utf8name = utf8name;
3521
+ desc.value = value;
3522
+ desc.attributes = attributes;
3523
+ return desc;
3524
+ }
3525
+
3526
+ template <typename T>
3527
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceValue(
3528
+ Symbol name,
3529
+ Napi::Value value,
3530
+ napi_property_attributes attributes) {
3531
+ napi_property_descriptor desc = napi_property_descriptor();
3532
+ desc.name = name;
3533
+ desc.value = value;
3534
+ desc.attributes = attributes;
3535
+ return desc;
3536
+ }
3537
+
3538
+ template <typename T>
3539
+ inline napi_value InstanceWrap<T>::InstanceVoidMethodCallbackWrapper(
3540
+ napi_env env,
3541
+ napi_callback_info info) {
3542
+ return details::WrapCallback([&] {
3543
+ CallbackInfo callbackInfo(env, info);
3544
+ InstanceVoidMethodCallbackData* callbackData =
3545
+ reinterpret_cast<InstanceVoidMethodCallbackData*>(callbackInfo.Data());
3546
+ callbackInfo.SetData(callbackData->data);
3547
+ T* instance = T::Unwrap(callbackInfo.This().As<Object>());
3548
+ auto cb = callbackData->callback;
3549
+ (instance->*cb)(callbackInfo);
3550
+ return nullptr;
3551
+ });
3552
+ }
3553
+
3554
+ template <typename T>
3555
+ inline napi_value InstanceWrap<T>::InstanceMethodCallbackWrapper(
3556
+ napi_env env,
3557
+ napi_callback_info info) {
3558
+ return details::WrapCallback([&] {
3559
+ CallbackInfo callbackInfo(env, info);
3560
+ InstanceMethodCallbackData* callbackData =
3561
+ reinterpret_cast<InstanceMethodCallbackData*>(callbackInfo.Data());
3562
+ callbackInfo.SetData(callbackData->data);
3563
+ T* instance = T::Unwrap(callbackInfo.This().As<Object>());
3564
+ auto cb = callbackData->callback;
3565
+ return (instance->*cb)(callbackInfo);
3566
+ });
3567
+ }
3568
+
3569
+ template <typename T>
3570
+ inline napi_value InstanceWrap<T>::InstanceGetterCallbackWrapper(
3571
+ napi_env env,
3572
+ napi_callback_info info) {
3573
+ return details::WrapCallback([&] {
3574
+ CallbackInfo callbackInfo(env, info);
3575
+ InstanceAccessorCallbackData* callbackData =
3576
+ reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
3577
+ callbackInfo.SetData(callbackData->data);
3578
+ T* instance = T::Unwrap(callbackInfo.This().As<Object>());
3579
+ auto cb = callbackData->getterCallback;
3580
+ return (instance->*cb)(callbackInfo);
3581
+ });
3582
+ }
3583
+
3584
+ template <typename T>
3585
+ inline napi_value InstanceWrap<T>::InstanceSetterCallbackWrapper(
3586
+ napi_env env,
3587
+ napi_callback_info info) {
3588
+ return details::WrapCallback([&] {
3589
+ CallbackInfo callbackInfo(env, info);
3590
+ InstanceAccessorCallbackData* callbackData =
3591
+ reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
3592
+ callbackInfo.SetData(callbackData->data);
3593
+ T* instance = T::Unwrap(callbackInfo.This().As<Object>());
3594
+ auto cb = callbackData->setterCallback;
3595
+ (instance->*cb)(callbackInfo, callbackInfo[0]);
3596
+ return nullptr;
3597
+ });
3598
+ }
3599
+
3600
+ template <typename T>
3601
+ template <typename InstanceWrap<T>::InstanceSetterCallback method>
3602
+ inline napi_value InstanceWrap<T>::WrappedMethod(
3603
+ napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
3604
+ return details::WrapCallback([&] {
3605
+ const CallbackInfo cbInfo(env, info);
3606
+ T* instance = T::Unwrap(cbInfo.This().As<Object>());
3607
+ (instance->*method)(cbInfo, cbInfo[0]);
3608
+ return nullptr;
3609
+ });
3610
+ }
3611
+
3612
+ ////////////////////////////////////////////////////////////////////////////////
3613
+ // ObjectWrap<T> class
3614
+ ////////////////////////////////////////////////////////////////////////////////
3615
+
3616
+ template <typename T>
3617
+ inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
3618
+ napi_env env = callbackInfo.Env();
3619
+ napi_value wrapper = callbackInfo.This();
3620
+ napi_status status;
3621
+ napi_ref ref;
3622
+ T* instance = static_cast<T*>(this);
3623
+ status = napi_wrap(env, wrapper, instance, FinalizeCallback, nullptr, &ref);
3624
+ NAPI_THROW_IF_FAILED_VOID(env, status);
3625
+
3626
+ Reference<Object>* instanceRef = instance;
3627
+ *instanceRef = Reference<Object>(env, ref);
3628
+ }
3629
+
3630
+ template <typename T>
3631
+ inline ObjectWrap<T>::~ObjectWrap() {
3632
+ // If the JS object still exists at this point, remove the finalizer added
3633
+ // through `napi_wrap()`.
3634
+ if (!IsEmpty()) {
3635
+ Object object = Value();
3636
+ // It is not valid to call `napi_remove_wrap()` with an empty `object`.
3637
+ // This happens e.g. during garbage collection.
3638
+ if (!object.IsEmpty() && _construction_failed) {
3639
+ napi_remove_wrap(Env(), object, nullptr);
3640
+ }
3641
+ }
3642
+ }
3643
+
3644
+ template<typename T>
3645
+ inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
3646
+ T* unwrapped;
3647
+ napi_status status = napi_unwrap(wrapper.Env(), wrapper, reinterpret_cast<void**>(&unwrapped));
3648
+ NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
3649
+ return unwrapped;
3650
+ }
3651
+
3652
+ template <typename T>
3653
+ inline Function
3654
+ ObjectWrap<T>::DefineClass(Napi::Env env,
3655
+ const char* utf8name,
3656
+ const size_t props_count,
3657
+ const napi_property_descriptor* descriptors,
3658
+ void* data) {
3659
+ napi_status status;
3660
+ std::vector<napi_property_descriptor> props(props_count);
3661
+
3662
+ // We copy the descriptors to a local array because before defining the class
3663
+ // we must replace static method property descriptors with value property
3664
+ // descriptors such that the value is a function-valued `napi_value` created
3665
+ // with `CreateFunction()`.
3666
+ //
3667
+ // This replacement could be made for instance methods as well, but V8 aborts
3668
+ // if we do that, because it expects methods defined on the prototype template
3669
+ // to have `FunctionTemplate`s.
3670
+ for (size_t index = 0; index < props_count; index++) {
3671
+ props[index] = descriptors[index];
3672
+ napi_property_descriptor* prop = &props[index];
3673
+ if (prop->method == T::StaticMethodCallbackWrapper) {
3674
+ status = CreateFunction(env,
3675
+ utf8name,
3676
+ prop->method,
3677
+ static_cast<StaticMethodCallbackData*>(prop->data),
3678
+ &(prop->value));
3679
+ NAPI_THROW_IF_FAILED(env, status, Function());
3680
+ prop->method = nullptr;
3681
+ prop->data = nullptr;
3682
+ } else if (prop->method == T::StaticVoidMethodCallbackWrapper) {
3683
+ status = CreateFunction(env,
3684
+ utf8name,
3685
+ prop->method,
3686
+ static_cast<StaticVoidMethodCallbackData*>(prop->data),
3687
+ &(prop->value));
3688
+ NAPI_THROW_IF_FAILED(env, status, Function());
3689
+ prop->method = nullptr;
3690
+ prop->data = nullptr;
3691
+ }
3692
+ }
3693
+
3694
+ napi_value value;
3695
+ status = napi_define_class(env,
3696
+ utf8name,
3697
+ NAPI_AUTO_LENGTH,
3698
+ T::ConstructorCallbackWrapper,
3699
+ data,
3700
+ props_count,
3701
+ props.data(),
3702
+ &value);
3703
+ NAPI_THROW_IF_FAILED(env, status, Function());
3704
+
3705
+ // After defining the class we iterate once more over the property descriptors
3706
+ // and attach the data associated with accessors and instance methods to the
3707
+ // newly created JavaScript class.
3708
+ for (size_t idx = 0; idx < props_count; idx++) {
3709
+ const napi_property_descriptor* prop = &props[idx];
3710
+
3711
+ if (prop->getter == T::StaticGetterCallbackWrapper ||
3712
+ prop->setter == T::StaticSetterCallbackWrapper) {
3713
+ status = Napi::details::AttachData(env,
3714
+ value,
3715
+ static_cast<StaticAccessorCallbackData*>(prop->data));
3716
+ NAPI_THROW_IF_FAILED(env, status, Function());
3717
+ } else {
3718
+ // InstanceWrap<T>::AttachPropData is responsible for attaching the data
3719
+ // of instance methods and accessors.
3720
+ T::AttachPropData(env, value, prop);
3721
+ }
3722
+ }
3723
+
3724
+ return Function(env, value);
3725
+ }
3726
+
3727
+ template <typename T>
3728
+ inline Function ObjectWrap<T>::DefineClass(
3729
+ Napi::Env env,
3730
+ const char* utf8name,
3731
+ const std::initializer_list<ClassPropertyDescriptor<T>>& properties,
3732
+ void* data) {
3733
+ return DefineClass(env,
3734
+ utf8name,
3735
+ properties.size(),
3736
+ reinterpret_cast<const napi_property_descriptor*>(properties.begin()),
3737
+ data);
3738
+ }
3739
+
3740
+ template <typename T>
3741
+ inline Function ObjectWrap<T>::DefineClass(
3742
+ Napi::Env env,
3743
+ const char* utf8name,
3744
+ const std::vector<ClassPropertyDescriptor<T>>& properties,
3745
+ void* data) {
3746
+ return DefineClass(env,
3747
+ utf8name,
3748
+ properties.size(),
3749
+ reinterpret_cast<const napi_property_descriptor*>(properties.data()),
3750
+ data);
3751
+ }
3752
+
3753
+ template <typename T>
3754
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3755
+ const char* utf8name,
3756
+ StaticVoidMethodCallback method,
3487
3757
  napi_property_attributes attributes,
3488
3758
  void* data) {
3489
- InstanceVoidMethodCallbackData* callbackData =
3490
- new InstanceVoidMethodCallbackData({ method, data});
3759
+ StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3491
3760
 
3492
3761
  napi_property_descriptor desc = napi_property_descriptor();
3493
3762
  desc.utf8name = utf8name;
3494
- desc.method = T::InstanceVoidMethodCallbackWrapper;
3763
+ desc.method = T::StaticVoidMethodCallbackWrapper;
3495
3764
  desc.data = callbackData;
3496
- desc.attributes = attributes;
3765
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3497
3766
  return desc;
3498
3767
  }
3499
3768
 
3500
3769
  template <typename T>
3501
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3770
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3502
3771
  const char* utf8name,
3503
- InstanceMethodCallback method,
3772
+ StaticMethodCallback method,
3504
3773
  napi_property_attributes attributes,
3505
3774
  void* data) {
3506
- InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3775
+ StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3507
3776
 
3508
3777
  napi_property_descriptor desc = napi_property_descriptor();
3509
3778
  desc.utf8name = utf8name;
3510
- desc.method = T::InstanceMethodCallbackWrapper;
3779
+ desc.method = T::StaticMethodCallbackWrapper;
3511
3780
  desc.data = callbackData;
3512
- desc.attributes = attributes;
3781
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3513
3782
  return desc;
3514
3783
  }
3515
3784
 
3516
3785
  template <typename T>
3517
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3786
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3518
3787
  Symbol name,
3519
- InstanceVoidMethodCallback method,
3788
+ StaticVoidMethodCallback method,
3520
3789
  napi_property_attributes attributes,
3521
3790
  void* data) {
3522
- InstanceVoidMethodCallbackData* callbackData =
3523
- new InstanceVoidMethodCallbackData({ method, data});
3791
+ StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3524
3792
 
3525
3793
  napi_property_descriptor desc = napi_property_descriptor();
3526
3794
  desc.name = name;
3527
- desc.method = T::InstanceVoidMethodCallbackWrapper;
3795
+ desc.method = T::StaticVoidMethodCallbackWrapper;
3528
3796
  desc.data = callbackData;
3529
- desc.attributes = attributes;
3797
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3530
3798
  return desc;
3531
3799
  }
3532
3800
 
3533
3801
  template <typename T>
3534
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3802
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3535
3803
  Symbol name,
3536
- InstanceMethodCallback method,
3804
+ StaticMethodCallback method,
3537
3805
  napi_property_attributes attributes,
3538
3806
  void* data) {
3539
- InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3807
+ StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3540
3808
 
3541
3809
  napi_property_descriptor desc = napi_property_descriptor();
3542
3810
  desc.name = name;
3543
- desc.method = T::InstanceMethodCallbackWrapper;
3811
+ desc.method = T::StaticMethodCallbackWrapper;
3544
3812
  desc.data = callbackData;
3545
- desc.attributes = attributes;
3813
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3546
3814
  return desc;
3547
3815
  }
3548
3816
 
3549
3817
  template <typename T>
3550
- template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3551
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3818
+ template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3819
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3552
3820
  const char* utf8name,
3553
3821
  napi_property_attributes attributes,
3554
3822
  void* data) {
3555
3823
  napi_property_descriptor desc = napi_property_descriptor();
3556
3824
  desc.utf8name = utf8name;
3557
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3825
+ desc.method = details::TemplatedVoidCallback<method>;
3558
3826
  desc.data = data;
3559
- desc.attributes = attributes;
3827
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3560
3828
  return desc;
3561
3829
  }
3562
3830
 
3563
3831
  template <typename T>
3564
- template <typename ObjectWrap<T>::InstanceMethodCallback method>
3565
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3566
- const char* utf8name,
3832
+ template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3833
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3834
+ Symbol name,
3567
3835
  napi_property_attributes attributes,
3568
3836
  void* data) {
3569
3837
  napi_property_descriptor desc = napi_property_descriptor();
3570
- desc.utf8name = utf8name;
3571
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3838
+ desc.name = name;
3839
+ desc.method = details::TemplatedVoidCallback<method>;
3572
3840
  desc.data = data;
3573
- desc.attributes = attributes;
3841
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3574
3842
  return desc;
3575
3843
  }
3576
3844
 
3577
3845
  template <typename T>
3578
- template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3579
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3580
- Symbol name,
3846
+ template <typename ObjectWrap<T>::StaticMethodCallback method>
3847
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3848
+ const char* utf8name,
3581
3849
  napi_property_attributes attributes,
3582
3850
  void* data) {
3583
3851
  napi_property_descriptor desc = napi_property_descriptor();
3584
- desc.name = name;
3585
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3852
+ desc.utf8name = utf8name;
3853
+ desc.method = details::TemplatedCallback<method>;
3586
3854
  desc.data = data;
3587
- desc.attributes = attributes;
3855
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3588
3856
  return desc;
3589
3857
  }
3590
3858
 
3591
3859
  template <typename T>
3592
- template <typename ObjectWrap<T>::InstanceMethodCallback method>
3593
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3860
+ template <typename ObjectWrap<T>::StaticMethodCallback method>
3861
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3594
3862
  Symbol name,
3595
3863
  napi_property_attributes attributes,
3596
3864
  void* data) {
3597
3865
  napi_property_descriptor desc = napi_property_descriptor();
3598
3866
  desc.name = name;
3599
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3867
+ desc.method = details::TemplatedCallback<method>;
3600
3868
  desc.data = data;
3601
- desc.attributes = attributes;
3869
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3602
3870
  return desc;
3603
3871
  }
3604
3872
 
3605
3873
  template <typename T>
3606
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3874
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3607
3875
  const char* utf8name,
3608
- InstanceGetterCallback getter,
3609
- InstanceSetterCallback setter,
3876
+ StaticGetterCallback getter,
3877
+ StaticSetterCallback setter,
3610
3878
  napi_property_attributes attributes,
3611
3879
  void* data) {
3612
- InstanceAccessorCallbackData* callbackData =
3613
- new InstanceAccessorCallbackData({ getter, setter, data });
3880
+ StaticAccessorCallbackData* callbackData =
3881
+ new StaticAccessorCallbackData({ getter, setter, data });
3614
3882
 
3615
3883
  napi_property_descriptor desc = napi_property_descriptor();
3616
3884
  desc.utf8name = utf8name;
3617
- desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3618
- desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3885
+ desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3886
+ desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3619
3887
  desc.data = callbackData;
3620
- desc.attributes = attributes;
3888
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3621
3889
  return desc;
3622
3890
  }
3623
3891
 
3624
3892
  template <typename T>
3625
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3893
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3626
3894
  Symbol name,
3627
- InstanceGetterCallback getter,
3628
- InstanceSetterCallback setter,
3895
+ StaticGetterCallback getter,
3896
+ StaticSetterCallback setter,
3629
3897
  napi_property_attributes attributes,
3630
3898
  void* data) {
3631
- InstanceAccessorCallbackData* callbackData =
3632
- new InstanceAccessorCallbackData({ getter, setter, data });
3899
+ StaticAccessorCallbackData* callbackData =
3900
+ new StaticAccessorCallbackData({ getter, setter, data });
3633
3901
 
3634
3902
  napi_property_descriptor desc = napi_property_descriptor();
3635
3903
  desc.name = name;
3636
- desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3637
- desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3904
+ desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3905
+ desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3638
3906
  desc.data = callbackData;
3639
- desc.attributes = attributes;
3907
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3640
3908
  return desc;
3641
3909
  }
3642
3910
 
3643
3911
  template <typename T>
3644
- template <typename ObjectWrap<T>::InstanceGetterCallback getter,
3645
- typename ObjectWrap<T>::InstanceSetterCallback setter>
3646
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3912
+ template <typename ObjectWrap<T>::StaticGetterCallback getter,
3913
+ typename ObjectWrap<T>::StaticSetterCallback setter>
3914
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3647
3915
  const char* utf8name,
3648
3916
  napi_property_attributes attributes,
3649
3917
  void* data) {
3650
3918
  napi_property_descriptor desc = napi_property_descriptor();
3651
3919
  desc.utf8name = utf8name;
3652
- desc.getter = This::WrapGetter(This::GetterTag<getter>());
3653
- desc.setter = This::WrapSetter(This::SetterTag<setter>());
3920
+ desc.getter = details::TemplatedCallback<getter>;
3921
+ desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3654
3922
  desc.data = data;
3655
- desc.attributes = attributes;
3923
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3656
3924
  return desc;
3657
3925
  }
3658
3926
 
3659
3927
  template <typename T>
3660
- template <typename ObjectWrap<T>::InstanceGetterCallback getter,
3661
- typename ObjectWrap<T>::InstanceSetterCallback setter>
3662
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3928
+ template <typename ObjectWrap<T>::StaticGetterCallback getter,
3929
+ typename ObjectWrap<T>::StaticSetterCallback setter>
3930
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3663
3931
  Symbol name,
3664
3932
  napi_property_attributes attributes,
3665
3933
  void* data) {
3666
3934
  napi_property_descriptor desc = napi_property_descriptor();
3667
3935
  desc.name = name;
3668
- desc.getter = This::WrapGetter(This::GetterTag<getter>());
3669
- desc.setter = This::WrapSetter(This::SetterTag<setter>());
3936
+ desc.getter = details::TemplatedCallback<getter>;
3937
+ desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3670
3938
  desc.data = data;
3671
- desc.attributes = attributes;
3939
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3672
3940
  return desc;
3673
3941
  }
3674
3942
 
@@ -3681,38 +3949,14 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(const char* utf8nam
3681
3949
  desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3682
3950
  return desc;
3683
3951
  }
3684
-
3685
- template <typename T>
3686
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(Symbol name,
3687
- Napi::Value value, napi_property_attributes attributes) {
3688
- napi_property_descriptor desc = napi_property_descriptor();
3689
- desc.name = name;
3690
- desc.value = value;
3691
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3692
- return desc;
3693
- }
3694
-
3695
- template <typename T>
3696
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
3697
- const char* utf8name,
3698
- Napi::Value value,
3699
- napi_property_attributes attributes) {
3700
- napi_property_descriptor desc = napi_property_descriptor();
3701
- desc.utf8name = utf8name;
3702
- desc.value = value;
3703
- desc.attributes = attributes;
3704
- return desc;
3705
- }
3706
-
3707
- template <typename T>
3708
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
3709
- Symbol name,
3710
- Napi::Value value,
3711
- napi_property_attributes attributes) {
3952
+
3953
+ template <typename T>
3954
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(Symbol name,
3955
+ Napi::Value value, napi_property_attributes attributes) {
3712
3956
  napi_property_descriptor desc = napi_property_descriptor();
3713
3957
  desc.name = name;
3714
3958
  desc.value = value;
3715
- desc.attributes = attributes;
3959
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3716
3960
  return desc;
3717
3961
  }
3718
3962
 
@@ -3808,116 +4052,18 @@ inline napi_value ObjectWrap<T>::StaticSetterCallbackWrapper(
3808
4052
  });
3809
4053
  }
3810
4054
 
3811
- template <typename T>
3812
- inline napi_value ObjectWrap<T>::InstanceVoidMethodCallbackWrapper(
3813
- napi_env env,
3814
- napi_callback_info info) {
3815
- return details::WrapCallback([&] {
3816
- CallbackInfo callbackInfo(env, info);
3817
- InstanceVoidMethodCallbackData* callbackData =
3818
- reinterpret_cast<InstanceVoidMethodCallbackData*>(callbackInfo.Data());
3819
- callbackInfo.SetData(callbackData->data);
3820
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3821
- auto cb = callbackData->callback;
3822
- (instance->*cb)(callbackInfo);
3823
- return nullptr;
3824
- });
3825
- }
3826
-
3827
- template <typename T>
3828
- inline napi_value ObjectWrap<T>::InstanceMethodCallbackWrapper(
3829
- napi_env env,
3830
- napi_callback_info info) {
3831
- return details::WrapCallback([&] {
3832
- CallbackInfo callbackInfo(env, info);
3833
- InstanceMethodCallbackData* callbackData =
3834
- reinterpret_cast<InstanceMethodCallbackData*>(callbackInfo.Data());
3835
- callbackInfo.SetData(callbackData->data);
3836
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3837
- auto cb = callbackData->callback;
3838
- return (instance->*cb)(callbackInfo);
3839
- });
3840
- }
3841
-
3842
- template <typename T>
3843
- inline napi_value ObjectWrap<T>::InstanceGetterCallbackWrapper(
3844
- napi_env env,
3845
- napi_callback_info info) {
3846
- return details::WrapCallback([&] {
3847
- CallbackInfo callbackInfo(env, info);
3848
- InstanceAccessorCallbackData* callbackData =
3849
- reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
3850
- callbackInfo.SetData(callbackData->data);
3851
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3852
- auto cb = callbackData->getterCallback;
3853
- return (instance->*cb)(callbackInfo);
3854
- });
3855
- }
3856
-
3857
- template <typename T>
3858
- inline napi_value ObjectWrap<T>::InstanceSetterCallbackWrapper(
3859
- napi_env env,
3860
- napi_callback_info info) {
3861
- return details::WrapCallback([&] {
3862
- CallbackInfo callbackInfo(env, info);
3863
- InstanceAccessorCallbackData* callbackData =
3864
- reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
3865
- callbackInfo.SetData(callbackData->data);
3866
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3867
- auto cb = callbackData->setterCallback;
3868
- (instance->*cb)(callbackInfo, callbackInfo[0]);
3869
- return nullptr;
3870
- });
3871
- }
3872
-
3873
4055
  template <typename T>
3874
4056
  inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hint*/) {
3875
- ObjectWrap<T>* instance = static_cast<ObjectWrap<T>*>(data);
4057
+ HandleScope scope(env);
4058
+ T* instance = static_cast<T*>(data);
3876
4059
  instance->Finalize(Napi::Env(env));
3877
4060
  delete instance;
3878
4061
  }
3879
4062
 
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
4063
  template <typename T>
3919
4064
  template <typename ObjectWrap<T>::StaticSetterCallback method>
3920
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
4065
+ inline napi_value ObjectWrap<T>::WrappedMethod(
4066
+ napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
3921
4067
  return details::WrapCallback([&] {
3922
4068
  const CallbackInfo cbInfo(env, info);
3923
4069
  method(cbInfo, cbInfo[0]);
@@ -3925,17 +4071,6 @@ inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info
3925
4071
  });
3926
4072
  }
3927
4073
 
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
-
3939
4074
  ////////////////////////////////////////////////////////////////////////////////
3940
4075
  // HandleScope class
3941
4076
  ////////////////////////////////////////////////////////////////////////////////
@@ -4041,10 +4176,9 @@ inline AsyncContext::AsyncContext(napi_env env, const char* resource_name)
4041
4176
  }
4042
4177
 
4043
4178
  inline AsyncContext::AsyncContext(napi_env env,
4044
- const char* resource_name,
4179
+ const char* resource_name,
4045
4180
  const Object& resource)
4046
- : _env(env),
4047
- _context(nullptr) {
4181
+ : _env(env), _context(nullptr) {
4048
4182
  napi_value resource_id;
4049
4183
  napi_status status = napi_create_string_utf8(
4050
4184
  _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
@@ -4295,7 +4429,491 @@ inline void AsyncWorker::OnWorkComplete(Napi::Env /*env*/, napi_status status) {
4295
4429
  }
4296
4430
  }
4297
4431
 
4298
- #if (NAPI_VERSION > 3)
4432
+ #if (NAPI_VERSION > 3 && !defined(__wasm32__))
4433
+ ////////////////////////////////////////////////////////////////////////////////
4434
+ // TypedThreadSafeFunction<ContextType,DataType,CallJs> class
4435
+ ////////////////////////////////////////////////////////////////////////////////
4436
+
4437
+ // Starting with NAPI 5, the JavaScript function `func` parameter of
4438
+ // `napi_create_threadsafe_function` is optional.
4439
+ #if NAPI_VERSION > 4
4440
+ // static, with Callback [missing] Resource [missing] Finalizer [missing]
4441
+ template <typename ContextType,
4442
+ typename DataType,
4443
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4444
+ template <typename ResourceString>
4445
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
4446
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
4447
+ napi_env env,
4448
+ ResourceString resourceName,
4449
+ size_t maxQueueSize,
4450
+ size_t initialThreadCount,
4451
+ ContextType* context) {
4452
+ TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
4453
+
4454
+ napi_status status =
4455
+ napi_create_threadsafe_function(env,
4456
+ nullptr,
4457
+ nullptr,
4458
+ String::From(env, resourceName),
4459
+ maxQueueSize,
4460
+ initialThreadCount,
4461
+ nullptr,
4462
+ nullptr,
4463
+ context,
4464
+ CallJsInternal,
4465
+ &tsfn._tsfn);
4466
+ if (status != napi_ok) {
4467
+ NAPI_THROW_IF_FAILED(
4468
+ env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
4469
+ }
4470
+
4471
+ return tsfn;
4472
+ }
4473
+
4474
+ // static, with Callback [missing] Resource [passed] Finalizer [missing]
4475
+ template <typename ContextType,
4476
+ typename DataType,
4477
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4478
+ template <typename ResourceString>
4479
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
4480
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
4481
+ napi_env env,
4482
+ const Object& resource,
4483
+ ResourceString resourceName,
4484
+ size_t maxQueueSize,
4485
+ size_t initialThreadCount,
4486
+ ContextType* context) {
4487
+ TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
4488
+
4489
+ napi_status status =
4490
+ napi_create_threadsafe_function(env,
4491
+ nullptr,
4492
+ resource,
4493
+ String::From(env, resourceName),
4494
+ maxQueueSize,
4495
+ initialThreadCount,
4496
+ nullptr,
4497
+ nullptr,
4498
+ context,
4499
+ CallJsInternal,
4500
+ &tsfn._tsfn);
4501
+ if (status != napi_ok) {
4502
+ NAPI_THROW_IF_FAILED(
4503
+ env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
4504
+ }
4505
+
4506
+ return tsfn;
4507
+ }
4508
+
4509
+ // static, with Callback [missing] Resource [missing] Finalizer [passed]
4510
+ template <typename ContextType,
4511
+ typename DataType,
4512
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4513
+ template <typename ResourceString,
4514
+ typename Finalizer,
4515
+ typename FinalizerDataType>
4516
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
4517
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
4518
+ napi_env env,
4519
+ ResourceString resourceName,
4520
+ size_t maxQueueSize,
4521
+ size_t initialThreadCount,
4522
+ ContextType* context,
4523
+ Finalizer finalizeCallback,
4524
+ FinalizerDataType* data) {
4525
+ TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
4526
+
4527
+ auto* finalizeData = new details::
4528
+ ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
4529
+ {data, finalizeCallback});
4530
+ napi_status status = napi_create_threadsafe_function(
4531
+ env,
4532
+ nullptr,
4533
+ nullptr,
4534
+ String::From(env, resourceName),
4535
+ maxQueueSize,
4536
+ initialThreadCount,
4537
+ finalizeData,
4538
+ details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
4539
+ FinalizeFinalizeWrapperWithDataAndContext,
4540
+ context,
4541
+ CallJsInternal,
4542
+ &tsfn._tsfn);
4543
+ if (status != napi_ok) {
4544
+ delete finalizeData;
4545
+ NAPI_THROW_IF_FAILED(
4546
+ env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
4547
+ }
4548
+
4549
+ return tsfn;
4550
+ }
4551
+
4552
+ // static, with Callback [missing] Resource [passed] Finalizer [passed]
4553
+ template <typename ContextType,
4554
+ typename DataType,
4555
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4556
+ template <typename ResourceString,
4557
+ typename Finalizer,
4558
+ typename FinalizerDataType>
4559
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
4560
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
4561
+ napi_env env,
4562
+ const Object& resource,
4563
+ ResourceString resourceName,
4564
+ size_t maxQueueSize,
4565
+ size_t initialThreadCount,
4566
+ ContextType* context,
4567
+ Finalizer finalizeCallback,
4568
+ FinalizerDataType* data) {
4569
+ TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
4570
+
4571
+ auto* finalizeData = new details::
4572
+ ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
4573
+ {data, finalizeCallback});
4574
+ napi_status status = napi_create_threadsafe_function(
4575
+ env,
4576
+ nullptr,
4577
+ resource,
4578
+ String::From(env, resourceName),
4579
+ maxQueueSize,
4580
+ initialThreadCount,
4581
+ finalizeData,
4582
+ details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
4583
+ FinalizeFinalizeWrapperWithDataAndContext,
4584
+ context,
4585
+ CallJsInternal,
4586
+ &tsfn._tsfn);
4587
+ if (status != napi_ok) {
4588
+ delete finalizeData;
4589
+ NAPI_THROW_IF_FAILED(
4590
+ env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
4591
+ }
4592
+
4593
+ return tsfn;
4594
+ }
4595
+ #endif
4596
+
4597
+ // static, with Callback [passed] Resource [missing] Finalizer [missing]
4598
+ template <typename ContextType,
4599
+ typename DataType,
4600
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4601
+ template <typename ResourceString>
4602
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
4603
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
4604
+ napi_env env,
4605
+ const Function& callback,
4606
+ ResourceString resourceName,
4607
+ size_t maxQueueSize,
4608
+ size_t initialThreadCount,
4609
+ ContextType* context) {
4610
+ TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
4611
+
4612
+ napi_status status =
4613
+ napi_create_threadsafe_function(env,
4614
+ callback,
4615
+ nullptr,
4616
+ String::From(env, resourceName),
4617
+ maxQueueSize,
4618
+ initialThreadCount,
4619
+ nullptr,
4620
+ nullptr,
4621
+ context,
4622
+ CallJsInternal,
4623
+ &tsfn._tsfn);
4624
+ if (status != napi_ok) {
4625
+ NAPI_THROW_IF_FAILED(
4626
+ env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
4627
+ }
4628
+
4629
+ return tsfn;
4630
+ }
4631
+
4632
+ // static, with Callback [passed] Resource [passed] Finalizer [missing]
4633
+ template <typename ContextType,
4634
+ typename DataType,
4635
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4636
+ template <typename ResourceString>
4637
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
4638
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
4639
+ napi_env env,
4640
+ const Function& callback,
4641
+ const Object& resource,
4642
+ ResourceString resourceName,
4643
+ size_t maxQueueSize,
4644
+ size_t initialThreadCount,
4645
+ ContextType* context) {
4646
+ TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
4647
+
4648
+ napi_status status =
4649
+ napi_create_threadsafe_function(env,
4650
+ callback,
4651
+ resource,
4652
+ String::From(env, resourceName),
4653
+ maxQueueSize,
4654
+ initialThreadCount,
4655
+ nullptr,
4656
+ nullptr,
4657
+ context,
4658
+ CallJsInternal,
4659
+ &tsfn._tsfn);
4660
+ if (status != napi_ok) {
4661
+ NAPI_THROW_IF_FAILED(
4662
+ env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
4663
+ }
4664
+
4665
+ return tsfn;
4666
+ }
4667
+
4668
+ // static, with Callback [passed] Resource [missing] Finalizer [passed]
4669
+ template <typename ContextType,
4670
+ typename DataType,
4671
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4672
+ template <typename ResourceString,
4673
+ typename Finalizer,
4674
+ typename FinalizerDataType>
4675
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
4676
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
4677
+ napi_env env,
4678
+ const Function& callback,
4679
+ ResourceString resourceName,
4680
+ size_t maxQueueSize,
4681
+ size_t initialThreadCount,
4682
+ ContextType* context,
4683
+ Finalizer finalizeCallback,
4684
+ FinalizerDataType* data) {
4685
+ TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
4686
+
4687
+ auto* finalizeData = new details::
4688
+ ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
4689
+ {data, finalizeCallback});
4690
+ napi_status status = napi_create_threadsafe_function(
4691
+ env,
4692
+ callback,
4693
+ nullptr,
4694
+ String::From(env, resourceName),
4695
+ maxQueueSize,
4696
+ initialThreadCount,
4697
+ finalizeData,
4698
+ details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
4699
+ FinalizeFinalizeWrapperWithDataAndContext,
4700
+ context,
4701
+ CallJsInternal,
4702
+ &tsfn._tsfn);
4703
+ if (status != napi_ok) {
4704
+ delete finalizeData;
4705
+ NAPI_THROW_IF_FAILED(
4706
+ env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
4707
+ }
4708
+
4709
+ return tsfn;
4710
+ }
4711
+
4712
+ // static, with: Callback [passed] Resource [passed] Finalizer [passed]
4713
+ template <typename ContextType,
4714
+ typename DataType,
4715
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4716
+ template <typename CallbackType,
4717
+ typename ResourceString,
4718
+ typename Finalizer,
4719
+ typename FinalizerDataType>
4720
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>
4721
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
4722
+ napi_env env,
4723
+ CallbackType callback,
4724
+ const Object& resource,
4725
+ ResourceString resourceName,
4726
+ size_t maxQueueSize,
4727
+ size_t initialThreadCount,
4728
+ ContextType* context,
4729
+ Finalizer finalizeCallback,
4730
+ FinalizerDataType* data) {
4731
+ TypedThreadSafeFunction<ContextType, DataType, CallJs> tsfn;
4732
+
4733
+ auto* finalizeData = new details::
4734
+ ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
4735
+ {data, finalizeCallback});
4736
+ napi_status status = napi_create_threadsafe_function(
4737
+ env,
4738
+ details::DefaultCallbackWrapper<
4739
+ CallbackType,
4740
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>>(env,
4741
+ callback),
4742
+ resource,
4743
+ String::From(env, resourceName),
4744
+ maxQueueSize,
4745
+ initialThreadCount,
4746
+ finalizeData,
4747
+ details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
4748
+ FinalizeFinalizeWrapperWithDataAndContext,
4749
+ context,
4750
+ CallJsInternal,
4751
+ &tsfn._tsfn);
4752
+ if (status != napi_ok) {
4753
+ delete finalizeData;
4754
+ NAPI_THROW_IF_FAILED(
4755
+ env, status, TypedThreadSafeFunction<ContextType, DataType, CallJs>());
4756
+ }
4757
+
4758
+ return tsfn;
4759
+ }
4760
+
4761
+ template <typename ContextType,
4762
+ typename DataType,
4763
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4764
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>::
4765
+ TypedThreadSafeFunction()
4766
+ : _tsfn() {}
4767
+
4768
+ template <typename ContextType,
4769
+ typename DataType,
4770
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4771
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>::
4772
+ TypedThreadSafeFunction(napi_threadsafe_function tsfn)
4773
+ : _tsfn(tsfn) {}
4774
+
4775
+ template <typename ContextType,
4776
+ typename DataType,
4777
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4778
+ inline TypedThreadSafeFunction<ContextType, DataType, CallJs>::
4779
+ operator napi_threadsafe_function() const {
4780
+ return _tsfn;
4781
+ }
4782
+
4783
+ template <typename ContextType,
4784
+ typename DataType,
4785
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4786
+ inline napi_status
4787
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::BlockingCall(
4788
+ DataType* data) const {
4789
+ return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_blocking);
4790
+ }
4791
+
4792
+ template <typename ContextType,
4793
+ typename DataType,
4794
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4795
+ inline napi_status
4796
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::NonBlockingCall(
4797
+ DataType* data) const {
4798
+ return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_nonblocking);
4799
+ }
4800
+
4801
+ template <typename ContextType,
4802
+ typename DataType,
4803
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4804
+ inline void TypedThreadSafeFunction<ContextType, DataType, CallJs>::Ref(
4805
+ napi_env env) const {
4806
+ if (_tsfn != nullptr) {
4807
+ napi_status status = napi_ref_threadsafe_function(env, _tsfn);
4808
+ NAPI_THROW_IF_FAILED_VOID(env, status);
4809
+ }
4810
+ }
4811
+
4812
+ template <typename ContextType,
4813
+ typename DataType,
4814
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4815
+ inline void TypedThreadSafeFunction<ContextType, DataType, CallJs>::Unref(
4816
+ napi_env env) const {
4817
+ if (_tsfn != nullptr) {
4818
+ napi_status status = napi_unref_threadsafe_function(env, _tsfn);
4819
+ NAPI_THROW_IF_FAILED_VOID(env, status);
4820
+ }
4821
+ }
4822
+
4823
+ template <typename ContextType,
4824
+ typename DataType,
4825
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4826
+ inline napi_status
4827
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::Acquire() const {
4828
+ return napi_acquire_threadsafe_function(_tsfn);
4829
+ }
4830
+
4831
+ template <typename ContextType,
4832
+ typename DataType,
4833
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4834
+ inline napi_status
4835
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::Release() {
4836
+ return napi_release_threadsafe_function(_tsfn, napi_tsfn_release);
4837
+ }
4838
+
4839
+ template <typename ContextType,
4840
+ typename DataType,
4841
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4842
+ inline napi_status
4843
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::Abort() {
4844
+ return napi_release_threadsafe_function(_tsfn, napi_tsfn_abort);
4845
+ }
4846
+
4847
+ template <typename ContextType,
4848
+ typename DataType,
4849
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4850
+ inline ContextType*
4851
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::GetContext() const {
4852
+ void* context;
4853
+ napi_status status = napi_get_threadsafe_function_context(_tsfn, &context);
4854
+ NAPI_FATAL_IF_FAILED(status,
4855
+ "TypedThreadSafeFunction::GetContext",
4856
+ "napi_get_threadsafe_function_context");
4857
+ return static_cast<ContextType*>(context);
4858
+ }
4859
+
4860
+ // static
4861
+ template <typename ContextType,
4862
+ typename DataType,
4863
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4864
+ void TypedThreadSafeFunction<ContextType, DataType, CallJs>::CallJsInternal(
4865
+ napi_env env, napi_value jsCallback, void* context, void* data) {
4866
+ details::CallJsWrapper<ContextType, DataType, decltype(CallJs), CallJs>(
4867
+ env, jsCallback, context, data);
4868
+ }
4869
+
4870
+ #if NAPI_VERSION == 4
4871
+ // static
4872
+ template <typename ContextType,
4873
+ typename DataType,
4874
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4875
+ Napi::Function
4876
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::EmptyFunctionFactory(
4877
+ Napi::Env env) {
4878
+ return Napi::Function::New(env, [](const CallbackInfo& cb) {});
4879
+ }
4880
+
4881
+ // static
4882
+ template <typename ContextType,
4883
+ typename DataType,
4884
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4885
+ Napi::Function
4886
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::FunctionOrEmpty(
4887
+ Napi::Env env, Napi::Function& callback) {
4888
+ if (callback.IsEmpty()) {
4889
+ return EmptyFunctionFactory(env);
4890
+ }
4891
+ return callback;
4892
+ }
4893
+
4894
+ #else
4895
+ // static
4896
+ template <typename ContextType,
4897
+ typename DataType,
4898
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4899
+ std::nullptr_t
4900
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::EmptyFunctionFactory(
4901
+ Napi::Env /*env*/) {
4902
+ return nullptr;
4903
+ }
4904
+
4905
+ // static
4906
+ template <typename ContextType,
4907
+ typename DataType,
4908
+ void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
4909
+ Napi::Function
4910
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::FunctionOrEmpty(
4911
+ Napi::Env /*env*/, Napi::Function& callback) {
4912
+ return callback;
4913
+ }
4914
+
4915
+ #endif
4916
+
4299
4917
  ////////////////////////////////////////////////////////////////////////////////
4300
4918
  // ThreadSafeFunction class
4301
4919
  ////////////////////////////////////////////////////////////////////////////////
@@ -4688,6 +5306,7 @@ inline void AsyncProgressWorkerBase<DataType>::OnAsyncWorkProgress(Napi::Env /*
4688
5306
  void* data) {
4689
5307
  ThreadSafeData* tsd = static_cast<ThreadSafeData*>(data);
4690
5308
  tsd->asyncprogressworker()->OnWorkProgress(tsd->data());
5309
+ delete tsd;
4691
5310
  }
4692
5311
 
4693
5312
  template <typename DataType>
@@ -4809,6 +5428,17 @@ inline void AsyncProgressWorker<T>::OnWorkProgress(void*) {
4809
5428
  this->_asyncsize = 0;
4810
5429
  }
4811
5430
 
5431
+ /**
5432
+ * The callback of ThreadSafeFunction is not been invoked immediately on the
5433
+ * callback of uv_async_t (uv io poll), rather the callback of TSFN is
5434
+ * invoked on the right next uv idle callback. There are chances that during
5435
+ * the deferring the signal of uv_async_t is been sent again, i.e. potential
5436
+ * not coalesced two calls of the TSFN callback.
5437
+ */
5438
+ if (data == nullptr) {
5439
+ return;
5440
+ }
5441
+
4812
5442
  this->OnProgress(data, size);
4813
5443
  delete[] data;
4814
5444
  }
@@ -4962,7 +5592,7 @@ template<class T>
4962
5592
  inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Send(const T* data, size_t count) const {
4963
5593
  _worker->SendProgress_(data, count);
4964
5594
  }
4965
- #endif
5595
+ #endif // NAPI_VERSION > 3 && !defined(__wasm32__)
4966
5596
 
4967
5597
  ////////////////////////////////////////////////////////////////////////////////
4968
5598
  // Memory Management class
@@ -4993,6 +5623,49 @@ inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) {
4993
5623
  return result;
4994
5624
  }
4995
5625
 
5626
+ #if NAPI_VERSION > 5
5627
+ ////////////////////////////////////////////////////////////////////////////////
5628
+ // Addon<T> class
5629
+ ////////////////////////////////////////////////////////////////////////////////
5630
+
5631
+ template <typename T>
5632
+ inline Object Addon<T>::Init(Env env, Object exports) {
5633
+ T* addon = new T(env, exports);
5634
+ env.SetInstanceData(addon);
5635
+ return addon->entry_point_;
5636
+ }
5637
+
5638
+ template <typename T>
5639
+ inline T* Addon<T>::Unwrap(Object wrapper) {
5640
+ return wrapper.Env().GetInstanceData<T>();
5641
+ }
5642
+
5643
+ template <typename T>
5644
+ inline void
5645
+ Addon<T>::DefineAddon(Object exports,
5646
+ const std::initializer_list<AddonProp>& props) {
5647
+ DefineProperties(exports, props);
5648
+ entry_point_ = exports;
5649
+ }
5650
+
5651
+ template <typename T>
5652
+ inline Napi::Object
5653
+ Addon<T>::DefineProperties(Object object,
5654
+ const std::initializer_list<AddonProp>& props) {
5655
+ const napi_property_descriptor* properties =
5656
+ reinterpret_cast<const napi_property_descriptor*>(props.begin());
5657
+ size_t size = props.size();
5658
+ napi_status status = napi_define_properties(object.Env(),
5659
+ object,
5660
+ size,
5661
+ properties);
5662
+ NAPI_THROW_IF_FAILED(object.Env(), status, object);
5663
+ for (size_t idx = 0; idx < size; idx++)
5664
+ T::AttachPropData(object.Env(), object, &properties[idx]);
5665
+ return object;
5666
+ }
5667
+ #endif // NAPI_VERSION > 5
5668
+
4996
5669
  } // namespace Napi
4997
5670
 
4998
5671
  #endif // SRC_NAPI_INL_H_