node-addon-api 1.7.2 → 2.0.0

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