node-addon-api 1.7.2 → 2.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/.travis.yml +4 -7
- package/CHANGELOG.md +54 -3
- package/README.md +6 -3
- package/doc/array_buffer.md +1 -1
- package/doc/async_context.md +10 -0
- package/doc/async_operations.md +1 -1
- package/doc/async_progress_worker.md +344 -0
- package/doc/async_worker.md +23 -22
- package/doc/basic_types.md +8 -0
- package/doc/class_property_descriptor.md +2 -3
- package/doc/cmake-js.md +58 -9
- package/doc/date.md +68 -0
- package/doc/object.md +34 -0
- package/doc/object_wrap.md +13 -2
- package/doc/prebuild_tools.md +1 -1
- package/doc/threadsafe_function.md +18 -1
- package/doc/value.md +9 -0
- package/napi-inl.h +346 -76
- package/napi.h +136 -18
- package/package.json +212 -47
- package/src/node_api.cc +3 -9
package/napi-inl.h
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
// Note: Do not include this file directly! Include "napi.h" instead.
|
|
11
11
|
|
|
12
|
+
#include <algorithm>
|
|
12
13
|
#include <cstring>
|
|
14
|
+
#include <mutex>
|
|
13
15
|
#include <type_traits>
|
|
14
16
|
|
|
15
17
|
namespace Napi {
|
|
@@ -24,16 +26,23 @@ namespace details {
|
|
|
24
26
|
template <typename FreeType>
|
|
25
27
|
static inline napi_status AttachData(napi_env env,
|
|
26
28
|
napi_value obj,
|
|
27
|
-
FreeType* data
|
|
29
|
+
FreeType* data,
|
|
30
|
+
napi_finalize finalizer = nullptr,
|
|
31
|
+
void* hint = nullptr) {
|
|
32
|
+
napi_status status;
|
|
33
|
+
if (finalizer == nullptr) {
|
|
34
|
+
finalizer = [](napi_env /*env*/, void* data, void* /*hint*/) {
|
|
35
|
+
delete static_cast<FreeType*>(data);
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
#if (NAPI_VERSION < 5)
|
|
28
39
|
napi_value symbol, external;
|
|
29
|
-
|
|
40
|
+
status = napi_create_symbol(env, nullptr, &symbol);
|
|
30
41
|
if (status == napi_ok) {
|
|
31
42
|
status = napi_create_external(env,
|
|
32
43
|
data,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
},
|
|
36
|
-
nullptr,
|
|
44
|
+
finalizer,
|
|
45
|
+
hint,
|
|
37
46
|
&external);
|
|
38
47
|
if (status == napi_ok) {
|
|
39
48
|
napi_property_descriptor desc = {
|
|
@@ -49,6 +58,9 @@ static inline napi_status AttachData(napi_env env,
|
|
|
49
58
|
status = napi_define_properties(env, obj, 1, &desc);
|
|
50
59
|
}
|
|
51
60
|
}
|
|
61
|
+
#else // NAPI_VERSION >= 5
|
|
62
|
+
status = napi_add_finalizer(env, obj, data, finalizer, hint, nullptr);
|
|
63
|
+
#endif
|
|
52
64
|
return status;
|
|
53
65
|
}
|
|
54
66
|
|
|
@@ -371,14 +383,28 @@ inline bool Value::IsNumber() const {
|
|
|
371
383
|
return Type() == napi_number;
|
|
372
384
|
}
|
|
373
385
|
|
|
374
|
-
//
|
|
375
|
-
//
|
|
376
|
-
|
|
386
|
+
// Currently experimental guard with the definition of NAPI_EXPERIMENTAL.
|
|
387
|
+
// Once it is no longer experimental guard with the NAPI_VERSION in which it is
|
|
388
|
+
// released instead.
|
|
389
|
+
#ifdef NAPI_EXPERIMENTAL
|
|
377
390
|
inline bool Value::IsBigInt() const {
|
|
378
391
|
return Type() == napi_bigint;
|
|
379
392
|
}
|
|
380
393
|
#endif // NAPI_EXPERIMENTAL
|
|
381
394
|
|
|
395
|
+
#if (NAPI_VERSION > 4)
|
|
396
|
+
inline bool Value::IsDate() const {
|
|
397
|
+
if (IsEmpty()) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
bool result;
|
|
402
|
+
napi_status status = napi_is_date(_env, _value, &result);
|
|
403
|
+
NAPI_THROW_IF_FAILED(_env, status, false);
|
|
404
|
+
return result;
|
|
405
|
+
}
|
|
406
|
+
#endif
|
|
407
|
+
|
|
382
408
|
inline bool Value::IsString() const {
|
|
383
409
|
return Type() == napi_string;
|
|
384
410
|
}
|
|
@@ -595,9 +621,10 @@ inline double Number::DoubleValue() const {
|
|
|
595
621
|
return result;
|
|
596
622
|
}
|
|
597
623
|
|
|
598
|
-
//
|
|
599
|
-
//
|
|
600
|
-
|
|
624
|
+
// Currently experimental guard with the definition of NAPI_EXPERIMENTAL.
|
|
625
|
+
// Once it is no longer experimental guard with the NAPI_VERSION in which it is
|
|
626
|
+
// released instead.
|
|
627
|
+
#ifdef NAPI_EXPERIMENTAL
|
|
601
628
|
////////////////////////////////////////////////////////////////////////////////
|
|
602
629
|
// BigInt Class
|
|
603
630
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -660,6 +687,37 @@ inline void BigInt::ToWords(int* sign_bit, size_t* word_count, uint64_t* words)
|
|
|
660
687
|
}
|
|
661
688
|
#endif // NAPI_EXPERIMENTAL
|
|
662
689
|
|
|
690
|
+
#if (NAPI_VERSION > 4)
|
|
691
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
692
|
+
// Date Class
|
|
693
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
694
|
+
|
|
695
|
+
inline Date Date::New(napi_env env, double val) {
|
|
696
|
+
napi_value value;
|
|
697
|
+
napi_status status = napi_create_date(env, val, &value);
|
|
698
|
+
NAPI_THROW_IF_FAILED(env, status, Date());
|
|
699
|
+
return Date(env, value);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
inline Date::Date() : Value() {
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
inline Date::Date(napi_env env, napi_value value) : Value(env, value) {
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
inline Date::operator double() const {
|
|
709
|
+
return ValueOf();
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
inline double Date::ValueOf() const {
|
|
713
|
+
double result;
|
|
714
|
+
napi_status status = napi_get_date_value(
|
|
715
|
+
_env, _value, &result);
|
|
716
|
+
NAPI_THROW_IF_FAILED(_env, status, 0);
|
|
717
|
+
return result;
|
|
718
|
+
}
|
|
719
|
+
#endif
|
|
720
|
+
|
|
663
721
|
////////////////////////////////////////////////////////////////////////////////
|
|
664
722
|
// Name class
|
|
665
723
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -1126,6 +1184,40 @@ inline bool Object::InstanceOf(const Function& constructor) const {
|
|
|
1126
1184
|
return result;
|
|
1127
1185
|
}
|
|
1128
1186
|
|
|
1187
|
+
template <typename Finalizer, typename T>
|
|
1188
|
+
inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) {
|
|
1189
|
+
details::FinalizeData<T, Finalizer>* finalizeData =
|
|
1190
|
+
new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
|
|
1191
|
+
napi_status status =
|
|
1192
|
+
details::AttachData(_env,
|
|
1193
|
+
*this,
|
|
1194
|
+
data,
|
|
1195
|
+
details::FinalizeData<T, Finalizer>::Wrapper,
|
|
1196
|
+
finalizeData);
|
|
1197
|
+
if (status != napi_ok) {
|
|
1198
|
+
delete finalizeData;
|
|
1199
|
+
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
template <typename Finalizer, typename T, typename Hint>
|
|
1204
|
+
inline void Object::AddFinalizer(Finalizer finalizeCallback,
|
|
1205
|
+
T* data,
|
|
1206
|
+
Hint* finalizeHint) {
|
|
1207
|
+
details::FinalizeData<T, Finalizer, Hint>* finalizeData =
|
|
1208
|
+
new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
|
|
1209
|
+
napi_status status =
|
|
1210
|
+
details::AttachData(_env,
|
|
1211
|
+
*this,
|
|
1212
|
+
data,
|
|
1213
|
+
details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
|
|
1214
|
+
finalizeData);
|
|
1215
|
+
if (status != napi_ok) {
|
|
1216
|
+
delete finalizeData;
|
|
1217
|
+
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1129
1221
|
////////////////////////////////////////////////////////////////////////////////
|
|
1130
1222
|
// External class
|
|
1131
1223
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -1950,47 +2042,43 @@ inline Error Error::New(napi_env env) {
|
|
|
1950
2042
|
status = napi_get_last_error_info(env, &info);
|
|
1951
2043
|
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info");
|
|
1952
2044
|
|
|
1953
|
-
if (
|
|
1954
|
-
|
|
2045
|
+
if (info->error_code == napi_pending_exception) {
|
|
2046
|
+
status = napi_get_and_clear_last_exception(env, &error);
|
|
2047
|
+
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
|
|
2048
|
+
}
|
|
2049
|
+
else {
|
|
2050
|
+
const char* error_message = info->error_message != nullptr ?
|
|
2051
|
+
info->error_message : "Error in native callback";
|
|
2052
|
+
|
|
2053
|
+
bool isExceptionPending;
|
|
2054
|
+
status = napi_is_exception_pending(env, &isExceptionPending);
|
|
2055
|
+
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
|
|
2056
|
+
|
|
2057
|
+
if (isExceptionPending) {
|
|
1955
2058
|
status = napi_get_and_clear_last_exception(env, &error);
|
|
1956
2059
|
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
|
|
1957
2060
|
}
|
|
1958
|
-
else {
|
|
1959
|
-
const char* error_message = info->error_message != nullptr ?
|
|
1960
|
-
info->error_message : "Error in native callback";
|
|
1961
2061
|
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
switch (info->error_code) {
|
|
1981
|
-
case napi_object_expected:
|
|
1982
|
-
case napi_string_expected:
|
|
1983
|
-
case napi_boolean_expected:
|
|
1984
|
-
case napi_number_expected:
|
|
1985
|
-
status = napi_create_type_error(env, nullptr, message, &error);
|
|
1986
|
-
break;
|
|
1987
|
-
default:
|
|
1988
|
-
status = napi_create_error(env, nullptr, message, &error);
|
|
1989
|
-
break;
|
|
1990
|
-
}
|
|
1991
|
-
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
|
|
1992
|
-
}
|
|
2062
|
+
napi_value message;
|
|
2063
|
+
status = napi_create_string_utf8(
|
|
2064
|
+
env,
|
|
2065
|
+
error_message,
|
|
2066
|
+
std::strlen(error_message),
|
|
2067
|
+
&message);
|
|
2068
|
+
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_string_utf8");
|
|
2069
|
+
|
|
2070
|
+
switch (info->error_code) {
|
|
2071
|
+
case napi_object_expected:
|
|
2072
|
+
case napi_string_expected:
|
|
2073
|
+
case napi_boolean_expected:
|
|
2074
|
+
case napi_number_expected:
|
|
2075
|
+
status = napi_create_type_error(env, nullptr, message, &error);
|
|
2076
|
+
break;
|
|
2077
|
+
default:
|
|
2078
|
+
status = napi_create_error(env, nullptr, message, &error);
|
|
2079
|
+
break;
|
|
1993
2080
|
}
|
|
2081
|
+
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
|
|
1994
2082
|
}
|
|
1995
2083
|
|
|
1996
2084
|
return Error(env, error);
|
|
@@ -2888,6 +2976,9 @@ inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
|
|
|
2888
2976
|
*instanceRef = Reference<Object>(env, ref);
|
|
2889
2977
|
}
|
|
2890
2978
|
|
|
2979
|
+
template<typename T>
|
|
2980
|
+
inline ObjectWrap<T>::~ObjectWrap() {}
|
|
2981
|
+
|
|
2891
2982
|
template<typename T>
|
|
2892
2983
|
inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
|
|
2893
2984
|
T* unwrapped;
|
|
@@ -3261,6 +3352,9 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
|
|
|
3261
3352
|
return desc;
|
|
3262
3353
|
}
|
|
3263
3354
|
|
|
3355
|
+
template <typename T>
|
|
3356
|
+
inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}
|
|
3357
|
+
|
|
3264
3358
|
template <typename T>
|
|
3265
3359
|
inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
|
|
3266
3360
|
napi_env env,
|
|
@@ -3402,8 +3496,9 @@ inline napi_value ObjectWrap<T>::InstanceSetterCallbackWrapper(
|
|
|
3402
3496
|
}
|
|
3403
3497
|
|
|
3404
3498
|
template <typename T>
|
|
3405
|
-
inline void ObjectWrap<T>::FinalizeCallback(napi_env
|
|
3499
|
+
inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hint*/) {
|
|
3406
3500
|
T* instance = reinterpret_cast<T*>(data);
|
|
3501
|
+
instance->Finalize(Napi::Env(env));
|
|
3407
3502
|
delete instance;
|
|
3408
3503
|
}
|
|
3409
3504
|
|
|
@@ -3421,7 +3516,10 @@ inline HandleScope::HandleScope(Napi::Env env) : _env(env) {
|
|
|
3421
3516
|
}
|
|
3422
3517
|
|
|
3423
3518
|
inline HandleScope::~HandleScope() {
|
|
3424
|
-
napi_close_handle_scope(_env, _scope);
|
|
3519
|
+
napi_status status = napi_close_handle_scope(_env, _scope);
|
|
3520
|
+
NAPI_FATAL_IF_FAILED(status,
|
|
3521
|
+
"HandleScope::~HandleScope",
|
|
3522
|
+
"napi_close_handle_scope");
|
|
3425
3523
|
}
|
|
3426
3524
|
|
|
3427
3525
|
inline HandleScope::operator napi_handle_scope() const {
|
|
@@ -3446,7 +3544,10 @@ inline EscapableHandleScope::EscapableHandleScope(Napi::Env env) : _env(env) {
|
|
|
3446
3544
|
}
|
|
3447
3545
|
|
|
3448
3546
|
inline EscapableHandleScope::~EscapableHandleScope() {
|
|
3449
|
-
napi_close_escapable_handle_scope(_env, _scope);
|
|
3547
|
+
napi_status status = napi_close_escapable_handle_scope(_env, _scope);
|
|
3548
|
+
NAPI_FATAL_IF_FAILED(status,
|
|
3549
|
+
"EscapableHandleScope::~EscapableHandleScope",
|
|
3550
|
+
"napi_close_escapable_handle_scope");
|
|
3450
3551
|
}
|
|
3451
3552
|
|
|
3452
3553
|
inline EscapableHandleScope::operator napi_escapable_handle_scope() const {
|
|
@@ -3482,7 +3583,10 @@ inline CallbackScope::CallbackScope(napi_env env, napi_async_context context)
|
|
|
3482
3583
|
}
|
|
3483
3584
|
|
|
3484
3585
|
inline CallbackScope::~CallbackScope() {
|
|
3485
|
-
napi_close_callback_scope(_env, _scope);
|
|
3586
|
+
napi_status status = napi_close_callback_scope(_env, _scope);
|
|
3587
|
+
NAPI_FATAL_IF_FAILED(status,
|
|
3588
|
+
"CallbackScope::~CallbackScope",
|
|
3589
|
+
"napi_close_callback_scope");
|
|
3486
3590
|
}
|
|
3487
3591
|
|
|
3488
3592
|
inline CallbackScope::operator napi_callback_scope() const {
|
|
@@ -3542,6 +3646,10 @@ inline AsyncContext::operator napi_async_context() const {
|
|
|
3542
3646
|
return _context;
|
|
3543
3647
|
}
|
|
3544
3648
|
|
|
3649
|
+
inline Napi::Env AsyncContext::Env() const {
|
|
3650
|
+
return Napi::Env(_env);
|
|
3651
|
+
}
|
|
3652
|
+
|
|
3545
3653
|
////////////////////////////////////////////////////////////////////////////////
|
|
3546
3654
|
// AsyncWorker class
|
|
3547
3655
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -3919,35 +4027,28 @@ inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
|
3919
4027
|
}
|
|
3920
4028
|
|
|
3921
4029
|
inline ThreadSafeFunction::ThreadSafeFunction()
|
|
3922
|
-
: _tsfn(
|
|
4030
|
+
: _tsfn() {
|
|
3923
4031
|
}
|
|
3924
4032
|
|
|
3925
4033
|
inline ThreadSafeFunction::ThreadSafeFunction(
|
|
3926
4034
|
napi_threadsafe_function tsfn)
|
|
3927
|
-
: _tsfn(
|
|
3928
|
-
}
|
|
3929
|
-
|
|
3930
|
-
inline ThreadSafeFunction::ThreadSafeFunction(ThreadSafeFunction&& other)
|
|
3931
|
-
: _tsfn(std::move(other._tsfn)) {
|
|
3932
|
-
other._tsfn.reset();
|
|
4035
|
+
: _tsfn(tsfn) {
|
|
3933
4036
|
}
|
|
3934
4037
|
|
|
3935
|
-
inline ThreadSafeFunction
|
|
3936
|
-
|
|
3937
|
-
if (*_tsfn != nullptr) {
|
|
3938
|
-
Error::Fatal("ThreadSafeFunction::operator =",
|
|
3939
|
-
"You cannot assign a new TSFN because existing one is still alive.");
|
|
3940
|
-
return *this;
|
|
3941
|
-
}
|
|
3942
|
-
_tsfn = std::move(other._tsfn);
|
|
3943
|
-
other._tsfn.reset();
|
|
3944
|
-
return *this;
|
|
4038
|
+
inline ThreadSafeFunction::operator napi_threadsafe_function() const {
|
|
4039
|
+
return _tsfn;
|
|
3945
4040
|
}
|
|
3946
4041
|
|
|
3947
4042
|
inline napi_status ThreadSafeFunction::BlockingCall() const {
|
|
3948
4043
|
return CallInternal(nullptr, napi_tsfn_blocking);
|
|
3949
4044
|
}
|
|
3950
4045
|
|
|
4046
|
+
template <>
|
|
4047
|
+
inline napi_status ThreadSafeFunction::BlockingCall(
|
|
4048
|
+
void* data) const {
|
|
4049
|
+
return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_blocking);
|
|
4050
|
+
}
|
|
4051
|
+
|
|
3951
4052
|
template <typename Callback>
|
|
3952
4053
|
inline napi_status ThreadSafeFunction::BlockingCall(
|
|
3953
4054
|
Callback callback) const {
|
|
@@ -3967,6 +4068,12 @@ inline napi_status ThreadSafeFunction::NonBlockingCall() const {
|
|
|
3967
4068
|
return CallInternal(nullptr, napi_tsfn_nonblocking);
|
|
3968
4069
|
}
|
|
3969
4070
|
|
|
4071
|
+
template <>
|
|
4072
|
+
inline napi_status ThreadSafeFunction::NonBlockingCall(
|
|
4073
|
+
void* data) const {
|
|
4074
|
+
return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_nonblocking);
|
|
4075
|
+
}
|
|
4076
|
+
|
|
3970
4077
|
template <typename Callback>
|
|
3971
4078
|
inline napi_status ThreadSafeFunction::NonBlockingCall(
|
|
3972
4079
|
Callback callback) const {
|
|
@@ -3982,22 +4089,37 @@ inline napi_status ThreadSafeFunction::NonBlockingCall(
|
|
|
3982
4089
|
return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_nonblocking);
|
|
3983
4090
|
}
|
|
3984
4091
|
|
|
4092
|
+
inline void ThreadSafeFunction::Ref(napi_env env) const {
|
|
4093
|
+
if (_tsfn != nullptr) {
|
|
4094
|
+
napi_status status = napi_ref_threadsafe_function(env, _tsfn);
|
|
4095
|
+
NAPI_THROW_IF_FAILED_VOID(env, status);
|
|
4096
|
+
}
|
|
4097
|
+
}
|
|
4098
|
+
|
|
4099
|
+
inline void ThreadSafeFunction::Unref(napi_env env) const {
|
|
4100
|
+
if (_tsfn != nullptr) {
|
|
4101
|
+
napi_status status = napi_unref_threadsafe_function(env, _tsfn);
|
|
4102
|
+
NAPI_THROW_IF_FAILED_VOID(env, status);
|
|
4103
|
+
}
|
|
4104
|
+
}
|
|
4105
|
+
|
|
3985
4106
|
inline napi_status ThreadSafeFunction::Acquire() const {
|
|
3986
|
-
return napi_acquire_threadsafe_function(
|
|
4107
|
+
return napi_acquire_threadsafe_function(_tsfn);
|
|
3987
4108
|
}
|
|
3988
4109
|
|
|
3989
4110
|
inline napi_status ThreadSafeFunction::Release() {
|
|
3990
|
-
return napi_release_threadsafe_function(
|
|
4111
|
+
return napi_release_threadsafe_function(_tsfn, napi_tsfn_release);
|
|
3991
4112
|
}
|
|
3992
4113
|
|
|
3993
4114
|
inline napi_status ThreadSafeFunction::Abort() {
|
|
3994
|
-
return napi_release_threadsafe_function(
|
|
4115
|
+
return napi_release_threadsafe_function(_tsfn, napi_tsfn_abort);
|
|
3995
4116
|
}
|
|
3996
4117
|
|
|
3997
4118
|
inline ThreadSafeFunction::ConvertibleContext
|
|
3998
4119
|
ThreadSafeFunction::GetContext() const {
|
|
3999
4120
|
void* context;
|
|
4000
|
-
napi_get_threadsafe_function_context(
|
|
4121
|
+
napi_status status = napi_get_threadsafe_function_context(_tsfn, &context);
|
|
4122
|
+
NAPI_FATAL_IF_FAILED(status, "ThreadSafeFunction::GetContext", "napi_get_threadsafe_function_context");
|
|
4001
4123
|
return ConvertibleContext({ context });
|
|
4002
4124
|
}
|
|
4003
4125
|
|
|
@@ -4020,10 +4142,10 @@ inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
|
4020
4142
|
|
|
4021
4143
|
ThreadSafeFunction tsfn;
|
|
4022
4144
|
auto* finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
|
|
4023
|
-
FinalizerDataType>({ data, finalizeCallback, tsfn._tsfn
|
|
4145
|
+
FinalizerDataType>({ data, finalizeCallback, &tsfn._tsfn });
|
|
4024
4146
|
napi_status status = napi_create_threadsafe_function(env, callback, resource,
|
|
4025
4147
|
Value::From(env, resourceName), maxQueueSize, initialThreadCount,
|
|
4026
|
-
finalizeData, wrapper, context, CallJS, tsfn._tsfn
|
|
4148
|
+
finalizeData, wrapper, context, CallJS, &tsfn._tsfn);
|
|
4027
4149
|
if (status != napi_ok) {
|
|
4028
4150
|
delete finalizeData;
|
|
4029
4151
|
NAPI_THROW_IF_FAILED(env, status, ThreadSafeFunction());
|
|
@@ -4036,7 +4158,7 @@ inline napi_status ThreadSafeFunction::CallInternal(
|
|
|
4036
4158
|
CallbackWrapper* callbackWrapper,
|
|
4037
4159
|
napi_threadsafe_function_call_mode mode) const {
|
|
4038
4160
|
napi_status status = napi_call_threadsafe_function(
|
|
4039
|
-
|
|
4161
|
+
_tsfn, callbackWrapper, mode);
|
|
4040
4162
|
if (status != napi_ok && callbackWrapper != nullptr) {
|
|
4041
4163
|
delete callbackWrapper;
|
|
4042
4164
|
}
|
|
@@ -4061,6 +4183,154 @@ inline void ThreadSafeFunction::CallJS(napi_env env,
|
|
|
4061
4183
|
Function(env, jsCallback).Call({});
|
|
4062
4184
|
}
|
|
4063
4185
|
}
|
|
4186
|
+
|
|
4187
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4188
|
+
// Async Progress Worker class
|
|
4189
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4190
|
+
|
|
4191
|
+
template<class T>
|
|
4192
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback)
|
|
4193
|
+
: AsyncProgressWorker(callback, "generic") {
|
|
4194
|
+
}
|
|
4195
|
+
|
|
4196
|
+
template<class T>
|
|
4197
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
|
|
4198
|
+
const char* resource_name)
|
|
4199
|
+
: AsyncProgressWorker(callback, resource_name, Object::New(callback.Env())) {
|
|
4200
|
+
}
|
|
4201
|
+
|
|
4202
|
+
template<class T>
|
|
4203
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
|
|
4204
|
+
const char* resource_name,
|
|
4205
|
+
const Object& resource)
|
|
4206
|
+
: AsyncProgressWorker(Object::New(callback.Env()),
|
|
4207
|
+
callback,
|
|
4208
|
+
resource_name,
|
|
4209
|
+
resource) {
|
|
4210
|
+
}
|
|
4211
|
+
|
|
4212
|
+
template<class T>
|
|
4213
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
|
|
4214
|
+
const Function& callback)
|
|
4215
|
+
: AsyncProgressWorker(receiver, callback, "generic") {
|
|
4216
|
+
}
|
|
4217
|
+
|
|
4218
|
+
template<class T>
|
|
4219
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
|
|
4220
|
+
const Function& callback,
|
|
4221
|
+
const char* resource_name)
|
|
4222
|
+
: AsyncProgressWorker(receiver,
|
|
4223
|
+
callback,
|
|
4224
|
+
resource_name,
|
|
4225
|
+
Object::New(callback.Env())) {
|
|
4226
|
+
}
|
|
4227
|
+
|
|
4228
|
+
template<class T>
|
|
4229
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
|
|
4230
|
+
const Function& callback,
|
|
4231
|
+
const char* resource_name,
|
|
4232
|
+
const Object& resource)
|
|
4233
|
+
: AsyncWorker(receiver, callback, resource_name, resource),
|
|
4234
|
+
_asyncdata(nullptr),
|
|
4235
|
+
_asyncsize(0) {
|
|
4236
|
+
_tsfn = ThreadSafeFunction::New(callback.Env(), callback, resource_name, 1, 1);
|
|
4237
|
+
}
|
|
4238
|
+
|
|
4239
|
+
#if NAPI_VERSION > 4
|
|
4240
|
+
template<class T>
|
|
4241
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env)
|
|
4242
|
+
: AsyncProgressWorker(env, "generic") {
|
|
4243
|
+
}
|
|
4244
|
+
|
|
4245
|
+
template<class T>
|
|
4246
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
|
|
4247
|
+
const char* resource_name)
|
|
4248
|
+
: AsyncProgressWorker(env, resource_name, Object::New(env)) {
|
|
4249
|
+
}
|
|
4250
|
+
|
|
4251
|
+
template<class T>
|
|
4252
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
|
|
4253
|
+
const char* resource_name,
|
|
4254
|
+
const Object& resource)
|
|
4255
|
+
: AsyncWorker(env, resource_name, resource),
|
|
4256
|
+
_asyncdata(nullptr),
|
|
4257
|
+
_asyncsize(0) {
|
|
4258
|
+
// TODO: Once the changes to make the callback optional for threadsafe
|
|
4259
|
+
// functions are no longer optional we can remove the dummy Function here.
|
|
4260
|
+
Function callback;
|
|
4261
|
+
_tsfn = ThreadSafeFunction::New(env, callback, resource_name, 1, 1);
|
|
4262
|
+
}
|
|
4263
|
+
#endif
|
|
4264
|
+
|
|
4265
|
+
template<class T>
|
|
4266
|
+
inline AsyncProgressWorker<T>::~AsyncProgressWorker() {
|
|
4267
|
+
// Abort pending tsfn call.
|
|
4268
|
+
// Don't send progress events after we've already completed.
|
|
4269
|
+
_tsfn.Abort();
|
|
4270
|
+
{
|
|
4271
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
|
4272
|
+
_asyncdata = nullptr;
|
|
4273
|
+
_asyncsize = 0;
|
|
4274
|
+
}
|
|
4275
|
+
_tsfn.Release();
|
|
4276
|
+
}
|
|
4277
|
+
|
|
4278
|
+
template<class T>
|
|
4279
|
+
inline void AsyncProgressWorker<T>::Execute() {
|
|
4280
|
+
ExecutionProgress progress(this);
|
|
4281
|
+
Execute(progress);
|
|
4282
|
+
}
|
|
4283
|
+
|
|
4284
|
+
template<class T>
|
|
4285
|
+
inline void AsyncProgressWorker<T>::WorkProgress_(Napi::Env /* env */, Napi::Function /* jsCallback */, void* _data) {
|
|
4286
|
+
AsyncProgressWorker* self = static_cast<AsyncProgressWorker*>(_data);
|
|
4287
|
+
|
|
4288
|
+
T* data;
|
|
4289
|
+
size_t size;
|
|
4290
|
+
{
|
|
4291
|
+
std::lock_guard<std::mutex> lock(self->_mutex);
|
|
4292
|
+
data = self->_asyncdata;
|
|
4293
|
+
size = self->_asyncsize;
|
|
4294
|
+
self->_asyncdata = nullptr;
|
|
4295
|
+
self->_asyncsize = 0;
|
|
4296
|
+
}
|
|
4297
|
+
|
|
4298
|
+
self->OnProgress(data, size);
|
|
4299
|
+
delete[] data;
|
|
4300
|
+
}
|
|
4301
|
+
|
|
4302
|
+
template<class T>
|
|
4303
|
+
inline void AsyncProgressWorker<T>::SendProgress_(const T* data, size_t count) {
|
|
4304
|
+
T* new_data = new T[count];
|
|
4305
|
+
std::copy(data, data + count, new_data);
|
|
4306
|
+
|
|
4307
|
+
T* old_data;
|
|
4308
|
+
{
|
|
4309
|
+
std::lock_guard<std::mutex> lock(_mutex);
|
|
4310
|
+
old_data = _asyncdata;
|
|
4311
|
+
_asyncdata = new_data;
|
|
4312
|
+
_asyncsize = count;
|
|
4313
|
+
}
|
|
4314
|
+
_tsfn.NonBlockingCall(this, WorkProgress_);
|
|
4315
|
+
|
|
4316
|
+
delete[] old_data;
|
|
4317
|
+
}
|
|
4318
|
+
|
|
4319
|
+
template<class T>
|
|
4320
|
+
inline void AsyncProgressWorker<T>::Signal() const {
|
|
4321
|
+
_tsfn.NonBlockingCall(this, WorkProgress_);
|
|
4322
|
+
}
|
|
4323
|
+
|
|
4324
|
+
template<class T>
|
|
4325
|
+
inline void AsyncProgressWorker<T>::ExecutionProgress::Signal() const {
|
|
4326
|
+
_worker->Signal();
|
|
4327
|
+
}
|
|
4328
|
+
|
|
4329
|
+
template<class T>
|
|
4330
|
+
inline void AsyncProgressWorker<T>::ExecutionProgress::Send(const T* data, size_t count) const {
|
|
4331
|
+
_worker->SendProgress_(data, count);
|
|
4332
|
+
}
|
|
4333
|
+
|
|
4064
4334
|
#endif
|
|
4065
4335
|
|
|
4066
4336
|
////////////////////////////////////////////////////////////////////////////////
|