node-addon-api 8.0.0 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/common.gypi +1 -0
- package/index.js +2 -0
- package/napi-inl.h +373 -110
- package/napi.h +86 -28
- package/package.json +6 -3
- package/tools/conversion.js +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# **node-addon-api module**
|
|
2
2
|
|
|
3
|
+
[](https://app.codecov.io/gh/nodejs/node-addon-api/tree/main)
|
|
4
|
+
|
|
3
5
|
[](https://nodei.co/npm/node-addon-api/) [](https://nodei.co/npm/node-addon-api/)
|
|
4
6
|
|
|
5
7
|
This module contains **header-only C++ wrapper classes** which simplify
|
|
@@ -16,7 +18,9 @@ and exception handling semantics with low overhead.
|
|
|
16
18
|
|
|
17
19
|
API references are available in the [doc](doc/README.md) directory.
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
<!-- x-release-please-start-version -->
|
|
22
|
+
## Current version: 8.2.0
|
|
23
|
+
<!-- x-release-please-end -->
|
|
20
24
|
|
|
21
25
|
(See [CHANGELOG.md](CHANGELOG.md) for complete Changelog)
|
|
22
26
|
|
package/common.gypi
CHANGED
package/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
+
const { version } = require('./package.json');
|
|
2
3
|
|
|
3
4
|
const includeDir = path.relative('.', __dirname);
|
|
4
5
|
|
|
@@ -7,6 +8,7 @@ module.exports = {
|
|
|
7
8
|
include_dir: includeDir,
|
|
8
9
|
gyp: path.join(includeDir, 'node_api.gyp:nothing'), // deprecated.
|
|
9
10
|
targets: path.join(includeDir, 'node_addon_api.gyp'),
|
|
11
|
+
version,
|
|
10
12
|
isNodeApiBuiltin: true,
|
|
11
13
|
needsFlag: false
|
|
12
14
|
};
|
package/napi-inl.h
CHANGED
|
@@ -9,8 +9,11 @@
|
|
|
9
9
|
////////////////////////////////////////////////////////////////////////////////
|
|
10
10
|
|
|
11
11
|
// Note: Do not include this file directly! Include "napi.h" instead.
|
|
12
|
+
// This should be a no-op and is intended for better IDE integration.
|
|
13
|
+
#include "napi.h"
|
|
12
14
|
|
|
13
15
|
#include <algorithm>
|
|
16
|
+
#include <cstdarg>
|
|
14
17
|
#include <cstring>
|
|
15
18
|
#if NAPI_HAS_THREADS
|
|
16
19
|
#include <mutex>
|
|
@@ -32,7 +35,9 @@ namespace details {
|
|
|
32
35
|
constexpr int napi_no_external_buffers_allowed = 22;
|
|
33
36
|
|
|
34
37
|
template <typename FreeType>
|
|
35
|
-
inline void
|
|
38
|
+
inline void default_basic_finalizer(node_api_nogc_env /*env*/,
|
|
39
|
+
void* data,
|
|
40
|
+
void* /*hint*/) {
|
|
36
41
|
delete static_cast<FreeType*>(data);
|
|
37
42
|
}
|
|
38
43
|
|
|
@@ -41,7 +46,7 @@ inline void default_finalizer(napi_env /*env*/, void* data, void* /*hint*/) {
|
|
|
41
46
|
// TODO: Replace this code with `napi_add_finalizer()` whenever it becomes
|
|
42
47
|
// available on all supported versions of Node.js.
|
|
43
48
|
template <typename FreeType,
|
|
44
|
-
|
|
49
|
+
node_api_nogc_finalize finalizer = default_basic_finalizer<FreeType>>
|
|
45
50
|
inline napi_status AttachData(napi_env env,
|
|
46
51
|
napi_value obj,
|
|
47
52
|
FreeType* data,
|
|
@@ -154,7 +159,10 @@ napi_value TemplatedCallback(napi_env env,
|
|
|
154
159
|
napi_callback_info info) NAPI_NOEXCEPT {
|
|
155
160
|
return details::WrapCallback([&] {
|
|
156
161
|
CallbackInfo cbInfo(env, info);
|
|
157
|
-
|
|
162
|
+
// MSVC requires to copy 'Callback' function pointer to a local variable
|
|
163
|
+
// before invoking it.
|
|
164
|
+
auto callback = Callback;
|
|
165
|
+
return callback(cbInfo);
|
|
158
166
|
});
|
|
159
167
|
}
|
|
160
168
|
|
|
@@ -182,23 +190,102 @@ napi_value TemplatedInstanceVoidCallback(napi_env env, napi_callback_info info)
|
|
|
182
190
|
|
|
183
191
|
template <typename T, typename Finalizer, typename Hint = void>
|
|
184
192
|
struct FinalizeData {
|
|
185
|
-
|
|
193
|
+
#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
194
|
+
template <typename F = Finalizer,
|
|
195
|
+
typename =
|
|
196
|
+
std::enable_if_t<std::is_invocable_v<F, node_api_nogc_env, T*>>>
|
|
197
|
+
#endif
|
|
198
|
+
static inline void Wrapper(node_api_nogc_env env,
|
|
186
199
|
void* data,
|
|
187
200
|
void* finalizeHint) NAPI_NOEXCEPT {
|
|
188
201
|
WrapVoidCallback([&] {
|
|
189
202
|
FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
|
|
190
|
-
finalizeData->callback(
|
|
203
|
+
finalizeData->callback(env, static_cast<T*>(data));
|
|
191
204
|
delete finalizeData;
|
|
192
205
|
});
|
|
193
206
|
}
|
|
194
207
|
|
|
195
|
-
|
|
208
|
+
#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
209
|
+
template <typename F = Finalizer,
|
|
210
|
+
typename = std::enable_if_t<
|
|
211
|
+
!std::is_invocable_v<F, node_api_nogc_env, T*>>,
|
|
212
|
+
typename = void>
|
|
213
|
+
static inline void Wrapper(node_api_nogc_env env,
|
|
214
|
+
void* data,
|
|
215
|
+
void* finalizeHint) NAPI_NOEXCEPT {
|
|
216
|
+
#ifdef NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS
|
|
217
|
+
static_assert(false,
|
|
218
|
+
"NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS defined: Finalizer "
|
|
219
|
+
"must be basic.");
|
|
220
|
+
#endif
|
|
221
|
+
napi_status status =
|
|
222
|
+
node_api_post_finalizer(env, WrapperGC, data, finalizeHint);
|
|
223
|
+
NAPI_FATAL_IF_FAILED(
|
|
224
|
+
status, "FinalizeData::Wrapper", "node_api_post_finalizer failed");
|
|
225
|
+
}
|
|
226
|
+
#endif
|
|
227
|
+
|
|
228
|
+
#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
229
|
+
template <typename F = Finalizer,
|
|
230
|
+
typename = std::enable_if_t<
|
|
231
|
+
std::is_invocable_v<F, node_api_nogc_env, T*, Hint*>>>
|
|
232
|
+
#endif
|
|
233
|
+
static inline void WrapperWithHint(node_api_nogc_env env,
|
|
196
234
|
void* data,
|
|
197
235
|
void* finalizeHint) NAPI_NOEXCEPT {
|
|
198
236
|
WrapVoidCallback([&] {
|
|
199
237
|
FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
|
|
200
|
-
finalizeData->callback(
|
|
201
|
-
|
|
238
|
+
finalizeData->callback(env, static_cast<T*>(data), finalizeData->hint);
|
|
239
|
+
delete finalizeData;
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
244
|
+
template <typename F = Finalizer,
|
|
245
|
+
typename = std::enable_if_t<
|
|
246
|
+
!std::is_invocable_v<F, node_api_nogc_env, T*, Hint*>>,
|
|
247
|
+
typename = void>
|
|
248
|
+
static inline void WrapperWithHint(node_api_nogc_env env,
|
|
249
|
+
void* data,
|
|
250
|
+
void* finalizeHint) NAPI_NOEXCEPT {
|
|
251
|
+
#ifdef NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS
|
|
252
|
+
static_assert(false,
|
|
253
|
+
"NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS defined: Finalizer "
|
|
254
|
+
"must be basic.");
|
|
255
|
+
#endif
|
|
256
|
+
napi_status status =
|
|
257
|
+
node_api_post_finalizer(env, WrapperGCWithHint, data, finalizeHint);
|
|
258
|
+
NAPI_FATAL_IF_FAILED(
|
|
259
|
+
status, "FinalizeData::Wrapper", "node_api_post_finalizer failed");
|
|
260
|
+
}
|
|
261
|
+
#endif
|
|
262
|
+
|
|
263
|
+
static inline void WrapperGCWithoutData(napi_env env,
|
|
264
|
+
void* /*data*/,
|
|
265
|
+
void* finalizeHint) NAPI_NOEXCEPT {
|
|
266
|
+
WrapVoidCallback([&] {
|
|
267
|
+
FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
|
|
268
|
+
finalizeData->callback(env);
|
|
269
|
+
delete finalizeData;
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
static inline void WrapperGC(napi_env env,
|
|
274
|
+
void* data,
|
|
275
|
+
void* finalizeHint) NAPI_NOEXCEPT {
|
|
276
|
+
WrapVoidCallback([&] {
|
|
277
|
+
FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
|
|
278
|
+
finalizeData->callback(env, static_cast<T*>(data));
|
|
279
|
+
delete finalizeData;
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
static inline void WrapperGCWithHint(napi_env env,
|
|
284
|
+
void* data,
|
|
285
|
+
void* finalizeHint) NAPI_NOEXCEPT {
|
|
286
|
+
WrapVoidCallback([&] {
|
|
287
|
+
FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
|
|
288
|
+
finalizeData->callback(env, static_cast<T*>(data), finalizeData->hint);
|
|
202
289
|
delete finalizeData;
|
|
203
290
|
});
|
|
204
291
|
}
|
|
@@ -337,6 +424,46 @@ struct AccessorCallbackData {
|
|
|
337
424
|
void* data;
|
|
338
425
|
};
|
|
339
426
|
|
|
427
|
+
// Debugging-purpose C++-style variant of sprintf().
|
|
428
|
+
inline std::string StringFormat(const char* format, ...) {
|
|
429
|
+
std::string result;
|
|
430
|
+
va_list args;
|
|
431
|
+
va_start(args, format);
|
|
432
|
+
int len = vsnprintf(nullptr, 0, format, args);
|
|
433
|
+
result.resize(len);
|
|
434
|
+
vsnprintf(&result[0], len + 1, format, args);
|
|
435
|
+
va_end(args);
|
|
436
|
+
return result;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
template <typename T>
|
|
440
|
+
class HasExtendedFinalizer {
|
|
441
|
+
private:
|
|
442
|
+
template <typename U, void (U::*)(Napi::Env)>
|
|
443
|
+
struct SFINAE {};
|
|
444
|
+
template <typename U>
|
|
445
|
+
static char test(SFINAE<U, &U::Finalize>*);
|
|
446
|
+
template <typename U>
|
|
447
|
+
static int test(...);
|
|
448
|
+
|
|
449
|
+
public:
|
|
450
|
+
static constexpr bool value = sizeof(test<T>(0)) == sizeof(char);
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
template <typename T>
|
|
454
|
+
class HasBasicFinalizer {
|
|
455
|
+
private:
|
|
456
|
+
template <typename U, void (U::*)(Napi::BasicEnv)>
|
|
457
|
+
struct SFINAE {};
|
|
458
|
+
template <typename U>
|
|
459
|
+
static char test(SFINAE<U, &U::Finalize>*);
|
|
460
|
+
template <typename U>
|
|
461
|
+
static int test(...);
|
|
462
|
+
|
|
463
|
+
public:
|
|
464
|
+
static constexpr bool value = sizeof(test<T>(0)) == sizeof(char);
|
|
465
|
+
};
|
|
466
|
+
|
|
340
467
|
} // namespace details
|
|
341
468
|
|
|
342
469
|
#ifndef NODE_ADDON_API_DISABLE_DEPRECATED
|
|
@@ -446,15 +573,21 @@ inline Maybe<T> Just(const T& t) {
|
|
|
446
573
|
}
|
|
447
574
|
|
|
448
575
|
////////////////////////////////////////////////////////////////////////////////
|
|
449
|
-
// Env class
|
|
576
|
+
// BasicEnv / Env class
|
|
450
577
|
////////////////////////////////////////////////////////////////////////////////
|
|
451
578
|
|
|
452
|
-
inline
|
|
579
|
+
inline BasicEnv::BasicEnv(node_api_nogc_env env) : _env(env) {}
|
|
453
580
|
|
|
454
|
-
inline
|
|
581
|
+
inline BasicEnv::operator node_api_nogc_env() const {
|
|
455
582
|
return _env;
|
|
456
583
|
}
|
|
457
584
|
|
|
585
|
+
inline Env::Env(napi_env env) : BasicEnv(env) {}
|
|
586
|
+
|
|
587
|
+
inline Env::operator napi_env() const {
|
|
588
|
+
return const_cast<napi_env>(_env);
|
|
589
|
+
}
|
|
590
|
+
|
|
458
591
|
inline Object Env::Global() const {
|
|
459
592
|
napi_value value;
|
|
460
593
|
napi_status status = napi_get_global(*this, &value);
|
|
@@ -478,7 +611,7 @@ inline Value Env::Null() const {
|
|
|
478
611
|
|
|
479
612
|
inline bool Env::IsExceptionPending() const {
|
|
480
613
|
bool result;
|
|
481
|
-
napi_status status = napi_is_exception_pending(
|
|
614
|
+
napi_status status = napi_is_exception_pending(*this, &result);
|
|
482
615
|
if (status != napi_ok)
|
|
483
616
|
result = false; // Checking for a pending exception shouldn't throw.
|
|
484
617
|
return result;
|
|
@@ -486,16 +619,16 @@ inline bool Env::IsExceptionPending() const {
|
|
|
486
619
|
|
|
487
620
|
inline Error Env::GetAndClearPendingException() const {
|
|
488
621
|
napi_value value;
|
|
489
|
-
napi_status status = napi_get_and_clear_last_exception(
|
|
622
|
+
napi_status status = napi_get_and_clear_last_exception(*this, &value);
|
|
490
623
|
if (status != napi_ok) {
|
|
491
624
|
// Don't throw another exception when failing to get the exception!
|
|
492
625
|
return Error();
|
|
493
626
|
}
|
|
494
|
-
return Error(
|
|
627
|
+
return Error(*this, value);
|
|
495
628
|
}
|
|
496
629
|
|
|
497
630
|
inline MaybeOrValue<Value> Env::RunScript(const char* utf8script) const {
|
|
498
|
-
String script = String::New(
|
|
631
|
+
String script = String::New(*this, utf8script);
|
|
499
632
|
return RunScript(script);
|
|
500
633
|
}
|
|
501
634
|
|
|
@@ -505,46 +638,46 @@ inline MaybeOrValue<Value> Env::RunScript(const std::string& utf8script) const {
|
|
|
505
638
|
|
|
506
639
|
inline MaybeOrValue<Value> Env::RunScript(String script) const {
|
|
507
640
|
napi_value result;
|
|
508
|
-
napi_status status = napi_run_script(
|
|
641
|
+
napi_status status = napi_run_script(*this, script, &result);
|
|
509
642
|
NAPI_RETURN_OR_THROW_IF_FAILED(
|
|
510
|
-
|
|
643
|
+
*this, status, Napi::Value(*this, result), Napi::Value);
|
|
511
644
|
}
|
|
512
645
|
|
|
513
646
|
#if NAPI_VERSION > 2
|
|
514
647
|
template <typename Hook, typename Arg>
|
|
515
|
-
void
|
|
516
|
-
auto* cleanupData =
|
|
517
|
-
|
|
518
|
-
data);
|
|
648
|
+
void BasicEnv::CleanupHook<Hook, Arg>::Wrapper(void* data) NAPI_NOEXCEPT {
|
|
649
|
+
auto* cleanupData = static_cast<
|
|
650
|
+
typename Napi::BasicEnv::CleanupHook<Hook, Arg>::CleanupData*>(data);
|
|
519
651
|
cleanupData->hook();
|
|
520
652
|
delete cleanupData;
|
|
521
653
|
}
|
|
522
654
|
|
|
523
655
|
template <typename Hook, typename Arg>
|
|
524
|
-
void
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
656
|
+
void BasicEnv::CleanupHook<Hook, Arg>::WrapperWithArg(void* data)
|
|
657
|
+
NAPI_NOEXCEPT {
|
|
658
|
+
auto* cleanupData = static_cast<
|
|
659
|
+
typename Napi::BasicEnv::CleanupHook<Hook, Arg>::CleanupData*>(data);
|
|
528
660
|
cleanupData->hook(static_cast<Arg*>(cleanupData->arg));
|
|
529
661
|
delete cleanupData;
|
|
530
662
|
}
|
|
531
663
|
#endif // NAPI_VERSION > 2
|
|
532
664
|
|
|
533
665
|
#if NAPI_VERSION > 5
|
|
534
|
-
template <typename T,
|
|
535
|
-
inline void
|
|
666
|
+
template <typename T, BasicEnv::Finalizer<T> fini>
|
|
667
|
+
inline void BasicEnv::SetInstanceData(T* data) const {
|
|
536
668
|
napi_status status = napi_set_instance_data(
|
|
537
669
|
_env,
|
|
538
670
|
data,
|
|
539
671
|
[](napi_env env, void* data, void*) { fini(env, static_cast<T*>(data)); },
|
|
540
672
|
nullptr);
|
|
541
|
-
|
|
673
|
+
NAPI_FATAL_IF_FAILED(
|
|
674
|
+
status, "BasicEnv::SetInstanceData", "invalid arguments");
|
|
542
675
|
}
|
|
543
676
|
|
|
544
677
|
template <typename DataType,
|
|
545
678
|
typename HintType,
|
|
546
|
-
Napi::
|
|
547
|
-
inline void
|
|
679
|
+
Napi::BasicEnv::FinalizerWithHint<DataType, HintType> fini>
|
|
680
|
+
inline void BasicEnv::SetInstanceData(DataType* data, HintType* hint) const {
|
|
548
681
|
napi_status status = napi_set_instance_data(
|
|
549
682
|
_env,
|
|
550
683
|
data,
|
|
@@ -552,35 +685,38 @@ inline void Env::SetInstanceData(DataType* data, HintType* hint) const {
|
|
|
552
685
|
fini(env, static_cast<DataType*>(data), static_cast<HintType*>(hint));
|
|
553
686
|
},
|
|
554
687
|
hint);
|
|
555
|
-
|
|
688
|
+
NAPI_FATAL_IF_FAILED(
|
|
689
|
+
status, "BasicEnv::SetInstanceData", "invalid arguments");
|
|
556
690
|
}
|
|
557
691
|
|
|
558
692
|
template <typename T>
|
|
559
|
-
inline T*
|
|
693
|
+
inline T* BasicEnv::GetInstanceData() const {
|
|
560
694
|
void* data = nullptr;
|
|
561
695
|
|
|
562
696
|
napi_status status = napi_get_instance_data(_env, &data);
|
|
563
|
-
|
|
697
|
+
NAPI_FATAL_IF_FAILED(
|
|
698
|
+
status, "BasicEnv::GetInstanceData", "invalid arguments");
|
|
564
699
|
|
|
565
700
|
return static_cast<T*>(data);
|
|
566
701
|
}
|
|
567
702
|
|
|
568
703
|
template <typename T>
|
|
569
|
-
void
|
|
704
|
+
void BasicEnv::DefaultFini(Env, T* data) {
|
|
570
705
|
delete data;
|
|
571
706
|
}
|
|
572
707
|
|
|
573
708
|
template <typename DataType, typename HintType>
|
|
574
|
-
void
|
|
709
|
+
void BasicEnv::DefaultFiniWithHint(Env, DataType* data, HintType*) {
|
|
575
710
|
delete data;
|
|
576
711
|
}
|
|
577
712
|
#endif // NAPI_VERSION > 5
|
|
578
713
|
|
|
579
714
|
#if NAPI_VERSION > 8
|
|
580
|
-
inline const char*
|
|
715
|
+
inline const char* BasicEnv::GetModuleFileName() const {
|
|
581
716
|
const char* result;
|
|
582
717
|
napi_status status = node_api_get_module_file_name(_env, &result);
|
|
583
|
-
|
|
718
|
+
NAPI_FATAL_IF_FAILED(
|
|
719
|
+
status, "BasicEnv::GetModuleFileName", "invalid arguments");
|
|
584
720
|
return result;
|
|
585
721
|
}
|
|
586
722
|
#endif // NAPI_VERSION > 8
|
|
@@ -805,8 +941,7 @@ inline void Boolean::CheckCast(napi_env env, napi_value value) {
|
|
|
805
941
|
napi_valuetype type;
|
|
806
942
|
napi_status status = napi_typeof(env, value, &type);
|
|
807
943
|
NAPI_CHECK(status == napi_ok, "Boolean::CheckCast", "napi_typeof failed");
|
|
808
|
-
|
|
809
|
-
type == napi_boolean, "Boolean::CheckCast", "value is not napi_boolean");
|
|
944
|
+
NAPI_INTERNAL_CHECK_EQ(type, napi_boolean, "%d", "Boolean::CheckCast");
|
|
810
945
|
}
|
|
811
946
|
|
|
812
947
|
inline Boolean::Boolean() : Napi::Value() {}
|
|
@@ -842,8 +977,7 @@ inline void Number::CheckCast(napi_env env, napi_value value) {
|
|
|
842
977
|
napi_valuetype type;
|
|
843
978
|
napi_status status = napi_typeof(env, value, &type);
|
|
844
979
|
NAPI_CHECK(status == napi_ok, "Number::CheckCast", "napi_typeof failed");
|
|
845
|
-
|
|
846
|
-
type == napi_number, "Number::CheckCast", "value is not napi_number");
|
|
980
|
+
NAPI_INTERNAL_CHECK_EQ(type, napi_number, "%d", "Number::CheckCast");
|
|
847
981
|
}
|
|
848
982
|
|
|
849
983
|
inline Number::Number() : Value() {}
|
|
@@ -938,8 +1072,7 @@ inline void BigInt::CheckCast(napi_env env, napi_value value) {
|
|
|
938
1072
|
napi_valuetype type;
|
|
939
1073
|
napi_status status = napi_typeof(env, value, &type);
|
|
940
1074
|
NAPI_CHECK(status == napi_ok, "BigInt::CheckCast", "napi_typeof failed");
|
|
941
|
-
|
|
942
|
-
type == napi_bigint, "BigInt::CheckCast", "value is not napi_bigint");
|
|
1075
|
+
NAPI_INTERNAL_CHECK_EQ(type, napi_bigint, "%d", "BigInt::CheckCast");
|
|
943
1076
|
}
|
|
944
1077
|
|
|
945
1078
|
inline BigInt::BigInt() : Value() {}
|
|
@@ -1025,9 +1158,10 @@ inline void Name::CheckCast(napi_env env, napi_value value) {
|
|
|
1025
1158
|
napi_valuetype type;
|
|
1026
1159
|
napi_status status = napi_typeof(env, value, &type);
|
|
1027
1160
|
NAPI_CHECK(status == napi_ok, "Name::CheckCast", "napi_typeof failed");
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1161
|
+
NAPI_INTERNAL_CHECK(type == napi_string || type == napi_symbol,
|
|
1162
|
+
"Name::CheckCast",
|
|
1163
|
+
"value is not napi_string or napi_symbol, got %d.",
|
|
1164
|
+
type);
|
|
1031
1165
|
}
|
|
1032
1166
|
|
|
1033
1167
|
inline Name::Name() : Value() {}
|
|
@@ -1094,8 +1228,7 @@ inline void String::CheckCast(napi_env env, napi_value value) {
|
|
|
1094
1228
|
napi_valuetype type;
|
|
1095
1229
|
napi_status status = napi_typeof(env, value, &type);
|
|
1096
1230
|
NAPI_CHECK(status == napi_ok, "String::CheckCast", "napi_typeof failed");
|
|
1097
|
-
|
|
1098
|
-
type == napi_string, "String::CheckCast", "value is not napi_string");
|
|
1231
|
+
NAPI_INTERNAL_CHECK_EQ(type, napi_string, "%d", "String::CheckCast");
|
|
1099
1232
|
}
|
|
1100
1233
|
|
|
1101
1234
|
inline String::String() : Name() {}
|
|
@@ -1231,8 +1364,7 @@ inline void Symbol::CheckCast(napi_env env, napi_value value) {
|
|
|
1231
1364
|
napi_valuetype type;
|
|
1232
1365
|
napi_status status = napi_typeof(env, value, &type);
|
|
1233
1366
|
NAPI_CHECK(status == napi_ok, "Symbol::CheckCast", "napi_typeof failed");
|
|
1234
|
-
|
|
1235
|
-
type == napi_symbol, "Symbol::CheckCast", "value is not napi_symbol");
|
|
1367
|
+
NAPI_INTERNAL_CHECK_EQ(type, napi_symbol, "%d", "Symbol::CheckCast");
|
|
1236
1368
|
}
|
|
1237
1369
|
|
|
1238
1370
|
inline Symbol::Symbol() : Name() {}
|
|
@@ -1403,8 +1535,7 @@ inline void Object::CheckCast(napi_env env, napi_value value) {
|
|
|
1403
1535
|
napi_valuetype type;
|
|
1404
1536
|
napi_status status = napi_typeof(env, value, &type);
|
|
1405
1537
|
NAPI_CHECK(status == napi_ok, "Object::CheckCast", "napi_typeof failed");
|
|
1406
|
-
|
|
1407
|
-
type == napi_object, "Object::CheckCast", "value is not napi_object");
|
|
1538
|
+
NAPI_INTERNAL_CHECK_EQ(type, napi_object, "%d", "Object::CheckCast");
|
|
1408
1539
|
}
|
|
1409
1540
|
|
|
1410
1541
|
inline Object::Object() : TypeTaggable() {}
|
|
@@ -1814,9 +1945,7 @@ inline void External<T>::CheckCast(napi_env env, napi_value value) {
|
|
|
1814
1945
|
napi_valuetype type;
|
|
1815
1946
|
napi_status status = napi_typeof(env, value, &type);
|
|
1816
1947
|
NAPI_CHECK(status == napi_ok, "External::CheckCast", "napi_typeof failed");
|
|
1817
|
-
|
|
1818
|
-
"External::CheckCast",
|
|
1819
|
-
"value is not napi_external");
|
|
1948
|
+
NAPI_INTERNAL_CHECK_EQ(type, napi_external, "%d", "External::CheckCast");
|
|
1820
1949
|
}
|
|
1821
1950
|
|
|
1822
1951
|
template <typename T>
|
|
@@ -2270,12 +2399,13 @@ inline void TypedArrayOf<T>::CheckCast(napi_env env, napi_value value) {
|
|
|
2270
2399
|
"TypedArrayOf::CheckCast",
|
|
2271
2400
|
"napi_is_typedarray failed");
|
|
2272
2401
|
|
|
2273
|
-
|
|
2402
|
+
NAPI_INTERNAL_CHECK(
|
|
2274
2403
|
(type == TypedArrayTypeForPrimitiveType<T>() ||
|
|
2275
2404
|
(type == napi_uint8_clamped_array && std::is_same<T, uint8_t>::value)),
|
|
2276
2405
|
"TypedArrayOf::CheckCast",
|
|
2277
|
-
"Array type must match the template parameter
|
|
2278
|
-
"optionally have the \"clamped\" array type.)"
|
|
2406
|
+
"Array type must match the template parameter, (Uint8 arrays may "
|
|
2407
|
+
"optionally have the \"clamped\" array type.), got %d.",
|
|
2408
|
+
type);
|
|
2279
2409
|
}
|
|
2280
2410
|
|
|
2281
2411
|
template <typename T>
|
|
@@ -2456,9 +2586,7 @@ inline void Function::CheckCast(napi_env env, napi_value value) {
|
|
|
2456
2586
|
napi_valuetype type;
|
|
2457
2587
|
napi_status status = napi_typeof(env, value, &type);
|
|
2458
2588
|
NAPI_CHECK(status == napi_ok, "Function::CheckCast", "napi_typeof failed");
|
|
2459
|
-
|
|
2460
|
-
"Function::CheckCast",
|
|
2461
|
-
"value is not napi_function");
|
|
2589
|
+
NAPI_INTERNAL_CHECK_EQ(type, napi_function, "%d", "Function::CheckCast");
|
|
2462
2590
|
}
|
|
2463
2591
|
|
|
2464
2592
|
inline Function::Function() : Object() {}
|
|
@@ -2731,7 +2859,7 @@ inline Buffer<T> Buffer<T>::NewOrCopy(napi_env env,
|
|
|
2731
2859
|
#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
|
|
2732
2860
|
// If we can't create an external buffer, we'll just copy the data.
|
|
2733
2861
|
Buffer<T> ret = Buffer<T>::Copy(env, data, length);
|
|
2734
|
-
details::FinalizeData<T, Finalizer>::
|
|
2862
|
+
details::FinalizeData<T, Finalizer>::WrapperGC(env, data, finalizeData);
|
|
2735
2863
|
return ret;
|
|
2736
2864
|
#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
|
|
2737
2865
|
}
|
|
@@ -2766,7 +2894,7 @@ inline Buffer<T> Buffer<T>::NewOrCopy(napi_env env,
|
|
|
2766
2894
|
#endif
|
|
2767
2895
|
// If we can't create an external buffer, we'll just copy the data.
|
|
2768
2896
|
Buffer<T> ret = Buffer<T>::Copy(env, data, length);
|
|
2769
|
-
details::FinalizeData<T, Finalizer, Hint>::
|
|
2897
|
+
details::FinalizeData<T, Finalizer, Hint>::WrapperGCWithHint(
|
|
2770
2898
|
env, data, finalizeData);
|
|
2771
2899
|
return ret;
|
|
2772
2900
|
#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
|
|
@@ -3054,7 +3182,12 @@ inline void Error::ThrowAsJavaScriptException() const {
|
|
|
3054
3182
|
|
|
3055
3183
|
status = napi_throw(_env, Value());
|
|
3056
3184
|
|
|
3057
|
-
|
|
3185
|
+
#ifdef NAPI_EXPERIMENTAL
|
|
3186
|
+
napi_status expected_failure_mode = napi_cannot_run_js;
|
|
3187
|
+
#else
|
|
3188
|
+
napi_status expected_failure_mode = napi_pending_exception;
|
|
3189
|
+
#endif
|
|
3190
|
+
if (status == expected_failure_mode) {
|
|
3058
3191
|
// The environment must be terminating as we checked earlier and there
|
|
3059
3192
|
// was no pending exception. In this case continuing will result
|
|
3060
3193
|
// in a fatal error and there is nothing the author has done incorrectly
|
|
@@ -3191,7 +3324,13 @@ template <typename T>
|
|
|
3191
3324
|
inline Reference<T>::~Reference() {
|
|
3192
3325
|
if (_ref != nullptr) {
|
|
3193
3326
|
if (!_suppressDestruct) {
|
|
3327
|
+
#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
3328
|
+
Env().PostFinalizer(
|
|
3329
|
+
[](Napi::Env env, napi_ref ref) { napi_delete_reference(env, ref); },
|
|
3330
|
+
_ref);
|
|
3331
|
+
#else
|
|
3194
3332
|
napi_delete_reference(_env, _ref);
|
|
3333
|
+
#endif
|
|
3195
3334
|
}
|
|
3196
3335
|
|
|
3197
3336
|
_ref = nullptr;
|
|
@@ -4791,6 +4930,9 @@ inline Value ObjectWrap<T>::OnCalledAsFunction(
|
|
|
4791
4930
|
template <typename T>
|
|
4792
4931
|
inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}
|
|
4793
4932
|
|
|
4933
|
+
template <typename T>
|
|
4934
|
+
inline void ObjectWrap<T>::Finalize(BasicEnv /*env*/) {}
|
|
4935
|
+
|
|
4794
4936
|
template <typename T>
|
|
4795
4937
|
inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
|
|
4796
4938
|
napi_env env, napi_callback_info info) {
|
|
@@ -4876,10 +5018,59 @@ inline napi_value ObjectWrap<T>::StaticSetterCallbackWrapper(
|
|
|
4876
5018
|
}
|
|
4877
5019
|
|
|
4878
5020
|
template <typename T>
|
|
4879
|
-
inline void ObjectWrap<T>::FinalizeCallback(
|
|
5021
|
+
inline void ObjectWrap<T>::FinalizeCallback(node_api_nogc_env env,
|
|
4880
5022
|
void* data,
|
|
4881
5023
|
void* /*hint*/) {
|
|
4882
|
-
|
|
5024
|
+
// If the child class does not override _any_ Finalize() method, `env` will be
|
|
5025
|
+
// unused because of the constexpr guards. Explicitly reference it here to
|
|
5026
|
+
// bypass compiler warnings.
|
|
5027
|
+
(void)env;
|
|
5028
|
+
T* instance = static_cast<T*>(data);
|
|
5029
|
+
|
|
5030
|
+
// Prevent ~ObjectWrap from calling napi_remove_wrap
|
|
5031
|
+
instance->_ref = nullptr;
|
|
5032
|
+
|
|
5033
|
+
// If class overrides the basic finalizer, execute it.
|
|
5034
|
+
if constexpr (details::HasBasicFinalizer<T>::value) {
|
|
5035
|
+
#ifndef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
5036
|
+
HandleScope scope(env);
|
|
5037
|
+
#endif
|
|
5038
|
+
|
|
5039
|
+
instance->Finalize(Napi::BasicEnv(env));
|
|
5040
|
+
}
|
|
5041
|
+
|
|
5042
|
+
// If class overrides the (extended) finalizer, either schedule it or
|
|
5043
|
+
// execute it immediately (depending on experimental features enabled).
|
|
5044
|
+
if constexpr (details::HasExtendedFinalizer<T>::value) {
|
|
5045
|
+
#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
5046
|
+
// In experimental, attach via node_api_post_finalizer.
|
|
5047
|
+
// `PostFinalizeCallback` is responsible for deleting the `T* instance`,
|
|
5048
|
+
// after calling the user-provided finalizer.
|
|
5049
|
+
napi_status status =
|
|
5050
|
+
node_api_post_finalizer(env, PostFinalizeCallback, data, nullptr);
|
|
5051
|
+
NAPI_FATAL_IF_FAILED(status,
|
|
5052
|
+
"ObjectWrap<T>::FinalizeCallback",
|
|
5053
|
+
"node_api_post_finalizer failed");
|
|
5054
|
+
#else
|
|
5055
|
+
// In non-experimental, this `FinalizeCallback` already executes from a
|
|
5056
|
+
// non-basic environment. Execute the override directly.
|
|
5057
|
+
// `PostFinalizeCallback` is responsible for deleting the `T* instance`,
|
|
5058
|
+
// after calling the user-provided finalizer.
|
|
5059
|
+
HandleScope scope(env);
|
|
5060
|
+
PostFinalizeCallback(env, data, static_cast<void*>(nullptr));
|
|
5061
|
+
#endif
|
|
5062
|
+
}
|
|
5063
|
+
// If the instance does _not_ override the (extended) finalizer, delete the
|
|
5064
|
+
// `T* instance` immediately.
|
|
5065
|
+
else {
|
|
5066
|
+
delete instance;
|
|
5067
|
+
}
|
|
5068
|
+
}
|
|
5069
|
+
|
|
5070
|
+
template <typename T>
|
|
5071
|
+
inline void ObjectWrap<T>::PostFinalizeCallback(napi_env env,
|
|
5072
|
+
void* data,
|
|
5073
|
+
void* /*hint*/) {
|
|
4883
5074
|
T* instance = static_cast<T*>(data);
|
|
4884
5075
|
instance->Finalize(Napi::Env(env));
|
|
4885
5076
|
delete instance;
|
|
@@ -4891,7 +5082,10 @@ inline napi_value ObjectWrap<T>::WrappedMethod(
|
|
|
4891
5082
|
napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
|
|
4892
5083
|
return details::WrapCallback([&] {
|
|
4893
5084
|
const CallbackInfo cbInfo(env, info);
|
|
4894
|
-
method
|
|
5085
|
+
// MSVC requires to copy 'method' function pointer to a local variable
|
|
5086
|
+
// before invoking it.
|
|
5087
|
+
auto m = method;
|
|
5088
|
+
m(cbInfo, cbInfo[0]);
|
|
4895
5089
|
return nullptr;
|
|
4896
5090
|
});
|
|
4897
5091
|
}
|
|
@@ -5321,19 +5515,21 @@ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
|
|
|
5321
5515
|
auto* finalizeData = new details::
|
|
5322
5516
|
ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
|
|
5323
5517
|
{data, finalizeCallback});
|
|
5324
|
-
|
|
5325
|
-
env,
|
|
5326
|
-
nullptr,
|
|
5327
|
-
nullptr,
|
|
5328
|
-
String::From(env, resourceName),
|
|
5329
|
-
maxQueueSize,
|
|
5330
|
-
initialThreadCount,
|
|
5331
|
-
finalizeData,
|
|
5518
|
+
auto fini =
|
|
5332
5519
|
details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
|
|
5333
|
-
FinalizeFinalizeWrapperWithDataAndContext
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5520
|
+
FinalizeFinalizeWrapperWithDataAndContext;
|
|
5521
|
+
napi_status status =
|
|
5522
|
+
napi_create_threadsafe_function(env,
|
|
5523
|
+
nullptr,
|
|
5524
|
+
nullptr,
|
|
5525
|
+
String::From(env, resourceName),
|
|
5526
|
+
maxQueueSize,
|
|
5527
|
+
initialThreadCount,
|
|
5528
|
+
finalizeData,
|
|
5529
|
+
fini,
|
|
5530
|
+
context,
|
|
5531
|
+
CallJsInternal,
|
|
5532
|
+
&tsfn._tsfn);
|
|
5337
5533
|
if (status != napi_ok) {
|
|
5338
5534
|
delete finalizeData;
|
|
5339
5535
|
NAPI_THROW_IF_FAILED(
|
|
@@ -5365,19 +5561,21 @@ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
|
|
|
5365
5561
|
auto* finalizeData = new details::
|
|
5366
5562
|
ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
|
|
5367
5563
|
{data, finalizeCallback});
|
|
5368
|
-
|
|
5369
|
-
env,
|
|
5370
|
-
nullptr,
|
|
5371
|
-
resource,
|
|
5372
|
-
String::From(env, resourceName),
|
|
5373
|
-
maxQueueSize,
|
|
5374
|
-
initialThreadCount,
|
|
5375
|
-
finalizeData,
|
|
5564
|
+
auto fini =
|
|
5376
5565
|
details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
|
|
5377
|
-
FinalizeFinalizeWrapperWithDataAndContext
|
|
5378
|
-
|
|
5379
|
-
|
|
5380
|
-
|
|
5566
|
+
FinalizeFinalizeWrapperWithDataAndContext;
|
|
5567
|
+
napi_status status =
|
|
5568
|
+
napi_create_threadsafe_function(env,
|
|
5569
|
+
nullptr,
|
|
5570
|
+
resource,
|
|
5571
|
+
String::From(env, resourceName),
|
|
5572
|
+
maxQueueSize,
|
|
5573
|
+
initialThreadCount,
|
|
5574
|
+
finalizeData,
|
|
5575
|
+
fini,
|
|
5576
|
+
context,
|
|
5577
|
+
CallJsInternal,
|
|
5578
|
+
&tsfn._tsfn);
|
|
5381
5579
|
if (status != napi_ok) {
|
|
5382
5580
|
delete finalizeData;
|
|
5383
5581
|
NAPI_THROW_IF_FAILED(
|
|
@@ -5481,19 +5679,21 @@ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
|
|
|
5481
5679
|
auto* finalizeData = new details::
|
|
5482
5680
|
ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
|
|
5483
5681
|
{data, finalizeCallback});
|
|
5484
|
-
|
|
5485
|
-
env,
|
|
5486
|
-
callback,
|
|
5487
|
-
nullptr,
|
|
5488
|
-
String::From(env, resourceName),
|
|
5489
|
-
maxQueueSize,
|
|
5490
|
-
initialThreadCount,
|
|
5491
|
-
finalizeData,
|
|
5682
|
+
auto fini =
|
|
5492
5683
|
details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
|
|
5493
|
-
FinalizeFinalizeWrapperWithDataAndContext
|
|
5494
|
-
|
|
5495
|
-
|
|
5496
|
-
|
|
5684
|
+
FinalizeFinalizeWrapperWithDataAndContext;
|
|
5685
|
+
napi_status status =
|
|
5686
|
+
napi_create_threadsafe_function(env,
|
|
5687
|
+
callback,
|
|
5688
|
+
nullptr,
|
|
5689
|
+
String::From(env, resourceName),
|
|
5690
|
+
maxQueueSize,
|
|
5691
|
+
initialThreadCount,
|
|
5692
|
+
finalizeData,
|
|
5693
|
+
fini,
|
|
5694
|
+
context,
|
|
5695
|
+
CallJsInternal,
|
|
5696
|
+
&tsfn._tsfn);
|
|
5497
5697
|
if (status != napi_ok) {
|
|
5498
5698
|
delete finalizeData;
|
|
5499
5699
|
NAPI_THROW_IF_FAILED(
|
|
@@ -5527,6 +5727,9 @@ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
|
|
|
5527
5727
|
auto* finalizeData = new details::
|
|
5528
5728
|
ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>(
|
|
5529
5729
|
{data, finalizeCallback});
|
|
5730
|
+
auto fini =
|
|
5731
|
+
details::ThreadSafeFinalize<ContextType, Finalizer, FinalizerDataType>::
|
|
5732
|
+
FinalizeFinalizeWrapperWithDataAndContext;
|
|
5530
5733
|
napi_status status = napi_create_threadsafe_function(
|
|
5531
5734
|
env,
|
|
5532
5735
|
details::DefaultCallbackWrapper<
|
|
@@ -5538,8 +5741,7 @@ TypedThreadSafeFunction<ContextType, DataType, CallJs>::New(
|
|
|
5538
5741
|
maxQueueSize,
|
|
5539
5742
|
initialThreadCount,
|
|
5540
5743
|
finalizeData,
|
|
5541
|
-
|
|
5542
|
-
FinalizeFinalizeWrapperWithDataAndContext,
|
|
5744
|
+
fini,
|
|
5543
5745
|
context,
|
|
5544
5746
|
CallJsInternal,
|
|
5545
5747
|
&tsfn._tsfn);
|
|
@@ -6548,12 +6750,12 @@ inline Napi::Object Addon<T>::DefineProperties(
|
|
|
6548
6750
|
|
|
6549
6751
|
#if NAPI_VERSION > 2
|
|
6550
6752
|
template <typename Hook, typename Arg>
|
|
6551
|
-
Env::CleanupHook<Hook, Arg>
|
|
6753
|
+
Env::CleanupHook<Hook, Arg> BasicEnv::AddCleanupHook(Hook hook, Arg* arg) {
|
|
6552
6754
|
return CleanupHook<Hook, Arg>(*this, hook, arg);
|
|
6553
6755
|
}
|
|
6554
6756
|
|
|
6555
6757
|
template <typename Hook>
|
|
6556
|
-
Env::CleanupHook<Hook>
|
|
6758
|
+
Env::CleanupHook<Hook> BasicEnv::AddCleanupHook(Hook hook) {
|
|
6557
6759
|
return CleanupHook<Hook>(*this, hook);
|
|
6558
6760
|
}
|
|
6559
6761
|
|
|
@@ -6563,7 +6765,7 @@ Env::CleanupHook<Hook, Arg>::CleanupHook() {
|
|
|
6563
6765
|
}
|
|
6564
6766
|
|
|
6565
6767
|
template <typename Hook, typename Arg>
|
|
6566
|
-
Env::CleanupHook<Hook, Arg>::CleanupHook(Napi::
|
|
6768
|
+
Env::CleanupHook<Hook, Arg>::CleanupHook(Napi::BasicEnv env, Hook hook)
|
|
6567
6769
|
: wrapper(Env::CleanupHook<Hook, Arg>::Wrapper) {
|
|
6568
6770
|
data = new CleanupData{std::move(hook), nullptr};
|
|
6569
6771
|
napi_status status = napi_add_env_cleanup_hook(env, wrapper, data);
|
|
@@ -6574,7 +6776,9 @@ Env::CleanupHook<Hook, Arg>::CleanupHook(Napi::Env env, Hook hook)
|
|
|
6574
6776
|
}
|
|
6575
6777
|
|
|
6576
6778
|
template <typename Hook, typename Arg>
|
|
6577
|
-
Env::CleanupHook<Hook, Arg>::CleanupHook(Napi::
|
|
6779
|
+
Env::CleanupHook<Hook, Arg>::CleanupHook(Napi::BasicEnv env,
|
|
6780
|
+
Hook hook,
|
|
6781
|
+
Arg* arg)
|
|
6578
6782
|
: wrapper(Env::CleanupHook<Hook, Arg>::WrapperWithArg) {
|
|
6579
6783
|
data = new CleanupData{std::move(hook), arg};
|
|
6580
6784
|
napi_status status = napi_add_env_cleanup_hook(env, wrapper, data);
|
|
@@ -6585,7 +6789,7 @@ Env::CleanupHook<Hook, Arg>::CleanupHook(Napi::Env env, Hook hook, Arg* arg)
|
|
|
6585
6789
|
}
|
|
6586
6790
|
|
|
6587
6791
|
template <class Hook, class Arg>
|
|
6588
|
-
bool Env::CleanupHook<Hook, Arg>::Remove(
|
|
6792
|
+
bool Env::CleanupHook<Hook, Arg>::Remove(BasicEnv env) {
|
|
6589
6793
|
napi_status status = napi_remove_env_cleanup_hook(env, wrapper, data);
|
|
6590
6794
|
delete data;
|
|
6591
6795
|
data = nullptr;
|
|
@@ -6598,6 +6802,65 @@ bool Env::CleanupHook<Hook, Arg>::IsEmpty() const {
|
|
|
6598
6802
|
}
|
|
6599
6803
|
#endif // NAPI_VERSION > 2
|
|
6600
6804
|
|
|
6805
|
+
#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
6806
|
+
template <typename FinalizerType>
|
|
6807
|
+
inline void BasicEnv::PostFinalizer(FinalizerType finalizeCallback) const {
|
|
6808
|
+
using T = void*;
|
|
6809
|
+
details::FinalizeData<T, FinalizerType>* finalizeData =
|
|
6810
|
+
new details::FinalizeData<T, FinalizerType>(
|
|
6811
|
+
{std::move(finalizeCallback), nullptr});
|
|
6812
|
+
|
|
6813
|
+
napi_status status = node_api_post_finalizer(
|
|
6814
|
+
_env,
|
|
6815
|
+
details::FinalizeData<T, FinalizerType>::WrapperGCWithoutData,
|
|
6816
|
+
static_cast<void*>(nullptr),
|
|
6817
|
+
finalizeData);
|
|
6818
|
+
if (status != napi_ok) {
|
|
6819
|
+
delete finalizeData;
|
|
6820
|
+
NAPI_FATAL_IF_FAILED(
|
|
6821
|
+
status, "BasicEnv::PostFinalizer", "invalid arguments");
|
|
6822
|
+
}
|
|
6823
|
+
}
|
|
6824
|
+
|
|
6825
|
+
template <typename FinalizerType, typename T>
|
|
6826
|
+
inline void BasicEnv::PostFinalizer(FinalizerType finalizeCallback,
|
|
6827
|
+
T* data) const {
|
|
6828
|
+
details::FinalizeData<T, FinalizerType>* finalizeData =
|
|
6829
|
+
new details::FinalizeData<T, FinalizerType>(
|
|
6830
|
+
{std::move(finalizeCallback), nullptr});
|
|
6831
|
+
|
|
6832
|
+
napi_status status = node_api_post_finalizer(
|
|
6833
|
+
_env,
|
|
6834
|
+
details::FinalizeData<T, FinalizerType>::WrapperGC,
|
|
6835
|
+
data,
|
|
6836
|
+
finalizeData);
|
|
6837
|
+
if (status != napi_ok) {
|
|
6838
|
+
delete finalizeData;
|
|
6839
|
+
NAPI_FATAL_IF_FAILED(
|
|
6840
|
+
status, "BasicEnv::PostFinalizer", "invalid arguments");
|
|
6841
|
+
}
|
|
6842
|
+
}
|
|
6843
|
+
|
|
6844
|
+
template <typename FinalizerType, typename T, typename Hint>
|
|
6845
|
+
inline void BasicEnv::PostFinalizer(FinalizerType finalizeCallback,
|
|
6846
|
+
T* data,
|
|
6847
|
+
Hint* finalizeHint) const {
|
|
6848
|
+
details::FinalizeData<T, FinalizerType, Hint>* finalizeData =
|
|
6849
|
+
new details::FinalizeData<T, FinalizerType, Hint>(
|
|
6850
|
+
{std::move(finalizeCallback), finalizeHint});
|
|
6851
|
+
napi_status status = node_api_post_finalizer(
|
|
6852
|
+
_env,
|
|
6853
|
+
details::FinalizeData<T, FinalizerType, Hint>::WrapperGCWithHint,
|
|
6854
|
+
data,
|
|
6855
|
+
finalizeData);
|
|
6856
|
+
if (status != napi_ok) {
|
|
6857
|
+
delete finalizeData;
|
|
6858
|
+
NAPI_FATAL_IF_FAILED(
|
|
6859
|
+
status, "BasicEnv::PostFinalizer", "invalid arguments");
|
|
6860
|
+
}
|
|
6861
|
+
}
|
|
6862
|
+
#endif // NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
6863
|
+
|
|
6601
6864
|
#ifdef NAPI_CPP_CUSTOM_NAMESPACE
|
|
6602
6865
|
} // namespace NAPI_CPP_CUSTOM_NAMESPACE
|
|
6603
6866
|
#endif
|
package/napi.h
CHANGED
|
@@ -142,6 +142,26 @@ static_assert(sizeof(char16_t) == sizeof(wchar_t),
|
|
|
142
142
|
} \
|
|
143
143
|
} while (0)
|
|
144
144
|
|
|
145
|
+
// Internal check helper. Be careful that the formatted message length should be
|
|
146
|
+
// max 255 size and null terminated.
|
|
147
|
+
#define NAPI_INTERNAL_CHECK(expr, location, ...) \
|
|
148
|
+
do { \
|
|
149
|
+
if (!(expr)) { \
|
|
150
|
+
std::string msg = Napi::details::StringFormat(__VA_ARGS__); \
|
|
151
|
+
Napi::Error::Fatal(location, msg.c_str()); \
|
|
152
|
+
} \
|
|
153
|
+
} while (0)
|
|
154
|
+
|
|
155
|
+
#define NAPI_INTERNAL_CHECK_EQ(actual, expected, value_format, location) \
|
|
156
|
+
do { \
|
|
157
|
+
auto actual_value = (actual); \
|
|
158
|
+
NAPI_INTERNAL_CHECK(actual_value == (expected), \
|
|
159
|
+
location, \
|
|
160
|
+
"Expected " #actual " to be equal to " #expected \
|
|
161
|
+
", but got " value_format ".", \
|
|
162
|
+
actual_value); \
|
|
163
|
+
} while (0)
|
|
164
|
+
|
|
145
165
|
#define NAPI_FATAL_IF_FAILED(status, location, message) \
|
|
146
166
|
NAPI_CHECK((status) == napi_ok, location, message)
|
|
147
167
|
|
|
@@ -292,9 +312,9 @@ using MaybeOrValue = T;
|
|
|
292
312
|
///
|
|
293
313
|
/// In the V8 JavaScript engine, a Node-API environment approximately
|
|
294
314
|
/// corresponds to an Isolate.
|
|
295
|
-
class
|
|
315
|
+
class BasicEnv {
|
|
296
316
|
private:
|
|
297
|
-
|
|
317
|
+
node_api_nogc_env _env;
|
|
298
318
|
#if NAPI_VERSION > 5
|
|
299
319
|
template <typename T>
|
|
300
320
|
static void DefaultFini(Env, T* data);
|
|
@@ -302,20 +322,21 @@ class Env {
|
|
|
302
322
|
static void DefaultFiniWithHint(Env, DataType* data, HintType* hint);
|
|
303
323
|
#endif // NAPI_VERSION > 5
|
|
304
324
|
public:
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
325
|
+
BasicEnv(node_api_nogc_env env);
|
|
326
|
+
operator node_api_nogc_env() const;
|
|
327
|
+
|
|
328
|
+
// Without these operator overloads, the error:
|
|
329
|
+
//
|
|
330
|
+
// Use of overloaded operator '==' is ambiguous (with operand types
|
|
331
|
+
// 'Napi::Env' and 'Napi::Env')
|
|
332
|
+
//
|
|
333
|
+
// ... occurs when comparing foo.Env() == bar.Env() or foo.Env() == nullptr
|
|
334
|
+
bool operator==(const BasicEnv& other) const {
|
|
335
|
+
return _env == other._env;
|
|
336
|
+
};
|
|
337
|
+
bool operator==(std::nullptr_t /*other*/) const {
|
|
338
|
+
return _env == nullptr;
|
|
339
|
+
};
|
|
319
340
|
|
|
320
341
|
#if NAPI_VERSION > 2
|
|
321
342
|
template <typename Hook, typename Arg = void>
|
|
@@ -334,7 +355,7 @@ class Env {
|
|
|
334
355
|
|
|
335
356
|
template <typename T>
|
|
336
357
|
using Finalizer = void (*)(Env, T*);
|
|
337
|
-
template <typename T, Finalizer<T> fini =
|
|
358
|
+
template <typename T, Finalizer<T> fini = BasicEnv::DefaultFini<T>>
|
|
338
359
|
void SetInstanceData(T* data) const;
|
|
339
360
|
|
|
340
361
|
template <typename DataType, typename HintType>
|
|
@@ -342,7 +363,7 @@ class Env {
|
|
|
342
363
|
template <typename DataType,
|
|
343
364
|
typename HintType,
|
|
344
365
|
FinalizerWithHint<DataType, HintType> fini =
|
|
345
|
-
|
|
366
|
+
BasicEnv::DefaultFiniWithHint<DataType, HintType>>
|
|
346
367
|
void SetInstanceData(DataType* data, HintType* hint) const;
|
|
347
368
|
#endif // NAPI_VERSION > 5
|
|
348
369
|
|
|
@@ -351,9 +372,9 @@ class Env {
|
|
|
351
372
|
class CleanupHook {
|
|
352
373
|
public:
|
|
353
374
|
CleanupHook();
|
|
354
|
-
CleanupHook(
|
|
355
|
-
CleanupHook(
|
|
356
|
-
bool Remove(
|
|
375
|
+
CleanupHook(BasicEnv env, Hook hook, Arg* arg);
|
|
376
|
+
CleanupHook(BasicEnv env, Hook hook);
|
|
377
|
+
bool Remove(BasicEnv env);
|
|
357
378
|
bool IsEmpty() const;
|
|
358
379
|
|
|
359
380
|
private:
|
|
@@ -371,6 +392,39 @@ class Env {
|
|
|
371
392
|
#if NAPI_VERSION > 8
|
|
372
393
|
const char* GetModuleFileName() const;
|
|
373
394
|
#endif // NAPI_VERSION > 8
|
|
395
|
+
|
|
396
|
+
#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
397
|
+
template <typename FinalizerType>
|
|
398
|
+
inline void PostFinalizer(FinalizerType finalizeCallback) const;
|
|
399
|
+
|
|
400
|
+
template <typename FinalizerType, typename T>
|
|
401
|
+
inline void PostFinalizer(FinalizerType finalizeCallback, T* data) const;
|
|
402
|
+
|
|
403
|
+
template <typename FinalizerType, typename T, typename Hint>
|
|
404
|
+
inline void PostFinalizer(FinalizerType finalizeCallback,
|
|
405
|
+
T* data,
|
|
406
|
+
Hint* finalizeHint) const;
|
|
407
|
+
#endif // NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER
|
|
408
|
+
|
|
409
|
+
friend class Env;
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
class Env : public BasicEnv {
|
|
413
|
+
public:
|
|
414
|
+
Env(napi_env env);
|
|
415
|
+
|
|
416
|
+
operator napi_env() const;
|
|
417
|
+
|
|
418
|
+
Object Global() const;
|
|
419
|
+
Value Undefined() const;
|
|
420
|
+
Value Null() const;
|
|
421
|
+
|
|
422
|
+
bool IsExceptionPending() const;
|
|
423
|
+
Error GetAndClearPendingException() const;
|
|
424
|
+
|
|
425
|
+
MaybeOrValue<Value> RunScript(const char* utf8script) const;
|
|
426
|
+
MaybeOrValue<Value> RunScript(const std::string& utf8script) const;
|
|
427
|
+
MaybeOrValue<Value> RunScript(String script) const;
|
|
374
428
|
};
|
|
375
429
|
|
|
376
430
|
/// A JavaScript value of unknown type.
|
|
@@ -1268,7 +1322,7 @@ class TypedArrayOf : public TypedArray {
|
|
|
1268
1322
|
napi_typedarray_type type =
|
|
1269
1323
|
TypedArray::TypedArrayTypeForPrimitiveType<T>()
|
|
1270
1324
|
#else
|
|
1271
|
-
|
|
1325
|
+
napi_typedarray_type type
|
|
1272
1326
|
#endif
|
|
1273
1327
|
///< Type of array, if different from the default array type for the
|
|
1274
1328
|
///< template parameter T.
|
|
@@ -1291,7 +1345,7 @@ class TypedArrayOf : public TypedArray {
|
|
|
1291
1345
|
napi_typedarray_type type =
|
|
1292
1346
|
TypedArray::TypedArrayTypeForPrimitiveType<T>()
|
|
1293
1347
|
#else
|
|
1294
|
-
|
|
1348
|
+
napi_typedarray_type type
|
|
1295
1349
|
#endif
|
|
1296
1350
|
///< Type of array, if different from the default array type for the
|
|
1297
1351
|
///< template parameter T.
|
|
@@ -1381,8 +1435,8 @@ class DataView : public Object {
|
|
|
1381
1435
|
template <typename T>
|
|
1382
1436
|
void WriteData(size_t byteOffset, T value) const;
|
|
1383
1437
|
|
|
1384
|
-
void* _data;
|
|
1385
|
-
size_t _length;
|
|
1438
|
+
void* _data{};
|
|
1439
|
+
size_t _length{};
|
|
1386
1440
|
};
|
|
1387
1441
|
|
|
1388
1442
|
class Function : public Object {
|
|
@@ -1715,7 +1769,7 @@ FunctionReference Persistent(Function value);
|
|
|
1715
1769
|
///
|
|
1716
1770
|
/// Following C++ statements will not be executed. The exception will bubble
|
|
1717
1771
|
/// up as a C++ exception of type `Napi::Error`, until it is either caught
|
|
1718
|
-
/// while still in C++, or else automatically
|
|
1772
|
+
/// while still in C++, or else automatically propagated as a JavaScript
|
|
1719
1773
|
/// exception when the callback returns to JavaScript.
|
|
1720
1774
|
///
|
|
1721
1775
|
/// #### Example 2A - Propagating a Node-API C++ exception:
|
|
@@ -1888,7 +1942,7 @@ class CallbackInfo {
|
|
|
1888
1942
|
napi_value _this;
|
|
1889
1943
|
size_t _argc;
|
|
1890
1944
|
napi_value* _argv;
|
|
1891
|
-
napi_value _staticArgs[6];
|
|
1945
|
+
napi_value _staticArgs[6]{};
|
|
1892
1946
|
napi_value* _dynamicArgs;
|
|
1893
1947
|
void* _data;
|
|
1894
1948
|
};
|
|
@@ -2395,6 +2449,7 @@ class ObjectWrap : public InstanceWrap<T>, public Reference<Object> {
|
|
|
2395
2449
|
napi_property_attributes attributes = napi_default);
|
|
2396
2450
|
static Napi::Value OnCalledAsFunction(const Napi::CallbackInfo& callbackInfo);
|
|
2397
2451
|
virtual void Finalize(Napi::Env env);
|
|
2452
|
+
virtual void Finalize(BasicEnv env);
|
|
2398
2453
|
|
|
2399
2454
|
private:
|
|
2400
2455
|
using This = ObjectWrap<T>;
|
|
@@ -2409,7 +2464,10 @@ class ObjectWrap : public InstanceWrap<T>, public Reference<Object> {
|
|
|
2409
2464
|
napi_callback_info info);
|
|
2410
2465
|
static napi_value StaticSetterCallbackWrapper(napi_env env,
|
|
2411
2466
|
napi_callback_info info);
|
|
2412
|
-
static void FinalizeCallback(
|
|
2467
|
+
static void FinalizeCallback(node_api_nogc_env env, void* data, void* hint);
|
|
2468
|
+
|
|
2469
|
+
static void PostFinalizeCallback(napi_env env, void* data, void* hint);
|
|
2470
|
+
|
|
2413
2471
|
static Function DefineClass(Napi::Env env,
|
|
2414
2472
|
const char* utf8name,
|
|
2415
2473
|
const size_t props_count,
|
package/package.json
CHANGED
|
@@ -374,7 +374,6 @@
|
|
|
374
374
|
{
|
|
375
375
|
"name": "Vladimir Morozov",
|
|
376
376
|
"url": "https://github.com/vmoroz"
|
|
377
|
-
|
|
378
377
|
},
|
|
379
378
|
{
|
|
380
379
|
"name": "WenheLI",
|
|
@@ -431,7 +430,8 @@
|
|
|
431
430
|
"fs-extra": "^11.1.1",
|
|
432
431
|
"path": "^0.12.7",
|
|
433
432
|
"pre-commit": "^1.2.2",
|
|
434
|
-
"safe-buffer": "^5.1.1"
|
|
433
|
+
"safe-buffer": "^5.1.1",
|
|
434
|
+
"semver": "^7.6.0"
|
|
435
435
|
},
|
|
436
436
|
"directories": {},
|
|
437
437
|
"gypfile": false,
|
|
@@ -463,6 +463,9 @@
|
|
|
463
463
|
"scripts": {
|
|
464
464
|
"prebenchmark": "node-gyp rebuild -C benchmark",
|
|
465
465
|
"benchmark": "node benchmark",
|
|
466
|
+
"create-coverage": "npm test --coverage",
|
|
467
|
+
"report-coverage-html": "rm -rf coverage-html && mkdir coverage-html && gcovr -e test --merge-mode-functions merge-use-line-max --html-nested ./coverage-html/index.html test",
|
|
468
|
+
"report-coverage-xml": "rm -rf coverage-xml && mkdir coverage-xml && gcovr -e test --merge-mode-functions merge-use-line-max --xml -o ./coverage-xml/coverage-cxx.xml test",
|
|
466
469
|
"pretest": "node-gyp rebuild -C test",
|
|
467
470
|
"test": "node test",
|
|
468
471
|
"test:debug": "node-gyp rebuild -C test --debug && NODE_API_BUILD_CONFIG=Debug node ./test/index.js",
|
|
@@ -475,7 +478,7 @@
|
|
|
475
478
|
"lint:fix": "node tools/clang-format --fix && node tools/eslint-format --fix"
|
|
476
479
|
},
|
|
477
480
|
"pre-commit": "lint",
|
|
478
|
-
"version": "8.
|
|
481
|
+
"version": "8.2.0",
|
|
479
482
|
"support": true,
|
|
480
483
|
"engines": {
|
|
481
484
|
"node": "^18 || ^20 || >= 21"
|