node-addon-api 1.6.3 → 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 +121 -1
- package/CONTRIBUTING.md +66 -0
- package/README.md +12 -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 +97 -25
- package/doc/basic_types.md +19 -0
- package/doc/class_property_descriptor.md +82 -1
- package/doc/cmake-js.md +58 -9
- package/doc/date.md +68 -0
- package/doc/object.md +36 -2
- package/doc/object_wrap.md +14 -3
- package/doc/prebuild_tools.md +2 -2
- package/doc/string.md +3 -0
- package/doc/threadsafe_function.md +320 -0
- package/doc/value.md +9 -0
- package/napi-inl.h +769 -63
- package/napi.h +351 -21
- package/package.json +212 -41
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
|
|
|
@@ -125,6 +137,80 @@ struct FinalizeData {
|
|
|
125
137
|
Hint* hint;
|
|
126
138
|
};
|
|
127
139
|
|
|
140
|
+
#if (NAPI_VERSION > 3)
|
|
141
|
+
template <typename ContextType=void,
|
|
142
|
+
typename Finalizer=std::function<void(Env, void*, ContextType*)>,
|
|
143
|
+
typename FinalizerDataType=void>
|
|
144
|
+
struct ThreadSafeFinalize {
|
|
145
|
+
static inline
|
|
146
|
+
void Wrapper(napi_env env, void* rawFinalizeData, void* /* rawContext */) {
|
|
147
|
+
if (rawFinalizeData == nullptr)
|
|
148
|
+
return;
|
|
149
|
+
|
|
150
|
+
ThreadSafeFinalize* finalizeData =
|
|
151
|
+
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
152
|
+
finalizeData->callback(Env(env));
|
|
153
|
+
if (finalizeData->tsfn) {
|
|
154
|
+
*finalizeData->tsfn = nullptr;
|
|
155
|
+
}
|
|
156
|
+
delete finalizeData;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
static inline
|
|
160
|
+
void FinalizeWrapperWithData(napi_env env,
|
|
161
|
+
void* rawFinalizeData,
|
|
162
|
+
void* /* rawContext */) {
|
|
163
|
+
if (rawFinalizeData == nullptr)
|
|
164
|
+
return;
|
|
165
|
+
|
|
166
|
+
ThreadSafeFinalize* finalizeData =
|
|
167
|
+
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
168
|
+
finalizeData->callback(Env(env), finalizeData->data);
|
|
169
|
+
if (finalizeData->tsfn) {
|
|
170
|
+
*finalizeData->tsfn = nullptr;
|
|
171
|
+
}
|
|
172
|
+
delete finalizeData;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
static inline
|
|
176
|
+
void FinalizeWrapperWithContext(napi_env env,
|
|
177
|
+
void* rawFinalizeData,
|
|
178
|
+
void* rawContext) {
|
|
179
|
+
if (rawFinalizeData == nullptr)
|
|
180
|
+
return;
|
|
181
|
+
|
|
182
|
+
ThreadSafeFinalize* finalizeData =
|
|
183
|
+
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
184
|
+
finalizeData->callback(Env(env), static_cast<ContextType*>(rawContext));
|
|
185
|
+
if (finalizeData->tsfn) {
|
|
186
|
+
*finalizeData->tsfn = nullptr;
|
|
187
|
+
}
|
|
188
|
+
delete finalizeData;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
static inline
|
|
192
|
+
void FinalizeFinalizeWrapperWithDataAndContext(napi_env env,
|
|
193
|
+
void* rawFinalizeData,
|
|
194
|
+
void* rawContext) {
|
|
195
|
+
if (rawFinalizeData == nullptr)
|
|
196
|
+
return;
|
|
197
|
+
|
|
198
|
+
ThreadSafeFinalize* finalizeData =
|
|
199
|
+
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
200
|
+
finalizeData->callback(Env(env), finalizeData->data,
|
|
201
|
+
static_cast<ContextType*>(rawContext));
|
|
202
|
+
if (finalizeData->tsfn) {
|
|
203
|
+
*finalizeData->tsfn = nullptr;
|
|
204
|
+
}
|
|
205
|
+
delete finalizeData;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
FinalizerDataType* data;
|
|
209
|
+
Finalizer callback;
|
|
210
|
+
napi_threadsafe_function* tsfn;
|
|
211
|
+
};
|
|
212
|
+
#endif
|
|
213
|
+
|
|
128
214
|
template <typename Getter, typename Setter>
|
|
129
215
|
struct AccessorCallbackData {
|
|
130
216
|
static inline
|
|
@@ -271,7 +357,7 @@ inline bool Value::IsEmpty() const {
|
|
|
271
357
|
}
|
|
272
358
|
|
|
273
359
|
inline napi_valuetype Value::Type() const {
|
|
274
|
-
if (
|
|
360
|
+
if (IsEmpty()) {
|
|
275
361
|
return napi_undefined;
|
|
276
362
|
}
|
|
277
363
|
|
|
@@ -297,14 +383,28 @@ inline bool Value::IsNumber() const {
|
|
|
297
383
|
return Type() == napi_number;
|
|
298
384
|
}
|
|
299
385
|
|
|
300
|
-
//
|
|
301
|
-
//
|
|
302
|
-
|
|
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
|
|
303
390
|
inline bool Value::IsBigInt() const {
|
|
304
391
|
return Type() == napi_bigint;
|
|
305
392
|
}
|
|
306
393
|
#endif // NAPI_EXPERIMENTAL
|
|
307
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
|
+
|
|
308
408
|
inline bool Value::IsString() const {
|
|
309
409
|
return Type() == napi_string;
|
|
310
410
|
}
|
|
@@ -314,7 +414,7 @@ inline bool Value::IsSymbol() const {
|
|
|
314
414
|
}
|
|
315
415
|
|
|
316
416
|
inline bool Value::IsArray() const {
|
|
317
|
-
if (
|
|
417
|
+
if (IsEmpty()) {
|
|
318
418
|
return false;
|
|
319
419
|
}
|
|
320
420
|
|
|
@@ -325,7 +425,7 @@ inline bool Value::IsArray() const {
|
|
|
325
425
|
}
|
|
326
426
|
|
|
327
427
|
inline bool Value::IsArrayBuffer() const {
|
|
328
|
-
if (
|
|
428
|
+
if (IsEmpty()) {
|
|
329
429
|
return false;
|
|
330
430
|
}
|
|
331
431
|
|
|
@@ -336,7 +436,7 @@ inline bool Value::IsArrayBuffer() const {
|
|
|
336
436
|
}
|
|
337
437
|
|
|
338
438
|
inline bool Value::IsTypedArray() const {
|
|
339
|
-
if (
|
|
439
|
+
if (IsEmpty()) {
|
|
340
440
|
return false;
|
|
341
441
|
}
|
|
342
442
|
|
|
@@ -355,7 +455,7 @@ inline bool Value::IsFunction() const {
|
|
|
355
455
|
}
|
|
356
456
|
|
|
357
457
|
inline bool Value::IsPromise() const {
|
|
358
|
-
if (
|
|
458
|
+
if (IsEmpty()) {
|
|
359
459
|
return false;
|
|
360
460
|
}
|
|
361
461
|
|
|
@@ -366,7 +466,7 @@ inline bool Value::IsPromise() const {
|
|
|
366
466
|
}
|
|
367
467
|
|
|
368
468
|
inline bool Value::IsDataView() const {
|
|
369
|
-
if (
|
|
469
|
+
if (IsEmpty()) {
|
|
370
470
|
return false;
|
|
371
471
|
}
|
|
372
472
|
|
|
@@ -377,7 +477,7 @@ inline bool Value::IsDataView() const {
|
|
|
377
477
|
}
|
|
378
478
|
|
|
379
479
|
inline bool Value::IsBuffer() const {
|
|
380
|
-
if (
|
|
480
|
+
if (IsEmpty()) {
|
|
381
481
|
return false;
|
|
382
482
|
}
|
|
383
483
|
|
|
@@ -521,9 +621,10 @@ inline double Number::DoubleValue() const {
|
|
|
521
621
|
return result;
|
|
522
622
|
}
|
|
523
623
|
|
|
524
|
-
//
|
|
525
|
-
//
|
|
526
|
-
|
|
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
|
|
527
628
|
////////////////////////////////////////////////////////////////////////////////
|
|
528
629
|
// BigInt Class
|
|
529
630
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -586,6 +687,37 @@ inline void BigInt::ToWords(int* sign_bit, size_t* word_count, uint64_t* words)
|
|
|
586
687
|
}
|
|
587
688
|
#endif // NAPI_EXPERIMENTAL
|
|
588
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
|
+
|
|
589
721
|
////////////////////////////////////////////////////////////////////////////////
|
|
590
722
|
// Name class
|
|
591
723
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -1052,6 +1184,40 @@ inline bool Object::InstanceOf(const Function& constructor) const {
|
|
|
1052
1184
|
return result;
|
|
1053
1185
|
}
|
|
1054
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
|
+
|
|
1055
1221
|
////////////////////////////////////////////////////////////////////////////////
|
|
1056
1222
|
// External class
|
|
1057
1223
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -1876,47 +2042,43 @@ inline Error Error::New(napi_env env) {
|
|
|
1876
2042
|
status = napi_get_last_error_info(env, &info);
|
|
1877
2043
|
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info");
|
|
1878
2044
|
|
|
1879
|
-
if (
|
|
1880
|
-
|
|
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) {
|
|
1881
2058
|
status = napi_get_and_clear_last_exception(env, &error);
|
|
1882
2059
|
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
|
|
1883
2060
|
}
|
|
1884
|
-
else {
|
|
1885
|
-
const char* error_message = info->error_message != nullptr ?
|
|
1886
|
-
info->error_message : "Error in native callback";
|
|
1887
|
-
|
|
1888
|
-
bool isExceptionPending;
|
|
1889
|
-
status = napi_is_exception_pending(env, &isExceptionPending);
|
|
1890
|
-
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
|
|
1891
|
-
|
|
1892
|
-
if (isExceptionPending) {
|
|
1893
|
-
status = napi_get_and_clear_last_exception(env, &error);
|
|
1894
|
-
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
|
|
1895
|
-
}
|
|
1896
2061
|
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
break;
|
|
1916
|
-
}
|
|
1917
|
-
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
|
|
1918
|
-
}
|
|
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;
|
|
1919
2080
|
}
|
|
2081
|
+
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
|
|
1920
2082
|
}
|
|
1921
2083
|
|
|
1922
2084
|
return Error(env, error);
|
|
@@ -2814,6 +2976,9 @@ inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
|
|
|
2814
2976
|
*instanceRef = Reference<Object>(env, ref);
|
|
2815
2977
|
}
|
|
2816
2978
|
|
|
2979
|
+
template<typename T>
|
|
2980
|
+
inline ObjectWrap<T>::~ObjectWrap() {}
|
|
2981
|
+
|
|
2817
2982
|
template<typename T>
|
|
2818
2983
|
inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
|
|
2819
2984
|
T* unwrapped;
|
|
@@ -3187,6 +3352,9 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
|
|
|
3187
3352
|
return desc;
|
|
3188
3353
|
}
|
|
3189
3354
|
|
|
3355
|
+
template <typename T>
|
|
3356
|
+
inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}
|
|
3357
|
+
|
|
3190
3358
|
template <typename T>
|
|
3191
3359
|
inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
|
|
3192
3360
|
napi_env env,
|
|
@@ -3328,8 +3496,9 @@ inline napi_value ObjectWrap<T>::InstanceSetterCallbackWrapper(
|
|
|
3328
3496
|
}
|
|
3329
3497
|
|
|
3330
3498
|
template <typename T>
|
|
3331
|
-
inline void ObjectWrap<T>::FinalizeCallback(napi_env
|
|
3499
|
+
inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hint*/) {
|
|
3332
3500
|
T* instance = reinterpret_cast<T*>(data);
|
|
3501
|
+
instance->Finalize(Napi::Env(env));
|
|
3333
3502
|
delete instance;
|
|
3334
3503
|
}
|
|
3335
3504
|
|
|
@@ -3347,7 +3516,10 @@ inline HandleScope::HandleScope(Napi::Env env) : _env(env) {
|
|
|
3347
3516
|
}
|
|
3348
3517
|
|
|
3349
3518
|
inline HandleScope::~HandleScope() {
|
|
3350
|
-
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");
|
|
3351
3523
|
}
|
|
3352
3524
|
|
|
3353
3525
|
inline HandleScope::operator napi_handle_scope() const {
|
|
@@ -3372,7 +3544,10 @@ inline EscapableHandleScope::EscapableHandleScope(Napi::Env env) : _env(env) {
|
|
|
3372
3544
|
}
|
|
3373
3545
|
|
|
3374
3546
|
inline EscapableHandleScope::~EscapableHandleScope() {
|
|
3375
|
-
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");
|
|
3376
3551
|
}
|
|
3377
3552
|
|
|
3378
3553
|
inline EscapableHandleScope::operator napi_escapable_handle_scope() const {
|
|
@@ -3408,7 +3583,10 @@ inline CallbackScope::CallbackScope(napi_env env, napi_async_context context)
|
|
|
3408
3583
|
}
|
|
3409
3584
|
|
|
3410
3585
|
inline CallbackScope::~CallbackScope() {
|
|
3411
|
-
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");
|
|
3412
3590
|
}
|
|
3413
3591
|
|
|
3414
3592
|
inline CallbackScope::operator napi_callback_scope() const {
|
|
@@ -3468,6 +3646,10 @@ inline AsyncContext::operator napi_async_context() const {
|
|
|
3468
3646
|
return _context;
|
|
3469
3647
|
}
|
|
3470
3648
|
|
|
3649
|
+
inline Napi::Env AsyncContext::Env() const {
|
|
3650
|
+
return Napi::Env(_env);
|
|
3651
|
+
}
|
|
3652
|
+
|
|
3471
3653
|
////////////////////////////////////////////////////////////////////////////////
|
|
3472
3654
|
// AsyncWorker class
|
|
3473
3655
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -3522,6 +3704,32 @@ inline AsyncWorker::AsyncWorker(const Object& receiver,
|
|
|
3522
3704
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3523
3705
|
}
|
|
3524
3706
|
|
|
3707
|
+
inline AsyncWorker::AsyncWorker(Napi::Env env)
|
|
3708
|
+
: AsyncWorker(env, "generic") {
|
|
3709
|
+
}
|
|
3710
|
+
|
|
3711
|
+
inline AsyncWorker::AsyncWorker(Napi::Env env,
|
|
3712
|
+
const char* resource_name)
|
|
3713
|
+
: AsyncWorker(env, resource_name, Object::New(env)) {
|
|
3714
|
+
}
|
|
3715
|
+
|
|
3716
|
+
inline AsyncWorker::AsyncWorker(Napi::Env env,
|
|
3717
|
+
const char* resource_name,
|
|
3718
|
+
const Object& resource)
|
|
3719
|
+
: _env(env),
|
|
3720
|
+
_receiver(),
|
|
3721
|
+
_callback(),
|
|
3722
|
+
_suppress_destruct(false) {
|
|
3723
|
+
napi_value resource_id;
|
|
3724
|
+
napi_status status = napi_create_string_latin1(
|
|
3725
|
+
_env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
|
|
3726
|
+
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3727
|
+
|
|
3728
|
+
status = napi_create_async_work(_env, resource, resource_id, OnExecute,
|
|
3729
|
+
OnWorkComplete, this, &_work);
|
|
3730
|
+
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3525
3733
|
inline AsyncWorker::~AsyncWorker() {
|
|
3526
3734
|
if (_work != nullptr) {
|
|
3527
3735
|
napi_delete_async_work(_env, _work);
|
|
@@ -3529,6 +3737,10 @@ inline AsyncWorker::~AsyncWorker() {
|
|
|
3529
3737
|
}
|
|
3530
3738
|
}
|
|
3531
3739
|
|
|
3740
|
+
inline void AsyncWorker::Destroy() {
|
|
3741
|
+
delete this;
|
|
3742
|
+
}
|
|
3743
|
+
|
|
3532
3744
|
inline AsyncWorker::AsyncWorker(AsyncWorker&& other) {
|
|
3533
3745
|
_env = other._env;
|
|
3534
3746
|
other._env = nullptr;
|
|
@@ -3583,18 +3795,29 @@ inline void AsyncWorker::SuppressDestruct() {
|
|
|
3583
3795
|
}
|
|
3584
3796
|
|
|
3585
3797
|
inline void AsyncWorker::OnOK() {
|
|
3586
|
-
_callback.
|
|
3798
|
+
if (!_callback.IsEmpty()) {
|
|
3799
|
+
_callback.Call(_receiver.Value(), GetResult(_callback.Env()));
|
|
3800
|
+
}
|
|
3587
3801
|
}
|
|
3588
3802
|
|
|
3589
3803
|
inline void AsyncWorker::OnError(const Error& e) {
|
|
3590
|
-
_callback.
|
|
3804
|
+
if (!_callback.IsEmpty()) {
|
|
3805
|
+
_callback.Call(_receiver.Value(), std::initializer_list<napi_value>{ e.Value() });
|
|
3806
|
+
}
|
|
3591
3807
|
}
|
|
3592
3808
|
|
|
3593
3809
|
inline void AsyncWorker::SetError(const std::string& error) {
|
|
3594
3810
|
_error = error;
|
|
3595
3811
|
}
|
|
3596
3812
|
|
|
3597
|
-
inline
|
|
3813
|
+
inline std::vector<napi_value> AsyncWorker::GetResult(Napi::Env /*env*/) {
|
|
3814
|
+
return {};
|
|
3815
|
+
}
|
|
3816
|
+
// The OnExecute method receives an napi_env argument. However, do NOT
|
|
3817
|
+
// use it within this method, as it does not run on the main thread and must
|
|
3818
|
+
// not run any method that would cause JavaScript to run. In practice, this
|
|
3819
|
+
// means that almost any use of napi_env will be incorrect.
|
|
3820
|
+
inline void AsyncWorker::OnExecute(napi_env /*DO_NOT_USE*/, void* this_pointer) {
|
|
3598
3821
|
AsyncWorker* self = static_cast<AsyncWorker*>(this_pointer);
|
|
3599
3822
|
#ifdef NAPI_CPP_EXCEPTIONS
|
|
3600
3823
|
try {
|
|
@@ -3623,10 +3846,493 @@ inline void AsyncWorker::OnWorkComplete(
|
|
|
3623
3846
|
});
|
|
3624
3847
|
}
|
|
3625
3848
|
if (!self->_suppress_destruct) {
|
|
3626
|
-
|
|
3849
|
+
self->Destroy();
|
|
3627
3850
|
}
|
|
3628
3851
|
}
|
|
3629
3852
|
|
|
3853
|
+
#if (NAPI_VERSION > 3)
|
|
3854
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
3855
|
+
// ThreadSafeFunction class
|
|
3856
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
3857
|
+
|
|
3858
|
+
// static
|
|
3859
|
+
template <typename ResourceString>
|
|
3860
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3861
|
+
const Function& callback,
|
|
3862
|
+
ResourceString resourceName,
|
|
3863
|
+
size_t maxQueueSize,
|
|
3864
|
+
size_t initialThreadCount) {
|
|
3865
|
+
return New(env, callback, Object(), resourceName, maxQueueSize,
|
|
3866
|
+
initialThreadCount);
|
|
3867
|
+
}
|
|
3868
|
+
|
|
3869
|
+
// static
|
|
3870
|
+
template <typename ResourceString, typename ContextType>
|
|
3871
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3872
|
+
const Function& callback,
|
|
3873
|
+
ResourceString resourceName,
|
|
3874
|
+
size_t maxQueueSize,
|
|
3875
|
+
size_t initialThreadCount,
|
|
3876
|
+
ContextType* context) {
|
|
3877
|
+
return New(env, callback, Object(), resourceName, maxQueueSize,
|
|
3878
|
+
initialThreadCount, context);
|
|
3879
|
+
}
|
|
3880
|
+
|
|
3881
|
+
// static
|
|
3882
|
+
template <typename ResourceString, typename Finalizer>
|
|
3883
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3884
|
+
const Function& callback,
|
|
3885
|
+
ResourceString resourceName,
|
|
3886
|
+
size_t maxQueueSize,
|
|
3887
|
+
size_t initialThreadCount,
|
|
3888
|
+
Finalizer finalizeCallback) {
|
|
3889
|
+
return New(env, callback, Object(), resourceName, maxQueueSize,
|
|
3890
|
+
initialThreadCount, finalizeCallback);
|
|
3891
|
+
}
|
|
3892
|
+
|
|
3893
|
+
// static
|
|
3894
|
+
template <typename ResourceString, typename Finalizer,
|
|
3895
|
+
typename FinalizerDataType>
|
|
3896
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3897
|
+
const Function& callback,
|
|
3898
|
+
ResourceString resourceName,
|
|
3899
|
+
size_t maxQueueSize,
|
|
3900
|
+
size_t initialThreadCount,
|
|
3901
|
+
Finalizer finalizeCallback,
|
|
3902
|
+
FinalizerDataType* data) {
|
|
3903
|
+
return New(env, callback, Object(), resourceName, maxQueueSize,
|
|
3904
|
+
initialThreadCount, finalizeCallback, data);
|
|
3905
|
+
}
|
|
3906
|
+
|
|
3907
|
+
// static
|
|
3908
|
+
template <typename ResourceString, typename ContextType, typename Finalizer>
|
|
3909
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3910
|
+
const Function& callback,
|
|
3911
|
+
ResourceString resourceName,
|
|
3912
|
+
size_t maxQueueSize,
|
|
3913
|
+
size_t initialThreadCount,
|
|
3914
|
+
ContextType* context,
|
|
3915
|
+
Finalizer finalizeCallback) {
|
|
3916
|
+
return New(env, callback, Object(), resourceName, maxQueueSize,
|
|
3917
|
+
initialThreadCount, context, finalizeCallback);
|
|
3918
|
+
}
|
|
3919
|
+
|
|
3920
|
+
// static
|
|
3921
|
+
template <typename ResourceString, typename ContextType,
|
|
3922
|
+
typename Finalizer, typename FinalizerDataType>
|
|
3923
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3924
|
+
const Function& callback,
|
|
3925
|
+
ResourceString resourceName,
|
|
3926
|
+
size_t maxQueueSize,
|
|
3927
|
+
size_t initialThreadCount,
|
|
3928
|
+
ContextType* context,
|
|
3929
|
+
Finalizer finalizeCallback,
|
|
3930
|
+
FinalizerDataType* data) {
|
|
3931
|
+
return New(env, callback, Object(), resourceName, maxQueueSize,
|
|
3932
|
+
initialThreadCount, context, finalizeCallback, data);
|
|
3933
|
+
}
|
|
3934
|
+
|
|
3935
|
+
// static
|
|
3936
|
+
template <typename ResourceString>
|
|
3937
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3938
|
+
const Function& callback,
|
|
3939
|
+
const Object& resource,
|
|
3940
|
+
ResourceString resourceName,
|
|
3941
|
+
size_t maxQueueSize,
|
|
3942
|
+
size_t initialThreadCount) {
|
|
3943
|
+
return New(env, callback, resource, resourceName, maxQueueSize,
|
|
3944
|
+
initialThreadCount, static_cast<void*>(nullptr) /* context */);
|
|
3945
|
+
}
|
|
3946
|
+
|
|
3947
|
+
// static
|
|
3948
|
+
template <typename ResourceString, typename ContextType>
|
|
3949
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3950
|
+
const Function& callback,
|
|
3951
|
+
const Object& resource,
|
|
3952
|
+
ResourceString resourceName,
|
|
3953
|
+
size_t maxQueueSize,
|
|
3954
|
+
size_t initialThreadCount,
|
|
3955
|
+
ContextType* context) {
|
|
3956
|
+
return New(env, callback, resource, resourceName, maxQueueSize,
|
|
3957
|
+
initialThreadCount, context,
|
|
3958
|
+
[](Env, ContextType*) {} /* empty finalizer */);
|
|
3959
|
+
}
|
|
3960
|
+
|
|
3961
|
+
// static
|
|
3962
|
+
template <typename ResourceString, typename Finalizer>
|
|
3963
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3964
|
+
const Function& callback,
|
|
3965
|
+
const Object& resource,
|
|
3966
|
+
ResourceString resourceName,
|
|
3967
|
+
size_t maxQueueSize,
|
|
3968
|
+
size_t initialThreadCount,
|
|
3969
|
+
Finalizer finalizeCallback) {
|
|
3970
|
+
return New(env, callback, resource, resourceName, maxQueueSize,
|
|
3971
|
+
initialThreadCount, static_cast<void*>(nullptr) /* context */,
|
|
3972
|
+
finalizeCallback, static_cast<void*>(nullptr) /* data */,
|
|
3973
|
+
details::ThreadSafeFinalize<void, Finalizer>::Wrapper);
|
|
3974
|
+
}
|
|
3975
|
+
|
|
3976
|
+
// static
|
|
3977
|
+
template <typename ResourceString, typename Finalizer,
|
|
3978
|
+
typename FinalizerDataType>
|
|
3979
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3980
|
+
const Function& callback,
|
|
3981
|
+
const Object& resource,
|
|
3982
|
+
ResourceString resourceName,
|
|
3983
|
+
size_t maxQueueSize,
|
|
3984
|
+
size_t initialThreadCount,
|
|
3985
|
+
Finalizer finalizeCallback,
|
|
3986
|
+
FinalizerDataType* data) {
|
|
3987
|
+
return New(env, callback, resource, resourceName, maxQueueSize,
|
|
3988
|
+
initialThreadCount, static_cast<void*>(nullptr) /* context */,
|
|
3989
|
+
finalizeCallback, data,
|
|
3990
|
+
details::ThreadSafeFinalize<
|
|
3991
|
+
void, Finalizer, FinalizerDataType>::FinalizeWrapperWithData);
|
|
3992
|
+
}
|
|
3993
|
+
|
|
3994
|
+
// static
|
|
3995
|
+
template <typename ResourceString, typename ContextType, typename Finalizer>
|
|
3996
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
3997
|
+
const Function& callback,
|
|
3998
|
+
const Object& resource,
|
|
3999
|
+
ResourceString resourceName,
|
|
4000
|
+
size_t maxQueueSize,
|
|
4001
|
+
size_t initialThreadCount,
|
|
4002
|
+
ContextType* context,
|
|
4003
|
+
Finalizer finalizeCallback) {
|
|
4004
|
+
return New(env, callback, resource, resourceName, maxQueueSize,
|
|
4005
|
+
initialThreadCount, context, finalizeCallback,
|
|
4006
|
+
static_cast<void*>(nullptr) /* data */,
|
|
4007
|
+
details::ThreadSafeFinalize<
|
|
4008
|
+
ContextType, Finalizer>::FinalizeWrapperWithContext);
|
|
4009
|
+
}
|
|
4010
|
+
|
|
4011
|
+
// static
|
|
4012
|
+
template <typename ResourceString, typename ContextType,
|
|
4013
|
+
typename Finalizer, typename FinalizerDataType>
|
|
4014
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
4015
|
+
const Function& callback,
|
|
4016
|
+
const Object& resource,
|
|
4017
|
+
ResourceString resourceName,
|
|
4018
|
+
size_t maxQueueSize,
|
|
4019
|
+
size_t initialThreadCount,
|
|
4020
|
+
ContextType* context,
|
|
4021
|
+
Finalizer finalizeCallback,
|
|
4022
|
+
FinalizerDataType* data) {
|
|
4023
|
+
return New(env, callback, resource, resourceName, maxQueueSize,
|
|
4024
|
+
initialThreadCount, context, finalizeCallback, data,
|
|
4025
|
+
details::ThreadSafeFinalize<ContextType, Finalizer,
|
|
4026
|
+
FinalizerDataType>::FinalizeFinalizeWrapperWithDataAndContext);
|
|
4027
|
+
}
|
|
4028
|
+
|
|
4029
|
+
inline ThreadSafeFunction::ThreadSafeFunction()
|
|
4030
|
+
: _tsfn() {
|
|
4031
|
+
}
|
|
4032
|
+
|
|
4033
|
+
inline ThreadSafeFunction::ThreadSafeFunction(
|
|
4034
|
+
napi_threadsafe_function tsfn)
|
|
4035
|
+
: _tsfn(tsfn) {
|
|
4036
|
+
}
|
|
4037
|
+
|
|
4038
|
+
inline ThreadSafeFunction::operator napi_threadsafe_function() const {
|
|
4039
|
+
return _tsfn;
|
|
4040
|
+
}
|
|
4041
|
+
|
|
4042
|
+
inline napi_status ThreadSafeFunction::BlockingCall() const {
|
|
4043
|
+
return CallInternal(nullptr, napi_tsfn_blocking);
|
|
4044
|
+
}
|
|
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
|
+
|
|
4052
|
+
template <typename Callback>
|
|
4053
|
+
inline napi_status ThreadSafeFunction::BlockingCall(
|
|
4054
|
+
Callback callback) const {
|
|
4055
|
+
return CallInternal(new CallbackWrapper(callback), napi_tsfn_blocking);
|
|
4056
|
+
}
|
|
4057
|
+
|
|
4058
|
+
template <typename DataType, typename Callback>
|
|
4059
|
+
inline napi_status ThreadSafeFunction::BlockingCall(
|
|
4060
|
+
DataType* data, Callback callback) const {
|
|
4061
|
+
auto wrapper = [data, callback](Env env, Function jsCallback) {
|
|
4062
|
+
callback(env, jsCallback, data);
|
|
4063
|
+
};
|
|
4064
|
+
return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_blocking);
|
|
4065
|
+
}
|
|
4066
|
+
|
|
4067
|
+
inline napi_status ThreadSafeFunction::NonBlockingCall() const {
|
|
4068
|
+
return CallInternal(nullptr, napi_tsfn_nonblocking);
|
|
4069
|
+
}
|
|
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
|
+
|
|
4077
|
+
template <typename Callback>
|
|
4078
|
+
inline napi_status ThreadSafeFunction::NonBlockingCall(
|
|
4079
|
+
Callback callback) const {
|
|
4080
|
+
return CallInternal(new CallbackWrapper(callback), napi_tsfn_nonblocking);
|
|
4081
|
+
}
|
|
4082
|
+
|
|
4083
|
+
template <typename DataType, typename Callback>
|
|
4084
|
+
inline napi_status ThreadSafeFunction::NonBlockingCall(
|
|
4085
|
+
DataType* data, Callback callback) const {
|
|
4086
|
+
auto wrapper = [data, callback](Env env, Function jsCallback) {
|
|
4087
|
+
callback(env, jsCallback, data);
|
|
4088
|
+
};
|
|
4089
|
+
return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_nonblocking);
|
|
4090
|
+
}
|
|
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
|
+
|
|
4106
|
+
inline napi_status ThreadSafeFunction::Acquire() const {
|
|
4107
|
+
return napi_acquire_threadsafe_function(_tsfn);
|
|
4108
|
+
}
|
|
4109
|
+
|
|
4110
|
+
inline napi_status ThreadSafeFunction::Release() {
|
|
4111
|
+
return napi_release_threadsafe_function(_tsfn, napi_tsfn_release);
|
|
4112
|
+
}
|
|
4113
|
+
|
|
4114
|
+
inline napi_status ThreadSafeFunction::Abort() {
|
|
4115
|
+
return napi_release_threadsafe_function(_tsfn, napi_tsfn_abort);
|
|
4116
|
+
}
|
|
4117
|
+
|
|
4118
|
+
inline ThreadSafeFunction::ConvertibleContext
|
|
4119
|
+
ThreadSafeFunction::GetContext() const {
|
|
4120
|
+
void* 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");
|
|
4123
|
+
return ConvertibleContext({ context });
|
|
4124
|
+
}
|
|
4125
|
+
|
|
4126
|
+
// static
|
|
4127
|
+
template <typename ResourceString, typename ContextType,
|
|
4128
|
+
typename Finalizer, typename FinalizerDataType>
|
|
4129
|
+
inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
4130
|
+
const Function& callback,
|
|
4131
|
+
const Object& resource,
|
|
4132
|
+
ResourceString resourceName,
|
|
4133
|
+
size_t maxQueueSize,
|
|
4134
|
+
size_t initialThreadCount,
|
|
4135
|
+
ContextType* context,
|
|
4136
|
+
Finalizer finalizeCallback,
|
|
4137
|
+
FinalizerDataType* data,
|
|
4138
|
+
napi_finalize wrapper) {
|
|
4139
|
+
static_assert(details::can_make_string<ResourceString>::value
|
|
4140
|
+
|| std::is_convertible<ResourceString, napi_value>::value,
|
|
4141
|
+
"Resource name should be convertible to the string type");
|
|
4142
|
+
|
|
4143
|
+
ThreadSafeFunction tsfn;
|
|
4144
|
+
auto* finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
|
|
4145
|
+
FinalizerDataType>({ data, finalizeCallback, &tsfn._tsfn });
|
|
4146
|
+
napi_status status = napi_create_threadsafe_function(env, callback, resource,
|
|
4147
|
+
Value::From(env, resourceName), maxQueueSize, initialThreadCount,
|
|
4148
|
+
finalizeData, wrapper, context, CallJS, &tsfn._tsfn);
|
|
4149
|
+
if (status != napi_ok) {
|
|
4150
|
+
delete finalizeData;
|
|
4151
|
+
NAPI_THROW_IF_FAILED(env, status, ThreadSafeFunction());
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4154
|
+
return tsfn;
|
|
4155
|
+
}
|
|
4156
|
+
|
|
4157
|
+
inline napi_status ThreadSafeFunction::CallInternal(
|
|
4158
|
+
CallbackWrapper* callbackWrapper,
|
|
4159
|
+
napi_threadsafe_function_call_mode mode) const {
|
|
4160
|
+
napi_status status = napi_call_threadsafe_function(
|
|
4161
|
+
_tsfn, callbackWrapper, mode);
|
|
4162
|
+
if (status != napi_ok && callbackWrapper != nullptr) {
|
|
4163
|
+
delete callbackWrapper;
|
|
4164
|
+
}
|
|
4165
|
+
|
|
4166
|
+
return status;
|
|
4167
|
+
}
|
|
4168
|
+
|
|
4169
|
+
// static
|
|
4170
|
+
inline void ThreadSafeFunction::CallJS(napi_env env,
|
|
4171
|
+
napi_value jsCallback,
|
|
4172
|
+
void* /* context */,
|
|
4173
|
+
void* data) {
|
|
4174
|
+
if (env == nullptr && jsCallback == nullptr) {
|
|
4175
|
+
return;
|
|
4176
|
+
}
|
|
4177
|
+
|
|
4178
|
+
if (data != nullptr) {
|
|
4179
|
+
auto* callbackWrapper = static_cast<CallbackWrapper*>(data);
|
|
4180
|
+
(*callbackWrapper)(env, Function(env, jsCallback));
|
|
4181
|
+
delete callbackWrapper;
|
|
4182
|
+
} else if (jsCallback != nullptr) {
|
|
4183
|
+
Function(env, jsCallback).Call({});
|
|
4184
|
+
}
|
|
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
|
+
|
|
4334
|
+
#endif
|
|
4335
|
+
|
|
3630
4336
|
////////////////////////////////////////////////////////////////////////////////
|
|
3631
4337
|
// Memory Management class
|
|
3632
4338
|
////////////////////////////////////////////////////////////////////////////////
|