node-addon-api 3.0.1 → 3.2.1

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 +217 -0
  2. package/README.md +104 -60
  3. package/common.gypi +1 -1
  4. package/index.js +4 -3
  5. package/napi-inl.deprecated.h +8 -8
  6. package/napi-inl.h +1206 -540
  7. package/napi.h +821 -522
  8. package/package-support.json +21 -0
  9. package/package.json +80 -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 -132
  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 -851
  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,20 +136,68 @@ 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;
@@ -196,6 +263,45 @@ struct ThreadSafeFinalize {
196
263
  FinalizerDataType* data;
197
264
  Finalizer callback;
198
265
  };
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
199
305
  #endif // NAPI_VERSION > 3 && !defined(__wasm32__)
200
306
 
201
307
  template <typename Getter, typename Setter>
@@ -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
  ////////////////////////////////////////////////////////////////////////////////
@@ -1808,15 +1971,12 @@ CreateFunction(napi_env env,
1808
1971
  template <Function::VoidCallback cb>
1809
1972
  inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1810
1973
  napi_value result = nullptr;
1811
- napi_status status = napi_create_function(
1812
- env, utf8name, NAPI_AUTO_LENGTH,
1813
- [](napi_env env, napi_callback_info info) {
1814
- CallbackInfo callbackInfo(env, info);
1815
- return details::WrapCallback([&] {
1816
- cb(callbackInfo);
1817
- return nullptr;
1818
- });
1819
- }, data, &result);
1974
+ napi_status status = napi_create_function(env,
1975
+ utf8name,
1976
+ NAPI_AUTO_LENGTH,
1977
+ details::TemplatedVoidCallback<cb>,
1978
+ data,
1979
+ &result);
1820
1980
  NAPI_THROW_IF_FAILED(env, status, Function());
1821
1981
  return Function(env, result);
1822
1982
  }
@@ -1824,14 +1984,12 @@ inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1824
1984
  template <Function::Callback cb>
1825
1985
  inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1826
1986
  napi_value result = nullptr;
1827
- napi_status status = napi_create_function(
1828
- env, utf8name, NAPI_AUTO_LENGTH,
1829
- [](napi_env env, napi_callback_info info) {
1830
- CallbackInfo callbackInfo(env, info);
1831
- return details::WrapCallback([&] {
1832
- return cb(callbackInfo);
1833
- });
1834
- }, data, &result);
1987
+ napi_status status = napi_create_function(env,
1988
+ utf8name,
1989
+ NAPI_AUTO_LENGTH,
1990
+ details::TemplatedCallback<cb>,
1991
+ data,
1992
+ &result);
1835
1993
  NAPI_THROW_IF_FAILED(env, status, Function());
1836
1994
  return Function(env, result);
1837
1995
  }
@@ -1855,8 +2013,8 @@ inline Function Function::New(napi_env env,
1855
2013
  Callable cb,
1856
2014
  const char* utf8name,
1857
2015
  void* data) {
1858
- typedef decltype(cb(CallbackInfo(nullptr, nullptr))) ReturnType;
1859
- typedef details::CallbackData<Callable, ReturnType> CbData;
2016
+ using ReturnType = decltype(cb(CallbackInfo(nullptr, nullptr)));
2017
+ using CbData = details::CallbackData<Callable, ReturnType>;
1860
2018
  auto callbackData = new CbData({ cb, data });
1861
2019
 
1862
2020
  napi_value value;
@@ -2025,7 +2183,8 @@ inline Buffer<T> Buffer<T>::New(napi_env env,
2025
2183
  Finalizer finalizeCallback) {
2026
2184
  napi_value value;
2027
2185
  details::FinalizeData<T, Finalizer>* finalizeData =
2028
- new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
2186
+ new details::FinalizeData<T, Finalizer>(
2187
+ {std::move(finalizeCallback), nullptr});
2029
2188
  napi_status status = napi_create_external_buffer(
2030
2189
  env,
2031
2190
  length * sizeof (T),
@@ -2049,7 +2208,8 @@ inline Buffer<T> Buffer<T>::New(napi_env env,
2049
2208
  Hint* finalizeHint) {
2050
2209
  napi_value value;
2051
2210
  details::FinalizeData<T, Finalizer, Hint>* finalizeData =
2052
- new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
2211
+ new details::FinalizeData<T, Finalizer, Hint>(
2212
+ {std::move(finalizeCallback), finalizeHint});
2053
2213
  napi_status status = napi_create_external_buffer(
2054
2214
  env,
2055
2215
  length * sizeof (T),
@@ -2529,54 +2689,58 @@ inline Napi::Value ObjectReference::Get(const std::string& utf8name) const {
2529
2689
  return scope.Escape(Value().Get(utf8name));
2530
2690
  }
2531
2691
 
2532
- inline void ObjectReference::Set(const char* utf8name, napi_value value) {
2692
+ inline bool ObjectReference::Set(const char* utf8name, napi_value value) {
2533
2693
  HandleScope scope(_env);
2534
- Value().Set(utf8name, value);
2694
+ return Value().Set(utf8name, value);
2535
2695
  }
2536
2696
 
2537
- inline void ObjectReference::Set(const char* utf8name, Napi::Value value) {
2697
+ inline bool ObjectReference::Set(const char* utf8name, Napi::Value value) {
2538
2698
  HandleScope scope(_env);
2539
- Value().Set(utf8name, value);
2699
+ return Value().Set(utf8name, value);
2540
2700
  }
2541
2701
 
2542
- inline void ObjectReference::Set(const char* utf8name, const char* utf8value) {
2702
+ inline bool ObjectReference::Set(const char* utf8name, const char* utf8value) {
2543
2703
  HandleScope scope(_env);
2544
- Value().Set(utf8name, utf8value);
2704
+ return Value().Set(utf8name, utf8value);
2545
2705
  }
2546
2706
 
2547
- inline void ObjectReference::Set(const char* utf8name, bool boolValue) {
2707
+ inline bool ObjectReference::Set(const char* utf8name, bool boolValue) {
2548
2708
  HandleScope scope(_env);
2549
- Value().Set(utf8name, boolValue);
2709
+ return Value().Set(utf8name, boolValue);
2550
2710
  }
2551
2711
 
2552
- inline void ObjectReference::Set(const char* utf8name, double numberValue) {
2712
+ inline bool ObjectReference::Set(const char* utf8name, double numberValue) {
2553
2713
  HandleScope scope(_env);
2554
- Value().Set(utf8name, numberValue);
2714
+ return Value().Set(utf8name, numberValue);
2555
2715
  }
2556
2716
 
2557
- inline void ObjectReference::Set(const std::string& utf8name, napi_value value) {
2717
+ inline bool ObjectReference::Set(const std::string& utf8name,
2718
+ napi_value value) {
2558
2719
  HandleScope scope(_env);
2559
- Value().Set(utf8name, value);
2720
+ return Value().Set(utf8name, value);
2560
2721
  }
2561
2722
 
2562
- inline void ObjectReference::Set(const std::string& utf8name, Napi::Value value) {
2723
+ inline bool ObjectReference::Set(const std::string& utf8name,
2724
+ Napi::Value value) {
2563
2725
  HandleScope scope(_env);
2564
- Value().Set(utf8name, value);
2726
+ return Value().Set(utf8name, value);
2565
2727
  }
2566
2728
 
2567
- inline void ObjectReference::Set(const std::string& utf8name, std::string& utf8value) {
2729
+ inline bool ObjectReference::Set(const std::string& utf8name,
2730
+ std::string& utf8value) {
2568
2731
  HandleScope scope(_env);
2569
- Value().Set(utf8name, utf8value);
2732
+ return Value().Set(utf8name, utf8value);
2570
2733
  }
2571
2734
 
2572
- inline void ObjectReference::Set(const std::string& utf8name, bool boolValue) {
2735
+ inline bool ObjectReference::Set(const std::string& utf8name, bool boolValue) {
2573
2736
  HandleScope scope(_env);
2574
- Value().Set(utf8name, boolValue);
2737
+ return Value().Set(utf8name, boolValue);
2575
2738
  }
2576
2739
 
2577
- inline void ObjectReference::Set(const std::string& utf8name, double numberValue) {
2740
+ inline bool ObjectReference::Set(const std::string& utf8name,
2741
+ double numberValue) {
2578
2742
  HandleScope scope(_env);
2579
- Value().Set(utf8name, numberValue);
2743
+ return Value().Set(utf8name, numberValue);
2580
2744
  }
2581
2745
 
2582
2746
  inline Napi::Value ObjectReference::Get(uint32_t index) const {
@@ -2584,34 +2748,34 @@ inline Napi::Value ObjectReference::Get(uint32_t index) const {
2584
2748
  return scope.Escape(Value().Get(index));
2585
2749
  }
2586
2750
 
2587
- inline void ObjectReference::Set(uint32_t index, napi_value value) {
2751
+ inline bool ObjectReference::Set(uint32_t index, napi_value value) {
2588
2752
  HandleScope scope(_env);
2589
- Value().Set(index, value);
2753
+ return Value().Set(index, value);
2590
2754
  }
2591
2755
 
2592
- inline void ObjectReference::Set(uint32_t index, Napi::Value value) {
2756
+ inline bool ObjectReference::Set(uint32_t index, Napi::Value value) {
2593
2757
  HandleScope scope(_env);
2594
- Value().Set(index, value);
2758
+ return Value().Set(index, value);
2595
2759
  }
2596
2760
 
2597
- inline void ObjectReference::Set(uint32_t index, const char* utf8value) {
2761
+ inline bool ObjectReference::Set(uint32_t index, const char* utf8value) {
2598
2762
  HandleScope scope(_env);
2599
- Value().Set(index, utf8value);
2763
+ return Value().Set(index, utf8value);
2600
2764
  }
2601
2765
 
2602
- inline void ObjectReference::Set(uint32_t index, const std::string& utf8value) {
2766
+ inline bool ObjectReference::Set(uint32_t index, const std::string& utf8value) {
2603
2767
  HandleScope scope(_env);
2604
- Value().Set(index, utf8value);
2768
+ return Value().Set(index, utf8value);
2605
2769
  }
2606
2770
 
2607
- inline void ObjectReference::Set(uint32_t index, bool boolValue) {
2771
+ inline bool ObjectReference::Set(uint32_t index, bool boolValue) {
2608
2772
  HandleScope scope(_env);
2609
- Value().Set(index, boolValue);
2773
+ return Value().Set(index, boolValue);
2610
2774
  }
2611
2775
 
2612
- inline void ObjectReference::Set(uint32_t index, double numberValue) {
2776
+ inline bool ObjectReference::Set(uint32_t index, double numberValue) {
2613
2777
  HandleScope scope(_env);
2614
- Value().Set(index, numberValue);
2778
+ return Value().Set(index, numberValue);
2615
2779
  }
2616
2780
 
2617
2781
  ////////////////////////////////////////////////////////////////////////////////
@@ -2822,7 +2986,7 @@ PropertyDescriptor::Accessor(const char* utf8name,
2822
2986
  napi_property_descriptor desc = napi_property_descriptor();
2823
2987
 
2824
2988
  desc.utf8name = utf8name;
2825
- desc.getter = &GetterCallbackWrapper<Getter>;
2989
+ desc.getter = details::TemplatedCallback<Getter>;
2826
2990
  desc.attributes = attributes;
2827
2991
  desc.data = data;
2828
2992
 
@@ -2845,7 +3009,7 @@ PropertyDescriptor::Accessor(Name name,
2845
3009
  napi_property_descriptor desc = napi_property_descriptor();
2846
3010
 
2847
3011
  desc.name = name;
2848
- desc.getter = &GetterCallbackWrapper<Getter>;
3012
+ desc.getter = details::TemplatedCallback<Getter>;
2849
3013
  desc.attributes = attributes;
2850
3014
  desc.data = data;
2851
3015
 
@@ -2863,8 +3027,8 @@ PropertyDescriptor::Accessor(const char* utf8name,
2863
3027
  napi_property_descriptor desc = napi_property_descriptor();
2864
3028
 
2865
3029
  desc.utf8name = utf8name;
2866
- desc.getter = &GetterCallbackWrapper<Getter>;
2867
- desc.setter = &SetterCallbackWrapper<Setter>;
3030
+ desc.getter = details::TemplatedCallback<Getter>;
3031
+ desc.setter = details::TemplatedVoidCallback<Setter>;
2868
3032
  desc.attributes = attributes;
2869
3033
  desc.data = data;
2870
3034
 
@@ -2891,31 +3055,14 @@ PropertyDescriptor::Accessor(Name name,
2891
3055
  napi_property_descriptor desc = napi_property_descriptor();
2892
3056
 
2893
3057
  desc.name = name;
2894
- desc.getter = &GetterCallbackWrapper<Getter>;
2895
- desc.setter = &SetterCallbackWrapper<Setter>;
3058
+ desc.getter = details::TemplatedCallback<Getter>;
3059
+ desc.setter = details::TemplatedVoidCallback<Setter>;
2896
3060
  desc.attributes = attributes;
2897
3061
  desc.data = data;
2898
3062
 
2899
3063
  return desc;
2900
3064
  }
2901
3065
 
2902
- template <typename PropertyDescriptor::GetterCallback Getter>
2903
- napi_value
2904
- PropertyDescriptor::GetterCallbackWrapper(napi_env env,
2905
- napi_callback_info info) {
2906
- CallbackInfo cbInfo(env, info);
2907
- return Getter(cbInfo);
2908
- }
2909
-
2910
- template <typename PropertyDescriptor::SetterCallback Setter>
2911
- napi_value
2912
- PropertyDescriptor::SetterCallbackWrapper(napi_env env,
2913
- napi_callback_info info) {
2914
- CallbackInfo cbInfo(env, info);
2915
- Setter(cbInfo);
2916
- return nullptr;
2917
- }
2918
-
2919
3066
  template <typename Getter>
2920
3067
  inline PropertyDescriptor
2921
3068
  PropertyDescriptor::Accessor(Napi::Env env,
@@ -2924,7 +3071,7 @@ PropertyDescriptor::Accessor(Napi::Env env,
2924
3071
  Getter getter,
2925
3072
  napi_property_attributes attributes,
2926
3073
  void* data) {
2927
- typedef details::CallbackData<Getter, Napi::Value> CbData;
3074
+ using CbData = details::CallbackData<Getter, Napi::Value>;
2928
3075
  auto callbackData = new CbData({ getter, data });
2929
3076
 
2930
3077
  napi_status status = AttachData(env, object, callbackData);
@@ -2962,7 +3109,7 @@ inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
2962
3109
  Getter getter,
2963
3110
  napi_property_attributes attributes,
2964
3111
  void* data) {
2965
- typedef details::CallbackData<Getter, Napi::Value> CbData;
3112
+ using CbData = details::CallbackData<Getter, Napi::Value>;
2966
3113
  auto callbackData = new CbData({ getter, data });
2967
3114
 
2968
3115
  napi_status status = AttachData(env, object, callbackData);
@@ -2991,7 +3138,7 @@ inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
2991
3138
  Setter setter,
2992
3139
  napi_property_attributes attributes,
2993
3140
  void* data) {
2994
- typedef details::AccessorCallbackData<Getter, Setter> CbData;
3141
+ using CbData = details::AccessorCallbackData<Getter, Setter>;
2995
3142
  auto callbackData = new CbData({ getter, setter, data });
2996
3143
 
2997
3144
  napi_status status = AttachData(env, object, callbackData);
@@ -3031,7 +3178,7 @@ inline PropertyDescriptor PropertyDescriptor::Accessor(Napi::Env env,
3031
3178
  Setter setter,
3032
3179
  napi_property_attributes attributes,
3033
3180
  void* data) {
3034
- typedef details::AccessorCallbackData<Getter, Setter> CbData;
3181
+ using CbData = details::AccessorCallbackData<Getter, Setter>;
3035
3182
  auto callbackData = new CbData({ getter, setter, data });
3036
3183
 
3037
3184
  napi_status status = AttachData(env, object, callbackData);
@@ -3143,539 +3290,653 @@ inline PropertyDescriptor::operator const napi_property_descriptor&() const {
3143
3290
  }
3144
3291
 
3145
3292
  ////////////////////////////////////////////////////////////////////////////////
3146
- // ObjectWrap<T> class
3293
+ // InstanceWrap<T> class
3147
3294
  ////////////////////////////////////////////////////////////////////////////////
3148
3295
 
3149
3296
  template <typename T>
3150
- inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
3151
- napi_env env = callbackInfo.Env();
3152
- napi_value wrapper = callbackInfo.This();
3153
- napi_status status;
3154
- napi_ref ref;
3155
- T* instance = static_cast<T*>(this);
3156
- status = napi_wrap(env, wrapper, instance, FinalizeCallback, nullptr, &ref);
3157
- NAPI_THROW_IF_FAILED_VOID(env, status);
3158
-
3159
- Reference<Object>* instanceRef = instance;
3160
- *instanceRef = Reference<Object>(env, ref);
3161
- }
3162
-
3163
- template <typename T>
3164
- inline ObjectWrap<T>::~ObjectWrap() {
3165
- // If the JS object still exists at this point, remove the finalizer added
3166
- // through `napi_wrap()`.
3167
- if (!IsEmpty()) {
3168
- Object object = Value();
3169
- // It is not valid to call `napi_remove_wrap()` with an empty `object`.
3170
- // This happens e.g. during garbage collection.
3171
- if (!object.IsEmpty() && _construction_failed) {
3172
- napi_remove_wrap(Env(), object, nullptr);
3173
- }
3174
- }
3175
- }
3176
-
3177
- template<typename T>
3178
- inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
3179
- T* unwrapped;
3180
- napi_status status = napi_unwrap(wrapper.Env(), wrapper, reinterpret_cast<void**>(&unwrapped));
3181
- NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
3182
- return unwrapped;
3183
- }
3184
-
3185
- template <typename T>
3186
- inline Function
3187
- ObjectWrap<T>::DefineClass(Napi::Env env,
3188
- const char* utf8name,
3189
- const size_t props_count,
3190
- const napi_property_descriptor* descriptors,
3191
- void* data) {
3297
+ inline void InstanceWrap<T>::AttachPropData(napi_env env,
3298
+ napi_value value,
3299
+ const napi_property_descriptor* prop) {
3192
3300
  napi_status status;
3193
- std::vector<napi_property_descriptor> props(props_count);
3194
-
3195
- // We copy the descriptors to a local array because before defining the class
3196
- // we must replace static method property descriptors with value property
3197
- // descriptors such that the value is a function-valued `napi_value` created
3198
- // with `CreateFunction()`.
3199
- //
3200
- // This replacement could be made for instance methods as well, but V8 aborts
3201
- // if we do that, because it expects methods defined on the prototype template
3202
- // to have `FunctionTemplate`s.
3203
- for (size_t index = 0; index < props_count; index++) {
3204
- props[index] = descriptors[index];
3205
- napi_property_descriptor* prop = &props[index];
3206
- if (prop->method == T::StaticMethodCallbackWrapper) {
3207
- status = CreateFunction(env,
3208
- utf8name,
3209
- prop->method,
3210
- static_cast<StaticMethodCallbackData*>(prop->data),
3211
- &(prop->value));
3212
- NAPI_THROW_IF_FAILED(env, status, Function());
3213
- prop->method = nullptr;
3214
- prop->data = nullptr;
3215
- } else if (prop->method == T::StaticVoidMethodCallbackWrapper) {
3216
- status = CreateFunction(env,
3217
- utf8name,
3218
- prop->method,
3219
- static_cast<StaticVoidMethodCallbackData*>(prop->data),
3220
- &(prop->value));
3221
- NAPI_THROW_IF_FAILED(env, status, Function());
3222
- prop->method = nullptr;
3223
- prop->data = nullptr;
3224
- }
3225
- }
3226
-
3227
- napi_value value;
3228
- status = napi_define_class(env,
3229
- utf8name,
3230
- NAPI_AUTO_LENGTH,
3231
- T::ConstructorCallbackWrapper,
3232
- data,
3233
- props_count,
3234
- props.data(),
3235
- &value);
3236
- NAPI_THROW_IF_FAILED(env, status, Function());
3237
-
3238
- // After defining the class we iterate once more over the property descriptors
3239
- // and attach the data associated with accessors and instance methods to the
3240
- // newly created JavaScript class.
3241
- for (size_t idx = 0; idx < props_count; idx++) {
3242
- const napi_property_descriptor* prop = &props[idx];
3243
-
3244
- if (prop->getter == T::StaticGetterCallbackWrapper ||
3245
- prop->setter == T::StaticSetterCallbackWrapper) {
3301
+ if (!(prop->attributes & napi_static)) {
3302
+ if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
3246
3303
  status = Napi::details::AttachData(env,
3247
- value,
3248
- static_cast<StaticAccessorCallbackData*>(prop->data));
3249
- 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);
3250
3312
  } else if (prop->getter == T::InstanceGetterCallbackWrapper ||
3251
3313
  prop->setter == T::InstanceSetterCallbackWrapper) {
3252
3314
  status = Napi::details::AttachData(env,
3253
3315
  value,
3254
3316
  static_cast<InstanceAccessorCallbackData*>(prop->data));
3255
- NAPI_THROW_IF_FAILED(env, status, Function());
3256
- } else if (prop->method != nullptr && !(prop->attributes & napi_static)) {
3257
- if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
3258
- status = Napi::details::AttachData(env,
3259
- value,
3260
- static_cast<InstanceVoidMethodCallbackData*>(prop->data));
3261
- NAPI_THROW_IF_FAILED(env, status, Function());
3262
- } else if (prop->method == T::InstanceMethodCallbackWrapper) {
3263
- status = Napi::details::AttachData(env,
3264
- value,
3265
- static_cast<InstanceMethodCallbackData*>(prop->data));
3266
- NAPI_THROW_IF_FAILED(env, status, Function());
3267
- }
3317
+ NAPI_THROW_IF_FAILED_VOID(env, status);
3268
3318
  }
3269
3319
  }
3270
-
3271
- return Function(env, value);
3272
- }
3273
-
3274
- template <typename T>
3275
- inline Function ObjectWrap<T>::DefineClass(
3276
- Napi::Env env,
3277
- const char* utf8name,
3278
- const std::initializer_list<ClassPropertyDescriptor<T>>& properties,
3279
- void* data) {
3280
- return DefineClass(env,
3281
- utf8name,
3282
- properties.size(),
3283
- reinterpret_cast<const napi_property_descriptor*>(properties.begin()),
3284
- data);
3285
- }
3286
-
3287
- template <typename T>
3288
- inline Function ObjectWrap<T>::DefineClass(
3289
- Napi::Env env,
3290
- const char* utf8name,
3291
- const std::vector<ClassPropertyDescriptor<T>>& properties,
3292
- void* data) {
3293
- return DefineClass(env,
3294
- utf8name,
3295
- properties.size(),
3296
- reinterpret_cast<const napi_property_descriptor*>(properties.data()),
3297
- data);
3298
3320
  }
3299
3321
 
3300
3322
  template <typename T>
3301
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3323
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3302
3324
  const char* utf8name,
3303
- StaticVoidMethodCallback method,
3325
+ InstanceVoidMethodCallback method,
3304
3326
  napi_property_attributes attributes,
3305
3327
  void* data) {
3306
- StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3328
+ InstanceVoidMethodCallbackData* callbackData =
3329
+ new InstanceVoidMethodCallbackData({ method, data});
3307
3330
 
3308
3331
  napi_property_descriptor desc = napi_property_descriptor();
3309
3332
  desc.utf8name = utf8name;
3310
- desc.method = T::StaticVoidMethodCallbackWrapper;
3333
+ desc.method = T::InstanceVoidMethodCallbackWrapper;
3311
3334
  desc.data = callbackData;
3312
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3335
+ desc.attributes = attributes;
3313
3336
  return desc;
3314
3337
  }
3315
3338
 
3316
3339
  template <typename T>
3317
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3340
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3318
3341
  const char* utf8name,
3319
- StaticMethodCallback method,
3342
+ InstanceMethodCallback method,
3320
3343
  napi_property_attributes attributes,
3321
3344
  void* data) {
3322
- StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3345
+ InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3323
3346
 
3324
3347
  napi_property_descriptor desc = napi_property_descriptor();
3325
3348
  desc.utf8name = utf8name;
3326
- desc.method = T::StaticMethodCallbackWrapper;
3349
+ desc.method = T::InstanceMethodCallbackWrapper;
3327
3350
  desc.data = callbackData;
3328
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3351
+ desc.attributes = attributes;
3329
3352
  return desc;
3330
3353
  }
3331
3354
 
3332
3355
  template <typename T>
3333
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3356
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3334
3357
  Symbol name,
3335
- StaticVoidMethodCallback method,
3358
+ InstanceVoidMethodCallback method,
3336
3359
  napi_property_attributes attributes,
3337
3360
  void* data) {
3338
- StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3361
+ InstanceVoidMethodCallbackData* callbackData =
3362
+ new InstanceVoidMethodCallbackData({ method, data});
3339
3363
 
3340
3364
  napi_property_descriptor desc = napi_property_descriptor();
3341
3365
  desc.name = name;
3342
- desc.method = T::StaticVoidMethodCallbackWrapper;
3366
+ desc.method = T::InstanceVoidMethodCallbackWrapper;
3343
3367
  desc.data = callbackData;
3344
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3368
+ desc.attributes = attributes;
3345
3369
  return desc;
3346
3370
  }
3347
3371
 
3348
3372
  template <typename T>
3349
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3373
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3350
3374
  Symbol name,
3351
- StaticMethodCallback method,
3375
+ InstanceMethodCallback method,
3352
3376
  napi_property_attributes attributes,
3353
3377
  void* data) {
3354
- StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3378
+ InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3355
3379
 
3356
3380
  napi_property_descriptor desc = napi_property_descriptor();
3357
3381
  desc.name = name;
3358
- desc.method = T::StaticMethodCallbackWrapper;
3382
+ desc.method = T::InstanceMethodCallbackWrapper;
3359
3383
  desc.data = callbackData;
3360
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3384
+ desc.attributes = attributes;
3361
3385
  return desc;
3362
3386
  }
3363
3387
 
3364
3388
  template <typename T>
3365
- template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3366
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3389
+ template <typename InstanceWrap<T>::InstanceVoidMethodCallback method>
3390
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3367
3391
  const char* utf8name,
3368
3392
  napi_property_attributes attributes,
3369
3393
  void* data) {
3370
3394
  napi_property_descriptor desc = napi_property_descriptor();
3371
3395
  desc.utf8name = utf8name;
3372
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3396
+ desc.method = details::TemplatedInstanceVoidCallback<T, method>;
3373
3397
  desc.data = data;
3374
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3398
+ desc.attributes = attributes;
3375
3399
  return desc;
3376
3400
  }
3377
3401
 
3378
3402
  template <typename T>
3379
- template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3380
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3381
- Symbol name,
3403
+ template <typename InstanceWrap<T>::InstanceMethodCallback method>
3404
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3405
+ const char* utf8name,
3382
3406
  napi_property_attributes attributes,
3383
3407
  void* data) {
3384
3408
  napi_property_descriptor desc = napi_property_descriptor();
3385
- desc.name = name;
3386
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3409
+ desc.utf8name = utf8name;
3410
+ desc.method = details::TemplatedInstanceCallback<T, method>;
3387
3411
  desc.data = data;
3388
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3412
+ desc.attributes = attributes;
3389
3413
  return desc;
3390
3414
  }
3391
3415
 
3392
3416
  template <typename T>
3393
- template <typename ObjectWrap<T>::StaticMethodCallback method>
3394
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3395
- const char* utf8name,
3417
+ template <typename InstanceWrap<T>::InstanceVoidMethodCallback method>
3418
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3419
+ Symbol name,
3396
3420
  napi_property_attributes attributes,
3397
3421
  void* data) {
3398
3422
  napi_property_descriptor desc = napi_property_descriptor();
3399
- desc.utf8name = utf8name;
3400
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3423
+ desc.name = name;
3424
+ desc.method = details::TemplatedInstanceVoidCallback<T, method>;
3401
3425
  desc.data = data;
3402
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3426
+ desc.attributes = attributes;
3403
3427
  return desc;
3404
3428
  }
3405
3429
 
3406
3430
  template <typename T>
3407
- template <typename ObjectWrap<T>::StaticMethodCallback method>
3408
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3431
+ template <typename InstanceWrap<T>::InstanceMethodCallback method>
3432
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3409
3433
  Symbol name,
3410
3434
  napi_property_attributes attributes,
3411
3435
  void* data) {
3412
3436
  napi_property_descriptor desc = napi_property_descriptor();
3413
3437
  desc.name = name;
3414
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3438
+ desc.method = details::TemplatedInstanceCallback<T, method>;
3415
3439
  desc.data = data;
3416
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3440
+ desc.attributes = attributes;
3417
3441
  return desc;
3418
3442
  }
3419
3443
 
3420
3444
  template <typename T>
3421
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3445
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
3422
3446
  const char* utf8name,
3423
- StaticGetterCallback getter,
3424
- StaticSetterCallback setter,
3447
+ InstanceGetterCallback getter,
3448
+ InstanceSetterCallback setter,
3425
3449
  napi_property_attributes attributes,
3426
3450
  void* data) {
3427
- StaticAccessorCallbackData* callbackData =
3428
- new StaticAccessorCallbackData({ getter, setter, data });
3451
+ InstanceAccessorCallbackData* callbackData =
3452
+ new InstanceAccessorCallbackData({ getter, setter, data });
3429
3453
 
3430
3454
  napi_property_descriptor desc = napi_property_descriptor();
3431
3455
  desc.utf8name = utf8name;
3432
- desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3433
- desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3456
+ desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3457
+ desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3434
3458
  desc.data = callbackData;
3435
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3459
+ desc.attributes = attributes;
3436
3460
  return desc;
3437
3461
  }
3438
3462
 
3439
3463
  template <typename T>
3440
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3464
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
3441
3465
  Symbol name,
3442
- StaticGetterCallback getter,
3443
- StaticSetterCallback setter,
3466
+ InstanceGetterCallback getter,
3467
+ InstanceSetterCallback setter,
3444
3468
  napi_property_attributes attributes,
3445
3469
  void* data) {
3446
- StaticAccessorCallbackData* callbackData =
3447
- new StaticAccessorCallbackData({ getter, setter, data });
3470
+ InstanceAccessorCallbackData* callbackData =
3471
+ new InstanceAccessorCallbackData({ getter, setter, data });
3448
3472
 
3449
3473
  napi_property_descriptor desc = napi_property_descriptor();
3450
3474
  desc.name = name;
3451
- desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3452
- desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3475
+ desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3476
+ desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3453
3477
  desc.data = callbackData;
3454
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3478
+ desc.attributes = attributes;
3455
3479
  return desc;
3456
3480
  }
3457
3481
 
3458
3482
  template <typename T>
3459
- template <typename ObjectWrap<T>::StaticGetterCallback getter,
3460
- typename ObjectWrap<T>::StaticSetterCallback setter>
3461
- 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(
3462
3486
  const char* utf8name,
3463
3487
  napi_property_attributes attributes,
3464
3488
  void* data) {
3465
3489
  napi_property_descriptor desc = napi_property_descriptor();
3466
3490
  desc.utf8name = utf8name;
3467
- desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
3468
- desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3491
+ desc.getter = details::TemplatedInstanceCallback<T, getter>;
3492
+ desc.setter = This::WrapSetter(This::SetterTag<setter>());
3469
3493
  desc.data = data;
3470
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3494
+ desc.attributes = attributes;
3471
3495
  return desc;
3472
3496
  }
3473
3497
 
3474
3498
  template <typename T>
3475
- template <typename ObjectWrap<T>::StaticGetterCallback getter,
3476
- typename ObjectWrap<T>::StaticSetterCallback setter>
3477
- 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(
3478
3502
  Symbol name,
3479
3503
  napi_property_attributes attributes,
3480
3504
  void* data) {
3481
3505
  napi_property_descriptor desc = napi_property_descriptor();
3482
3506
  desc.name = name;
3483
- desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
3484
- desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3507
+ desc.getter = details::TemplatedInstanceCallback<T, getter>;
3508
+ desc.setter = This::WrapSetter(This::SetterTag<setter>());
3485
3509
  desc.data = data;
3486
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3510
+ desc.attributes = attributes;
3487
3511
  return desc;
3488
3512
  }
3489
3513
 
3490
3514
  template <typename T>
3491
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3515
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceValue(
3492
3516
  const char* utf8name,
3493
- 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,
3494
3757
  napi_property_attributes attributes,
3495
3758
  void* data) {
3496
- InstanceVoidMethodCallbackData* callbackData =
3497
- new InstanceVoidMethodCallbackData({ method, data});
3759
+ StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3498
3760
 
3499
3761
  napi_property_descriptor desc = napi_property_descriptor();
3500
3762
  desc.utf8name = utf8name;
3501
- desc.method = T::InstanceVoidMethodCallbackWrapper;
3763
+ desc.method = T::StaticVoidMethodCallbackWrapper;
3502
3764
  desc.data = callbackData;
3503
- desc.attributes = attributes;
3765
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3504
3766
  return desc;
3505
3767
  }
3506
3768
 
3507
3769
  template <typename T>
3508
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3770
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3509
3771
  const char* utf8name,
3510
- InstanceMethodCallback method,
3772
+ StaticMethodCallback method,
3511
3773
  napi_property_attributes attributes,
3512
3774
  void* data) {
3513
- InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3775
+ StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3514
3776
 
3515
3777
  napi_property_descriptor desc = napi_property_descriptor();
3516
3778
  desc.utf8name = utf8name;
3517
- desc.method = T::InstanceMethodCallbackWrapper;
3779
+ desc.method = T::StaticMethodCallbackWrapper;
3518
3780
  desc.data = callbackData;
3519
- desc.attributes = attributes;
3781
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3520
3782
  return desc;
3521
3783
  }
3522
3784
 
3523
3785
  template <typename T>
3524
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3786
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3525
3787
  Symbol name,
3526
- InstanceVoidMethodCallback method,
3788
+ StaticVoidMethodCallback method,
3527
3789
  napi_property_attributes attributes,
3528
3790
  void* data) {
3529
- InstanceVoidMethodCallbackData* callbackData =
3530
- new InstanceVoidMethodCallbackData({ method, data});
3791
+ StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3531
3792
 
3532
3793
  napi_property_descriptor desc = napi_property_descriptor();
3533
3794
  desc.name = name;
3534
- desc.method = T::InstanceVoidMethodCallbackWrapper;
3795
+ desc.method = T::StaticVoidMethodCallbackWrapper;
3535
3796
  desc.data = callbackData;
3536
- desc.attributes = attributes;
3797
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3537
3798
  return desc;
3538
3799
  }
3539
3800
 
3540
3801
  template <typename T>
3541
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3802
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3542
3803
  Symbol name,
3543
- InstanceMethodCallback method,
3804
+ StaticMethodCallback method,
3544
3805
  napi_property_attributes attributes,
3545
3806
  void* data) {
3546
- InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3807
+ StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3547
3808
 
3548
3809
  napi_property_descriptor desc = napi_property_descriptor();
3549
3810
  desc.name = name;
3550
- desc.method = T::InstanceMethodCallbackWrapper;
3811
+ desc.method = T::StaticMethodCallbackWrapper;
3551
3812
  desc.data = callbackData;
3552
- desc.attributes = attributes;
3813
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3553
3814
  return desc;
3554
3815
  }
3555
3816
 
3556
3817
  template <typename T>
3557
- template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3558
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3818
+ template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3819
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3559
3820
  const char* utf8name,
3560
3821
  napi_property_attributes attributes,
3561
3822
  void* data) {
3562
3823
  napi_property_descriptor desc = napi_property_descriptor();
3563
3824
  desc.utf8name = utf8name;
3564
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3825
+ desc.method = details::TemplatedVoidCallback<method>;
3565
3826
  desc.data = data;
3566
- desc.attributes = attributes;
3827
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3567
3828
  return desc;
3568
3829
  }
3569
3830
 
3570
3831
  template <typename T>
3571
- template <typename ObjectWrap<T>::InstanceMethodCallback method>
3572
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3573
- const char* utf8name,
3832
+ template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3833
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3834
+ Symbol name,
3574
3835
  napi_property_attributes attributes,
3575
3836
  void* data) {
3576
3837
  napi_property_descriptor desc = napi_property_descriptor();
3577
- desc.utf8name = utf8name;
3578
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3838
+ desc.name = name;
3839
+ desc.method = details::TemplatedVoidCallback<method>;
3579
3840
  desc.data = data;
3580
- desc.attributes = attributes;
3841
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3581
3842
  return desc;
3582
3843
  }
3583
3844
 
3584
3845
  template <typename T>
3585
- template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3586
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3587
- Symbol name,
3846
+ template <typename ObjectWrap<T>::StaticMethodCallback method>
3847
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3848
+ const char* utf8name,
3588
3849
  napi_property_attributes attributes,
3589
3850
  void* data) {
3590
3851
  napi_property_descriptor desc = napi_property_descriptor();
3591
- desc.name = name;
3592
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3852
+ desc.utf8name = utf8name;
3853
+ desc.method = details::TemplatedCallback<method>;
3593
3854
  desc.data = data;
3594
- desc.attributes = attributes;
3855
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3595
3856
  return desc;
3596
3857
  }
3597
3858
 
3598
3859
  template <typename T>
3599
- template <typename ObjectWrap<T>::InstanceMethodCallback method>
3600
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3860
+ template <typename ObjectWrap<T>::StaticMethodCallback method>
3861
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3601
3862
  Symbol name,
3602
3863
  napi_property_attributes attributes,
3603
3864
  void* data) {
3604
3865
  napi_property_descriptor desc = napi_property_descriptor();
3605
3866
  desc.name = name;
3606
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3867
+ desc.method = details::TemplatedCallback<method>;
3607
3868
  desc.data = data;
3608
- desc.attributes = attributes;
3869
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3609
3870
  return desc;
3610
3871
  }
3611
3872
 
3612
3873
  template <typename T>
3613
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3874
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3614
3875
  const char* utf8name,
3615
- InstanceGetterCallback getter,
3616
- InstanceSetterCallback setter,
3876
+ StaticGetterCallback getter,
3877
+ StaticSetterCallback setter,
3617
3878
  napi_property_attributes attributes,
3618
3879
  void* data) {
3619
- InstanceAccessorCallbackData* callbackData =
3620
- new InstanceAccessorCallbackData({ getter, setter, data });
3880
+ StaticAccessorCallbackData* callbackData =
3881
+ new StaticAccessorCallbackData({ getter, setter, data });
3621
3882
 
3622
3883
  napi_property_descriptor desc = napi_property_descriptor();
3623
3884
  desc.utf8name = utf8name;
3624
- desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3625
- desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3885
+ desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3886
+ desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3626
3887
  desc.data = callbackData;
3627
- desc.attributes = attributes;
3888
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3628
3889
  return desc;
3629
3890
  }
3630
3891
 
3631
3892
  template <typename T>
3632
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3893
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3633
3894
  Symbol name,
3634
- InstanceGetterCallback getter,
3635
- InstanceSetterCallback setter,
3895
+ StaticGetterCallback getter,
3896
+ StaticSetterCallback setter,
3636
3897
  napi_property_attributes attributes,
3637
3898
  void* data) {
3638
- InstanceAccessorCallbackData* callbackData =
3639
- new InstanceAccessorCallbackData({ getter, setter, data });
3899
+ StaticAccessorCallbackData* callbackData =
3900
+ new StaticAccessorCallbackData({ getter, setter, data });
3640
3901
 
3641
3902
  napi_property_descriptor desc = napi_property_descriptor();
3642
3903
  desc.name = name;
3643
- desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3644
- desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3904
+ desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3905
+ desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3645
3906
  desc.data = callbackData;
3646
- desc.attributes = attributes;
3907
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3647
3908
  return desc;
3648
3909
  }
3649
3910
 
3650
3911
  template <typename T>
3651
- template <typename ObjectWrap<T>::InstanceGetterCallback getter,
3652
- typename ObjectWrap<T>::InstanceSetterCallback setter>
3653
- 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(
3654
3915
  const char* utf8name,
3655
3916
  napi_property_attributes attributes,
3656
3917
  void* data) {
3657
3918
  napi_property_descriptor desc = napi_property_descriptor();
3658
3919
  desc.utf8name = utf8name;
3659
- desc.getter = This::WrapGetter(This::GetterTag<getter>());
3660
- desc.setter = This::WrapSetter(This::SetterTag<setter>());
3920
+ desc.getter = details::TemplatedCallback<getter>;
3921
+ desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3661
3922
  desc.data = data;
3662
- desc.attributes = attributes;
3923
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3663
3924
  return desc;
3664
3925
  }
3665
3926
 
3666
3927
  template <typename T>
3667
- template <typename ObjectWrap<T>::InstanceGetterCallback getter,
3668
- typename ObjectWrap<T>::InstanceSetterCallback setter>
3669
- 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(
3670
3931
  Symbol name,
3671
3932
  napi_property_attributes attributes,
3672
3933
  void* data) {
3673
3934
  napi_property_descriptor desc = napi_property_descriptor();
3674
3935
  desc.name = name;
3675
- desc.getter = This::WrapGetter(This::GetterTag<getter>());
3676
- desc.setter = This::WrapSetter(This::SetterTag<setter>());
3936
+ desc.getter = details::TemplatedCallback<getter>;
3937
+ desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3677
3938
  desc.data = data;
3678
- desc.attributes = attributes;
3939
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3679
3940
  return desc;
3680
3941
  }
3681
3942
 
@@ -3690,36 +3951,12 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(const char* utf8nam
3690
3951
  }
3691
3952
 
3692
3953
  template <typename T>
3693
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(Symbol name,
3694
- Napi::Value value, napi_property_attributes attributes) {
3695
- napi_property_descriptor desc = napi_property_descriptor();
3696
- desc.name = name;
3697
- desc.value = value;
3698
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3699
- return desc;
3700
- }
3701
-
3702
- template <typename T>
3703
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
3704
- const char* utf8name,
3705
- Napi::Value value,
3706
- napi_property_attributes attributes) {
3707
- napi_property_descriptor desc = napi_property_descriptor();
3708
- desc.utf8name = utf8name;
3709
- desc.value = value;
3710
- desc.attributes = attributes;
3711
- return desc;
3712
- }
3713
-
3714
- template <typename T>
3715
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
3716
- Symbol name,
3717
- Napi::Value value,
3718
- napi_property_attributes attributes) {
3954
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(Symbol name,
3955
+ Napi::Value value, napi_property_attributes attributes) {
3719
3956
  napi_property_descriptor desc = napi_property_descriptor();
3720
3957
  desc.name = name;
3721
3958
  desc.value = value;
3722
- desc.attributes = attributes;
3959
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3723
3960
  return desc;
3724
3961
  }
3725
3962
 
@@ -3815,116 +4052,18 @@ inline napi_value ObjectWrap<T>::StaticSetterCallbackWrapper(
3815
4052
  });
3816
4053
  }
3817
4054
 
3818
- template <typename T>
3819
- inline napi_value ObjectWrap<T>::InstanceVoidMethodCallbackWrapper(
3820
- napi_env env,
3821
- napi_callback_info info) {
3822
- return details::WrapCallback([&] {
3823
- CallbackInfo callbackInfo(env, info);
3824
- InstanceVoidMethodCallbackData* callbackData =
3825
- reinterpret_cast<InstanceVoidMethodCallbackData*>(callbackInfo.Data());
3826
- callbackInfo.SetData(callbackData->data);
3827
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3828
- auto cb = callbackData->callback;
3829
- (instance->*cb)(callbackInfo);
3830
- return nullptr;
3831
- });
3832
- }
3833
-
3834
- template <typename T>
3835
- inline napi_value ObjectWrap<T>::InstanceMethodCallbackWrapper(
3836
- napi_env env,
3837
- napi_callback_info info) {
3838
- return details::WrapCallback([&] {
3839
- CallbackInfo callbackInfo(env, info);
3840
- InstanceMethodCallbackData* callbackData =
3841
- reinterpret_cast<InstanceMethodCallbackData*>(callbackInfo.Data());
3842
- callbackInfo.SetData(callbackData->data);
3843
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3844
- auto cb = callbackData->callback;
3845
- return (instance->*cb)(callbackInfo);
3846
- });
3847
- }
3848
-
3849
- template <typename T>
3850
- inline napi_value ObjectWrap<T>::InstanceGetterCallbackWrapper(
3851
- napi_env env,
3852
- napi_callback_info info) {
3853
- return details::WrapCallback([&] {
3854
- CallbackInfo callbackInfo(env, info);
3855
- InstanceAccessorCallbackData* callbackData =
3856
- reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
3857
- callbackInfo.SetData(callbackData->data);
3858
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3859
- auto cb = callbackData->getterCallback;
3860
- return (instance->*cb)(callbackInfo);
3861
- });
3862
- }
3863
-
3864
- template <typename T>
3865
- inline napi_value ObjectWrap<T>::InstanceSetterCallbackWrapper(
3866
- napi_env env,
3867
- napi_callback_info info) {
3868
- return details::WrapCallback([&] {
3869
- CallbackInfo callbackInfo(env, info);
3870
- InstanceAccessorCallbackData* callbackData =
3871
- reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
3872
- callbackInfo.SetData(callbackData->data);
3873
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3874
- auto cb = callbackData->setterCallback;
3875
- (instance->*cb)(callbackInfo, callbackInfo[0]);
3876
- return nullptr;
3877
- });
3878
- }
3879
-
3880
4055
  template <typename T>
3881
4056
  inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hint*/) {
4057
+ HandleScope scope(env);
3882
4058
  T* instance = static_cast<T*>(data);
3883
4059
  instance->Finalize(Napi::Env(env));
3884
4060
  delete instance;
3885
4061
  }
3886
4062
 
3887
- template <typename T>
3888
- template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3889
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3890
- return details::WrapCallback([&] {
3891
- method(CallbackInfo(env, info));
3892
- return nullptr;
3893
- });
3894
- }
3895
-
3896
- template <typename T>
3897
- template <typename ObjectWrap<T>::StaticMethodCallback method>
3898
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3899
- return details::WrapCallback([&] {
3900
- return method(CallbackInfo(env, info));
3901
- });
3902
- }
3903
-
3904
- template <typename T>
3905
- template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3906
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3907
- return details::WrapCallback([&] {
3908
- const CallbackInfo cbInfo(env, info);
3909
- T* instance = Unwrap(cbInfo.This().As<Object>());
3910
- (instance->*method)(cbInfo);
3911
- return nullptr;
3912
- });
3913
- }
3914
-
3915
- template <typename T>
3916
- template <typename ObjectWrap<T>::InstanceMethodCallback method>
3917
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3918
- return details::WrapCallback([&] {
3919
- const CallbackInfo cbInfo(env, info);
3920
- T* instance = Unwrap(cbInfo.This().As<Object>());
3921
- return (instance->*method)(cbInfo);
3922
- });
3923
- }
3924
-
3925
4063
  template <typename T>
3926
4064
  template <typename ObjectWrap<T>::StaticSetterCallback method>
3927
- 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 {
3928
4067
  return details::WrapCallback([&] {
3929
4068
  const CallbackInfo cbInfo(env, info);
3930
4069
  method(cbInfo, cbInfo[0]);
@@ -3932,17 +4071,6 @@ inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info
3932
4071
  });
3933
4072
  }
3934
4073
 
3935
- template <typename T>
3936
- template <typename ObjectWrap<T>::InstanceSetterCallback method>
3937
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3938
- return details::WrapCallback([&] {
3939
- const CallbackInfo cbInfo(env, info);
3940
- T* instance = Unwrap(cbInfo.This().As<Object>());
3941
- (instance->*method)(cbInfo, cbInfo[0]);
3942
- return nullptr;
3943
- });
3944
- }
3945
-
3946
4074
  ////////////////////////////////////////////////////////////////////////////////
3947
4075
  // HandleScope class
3948
4076
  ////////////////////////////////////////////////////////////////////////////////
@@ -4048,10 +4176,9 @@ inline AsyncContext::AsyncContext(napi_env env, const char* resource_name)
4048
4176
  }
4049
4177
 
4050
4178
  inline AsyncContext::AsyncContext(napi_env env,
4051
- const char* resource_name,
4179
+ const char* resource_name,
4052
4180
  const Object& resource)
4053
- : _env(env),
4054
- _context(nullptr) {
4181
+ : _env(env), _context(nullptr) {
4055
4182
  napi_value resource_id;
4056
4183
  napi_status status = napi_create_string_utf8(
4057
4184
  _env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
@@ -4303,6 +4430,490 @@ inline void AsyncWorker::OnWorkComplete(Napi::Env /*env*/, napi_status status) {
4303
4430
  }
4304
4431
 
4305
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
+
4306
4917
  ////////////////////////////////////////////////////////////////////////////////
4307
4918
  // ThreadSafeFunction class
4308
4919
  ////////////////////////////////////////////////////////////////////////////////
@@ -4695,6 +5306,7 @@ inline void AsyncProgressWorkerBase<DataType>::OnAsyncWorkProgress(Napi::Env /*
4695
5306
  void* data) {
4696
5307
  ThreadSafeData* tsd = static_cast<ThreadSafeData*>(data);
4697
5308
  tsd->asyncprogressworker()->OnWorkProgress(tsd->data());
5309
+ delete tsd;
4698
5310
  }
4699
5311
 
4700
5312
  template <typename DataType>
@@ -4816,6 +5428,17 @@ inline void AsyncProgressWorker<T>::OnWorkProgress(void*) {
4816
5428
  this->_asyncsize = 0;
4817
5429
  }
4818
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
+
4819
5442
  this->OnProgress(data, size);
4820
5443
  delete[] data;
4821
5444
  }
@@ -5000,6 +5623,49 @@ inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) {
5000
5623
  return result;
5001
5624
  }
5002
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
+
5003
5669
  } // namespace Napi
5004
5670
 
5005
5671
  #endif // SRC_NAPI_INL_H_