node-addon-api 4.1.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/napi-inl.h CHANGED
@@ -14,9 +14,14 @@
14
14
  #include <cstring>
15
15
  #include <mutex>
16
16
  #include <type_traits>
17
+ #include <utility>
17
18
 
18
19
  namespace Napi {
19
20
 
21
+ #ifdef NAPI_CPP_CUSTOM_NAMESPACE
22
+ namespace NAPI_CPP_CUSTOM_NAMESPACE {
23
+ #endif
24
+
20
25
  // Helpers to handle functions exposed from C++.
21
26
  namespace details {
22
27
 
@@ -482,7 +487,7 @@ inline bool Env::IsExceptionPending() const {
482
487
  return result;
483
488
  }
484
489
 
485
- inline Error Env::GetAndClearPendingException() {
490
+ inline Error Env::GetAndClearPendingException() const {
486
491
  napi_value value;
487
492
  napi_status status = napi_get_and_clear_last_exception(_env, &value);
488
493
  if (status != napi_ok) {
@@ -492,16 +497,16 @@ inline Error Env::GetAndClearPendingException() {
492
497
  return Error(_env, value);
493
498
  }
494
499
 
495
- inline MaybeOrValue<Value> Env::RunScript(const char* utf8script) {
500
+ inline MaybeOrValue<Value> Env::RunScript(const char* utf8script) const {
496
501
  String script = String::New(_env, utf8script);
497
502
  return RunScript(script);
498
503
  }
499
504
 
500
- inline MaybeOrValue<Value> Env::RunScript(const std::string& utf8script) {
505
+ inline MaybeOrValue<Value> Env::RunScript(const std::string& utf8script) const {
501
506
  return RunScript(utf8script.c_str());
502
507
  }
503
508
 
504
- inline MaybeOrValue<Value> Env::RunScript(String script) {
509
+ inline MaybeOrValue<Value> Env::RunScript(String script) const {
505
510
  napi_value result;
506
511
  napi_status status = napi_run_script(_env, script, &result);
507
512
  NAPI_RETURN_OR_THROW_IF_FAILED(
@@ -530,7 +535,7 @@ void Env::CleanupHook<Hook, Arg>::WrapperWithArg(void* data) NAPI_NOEXCEPT {
530
535
 
531
536
  #if NAPI_VERSION > 5
532
537
  template <typename T, Env::Finalizer<T> fini>
533
- inline void Env::SetInstanceData(T* data) {
538
+ inline void Env::SetInstanceData(T* data) const {
534
539
  napi_status status =
535
540
  napi_set_instance_data(_env, data, [](napi_env env, void* data, void*) {
536
541
  fini(env, static_cast<T*>(data));
@@ -541,7 +546,7 @@ inline void Env::SetInstanceData(T* data) {
541
546
  template <typename DataType,
542
547
  typename HintType,
543
548
  Napi::Env::FinalizerWithHint<DataType, HintType> fini>
544
- inline void Env::SetInstanceData(DataType* data, HintType* hint) {
549
+ inline void Env::SetInstanceData(DataType* data, HintType* hint) const {
545
550
  napi_status status =
546
551
  napi_set_instance_data(_env, data,
547
552
  [](napi_env env, void* data, void* hint) {
@@ -551,7 +556,7 @@ inline void Env::SetInstanceData(DataType* data, HintType* hint) {
551
556
  }
552
557
 
553
558
  template <typename T>
554
- inline T* Env::GetInstanceData() {
559
+ inline T* Env::GetInstanceData() const {
555
560
  void* data = nullptr;
556
561
 
557
562
  napi_status status = napi_get_instance_data(_env, &data);
@@ -1293,18 +1298,24 @@ inline Object::Object() : Value() {
1293
1298
  inline Object::Object(napi_env env, napi_value value) : Value(env, value) {
1294
1299
  }
1295
1300
 
1296
- inline Object::PropertyLValue<std::string> Object::operator [](const char* utf8name) {
1301
+ inline Object::PropertyLValue<std::string> Object::operator[](
1302
+ const char* utf8name) {
1297
1303
  return PropertyLValue<std::string>(*this, utf8name);
1298
1304
  }
1299
1305
 
1300
- inline Object::PropertyLValue<std::string> Object::operator [](const std::string& utf8name) {
1306
+ inline Object::PropertyLValue<std::string> Object::operator[](
1307
+ const std::string& utf8name) {
1301
1308
  return PropertyLValue<std::string>(*this, utf8name);
1302
1309
  }
1303
1310
 
1304
- inline Object::PropertyLValue<uint32_t> Object::operator [](uint32_t index) {
1311
+ inline Object::PropertyLValue<uint32_t> Object::operator[](uint32_t index) {
1305
1312
  return PropertyLValue<uint32_t>(*this, index);
1306
1313
  }
1307
1314
 
1315
+ inline Object::PropertyLValue<Value> Object::operator[](Value index) const {
1316
+ return PropertyLValue<Value>(*this, index);
1317
+ }
1318
+
1308
1319
  inline MaybeOrValue<Value> Object::operator[](const char* utf8name) const {
1309
1320
  return Get(utf8name);
1310
1321
  }
@@ -1387,14 +1398,15 @@ inline MaybeOrValue<Value> Object::Get(const std::string& utf8name) const {
1387
1398
  }
1388
1399
 
1389
1400
  template <typename ValueType>
1390
- inline MaybeOrValue<bool> Object::Set(napi_value key, const ValueType& value) {
1401
+ inline MaybeOrValue<bool> Object::Set(napi_value key,
1402
+ const ValueType& value) const {
1391
1403
  napi_status status =
1392
1404
  napi_set_property(_env, _value, key, Value::From(_env, value));
1393
1405
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
1394
1406
  }
1395
1407
 
1396
1408
  template <typename ValueType>
1397
- inline MaybeOrValue<bool> Object::Set(Value key, const ValueType& value) {
1409
+ inline MaybeOrValue<bool> Object::Set(Value key, const ValueType& value) const {
1398
1410
  napi_status status =
1399
1411
  napi_set_property(_env, _value, key, Value::From(_env, value));
1400
1412
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
@@ -1402,7 +1414,7 @@ inline MaybeOrValue<bool> Object::Set(Value key, const ValueType& value) {
1402
1414
 
1403
1415
  template <typename ValueType>
1404
1416
  inline MaybeOrValue<bool> Object::Set(const char* utf8name,
1405
- const ValueType& value) {
1417
+ const ValueType& value) const {
1406
1418
  napi_status status =
1407
1419
  napi_set_named_property(_env, _value, utf8name, Value::From(_env, value));
1408
1420
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
@@ -1410,27 +1422,27 @@ inline MaybeOrValue<bool> Object::Set(const char* utf8name,
1410
1422
 
1411
1423
  template <typename ValueType>
1412
1424
  inline MaybeOrValue<bool> Object::Set(const std::string& utf8name,
1413
- const ValueType& value) {
1425
+ const ValueType& value) const {
1414
1426
  return Set(utf8name.c_str(), value);
1415
1427
  }
1416
1428
 
1417
- inline MaybeOrValue<bool> Object::Delete(napi_value key) {
1429
+ inline MaybeOrValue<bool> Object::Delete(napi_value key) const {
1418
1430
  bool result;
1419
1431
  napi_status status = napi_delete_property(_env, _value, key, &result);
1420
1432
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
1421
1433
  }
1422
1434
 
1423
- inline MaybeOrValue<bool> Object::Delete(Value key) {
1435
+ inline MaybeOrValue<bool> Object::Delete(Value key) const {
1424
1436
  bool result;
1425
1437
  napi_status status = napi_delete_property(_env, _value, key, &result);
1426
1438
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
1427
1439
  }
1428
1440
 
1429
- inline MaybeOrValue<bool> Object::Delete(const char* utf8name) {
1441
+ inline MaybeOrValue<bool> Object::Delete(const char* utf8name) const {
1430
1442
  return Delete(String::New(_env, utf8name));
1431
1443
  }
1432
1444
 
1433
- inline MaybeOrValue<bool> Object::Delete(const std::string& utf8name) {
1445
+ inline MaybeOrValue<bool> Object::Delete(const std::string& utf8name) const {
1434
1446
  return Delete(String::New(_env, utf8name));
1435
1447
  }
1436
1448
 
@@ -1447,13 +1459,14 @@ inline MaybeOrValue<Value> Object::Get(uint32_t index) const {
1447
1459
  }
1448
1460
 
1449
1461
  template <typename ValueType>
1450
- inline MaybeOrValue<bool> Object::Set(uint32_t index, const ValueType& value) {
1462
+ inline MaybeOrValue<bool> Object::Set(uint32_t index,
1463
+ const ValueType& value) const {
1451
1464
  napi_status status =
1452
1465
  napi_set_element(_env, _value, index, Value::From(_env, value));
1453
1466
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
1454
1467
  }
1455
1468
 
1456
- inline MaybeOrValue<bool> Object::Delete(uint32_t index) {
1469
+ inline MaybeOrValue<bool> Object::Delete(uint32_t index) const {
1457
1470
  bool result;
1458
1471
  napi_status status = napi_delete_element(_env, _value, index, &result);
1459
1472
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool);
@@ -1466,21 +1479,21 @@ inline MaybeOrValue<Array> Object::GetPropertyNames() const {
1466
1479
  }
1467
1480
 
1468
1481
  inline MaybeOrValue<bool> Object::DefineProperty(
1469
- const PropertyDescriptor& property) {
1482
+ const PropertyDescriptor& property) const {
1470
1483
  napi_status status = napi_define_properties(_env, _value, 1,
1471
1484
  reinterpret_cast<const napi_property_descriptor*>(&property));
1472
1485
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
1473
1486
  }
1474
1487
 
1475
1488
  inline MaybeOrValue<bool> Object::DefineProperties(
1476
- const std::initializer_list<PropertyDescriptor>& properties) {
1489
+ const std::initializer_list<PropertyDescriptor>& properties) const {
1477
1490
  napi_status status = napi_define_properties(_env, _value, properties.size(),
1478
1491
  reinterpret_cast<const napi_property_descriptor*>(properties.begin()));
1479
1492
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
1480
1493
  }
1481
1494
 
1482
1495
  inline MaybeOrValue<bool> Object::DefineProperties(
1483
- const std::vector<PropertyDescriptor>& properties) {
1496
+ const std::vector<PropertyDescriptor>& properties) const {
1484
1497
  napi_status status = napi_define_properties(_env, _value, properties.size(),
1485
1498
  reinterpret_cast<const napi_property_descriptor*>(properties.data()));
1486
1499
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
@@ -1494,7 +1507,7 @@ inline MaybeOrValue<bool> Object::InstanceOf(
1494
1507
  }
1495
1508
 
1496
1509
  template <typename Finalizer, typename T>
1497
- inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) {
1510
+ inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) const {
1498
1511
  details::FinalizeData<T, Finalizer>* finalizeData =
1499
1512
  new details::FinalizeData<T, Finalizer>(
1500
1513
  {std::move(finalizeCallback), nullptr});
@@ -1513,7 +1526,7 @@ inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) {
1513
1526
  template <typename Finalizer, typename T, typename Hint>
1514
1527
  inline void Object::AddFinalizer(Finalizer finalizeCallback,
1515
1528
  T* data,
1516
- Hint* finalizeHint) {
1529
+ Hint* finalizeHint) const {
1517
1530
  details::FinalizeData<T, Finalizer, Hint>* finalizeData =
1518
1531
  new details::FinalizeData<T, Finalizer, Hint>(
1519
1532
  {std::move(finalizeCallback), finalizeHint});
@@ -1529,13 +1542,90 @@ inline void Object::AddFinalizer(Finalizer finalizeCallback,
1529
1542
  }
1530
1543
  }
1531
1544
 
1545
+ #ifdef NAPI_CPP_EXCEPTIONS
1546
+ inline Object::const_iterator::const_iterator(const Object* object,
1547
+ const Type type) {
1548
+ _object = object;
1549
+ _keys = object->GetPropertyNames();
1550
+ _index = type == Type::BEGIN ? 0 : _keys.Length();
1551
+ }
1552
+
1553
+ inline Object::const_iterator Napi::Object::begin() const {
1554
+ const_iterator it(this, Object::const_iterator::Type::BEGIN);
1555
+ return it;
1556
+ }
1557
+
1558
+ inline Object::const_iterator Napi::Object::end() const {
1559
+ const_iterator it(this, Object::const_iterator::Type::END);
1560
+ return it;
1561
+ }
1562
+
1563
+ inline Object::const_iterator& Object::const_iterator::operator++() {
1564
+ ++_index;
1565
+ return *this;
1566
+ }
1567
+
1568
+ inline bool Object::const_iterator::operator==(
1569
+ const const_iterator& other) const {
1570
+ return _index == other._index;
1571
+ }
1572
+
1573
+ inline bool Object::const_iterator::operator!=(
1574
+ const const_iterator& other) const {
1575
+ return _index != other._index;
1576
+ }
1577
+
1578
+ inline const std::pair<Value, Object::PropertyLValue<Value>>
1579
+ Object::const_iterator::operator*() const {
1580
+ const Value key = _keys[_index];
1581
+ const PropertyLValue<Value> value = (*_object)[key];
1582
+ return {key, value};
1583
+ }
1584
+
1585
+ inline Object::iterator::iterator(Object* object, const Type type) {
1586
+ _object = object;
1587
+ _keys = object->GetPropertyNames();
1588
+ _index = type == Type::BEGIN ? 0 : _keys.Length();
1589
+ }
1590
+
1591
+ inline Object::iterator Napi::Object::begin() {
1592
+ iterator it(this, Object::iterator::Type::BEGIN);
1593
+ return it;
1594
+ }
1595
+
1596
+ inline Object::iterator Napi::Object::end() {
1597
+ iterator it(this, Object::iterator::Type::END);
1598
+ return it;
1599
+ }
1600
+
1601
+ inline Object::iterator& Object::iterator::operator++() {
1602
+ ++_index;
1603
+ return *this;
1604
+ }
1605
+
1606
+ inline bool Object::iterator::operator==(const iterator& other) const {
1607
+ return _index == other._index;
1608
+ }
1609
+
1610
+ inline bool Object::iterator::operator!=(const iterator& other) const {
1611
+ return _index != other._index;
1612
+ }
1613
+
1614
+ inline std::pair<Value, Object::PropertyLValue<Value>>
1615
+ Object::iterator::operator*() {
1616
+ Value key = _keys[_index];
1617
+ PropertyLValue<Value> value = (*_object)[key];
1618
+ return {key, value};
1619
+ }
1620
+ #endif // NAPI_CPP_EXCEPTIONS
1621
+
1532
1622
  #if NAPI_VERSION >= 8
1533
- inline MaybeOrValue<bool> Object::Freeze() {
1623
+ inline MaybeOrValue<bool> Object::Freeze() const {
1534
1624
  napi_status status = napi_object_freeze(_env, _value);
1535
1625
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
1536
1626
  }
1537
1627
 
1538
- inline MaybeOrValue<bool> Object::Seal() {
1628
+ inline MaybeOrValue<bool> Object::Seal() const {
1539
1629
  napi_status status = napi_object_seal(_env, _value);
1540
1630
  NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
1541
1631
  }
@@ -2044,8 +2134,10 @@ inline TypedArrayOf<T>::TypedArrayOf(napi_env env, napi_value value)
2044
2134
  : TypedArray(env, value), _data(nullptr) {
2045
2135
  napi_status status = napi_ok;
2046
2136
  if (value != nullptr) {
2137
+ void* data = nullptr;
2047
2138
  status = napi_get_typedarray_info(
2048
- _env, _value, &_type, &_length, reinterpret_cast<void**>(&_data), nullptr, nullptr);
2139
+ _env, _value, &_type, &_length, &data, nullptr, nullptr);
2140
+ _data = static_cast<T*>(data);
2049
2141
  } else {
2050
2142
  _type = TypedArrayTypeForPrimitiveType<T>();
2051
2143
  _length = 0;
@@ -2154,7 +2246,7 @@ inline Function Function::New(napi_env env,
2154
2246
  void* data) {
2155
2247
  using ReturnType = decltype(cb(CallbackInfo(nullptr, nullptr)));
2156
2248
  using CbData = details::CallbackData<Callable, ReturnType>;
2157
- auto callbackData = new CbData({ cb, data });
2249
+ auto callbackData = new CbData{std::move(cb), data};
2158
2250
 
2159
2251
  napi_value value;
2160
2252
  napi_status status = CreateFunction(env,
@@ -2199,6 +2291,11 @@ inline MaybeOrValue<Value> Function::Call(
2199
2291
  return Call(Env().Undefined(), args);
2200
2292
  }
2201
2293
 
2294
+ inline MaybeOrValue<Value> Function::Call(
2295
+ const std::vector<Value>& args) const {
2296
+ return Call(Env().Undefined(), args);
2297
+ }
2298
+
2202
2299
  inline MaybeOrValue<Value> Function::Call(size_t argc,
2203
2300
  const napi_value* args) const {
2204
2301
  return Call(Env().Undefined(), argc, args);
@@ -2214,6 +2311,27 @@ inline MaybeOrValue<Value> Function::Call(
2214
2311
  return Call(recv, args.size(), args.data());
2215
2312
  }
2216
2313
 
2314
+ inline MaybeOrValue<Value> Function::Call(
2315
+ napi_value recv, const std::vector<Value>& args) const {
2316
+ const size_t argc = args.size();
2317
+ const size_t stackArgsCount = 6;
2318
+ napi_value stackArgs[stackArgsCount];
2319
+ std::vector<napi_value> heapArgs;
2320
+ napi_value* argv;
2321
+ if (argc <= stackArgsCount) {
2322
+ argv = stackArgs;
2323
+ } else {
2324
+ heapArgs.resize(argc);
2325
+ argv = heapArgs.data();
2326
+ }
2327
+
2328
+ for (size_t index = 0; index < argc; index++) {
2329
+ argv[index] = static_cast<napi_value>(args[index]);
2330
+ }
2331
+
2332
+ return Call(recv, argc, argv);
2333
+ }
2334
+
2217
2335
  inline MaybeOrValue<Value> Function::Call(napi_value recv,
2218
2336
  size_t argc,
2219
2337
  const napi_value* args) const {
@@ -2432,12 +2550,23 @@ inline Error Error::New(napi_env env) {
2432
2550
  napi_status status;
2433
2551
  napi_value error = nullptr;
2434
2552
  bool is_exception_pending;
2435
- const napi_extended_error_info* info;
2553
+ napi_extended_error_info last_error_info_copy;
2436
2554
 
2437
- // We must retrieve the last error info before doing anything else, because
2438
- // doing anything else will replace the last error info.
2439
- status = napi_get_last_error_info(env, &info);
2440
- NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info");
2555
+ {
2556
+ // We must retrieve the last error info before doing anything else because
2557
+ // doing anything else will replace the last error info.
2558
+ const napi_extended_error_info* last_error_info;
2559
+ status = napi_get_last_error_info(env, &last_error_info);
2560
+ NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info");
2561
+
2562
+ // All fields of the `napi_extended_error_info` structure gets reset in
2563
+ // subsequent Node-API function calls on the same `env`. This includes a
2564
+ // call to `napi_is_exception_pending()`. So here it is necessary to make a
2565
+ // copy of the information as the `error_code` field is used later on.
2566
+ memcpy(&last_error_info_copy,
2567
+ last_error_info,
2568
+ sizeof(napi_extended_error_info));
2569
+ }
2441
2570
 
2442
2571
  status = napi_is_exception_pending(env, &is_exception_pending);
2443
2572
  NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
@@ -2448,8 +2577,9 @@ inline Error Error::New(napi_env env) {
2448
2577
  NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
2449
2578
  }
2450
2579
  else {
2451
- const char* error_message = info->error_message != nullptr ?
2452
- info->error_message : "Error in native callback";
2580
+ const char* error_message = last_error_info_copy.error_message != nullptr
2581
+ ? last_error_info_copy.error_message
2582
+ : "Error in native callback";
2453
2583
 
2454
2584
  napi_value message;
2455
2585
  status = napi_create_string_utf8(
@@ -2459,16 +2589,16 @@ inline Error Error::New(napi_env env) {
2459
2589
  &message);
2460
2590
  NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_string_utf8");
2461
2591
 
2462
- switch (info->error_code) {
2463
- case napi_object_expected:
2464
- case napi_string_expected:
2465
- case napi_boolean_expected:
2466
- case napi_number_expected:
2467
- status = napi_create_type_error(env, nullptr, message, &error);
2468
- break;
2469
- default:
2470
- status = napi_create_error(env, nullptr, message, &error);
2471
- break;
2592
+ switch (last_error_info_copy.error_code) {
2593
+ case napi_object_expected:
2594
+ case napi_string_expected:
2595
+ case napi_boolean_expected:
2596
+ case napi_number_expected:
2597
+ status = napi_create_type_error(env, nullptr, message, &error);
2598
+ break;
2599
+ default:
2600
+ status = napi_create_error(env, nullptr, message, &error);
2601
+ break;
2472
2602
  }
2473
2603
  NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
2474
2604
  }
@@ -2493,14 +2623,82 @@ inline Error::Error() : ObjectReference() {
2493
2623
 
2494
2624
  inline Error::Error(napi_env env, napi_value value) : ObjectReference(env, nullptr) {
2495
2625
  if (value != nullptr) {
2626
+ // Attempting to create a reference on the error object.
2627
+ // If it's not a Object/Function/Symbol, this call will return an error
2628
+ // status.
2496
2629
  napi_status status = napi_create_reference(env, value, 1, &_ref);
2497
2630
 
2631
+ if (status != napi_ok) {
2632
+ napi_value wrappedErrorObj;
2633
+
2634
+ // Create an error object
2635
+ status = napi_create_object(env, &wrappedErrorObj);
2636
+ NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_create_object");
2637
+
2638
+ // property flag that we attach to show the error object is wrapped
2639
+ napi_property_descriptor wrapObjFlag = {
2640
+ ERROR_WRAP_VALUE(), // Unique GUID identifier since Symbol isn't a
2641
+ // viable option
2642
+ nullptr,
2643
+ nullptr,
2644
+ nullptr,
2645
+ nullptr,
2646
+ Value::From(env, value),
2647
+ napi_enumerable,
2648
+ nullptr};
2649
+
2650
+ status = napi_define_properties(env, wrappedErrorObj, 1, &wrapObjFlag);
2651
+ NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_define_properties");
2652
+
2653
+ // Create a reference on the newly wrapped object
2654
+ status = napi_create_reference(env, wrappedErrorObj, 1, &_ref);
2655
+ }
2656
+
2498
2657
  // Avoid infinite recursion in the failure case.
2499
- // Don't try to construct & throw another Error instance.
2500
2658
  NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_create_reference");
2501
2659
  }
2502
2660
  }
2503
2661
 
2662
+ inline Object Error::Value() const {
2663
+ if (_ref == nullptr) {
2664
+ return Object(_env, nullptr);
2665
+ }
2666
+
2667
+ napi_value refValue;
2668
+ napi_status status = napi_get_reference_value(_env, _ref, &refValue);
2669
+ NAPI_THROW_IF_FAILED(_env, status, Object());
2670
+
2671
+ napi_valuetype type;
2672
+ status = napi_typeof(_env, refValue, &type);
2673
+ NAPI_THROW_IF_FAILED(_env, status, Object());
2674
+
2675
+ // If refValue isn't a symbol, then we proceed to whether the refValue has the
2676
+ // wrapped error flag
2677
+ if (type != napi_symbol) {
2678
+ // We are checking if the object is wrapped
2679
+ bool isWrappedObject = false;
2680
+
2681
+ status = napi_has_property(_env,
2682
+ refValue,
2683
+ String::From(_env, ERROR_WRAP_VALUE()),
2684
+ &isWrappedObject);
2685
+
2686
+ // Don't care about status
2687
+ if (isWrappedObject) {
2688
+ napi_value unwrappedValue;
2689
+ status = napi_get_property(_env,
2690
+ refValue,
2691
+ String::From(_env, ERROR_WRAP_VALUE()),
2692
+ &unwrappedValue);
2693
+ NAPI_THROW_IF_FAILED(_env, status, Object());
2694
+
2695
+ return Object(_env, unwrappedValue);
2696
+ }
2697
+ }
2698
+
2699
+ return Object(_env, refValue);
2700
+ }
2701
+
2504
2702
  inline Error::Error(Error&& other) : ObjectReference(std::move(other)) {
2505
2703
  }
2506
2704
 
@@ -2551,6 +2749,7 @@ inline const std::string& Error::Message() const NAPI_NOEXCEPT {
2551
2749
  return _message;
2552
2750
  }
2553
2751
 
2752
+ // we created an object on the &_ref
2554
2753
  inline void Error::ThrowAsJavaScriptException() const {
2555
2754
  HandleScope scope(_env);
2556
2755
  if (!IsEmpty()) {
@@ -2605,6 +2804,10 @@ inline const char* Error::what() const NAPI_NOEXCEPT {
2605
2804
 
2606
2805
  #endif // NAPI_CPP_EXCEPTIONS
2607
2806
 
2807
+ inline const char* Error::ERROR_WRAP_VALUE() NAPI_NOEXCEPT {
2808
+ return "4bda9e7e-4913-4dbc-95de-891cbf66598e-errorVal";
2809
+ }
2810
+
2608
2811
  template <typename TError>
2609
2812
  inline TError Error::New(napi_env env,
2610
2813
  const char* message,
@@ -2763,7 +2966,7 @@ inline T Reference<T>::Value() const {
2763
2966
  }
2764
2967
 
2765
2968
  template <typename T>
2766
- inline uint32_t Reference<T>::Ref() {
2969
+ inline uint32_t Reference<T>::Ref() const {
2767
2970
  uint32_t result;
2768
2971
  napi_status status = napi_reference_ref(_env, _ref, &result);
2769
2972
  NAPI_THROW_IF_FAILED(_env, status, 0);
@@ -2771,7 +2974,7 @@ inline uint32_t Reference<T>::Ref() {
2771
2974
  }
2772
2975
 
2773
2976
  template <typename T>
2774
- inline uint32_t Reference<T>::Unref() {
2977
+ inline uint32_t Reference<T>::Unref() const {
2775
2978
  uint32_t result;
2776
2979
  napi_status status = napi_reference_unref(_env, _ref, &result);
2777
2980
  NAPI_THROW_IF_FAILED(_env, status, 0);
@@ -2897,61 +3100,61 @@ inline MaybeOrValue<Napi::Value> ObjectReference::Get(
2897
3100
  }
2898
3101
 
2899
3102
  inline MaybeOrValue<bool> ObjectReference::Set(const char* utf8name,
2900
- napi_value value) {
3103
+ napi_value value) const {
2901
3104
  HandleScope scope(_env);
2902
3105
  return Value().Set(utf8name, value);
2903
3106
  }
2904
3107
 
2905
3108
  inline MaybeOrValue<bool> ObjectReference::Set(const char* utf8name,
2906
- Napi::Value value) {
3109
+ Napi::Value value) const {
2907
3110
  HandleScope scope(_env);
2908
3111
  return Value().Set(utf8name, value);
2909
3112
  }
2910
3113
 
2911
3114
  inline MaybeOrValue<bool> ObjectReference::Set(const char* utf8name,
2912
- const char* utf8value) {
3115
+ const char* utf8value) const {
2913
3116
  HandleScope scope(_env);
2914
3117
  return Value().Set(utf8name, utf8value);
2915
3118
  }
2916
3119
 
2917
3120
  inline MaybeOrValue<bool> ObjectReference::Set(const char* utf8name,
2918
- bool boolValue) {
3121
+ bool boolValue) const {
2919
3122
  HandleScope scope(_env);
2920
3123
  return Value().Set(utf8name, boolValue);
2921
3124
  }
2922
3125
 
2923
3126
  inline MaybeOrValue<bool> ObjectReference::Set(const char* utf8name,
2924
- double numberValue) {
3127
+ double numberValue) const {
2925
3128
  HandleScope scope(_env);
2926
3129
  return Value().Set(utf8name, numberValue);
2927
3130
  }
2928
3131
 
2929
3132
  inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
2930
- napi_value value) {
3133
+ napi_value value) const {
2931
3134
  HandleScope scope(_env);
2932
3135
  return Value().Set(utf8name, value);
2933
3136
  }
2934
3137
 
2935
3138
  inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
2936
- Napi::Value value) {
3139
+ Napi::Value value) const {
2937
3140
  HandleScope scope(_env);
2938
3141
  return Value().Set(utf8name, value);
2939
3142
  }
2940
3143
 
2941
3144
  inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
2942
- std::string& utf8value) {
3145
+ std::string& utf8value) const {
2943
3146
  HandleScope scope(_env);
2944
3147
  return Value().Set(utf8name, utf8value);
2945
3148
  }
2946
3149
 
2947
3150
  inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
2948
- bool boolValue) {
3151
+ bool boolValue) const {
2949
3152
  HandleScope scope(_env);
2950
3153
  return Value().Set(utf8name, boolValue);
2951
3154
  }
2952
3155
 
2953
3156
  inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
2954
- double numberValue) {
3157
+ double numberValue) const {
2955
3158
  HandleScope scope(_env);
2956
3159
  return Value().Set(utf8name, numberValue);
2957
3160
  }
@@ -2973,36 +3176,37 @@ inline MaybeOrValue<Napi::Value> ObjectReference::Get(uint32_t index) const {
2973
3176
  }
2974
3177
 
2975
3178
  inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
2976
- napi_value value) {
3179
+ napi_value value) const {
2977
3180
  HandleScope scope(_env);
2978
3181
  return Value().Set(index, value);
2979
3182
  }
2980
3183
 
2981
3184
  inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
2982
- Napi::Value value) {
3185
+ Napi::Value value) const {
2983
3186
  HandleScope scope(_env);
2984
3187
  return Value().Set(index, value);
2985
3188
  }
2986
3189
 
2987
3190
  inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
2988
- const char* utf8value) {
3191
+ const char* utf8value) const {
2989
3192
  HandleScope scope(_env);
2990
3193
  return Value().Set(index, utf8value);
2991
3194
  }
2992
3195
 
2993
- inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
2994
- const std::string& utf8value) {
3196
+ inline MaybeOrValue<bool> ObjectReference::Set(
3197
+ uint32_t index, const std::string& utf8value) const {
2995
3198
  HandleScope scope(_env);
2996
3199
  return Value().Set(index, utf8value);
2997
3200
  }
2998
3201
 
2999
- inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index, bool boolValue) {
3202
+ inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
3203
+ bool boolValue) const {
3000
3204
  HandleScope scope(_env);
3001
3205
  return Value().Set(index, boolValue);
3002
3206
  }
3003
3207
 
3004
3208
  inline MaybeOrValue<bool> ObjectReference::Set(uint32_t index,
3005
- double numberValue) {
3209
+ double numberValue) const {
3006
3210
  HandleScope scope(_env);
3007
3211
  return Value().Set(index, numberValue);
3008
3212
  }
@@ -3967,10 +4171,10 @@ inline ObjectWrap<T>::~ObjectWrap() {
3967
4171
 
3968
4172
  template<typename T>
3969
4173
  inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
3970
- T* unwrapped;
3971
- napi_status status = napi_unwrap(wrapper.Env(), wrapper, reinterpret_cast<void**>(&unwrapped));
4174
+ void* unwrapped;
4175
+ napi_status status = napi_unwrap(wrapper.Env(), wrapper, &unwrapped);
3972
4176
  NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
3973
- return unwrapped;
4177
+ return static_cast<T*>(unwrapped);
3974
4178
  }
3975
4179
 
3976
4180
  template <typename T>
@@ -4284,6 +4488,15 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(Symbol name,
4284
4488
  return desc;
4285
4489
  }
4286
4490
 
4491
+ template <typename T>
4492
+ inline Value ObjectWrap<T>::OnCalledAsFunction(
4493
+ const Napi::CallbackInfo& callbackInfo) {
4494
+ NAPI_THROW(
4495
+ TypeError::New(callbackInfo.Env(),
4496
+ "Class constructors cannot be invoked without 'new'"),
4497
+ Napi::Value());
4498
+ }
4499
+
4287
4500
  template <typename T>
4288
4501
  inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}
4289
4502
 
@@ -4297,8 +4510,8 @@ inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
4297
4510
 
4298
4511
  bool isConstructCall = (new_target != nullptr);
4299
4512
  if (!isConstructCall) {
4300
- napi_throw_type_error(env, nullptr, "Class constructors cannot be invoked without 'new'");
4301
- return nullptr;
4513
+ return details::WrapCallback(
4514
+ [&] { return T::OnCalledAsFunction(CallbackInfo(env, info)); });
4302
4515
  }
4303
4516
 
4304
4517
  napi_value wrapper = details::WrapCallback([&] {
@@ -5156,7 +5369,7 @@ template <typename ContextType,
5156
5369
  typename DataType,
5157
5370
  void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
5158
5371
  inline napi_status
5159
- TypedThreadSafeFunction<ContextType, DataType, CallJs>::Release() {
5372
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::Release() const {
5160
5373
  return napi_release_threadsafe_function(_tsfn, napi_tsfn_release);
5161
5374
  }
5162
5375
 
@@ -5164,7 +5377,7 @@ template <typename ContextType,
5164
5377
  typename DataType,
5165
5378
  void (*CallJs)(Napi::Env, Napi::Function, ContextType*, DataType*)>
5166
5379
  inline napi_status
5167
- TypedThreadSafeFunction<ContextType, DataType, CallJs>::Abort() {
5380
+ TypedThreadSafeFunction<ContextType, DataType, CallJs>::Abort() const {
5168
5381
  return napi_release_threadsafe_function(_tsfn, napi_tsfn_abort);
5169
5382
  }
5170
5383
 
@@ -5494,11 +5707,11 @@ inline napi_status ThreadSafeFunction::Acquire() const {
5494
5707
  return napi_acquire_threadsafe_function(_tsfn);
5495
5708
  }
5496
5709
 
5497
- inline napi_status ThreadSafeFunction::Release() {
5710
+ inline napi_status ThreadSafeFunction::Release() const {
5498
5711
  return napi_release_threadsafe_function(_tsfn, napi_tsfn_release);
5499
5712
  }
5500
5713
 
5501
- inline napi_status ThreadSafeFunction::Abort() {
5714
+ inline napi_status ThreadSafeFunction::Abort() const {
5502
5715
  return napi_release_threadsafe_function(_tsfn, napi_tsfn_abort);
5503
5716
  }
5504
5717
 
@@ -6037,6 +6250,10 @@ bool Env::CleanupHook<Hook, Arg>::IsEmpty() const {
6037
6250
  }
6038
6251
  #endif // NAPI_VERSION > 2
6039
6252
 
6253
+ #ifdef NAPI_CPP_CUSTOM_NAMESPACE
6254
+ } // namespace NAPI_CPP_CUSTOM_NAMESPACE
6255
+ #endif
6256
+
6040
6257
  } // namespace Napi
6041
6258
 
6042
6259
  #endif // SRC_NAPI_INL_H_