node-addon-api 2.0.1 → 3.0.2
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 +1 -4
- package/CHANGELOG.md +172 -10
- package/README.md +81 -30
- package/appveyor.yml +3 -14
- package/benchmark/README.md +47 -0
- package/benchmark/binding.gyp +25 -0
- package/benchmark/function_args.cc +217 -0
- package/benchmark/function_args.js +60 -0
- package/benchmark/index.js +34 -0
- package/benchmark/property_descriptor.cc +91 -0
- package/benchmark/property_descriptor.js +37 -0
- package/common.gypi +21 -0
- package/doc/addon.md +157 -0
- package/doc/array.md +81 -0
- package/doc/array_buffer.md +4 -0
- package/doc/async_worker.md +33 -4
- package/doc/{async_progress_worker.md → async_worker_variants.md} +115 -3
- package/doc/bigint.md +7 -2
- package/doc/boolean.md +4 -0
- package/doc/buffer.md +4 -0
- package/doc/class_property_descriptor.md +3 -3
- package/doc/creating_a_release.md +5 -5
- package/doc/dataview.md +4 -0
- package/doc/date.md +2 -2
- package/doc/env.md +69 -0
- package/doc/error.md +5 -0
- package/doc/external.md +4 -0
- package/doc/function.md +109 -1
- package/doc/hierarchy.md +91 -0
- package/doc/instance_wrap.md +408 -0
- package/doc/name.md +29 -0
- package/doc/object.md +44 -1
- package/doc/object_lifetime_management.md +1 -1
- package/doc/object_wrap.md +219 -215
- package/doc/promises.md +5 -0
- package/doc/property_descriptor.md +64 -9
- package/doc/setup.md +1 -2
- package/doc/string.md +5 -1
- package/doc/symbol.md +5 -1
- package/doc/typed_array.md +4 -0
- package/doc/typed_array_of.md +4 -0
- package/doc/value.md +166 -104
- package/except.gypi +16 -0
- package/index.js +7 -41
- package/napi-inl.h +1116 -400
- package/napi.h +414 -142
- package/node_api.gyp +9 -0
- package/noexcept.gypi +16 -0
- package/{src/nothing.c → nothing.c} +0 -0
- package/package.json +63 -1
- package/tools/README.md +4 -4
- package/tools/conversion.js +4 -8
- package/doc/basic_types.md +0 -423
- package/doc/working_with_javascript_values.md +0 -14
- 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
|
@@ -82,6 +82,24 @@ inline napi_value WrapCallback(Callable callback) {
|
|
|
82
82
|
#endif // NAPI_CPP_EXCEPTIONS
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
// For use in JS to C++ void callback wrappers to catch any Napi::Error
|
|
86
|
+
// exceptions and rethrow them as JavaScript exceptions before returning from the
|
|
87
|
+
// callback.
|
|
88
|
+
template <typename Callable>
|
|
89
|
+
inline void WrapVoidCallback(Callable callback) {
|
|
90
|
+
#ifdef NAPI_CPP_EXCEPTIONS
|
|
91
|
+
try {
|
|
92
|
+
callback();
|
|
93
|
+
} catch (const Error& e) {
|
|
94
|
+
e.ThrowAsJavaScriptException();
|
|
95
|
+
}
|
|
96
|
+
#else // NAPI_CPP_EXCEPTIONS
|
|
97
|
+
// When C++ exceptions are disabled, errors are immediately thrown as JS
|
|
98
|
+
// exceptions, so there is no need to catch and rethrow them here.
|
|
99
|
+
callback();
|
|
100
|
+
#endif // NAPI_CPP_EXCEPTIONS
|
|
101
|
+
}
|
|
102
|
+
|
|
85
103
|
template <typename Callable, typename Return>
|
|
86
104
|
struct CallbackData {
|
|
87
105
|
static inline
|
|
@@ -117,27 +135,73 @@ struct CallbackData<Callable, void> {
|
|
|
117
135
|
void* data;
|
|
118
136
|
};
|
|
119
137
|
|
|
138
|
+
template <void (*Callback)(const CallbackInfo& info)>
|
|
139
|
+
static napi_value
|
|
140
|
+
TemplatedVoidCallback(napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
|
|
141
|
+
return details::WrapCallback([&] {
|
|
142
|
+
CallbackInfo cbInfo(env, info);
|
|
143
|
+
Callback(cbInfo);
|
|
144
|
+
return nullptr;
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
template <Napi::Value (*Callback)(const CallbackInfo& info)>
|
|
149
|
+
static napi_value
|
|
150
|
+
TemplatedCallback(napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
|
|
151
|
+
return details::WrapCallback([&] {
|
|
152
|
+
CallbackInfo cbInfo(env, info);
|
|
153
|
+
return Callback(cbInfo);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
template <typename T,
|
|
158
|
+
Napi::Value (T::*UnwrapCallback)(const CallbackInfo& info)>
|
|
159
|
+
static napi_value
|
|
160
|
+
TemplatedInstanceCallback(napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
|
|
161
|
+
return details::WrapCallback([&] {
|
|
162
|
+
CallbackInfo cbInfo(env, info);
|
|
163
|
+
T* instance = T::Unwrap(cbInfo.This().As<Object>());
|
|
164
|
+
return (instance->*UnwrapCallback)(cbInfo);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
template <typename T, void (T::*UnwrapCallback)(const CallbackInfo& info)>
|
|
169
|
+
static napi_value
|
|
170
|
+
TemplatedInstanceVoidCallback(napi_env env,
|
|
171
|
+
napi_callback_info info) NAPI_NOEXCEPT {
|
|
172
|
+
return details::WrapCallback([&] {
|
|
173
|
+
CallbackInfo cbInfo(env, info);
|
|
174
|
+
T* instance = T::Unwrap(cbInfo.This().As<Object>());
|
|
175
|
+
(instance->*UnwrapCallback)(cbInfo);
|
|
176
|
+
return nullptr;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
120
180
|
template <typename T, typename Finalizer, typename Hint = void>
|
|
121
181
|
struct FinalizeData {
|
|
122
182
|
static inline
|
|
123
|
-
void Wrapper(napi_env env, void* data, void* finalizeHint) {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
183
|
+
void Wrapper(napi_env env, void* data, void* finalizeHint) noexcept {
|
|
184
|
+
WrapVoidCallback([&] {
|
|
185
|
+
FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
|
|
186
|
+
finalizeData->callback(Env(env), static_cast<T*>(data));
|
|
187
|
+
delete finalizeData;
|
|
188
|
+
});
|
|
127
189
|
}
|
|
128
190
|
|
|
129
191
|
static inline
|
|
130
|
-
void WrapperWithHint(napi_env env, void* data, void* finalizeHint) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
192
|
+
void WrapperWithHint(napi_env env, void* data, void* finalizeHint) noexcept {
|
|
193
|
+
WrapVoidCallback([&] {
|
|
194
|
+
FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
|
|
195
|
+
finalizeData->callback(Env(env), static_cast<T*>(data), finalizeData->hint);
|
|
196
|
+
delete finalizeData;
|
|
197
|
+
});
|
|
134
198
|
}
|
|
135
199
|
|
|
136
200
|
Finalizer callback;
|
|
137
201
|
Hint* hint;
|
|
138
202
|
};
|
|
139
203
|
|
|
140
|
-
#if (NAPI_VERSION > 3)
|
|
204
|
+
#if (NAPI_VERSION > 3 && !defined(__wasm32__))
|
|
141
205
|
template <typename ContextType=void,
|
|
142
206
|
typename Finalizer=std::function<void(Env, void*, ContextType*)>,
|
|
143
207
|
typename FinalizerDataType=void>
|
|
@@ -150,9 +214,6 @@ struct ThreadSafeFinalize {
|
|
|
150
214
|
ThreadSafeFinalize* finalizeData =
|
|
151
215
|
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
152
216
|
finalizeData->callback(Env(env));
|
|
153
|
-
if (finalizeData->tsfn) {
|
|
154
|
-
*finalizeData->tsfn = nullptr;
|
|
155
|
-
}
|
|
156
217
|
delete finalizeData;
|
|
157
218
|
}
|
|
158
219
|
|
|
@@ -166,9 +227,6 @@ struct ThreadSafeFinalize {
|
|
|
166
227
|
ThreadSafeFinalize* finalizeData =
|
|
167
228
|
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
168
229
|
finalizeData->callback(Env(env), finalizeData->data);
|
|
169
|
-
if (finalizeData->tsfn) {
|
|
170
|
-
*finalizeData->tsfn = nullptr;
|
|
171
|
-
}
|
|
172
230
|
delete finalizeData;
|
|
173
231
|
}
|
|
174
232
|
|
|
@@ -182,9 +240,6 @@ struct ThreadSafeFinalize {
|
|
|
182
240
|
ThreadSafeFinalize* finalizeData =
|
|
183
241
|
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
184
242
|
finalizeData->callback(Env(env), static_cast<ContextType*>(rawContext));
|
|
185
|
-
if (finalizeData->tsfn) {
|
|
186
|
-
*finalizeData->tsfn = nullptr;
|
|
187
|
-
}
|
|
188
243
|
delete finalizeData;
|
|
189
244
|
}
|
|
190
245
|
|
|
@@ -199,17 +254,13 @@ struct ThreadSafeFinalize {
|
|
|
199
254
|
static_cast<ThreadSafeFinalize*>(rawFinalizeData);
|
|
200
255
|
finalizeData->callback(Env(env), finalizeData->data,
|
|
201
256
|
static_cast<ContextType*>(rawContext));
|
|
202
|
-
if (finalizeData->tsfn) {
|
|
203
|
-
*finalizeData->tsfn = nullptr;
|
|
204
|
-
}
|
|
205
257
|
delete finalizeData;
|
|
206
258
|
}
|
|
207
259
|
|
|
208
260
|
FinalizerDataType* data;
|
|
209
261
|
Finalizer callback;
|
|
210
|
-
napi_threadsafe_function* tsfn;
|
|
211
262
|
};
|
|
212
|
-
#endif
|
|
263
|
+
#endif // NAPI_VERSION > 3 && !defined(__wasm32__)
|
|
213
264
|
|
|
214
265
|
template <typename Getter, typename Setter>
|
|
215
266
|
struct AccessorCallbackData {
|
|
@@ -251,6 +302,7 @@ struct AccessorCallbackData {
|
|
|
251
302
|
// Module registration
|
|
252
303
|
////////////////////////////////////////////////////////////////////////////////
|
|
253
304
|
|
|
305
|
+
// Register an add-on based on an initializer function.
|
|
254
306
|
#define NODE_API_MODULE(modname, regfunc) \
|
|
255
307
|
napi_value __napi_ ## regfunc(napi_env env, \
|
|
256
308
|
napi_value exports) { \
|
|
@@ -258,6 +310,20 @@ struct AccessorCallbackData {
|
|
|
258
310
|
} \
|
|
259
311
|
NAPI_MODULE(modname, __napi_ ## regfunc)
|
|
260
312
|
|
|
313
|
+
// Register an add-on based on a subclass of `Addon<T>` with a custom Node.js
|
|
314
|
+
// module name.
|
|
315
|
+
#define NODE_API_NAMED_ADDON(modname, classname) \
|
|
316
|
+
static napi_value __napi_ ## classname(napi_env env, \
|
|
317
|
+
napi_value exports) { \
|
|
318
|
+
return Napi::RegisterModule(env, exports, &classname::Init); \
|
|
319
|
+
} \
|
|
320
|
+
NAPI_MODULE(modname, __napi_ ## classname)
|
|
321
|
+
|
|
322
|
+
// Register an add-on based on a subclass of `Addon<T>` with the Node.js module
|
|
323
|
+
// name given by node-gyp from the `target_name` in binding.gyp.
|
|
324
|
+
#define NODE_API_ADDON(classname) \
|
|
325
|
+
NODE_API_NAMED_ADDON(NODE_GYP_MODULE_NAME, classname)
|
|
326
|
+
|
|
261
327
|
// Adapt the NAPI_MODULE registration function:
|
|
262
328
|
// - Wrap the arguments in NAPI wrappers.
|
|
263
329
|
// - Catch any NAPI errors and rethrow as JS exceptions.
|
|
@@ -319,6 +385,64 @@ inline Error Env::GetAndClearPendingException() {
|
|
|
319
385
|
return Error(_env, value);
|
|
320
386
|
}
|
|
321
387
|
|
|
388
|
+
inline Value Env::RunScript(const char* utf8script) {
|
|
389
|
+
String script = String::New(_env, utf8script);
|
|
390
|
+
return RunScript(script);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
inline Value Env::RunScript(const std::string& utf8script) {
|
|
394
|
+
return RunScript(utf8script.c_str());
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
inline Value Env::RunScript(String script) {
|
|
398
|
+
napi_value result;
|
|
399
|
+
napi_status status = napi_run_script(_env, script, &result);
|
|
400
|
+
NAPI_THROW_IF_FAILED(_env, status, Undefined());
|
|
401
|
+
return Value(_env, result);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
#if NAPI_VERSION > 5
|
|
405
|
+
template <typename T, Env::Finalizer<T> fini>
|
|
406
|
+
inline void Env::SetInstanceData(T* data) {
|
|
407
|
+
napi_status status =
|
|
408
|
+
napi_set_instance_data(_env, data, [](napi_env env, void* data, void*) {
|
|
409
|
+
fini(env, static_cast<T*>(data));
|
|
410
|
+
}, nullptr);
|
|
411
|
+
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
template <typename DataType,
|
|
415
|
+
typename HintType,
|
|
416
|
+
Napi::Env::FinalizerWithHint<DataType, HintType> fini>
|
|
417
|
+
inline void Env::SetInstanceData(DataType* data, HintType* hint) {
|
|
418
|
+
napi_status status =
|
|
419
|
+
napi_set_instance_data(_env, data,
|
|
420
|
+
[](napi_env env, void* data, void* hint) {
|
|
421
|
+
fini(env, static_cast<DataType*>(data), static_cast<HintType*>(hint));
|
|
422
|
+
}, hint);
|
|
423
|
+
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
template <typename T>
|
|
427
|
+
inline T* Env::GetInstanceData() {
|
|
428
|
+
void* data = nullptr;
|
|
429
|
+
|
|
430
|
+
napi_status status = napi_get_instance_data(_env, &data);
|
|
431
|
+
NAPI_THROW_IF_FAILED(_env, status, nullptr);
|
|
432
|
+
|
|
433
|
+
return static_cast<T*>(data);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
template <typename T> void Env::DefaultFini(Env, T* data) {
|
|
437
|
+
delete data;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
template <typename DataType, typename HintType>
|
|
441
|
+
void Env::DefaultFiniWithHint(Env, DataType* data, HintType*) {
|
|
442
|
+
delete data;
|
|
443
|
+
}
|
|
444
|
+
#endif // NAPI_VERSION > 5
|
|
445
|
+
|
|
322
446
|
////////////////////////////////////////////////////////////////////////////////
|
|
323
447
|
// Value class
|
|
324
448
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -383,14 +507,11 @@ inline bool Value::IsNumber() const {
|
|
|
383
507
|
return Type() == napi_number;
|
|
384
508
|
}
|
|
385
509
|
|
|
386
|
-
|
|
387
|
-
// Once it is no longer experimental guard with the NAPI_VERSION in which it is
|
|
388
|
-
// released instead.
|
|
389
|
-
#ifdef NAPI_EXPERIMENTAL
|
|
510
|
+
#if NAPI_VERSION > 5
|
|
390
511
|
inline bool Value::IsBigInt() const {
|
|
391
512
|
return Type() == napi_bigint;
|
|
392
513
|
}
|
|
393
|
-
#endif //
|
|
514
|
+
#endif // NAPI_VERSION > 5
|
|
394
515
|
|
|
395
516
|
#if (NAPI_VERSION > 4)
|
|
396
517
|
inline bool Value::IsDate() const {
|
|
@@ -621,10 +742,7 @@ inline double Number::DoubleValue() const {
|
|
|
621
742
|
return result;
|
|
622
743
|
}
|
|
623
744
|
|
|
624
|
-
|
|
625
|
-
// Once it is no longer experimental guard with the NAPI_VERSION in which it is
|
|
626
|
-
// released instead.
|
|
627
|
-
#ifdef NAPI_EXPERIMENTAL
|
|
745
|
+
#if NAPI_VERSION > 5
|
|
628
746
|
////////////////////////////////////////////////////////////////////////////////
|
|
629
747
|
// BigInt Class
|
|
630
748
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -685,7 +803,7 @@ inline void BigInt::ToWords(int* sign_bit, size_t* word_count, uint64_t* words)
|
|
|
685
803
|
_env, _value, sign_bit, word_count, words);
|
|
686
804
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
687
805
|
}
|
|
688
|
-
#endif //
|
|
806
|
+
#endif // NAPI_VERSION > 5
|
|
689
807
|
|
|
690
808
|
#if (NAPI_VERSION > 4)
|
|
691
809
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -1330,7 +1448,7 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env, size_t byteLength) {
|
|
|
1330
1448
|
napi_status status = napi_create_arraybuffer(env, byteLength, &data, &value);
|
|
1331
1449
|
NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
|
|
1332
1450
|
|
|
1333
|
-
return ArrayBuffer(env, value
|
|
1451
|
+
return ArrayBuffer(env, value);
|
|
1334
1452
|
}
|
|
1335
1453
|
|
|
1336
1454
|
inline ArrayBuffer ArrayBuffer::New(napi_env env,
|
|
@@ -1341,7 +1459,7 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
|
|
|
1341
1459
|
env, externalData, byteLength, nullptr, nullptr, &value);
|
|
1342
1460
|
NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
|
|
1343
1461
|
|
|
1344
|
-
return ArrayBuffer(env, value
|
|
1462
|
+
return ArrayBuffer(env, value);
|
|
1345
1463
|
}
|
|
1346
1464
|
|
|
1347
1465
|
template <typename Finalizer>
|
|
@@ -1364,7 +1482,7 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
|
|
|
1364
1482
|
NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
|
|
1365
1483
|
}
|
|
1366
1484
|
|
|
1367
|
-
return ArrayBuffer(env, value
|
|
1485
|
+
return ArrayBuffer(env, value);
|
|
1368
1486
|
}
|
|
1369
1487
|
|
|
1370
1488
|
template <typename Finalizer, typename Hint>
|
|
@@ -1388,38 +1506,28 @@ inline ArrayBuffer ArrayBuffer::New(napi_env env,
|
|
|
1388
1506
|
NAPI_THROW_IF_FAILED(env, status, ArrayBuffer());
|
|
1389
1507
|
}
|
|
1390
1508
|
|
|
1391
|
-
return ArrayBuffer(env, value
|
|
1509
|
+
return ArrayBuffer(env, value);
|
|
1392
1510
|
}
|
|
1393
1511
|
|
|
1394
|
-
inline ArrayBuffer::ArrayBuffer() : Object()
|
|
1512
|
+
inline ArrayBuffer::ArrayBuffer() : Object() {
|
|
1395
1513
|
}
|
|
1396
1514
|
|
|
1397
1515
|
inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value)
|
|
1398
|
-
: Object(env, value)
|
|
1399
|
-
}
|
|
1400
|
-
|
|
1401
|
-
inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value, void* data, size_t length)
|
|
1402
|
-
: Object(env, value), _data(data), _length(length) {
|
|
1516
|
+
: Object(env, value) {
|
|
1403
1517
|
}
|
|
1404
1518
|
|
|
1405
1519
|
inline void* ArrayBuffer::Data() {
|
|
1406
|
-
|
|
1407
|
-
|
|
1520
|
+
void* data;
|
|
1521
|
+
napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr);
|
|
1522
|
+
NAPI_THROW_IF_FAILED(_env, status, nullptr);
|
|
1523
|
+
return data;
|
|
1408
1524
|
}
|
|
1409
1525
|
|
|
1410
1526
|
inline size_t ArrayBuffer::ByteLength() {
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
inline void ArrayBuffer::EnsureInfo() const {
|
|
1416
|
-
// The ArrayBuffer instance may have been constructed from a napi_value whose
|
|
1417
|
-
// length/data are not yet known. Fetch and cache these values just once,
|
|
1418
|
-
// since they can never change during the lifetime of the ArrayBuffer.
|
|
1419
|
-
if (_data == nullptr) {
|
|
1420
|
-
napi_status status = napi_get_arraybuffer_info(_env, _value, &_data, &_length);
|
|
1421
|
-
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
1422
|
-
}
|
|
1527
|
+
size_t length;
|
|
1528
|
+
napi_status status = napi_get_arraybuffer_info(_env, _value, nullptr, &length);
|
|
1529
|
+
NAPI_THROW_IF_FAILED(_env, status, 0);
|
|
1530
|
+
return length;
|
|
1423
1531
|
}
|
|
1424
1532
|
|
|
1425
1533
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -1635,6 +1743,10 @@ inline uint8_t TypedArray::ElementSize() const {
|
|
|
1635
1743
|
case napi_float32_array:
|
|
1636
1744
|
return 4;
|
|
1637
1745
|
case napi_float64_array:
|
|
1746
|
+
#if (NAPI_VERSION > 5)
|
|
1747
|
+
case napi_bigint64_array:
|
|
1748
|
+
case napi_biguint64_array:
|
|
1749
|
+
#endif // (NAPI_VERSION > 5)
|
|
1638
1750
|
return 8;
|
|
1639
1751
|
default:
|
|
1640
1752
|
return 0;
|
|
@@ -1707,8 +1819,14 @@ inline TypedArrayOf<T>::TypedArrayOf() : TypedArray(), _data(nullptr) {
|
|
|
1707
1819
|
template <typename T>
|
|
1708
1820
|
inline TypedArrayOf<T>::TypedArrayOf(napi_env env, napi_value value)
|
|
1709
1821
|
: TypedArray(env, value), _data(nullptr) {
|
|
1710
|
-
napi_status status =
|
|
1711
|
-
|
|
1822
|
+
napi_status status = napi_ok;
|
|
1823
|
+
if (value != nullptr) {
|
|
1824
|
+
status = napi_get_typedarray_info(
|
|
1825
|
+
_env, _value, &_type, &_length, reinterpret_cast<void**>(&_data), nullptr, nullptr);
|
|
1826
|
+
} else {
|
|
1827
|
+
_type = TypedArrayTypeForPrimitiveType<T>();
|
|
1828
|
+
_length = 0;
|
|
1829
|
+
}
|
|
1712
1830
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
1713
1831
|
}
|
|
1714
1832
|
|
|
@@ -1766,6 +1884,46 @@ CreateFunction(napi_env env,
|
|
|
1766
1884
|
return status;
|
|
1767
1885
|
}
|
|
1768
1886
|
|
|
1887
|
+
template <Function::VoidCallback cb>
|
|
1888
|
+
inline Function Function::New(napi_env env, const char* utf8name, void* data) {
|
|
1889
|
+
napi_value result = nullptr;
|
|
1890
|
+
napi_status status = napi_create_function(env,
|
|
1891
|
+
utf8name,
|
|
1892
|
+
NAPI_AUTO_LENGTH,
|
|
1893
|
+
details::TemplatedVoidCallback<cb>,
|
|
1894
|
+
data,
|
|
1895
|
+
&result);
|
|
1896
|
+
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
1897
|
+
return Function(env, result);
|
|
1898
|
+
}
|
|
1899
|
+
|
|
1900
|
+
template <Function::Callback cb>
|
|
1901
|
+
inline Function Function::New(napi_env env, const char* utf8name, void* data) {
|
|
1902
|
+
napi_value result = nullptr;
|
|
1903
|
+
napi_status status = napi_create_function(env,
|
|
1904
|
+
utf8name,
|
|
1905
|
+
NAPI_AUTO_LENGTH,
|
|
1906
|
+
details::TemplatedCallback<cb>,
|
|
1907
|
+
data,
|
|
1908
|
+
&result);
|
|
1909
|
+
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
1910
|
+
return Function(env, result);
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
template <Function::VoidCallback cb>
|
|
1914
|
+
inline Function Function::New(napi_env env,
|
|
1915
|
+
const std::string& utf8name,
|
|
1916
|
+
void* data) {
|
|
1917
|
+
return Function::New<cb>(env, utf8name.c_str(), data);
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
template <Function::Callback cb>
|
|
1921
|
+
inline Function Function::New(napi_env env,
|
|
1922
|
+
const std::string& utf8name,
|
|
1923
|
+
void* data) {
|
|
1924
|
+
return Function::New<cb>(env, utf8name.c_str(), data);
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1769
1927
|
template <typename Callable>
|
|
1770
1928
|
inline Function Function::New(napi_env env,
|
|
1771
1929
|
Callable cb,
|
|
@@ -2037,12 +2195,19 @@ inline void Buffer<T>::EnsureInfo() const {
|
|
|
2037
2195
|
inline Error Error::New(napi_env env) {
|
|
2038
2196
|
napi_status status;
|
|
2039
2197
|
napi_value error = nullptr;
|
|
2040
|
-
|
|
2198
|
+
bool is_exception_pending;
|
|
2041
2199
|
const napi_extended_error_info* info;
|
|
2200
|
+
|
|
2201
|
+
// We must retrieve the last error info before doing anything else, because
|
|
2202
|
+
// doing anything else will replace the last error info.
|
|
2042
2203
|
status = napi_get_last_error_info(env, &info);
|
|
2043
2204
|
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info");
|
|
2044
2205
|
|
|
2045
|
-
|
|
2206
|
+
status = napi_is_exception_pending(env, &is_exception_pending);
|
|
2207
|
+
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending");
|
|
2208
|
+
|
|
2209
|
+
// A pending exception takes precedence over any internal error status.
|
|
2210
|
+
if (is_exception_pending) {
|
|
2046
2211
|
status = napi_get_and_clear_last_exception(env, &error);
|
|
2047
2212
|
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
|
|
2048
2213
|
}
|
|
@@ -2050,15 +2215,6 @@ inline Error Error::New(napi_env env) {
|
|
|
2050
2215
|
const char* error_message = info->error_message != nullptr ?
|
|
2051
2216
|
info->error_message : "Error in native callback";
|
|
2052
2217
|
|
|
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) {
|
|
2058
|
-
status = napi_get_and_clear_last_exception(env, &error);
|
|
2059
|
-
NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_and_clear_last_exception");
|
|
2060
|
-
}
|
|
2061
|
-
|
|
2062
2218
|
napi_value message;
|
|
2063
2219
|
status = napi_create_string_utf8(
|
|
2064
2220
|
env,
|
|
@@ -2120,7 +2276,7 @@ inline Error& Error::operator =(Error&& other) {
|
|
|
2120
2276
|
inline Error::Error(const Error& other) : ObjectReference(other) {
|
|
2121
2277
|
}
|
|
2122
2278
|
|
|
2123
|
-
inline Error& Error::operator =(Error& other) {
|
|
2279
|
+
inline Error& Error::operator =(const Error& other) {
|
|
2124
2280
|
Reset();
|
|
2125
2281
|
|
|
2126
2282
|
_env = other.Env();
|
|
@@ -2732,6 +2888,91 @@ inline void CallbackInfo::SetData(void* data) {
|
|
|
2732
2888
|
// PropertyDescriptor class
|
|
2733
2889
|
////////////////////////////////////////////////////////////////////////////////
|
|
2734
2890
|
|
|
2891
|
+
template <typename PropertyDescriptor::GetterCallback Getter>
|
|
2892
|
+
PropertyDescriptor
|
|
2893
|
+
PropertyDescriptor::Accessor(const char* utf8name,
|
|
2894
|
+
napi_property_attributes attributes,
|
|
2895
|
+
void* data) {
|
|
2896
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
2897
|
+
|
|
2898
|
+
desc.utf8name = utf8name;
|
|
2899
|
+
desc.getter = details::TemplatedCallback<Getter>;
|
|
2900
|
+
desc.attributes = attributes;
|
|
2901
|
+
desc.data = data;
|
|
2902
|
+
|
|
2903
|
+
return desc;
|
|
2904
|
+
}
|
|
2905
|
+
|
|
2906
|
+
template <typename PropertyDescriptor::GetterCallback Getter>
|
|
2907
|
+
PropertyDescriptor
|
|
2908
|
+
PropertyDescriptor::Accessor(const std::string& utf8name,
|
|
2909
|
+
napi_property_attributes attributes,
|
|
2910
|
+
void* data) {
|
|
2911
|
+
return Accessor<Getter>(utf8name.c_str(), attributes, data);
|
|
2912
|
+
}
|
|
2913
|
+
|
|
2914
|
+
template <typename PropertyDescriptor::GetterCallback Getter>
|
|
2915
|
+
PropertyDescriptor
|
|
2916
|
+
PropertyDescriptor::Accessor(Name name,
|
|
2917
|
+
napi_property_attributes attributes,
|
|
2918
|
+
void* data) {
|
|
2919
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
2920
|
+
|
|
2921
|
+
desc.name = name;
|
|
2922
|
+
desc.getter = details::TemplatedCallback<Getter>;
|
|
2923
|
+
desc.attributes = attributes;
|
|
2924
|
+
desc.data = data;
|
|
2925
|
+
|
|
2926
|
+
return desc;
|
|
2927
|
+
}
|
|
2928
|
+
|
|
2929
|
+
template <
|
|
2930
|
+
typename PropertyDescriptor::GetterCallback Getter,
|
|
2931
|
+
typename PropertyDescriptor::SetterCallback Setter>
|
|
2932
|
+
PropertyDescriptor
|
|
2933
|
+
PropertyDescriptor::Accessor(const char* utf8name,
|
|
2934
|
+
napi_property_attributes attributes,
|
|
2935
|
+
void* data) {
|
|
2936
|
+
|
|
2937
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
2938
|
+
|
|
2939
|
+
desc.utf8name = utf8name;
|
|
2940
|
+
desc.getter = details::TemplatedCallback<Getter>;
|
|
2941
|
+
desc.setter = details::TemplatedVoidCallback<Setter>;
|
|
2942
|
+
desc.attributes = attributes;
|
|
2943
|
+
desc.data = data;
|
|
2944
|
+
|
|
2945
|
+
return desc;
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2948
|
+
template <
|
|
2949
|
+
typename PropertyDescriptor::GetterCallback Getter,
|
|
2950
|
+
typename PropertyDescriptor::SetterCallback Setter>
|
|
2951
|
+
PropertyDescriptor
|
|
2952
|
+
PropertyDescriptor::Accessor(const std::string& utf8name,
|
|
2953
|
+
napi_property_attributes attributes,
|
|
2954
|
+
void* data) {
|
|
2955
|
+
return Accessor<Getter, Setter>(utf8name.c_str(), attributes, data);
|
|
2956
|
+
}
|
|
2957
|
+
|
|
2958
|
+
template <
|
|
2959
|
+
typename PropertyDescriptor::GetterCallback Getter,
|
|
2960
|
+
typename PropertyDescriptor::SetterCallback Setter>
|
|
2961
|
+
PropertyDescriptor
|
|
2962
|
+
PropertyDescriptor::Accessor(Name name,
|
|
2963
|
+
napi_property_attributes attributes,
|
|
2964
|
+
void* data) {
|
|
2965
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
2966
|
+
|
|
2967
|
+
desc.name = name;
|
|
2968
|
+
desc.getter = details::TemplatedCallback<Getter>;
|
|
2969
|
+
desc.setter = details::TemplatedVoidCallback<Setter>;
|
|
2970
|
+
desc.attributes = attributes;
|
|
2971
|
+
desc.data = data;
|
|
2972
|
+
|
|
2973
|
+
return desc;
|
|
2974
|
+
}
|
|
2975
|
+
|
|
2735
2976
|
template <typename Getter>
|
|
2736
2977
|
inline PropertyDescriptor
|
|
2737
2978
|
PropertyDescriptor::Accessor(Napi::Env env,
|
|
@@ -2959,137 +3200,453 @@ inline PropertyDescriptor::operator const napi_property_descriptor&() const {
|
|
|
2959
3200
|
}
|
|
2960
3201
|
|
|
2961
3202
|
////////////////////////////////////////////////////////////////////////////////
|
|
2962
|
-
//
|
|
3203
|
+
// InstanceWrap<T> class
|
|
2963
3204
|
////////////////////////////////////////////////////////////////////////////////
|
|
2964
3205
|
|
|
2965
3206
|
template <typename T>
|
|
2966
|
-
inline
|
|
2967
|
-
|
|
2968
|
-
|
|
2969
|
-
napi_status status;
|
|
2970
|
-
napi_ref ref;
|
|
2971
|
-
T* instance = static_cast<T*>(this);
|
|
2972
|
-
status = napi_wrap(env, wrapper, instance, FinalizeCallback, nullptr, &ref);
|
|
2973
|
-
NAPI_THROW_IF_FAILED_VOID(env, status);
|
|
2974
|
-
|
|
2975
|
-
Reference<Object>* instanceRef = instance;
|
|
2976
|
-
*instanceRef = Reference<Object>(env, ref);
|
|
2977
|
-
}
|
|
2978
|
-
|
|
2979
|
-
template<typename T>
|
|
2980
|
-
inline ObjectWrap<T>::~ObjectWrap() {}
|
|
2981
|
-
|
|
2982
|
-
template<typename T>
|
|
2983
|
-
inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
|
|
2984
|
-
T* unwrapped;
|
|
2985
|
-
napi_status status = napi_unwrap(wrapper.Env(), wrapper, reinterpret_cast<void**>(&unwrapped));
|
|
2986
|
-
NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
|
|
2987
|
-
return unwrapped;
|
|
2988
|
-
}
|
|
2989
|
-
|
|
2990
|
-
template <typename T>
|
|
2991
|
-
inline Function
|
|
2992
|
-
ObjectWrap<T>::DefineClass(Napi::Env env,
|
|
2993
|
-
const char* utf8name,
|
|
2994
|
-
const size_t props_count,
|
|
2995
|
-
const napi_property_descriptor* descriptors,
|
|
2996
|
-
void* data) {
|
|
3207
|
+
inline void InstanceWrap<T>::AttachPropData(napi_env env,
|
|
3208
|
+
napi_value value,
|
|
3209
|
+
const napi_property_descriptor* prop) {
|
|
2997
3210
|
napi_status status;
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
// We copy the descriptors to a local array because before defining the class
|
|
3001
|
-
// we must replace static method property descriptors with value property
|
|
3002
|
-
// descriptors such that the value is a function-valued `napi_value` created
|
|
3003
|
-
// with `CreateFunction()`.
|
|
3004
|
-
//
|
|
3005
|
-
// This replacement could be made for instance methods as well, but V8 aborts
|
|
3006
|
-
// if we do that, because it expects methods defined on the prototype template
|
|
3007
|
-
// to have `FunctionTemplate`s.
|
|
3008
|
-
for (size_t index = 0; index < props_count; index++) {
|
|
3009
|
-
props[index] = descriptors[index];
|
|
3010
|
-
napi_property_descriptor* prop = &props[index];
|
|
3011
|
-
if (prop->method == T::StaticMethodCallbackWrapper) {
|
|
3012
|
-
status = CreateFunction(env,
|
|
3013
|
-
utf8name,
|
|
3014
|
-
prop->method,
|
|
3015
|
-
static_cast<StaticMethodCallbackData*>(prop->data),
|
|
3016
|
-
&(prop->value));
|
|
3017
|
-
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
3018
|
-
prop->method = nullptr;
|
|
3019
|
-
prop->data = nullptr;
|
|
3020
|
-
} else if (prop->method == T::StaticVoidMethodCallbackWrapper) {
|
|
3021
|
-
status = CreateFunction(env,
|
|
3022
|
-
utf8name,
|
|
3023
|
-
prop->method,
|
|
3024
|
-
static_cast<StaticVoidMethodCallbackData*>(prop->data),
|
|
3025
|
-
&(prop->value));
|
|
3026
|
-
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
3027
|
-
prop->method = nullptr;
|
|
3028
|
-
prop->data = nullptr;
|
|
3029
|
-
}
|
|
3030
|
-
}
|
|
3031
|
-
|
|
3032
|
-
napi_value value;
|
|
3033
|
-
status = napi_define_class(env,
|
|
3034
|
-
utf8name,
|
|
3035
|
-
NAPI_AUTO_LENGTH,
|
|
3036
|
-
T::ConstructorCallbackWrapper,
|
|
3037
|
-
data,
|
|
3038
|
-
props_count,
|
|
3039
|
-
props.data(),
|
|
3040
|
-
&value);
|
|
3041
|
-
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
3042
|
-
|
|
3043
|
-
// After defining the class we iterate once more over the property descriptors
|
|
3044
|
-
// and attach the data associated with accessors and instance methods to the
|
|
3045
|
-
// newly created JavaScript class.
|
|
3046
|
-
for (size_t idx = 0; idx < props_count; idx++) {
|
|
3047
|
-
const napi_property_descriptor* prop = &props[idx];
|
|
3048
|
-
|
|
3049
|
-
if (prop->getter == T::StaticGetterCallbackWrapper ||
|
|
3050
|
-
prop->setter == T::StaticSetterCallbackWrapper) {
|
|
3211
|
+
if (prop->method != nullptr && !(prop->attributes & napi_static)) {
|
|
3212
|
+
if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
|
|
3051
3213
|
status = Napi::details::AttachData(env,
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3214
|
+
value,
|
|
3215
|
+
static_cast<InstanceVoidMethodCallbackData*>(prop->data));
|
|
3216
|
+
NAPI_THROW_IF_FAILED_VOID(env, status);
|
|
3217
|
+
} else if (prop->method == T::InstanceMethodCallbackWrapper) {
|
|
3218
|
+
status = Napi::details::AttachData(env,
|
|
3219
|
+
value,
|
|
3220
|
+
static_cast<InstanceMethodCallbackData*>(prop->data));
|
|
3221
|
+
NAPI_THROW_IF_FAILED_VOID(env, status);
|
|
3055
3222
|
} else if (prop->getter == T::InstanceGetterCallbackWrapper ||
|
|
3056
3223
|
prop->setter == T::InstanceSetterCallbackWrapper) {
|
|
3057
3224
|
status = Napi::details::AttachData(env,
|
|
3058
3225
|
value,
|
|
3059
3226
|
static_cast<InstanceAccessorCallbackData*>(prop->data));
|
|
3060
|
-
|
|
3061
|
-
} else if (prop->method != nullptr && !(prop->attributes & napi_static)) {
|
|
3062
|
-
if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
|
|
3063
|
-
status = Napi::details::AttachData(env,
|
|
3064
|
-
value,
|
|
3065
|
-
static_cast<InstanceVoidMethodCallbackData*>(prop->data));
|
|
3066
|
-
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
3067
|
-
} else if (prop->method == T::InstanceMethodCallbackWrapper) {
|
|
3068
|
-
status = Napi::details::AttachData(env,
|
|
3069
|
-
value,
|
|
3070
|
-
static_cast<InstanceMethodCallbackData*>(prop->data));
|
|
3071
|
-
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
3072
|
-
}
|
|
3227
|
+
NAPI_THROW_IF_FAILED_VOID(env, status);
|
|
3073
3228
|
}
|
|
3074
3229
|
}
|
|
3075
|
-
|
|
3076
|
-
return Function(env, value);
|
|
3077
3230
|
}
|
|
3078
3231
|
|
|
3079
3232
|
template <typename T>
|
|
3080
|
-
inline
|
|
3081
|
-
Napi::Env env,
|
|
3233
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
|
|
3082
3234
|
const char* utf8name,
|
|
3083
|
-
|
|
3235
|
+
InstanceVoidMethodCallback method,
|
|
3236
|
+
napi_property_attributes attributes,
|
|
3084
3237
|
void* data) {
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
properties.size(),
|
|
3088
|
-
reinterpret_cast<const napi_property_descriptor*>(properties.begin()),
|
|
3089
|
-
data);
|
|
3090
|
-
}
|
|
3238
|
+
InstanceVoidMethodCallbackData* callbackData =
|
|
3239
|
+
new InstanceVoidMethodCallbackData({ method, data});
|
|
3091
3240
|
|
|
3092
|
-
|
|
3241
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3242
|
+
desc.utf8name = utf8name;
|
|
3243
|
+
desc.method = T::InstanceVoidMethodCallbackWrapper;
|
|
3244
|
+
desc.data = callbackData;
|
|
3245
|
+
desc.attributes = attributes;
|
|
3246
|
+
return desc;
|
|
3247
|
+
}
|
|
3248
|
+
|
|
3249
|
+
template <typename T>
|
|
3250
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
|
|
3251
|
+
const char* utf8name,
|
|
3252
|
+
InstanceMethodCallback method,
|
|
3253
|
+
napi_property_attributes attributes,
|
|
3254
|
+
void* data) {
|
|
3255
|
+
InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
|
|
3256
|
+
|
|
3257
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3258
|
+
desc.utf8name = utf8name;
|
|
3259
|
+
desc.method = T::InstanceMethodCallbackWrapper;
|
|
3260
|
+
desc.data = callbackData;
|
|
3261
|
+
desc.attributes = attributes;
|
|
3262
|
+
return desc;
|
|
3263
|
+
}
|
|
3264
|
+
|
|
3265
|
+
template <typename T>
|
|
3266
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
|
|
3267
|
+
Symbol name,
|
|
3268
|
+
InstanceVoidMethodCallback method,
|
|
3269
|
+
napi_property_attributes attributes,
|
|
3270
|
+
void* data) {
|
|
3271
|
+
InstanceVoidMethodCallbackData* callbackData =
|
|
3272
|
+
new InstanceVoidMethodCallbackData({ method, data});
|
|
3273
|
+
|
|
3274
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3275
|
+
desc.name = name;
|
|
3276
|
+
desc.method = T::InstanceVoidMethodCallbackWrapper;
|
|
3277
|
+
desc.data = callbackData;
|
|
3278
|
+
desc.attributes = attributes;
|
|
3279
|
+
return desc;
|
|
3280
|
+
}
|
|
3281
|
+
|
|
3282
|
+
template <typename T>
|
|
3283
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
|
|
3284
|
+
Symbol name,
|
|
3285
|
+
InstanceMethodCallback method,
|
|
3286
|
+
napi_property_attributes attributes,
|
|
3287
|
+
void* data) {
|
|
3288
|
+
InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
|
|
3289
|
+
|
|
3290
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3291
|
+
desc.name = name;
|
|
3292
|
+
desc.method = T::InstanceMethodCallbackWrapper;
|
|
3293
|
+
desc.data = callbackData;
|
|
3294
|
+
desc.attributes = attributes;
|
|
3295
|
+
return desc;
|
|
3296
|
+
}
|
|
3297
|
+
|
|
3298
|
+
template <typename T>
|
|
3299
|
+
template <typename InstanceWrap<T>::InstanceVoidMethodCallback method>
|
|
3300
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
|
|
3301
|
+
const char* utf8name,
|
|
3302
|
+
napi_property_attributes attributes,
|
|
3303
|
+
void* data) {
|
|
3304
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3305
|
+
desc.utf8name = utf8name;
|
|
3306
|
+
desc.method = details::TemplatedInstanceVoidCallback<T, method>;
|
|
3307
|
+
desc.data = data;
|
|
3308
|
+
desc.attributes = attributes;
|
|
3309
|
+
return desc;
|
|
3310
|
+
}
|
|
3311
|
+
|
|
3312
|
+
template <typename T>
|
|
3313
|
+
template <typename InstanceWrap<T>::InstanceMethodCallback method>
|
|
3314
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
|
|
3315
|
+
const char* utf8name,
|
|
3316
|
+
napi_property_attributes attributes,
|
|
3317
|
+
void* data) {
|
|
3318
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3319
|
+
desc.utf8name = utf8name;
|
|
3320
|
+
desc.method = details::TemplatedInstanceCallback<T, method>;
|
|
3321
|
+
desc.data = data;
|
|
3322
|
+
desc.attributes = attributes;
|
|
3323
|
+
return desc;
|
|
3324
|
+
}
|
|
3325
|
+
|
|
3326
|
+
template <typename T>
|
|
3327
|
+
template <typename InstanceWrap<T>::InstanceVoidMethodCallback method>
|
|
3328
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
|
|
3329
|
+
Symbol name,
|
|
3330
|
+
napi_property_attributes attributes,
|
|
3331
|
+
void* data) {
|
|
3332
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3333
|
+
desc.name = name;
|
|
3334
|
+
desc.method = details::TemplatedInstanceVoidCallback<T, method>;
|
|
3335
|
+
desc.data = data;
|
|
3336
|
+
desc.attributes = attributes;
|
|
3337
|
+
return desc;
|
|
3338
|
+
}
|
|
3339
|
+
|
|
3340
|
+
template <typename T>
|
|
3341
|
+
template <typename InstanceWrap<T>::InstanceMethodCallback method>
|
|
3342
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
|
|
3343
|
+
Symbol name,
|
|
3344
|
+
napi_property_attributes attributes,
|
|
3345
|
+
void* data) {
|
|
3346
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3347
|
+
desc.name = name;
|
|
3348
|
+
desc.method = details::TemplatedInstanceCallback<T, method>;
|
|
3349
|
+
desc.data = data;
|
|
3350
|
+
desc.attributes = attributes;
|
|
3351
|
+
return desc;
|
|
3352
|
+
}
|
|
3353
|
+
|
|
3354
|
+
template <typename T>
|
|
3355
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
|
|
3356
|
+
const char* utf8name,
|
|
3357
|
+
InstanceGetterCallback getter,
|
|
3358
|
+
InstanceSetterCallback setter,
|
|
3359
|
+
napi_property_attributes attributes,
|
|
3360
|
+
void* data) {
|
|
3361
|
+
InstanceAccessorCallbackData* callbackData =
|
|
3362
|
+
new InstanceAccessorCallbackData({ getter, setter, data });
|
|
3363
|
+
|
|
3364
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3365
|
+
desc.utf8name = utf8name;
|
|
3366
|
+
desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
|
|
3367
|
+
desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
|
|
3368
|
+
desc.data = callbackData;
|
|
3369
|
+
desc.attributes = attributes;
|
|
3370
|
+
return desc;
|
|
3371
|
+
}
|
|
3372
|
+
|
|
3373
|
+
template <typename T>
|
|
3374
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
|
|
3375
|
+
Symbol name,
|
|
3376
|
+
InstanceGetterCallback getter,
|
|
3377
|
+
InstanceSetterCallback setter,
|
|
3378
|
+
napi_property_attributes attributes,
|
|
3379
|
+
void* data) {
|
|
3380
|
+
InstanceAccessorCallbackData* callbackData =
|
|
3381
|
+
new InstanceAccessorCallbackData({ getter, setter, data });
|
|
3382
|
+
|
|
3383
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3384
|
+
desc.name = name;
|
|
3385
|
+
desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
|
|
3386
|
+
desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
|
|
3387
|
+
desc.data = callbackData;
|
|
3388
|
+
desc.attributes = attributes;
|
|
3389
|
+
return desc;
|
|
3390
|
+
}
|
|
3391
|
+
|
|
3392
|
+
template <typename T>
|
|
3393
|
+
template <typename InstanceWrap<T>::InstanceGetterCallback getter,
|
|
3394
|
+
typename InstanceWrap<T>::InstanceSetterCallback setter>
|
|
3395
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
|
|
3396
|
+
const char* utf8name,
|
|
3397
|
+
napi_property_attributes attributes,
|
|
3398
|
+
void* data) {
|
|
3399
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3400
|
+
desc.utf8name = utf8name;
|
|
3401
|
+
desc.getter = details::TemplatedInstanceCallback<T, getter>;
|
|
3402
|
+
desc.setter = This::WrapSetter(This::SetterTag<setter>());
|
|
3403
|
+
desc.data = data;
|
|
3404
|
+
desc.attributes = attributes;
|
|
3405
|
+
return desc;
|
|
3406
|
+
}
|
|
3407
|
+
|
|
3408
|
+
template <typename T>
|
|
3409
|
+
template <typename InstanceWrap<T>::InstanceGetterCallback getter,
|
|
3410
|
+
typename InstanceWrap<T>::InstanceSetterCallback setter>
|
|
3411
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
|
|
3412
|
+
Symbol name,
|
|
3413
|
+
napi_property_attributes attributes,
|
|
3414
|
+
void* data) {
|
|
3415
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3416
|
+
desc.name = name;
|
|
3417
|
+
desc.getter = details::TemplatedInstanceCallback<T, getter>;
|
|
3418
|
+
desc.setter = This::WrapSetter(This::SetterTag<setter>());
|
|
3419
|
+
desc.data = data;
|
|
3420
|
+
desc.attributes = attributes;
|
|
3421
|
+
return desc;
|
|
3422
|
+
}
|
|
3423
|
+
|
|
3424
|
+
template <typename T>
|
|
3425
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceValue(
|
|
3426
|
+
const char* utf8name,
|
|
3427
|
+
Napi::Value value,
|
|
3428
|
+
napi_property_attributes attributes) {
|
|
3429
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3430
|
+
desc.utf8name = utf8name;
|
|
3431
|
+
desc.value = value;
|
|
3432
|
+
desc.attributes = attributes;
|
|
3433
|
+
return desc;
|
|
3434
|
+
}
|
|
3435
|
+
|
|
3436
|
+
template <typename T>
|
|
3437
|
+
inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceValue(
|
|
3438
|
+
Symbol name,
|
|
3439
|
+
Napi::Value value,
|
|
3440
|
+
napi_property_attributes attributes) {
|
|
3441
|
+
napi_property_descriptor desc = napi_property_descriptor();
|
|
3442
|
+
desc.name = name;
|
|
3443
|
+
desc.value = value;
|
|
3444
|
+
desc.attributes = attributes;
|
|
3445
|
+
return desc;
|
|
3446
|
+
}
|
|
3447
|
+
|
|
3448
|
+
template <typename T>
|
|
3449
|
+
inline napi_value InstanceWrap<T>::InstanceVoidMethodCallbackWrapper(
|
|
3450
|
+
napi_env env,
|
|
3451
|
+
napi_callback_info info) {
|
|
3452
|
+
return details::WrapCallback([&] {
|
|
3453
|
+
CallbackInfo callbackInfo(env, info);
|
|
3454
|
+
InstanceVoidMethodCallbackData* callbackData =
|
|
3455
|
+
reinterpret_cast<InstanceVoidMethodCallbackData*>(callbackInfo.Data());
|
|
3456
|
+
callbackInfo.SetData(callbackData->data);
|
|
3457
|
+
T* instance = T::Unwrap(callbackInfo.This().As<Object>());
|
|
3458
|
+
auto cb = callbackData->callback;
|
|
3459
|
+
(instance->*cb)(callbackInfo);
|
|
3460
|
+
return nullptr;
|
|
3461
|
+
});
|
|
3462
|
+
}
|
|
3463
|
+
|
|
3464
|
+
template <typename T>
|
|
3465
|
+
inline napi_value InstanceWrap<T>::InstanceMethodCallbackWrapper(
|
|
3466
|
+
napi_env env,
|
|
3467
|
+
napi_callback_info info) {
|
|
3468
|
+
return details::WrapCallback([&] {
|
|
3469
|
+
CallbackInfo callbackInfo(env, info);
|
|
3470
|
+
InstanceMethodCallbackData* callbackData =
|
|
3471
|
+
reinterpret_cast<InstanceMethodCallbackData*>(callbackInfo.Data());
|
|
3472
|
+
callbackInfo.SetData(callbackData->data);
|
|
3473
|
+
T* instance = T::Unwrap(callbackInfo.This().As<Object>());
|
|
3474
|
+
auto cb = callbackData->callback;
|
|
3475
|
+
return (instance->*cb)(callbackInfo);
|
|
3476
|
+
});
|
|
3477
|
+
}
|
|
3478
|
+
|
|
3479
|
+
template <typename T>
|
|
3480
|
+
inline napi_value InstanceWrap<T>::InstanceGetterCallbackWrapper(
|
|
3481
|
+
napi_env env,
|
|
3482
|
+
napi_callback_info info) {
|
|
3483
|
+
return details::WrapCallback([&] {
|
|
3484
|
+
CallbackInfo callbackInfo(env, info);
|
|
3485
|
+
InstanceAccessorCallbackData* callbackData =
|
|
3486
|
+
reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
|
|
3487
|
+
callbackInfo.SetData(callbackData->data);
|
|
3488
|
+
T* instance = T::Unwrap(callbackInfo.This().As<Object>());
|
|
3489
|
+
auto cb = callbackData->getterCallback;
|
|
3490
|
+
return (instance->*cb)(callbackInfo);
|
|
3491
|
+
});
|
|
3492
|
+
}
|
|
3493
|
+
|
|
3494
|
+
template <typename T>
|
|
3495
|
+
inline napi_value InstanceWrap<T>::InstanceSetterCallbackWrapper(
|
|
3496
|
+
napi_env env,
|
|
3497
|
+
napi_callback_info info) {
|
|
3498
|
+
return details::WrapCallback([&] {
|
|
3499
|
+
CallbackInfo callbackInfo(env, info);
|
|
3500
|
+
InstanceAccessorCallbackData* callbackData =
|
|
3501
|
+
reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
|
|
3502
|
+
callbackInfo.SetData(callbackData->data);
|
|
3503
|
+
T* instance = T::Unwrap(callbackInfo.This().As<Object>());
|
|
3504
|
+
auto cb = callbackData->setterCallback;
|
|
3505
|
+
(instance->*cb)(callbackInfo, callbackInfo[0]);
|
|
3506
|
+
return nullptr;
|
|
3507
|
+
});
|
|
3508
|
+
}
|
|
3509
|
+
|
|
3510
|
+
template <typename T>
|
|
3511
|
+
template <typename InstanceWrap<T>::InstanceSetterCallback method>
|
|
3512
|
+
inline napi_value InstanceWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
|
|
3513
|
+
return details::WrapCallback([&] {
|
|
3514
|
+
const CallbackInfo cbInfo(env, info);
|
|
3515
|
+
T* instance = T::Unwrap(cbInfo.This().As<Object>());
|
|
3516
|
+
(instance->*method)(cbInfo, cbInfo[0]);
|
|
3517
|
+
return nullptr;
|
|
3518
|
+
});
|
|
3519
|
+
}
|
|
3520
|
+
|
|
3521
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
3522
|
+
// ObjectWrap<T> class
|
|
3523
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
3524
|
+
|
|
3525
|
+
template <typename T>
|
|
3526
|
+
inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
|
|
3527
|
+
napi_env env = callbackInfo.Env();
|
|
3528
|
+
napi_value wrapper = callbackInfo.This();
|
|
3529
|
+
napi_status status;
|
|
3530
|
+
napi_ref ref;
|
|
3531
|
+
T* instance = static_cast<T*>(this);
|
|
3532
|
+
status = napi_wrap(env, wrapper, instance, FinalizeCallback, nullptr, &ref);
|
|
3533
|
+
NAPI_THROW_IF_FAILED_VOID(env, status);
|
|
3534
|
+
|
|
3535
|
+
Reference<Object>* instanceRef = instance;
|
|
3536
|
+
*instanceRef = Reference<Object>(env, ref);
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
template <typename T>
|
|
3540
|
+
inline ObjectWrap<T>::~ObjectWrap() {
|
|
3541
|
+
// If the JS object still exists at this point, remove the finalizer added
|
|
3542
|
+
// through `napi_wrap()`.
|
|
3543
|
+
if (!IsEmpty()) {
|
|
3544
|
+
Object object = Value();
|
|
3545
|
+
// It is not valid to call `napi_remove_wrap()` with an empty `object`.
|
|
3546
|
+
// This happens e.g. during garbage collection.
|
|
3547
|
+
if (!object.IsEmpty() && _construction_failed) {
|
|
3548
|
+
napi_remove_wrap(Env(), object, nullptr);
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
}
|
|
3552
|
+
|
|
3553
|
+
template<typename T>
|
|
3554
|
+
inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
|
|
3555
|
+
T* unwrapped;
|
|
3556
|
+
napi_status status = napi_unwrap(wrapper.Env(), wrapper, reinterpret_cast<void**>(&unwrapped));
|
|
3557
|
+
NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
|
|
3558
|
+
return unwrapped;
|
|
3559
|
+
}
|
|
3560
|
+
|
|
3561
|
+
template <typename T>
|
|
3562
|
+
inline Function
|
|
3563
|
+
ObjectWrap<T>::DefineClass(Napi::Env env,
|
|
3564
|
+
const char* utf8name,
|
|
3565
|
+
const size_t props_count,
|
|
3566
|
+
const napi_property_descriptor* descriptors,
|
|
3567
|
+
void* data) {
|
|
3568
|
+
napi_status status;
|
|
3569
|
+
std::vector<napi_property_descriptor> props(props_count);
|
|
3570
|
+
|
|
3571
|
+
// We copy the descriptors to a local array because before defining the class
|
|
3572
|
+
// we must replace static method property descriptors with value property
|
|
3573
|
+
// descriptors such that the value is a function-valued `napi_value` created
|
|
3574
|
+
// with `CreateFunction()`.
|
|
3575
|
+
//
|
|
3576
|
+
// This replacement could be made for instance methods as well, but V8 aborts
|
|
3577
|
+
// if we do that, because it expects methods defined on the prototype template
|
|
3578
|
+
// to have `FunctionTemplate`s.
|
|
3579
|
+
for (size_t index = 0; index < props_count; index++) {
|
|
3580
|
+
props[index] = descriptors[index];
|
|
3581
|
+
napi_property_descriptor* prop = &props[index];
|
|
3582
|
+
if (prop->method == T::StaticMethodCallbackWrapper) {
|
|
3583
|
+
status = CreateFunction(env,
|
|
3584
|
+
utf8name,
|
|
3585
|
+
prop->method,
|
|
3586
|
+
static_cast<StaticMethodCallbackData*>(prop->data),
|
|
3587
|
+
&(prop->value));
|
|
3588
|
+
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
3589
|
+
prop->method = nullptr;
|
|
3590
|
+
prop->data = nullptr;
|
|
3591
|
+
} else if (prop->method == T::StaticVoidMethodCallbackWrapper) {
|
|
3592
|
+
status = CreateFunction(env,
|
|
3593
|
+
utf8name,
|
|
3594
|
+
prop->method,
|
|
3595
|
+
static_cast<StaticVoidMethodCallbackData*>(prop->data),
|
|
3596
|
+
&(prop->value));
|
|
3597
|
+
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
3598
|
+
prop->method = nullptr;
|
|
3599
|
+
prop->data = nullptr;
|
|
3600
|
+
}
|
|
3601
|
+
}
|
|
3602
|
+
|
|
3603
|
+
napi_value value;
|
|
3604
|
+
status = napi_define_class(env,
|
|
3605
|
+
utf8name,
|
|
3606
|
+
NAPI_AUTO_LENGTH,
|
|
3607
|
+
T::ConstructorCallbackWrapper,
|
|
3608
|
+
data,
|
|
3609
|
+
props_count,
|
|
3610
|
+
props.data(),
|
|
3611
|
+
&value);
|
|
3612
|
+
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
3613
|
+
|
|
3614
|
+
// After defining the class we iterate once more over the property descriptors
|
|
3615
|
+
// and attach the data associated with accessors and instance methods to the
|
|
3616
|
+
// newly created JavaScript class.
|
|
3617
|
+
for (size_t idx = 0; idx < props_count; idx++) {
|
|
3618
|
+
const napi_property_descriptor* prop = &props[idx];
|
|
3619
|
+
|
|
3620
|
+
if (prop->getter == T::StaticGetterCallbackWrapper ||
|
|
3621
|
+
prop->setter == T::StaticSetterCallbackWrapper) {
|
|
3622
|
+
status = Napi::details::AttachData(env,
|
|
3623
|
+
value,
|
|
3624
|
+
static_cast<StaticAccessorCallbackData*>(prop->data));
|
|
3625
|
+
NAPI_THROW_IF_FAILED(env, status, Function());
|
|
3626
|
+
} else {
|
|
3627
|
+
// InstanceWrap<T>::AttachPropData is responsible for attaching the data
|
|
3628
|
+
// of instance methods and accessors.
|
|
3629
|
+
T::AttachPropData(env, value, prop);
|
|
3630
|
+
}
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3633
|
+
return Function(env, value);
|
|
3634
|
+
}
|
|
3635
|
+
|
|
3636
|
+
template <typename T>
|
|
3637
|
+
inline Function ObjectWrap<T>::DefineClass(
|
|
3638
|
+
Napi::Env env,
|
|
3639
|
+
const char* utf8name,
|
|
3640
|
+
const std::initializer_list<ClassPropertyDescriptor<T>>& properties,
|
|
3641
|
+
void* data) {
|
|
3642
|
+
return DefineClass(env,
|
|
3643
|
+
utf8name,
|
|
3644
|
+
properties.size(),
|
|
3645
|
+
reinterpret_cast<const napi_property_descriptor*>(properties.begin()),
|
|
3646
|
+
data);
|
|
3647
|
+
}
|
|
3648
|
+
|
|
3649
|
+
template <typename T>
|
|
3093
3650
|
inline Function ObjectWrap<T>::DefineClass(
|
|
3094
3651
|
Napi::Env env,
|
|
3095
3652
|
const char* utf8name,
|
|
@@ -3167,188 +3724,148 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
|
|
|
3167
3724
|
}
|
|
3168
3725
|
|
|
3169
3726
|
template <typename T>
|
|
3170
|
-
|
|
3727
|
+
template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
|
|
3728
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
|
|
3171
3729
|
const char* utf8name,
|
|
3172
|
-
StaticGetterCallback getter,
|
|
3173
|
-
StaticSetterCallback setter,
|
|
3174
3730
|
napi_property_attributes attributes,
|
|
3175
3731
|
void* data) {
|
|
3176
|
-
StaticAccessorCallbackData* callbackData =
|
|
3177
|
-
new StaticAccessorCallbackData({ getter, setter, data });
|
|
3178
|
-
|
|
3179
3732
|
napi_property_descriptor desc = napi_property_descriptor();
|
|
3180
3733
|
desc.utf8name = utf8name;
|
|
3181
|
-
desc.
|
|
3182
|
-
desc.
|
|
3183
|
-
desc.data = callbackData;
|
|
3734
|
+
desc.method = details::TemplatedVoidCallback<method>;
|
|
3735
|
+
desc.data = data;
|
|
3184
3736
|
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3185
3737
|
return desc;
|
|
3186
3738
|
}
|
|
3187
3739
|
|
|
3188
3740
|
template <typename T>
|
|
3189
|
-
|
|
3741
|
+
template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
|
|
3742
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
|
|
3190
3743
|
Symbol name,
|
|
3191
|
-
StaticGetterCallback getter,
|
|
3192
|
-
StaticSetterCallback setter,
|
|
3193
3744
|
napi_property_attributes attributes,
|
|
3194
3745
|
void* data) {
|
|
3195
|
-
StaticAccessorCallbackData* callbackData =
|
|
3196
|
-
new StaticAccessorCallbackData({ getter, setter, data });
|
|
3197
|
-
|
|
3198
3746
|
napi_property_descriptor desc = napi_property_descriptor();
|
|
3199
3747
|
desc.name = name;
|
|
3200
|
-
desc.
|
|
3201
|
-
desc.
|
|
3202
|
-
desc.data = callbackData;
|
|
3748
|
+
desc.method = details::TemplatedVoidCallback<method>;
|
|
3749
|
+
desc.data = data;
|
|
3203
3750
|
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3204
3751
|
return desc;
|
|
3205
3752
|
}
|
|
3206
3753
|
|
|
3207
3754
|
template <typename T>
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
napi_property_attributes attributes,
|
|
3212
|
-
void* data) {
|
|
3213
|
-
InstanceVoidMethodCallbackData* callbackData =
|
|
3214
|
-
new InstanceVoidMethodCallbackData({ method, data});
|
|
3215
|
-
|
|
3216
|
-
napi_property_descriptor desc = napi_property_descriptor();
|
|
3217
|
-
desc.utf8name = utf8name;
|
|
3218
|
-
desc.method = T::InstanceVoidMethodCallbackWrapper;
|
|
3219
|
-
desc.data = callbackData;
|
|
3220
|
-
desc.attributes = attributes;
|
|
3221
|
-
return desc;
|
|
3222
|
-
}
|
|
3223
|
-
|
|
3224
|
-
template <typename T>
|
|
3225
|
-
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
|
|
3226
|
-
const char* utf8name,
|
|
3227
|
-
InstanceMethodCallback method,
|
|
3228
|
-
napi_property_attributes attributes,
|
|
3229
|
-
void* data) {
|
|
3230
|
-
InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
|
|
3231
|
-
|
|
3232
|
-
napi_property_descriptor desc = napi_property_descriptor();
|
|
3233
|
-
desc.utf8name = utf8name;
|
|
3234
|
-
desc.method = T::InstanceMethodCallbackWrapper;
|
|
3235
|
-
desc.data = callbackData;
|
|
3236
|
-
desc.attributes = attributes;
|
|
3237
|
-
return desc;
|
|
3238
|
-
}
|
|
3239
|
-
|
|
3240
|
-
template <typename T>
|
|
3241
|
-
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
|
|
3242
|
-
Symbol name,
|
|
3243
|
-
InstanceVoidMethodCallback method,
|
|
3755
|
+
template <typename ObjectWrap<T>::StaticMethodCallback method>
|
|
3756
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
|
|
3757
|
+
const char* utf8name,
|
|
3244
3758
|
napi_property_attributes attributes,
|
|
3245
3759
|
void* data) {
|
|
3246
|
-
InstanceVoidMethodCallbackData* callbackData =
|
|
3247
|
-
new InstanceVoidMethodCallbackData({ method, data});
|
|
3248
|
-
|
|
3249
3760
|
napi_property_descriptor desc = napi_property_descriptor();
|
|
3250
|
-
desc.
|
|
3251
|
-
desc.method =
|
|
3252
|
-
desc.data =
|
|
3253
|
-
desc.attributes = attributes;
|
|
3761
|
+
desc.utf8name = utf8name;
|
|
3762
|
+
desc.method = details::TemplatedCallback<method>;
|
|
3763
|
+
desc.data = data;
|
|
3764
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3254
3765
|
return desc;
|
|
3255
3766
|
}
|
|
3256
3767
|
|
|
3257
3768
|
template <typename T>
|
|
3258
|
-
|
|
3769
|
+
template <typename ObjectWrap<T>::StaticMethodCallback method>
|
|
3770
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
|
|
3259
3771
|
Symbol name,
|
|
3260
|
-
InstanceMethodCallback method,
|
|
3261
3772
|
napi_property_attributes attributes,
|
|
3262
3773
|
void* data) {
|
|
3263
|
-
InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
|
|
3264
|
-
|
|
3265
3774
|
napi_property_descriptor desc = napi_property_descriptor();
|
|
3266
3775
|
desc.name = name;
|
|
3267
|
-
desc.method =
|
|
3268
|
-
desc.data =
|
|
3269
|
-
desc.attributes = attributes;
|
|
3776
|
+
desc.method = details::TemplatedCallback<method>;
|
|
3777
|
+
desc.data = data;
|
|
3778
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3270
3779
|
return desc;
|
|
3271
3780
|
}
|
|
3272
3781
|
|
|
3273
3782
|
template <typename T>
|
|
3274
|
-
inline ClassPropertyDescriptor<T> ObjectWrap<T>::
|
|
3783
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
|
|
3275
3784
|
const char* utf8name,
|
|
3276
|
-
|
|
3277
|
-
|
|
3785
|
+
StaticGetterCallback getter,
|
|
3786
|
+
StaticSetterCallback setter,
|
|
3278
3787
|
napi_property_attributes attributes,
|
|
3279
3788
|
void* data) {
|
|
3280
|
-
|
|
3281
|
-
new
|
|
3789
|
+
StaticAccessorCallbackData* callbackData =
|
|
3790
|
+
new StaticAccessorCallbackData({ getter, setter, data });
|
|
3282
3791
|
|
|
3283
3792
|
napi_property_descriptor desc = napi_property_descriptor();
|
|
3284
3793
|
desc.utf8name = utf8name;
|
|
3285
|
-
desc.getter = getter != nullptr ? T::
|
|
3286
|
-
desc.setter = setter != nullptr ? T::
|
|
3794
|
+
desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
|
|
3795
|
+
desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
|
|
3287
3796
|
desc.data = callbackData;
|
|
3288
|
-
desc.attributes = attributes;
|
|
3797
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3289
3798
|
return desc;
|
|
3290
3799
|
}
|
|
3291
3800
|
|
|
3292
3801
|
template <typename T>
|
|
3293
|
-
inline ClassPropertyDescriptor<T> ObjectWrap<T>::
|
|
3802
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
|
|
3294
3803
|
Symbol name,
|
|
3295
|
-
|
|
3296
|
-
|
|
3804
|
+
StaticGetterCallback getter,
|
|
3805
|
+
StaticSetterCallback setter,
|
|
3297
3806
|
napi_property_attributes attributes,
|
|
3298
3807
|
void* data) {
|
|
3299
|
-
|
|
3300
|
-
new
|
|
3808
|
+
StaticAccessorCallbackData* callbackData =
|
|
3809
|
+
new StaticAccessorCallbackData({ getter, setter, data });
|
|
3301
3810
|
|
|
3302
3811
|
napi_property_descriptor desc = napi_property_descriptor();
|
|
3303
3812
|
desc.name = name;
|
|
3304
|
-
desc.getter = getter != nullptr ? T::
|
|
3305
|
-
desc.setter = setter != nullptr ? T::
|
|
3813
|
+
desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
|
|
3814
|
+
desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
|
|
3306
3815
|
desc.data = callbackData;
|
|
3307
|
-
desc.attributes = attributes;
|
|
3816
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3308
3817
|
return desc;
|
|
3309
3818
|
}
|
|
3310
3819
|
|
|
3311
3820
|
template <typename T>
|
|
3312
|
-
|
|
3313
|
-
|
|
3821
|
+
template <typename ObjectWrap<T>::StaticGetterCallback getter,
|
|
3822
|
+
typename ObjectWrap<T>::StaticSetterCallback setter>
|
|
3823
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
|
|
3824
|
+
const char* utf8name,
|
|
3825
|
+
napi_property_attributes attributes,
|
|
3826
|
+
void* data) {
|
|
3314
3827
|
napi_property_descriptor desc = napi_property_descriptor();
|
|
3315
3828
|
desc.utf8name = utf8name;
|
|
3316
|
-
desc.
|
|
3829
|
+
desc.getter = details::TemplatedCallback<getter>;
|
|
3830
|
+
desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
|
|
3831
|
+
desc.data = data;
|
|
3317
3832
|
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3318
3833
|
return desc;
|
|
3319
3834
|
}
|
|
3320
3835
|
|
|
3321
3836
|
template <typename T>
|
|
3322
|
-
|
|
3323
|
-
|
|
3837
|
+
template <typename ObjectWrap<T>::StaticGetterCallback getter,
|
|
3838
|
+
typename ObjectWrap<T>::StaticSetterCallback setter>
|
|
3839
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
|
|
3840
|
+
Symbol name,
|
|
3841
|
+
napi_property_attributes attributes,
|
|
3842
|
+
void* data) {
|
|
3324
3843
|
napi_property_descriptor desc = napi_property_descriptor();
|
|
3325
3844
|
desc.name = name;
|
|
3326
|
-
desc.
|
|
3845
|
+
desc.getter = details::TemplatedCallback<getter>;
|
|
3846
|
+
desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
|
|
3847
|
+
desc.data = data;
|
|
3327
3848
|
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3328
3849
|
return desc;
|
|
3329
3850
|
}
|
|
3330
3851
|
|
|
3331
3852
|
template <typename T>
|
|
3332
|
-
inline ClassPropertyDescriptor<T> ObjectWrap<T>::
|
|
3333
|
-
|
|
3334
|
-
Napi::Value value,
|
|
3335
|
-
napi_property_attributes attributes) {
|
|
3853
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(const char* utf8name,
|
|
3854
|
+
Napi::Value value, napi_property_attributes attributes) {
|
|
3336
3855
|
napi_property_descriptor desc = napi_property_descriptor();
|
|
3337
3856
|
desc.utf8name = utf8name;
|
|
3338
3857
|
desc.value = value;
|
|
3339
|
-
desc.attributes = attributes;
|
|
3858
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3340
3859
|
return desc;
|
|
3341
3860
|
}
|
|
3342
3861
|
|
|
3343
3862
|
template <typename T>
|
|
3344
|
-
inline ClassPropertyDescriptor<T> ObjectWrap<T>::
|
|
3345
|
-
|
|
3346
|
-
Napi::Value value,
|
|
3347
|
-
napi_property_attributes attributes) {
|
|
3863
|
+
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(Symbol name,
|
|
3864
|
+
Napi::Value value, napi_property_attributes attributes) {
|
|
3348
3865
|
napi_property_descriptor desc = napi_property_descriptor();
|
|
3349
3866
|
desc.name = name;
|
|
3350
3867
|
desc.value = value;
|
|
3351
|
-
desc.attributes = attributes;
|
|
3868
|
+
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
|
|
3352
3869
|
return desc;
|
|
3353
3870
|
}
|
|
3354
3871
|
|
|
@@ -3369,10 +3886,21 @@ inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
|
|
|
3369
3886
|
return nullptr;
|
|
3370
3887
|
}
|
|
3371
3888
|
|
|
3372
|
-
T* instance;
|
|
3373
3889
|
napi_value wrapper = details::WrapCallback([&] {
|
|
3374
3890
|
CallbackInfo callbackInfo(env, info);
|
|
3375
|
-
instance = new T(callbackInfo);
|
|
3891
|
+
T* instance = new T(callbackInfo);
|
|
3892
|
+
#ifdef NAPI_CPP_EXCEPTIONS
|
|
3893
|
+
instance->_construction_failed = false;
|
|
3894
|
+
#else
|
|
3895
|
+
if (callbackInfo.Env().IsExceptionPending()) {
|
|
3896
|
+
// We need to clear the exception so that removing the wrap might work.
|
|
3897
|
+
Error e = callbackInfo.Env().GetAndClearPendingException();
|
|
3898
|
+
delete instance;
|
|
3899
|
+
e.ThrowAsJavaScriptException();
|
|
3900
|
+
} else {
|
|
3901
|
+
instance->_construction_failed = false;
|
|
3902
|
+
}
|
|
3903
|
+
# endif // NAPI_CPP_EXCEPTIONS
|
|
3376
3904
|
return callbackInfo.This();
|
|
3377
3905
|
});
|
|
3378
3906
|
|
|
@@ -3434,74 +3962,22 @@ inline napi_value ObjectWrap<T>::StaticSetterCallbackWrapper(
|
|
|
3434
3962
|
}
|
|
3435
3963
|
|
|
3436
3964
|
template <typename T>
|
|
3437
|
-
inline
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
CallbackInfo callbackInfo(env, info);
|
|
3442
|
-
InstanceVoidMethodCallbackData* callbackData =
|
|
3443
|
-
reinterpret_cast<InstanceVoidMethodCallbackData*>(callbackInfo.Data());
|
|
3444
|
-
callbackInfo.SetData(callbackData->data);
|
|
3445
|
-
T* instance = Unwrap(callbackInfo.This().As<Object>());
|
|
3446
|
-
auto cb = callbackData->callback;
|
|
3447
|
-
(instance->*cb)(callbackInfo);
|
|
3448
|
-
return nullptr;
|
|
3449
|
-
});
|
|
3450
|
-
}
|
|
3451
|
-
|
|
3452
|
-
template <typename T>
|
|
3453
|
-
inline napi_value ObjectWrap<T>::InstanceMethodCallbackWrapper(
|
|
3454
|
-
napi_env env,
|
|
3455
|
-
napi_callback_info info) {
|
|
3456
|
-
return details::WrapCallback([&] {
|
|
3457
|
-
CallbackInfo callbackInfo(env, info);
|
|
3458
|
-
InstanceMethodCallbackData* callbackData =
|
|
3459
|
-
reinterpret_cast<InstanceMethodCallbackData*>(callbackInfo.Data());
|
|
3460
|
-
callbackInfo.SetData(callbackData->data);
|
|
3461
|
-
T* instance = Unwrap(callbackInfo.This().As<Object>());
|
|
3462
|
-
auto cb = callbackData->callback;
|
|
3463
|
-
return (instance->*cb)(callbackInfo);
|
|
3464
|
-
});
|
|
3465
|
-
}
|
|
3466
|
-
|
|
3467
|
-
template <typename T>
|
|
3468
|
-
inline napi_value ObjectWrap<T>::InstanceGetterCallbackWrapper(
|
|
3469
|
-
napi_env env,
|
|
3470
|
-
napi_callback_info info) {
|
|
3471
|
-
return details::WrapCallback([&] {
|
|
3472
|
-
CallbackInfo callbackInfo(env, info);
|
|
3473
|
-
InstanceAccessorCallbackData* callbackData =
|
|
3474
|
-
reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
|
|
3475
|
-
callbackInfo.SetData(callbackData->data);
|
|
3476
|
-
T* instance = Unwrap(callbackInfo.This().As<Object>());
|
|
3477
|
-
auto cb = callbackData->getterCallback;
|
|
3478
|
-
return (instance->*cb)(callbackInfo);
|
|
3479
|
-
});
|
|
3965
|
+
inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hint*/) {
|
|
3966
|
+
T* instance = static_cast<T*>(data);
|
|
3967
|
+
instance->Finalize(Napi::Env(env));
|
|
3968
|
+
delete instance;
|
|
3480
3969
|
}
|
|
3481
3970
|
|
|
3482
3971
|
template <typename T>
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
napi_callback_info info) {
|
|
3972
|
+
template <typename ObjectWrap<T>::StaticSetterCallback method>
|
|
3973
|
+
inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
|
|
3486
3974
|
return details::WrapCallback([&] {
|
|
3487
|
-
CallbackInfo
|
|
3488
|
-
|
|
3489
|
-
reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
|
|
3490
|
-
callbackInfo.SetData(callbackData->data);
|
|
3491
|
-
T* instance = Unwrap(callbackInfo.This().As<Object>());
|
|
3492
|
-
auto cb = callbackData->setterCallback;
|
|
3493
|
-
(instance->*cb)(callbackInfo, callbackInfo[0]);
|
|
3975
|
+
const CallbackInfo cbInfo(env, info);
|
|
3976
|
+
method(cbInfo, cbInfo[0]);
|
|
3494
3977
|
return nullptr;
|
|
3495
3978
|
});
|
|
3496
3979
|
}
|
|
3497
3980
|
|
|
3498
|
-
template <typename T>
|
|
3499
|
-
inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hint*/) {
|
|
3500
|
-
T* instance = reinterpret_cast<T*>(data);
|
|
3501
|
-
instance->Finalize(Napi::Env(env));
|
|
3502
|
-
delete instance;
|
|
3503
|
-
}
|
|
3504
|
-
|
|
3505
3981
|
////////////////////////////////////////////////////////////////////////////////
|
|
3506
3982
|
// HandleScope class
|
|
3507
3983
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -3699,8 +4175,8 @@ inline AsyncWorker::AsyncWorker(const Object& receiver,
|
|
|
3699
4175
|
_env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
|
|
3700
4176
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3701
4177
|
|
|
3702
|
-
status = napi_create_async_work(_env, resource, resource_id,
|
|
3703
|
-
|
|
4178
|
+
status = napi_create_async_work(_env, resource, resource_id, OnAsyncWorkExecute,
|
|
4179
|
+
OnAsyncWorkComplete, this, &_work);
|
|
3704
4180
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3705
4181
|
}
|
|
3706
4182
|
|
|
@@ -3725,8 +4201,8 @@ inline AsyncWorker::AsyncWorker(Napi::Env env,
|
|
|
3725
4201
|
_env, resource_name, NAPI_AUTO_LENGTH, &resource_id);
|
|
3726
4202
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3727
4203
|
|
|
3728
|
-
status = napi_create_async_work(_env, resource, resource_id,
|
|
3729
|
-
|
|
4204
|
+
status = napi_create_async_work(_env, resource, resource_id, OnAsyncWorkExecute,
|
|
4205
|
+
OnAsyncWorkComplete, this, &_work);
|
|
3730
4206
|
NAPI_THROW_IF_FAILED_VOID(_env, status);
|
|
3731
4207
|
}
|
|
3732
4208
|
|
|
@@ -3813,44 +4289,55 @@ inline void AsyncWorker::SetError(const std::string& error) {
|
|
|
3813
4289
|
inline std::vector<napi_value> AsyncWorker::GetResult(Napi::Env /*env*/) {
|
|
3814
4290
|
return {};
|
|
3815
4291
|
}
|
|
4292
|
+
// The OnAsyncWorkExecute method receives an napi_env argument. However, do NOT
|
|
4293
|
+
// use it within this method, as it does not run on the JavaScript thread and
|
|
4294
|
+
// must not run any method that would cause JavaScript to run. In practice,
|
|
4295
|
+
// this means that almost any use of napi_env will be incorrect.
|
|
4296
|
+
inline void AsyncWorker::OnAsyncWorkExecute(napi_env env, void* asyncworker) {
|
|
4297
|
+
AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
|
|
4298
|
+
self->OnExecute(env);
|
|
4299
|
+
}
|
|
3816
4300
|
// The OnExecute method receives an napi_env argument. However, do NOT
|
|
3817
|
-
// use it within this method, as it does not run on the
|
|
3818
|
-
// not run any method that would cause JavaScript to run. In practice,
|
|
3819
|
-
// means that almost any use of napi_env will be incorrect.
|
|
3820
|
-
inline void AsyncWorker::OnExecute(
|
|
3821
|
-
AsyncWorker* self = static_cast<AsyncWorker*>(this_pointer);
|
|
4301
|
+
// use it within this method, as it does not run on the JavaScript thread and
|
|
4302
|
+
// must not run any method that would cause JavaScript to run. In practice,
|
|
4303
|
+
// this means that almost any use of napi_env will be incorrect.
|
|
4304
|
+
inline void AsyncWorker::OnExecute(Napi::Env /*DO_NOT_USE*/) {
|
|
3822
4305
|
#ifdef NAPI_CPP_EXCEPTIONS
|
|
3823
4306
|
try {
|
|
3824
|
-
|
|
4307
|
+
Execute();
|
|
3825
4308
|
} catch (const std::exception& e) {
|
|
3826
|
-
|
|
4309
|
+
SetError(e.what());
|
|
3827
4310
|
}
|
|
3828
4311
|
#else // NAPI_CPP_EXCEPTIONS
|
|
3829
|
-
|
|
4312
|
+
Execute();
|
|
3830
4313
|
#endif // NAPI_CPP_EXCEPTIONS
|
|
3831
4314
|
}
|
|
3832
4315
|
|
|
3833
|
-
inline void AsyncWorker::
|
|
3834
|
-
|
|
3835
|
-
|
|
4316
|
+
inline void AsyncWorker::OnAsyncWorkComplete(napi_env env,
|
|
4317
|
+
napi_status status,
|
|
4318
|
+
void* asyncworker) {
|
|
4319
|
+
AsyncWorker* self = static_cast<AsyncWorker*>(asyncworker);
|
|
4320
|
+
self->OnWorkComplete(env, status);
|
|
4321
|
+
}
|
|
4322
|
+
inline void AsyncWorker::OnWorkComplete(Napi::Env /*env*/, napi_status status) {
|
|
3836
4323
|
if (status != napi_cancelled) {
|
|
3837
|
-
HandleScope scope(
|
|
4324
|
+
HandleScope scope(_env);
|
|
3838
4325
|
details::WrapCallback([&] {
|
|
3839
|
-
if (
|
|
3840
|
-
|
|
4326
|
+
if (_error.size() == 0) {
|
|
4327
|
+
OnOK();
|
|
3841
4328
|
}
|
|
3842
4329
|
else {
|
|
3843
|
-
|
|
4330
|
+
OnError(Error::New(_env, _error));
|
|
3844
4331
|
}
|
|
3845
4332
|
return nullptr;
|
|
3846
4333
|
});
|
|
3847
4334
|
}
|
|
3848
|
-
if (!
|
|
3849
|
-
|
|
4335
|
+
if (!_suppress_destruct) {
|
|
4336
|
+
Destroy();
|
|
3850
4337
|
}
|
|
3851
4338
|
}
|
|
3852
4339
|
|
|
3853
|
-
#if (NAPI_VERSION > 3)
|
|
4340
|
+
#if (NAPI_VERSION > 3 && !defined(__wasm32__))
|
|
3854
4341
|
////////////////////////////////////////////////////////////////////////////////
|
|
3855
4342
|
// ThreadSafeFunction class
|
|
3856
4343
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -4142,7 +4629,7 @@ inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
|
|
|
4142
4629
|
|
|
4143
4630
|
ThreadSafeFunction tsfn;
|
|
4144
4631
|
auto* finalizeData = new details::ThreadSafeFinalize<ContextType, Finalizer,
|
|
4145
|
-
FinalizerDataType>({ data, finalizeCallback
|
|
4632
|
+
FinalizerDataType>({ data, finalizeCallback });
|
|
4146
4633
|
napi_status status = napi_create_threadsafe_function(env, callback, resource,
|
|
4147
4634
|
Value::From(env, resourceName), maxQueueSize, initialThreadCount,
|
|
4148
4635
|
finalizeData, wrapper, context, CallJS, &tsfn._tsfn);
|
|
@@ -4185,9 +4672,89 @@ inline void ThreadSafeFunction::CallJS(napi_env env,
|
|
|
4185
4672
|
}
|
|
4186
4673
|
|
|
4187
4674
|
////////////////////////////////////////////////////////////////////////////////
|
|
4188
|
-
// Async Progress Worker class
|
|
4675
|
+
// Async Progress Worker Base class
|
|
4189
4676
|
////////////////////////////////////////////////////////////////////////////////
|
|
4677
|
+
template <typename DataType>
|
|
4678
|
+
inline AsyncProgressWorkerBase<DataType>::AsyncProgressWorkerBase(const Object& receiver,
|
|
4679
|
+
const Function& callback,
|
|
4680
|
+
const char* resource_name,
|
|
4681
|
+
const Object& resource,
|
|
4682
|
+
size_t queue_size)
|
|
4683
|
+
: AsyncWorker(receiver, callback, resource_name, resource) {
|
|
4684
|
+
// Fill all possible arguments to work around ambiguous ThreadSafeFunction::New signatures.
|
|
4685
|
+
_tsfn = ThreadSafeFunction::New(callback.Env(),
|
|
4686
|
+
callback,
|
|
4687
|
+
resource,
|
|
4688
|
+
resource_name,
|
|
4689
|
+
queue_size,
|
|
4690
|
+
/** initialThreadCount */ 1,
|
|
4691
|
+
/** context */ this,
|
|
4692
|
+
OnThreadSafeFunctionFinalize,
|
|
4693
|
+
/** finalizeData */ this);
|
|
4694
|
+
}
|
|
4695
|
+
|
|
4696
|
+
#if NAPI_VERSION > 4
|
|
4697
|
+
template <typename DataType>
|
|
4698
|
+
inline AsyncProgressWorkerBase<DataType>::AsyncProgressWorkerBase(Napi::Env env,
|
|
4699
|
+
const char* resource_name,
|
|
4700
|
+
const Object& resource,
|
|
4701
|
+
size_t queue_size)
|
|
4702
|
+
: AsyncWorker(env, resource_name, resource) {
|
|
4703
|
+
// TODO: Once the changes to make the callback optional for threadsafe
|
|
4704
|
+
// functions are available on all versions we can remove the dummy Function here.
|
|
4705
|
+
Function callback;
|
|
4706
|
+
// Fill all possible arguments to work around ambiguous ThreadSafeFunction::New signatures.
|
|
4707
|
+
_tsfn = ThreadSafeFunction::New(env,
|
|
4708
|
+
callback,
|
|
4709
|
+
resource,
|
|
4710
|
+
resource_name,
|
|
4711
|
+
queue_size,
|
|
4712
|
+
/** initialThreadCount */ 1,
|
|
4713
|
+
/** context */ this,
|
|
4714
|
+
OnThreadSafeFunctionFinalize,
|
|
4715
|
+
/** finalizeData */ this);
|
|
4716
|
+
}
|
|
4717
|
+
#endif
|
|
4718
|
+
|
|
4719
|
+
template<typename DataType>
|
|
4720
|
+
inline AsyncProgressWorkerBase<DataType>::~AsyncProgressWorkerBase() {
|
|
4721
|
+
// Abort pending tsfn call.
|
|
4722
|
+
// Don't send progress events after we've already completed.
|
|
4723
|
+
// It's ok to call ThreadSafeFunction::Abort and ThreadSafeFunction::Release duplicated.
|
|
4724
|
+
_tsfn.Abort();
|
|
4725
|
+
}
|
|
4726
|
+
|
|
4727
|
+
template <typename DataType>
|
|
4728
|
+
inline void AsyncProgressWorkerBase<DataType>::OnAsyncWorkProgress(Napi::Env /* env */,
|
|
4729
|
+
Napi::Function /* jsCallback */,
|
|
4730
|
+
void* data) {
|
|
4731
|
+
ThreadSafeData* tsd = static_cast<ThreadSafeData*>(data);
|
|
4732
|
+
tsd->asyncprogressworker()->OnWorkProgress(tsd->data());
|
|
4733
|
+
}
|
|
4734
|
+
|
|
4735
|
+
template <typename DataType>
|
|
4736
|
+
inline napi_status AsyncProgressWorkerBase<DataType>::NonBlockingCall(DataType* data) {
|
|
4737
|
+
auto tsd = new AsyncProgressWorkerBase::ThreadSafeData(this, data);
|
|
4738
|
+
return _tsfn.NonBlockingCall(tsd, OnAsyncWorkProgress);
|
|
4739
|
+
}
|
|
4740
|
+
|
|
4741
|
+
template <typename DataType>
|
|
4742
|
+
inline void AsyncProgressWorkerBase<DataType>::OnWorkComplete(Napi::Env /* env */, napi_status status) {
|
|
4743
|
+
_work_completed = true;
|
|
4744
|
+
_complete_status = status;
|
|
4745
|
+
_tsfn.Release();
|
|
4746
|
+
}
|
|
4747
|
+
|
|
4748
|
+
template <typename DataType>
|
|
4749
|
+
inline void AsyncProgressWorkerBase<DataType>::OnThreadSafeFunctionFinalize(Napi::Env env, void* /* data */, AsyncProgressWorkerBase* context) {
|
|
4750
|
+
if (context->_work_completed) {
|
|
4751
|
+
context->AsyncWorker::OnWorkComplete(env, context->_complete_status);
|
|
4752
|
+
}
|
|
4753
|
+
}
|
|
4190
4754
|
|
|
4755
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4756
|
+
// Async Progress Worker class
|
|
4757
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4191
4758
|
template<class T>
|
|
4192
4759
|
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback)
|
|
4193
4760
|
: AsyncProgressWorker(callback, "generic") {
|
|
@@ -4211,14 +4778,14 @@ inline AsyncProgressWorker<T>::AsyncProgressWorker(const Function& callback,
|
|
|
4211
4778
|
|
|
4212
4779
|
template<class T>
|
|
4213
4780
|
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
|
|
4214
|
-
|
|
4781
|
+
const Function& callback)
|
|
4215
4782
|
: AsyncProgressWorker(receiver, callback, "generic") {
|
|
4216
4783
|
}
|
|
4217
4784
|
|
|
4218
4785
|
template<class T>
|
|
4219
4786
|
inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
|
|
4220
|
-
|
|
4221
|
-
|
|
4787
|
+
const Function& callback,
|
|
4788
|
+
const char* resource_name)
|
|
4222
4789
|
: AsyncProgressWorker(receiver,
|
|
4223
4790
|
callback,
|
|
4224
4791
|
resource_name,
|
|
@@ -4230,10 +4797,9 @@ inline AsyncProgressWorker<T>::AsyncProgressWorker(const Object& receiver,
|
|
|
4230
4797
|
const Function& callback,
|
|
4231
4798
|
const char* resource_name,
|
|
4232
4799
|
const Object& resource)
|
|
4233
|
-
:
|
|
4800
|
+
: AsyncProgressWorkerBase(receiver, callback, resource_name, resource),
|
|
4234
4801
|
_asyncdata(nullptr),
|
|
4235
4802
|
_asyncsize(0) {
|
|
4236
|
-
_tsfn = ThreadSafeFunction::New(callback.Env(), callback, resource_name, 1, 1);
|
|
4237
4803
|
}
|
|
4238
4804
|
|
|
4239
4805
|
#if NAPI_VERSION > 4
|
|
@@ -4244,35 +4810,27 @@ inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env)
|
|
|
4244
4810
|
|
|
4245
4811
|
template<class T>
|
|
4246
4812
|
inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
|
|
4247
|
-
|
|
4813
|
+
const char* resource_name)
|
|
4248
4814
|
: AsyncProgressWorker(env, resource_name, Object::New(env)) {
|
|
4249
4815
|
}
|
|
4250
4816
|
|
|
4251
4817
|
template<class T>
|
|
4252
4818
|
inline AsyncProgressWorker<T>::AsyncProgressWorker(Napi::Env env,
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
:
|
|
4819
|
+
const char* resource_name,
|
|
4820
|
+
const Object& resource)
|
|
4821
|
+
: AsyncProgressWorkerBase(env, resource_name, resource),
|
|
4256
4822
|
_asyncdata(nullptr),
|
|
4257
4823
|
_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
4824
|
}
|
|
4263
4825
|
#endif
|
|
4264
4826
|
|
|
4265
4827
|
template<class T>
|
|
4266
4828
|
inline AsyncProgressWorker<T>::~AsyncProgressWorker() {
|
|
4267
|
-
// Abort pending tsfn call.
|
|
4268
|
-
// Don't send progress events after we've already completed.
|
|
4269
|
-
_tsfn.Abort();
|
|
4270
4829
|
{
|
|
4271
|
-
std::lock_guard<std::mutex> lock(_mutex);
|
|
4830
|
+
std::lock_guard<std::mutex> lock(this->_mutex);
|
|
4272
4831
|
_asyncdata = nullptr;
|
|
4273
4832
|
_asyncsize = 0;
|
|
4274
4833
|
}
|
|
4275
|
-
_tsfn.Release();
|
|
4276
4834
|
}
|
|
4277
4835
|
|
|
4278
4836
|
template<class T>
|
|
@@ -4282,20 +4840,18 @@ inline void AsyncProgressWorker<T>::Execute() {
|
|
|
4282
4840
|
}
|
|
4283
4841
|
|
|
4284
4842
|
template<class T>
|
|
4285
|
-
inline void AsyncProgressWorker<T>::
|
|
4286
|
-
AsyncProgressWorker* self = static_cast<AsyncProgressWorker*>(_data);
|
|
4287
|
-
|
|
4843
|
+
inline void AsyncProgressWorker<T>::OnWorkProgress(void*) {
|
|
4288
4844
|
T* data;
|
|
4289
4845
|
size_t size;
|
|
4290
4846
|
{
|
|
4291
|
-
std::lock_guard<std::mutex> lock(
|
|
4292
|
-
data =
|
|
4293
|
-
size =
|
|
4294
|
-
|
|
4295
|
-
|
|
4847
|
+
std::lock_guard<std::mutex> lock(this->_mutex);
|
|
4848
|
+
data = this->_asyncdata;
|
|
4849
|
+
size = this->_asyncsize;
|
|
4850
|
+
this->_asyncdata = nullptr;
|
|
4851
|
+
this->_asyncsize = 0;
|
|
4296
4852
|
}
|
|
4297
4853
|
|
|
4298
|
-
|
|
4854
|
+
this->OnProgress(data, size);
|
|
4299
4855
|
delete[] data;
|
|
4300
4856
|
}
|
|
4301
4857
|
|
|
@@ -4306,19 +4862,19 @@ inline void AsyncProgressWorker<T>::SendProgress_(const T* data, size_t count) {
|
|
|
4306
4862
|
|
|
4307
4863
|
T* old_data;
|
|
4308
4864
|
{
|
|
4309
|
-
std::lock_guard<std::mutex> lock(_mutex);
|
|
4865
|
+
std::lock_guard<std::mutex> lock(this->_mutex);
|
|
4310
4866
|
old_data = _asyncdata;
|
|
4311
4867
|
_asyncdata = new_data;
|
|
4312
4868
|
_asyncsize = count;
|
|
4313
4869
|
}
|
|
4314
|
-
|
|
4870
|
+
this->NonBlockingCall(nullptr);
|
|
4315
4871
|
|
|
4316
4872
|
delete[] old_data;
|
|
4317
4873
|
}
|
|
4318
4874
|
|
|
4319
4875
|
template<class T>
|
|
4320
4876
|
inline void AsyncProgressWorker<T>::Signal() const {
|
|
4321
|
-
|
|
4877
|
+
this->NonBlockingCall(static_cast<T*>(nullptr));
|
|
4322
4878
|
}
|
|
4323
4879
|
|
|
4324
4880
|
template<class T>
|
|
@@ -4331,8 +4887,125 @@ inline void AsyncProgressWorker<T>::ExecutionProgress::Send(const T* data, size_
|
|
|
4331
4887
|
_worker->SendProgress_(data, count);
|
|
4332
4888
|
}
|
|
4333
4889
|
|
|
4890
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4891
|
+
// Async Progress Queue Worker class
|
|
4892
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
4893
|
+
template<class T>
|
|
4894
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback)
|
|
4895
|
+
: AsyncProgressQueueWorker(callback, "generic") {
|
|
4896
|
+
}
|
|
4897
|
+
|
|
4898
|
+
template<class T>
|
|
4899
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback,
|
|
4900
|
+
const char* resource_name)
|
|
4901
|
+
: AsyncProgressQueueWorker(callback, resource_name, Object::New(callback.Env())) {
|
|
4902
|
+
}
|
|
4903
|
+
|
|
4904
|
+
template<class T>
|
|
4905
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Function& callback,
|
|
4906
|
+
const char* resource_name,
|
|
4907
|
+
const Object& resource)
|
|
4908
|
+
: AsyncProgressQueueWorker(Object::New(callback.Env()),
|
|
4909
|
+
callback,
|
|
4910
|
+
resource_name,
|
|
4911
|
+
resource) {
|
|
4912
|
+
}
|
|
4913
|
+
|
|
4914
|
+
template<class T>
|
|
4915
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
|
|
4916
|
+
const Function& callback)
|
|
4917
|
+
: AsyncProgressQueueWorker(receiver, callback, "generic") {
|
|
4918
|
+
}
|
|
4919
|
+
|
|
4920
|
+
template<class T>
|
|
4921
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
|
|
4922
|
+
const Function& callback,
|
|
4923
|
+
const char* resource_name)
|
|
4924
|
+
: AsyncProgressQueueWorker(receiver,
|
|
4925
|
+
callback,
|
|
4926
|
+
resource_name,
|
|
4927
|
+
Object::New(callback.Env())) {
|
|
4928
|
+
}
|
|
4929
|
+
|
|
4930
|
+
template<class T>
|
|
4931
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(const Object& receiver,
|
|
4932
|
+
const Function& callback,
|
|
4933
|
+
const char* resource_name,
|
|
4934
|
+
const Object& resource)
|
|
4935
|
+
: AsyncProgressWorkerBase<std::pair<T*, size_t>>(receiver, callback, resource_name, resource, /** unlimited queue size */0) {
|
|
4936
|
+
}
|
|
4937
|
+
|
|
4938
|
+
#if NAPI_VERSION > 4
|
|
4939
|
+
template<class T>
|
|
4940
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env)
|
|
4941
|
+
: AsyncProgressQueueWorker(env, "generic") {
|
|
4942
|
+
}
|
|
4943
|
+
|
|
4944
|
+
template<class T>
|
|
4945
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env,
|
|
4946
|
+
const char* resource_name)
|
|
4947
|
+
: AsyncProgressQueueWorker(env, resource_name, Object::New(env)) {
|
|
4948
|
+
}
|
|
4949
|
+
|
|
4950
|
+
template<class T>
|
|
4951
|
+
inline AsyncProgressQueueWorker<T>::AsyncProgressQueueWorker(Napi::Env env,
|
|
4952
|
+
const char* resource_name,
|
|
4953
|
+
const Object& resource)
|
|
4954
|
+
: AsyncProgressWorkerBase<std::pair<T*, size_t>>(env, resource_name, resource, /** unlimited queue size */0) {
|
|
4955
|
+
}
|
|
4334
4956
|
#endif
|
|
4335
4957
|
|
|
4958
|
+
template<class T>
|
|
4959
|
+
inline void AsyncProgressQueueWorker<T>::Execute() {
|
|
4960
|
+
ExecutionProgress progress(this);
|
|
4961
|
+
Execute(progress);
|
|
4962
|
+
}
|
|
4963
|
+
|
|
4964
|
+
template<class T>
|
|
4965
|
+
inline void AsyncProgressQueueWorker<T>::OnWorkProgress(std::pair<T*, size_t>* datapair) {
|
|
4966
|
+
if (datapair == nullptr) {
|
|
4967
|
+
return;
|
|
4968
|
+
}
|
|
4969
|
+
|
|
4970
|
+
T *data = datapair->first;
|
|
4971
|
+
size_t size = datapair->second;
|
|
4972
|
+
|
|
4973
|
+
this->OnProgress(data, size);
|
|
4974
|
+
delete datapair;
|
|
4975
|
+
delete[] data;
|
|
4976
|
+
}
|
|
4977
|
+
|
|
4978
|
+
template<class T>
|
|
4979
|
+
inline void AsyncProgressQueueWorker<T>::SendProgress_(const T* data, size_t count) {
|
|
4980
|
+
T* new_data = new T[count];
|
|
4981
|
+
std::copy(data, data + count, new_data);
|
|
4982
|
+
|
|
4983
|
+
auto pair = new std::pair<T*, size_t>(new_data, count);
|
|
4984
|
+
this->NonBlockingCall(pair);
|
|
4985
|
+
}
|
|
4986
|
+
|
|
4987
|
+
template<class T>
|
|
4988
|
+
inline void AsyncProgressQueueWorker<T>::Signal() const {
|
|
4989
|
+
this->NonBlockingCall(nullptr);
|
|
4990
|
+
}
|
|
4991
|
+
|
|
4992
|
+
template<class T>
|
|
4993
|
+
inline void AsyncProgressQueueWorker<T>::OnWorkComplete(Napi::Env env, napi_status status) {
|
|
4994
|
+
// Draining queued items in TSFN.
|
|
4995
|
+
AsyncProgressWorkerBase<std::pair<T*, size_t>>::OnWorkComplete(env, status);
|
|
4996
|
+
}
|
|
4997
|
+
|
|
4998
|
+
template<class T>
|
|
4999
|
+
inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Signal() const {
|
|
5000
|
+
_worker->Signal();
|
|
5001
|
+
}
|
|
5002
|
+
|
|
5003
|
+
template<class T>
|
|
5004
|
+
inline void AsyncProgressQueueWorker<T>::ExecutionProgress::Send(const T* data, size_t count) const {
|
|
5005
|
+
_worker->SendProgress_(data, count);
|
|
5006
|
+
}
|
|
5007
|
+
#endif // NAPI_VERSION > 3 && !defined(__wasm32__)
|
|
5008
|
+
|
|
4336
5009
|
////////////////////////////////////////////////////////////////////////////////
|
|
4337
5010
|
// Memory Management class
|
|
4338
5011
|
////////////////////////////////////////////////////////////////////////////////
|
|
@@ -4362,6 +5035,49 @@ inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) {
|
|
|
4362
5035
|
return result;
|
|
4363
5036
|
}
|
|
4364
5037
|
|
|
5038
|
+
#if NAPI_VERSION > 5
|
|
5039
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
5040
|
+
// Addon<T> class
|
|
5041
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
5042
|
+
|
|
5043
|
+
template <typename T>
|
|
5044
|
+
inline Object Addon<T>::Init(Env env, Object exports) {
|
|
5045
|
+
T* addon = new T(env, exports);
|
|
5046
|
+
env.SetInstanceData(addon);
|
|
5047
|
+
return addon->entry_point_;
|
|
5048
|
+
}
|
|
5049
|
+
|
|
5050
|
+
template <typename T>
|
|
5051
|
+
inline T* Addon<T>::Unwrap(Object wrapper) {
|
|
5052
|
+
return wrapper.Env().GetInstanceData<T>();
|
|
5053
|
+
}
|
|
5054
|
+
|
|
5055
|
+
template <typename T>
|
|
5056
|
+
inline void
|
|
5057
|
+
Addon<T>::DefineAddon(Object exports,
|
|
5058
|
+
const std::initializer_list<AddonProp>& props) {
|
|
5059
|
+
DefineProperties(exports, props);
|
|
5060
|
+
entry_point_ = exports;
|
|
5061
|
+
}
|
|
5062
|
+
|
|
5063
|
+
template <typename T>
|
|
5064
|
+
inline Napi::Object
|
|
5065
|
+
Addon<T>::DefineProperties(Object object,
|
|
5066
|
+
const std::initializer_list<AddonProp>& props) {
|
|
5067
|
+
const napi_property_descriptor* properties =
|
|
5068
|
+
reinterpret_cast<const napi_property_descriptor*>(props.begin());
|
|
5069
|
+
size_t size = props.size();
|
|
5070
|
+
napi_status status = napi_define_properties(object.Env(),
|
|
5071
|
+
object,
|
|
5072
|
+
size,
|
|
5073
|
+
properties);
|
|
5074
|
+
NAPI_THROW_IF_FAILED(object.Env(), status, object);
|
|
5075
|
+
for (size_t idx = 0; idx < size; idx++)
|
|
5076
|
+
T::AttachPropData(object.Env(), object, &properties[idx]);
|
|
5077
|
+
return object;
|
|
5078
|
+
}
|
|
5079
|
+
#endif // NAPI_VERSION > 5
|
|
5080
|
+
|
|
4365
5081
|
} // namespace Napi
|
|
4366
5082
|
|
|
4367
5083
|
#endif // SRC_NAPI_INL_H_
|