node-addon-api 8.2.0 → 8.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +1 -1
  2. package/napi-inl.h +53 -27
  3. package/napi.h +26 -9
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -19,7 +19,7 @@ and exception handling semantics with low overhead.
19
19
  API references are available in the [doc](doc/README.md) directory.
20
20
 
21
21
  <!-- x-release-please-start-version -->
22
- ## Current version: 8.2.0
22
+ ## Current version: 8.2.2
23
23
  <!-- x-release-please-end -->
24
24
 
25
25
  (See [CHANGELOG.md](CHANGELOG.md) for complete Changelog)
package/napi-inl.h CHANGED
@@ -35,7 +35,7 @@ namespace details {
35
35
  constexpr int napi_no_external_buffers_allowed = 22;
36
36
 
37
37
  template <typename FreeType>
38
- inline void default_basic_finalizer(node_api_nogc_env /*env*/,
38
+ inline void default_basic_finalizer(node_addon_api_basic_env /*env*/,
39
39
  void* data,
40
40
  void* /*hint*/) {
41
41
  delete static_cast<FreeType*>(data);
@@ -45,8 +45,9 @@ inline void default_basic_finalizer(node_api_nogc_env /*env*/,
45
45
  // garbage-collected.
46
46
  // TODO: Replace this code with `napi_add_finalizer()` whenever it becomes
47
47
  // available on all supported versions of Node.js.
48
- template <typename FreeType,
49
- node_api_nogc_finalize finalizer = default_basic_finalizer<FreeType>>
48
+ template <
49
+ typename FreeType,
50
+ node_addon_api_basic_finalize finalizer = default_basic_finalizer<FreeType>>
50
51
  inline napi_status AttachData(napi_env env,
51
52
  napi_value obj,
52
53
  FreeType* data,
@@ -192,10 +193,10 @@ template <typename T, typename Finalizer, typename Hint = void>
192
193
  struct FinalizeData {
193
194
  #ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
194
195
  template <typename F = Finalizer,
195
- typename =
196
- std::enable_if_t<std::is_invocable_v<F, node_api_nogc_env, T*>>>
196
+ typename = std::enable_if_t<
197
+ std::is_invocable_v<F, node_addon_api_basic_env, T*>>>
197
198
  #endif
198
- static inline void Wrapper(node_api_nogc_env env,
199
+ static inline void Wrapper(node_addon_api_basic_env env,
199
200
  void* data,
200
201
  void* finalizeHint) NAPI_NOEXCEPT {
201
202
  WrapVoidCallback([&] {
@@ -208,9 +209,9 @@ struct FinalizeData {
208
209
  #ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
209
210
  template <typename F = Finalizer,
210
211
  typename = std::enable_if_t<
211
- !std::is_invocable_v<F, node_api_nogc_env, T*>>,
212
+ !std::is_invocable_v<F, node_addon_api_basic_env, T*>>,
212
213
  typename = void>
213
- static inline void Wrapper(node_api_nogc_env env,
214
+ static inline void Wrapper(node_addon_api_basic_env env,
214
215
  void* data,
215
216
  void* finalizeHint) NAPI_NOEXCEPT {
216
217
  #ifdef NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS
@@ -228,9 +229,9 @@ struct FinalizeData {
228
229
  #ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
229
230
  template <typename F = Finalizer,
230
231
  typename = std::enable_if_t<
231
- std::is_invocable_v<F, node_api_nogc_env, T*, Hint*>>>
232
+ std::is_invocable_v<F, node_addon_api_basic_env, T*, Hint*>>>
232
233
  #endif
233
- static inline void WrapperWithHint(node_api_nogc_env env,
234
+ static inline void WrapperWithHint(node_addon_api_basic_env env,
234
235
  void* data,
235
236
  void* finalizeHint) NAPI_NOEXCEPT {
236
237
  WrapVoidCallback([&] {
@@ -243,9 +244,9 @@ struct FinalizeData {
243
244
  #ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
244
245
  template <typename F = Finalizer,
245
246
  typename = std::enable_if_t<
246
- !std::is_invocable_v<F, node_api_nogc_env, T*, Hint*>>,
247
+ !std::is_invocable_v<F, node_addon_api_basic_env, T*, Hint*>>,
247
248
  typename = void>
248
- static inline void WrapperWithHint(node_api_nogc_env env,
249
+ static inline void WrapperWithHint(node_addon_api_basic_env env,
249
250
  void* data,
250
251
  void* finalizeHint) NAPI_NOEXCEPT {
251
252
  #ifdef NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS
@@ -576,9 +577,9 @@ inline Maybe<T> Just(const T& t) {
576
577
  // BasicEnv / Env class
577
578
  ////////////////////////////////////////////////////////////////////////////////
578
579
 
579
- inline BasicEnv::BasicEnv(node_api_nogc_env env) : _env(env) {}
580
+ inline BasicEnv::BasicEnv(node_addon_api_basic_env env) : _env(env) {}
580
581
 
581
- inline BasicEnv::operator node_api_nogc_env() const {
582
+ inline BasicEnv::operator node_addon_api_basic_env() const {
582
583
  return _env;
583
584
  }
584
585
 
@@ -896,6 +897,16 @@ inline T Value::As() const {
896
897
  return T(_env, _value);
897
898
  }
898
899
 
900
+ template <typename T>
901
+ inline T Value::UnsafeAs() const {
902
+ return T(_env, _value);
903
+ }
904
+
905
+ // static
906
+ inline void Value::CheckCast(napi_env /* env */, napi_value value) {
907
+ NAPI_CHECK(value != nullptr, "Value::CheckCast", "empty value");
908
+ }
909
+
899
910
  inline MaybeOrValue<Boolean> Value::ToBoolean() const {
900
911
  napi_value result;
901
912
  napi_status status = napi_coerce_to_bool(_env, _value, &result);
@@ -1303,12 +1314,15 @@ inline Symbol Symbol::New(napi_env env, napi_value description) {
1303
1314
 
1304
1315
  inline MaybeOrValue<Symbol> Symbol::WellKnown(napi_env env,
1305
1316
  const std::string& name) {
1317
+ // No need to check if the return value is a symbol or undefined.
1318
+ // Well known symbols are definite and it is an develop time error
1319
+ // if the symbol does not exist.
1306
1320
  #if defined(NODE_ADDON_API_ENABLE_MAYBE)
1307
1321
  Value symbol_obj;
1308
1322
  Value symbol_value;
1309
1323
  if (Napi::Env(env).Global().Get("Symbol").UnwrapTo(&symbol_obj) &&
1310
1324
  symbol_obj.As<Object>().Get(name).UnwrapTo(&symbol_value)) {
1311
- return Just<Symbol>(symbol_value.As<Symbol>());
1325
+ return Just<Symbol>(symbol_value.UnsafeAs<Symbol>());
1312
1326
  }
1313
1327
  return Nothing<Symbol>();
1314
1328
  #else
@@ -1317,7 +1331,7 @@ inline MaybeOrValue<Symbol> Symbol::WellKnown(napi_env env,
1317
1331
  .Get("Symbol")
1318
1332
  .As<Object>()
1319
1333
  .Get(name)
1320
- .As<Symbol>();
1334
+ .UnsafeAs<Symbol>();
1321
1335
  #endif
1322
1336
  }
1323
1337
 
@@ -1535,7 +1549,10 @@ inline void Object::CheckCast(napi_env env, napi_value value) {
1535
1549
  napi_valuetype type;
1536
1550
  napi_status status = napi_typeof(env, value, &type);
1537
1551
  NAPI_CHECK(status == napi_ok, "Object::CheckCast", "napi_typeof failed");
1538
- NAPI_INTERNAL_CHECK_EQ(type, napi_object, "%d", "Object::CheckCast");
1552
+ NAPI_INTERNAL_CHECK(type == napi_object || type == napi_function,
1553
+ "Object::CheckCast",
1554
+ "Expect napi_object or napi_function, but got %d.",
1555
+ type);
1539
1556
  }
1540
1557
 
1541
1558
  inline Object::Object() : TypeTaggable() {}
@@ -3324,6 +3341,8 @@ template <typename T>
3324
3341
  inline Reference<T>::~Reference() {
3325
3342
  if (_ref != nullptr) {
3326
3343
  if (!_suppressDestruct) {
3344
+ // TODO(legendecas): napi_delete_reference should be invoked immediately.
3345
+ // Fix this when https://github.com/nodejs/node/pull/55620 lands.
3327
3346
  #ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
3328
3347
  Env().PostFinalizer(
3329
3348
  [](Napi::Env env, napi_ref ref) { napi_delete_reference(env, ref); },
@@ -4578,7 +4597,7 @@ template <typename T>
4578
4597
  inline ObjectWrap<T>::~ObjectWrap() {
4579
4598
  // If the JS object still exists at this point, remove the finalizer added
4580
4599
  // through `napi_wrap()`.
4581
- if (!IsEmpty()) {
4600
+ if (!IsEmpty() && !_finalized) {
4582
4601
  Object object = Value();
4583
4602
  // It is not valid to call `napi_remove_wrap()` with an empty `object`.
4584
4603
  // This happens e.g. during garbage collection.
@@ -5018,7 +5037,7 @@ inline napi_value ObjectWrap<T>::StaticSetterCallbackWrapper(
5018
5037
  }
5019
5038
 
5020
5039
  template <typename T>
5021
- inline void ObjectWrap<T>::FinalizeCallback(node_api_nogc_env env,
5040
+ inline void ObjectWrap<T>::FinalizeCallback(node_addon_api_basic_env env,
5022
5041
  void* data,
5023
5042
  void* /*hint*/) {
5024
5043
  // If the child class does not override _any_ Finalize() method, `env` will be
@@ -5027,8 +5046,10 @@ inline void ObjectWrap<T>::FinalizeCallback(node_api_nogc_env env,
5027
5046
  (void)env;
5028
5047
  T* instance = static_cast<T*>(data);
5029
5048
 
5030
- // Prevent ~ObjectWrap from calling napi_remove_wrap
5031
- instance->_ref = nullptr;
5049
+ // Prevent ~ObjectWrap from calling napi_remove_wrap.
5050
+ // The instance->_ref should be deleted with napi_delete_reference in
5051
+ // ~Reference.
5052
+ instance->_finalized = true;
5032
5053
 
5033
5054
  // If class overrides the basic finalizer, execute it.
5034
5055
  if constexpr (details::HasBasicFinalizer<T>::value) {
@@ -6682,12 +6703,14 @@ inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Send(
6682
6703
  // Memory Management class
6683
6704
  ////////////////////////////////////////////////////////////////////////////////
6684
6705
 
6685
- inline int64_t MemoryManagement::AdjustExternalMemory(Env env,
6706
+ inline int64_t MemoryManagement::AdjustExternalMemory(BasicEnv env,
6686
6707
  int64_t change_in_bytes) {
6687
6708
  int64_t result;
6688
6709
  napi_status status =
6689
6710
  napi_adjust_external_memory(env, change_in_bytes, &result);
6690
- NAPI_THROW_IF_FAILED(env, status, 0);
6711
+ NAPI_FATAL_IF_FAILED(status,
6712
+ "MemoryManagement::AdjustExternalMemory",
6713
+ "napi_adjust_external_memory");
6691
6714
  return result;
6692
6715
  }
6693
6716
 
@@ -6695,17 +6718,20 @@ inline int64_t MemoryManagement::AdjustExternalMemory(Env env,
6695
6718
  // Version Management class
6696
6719
  ////////////////////////////////////////////////////////////////////////////////
6697
6720
 
6698
- inline uint32_t VersionManagement::GetNapiVersion(Env env) {
6721
+ inline uint32_t VersionManagement::GetNapiVersion(BasicEnv env) {
6699
6722
  uint32_t result;
6700
6723
  napi_status status = napi_get_version(env, &result);
6701
- NAPI_THROW_IF_FAILED(env, status, 0);
6724
+ NAPI_FATAL_IF_FAILED(
6725
+ status, "VersionManagement::GetNapiVersion", "napi_get_version");
6702
6726
  return result;
6703
6727
  }
6704
6728
 
6705
- inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) {
6729
+ inline const napi_node_version* VersionManagement::GetNodeVersion(
6730
+ BasicEnv env) {
6706
6731
  const napi_node_version* result;
6707
6732
  napi_status status = napi_get_node_version(env, &result);
6708
- NAPI_THROW_IF_FAILED(env, status, 0);
6733
+ NAPI_FATAL_IF_FAILED(
6734
+ status, "VersionManagement::GetNodeVersion", "napi_get_node_version");
6709
6735
  return result;
6710
6736
  }
6711
6737
 
package/napi.h CHANGED
@@ -299,6 +299,14 @@ template <typename T>
299
299
  using MaybeOrValue = T;
300
300
  #endif
301
301
 
302
+ #ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
303
+ using node_addon_api_basic_env = node_api_nogc_env;
304
+ using node_addon_api_basic_finalize = node_api_nogc_finalize;
305
+ #else
306
+ using node_addon_api_basic_env = napi_env;
307
+ using node_addon_api_basic_finalize = napi_finalize;
308
+ #endif
309
+
302
310
  /// Environment for Node-API values and operations.
303
311
  ///
304
312
  /// All Node-API values and operations must be associated with an environment.
@@ -307,14 +315,13 @@ using MaybeOrValue = T;
307
315
  /// Node-API operations within the callback. (Many methods infer the
308
316
  /// environment from the `this` instance that the method is called on.)
309
317
  ///
310
- /// In the future, multiple environments per process may be supported,
311
- /// although current implementations only support one environment per process.
318
+ /// Multiple environments may co-exist in a single process or a thread.
312
319
  ///
313
320
  /// In the V8 JavaScript engine, a Node-API environment approximately
314
321
  /// corresponds to an Isolate.
315
322
  class BasicEnv {
316
323
  private:
317
- node_api_nogc_env _env;
324
+ node_addon_api_basic_env _env;
318
325
  #if NAPI_VERSION > 5
319
326
  template <typename T>
320
327
  static void DefaultFini(Env, T* data);
@@ -322,8 +329,9 @@ class BasicEnv {
322
329
  static void DefaultFiniWithHint(Env, DataType* data, HintType* hint);
323
330
  #endif // NAPI_VERSION > 5
324
331
  public:
325
- BasicEnv(node_api_nogc_env env);
326
- operator node_api_nogc_env() const;
332
+ BasicEnv(node_addon_api_basic_env env);
333
+
334
+ operator node_addon_api_basic_env() const;
327
335
 
328
336
  // Without these operator overloads, the error:
329
337
  //
@@ -461,6 +469,8 @@ class Value {
461
469
  template <typename T>
462
470
  static Value From(napi_env env, const T& value);
463
471
 
472
+ static void CheckCast(napi_env env, napi_value value);
473
+
464
474
  /// Converts to a Node-API value primitive.
465
475
  ///
466
476
  /// If the instance is _empty_, this returns `nullptr`.
@@ -527,6 +537,10 @@ class Value {
527
537
  template <typename T>
528
538
  T As() const;
529
539
 
540
+ // Unsafe Value::As(), should be avoided.
541
+ template <typename T>
542
+ T UnsafeAs() const;
543
+
530
544
  MaybeOrValue<Boolean> ToBoolean()
531
545
  const; ///< Coerces a value to a JavaScript boolean.
532
546
  MaybeOrValue<Number> ToNumber()
@@ -2464,7 +2478,9 @@ class ObjectWrap : public InstanceWrap<T>, public Reference<Object> {
2464
2478
  napi_callback_info info);
2465
2479
  static napi_value StaticSetterCallbackWrapper(napi_env env,
2466
2480
  napi_callback_info info);
2467
- static void FinalizeCallback(node_api_nogc_env env, void* data, void* hint);
2481
+ static void FinalizeCallback(node_addon_api_basic_env env,
2482
+ void* data,
2483
+ void* hint);
2468
2484
 
2469
2485
  static void PostFinalizeCallback(napi_env env, void* data, void* hint);
2470
2486
 
@@ -2498,6 +2514,7 @@ class ObjectWrap : public InstanceWrap<T>, public Reference<Object> {
2498
2514
  }
2499
2515
 
2500
2516
  bool _construction_failed = true;
2517
+ bool _finalized = false;
2501
2518
  };
2502
2519
 
2503
2520
  class HandleScope {
@@ -3218,14 +3235,14 @@ class AsyncProgressQueueWorker
3218
3235
  // Memory management.
3219
3236
  class MemoryManagement {
3220
3237
  public:
3221
- static int64_t AdjustExternalMemory(Env env, int64_t change_in_bytes);
3238
+ static int64_t AdjustExternalMemory(BasicEnv env, int64_t change_in_bytes);
3222
3239
  };
3223
3240
 
3224
3241
  // Version management
3225
3242
  class VersionManagement {
3226
3243
  public:
3227
- static uint32_t GetNapiVersion(Env env);
3228
- static const napi_node_version* GetNodeVersion(Env env);
3244
+ static uint32_t GetNapiVersion(BasicEnv env);
3245
+ static const napi_node_version* GetNodeVersion(BasicEnv env);
3229
3246
  };
3230
3247
 
3231
3248
  #if NAPI_VERSION > 5
package/package.json CHANGED
@@ -478,7 +478,7 @@
478
478
  "lint:fix": "node tools/clang-format --fix && node tools/eslint-format --fix"
479
479
  },
480
480
  "pre-commit": "lint",
481
- "version": "8.2.0",
481
+ "version": "8.2.2",
482
482
  "support": true,
483
483
  "engines": {
484
484
  "node": "^18 || ^20 || >= 21"