node-addon-api 1.7.2 → 3.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 +3 -9
- package/CHANGELOG.md +154 -9
- package/README.md +58 -9
- package/benchmark/README.md +47 -0
- package/benchmark/binding.gyp +25 -0
- package/benchmark/function_args.cc +153 -0
- package/benchmark/function_args.js +52 -0
- package/benchmark/index.js +34 -0
- package/benchmark/property_descriptor.cc +60 -0
- package/benchmark/property_descriptor.js +29 -0
- package/common.gypi +21 -0
- package/doc/array_buffer.md +1 -1
- package/doc/async_context.md +10 -0
- package/doc/async_operations.md +1 -1
- package/doc/async_worker.md +56 -26
- package/doc/async_worker_variants.md +456 -0
- package/doc/basic_types.md +8 -0
- package/doc/bigint.md +2 -1
- package/doc/class_property_descriptor.md +5 -6
- package/doc/cmake-js.md +58 -9
- package/doc/creating_a_release.md +5 -5
- package/doc/date.md +68 -0
- package/doc/env.md +14 -0
- package/doc/function.md +108 -1
- package/doc/object.md +74 -1
- package/doc/object_lifetime_management.md +1 -1
- package/doc/object_wrap.md +291 -4
- package/doc/prebuild_tools.md +1 -1
- package/doc/property_descriptor.md +64 -9
- package/doc/setup.md +0 -1
- package/doc/string.md +1 -1
- package/doc/symbol.md +1 -1
- package/doc/threadsafe_function.md +18 -1
- package/doc/value.md +10 -1
- package/except.gypi +16 -0
- package/index.js +5 -42
- package/napi-inl.h +1048 -147
- package/napi.h +424 -49
- package/node_api.gyp +9 -0
- package/noexcept.gypi +16 -0
- package/{src/nothing.c → nothing.c} +0 -0
- package/package.json +244 -47
- package/tools/README.md +4 -4
- package/tools/conversion.js +0 -4
- package/external-napi/node_api.h +0 -7
- package/src/node_api.cc +0 -3655
- package/src/node_api.gyp +0 -21
- package/src/node_api.h +0 -588
- package/src/node_api_types.h +0 -115
- package/src/node_internals.cc +0 -142
- package/src/node_internals.h +0 -157
- package/src/util-inl.h +0 -38
- package/src/util.h +0 -7
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
|
|
|
@@ -138,9 +150,6 @@ struct ThreadSafeFinalize {
|
|
|
138
150
|
ThreadSafeFinalize* finalizeData =
|
|
139
151
|
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
140
152
|
finalizeData->callback(Env(env));
|
|
141
|
-
if (finalizeData->tsfn) {
|
|
142
|
-
*finalizeData->tsfn = nullptr;
|
|
143
|
-
}
|
|
144
153
|
delete finalizeData;
|
|
145
154
|
}
|
|
146
155
|
|
|
@@ -154,9 +163,6 @@ struct ThreadSafeFinalize {
|
|
|
154
163
|
ThreadSafeFinalize* finalizeData =
|
|
155
164
|
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
156
165
|
finalizeData->callback(Env(env), finalizeData->data);
|
|
157
|
-
if (finalizeData->tsfn) {
|
|
158
|
-
*finalizeData->tsfn = nullptr;
|
|
159
|
-
}
|
|
160
166
|
delete finalizeData;
|
|
161
167
|
}
|
|
162
168
|
|
|
@@ -170,9 +176,6 @@ struct ThreadSafeFinalize {
|
|
|
170
176
|
ThreadSafeFinalize* finalizeData =
|
|
171
177
|
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
172
178
|
finalizeData->callback(Env(env), static_cast<ContextType*>(rawContext));
|
|
173
|
-
if (finalizeData->tsfn) {
|
|
174
|
-
*finalizeData->tsfn = nullptr;
|
|
175
|
-
}
|
|
176
179
|
delete finalizeData;
|
|
177
180
|
}
|
|
178
181
|
|
|
@@ -187,15 +190,11 @@ struct ThreadSafeFinalize {
|
|
|
187
190
|
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
188
191
|
finalizeData->callback(Env(env), finalizeData->data,
|
|
189
192
|
static_cast<ContextType*>(rawContext));
|
|
190
|
-
if (finalizeData->tsfn) {
|
|
191
|
-
*finalizeData->tsfn = nullptr;
|
|
192
|
-
}
|
|
193
193
|
delete finalizeData;
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
FinalizerDataType* data;
|
|
197
197
|
Finalizer callback;
|
|
198
|
-
napi_threadsafe_function* tsfn;
|
|
199
198
|
};
|
|
200
199
|
#endif
|
|
201
200
|
|
|
@@ -307,6 +306,64 @@ inline Error Env::GetAndClearPendingException() {
|
|
|
307
306
|
return Error(_env, value);
|
|
308
307
|
}
|
|
309
308
|
|
|
309
|
+
inline Value Env::RunScript(const char* utf8script) {
|
|
310
|
+
String script = String::New(_env, utf8script);
|
|
311
|
+
return RunScript(script);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
inline Value Env::RunScript(const std::string& utf8script) {
|
|
315
|
+
return RunScript(utf8script.c_str());
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
inline Value Env::RunScript(String script) {
|
|
319
|
+
napi_value result;
|
|
320
|
+
napi_status status = napi_run_script(_env, script, &result);
|
|
321
|
+
NAPI_THROW_IF_FAILED(_env, status, Undefined());
|
|
322
|
+
return Value(_env, result);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
#if NAPI_VERSION > 5
|
|
326
|
+
template <typename T, Env::Finalizer<T> fini>
|
|
327
|
+
inline void Env::SetInstanceData(T* data) {
|
|
328
|
+
napi_status status =
|
|
329
|
+
napi_set_instance_data(_env, data, [](napi_env env, void* data, void*) {
|
|
330
|
+
fini(env, static_cast<T*>(data));
|
|
331
|
+
}, nullptr);
|
|
332
|
+
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
template <typename DataType,
|
|
336
|
+
typename HintType,
|
|
337
|
+
Napi::Env::FinalizerWithHint<DataType, HintType> fini>
|
|
338
|
+
inline void Env::SetInstanceData(DataType* data, HintType* hint) {
|
|
339
|
+
napi_status status =
|
|
340
|
+
napi_set_instance_data(_env, data,
|
|
341
|
+
[](napi_env env, void* data, void* hint) {
|
|
342
|
+
fini(env, static_cast<DataType*>(data), static_cast<HintType*>(hint));
|
|
343
|
+
}, hint);
|
|
344
|
+
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
template <typename T>
|
|
348
|
+
inline T* Env::GetInstanceData() {
|
|
349
|
+
void* data = nullptr;
|
|
350
|
+
|
|
351
|
+
napi_status status = napi_get_instance_data(_env, &data);
|
|
352
|
+
NAPI_THROW_IF_FAILED(_env, status, nullptr);
|
|
353
|
+
|
|
354
|
+
return static_cast<T*>(data);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
template <typename T> void Env::DefaultFini(Env, T* data) {
|
|
358
|
+
delete data;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
template <typename DataType, typename HintType>
|
|
362
|
+
void Env::DefaultFiniWithHint(Env, DataType* data, HintType*) {
|
|
363
|
+
delete data;
|
|
364
|
+
}
|
|
365
|
+
#endif // NAPI_VERSION > 5
|
|
366
|
+
|
|
310
367
|
////////////////////////////////////////////////////////////////////////////////
|
|
311
368
|
// Value class
|
|
312
369
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -371,13 +428,24 @@ inline bool Value::IsNumber() const {
|
|
|
371
428
|
return Type() == napi_number;
|
|
372
429
|
}
|
|
373
430
|
|
|
374
|
-
|
|
375
|
-
// released in once it is no longer experimental
|
|
376
|
-
#if (NAPI_VERSION > 2147483646)
|
|
431
|
+
#if NAPI_VERSION > 5
|
|
377
432
|
inline bool Value::IsBigInt() const {
|
|
378
433
|
return Type() == napi_bigint;
|
|
379
434
|
}
|
|
380
|
-
#endif //
|
|
435
|
+
#endif // NAPI_VERSION > 5
|
|
436
|
+
|
|
437
|
+
#if (NAPI_VERSION > 4)
|
|
438
|
+
inline bool Value::IsDate() const {
|
|
439
|
+
if (IsEmpty()) {
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
bool result;
|
|
444
|
+
napi_status status = napi_is_date(_env, _value, &result);
|
|
445
|
+
NAPI_THROW_IF_FAILED(_env, status, false);
|
|
446
|
+
return result;
|
|
447
|
+
}
|
|
448
|
+
#endif
|
|
381
449
|
|
|
382
450
|
inline bool Value::IsString() const {
|
|
383
451
|
return Type() == napi_string;
|
|
@@ -595,9 +663,7 @@ inline double Number::DoubleValue() const {
|
|
|
595
663
|
return result;
|
|
596
664
|
}
|
|
597
665
|
|
|
598
|
-
|
|
599
|
-
// released in once it is no longer experimental
|
|
600
|
-
#if (NAPI_VERSION > 2147483646)
|
|
666
|
+
#if NAPI_VERSION > 5
|
|
601
667
|
////////////////////////////////////////////////////////////////////////////////
|
|
602
668
|
// BigInt Class
|
|
603
669
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -658,7 +724,38 @@ inline void BigInt::ToWords(int* sign_bit, size_t* word_count, uint64_t* words)
|
|
|
658
724
|
_env, _value, sign_bit, word_count, words);
|
|
659
725
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
660
726
|
}
|
|
661
|
-
#endif //
|
|
727
|
+
#endif // NAPI_VERSION > 5
|
|
728
|
+
|
|
729
|
+
#if (NAPI_VERSION > 4)
|
|
730
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
731
|
+
// Date Class
|
|
732
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
733
|
+
|
|
734
|
+
inline Date Date::New(napi_env env, double val) {
|
|
735
|
+
napi_value value;
|
|
736
|
+
napi_status status = napi_create_date(env, val, &value);
|
|
737
|
+
NAPI_THROW_IF_FAILED(env, status, Date());
|
|
738
|
+
return Date(env, value);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
inline Date::Date() : Value() {
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
inline Date::Date(napi_env env, napi_value value) : Value(env, value) {
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
inline Date::operator double() const {
|
|
748
|
+
return ValueOf();
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
inline double Date::ValueOf() const {
|
|
752
|
+
double result;
|
|
753
|
+
napi_status status = napi_get_date_value(
|
|
754
|
+
_env, _value, &result);
|
|
755
|
+
NAPI_THROW_IF_FAILED(_env, status, 0);
|
|
756
|
+
return result;
|
|
757
|
+
}
|
|
758
|
+
#endif
|
|
662
759
|
|
|
663
760
|
////////////////////////////////////////////////////////////////////////////////
|
|
664
761
|
// Name class
|
|
@@ -1126,6 +1223,40 @@ inline bool Object::InstanceOf(const Function& constructor) const {
|
|
|
1126
1223
|
return result;
|
|
1127
1224
|
}
|
|
1128
1225
|
|
|
1226
|
+
template <typename Finalizer, typename T>
|
|
1227
|
+
inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) {
|
|
1228
|
+
details::FinalizeData<T, Finalizer>* finalizeData =
|
|
1229
|
+
new details::FinalizeData<T, Finalizer>({ finalizeCallback, nullptr });
|
|
1230
|
+
napi_status status =
|
|
1231
|
+
details::AttachData(_env,
|
|
1232
|
+
*this,
|
|
1233
|
+
data,
|
|
1234
|
+
details::FinalizeData<T, Finalizer>::Wrapper,
|
|
1235
|
+
finalizeData);
|
|
1236
|
+
if (status != napi_ok) {
|
|
1237
|
+
delete finalizeData;
|
|
1238
|
+
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
template <typename Finalizer, typename T, typename Hint>
|
|
1243
|
+
inline void Object::AddFinalizer(Finalizer finalizeCallback,
|
|
1244
|
+
T* data,
|
|
1245
|
+
Hint* finalizeHint) {
|
|
1246
|
+
details::FinalizeData<T, Finalizer, Hint>* finalizeData =
|
|
1247
|
+
new details::FinalizeData<T, Finalizer, Hint>({ finalizeCallback, finalizeHint });
|
|
1248
|
+
napi_status status =
|
|
1249
|
+
details::AttachData(_env,
|
|
1250
|
+
*this,
|
|
1251
|
+
data,
|
|
1252
|
+
details::FinalizeData<T, Finalizer, Hint>::WrapperWithHint,
|
|
1253
|
+
finalizeData);
|
|
1254
|
+
if (status != napi_ok) {
|
|
1255
|
+
delete finalizeData;
|
|
1256
|
+
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1129
1260
|
////////////////////////////////////////////////////////////////////////////////
|
|
1130
1261
|
// External class
|
|
1131
1262
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -1238,7 +1369,7 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env, size_t byteLength) {
|
|
|
1238
1369
|
napi_status status = napi_create_arraybuffer(env, byteLength, &data, &value);
|
|
1239
1370
|
NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
|
|
1240
1371
|
|
|
1241
|
-
return ArrayBuffer(env, value
|
|
1372
|
+
return ArrayBuffer(env, value);
|
|
1242
1373
|
}
|
|
1243
1374
|
|
|
1244
1375
|
inline ArrayBuffer ArrayBuffer::New(napi_env env,
|
|
@@ -1249,7 +1380,7 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
|
|
|
1249
1380
|
env, externalData, byteLength, nullptr, nullptr, &value);
|
|
1250
1381
|
NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
|
|
1251
1382
|
|
|
1252
|
-
return ArrayBuffer(env, value
|
|
1383
|
+
return ArrayBuffer(env, value);
|
|
1253
1384
|
}
|
|
1254
1385
|
|
|
1255
1386
|
template <typename Finalizer>
|
|
@@ -1272,7 +1403,7 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
|
|
|
1272
1403
|
NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
|
|
1273
1404
|
}
|
|
1274
1405
|
|
|
1275
|
-
return ArrayBuffer(env, value
|
|
1406
|
+
return ArrayBuffer(env, value);
|
|
1276
1407
|
}
|
|
1277
1408
|
|
|
1278
1409
|
template <typename Finalizer, typename Hint>
|
|
@@ -1296,38 +1427,28 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
|
|
|
1296
1427
|
NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
|
|
1297
1428
|
}
|
|
1298
1429
|
|
|
1299
|
-
return ArrayBuffer(env, value
|
|
1430
|
+
return ArrayBuffer(env, value);
|
|
1300
1431
|
}
|
|
1301
1432
|
|
|
1302
|
-
inline ArrayBuffer::ArrayBuffer() : Object()
|
|
1433
|
+
inline ArrayBuffer::ArrayBuffer() : Object() {
|
|
1303
1434
|
}
|
|
1304
1435
|
|
|
1305
1436
|
inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value)
|
|
1306
|
-
: Object(env, value)
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
|
-
inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value, void* data, size_t length)
|
|
1310
|
-
: Object(env, value), _data(data), _length(length) {
|
|
1437
|
+
: Object(env, value) {
|
|
1311
1438
|
}
|
|
1312
1439
|
|
|
1313
1440
|
inline void* ArrayBuffer::Data() {
|
|
1314
|
-
|
|
1315
|
-
|
|
1441
|
+
void* data;
|
|
1442
|
+
napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr);
|
|
1443
|
+
NAPI_THROW_IF_FAILED(_env, status, nullptr);
|
|
1444
|
+
return data;
|
|
1316
1445
|
}
|
|
1317
1446
|
|
|
1318
1447
|
inline size_t ArrayBuffer::ByteLength() {
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
inline void ArrayBuffer::EnsureInfo() const {
|
|
1324
|
-
// The ArrayBuffer instance may have been constructed from a napi_value whose
|
|
1325
|
-
// length/data are not yet known. Fetch and cache these values just once,
|
|
1326
|
-
// since they can never change during the lifetime of the ArrayBuffer.
|
|
1327
|
-
if (_data == nullptr) {
|
|
1328
|
-
napi_status status = napi_get_arraybuffer_info(_env, _value, &_data, &_length);
|
|
1329
|
-
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
1330
|
-
}
|
|
1448
|
+
size_t length;
|
|
1449
|
+
napi_status status = napi_get_arraybuffer_info(_env, _value, nullptr, &length);
|
|
1450
|
+
NAPI_THROW_IF_FAILED(_env, status, 0);
|
|
1451
|
+
return length;
|
|
1331
1452
|
}
|
|
1332
1453
|
|
|
1333
1454
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -1543,6 +1664,10 @@ inline uint8_t TypedArray::ElementSize() const {
|
|
|
1543
1664
|
case napi_float32_array:
|
|
1544
1665
|
return 4;
|
|
1545
1666
|
case napi_float64_array:
|
|
1667
|
+
#if (NAPI_VERSION > 5)
|
|
1668
|
+
case napi_bigint64_array:
|
|
1669
|
+
case napi_biguint64_array:
|
|
1670
|
+
#endif // (NAPI_VERSION > 5)
|
|
1546
1671
|
return 8;
|
|
1547
1672
|
default:
|
|
1548
1673
|
return 0;
|
|
@@ -1674,6 +1799,51 @@ CreateFunction(napi_env env,
|
|
|
1674
1799
|
return status;
|
|
1675
1800
|
}
|
|
1676
1801
|
|
|
1802
|
+
template <Function::VoidCallback cb>
|
|
1803
|
+
inline Function Function::New(napi_env env, const char* utf8name, void* data) {
|
|
1804
|
+
napi_value result = nullptr;
|
|
1805
|
+
napi_status status = napi_create_function(
|
|
1806
|
+
env, utf8name, NAPI_AUTO_LENGTH,
|
|
1807
|
+
[](napi_env env, napi_callback_info info) {
|
|
1808
|
+
CallbackInfo callbackInfo(env, info);
|
|
1809
|
+
return details::WrapCallback([&] {
|
|
1810
|
+
cb(callbackInfo);
|
|
1811
|
+
return nullptr;
|
|
1812
|
+
});
|
|
1813
|
+
}, data, &result);
|
|
1814
|
+
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
1815
|
+
return Function(env, result);
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
template <Function::Callback cb>
|
|
1819
|
+
inline Function Function::New(napi_env env, const char* utf8name, void* data) {
|
|
1820
|
+
napi_value result = nullptr;
|
|
1821
|
+
napi_status status = napi_create_function(
|
|
1822
|
+
env, utf8name, NAPI_AUTO_LENGTH,
|
|
1823
|
+
[](napi_env env, napi_callback_info info) {
|
|
1824
|
+
CallbackInfo callbackInfo(env, info);
|
|
1825
|
+
return details::WrapCallback([&] {
|
|
1826
|
+
return cb(callbackInfo);
|
|
1827
|
+
});
|
|
1828
|
+
}, data, &result);
|
|
1829
|
+
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
1830
|
+
return Function(env, result);
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
template <Function::VoidCallback cb>
|
|
1834
|
+
inline Function Function::New(napi_env env,
|
|
1835
|
+
const std::string& utf8name,
|
|
1836
|
+
void* data) {
|
|
1837
|
+
return Function::New<cb>(env, utf8name.c_str(), data);
|
|
1838
|
+
}
|
|
1839
|
+
|
|
1840
|
+
template <Function::Callback cb>
|
|
1841
|
+
inline Function Function::New(napi_env env,
|
|
1842
|
+
const std::string& utf8name,
|
|
1843
|
+
void* data) {
|
|
1844
|
+
return Function::New<cb>(env, utf8name.c_str(), data);
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1677
1847
|
template <typename Callable>
|
|
1678
1848
|
inline Function Function::New(napi_env env,
|
|
1679
1849
|
Callable cb,
|
|
@@ -1945,52 +2115,46 @@ inline void Buffer<T>::EnsureInfo() const {
|
|
|
1945
2115
|
inline Error Error::New(napi_env env) {
|
|
1946
2116
|
napi_status status;
|
|
1947
2117
|
napi_value error = nullptr;
|
|
1948
|
-
|
|
2118
|
+
bool is_exception_pending;
|
|
1949
2119
|
const napi_extended_error_info* info;
|
|
2120
|
+
|
|
2121
|
+
// We must retrieve the last error info before doing anything else, because
|
|
2122
|
+
// doing anything else will replace the last error info.
|
|
1950
2123
|
status = napi_get_last_error_info(env, &info);
|
|
1951
2124
|
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info");
|
|
1952
2125
|
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
status = napi_get_and_clear_last_exception(env, &error);
|
|
1956
|
-
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
|
|
1957
|
-
}
|
|
1958
|
-
else {
|
|
1959
|
-
const char* error_message = info->error_message != nullptr ?
|
|
1960
|
-
info->error_message : "Error in native callback";
|
|
1961
|
-
|
|
1962
|
-
bool isExceptionPending;
|
|
1963
|
-
status = napi_is_exception_pending(env, &isExceptionPending);
|
|
1964
|
-
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
|
|
1965
|
-
|
|
1966
|
-
if (isExceptionPending) {
|
|
1967
|
-
status = napi_get_and_clear_last_exception(env, &error);
|
|
1968
|
-
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
|
|
1969
|
-
}
|
|
2126
|
+
status = napi_is_exception_pending(env, &is_exception_pending);
|
|
2127
|
+
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
|
|
1970
2128
|
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
2129
|
+
// A pending exception takes precedence over any internal error status.
|
|
2130
|
+
if (is_exception_pending) {
|
|
2131
|
+
status = napi_get_and_clear_last_exception(env, &error);
|
|
2132
|
+
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
|
|
2133
|
+
}
|
|
2134
|
+
else {
|
|
2135
|
+
const char* error_message = info->error_message != nullptr ?
|
|
2136
|
+
info->error_message : "Error in native callback";
|
|
2137
|
+
|
|
2138
|
+
napi_value message;
|
|
2139
|
+
status = napi_create_string_utf8(
|
|
2140
|
+
env,
|
|
2141
|
+
error_message,
|
|
2142
|
+
std::strlen(error_message),
|
|
2143
|
+
&message);
|
|
2144
|
+
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_string_utf8");
|
|
2145
|
+
|
|
2146
|
+
switch (info->error_code) {
|
|
2147
|
+
case napi_object_expected:
|
|
2148
|
+
case napi_string_expected:
|
|
2149
|
+
case napi_boolean_expected:
|
|
2150
|
+
case napi_number_expected:
|
|
2151
|
+
status = napi_create_type_error(env, nullptr, message, &error);
|
|
2152
|
+
break;
|
|
2153
|
+
default:
|
|
2154
|
+
status = napi_create_error(env, nullptr, message, &error);
|
|
2155
|
+
break;
|
|
1993
2156
|
}
|
|
2157
|
+
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error");
|
|
1994
2158
|
}
|
|
1995
2159
|
|
|
1996
2160
|
return Error(env, error);
|
|
@@ -2032,7 +2196,7 @@ inline Error& Error::operator =(Error&& other) {
|
|
|
2032
2196
|
inline Error::Error(const Error& other) : ObjectReference(other) {
|
|
2033
2197
|
}
|
|
2034
2198
|
|
|
2035
|
-
inline Error& Error::operator =(Error& other) {
|
|
2199
|
+
inline Error& Error::operator =(const Error& other) {
|
|
2036
2200
|
Reset();
|
|
2037
2201
|
|
|
2038
2202
|
_env = other.Env();
|
|
@@ -2644,6 +2808,108 @@ inline void CallbackInfo::SetData(void* data) {
|
|
|
2644
2808
|
// PropertyDescriptor class
|
|
2645
2809
|
////////////////////////////////////////////////////////////////////////////////
|
|
2646
2810
|
|
|
2811
|
+
template <typename PropertyDescriptor::GetterCallback Getter>
|
|
2812
|
+
PropertyDescriptor
|
|
2813
|
+
PropertyDescriptor::Accessor(const char* utf8name,
|
|
2814
|
+
napi_property_attributes attributes,
|
|
2815
|
+
void* data) {
|
|
2816
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
2817
|
+
|
|
2818
|
+
desc.utf8name = utf8name;
|
|
2819
|
+
desc.getter = &GetterCallbackWrapper<Getter>;
|
|
2820
|
+
desc.attributes = attributes;
|
|
2821
|
+
desc.data = data;
|
|
2822
|
+
|
|
2823
|
+
return desc;
|
|
2824
|
+
}
|
|
2825
|
+
|
|
2826
|
+
template <typename PropertyDescriptor::GetterCallback Getter>
|
|
2827
|
+
PropertyDescriptor
|
|
2828
|
+
PropertyDescriptor::Accessor(const std::string& utf8name,
|
|
2829
|
+
napi_property_attributes attributes,
|
|
2830
|
+
void* data) {
|
|
2831
|
+
return Accessor<Getter>(utf8name.c_str(), attributes, data);
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
template <typename PropertyDescriptor::GetterCallback Getter>
|
|
2835
|
+
PropertyDescriptor
|
|
2836
|
+
PropertyDescriptor::Accessor(Name name,
|
|
2837
|
+
napi_property_attributes attributes,
|
|
2838
|
+
void* data) {
|
|
2839
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
2840
|
+
|
|
2841
|
+
desc.name = name;
|
|
2842
|
+
desc.getter = &GetterCallbackWrapper<Getter>;
|
|
2843
|
+
desc.attributes = attributes;
|
|
2844
|
+
desc.data = data;
|
|
2845
|
+
|
|
2846
|
+
return desc;
|
|
2847
|
+
}
|
|
2848
|
+
|
|
2849
|
+
template <
|
|
2850
|
+
typename PropertyDescriptor::GetterCallback Getter,
|
|
2851
|
+
typename PropertyDescriptor::SetterCallback Setter>
|
|
2852
|
+
PropertyDescriptor
|
|
2853
|
+
PropertyDescriptor::Accessor(const char* utf8name,
|
|
2854
|
+
napi_property_attributes attributes,
|
|
2855
|
+
void* data) {
|
|
2856
|
+
|
|
2857
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
2858
|
+
|
|
2859
|
+
desc.utf8name = utf8name;
|
|
2860
|
+
desc.getter = &GetterCallbackWrapper<Getter>;
|
|
2861
|
+
desc.setter = &SetterCallbackWrapper<Setter>;
|
|
2862
|
+
desc.attributes = attributes;
|
|
2863
|
+
desc.data = data;
|
|
2864
|
+
|
|
2865
|
+
return desc;
|
|
2866
|
+
}
|
|
2867
|
+
|
|
2868
|
+
template <
|
|
2869
|
+
typename PropertyDescriptor::GetterCallback Getter,
|
|
2870
|
+
typename PropertyDescriptor::SetterCallback Setter>
|
|
2871
|
+
PropertyDescriptor
|
|
2872
|
+
PropertyDescriptor::Accessor(const std::string& utf8name,
|
|
2873
|
+
napi_property_attributes attributes,
|
|
2874
|
+
void* data) {
|
|
2875
|
+
return Accessor<Getter, Setter>(utf8name.c_str(), attributes, data);
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
template <
|
|
2879
|
+
typename PropertyDescriptor::GetterCallback Getter,
|
|
2880
|
+
typename PropertyDescriptor::SetterCallback Setter>
|
|
2881
|
+
PropertyDescriptor
|
|
2882
|
+
PropertyDescriptor::Accessor(Name name,
|
|
2883
|
+
napi_property_attributes attributes,
|
|
2884
|
+
void* data) {
|
|
2885
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
2886
|
+
|
|
2887
|
+
desc.name = name;
|
|
2888
|
+
desc.getter = &GetterCallbackWrapper<Getter>;
|
|
2889
|
+
desc.setter = &SetterCallbackWrapper<Setter>;
|
|
2890
|
+
desc.attributes = attributes;
|
|
2891
|
+
desc.data = data;
|
|
2892
|
+
|
|
2893
|
+
return desc;
|
|
2894
|
+
}
|
|
2895
|
+
|
|
2896
|
+
template <typename PropertyDescriptor::GetterCallback Getter>
|
|
2897
|
+
napi_value
|
|
2898
|
+
PropertyDescriptor::GetterCallbackWrapper(napi_env env,
|
|
2899
|
+
napi_callback_info info) {
|
|
2900
|
+
CallbackInfo cbInfo(env, info);
|
|
2901
|
+
return Getter(cbInfo);
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
template <typename PropertyDescriptor::SetterCallback Setter>
|
|
2905
|
+
napi_value
|
|
2906
|
+
PropertyDescriptor::SetterCallbackWrapper(napi_env env,
|
|
2907
|
+
napi_callback_info info) {
|
|
2908
|
+
CallbackInfo cbInfo(env, info);
|
|
2909
|
+
Setter(cbInfo);
|
|
2910
|
+
return nullptr;
|
|
2911
|
+
}
|
|
2912
|
+
|
|
2647
2913
|
template <typename Getter>
|
|
2648
2914
|
inline PropertyDescriptor
|
|
2649
2915
|
PropertyDescriptor::Accessor(Napi::Env env,
|
|
@@ -2880,14 +3146,27 @@ inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
|
|
|
2880
3146
|
napi_value wrapper = callbackInfo.This();
|
|
2881
3147
|
napi_status status;
|
|
2882
3148
|
napi_ref ref;
|
|
2883
|
-
|
|
2884
|
-
status = napi_wrap(env, wrapper, instance, FinalizeCallback, nullptr, &ref);
|
|
3149
|
+
status = napi_wrap(env, wrapper, this, FinalizeCallback, nullptr, &ref);
|
|
2885
3150
|
NAPI_THROW_IF_FAILED_VOID(env, status);
|
|
2886
3151
|
|
|
2887
|
-
Reference<Object>* instanceRef =
|
|
3152
|
+
Reference<Object>* instanceRef = this;
|
|
2888
3153
|
*instanceRef = Reference<Object>(env, ref);
|
|
2889
3154
|
}
|
|
2890
3155
|
|
|
3156
|
+
template <typename T>
|
|
3157
|
+
inline ObjectWrap<T>::~ObjectWrap() {
|
|
3158
|
+
// If the JS object still exists at this point, remove the finalizer added
|
|
3159
|
+
// through `napi_wrap()`.
|
|
3160
|
+
if (!IsEmpty()) {
|
|
3161
|
+
Object object = Value();
|
|
3162
|
+
// It is not valid to call `napi_remove_wrap()` with an empty `object`.
|
|
3163
|
+
// This happens e.g. during garbage collection.
|
|
3164
|
+
if (!object.IsEmpty() && _construction_failed) {
|
|
3165
|
+
napi_remove_wrap(Env(), object, nullptr);
|
|
3166
|
+
}
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3169
|
+
|
|
2891
3170
|
template<typename T>
|
|
2892
3171
|
inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
|
|
2893
3172
|
T* unwrapped;
|
|
@@ -3075,6 +3354,62 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
|
|
|
3075
3354
|
return desc;
|
|
3076
3355
|
}
|
|
3077
3356
|
|
|
3357
|
+
template <typename T>
|
|
3358
|
+
template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
|
|
3359
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
|
|
3360
|
+
const char* utf8name,
|
|
3361
|
+
napi_property_attributes attributes,
|
|
3362
|
+
void* data) {
|
|
3363
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3364
|
+
desc.utf8name = utf8name;
|
|
3365
|
+
desc.method = &ObjectWrap<T>::WrappedMethod<method>;
|
|
3366
|
+
desc.data = data;
|
|
3367
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3368
|
+
return desc;
|
|
3369
|
+
}
|
|
3370
|
+
|
|
3371
|
+
template <typename T>
|
|
3372
|
+
template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
|
|
3373
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
|
|
3374
|
+
Symbol name,
|
|
3375
|
+
napi_property_attributes attributes,
|
|
3376
|
+
void* data) {
|
|
3377
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3378
|
+
desc.name = name;
|
|
3379
|
+
desc.method = &ObjectWrap<T>::WrappedMethod<method>;
|
|
3380
|
+
desc.data = data;
|
|
3381
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3382
|
+
return desc;
|
|
3383
|
+
}
|
|
3384
|
+
|
|
3385
|
+
template <typename T>
|
|
3386
|
+
template <typename ObjectWrap<T>::StaticMethodCallback method>
|
|
3387
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
|
|
3388
|
+
const char* utf8name,
|
|
3389
|
+
napi_property_attributes attributes,
|
|
3390
|
+
void* data) {
|
|
3391
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3392
|
+
desc.utf8name = utf8name;
|
|
3393
|
+
desc.method = &ObjectWrap<T>::WrappedMethod<method>;
|
|
3394
|
+
desc.data = data;
|
|
3395
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3396
|
+
return desc;
|
|
3397
|
+
}
|
|
3398
|
+
|
|
3399
|
+
template <typename T>
|
|
3400
|
+
template <typename ObjectWrap<T>::StaticMethodCallback method>
|
|
3401
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
|
|
3402
|
+
Symbol name,
|
|
3403
|
+
napi_property_attributes attributes,
|
|
3404
|
+
void* data) {
|
|
3405
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3406
|
+
desc.name = name;
|
|
3407
|
+
desc.method = &ObjectWrap<T>::WrappedMethod<method>;
|
|
3408
|
+
desc.data = data;
|
|
3409
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3410
|
+
return desc;
|
|
3411
|
+
}
|
|
3412
|
+
|
|
3078
3413
|
template <typename T>
|
|
3079
3414
|
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
|
|
3080
3415
|
const char* utf8name,
|
|
@@ -3113,6 +3448,38 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
|
|
|
3113
3448
|
return desc;
|
|
3114
3449
|
}
|
|
3115
3450
|
|
|
3451
|
+
template <typename T>
|
|
3452
|
+
template <typename ObjectWrap<T>::StaticGetterCallback getter,
|
|
3453
|
+
typename ObjectWrap<T>::StaticSetterCallback setter>
|
|
3454
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
|
|
3455
|
+
const char* utf8name,
|
|
3456
|
+
napi_property_attributes attributes,
|
|
3457
|
+
void* data) {
|
|
3458
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3459
|
+
desc.utf8name = utf8name;
|
|
3460
|
+
desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
|
|
3461
|
+
desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
|
|
3462
|
+
desc.data = data;
|
|
3463
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3464
|
+
return desc;
|
|
3465
|
+
}
|
|
3466
|
+
|
|
3467
|
+
template <typename T>
|
|
3468
|
+
template <typename ObjectWrap<T>::StaticGetterCallback getter,
|
|
3469
|
+
typename ObjectWrap<T>::StaticSetterCallback setter>
|
|
3470
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
|
|
3471
|
+
Symbol name,
|
|
3472
|
+
napi_property_attributes attributes,
|
|
3473
|
+
void* data) {
|
|
3474
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3475
|
+
desc.name = name;
|
|
3476
|
+
desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
|
|
3477
|
+
desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
|
|
3478
|
+
desc.data = data;
|
|
3479
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3480
|
+
return desc;
|
|
3481
|
+
}
|
|
3482
|
+
|
|
3116
3483
|
template <typename T>
|
|
3117
3484
|
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
|
|
3118
3485
|
const char* utf8name,
|
|
@@ -3179,6 +3546,62 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
|
|
|
3179
3546
|
return desc;
|
|
3180
3547
|
}
|
|
3181
3548
|
|
|
3549
|
+
template <typename T>
|
|
3550
|
+
template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
|
|
3551
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
|
|
3552
|
+
const char* utf8name,
|
|
3553
|
+
napi_property_attributes attributes,
|
|
3554
|
+
void* data) {
|
|
3555
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3556
|
+
desc.utf8name = utf8name;
|
|
3557
|
+
desc.method = &ObjectWrap<T>::WrappedMethod<method>;
|
|
3558
|
+
desc.data = data;
|
|
3559
|
+
desc.attributes = attributes;
|
|
3560
|
+
return desc;
|
|
3561
|
+
}
|
|
3562
|
+
|
|
3563
|
+
template <typename T>
|
|
3564
|
+
template <typename ObjectWrap<T>::InstanceMethodCallback method>
|
|
3565
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
|
|
3566
|
+
const char* utf8name,
|
|
3567
|
+
napi_property_attributes attributes,
|
|
3568
|
+
void* data) {
|
|
3569
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3570
|
+
desc.utf8name = utf8name;
|
|
3571
|
+
desc.method = &ObjectWrap<T>::WrappedMethod<method>;
|
|
3572
|
+
desc.data = data;
|
|
3573
|
+
desc.attributes = attributes;
|
|
3574
|
+
return desc;
|
|
3575
|
+
}
|
|
3576
|
+
|
|
3577
|
+
template <typename T>
|
|
3578
|
+
template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
|
|
3579
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
|
|
3580
|
+
Symbol name,
|
|
3581
|
+
napi_property_attributes attributes,
|
|
3582
|
+
void* data) {
|
|
3583
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3584
|
+
desc.name = name;
|
|
3585
|
+
desc.method = &ObjectWrap<T>::WrappedMethod<method>;
|
|
3586
|
+
desc.data = data;
|
|
3587
|
+
desc.attributes = attributes;
|
|
3588
|
+
return desc;
|
|
3589
|
+
}
|
|
3590
|
+
|
|
3591
|
+
template <typename T>
|
|
3592
|
+
template <typename ObjectWrap<T>::InstanceMethodCallback method>
|
|
3593
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
|
|
3594
|
+
Symbol name,
|
|
3595
|
+
napi_property_attributes attributes,
|
|
3596
|
+
void* data) {
|
|
3597
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3598
|
+
desc.name = name;
|
|
3599
|
+
desc.method = &ObjectWrap<T>::WrappedMethod<method>;
|
|
3600
|
+
desc.data = data;
|
|
3601
|
+
desc.attributes = attributes;
|
|
3602
|
+
return desc;
|
|
3603
|
+
}
|
|
3604
|
+
|
|
3182
3605
|
template <typename T>
|
|
3183
3606
|
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
|
|
3184
3607
|
const char* utf8name,
|
|
@@ -3217,6 +3640,38 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
|
|
|
3217
3640
|
return desc;
|
|
3218
3641
|
}
|
|
3219
3642
|
|
|
3643
|
+
template <typename T>
|
|
3644
|
+
template <typename ObjectWrap<T>::InstanceGetterCallback getter,
|
|
3645
|
+
typename ObjectWrap<T>::InstanceSetterCallback setter>
|
|
3646
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
|
|
3647
|
+
const char* utf8name,
|
|
3648
|
+
napi_property_attributes attributes,
|
|
3649
|
+
void* data) {
|
|
3650
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3651
|
+
desc.utf8name = utf8name;
|
|
3652
|
+
desc.getter = This::WrapGetter(This::GetterTag<getter>());
|
|
3653
|
+
desc.setter = This::WrapSetter(This::SetterTag<setter>());
|
|
3654
|
+
desc.data = data;
|
|
3655
|
+
desc.attributes = attributes;
|
|
3656
|
+
return desc;
|
|
3657
|
+
}
|
|
3658
|
+
|
|
3659
|
+
template <typename T>
|
|
3660
|
+
template <typename ObjectWrap<T>::InstanceGetterCallback getter,
|
|
3661
|
+
typename ObjectWrap<T>::InstanceSetterCallback setter>
|
|
3662
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
|
|
3663
|
+
Symbol name,
|
|
3664
|
+
napi_property_attributes attributes,
|
|
3665
|
+
void* data) {
|
|
3666
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3667
|
+
desc.name = name;
|
|
3668
|
+
desc.getter = This::WrapGetter(This::GetterTag<getter>());
|
|
3669
|
+
desc.setter = This::WrapSetter(This::SetterTag<setter>());
|
|
3670
|
+
desc.data = data;
|
|
3671
|
+
desc.attributes = attributes;
|
|
3672
|
+
return desc;
|
|
3673
|
+
}
|
|
3674
|
+
|
|
3220
3675
|
template <typename T>
|
|
3221
3676
|
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(const char* utf8name,
|
|
3222
3677
|
Napi::Value value, napi_property_attributes attributes) {
|
|
@@ -3261,6 +3716,9 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
|
|
|
3261
3716
|
return desc;
|
|
3262
3717
|
}
|
|
3263
3718
|
|
|
3719
|
+
template <typename T>
|
|
3720
|
+
inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}
|
|
3721
|
+
|
|
3264
3722
|
template <typename T>
|
|
3265
3723
|
inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
|
|
3266
3724
|
napi_env env,
|
|
@@ -3275,10 +3733,21 @@ inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
|
|
|
3275
3733
|
return nullptr;
|
|
3276
3734
|
}
|
|
3277
3735
|
|
|
3278
|
-
T* instance;
|
|
3279
3736
|
napi_value wrapper = details::WrapCallback([&] {
|
|
3280
3737
|
CallbackInfo callbackInfo(env, info);
|
|
3281
|
-
instance = new T(callbackInfo);
|
|
3738
|
+
T* instance = new T(callbackInfo);
|
|
3739
|
+
#ifdef NAPI_CPP_EXCEPTIONS
|
|
3740
|
+
instance->_construction_failed = false;
|
|
3741
|
+
#else
|
|
3742
|
+
if (callbackInfo.Env().IsExceptionPending()) {
|
|
3743
|
+
// We need to clear the exception so that removing the wrap might work.
|
|
3744
|
+
Error e = callbackInfo.Env().GetAndClearPendingException();
|
|
3745
|
+
delete instance;
|
|
3746
|
+
e.ThrowAsJavaScriptException();
|
|
3747
|
+
} else {
|
|
3748
|
+
instance->_construction_failed = false;
|
|
3749
|
+
}
|
|
3750
|
+
# endif // NAPI_CPP_EXCEPTIONS
|
|
3282
3751
|
return callbackInfo.This();
|
|
3283
3752
|
});
|
|
3284
3753
|
|
|
@@ -3402,11 +3871,71 @@ inline napi_value ObjectWrap<T>::InstanceSetterCallbackWrapper(
|
|
|
3402
3871
|
}
|
|
3403
3872
|
|
|
3404
3873
|
template <typename T>
|
|
3405
|
-
inline void ObjectWrap<T>::FinalizeCallback(napi_env
|
|
3406
|
-
T
|
|
3874
|
+
inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hint*/) {
|
|
3875
|
+
ObjectWrap<T>* instance = static_cast<ObjectWrap<T>*>(data);
|
|
3876
|
+
instance->Finalize(Napi::Env(env));
|
|
3407
3877
|
delete instance;
|
|
3408
3878
|
}
|
|
3409
3879
|
|
|
3880
|
+
template <typename T>
|
|
3881
|
+
template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
|
|
3882
|
+
inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
|
|
3883
|
+
return details::WrapCallback([&] {
|
|
3884
|
+
method(CallbackInfo(env, info));
|
|
3885
|
+
return nullptr;
|
|
3886
|
+
});
|
|
3887
|
+
}
|
|
3888
|
+
|
|
3889
|
+
template <typename T>
|
|
3890
|
+
template <typename ObjectWrap<T>::StaticMethodCallback method>
|
|
3891
|
+
inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
|
|
3892
|
+
return details::WrapCallback([&] {
|
|
3893
|
+
return method(CallbackInfo(env, info));
|
|
3894
|
+
});
|
|
3895
|
+
}
|
|
3896
|
+
|
|
3897
|
+
template <typename T>
|
|
3898
|
+
template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
|
|
3899
|
+
inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
|
|
3900
|
+
return details::WrapCallback([&] {
|
|
3901
|
+
const CallbackInfo cbInfo(env, info);
|
|
3902
|
+
T* instance = Unwrap(cbInfo.This().As<Object>());
|
|
3903
|
+
(instance->*method)(cbInfo);
|
|
3904
|
+
return nullptr;
|
|
3905
|
+
});
|
|
3906
|
+
}
|
|
3907
|
+
|
|
3908
|
+
template <typename T>
|
|
3909
|
+
template <typename ObjectWrap<T>::InstanceMethodCallback method>
|
|
3910
|
+
inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
|
|
3911
|
+
return details::WrapCallback([&] {
|
|
3912
|
+
const CallbackInfo cbInfo(env, info);
|
|
3913
|
+
T* instance = Unwrap(cbInfo.This().As<Object>());
|
|
3914
|
+
return (instance->*method)(cbInfo);
|
|
3915
|
+
});
|
|
3916
|
+
}
|
|
3917
|
+
|
|
3918
|
+
template <typename T>
|
|
3919
|
+
template <typename ObjectWrap<T>::StaticSetterCallback method>
|
|
3920
|
+
inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
|
|
3921
|
+
return details::WrapCallback([&] {
|
|
3922
|
+
const CallbackInfo cbInfo(env, info);
|
|
3923
|
+
method(cbInfo, cbInfo[0]);
|
|
3924
|
+
return nullptr;
|
|
3925
|
+
});
|
|
3926
|
+
}
|
|
3927
|
+
|
|
3928
|
+
template <typename T>
|
|
3929
|
+
template <typename ObjectWrap<T>::InstanceSetterCallback method>
|
|
3930
|
+
inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
|
|
3931
|
+
return details::WrapCallback([&] {
|
|
3932
|
+
const CallbackInfo cbInfo(env, info);
|
|
3933
|
+
T* instance = Unwrap(cbInfo.This().As<Object>());
|
|
3934
|
+
(instance->*method)(cbInfo, cbInfo[0]);
|
|
3935
|
+
return nullptr;
|
|
3936
|
+
});
|
|
3937
|
+
}
|
|
3938
|
+
|
|
3410
3939
|
////////////////////////////////////////////////////////////////////////////////
|
|
3411
3940
|
// HandleScope class
|
|
3412
3941
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -3421,7 +3950,10 @@ inline HandleScope::HandleScope(Napi::Env env) : _env(env) {
|
|
|
3421
3950
|
}
|
|
3422
3951
|
|
|
3423
3952
|
inline HandleScope::~HandleScope() {
|
|
3424
|
-
napi_close_handle_scope(_env, _scope);
|
|
3953
|
+
napi_status status = napi_close_handle_scope(_env, _scope);
|
|
3954
|
+
NAPI_FATAL_IF_FAILED(status,
|
|
3955
|
+
"HandleScope::~HandleScope",
|
|
3956
|
+
"napi_close_handle_scope");
|
|
3425
3957
|
}
|
|
3426
3958
|
|
|
3427
3959
|
inline HandleScope::operator napi_handle_scope() const {
|
|
@@ -3446,7 +3978,10 @@ inline EscapableHandleScope::EscapableHandleScope(Napi::Env env) : _env(env) {
|
|
|
3446
3978
|
}
|
|
3447
3979
|
|
|
3448
3980
|
inline EscapableHandleScope::~EscapableHandleScope() {
|
|
3449
|
-
napi_close_escapable_handle_scope(_env, _scope);
|
|
3981
|
+
napi_status status = napi_close_escapable_handle_scope(_env, _scope);
|
|
3982
|
+
NAPI_FATAL_IF_FAILED(status,
|
|
3983
|
+
"EscapableHandleScope::~EscapableHandleScope",
|
|
3984
|
+
"napi_close_escapable_handle_scope");
|
|
3450
3985
|
}
|
|
3451
3986
|
|
|
3452
3987
|
inline EscapableHandleScope::operator napi_escapable_handle_scope() const {
|
|
@@ -3482,7 +4017,10 @@ inline CallbackScope::CallbackScope(napi_env env, napi_async_context context)
|
|
|
3482
4017
|
}
|
|
3483
4018
|
|
|
3484
4019
|
inline CallbackScope::~CallbackScope() {
|
|
3485
|
-
napi_close_callback_scope(_env, _scope);
|
|
4020
|
+
napi_status status = napi_close_callback_scope(_env, _scope);
|
|
4021
|
+
NAPI_FATAL_IF_FAILED(status,
|
|
4022
|
+
"CallbackScope::~CallbackScope",
|
|
4023
|
+
"napi_close_callback_scope");
|
|
3486
4024
|
}
|
|
3487
4025
|
|
|
3488
4026
|
inline CallbackScope::operator napi_callback_scope() const {
|
|
@@ -3542,6 +4080,10 @@ inline AsyncContext::operator napi_async_context() const {
|
|
|
3542
4080
|
return _context;
|
|
3543
4081
|
}
|
|
3544
4082
|
|
|
4083
|
+
inline Napi::Env AsyncContext::Env() const {
|
|
4084
|
+
return Napi::Env(_env);
|
|
4085
|
+
}
|
|
4086
|
+
|
|
3545
4087
|
////////////////////////////////////////////////////////////////////////////////
|
|
3546
4088
|
// AsyncWorker class
|
|
3547
4089
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -3591,8 +4133,8 @@ inline AsyncWorker::AsyncWorker(const Object& receiver,
|
|
|
3591
4133
|
_env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
|
|
3592
4134
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3593
4135
|
|
|
3594
|
-
status = napi_create_async_work(_env, resource, resource_id,
|
|
3595
|
-
|
|
4136
|
+
status = napi_create_async_work(_env, resource, resource_id, OnAsyncWorkExecute,
|
|
4137
|
+
OnAsyncWorkComplete, this, &_work);
|
|
3596
4138
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3597
4139
|
}
|
|
3598
4140
|
|
|
@@ -3617,8 +4159,8 @@ inline AsyncWorker::AsyncWorker(Napi::Env env,
|
|
|
3617
4159
|
_env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
|
|
3618
4160
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3619
4161
|
|
|
3620
|
-
status = napi_create_async_work(_env, resource, resource_id,
|
|
3621
|
-
|
|
4162
|
+
status = napi_create_async_work(_env, resource, resource_id, OnAsyncWorkExecute,
|
|
4163
|
+
OnAsyncWorkComplete, this, &_work);
|
|
3622
4164
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3623
4165
|
}
|
|
3624
4166
|
|
|
@@ -3705,40 +4247,51 @@ inline void AsyncWorker::SetError(const std::string& error) {
|
|
|
3705
4247
|
inline std::vector<napi_value> AsyncWorker::GetResult(Napi::Env /*env*/) {
|
|
3706
4248
|
return {};
|
|
3707
4249
|
}
|
|
4250
|
+
// The OnAsyncWorkExecute method receives an napi_env argument. However, do NOT
|
|
4251
|
+
// use it within this method, as it does not run on the JavaScript thread and
|
|
4252
|
+
// must not run any method that would cause JavaScript to run. In practice,
|
|
4253
|
+
// this means that almost any use of napi_env will be incorrect.
|
|
4254
|
+
inline void AsyncWorker::OnAsyncWorkExecute(napi_env env, void* asyncworker) {
|
|
4255
|
+
AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
|
|
4256
|
+
self->OnExecute(env);
|
|
4257
|
+
}
|
|
3708
4258
|
// The OnExecute method receives an napi_env argument. However, do NOT
|
|
3709
|
-
// use it within this method, as it does not run on the
|
|
3710
|
-
// not run any method that would cause JavaScript to run. In practice,
|
|
3711
|
-
// means that almost any use of napi_env will be incorrect.
|
|
3712
|
-
inline void AsyncWorker::OnExecute(
|
|
3713
|
-
AsyncWorker* self = static_cast<AsyncWorker*>(this_pointer);
|
|
4259
|
+
// use it within this method, as it does not run on the JavaScript thread and
|
|
4260
|
+
// must not run any method that would cause JavaScript to run. In practice,
|
|
4261
|
+
// this means that almost any use of napi_env will be incorrect.
|
|
4262
|
+
inline void AsyncWorker::OnExecute(Napi::Env /*DO_NOT_USE*/) {
|
|
3714
4263
|
#ifdef NAPI_CPP_EXCEPTIONS
|
|
3715
4264
|
try {
|
|
3716
|
-
|
|
4265
|
+
Execute();
|
|
3717
4266
|
} catch (const std::exception& e) {
|
|
3718
|
-
|
|
4267
|
+
SetError(e.what());
|
|
3719
4268
|
}
|
|
3720
4269
|
#else // NAPI_CPP_EXCEPTIONS
|
|
3721
|
-
|
|
4270
|
+
Execute();
|
|
3722
4271
|
#endif // NAPI_CPP_EXCEPTIONS
|
|
3723
4272
|
}
|
|
3724
4273
|
|
|
3725
|
-
inline void AsyncWorker::
|
|
3726
|
-
|
|
3727
|
-
|
|
4274
|
+
inline void AsyncWorker::OnAsyncWorkComplete(napi_env env,
|
|
4275
|
+
napi_status status,
|
|
4276
|
+
void* asyncworker) {
|
|
4277
|
+
AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
|
|
4278
|
+
self->OnWorkComplete(env, status);
|
|
4279
|
+
}
|
|
4280
|
+
inline void AsyncWorker::OnWorkComplete(Napi::Env /*env*/, napi_status status) {
|
|
3728
4281
|
if (status != napi_cancelled) {
|
|
3729
|
-
HandleScope scope(
|
|
4282
|
+
HandleScope scope(_env);
|
|
3730
4283
|
details::WrapCallback([&] {
|
|
3731
|
-
if (
|
|
3732
|
-
|
|
4284
|
+
if (_error.size() == 0) {
|
|
4285
|
+
OnOK();
|
|
3733
4286
|
}
|
|
3734
4287
|
else {
|
|
3735
|
-
|
|
4288
|
+
OnError(Error::New(_env, _error));
|
|
3736
4289
|
}
|
|
3737
4290
|
return nullptr;
|
|
3738
4291
|
});
|
|
3739
4292
|
}
|
|
3740
|
-
if (!
|
|
3741
|
-
|
|
4293
|
+
if (!_suppress_destruct) {
|
|
4294
|
+
Destroy();
|
|
3742
4295
|
}
|
|
3743
4296
|
}
|
|
3744
4297
|
|
|
@@ -3919,35 +4472,28 @@ inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
|
3919
4472
|
}
|
|
3920
4473
|
|
|
3921
4474
|
inline ThreadSafeFunction::ThreadSafeFunction()
|
|
3922
|
-
: _tsfn(
|
|
4475
|
+
: _tsfn() {
|
|
3923
4476
|
}
|
|
3924
4477
|
|
|
3925
4478
|
inline ThreadSafeFunction::ThreadSafeFunction(
|
|
3926
4479
|
napi_threadsafe_function tsfn)
|
|
3927
|
-
: _tsfn(
|
|
4480
|
+
: _tsfn(tsfn) {
|
|
3928
4481
|
}
|
|
3929
4482
|
|
|
3930
|
-
inline ThreadSafeFunction::
|
|
3931
|
-
|
|
3932
|
-
other._tsfn.reset();
|
|
3933
|
-
}
|
|
3934
|
-
|
|
3935
|
-
inline ThreadSafeFunction& ThreadSafeFunction::operator =(
|
|
3936
|
-
ThreadSafeFunction&& other) {
|
|
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;
|
|
4483
|
+
inline ThreadSafeFunction::operator napi_threadsafe_function() const {
|
|
4484
|
+
return _tsfn;
|
|
3945
4485
|
}
|
|
3946
4486
|
|
|
3947
4487
|
inline napi_status ThreadSafeFunction::BlockingCall() const {
|
|
3948
4488
|
return CallInternal(nullptr, napi_tsfn_blocking);
|
|
3949
4489
|
}
|
|
3950
4490
|
|
|
4491
|
+
template <>
|
|
4492
|
+
inline napi_status ThreadSafeFunction::BlockingCall(
|
|
4493
|
+
void* data) const {
|
|
4494
|
+
return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_blocking);
|
|
4495
|
+
}
|
|
4496
|
+
|
|
3951
4497
|
template <typename Callback>
|
|
3952
4498
|
inline napi_status ThreadSafeFunction::BlockingCall(
|
|
3953
4499
|
Callback callback) const {
|
|
@@ -3967,6 +4513,12 @@ inline napi_status ThreadSafeFunction::NonBlockingCall() const {
|
|
|
3967
4513
|
return CallInternal(nullptr, napi_tsfn_nonblocking);
|
|
3968
4514
|
}
|
|
3969
4515
|
|
|
4516
|
+
template <>
|
|
4517
|
+
inline napi_status ThreadSafeFunction::NonBlockingCall(
|
|
4518
|
+
void* data) const {
|
|
4519
|
+
return napi_call_threadsafe_function(_tsfn, data, napi_tsfn_nonblocking);
|
|
4520
|
+
}
|
|
4521
|
+
|
|
3970
4522
|
template <typename Callback>
|
|
3971
4523
|
inline napi_status ThreadSafeFunction::NonBlockingCall(
|
|
3972
4524
|
Callback callback) const {
|
|
@@ -3982,22 +4534,37 @@ inline napi_status ThreadSafeFunction::NonBlockingCall(
|
|
|
3982
4534
|
return CallInternal(new CallbackWrapper(wrapper), napi_tsfn_nonblocking);
|
|
3983
4535
|
}
|
|
3984
4536
|
|
|
4537
|
+
inline void ThreadSafeFunction::Ref(napi_env env) const {
|
|
4538
|
+
if (_tsfn != nullptr) {
|
|
4539
|
+
napi_status status = napi_ref_threadsafe_function(env, _tsfn);
|
|
4540
|
+
NAPI_THROW_IF_FAILED_VOID(env, status);
|
|
4541
|
+
}
|
|
4542
|
+
}
|
|
4543
|
+
|
|
4544
|
+
inline void ThreadSafeFunction::Unref(napi_env env) const {
|
|
4545
|
+
if (_tsfn != nullptr) {
|
|
4546
|
+
napi_status status = napi_unref_threadsafe_function(env, _tsfn);
|
|
4547
|
+
NAPI_THROW_IF_FAILED_VOID(env, status);
|
|
4548
|
+
}
|
|
4549
|
+
}
|
|
4550
|
+
|
|
3985
4551
|
inline napi_status ThreadSafeFunction::Acquire() const {
|
|
3986
|
-
return napi_acquire_threadsafe_function(
|
|
4552
|
+
return napi_acquire_threadsafe_function(_tsfn);
|
|
3987
4553
|
}
|
|
3988
4554
|
|
|
3989
4555
|
inline napi_status ThreadSafeFunction::Release() {
|
|
3990
|
-
return napi_release_threadsafe_function(
|
|
4556
|
+
return napi_release_threadsafe_function(_tsfn, napi_tsfn_release);
|
|
3991
4557
|
}
|
|
3992
4558
|
|
|
3993
4559
|
inline napi_status ThreadSafeFunction::Abort() {
|
|
3994
|
-
return napi_release_threadsafe_function(
|
|
4560
|
+
return napi_release_threadsafe_function(_tsfn, napi_tsfn_abort);
|
|
3995
4561
|
}
|
|
3996
4562
|
|
|
3997
4563
|
inline ThreadSafeFunction::ConvertibleContext
|
|
3998
4564
|
ThreadSafeFunction::GetContext() const {
|
|
3999
4565
|
void* context;
|
|
4000
|
-
napi_get_threadsafe_function_context(
|
|
4566
|
+
napi_status status = napi_get_threadsafe_function_context(_tsfn, &context);
|
|
4567
|
+
NAPI_FATAL_IF_FAILED(status, "ThreadSafeFunction::GetContext", "napi_get_threadsafe_function_context");
|
|
4001
4568
|
return ConvertibleContext({ context });
|
|
4002
4569
|
}
|
|
4003
4570
|
|
|
@@ -4020,10 +4587,10 @@ inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
|
4020
4587
|
|
|
4021
4588
|
ThreadSafeFunction tsfn;
|
|
4022
4589
|
auto* finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
|
|
4023
|
-
FinalizerDataType>({ data, finalizeCallback
|
|
4590
|
+
FinalizerDataType>({ data, finalizeCallback });
|
|
4024
4591
|
napi_status status = napi_create_threadsafe_function(env, callback, resource,
|
|
4025
4592
|
Value::From(env, resourceName), maxQueueSize, initialThreadCount,
|
|
4026
|
-
finalizeData, wrapper, context, CallJS, tsfn._tsfn
|
|
4593
|
+
finalizeData, wrapper, context, CallJS, &tsfn._tsfn);
|
|
4027
4594
|
if (status != napi_ok) {
|
|
4028
4595
|
delete finalizeData;
|
|
4029
4596
|
NAPI_THROW_IF_FAILED(env, status, ThreadSafeFunction());
|
|
@@ -4036,7 +4603,7 @@ inline napi_status ThreadSafeFunction::CallInternal(
|
|
|
4036
4603
|
CallbackWrapper* callbackWrapper,
|
|
4037
4604
|
napi_threadsafe_function_call_mode mode) const {
|
|
4038
4605
|
napi_status status = napi_call_threadsafe_function(
|
|
4039
|
-
|
|
4606
|
+
_tsfn, callbackWrapper, mode);
|
|
4040
4607
|
if (status != napi_ok && callbackWrapper != nullptr) {
|
|
4041
4608
|
delete callbackWrapper;
|
|
4042
4609
|
}
|
|
@@ -4061,6 +4628,340 @@ inline void ThreadSafeFunction::CallJS(napi_env env,
|
|
|
4061
4628
|
Function(env, jsCallback).Call({});
|
|
4062
4629
|
}
|
|
4063
4630
|
}
|
|
4631
|
+
|
|
4632
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4633
|
+
// Async Progress Worker Base class
|
|
4634
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4635
|
+
template <typename DataType>
|
|
4636
|
+
inline AsyncProgressWorkerBase<DataType>::AsyncProgressWorkerBase(const Object& receiver,
|
|
4637
|
+
const Function& callback,
|
|
4638
|
+
const char* resource_name,
|
|
4639
|
+
const Object& resource,
|
|
4640
|
+
size_t queue_size)
|
|
4641
|
+
: AsyncWorker(receiver, callback, resource_name, resource) {
|
|
4642
|
+
// Fill all possible arguments to work around ambiguous ThreadSafeFunction::New signatures.
|
|
4643
|
+
_tsfn = ThreadSafeFunction::New(callback.Env(),
|
|
4644
|
+
callback,
|
|
4645
|
+
resource,
|
|
4646
|
+
resource_name,
|
|
4647
|
+
queue_size,
|
|
4648
|
+
/** initialThreadCount */ 1,
|
|
4649
|
+
/** context */ this,
|
|
4650
|
+
OnThreadSafeFunctionFinalize,
|
|
4651
|
+
/** finalizeData */ this);
|
|
4652
|
+
}
|
|
4653
|
+
|
|
4654
|
+
#if NAPI_VERSION > 4
|
|
4655
|
+
template <typename DataType>
|
|
4656
|
+
inline AsyncProgressWorkerBase<DataType>::AsyncProgressWorkerBase(Napi::Env env,
|
|
4657
|
+
const char* resource_name,
|
|
4658
|
+
const Object& resource,
|
|
4659
|
+
size_t queue_size)
|
|
4660
|
+
: AsyncWorker(env, resource_name, resource) {
|
|
4661
|
+
// TODO: Once the changes to make the callback optional for threadsafe
|
|
4662
|
+
// functions are available on all versions we can remove the dummy Function here.
|
|
4663
|
+
Function callback;
|
|
4664
|
+
// Fill all possible arguments to work around ambiguous ThreadSafeFunction::New signatures.
|
|
4665
|
+
_tsfn = ThreadSafeFunction::New(env,
|
|
4666
|
+
callback,
|
|
4667
|
+
resource,
|
|
4668
|
+
resource_name,
|
|
4669
|
+
queue_size,
|
|
4670
|
+
/** initialThreadCount */ 1,
|
|
4671
|
+
/** context */ this,
|
|
4672
|
+
OnThreadSafeFunctionFinalize,
|
|
4673
|
+
/** finalizeData */ this);
|
|
4674
|
+
}
|
|
4675
|
+
#endif
|
|
4676
|
+
|
|
4677
|
+
template<typename DataType>
|
|
4678
|
+
inline AsyncProgressWorkerBase<DataType>::~AsyncProgressWorkerBase() {
|
|
4679
|
+
// Abort pending tsfn call.
|
|
4680
|
+
// Don't send progress events after we've already completed.
|
|
4681
|
+
// It's ok to call ThreadSafeFunction::Abort and ThreadSafeFunction::Release duplicated.
|
|
4682
|
+
_tsfn.Abort();
|
|
4683
|
+
}
|
|
4684
|
+
|
|
4685
|
+
template <typename DataType>
|
|
4686
|
+
inline void AsyncProgressWorkerBase<DataType>::OnAsyncWorkProgress(Napi::Env /* env */,
|
|
4687
|
+
Napi::Function /* jsCallback */,
|
|
4688
|
+
void* data) {
|
|
4689
|
+
ThreadSafeData* tsd = static_cast<ThreadSafeData*>(data);
|
|
4690
|
+
tsd->asyncprogressworker()->OnWorkProgress(tsd->data());
|
|
4691
|
+
}
|
|
4692
|
+
|
|
4693
|
+
template <typename DataType>
|
|
4694
|
+
inline napi_status AsyncProgressWorkerBase<DataType>::NonBlockingCall(DataType* data) {
|
|
4695
|
+
auto tsd = new AsyncProgressWorkerBase::ThreadSafeData(this, data);
|
|
4696
|
+
return _tsfn.NonBlockingCall(tsd, OnAsyncWorkProgress);
|
|
4697
|
+
}
|
|
4698
|
+
|
|
4699
|
+
template <typename DataType>
|
|
4700
|
+
inline void AsyncProgressWorkerBase<DataType>::OnWorkComplete(Napi::Env /* env */, napi_status status) {
|
|
4701
|
+
_work_completed = true;
|
|
4702
|
+
_complete_status = status;
|
|
4703
|
+
_tsfn.Release();
|
|
4704
|
+
}
|
|
4705
|
+
|
|
4706
|
+
template <typename DataType>
|
|
4707
|
+
inline void AsyncProgressWorkerBase<DataType>::OnThreadSafeFunctionFinalize(Napi::Env env, void* /* data */, AsyncProgressWorkerBase* context) {
|
|
4708
|
+
if (context->_work_completed) {
|
|
4709
|
+
context->AsyncWorker::OnWorkComplete(env, context->_complete_status);
|
|
4710
|
+
}
|
|
4711
|
+
}
|
|
4712
|
+
|
|
4713
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4714
|
+
// Async Progress Worker class
|
|
4715
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4716
|
+
template<class T>
|
|
4717
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback)
|
|
4718
|
+
: AsyncProgressWorker(callback, "generic") {
|
|
4719
|
+
}
|
|
4720
|
+
|
|
4721
|
+
template<class T>
|
|
4722
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
|
|
4723
|
+
const char* resource_name)
|
|
4724
|
+
: AsyncProgressWorker(callback, resource_name, Object::New(callback.Env())) {
|
|
4725
|
+
}
|
|
4726
|
+
|
|
4727
|
+
template<class T>
|
|
4728
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
|
|
4729
|
+
const char* resource_name,
|
|
4730
|
+
const Object& resource)
|
|
4731
|
+
: AsyncProgressWorker(Object::New(callback.Env()),
|
|
4732
|
+
callback,
|
|
4733
|
+
resource_name,
|
|
4734
|
+
resource) {
|
|
4735
|
+
}
|
|
4736
|
+
|
|
4737
|
+
template<class T>
|
|
4738
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
|
|
4739
|
+
const Function& callback)
|
|
4740
|
+
: AsyncProgressWorker(receiver, callback, "generic") {
|
|
4741
|
+
}
|
|
4742
|
+
|
|
4743
|
+
template<class T>
|
|
4744
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
|
|
4745
|
+
const Function& callback,
|
|
4746
|
+
const char* resource_name)
|
|
4747
|
+
: AsyncProgressWorker(receiver,
|
|
4748
|
+
callback,
|
|
4749
|
+
resource_name,
|
|
4750
|
+
Object::New(callback.Env())) {
|
|
4751
|
+
}
|
|
4752
|
+
|
|
4753
|
+
template<class T>
|
|
4754
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
|
|
4755
|
+
const Function& callback,
|
|
4756
|
+
const char* resource_name,
|
|
4757
|
+
const Object& resource)
|
|
4758
|
+
: AsyncProgressWorkerBase(receiver, callback, resource_name, resource),
|
|
4759
|
+
_asyncdata(nullptr),
|
|
4760
|
+
_asyncsize(0) {
|
|
4761
|
+
}
|
|
4762
|
+
|
|
4763
|
+
#if NAPI_VERSION > 4
|
|
4764
|
+
template<class T>
|
|
4765
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env)
|
|
4766
|
+
: AsyncProgressWorker(env, "generic") {
|
|
4767
|
+
}
|
|
4768
|
+
|
|
4769
|
+
template<class T>
|
|
4770
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
|
|
4771
|
+
const char* resource_name)
|
|
4772
|
+
: AsyncProgressWorker(env, resource_name, Object::New(env)) {
|
|
4773
|
+
}
|
|
4774
|
+
|
|
4775
|
+
template<class T>
|
|
4776
|
+
inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
|
|
4777
|
+
const char* resource_name,
|
|
4778
|
+
const Object& resource)
|
|
4779
|
+
: AsyncProgressWorkerBase(env, resource_name, resource),
|
|
4780
|
+
_asyncdata(nullptr),
|
|
4781
|
+
_asyncsize(0) {
|
|
4782
|
+
}
|
|
4783
|
+
#endif
|
|
4784
|
+
|
|
4785
|
+
template<class T>
|
|
4786
|
+
inline AsyncProgressWorker<T>::~AsyncProgressWorker() {
|
|
4787
|
+
{
|
|
4788
|
+
std::lock_guard<std::mutex> lock(this->_mutex);
|
|
4789
|
+
_asyncdata = nullptr;
|
|
4790
|
+
_asyncsize = 0;
|
|
4791
|
+
}
|
|
4792
|
+
}
|
|
4793
|
+
|
|
4794
|
+
template<class T>
|
|
4795
|
+
inline void AsyncProgressWorker<T>::Execute() {
|
|
4796
|
+
ExecutionProgress progress(this);
|
|
4797
|
+
Execute(progress);
|
|
4798
|
+
}
|
|
4799
|
+
|
|
4800
|
+
template<class T>
|
|
4801
|
+
inline void AsyncProgressWorker<T>::OnWorkProgress(void*) {
|
|
4802
|
+
T* data;
|
|
4803
|
+
size_t size;
|
|
4804
|
+
{
|
|
4805
|
+
std::lock_guard<std::mutex> lock(this->_mutex);
|
|
4806
|
+
data = this->_asyncdata;
|
|
4807
|
+
size = this->_asyncsize;
|
|
4808
|
+
this->_asyncdata = nullptr;
|
|
4809
|
+
this->_asyncsize = 0;
|
|
4810
|
+
}
|
|
4811
|
+
|
|
4812
|
+
this->OnProgress(data, size);
|
|
4813
|
+
delete[] data;
|
|
4814
|
+
}
|
|
4815
|
+
|
|
4816
|
+
template<class T>
|
|
4817
|
+
inline void AsyncProgressWorker<T>::SendProgress_(const T* data, size_t count) {
|
|
4818
|
+
T* new_data = new T[count];
|
|
4819
|
+
std::copy(data, data + count, new_data);
|
|
4820
|
+
|
|
4821
|
+
T* old_data;
|
|
4822
|
+
{
|
|
4823
|
+
std::lock_guard<std::mutex> lock(this->_mutex);
|
|
4824
|
+
old_data = _asyncdata;
|
|
4825
|
+
_asyncdata = new_data;
|
|
4826
|
+
_asyncsize = count;
|
|
4827
|
+
}
|
|
4828
|
+
this->NonBlockingCall(nullptr);
|
|
4829
|
+
|
|
4830
|
+
delete[] old_data;
|
|
4831
|
+
}
|
|
4832
|
+
|
|
4833
|
+
template<class T>
|
|
4834
|
+
inline void AsyncProgressWorker<T>::Signal() const {
|
|
4835
|
+
this->NonBlockingCall(static_cast<T*>(nullptr));
|
|
4836
|
+
}
|
|
4837
|
+
|
|
4838
|
+
template<class T>
|
|
4839
|
+
inline void AsyncProgressWorker<T>::ExecutionProgress::Signal() const {
|
|
4840
|
+
_worker->Signal();
|
|
4841
|
+
}
|
|
4842
|
+
|
|
4843
|
+
template<class T>
|
|
4844
|
+
inline void AsyncProgressWorker<T>::ExecutionProgress::Send(const T* data, size_t count) const {
|
|
4845
|
+
_worker->SendProgress_(data, count);
|
|
4846
|
+
}
|
|
4847
|
+
|
|
4848
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4849
|
+
// Async Progress Queue Worker class
|
|
4850
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4851
|
+
template<class T>
|
|
4852
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback)
|
|
4853
|
+
: AsyncProgressQueueWorker(callback, "generic") {
|
|
4854
|
+
}
|
|
4855
|
+
|
|
4856
|
+
template<class T>
|
|
4857
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback,
|
|
4858
|
+
const char* resource_name)
|
|
4859
|
+
: AsyncProgressQueueWorker(callback, resource_name, Object::New(callback.Env())) {
|
|
4860
|
+
}
|
|
4861
|
+
|
|
4862
|
+
template<class T>
|
|
4863
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback,
|
|
4864
|
+
const char* resource_name,
|
|
4865
|
+
const Object& resource)
|
|
4866
|
+
: AsyncProgressQueueWorker(Object::New(callback.Env()),
|
|
4867
|
+
callback,
|
|
4868
|
+
resource_name,
|
|
4869
|
+
resource) {
|
|
4870
|
+
}
|
|
4871
|
+
|
|
4872
|
+
template<class T>
|
|
4873
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
|
|
4874
|
+
const Function& callback)
|
|
4875
|
+
: AsyncProgressQueueWorker(receiver, callback, "generic") {
|
|
4876
|
+
}
|
|
4877
|
+
|
|
4878
|
+
template<class T>
|
|
4879
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
|
|
4880
|
+
const Function& callback,
|
|
4881
|
+
const char* resource_name)
|
|
4882
|
+
: AsyncProgressQueueWorker(receiver,
|
|
4883
|
+
callback,
|
|
4884
|
+
resource_name,
|
|
4885
|
+
Object::New(callback.Env())) {
|
|
4886
|
+
}
|
|
4887
|
+
|
|
4888
|
+
template<class T>
|
|
4889
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
|
|
4890
|
+
const Function& callback,
|
|
4891
|
+
const char* resource_name,
|
|
4892
|
+
const Object& resource)
|
|
4893
|
+
: AsyncProgressWorkerBase<std::pair<T*, size_t>>(receiver, callback, resource_name, resource, /** unlimited queue size */0) {
|
|
4894
|
+
}
|
|
4895
|
+
|
|
4896
|
+
#if NAPI_VERSION > 4
|
|
4897
|
+
template<class T>
|
|
4898
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env)
|
|
4899
|
+
: AsyncProgressQueueWorker(env, "generic") {
|
|
4900
|
+
}
|
|
4901
|
+
|
|
4902
|
+
template<class T>
|
|
4903
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env,
|
|
4904
|
+
const char* resource_name)
|
|
4905
|
+
: AsyncProgressQueueWorker(env, resource_name, Object::New(env)) {
|
|
4906
|
+
}
|
|
4907
|
+
|
|
4908
|
+
template<class T>
|
|
4909
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env,
|
|
4910
|
+
const char* resource_name,
|
|
4911
|
+
const Object& resource)
|
|
4912
|
+
: AsyncProgressWorkerBase<std::pair<T*, size_t>>(env, resource_name, resource, /** unlimited queue size */0) {
|
|
4913
|
+
}
|
|
4914
|
+
#endif
|
|
4915
|
+
|
|
4916
|
+
template<class T>
|
|
4917
|
+
inline void AsyncProgressQueueWorker<T>::Execute() {
|
|
4918
|
+
ExecutionProgress progress(this);
|
|
4919
|
+
Execute(progress);
|
|
4920
|
+
}
|
|
4921
|
+
|
|
4922
|
+
template<class T>
|
|
4923
|
+
inline void AsyncProgressQueueWorker<T>::OnWorkProgress(std::pair<T*, size_t>* datapair) {
|
|
4924
|
+
if (datapair == nullptr) {
|
|
4925
|
+
return;
|
|
4926
|
+
}
|
|
4927
|
+
|
|
4928
|
+
T *data = datapair->first;
|
|
4929
|
+
size_t size = datapair->second;
|
|
4930
|
+
|
|
4931
|
+
this->OnProgress(data, size);
|
|
4932
|
+
delete datapair;
|
|
4933
|
+
delete[] data;
|
|
4934
|
+
}
|
|
4935
|
+
|
|
4936
|
+
template<class T>
|
|
4937
|
+
inline void AsyncProgressQueueWorker<T>::SendProgress_(const T* data, size_t count) {
|
|
4938
|
+
T* new_data = new T[count];
|
|
4939
|
+
std::copy(data, data + count, new_data);
|
|
4940
|
+
|
|
4941
|
+
auto pair = new std::pair<T*, size_t>(new_data, count);
|
|
4942
|
+
this->NonBlockingCall(pair);
|
|
4943
|
+
}
|
|
4944
|
+
|
|
4945
|
+
template<class T>
|
|
4946
|
+
inline void AsyncProgressQueueWorker<T>::Signal() const {
|
|
4947
|
+
this->NonBlockingCall(nullptr);
|
|
4948
|
+
}
|
|
4949
|
+
|
|
4950
|
+
template<class T>
|
|
4951
|
+
inline void AsyncProgressQueueWorker<T>::OnWorkComplete(Napi::Env env, napi_status status) {
|
|
4952
|
+
// Draining queued items in TSFN.
|
|
4953
|
+
AsyncProgressWorkerBase<std::pair<T*, size_t>>::OnWorkComplete(env, status);
|
|
4954
|
+
}
|
|
4955
|
+
|
|
4956
|
+
template<class T>
|
|
4957
|
+
inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Signal() const {
|
|
4958
|
+
_worker->Signal();
|
|
4959
|
+
}
|
|
4960
|
+
|
|
4961
|
+
template<class T>
|
|
4962
|
+
inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Send(const T* data, size_t count) const {
|
|
4963
|
+
_worker->SendProgress_(data, count);
|
|
4964
|
+
}
|
|
4064
4965
|
#endif
|
|
4065
4966
|
|
|
4066
4967
|
////////////////////////////////////////////////////////////////////////////////
|