node-addon-api 3.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/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,20 +135,66 @@ 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
- FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
125
- finalizeData->callback(Env(env), static_cast<T*>(data));
126
- delete finalizeData;
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
- FinalizeData* finalizeData = static_cast<FinalizeData*>(finalizeHint);
132
- finalizeData->callback(Env(env), static_cast<T*>(data), finalizeData->hint);
133
- delete finalizeData;
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;
@@ -238,6 +302,7 @@ struct AccessorCallbackData {
238
302
  // Module registration
239
303
  ////////////////////////////////////////////////////////////////////////////////
240
304
 
305
+ // Register an add-on based on an initializer function.
241
306
  #define NODE_API_MODULE(modname, regfunc) \
242
307
  napi_value __napi_ ## regfunc(napi_env env, \
243
308
  napi_value exports) { \
@@ -245,6 +310,20 @@ struct AccessorCallbackData {
245
310
  } \
246
311
  NAPI_MODULE(modname, __napi_ ## regfunc)
247
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
+
248
327
  // Adapt the NAPI_MODULE registration function:
249
328
  // - Wrap the arguments in NAPI wrappers.
250
329
  // - Catch any NAPI errors and rethrow as JS exceptions.
@@ -1808,15 +1887,12 @@ CreateFunction(napi_env env,
1808
1887
  template <Function::VoidCallback cb>
1809
1888
  inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1810
1889
  napi_value result = nullptr;
1811
- napi_status status = napi_create_function(
1812
- env, utf8name, NAPI_AUTO_LENGTH,
1813
- [](napi_env env, napi_callback_info info) {
1814
- CallbackInfo callbackInfo(env, info);
1815
- return details::WrapCallback([&] {
1816
- cb(callbackInfo);
1817
- return nullptr;
1818
- });
1819
- }, data, &result);
1890
+ napi_status status = napi_create_function(env,
1891
+ utf8name,
1892
+ NAPI_AUTO_LENGTH,
1893
+ details::TemplatedVoidCallback<cb>,
1894
+ data,
1895
+ &result);
1820
1896
  NAPI_THROW_IF_FAILED(env, status, Function());
1821
1897
  return Function(env, result);
1822
1898
  }
@@ -1824,14 +1900,12 @@ inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1824
1900
  template <Function::Callback cb>
1825
1901
  inline Function Function::New(napi_env env, const char* utf8name, void* data) {
1826
1902
  napi_value result = nullptr;
1827
- napi_status status = napi_create_function(
1828
- env, utf8name, NAPI_AUTO_LENGTH,
1829
- [](napi_env env, napi_callback_info info) {
1830
- CallbackInfo callbackInfo(env, info);
1831
- return details::WrapCallback([&] {
1832
- return cb(callbackInfo);
1833
- });
1834
- }, data, &result);
1903
+ napi_status status = napi_create_function(env,
1904
+ utf8name,
1905
+ NAPI_AUTO_LENGTH,
1906
+ details::TemplatedCallback<cb>,
1907
+ data,
1908
+ &result);
1835
1909
  NAPI_THROW_IF_FAILED(env, status, Function());
1836
1910
  return Function(env, result);
1837
1911
  }
@@ -2822,7 +2896,7 @@ PropertyDescriptor::Accessor(const char* utf8name,
2822
2896
  napi_property_descriptor desc = napi_property_descriptor();
2823
2897
 
2824
2898
  desc.utf8name = utf8name;
2825
- desc.getter = &GetterCallbackWrapper<Getter>;
2899
+ desc.getter = details::TemplatedCallback<Getter>;
2826
2900
  desc.attributes = attributes;
2827
2901
  desc.data = data;
2828
2902
 
@@ -2845,7 +2919,7 @@ PropertyDescriptor::Accessor(Name name,
2845
2919
  napi_property_descriptor desc = napi_property_descriptor();
2846
2920
 
2847
2921
  desc.name = name;
2848
- desc.getter = &GetterCallbackWrapper<Getter>;
2922
+ desc.getter = details::TemplatedCallback<Getter>;
2849
2923
  desc.attributes = attributes;
2850
2924
  desc.data = data;
2851
2925
 
@@ -2863,8 +2937,8 @@ PropertyDescriptor::Accessor(const char* utf8name,
2863
2937
  napi_property_descriptor desc = napi_property_descriptor();
2864
2938
 
2865
2939
  desc.utf8name = utf8name;
2866
- desc.getter = &GetterCallbackWrapper<Getter>;
2867
- desc.setter = &SetterCallbackWrapper<Setter>;
2940
+ desc.getter = details::TemplatedCallback<Getter>;
2941
+ desc.setter = details::TemplatedVoidCallback<Setter>;
2868
2942
  desc.attributes = attributes;
2869
2943
  desc.data = data;
2870
2944
 
@@ -2891,31 +2965,14 @@ PropertyDescriptor::Accessor(Name name,
2891
2965
  napi_property_descriptor desc = napi_property_descriptor();
2892
2966
 
2893
2967
  desc.name = name;
2894
- desc.getter = &GetterCallbackWrapper<Getter>;
2895
- desc.setter = &SetterCallbackWrapper<Setter>;
2968
+ desc.getter = details::TemplatedCallback<Getter>;
2969
+ desc.setter = details::TemplatedVoidCallback<Setter>;
2896
2970
  desc.attributes = attributes;
2897
2971
  desc.data = data;
2898
2972
 
2899
2973
  return desc;
2900
2974
  }
2901
2975
 
2902
- template <typename PropertyDescriptor::GetterCallback Getter>
2903
- napi_value
2904
- PropertyDescriptor::GetterCallbackWrapper(napi_env env,
2905
- napi_callback_info info) {
2906
- CallbackInfo cbInfo(env, info);
2907
- return Getter(cbInfo);
2908
- }
2909
-
2910
- template <typename PropertyDescriptor::SetterCallback Setter>
2911
- napi_value
2912
- PropertyDescriptor::SetterCallbackWrapper(napi_env env,
2913
- napi_callback_info info) {
2914
- CallbackInfo cbInfo(env, info);
2915
- Setter(cbInfo);
2916
- return nullptr;
2917
- }
2918
-
2919
2976
  template <typename Getter>
2920
2977
  inline PropertyDescriptor
2921
2978
  PropertyDescriptor::Accessor(Napi::Env env,
@@ -3143,539 +3200,652 @@ inline PropertyDescriptor::operator const napi_property_descriptor&() const {
3143
3200
  }
3144
3201
 
3145
3202
  ////////////////////////////////////////////////////////////////////////////////
3146
- // ObjectWrap<T> class
3203
+ // InstanceWrap<T> class
3147
3204
  ////////////////////////////////////////////////////////////////////////////////
3148
3205
 
3149
3206
  template <typename T>
3150
- inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
3151
- napi_env env = callbackInfo.Env();
3152
- napi_value wrapper = callbackInfo.This();
3153
- napi_status status;
3154
- napi_ref ref;
3155
- T* instance = static_cast<T*>(this);
3156
- status = napi_wrap(env, wrapper, instance, FinalizeCallback, nullptr, &ref);
3157
- NAPI_THROW_IF_FAILED_VOID(env, status);
3158
-
3159
- Reference<Object>* instanceRef = instance;
3160
- *instanceRef = Reference<Object>(env, ref);
3161
- }
3162
-
3163
- template <typename T>
3164
- inline ObjectWrap<T>::~ObjectWrap() {
3165
- // If the JS object still exists at this point, remove the finalizer added
3166
- // through `napi_wrap()`.
3167
- if (!IsEmpty()) {
3168
- Object object = Value();
3169
- // It is not valid to call `napi_remove_wrap()` with an empty `object`.
3170
- // This happens e.g. during garbage collection.
3171
- if (!object.IsEmpty() && _construction_failed) {
3172
- napi_remove_wrap(Env(), object, nullptr);
3173
- }
3174
- }
3175
- }
3176
-
3177
- template<typename T>
3178
- inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
3179
- T* unwrapped;
3180
- napi_status status = napi_unwrap(wrapper.Env(), wrapper, reinterpret_cast<void**>(&unwrapped));
3181
- NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
3182
- return unwrapped;
3183
- }
3184
-
3185
- template <typename T>
3186
- inline Function
3187
- ObjectWrap<T>::DefineClass(Napi::Env env,
3188
- const char* utf8name,
3189
- const size_t props_count,
3190
- const napi_property_descriptor* descriptors,
3191
- void* data) {
3207
+ inline void InstanceWrap<T>::AttachPropData(napi_env env,
3208
+ napi_value value,
3209
+ const napi_property_descriptor* prop) {
3192
3210
  napi_status status;
3193
- std::vector<napi_property_descriptor> props(props_count);
3194
-
3195
- // We copy the descriptors to a local array because before defining the class
3196
- // we must replace static method property descriptors with value property
3197
- // descriptors such that the value is a function-valued `napi_value` created
3198
- // with `CreateFunction()`.
3199
- //
3200
- // This replacement could be made for instance methods as well, but V8 aborts
3201
- // if we do that, because it expects methods defined on the prototype template
3202
- // to have `FunctionTemplate`s.
3203
- for (size_t index = 0; index < props_count; index++) {
3204
- props[index] = descriptors[index];
3205
- napi_property_descriptor* prop = &props[index];
3206
- if (prop->method == T::StaticMethodCallbackWrapper) {
3207
- status = CreateFunction(env,
3208
- utf8name,
3209
- prop->method,
3210
- static_cast<StaticMethodCallbackData*>(prop->data),
3211
- &(prop->value));
3212
- NAPI_THROW_IF_FAILED(env, status, Function());
3213
- prop->method = nullptr;
3214
- prop->data = nullptr;
3215
- } else if (prop->method == T::StaticVoidMethodCallbackWrapper) {
3216
- status = CreateFunction(env,
3217
- utf8name,
3218
- prop->method,
3219
- static_cast<StaticVoidMethodCallbackData*>(prop->data),
3220
- &(prop->value));
3221
- NAPI_THROW_IF_FAILED(env, status, Function());
3222
- prop->method = nullptr;
3223
- prop->data = nullptr;
3224
- }
3225
- }
3226
-
3227
- napi_value value;
3228
- status = napi_define_class(env,
3229
- utf8name,
3230
- NAPI_AUTO_LENGTH,
3231
- T::ConstructorCallbackWrapper,
3232
- data,
3233
- props_count,
3234
- props.data(),
3235
- &value);
3236
- NAPI_THROW_IF_FAILED(env, status, Function());
3237
-
3238
- // After defining the class we iterate once more over the property descriptors
3239
- // and attach the data associated with accessors and instance methods to the
3240
- // newly created JavaScript class.
3241
- for (size_t idx = 0; idx < props_count; idx++) {
3242
- const napi_property_descriptor* prop = &props[idx];
3243
-
3244
- if (prop->getter == T::StaticGetterCallbackWrapper ||
3245
- prop->setter == T::StaticSetterCallbackWrapper) {
3211
+ if (prop->method != nullptr && !(prop->attributes & napi_static)) {
3212
+ if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
3246
3213
  status = Napi::details::AttachData(env,
3247
- value,
3248
- static_cast<StaticAccessorCallbackData*>(prop->data));
3249
- NAPI_THROW_IF_FAILED(env, status, Function());
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);
3250
3222
  } else if (prop->getter == T::InstanceGetterCallbackWrapper ||
3251
3223
  prop->setter == T::InstanceSetterCallbackWrapper) {
3252
3224
  status = Napi::details::AttachData(env,
3253
3225
  value,
3254
3226
  static_cast<InstanceAccessorCallbackData*>(prop->data));
3255
- NAPI_THROW_IF_FAILED(env, status, Function());
3256
- } else if (prop->method != nullptr && !(prop->attributes & napi_static)) {
3257
- if (prop->method == T::InstanceVoidMethodCallbackWrapper) {
3258
- status = Napi::details::AttachData(env,
3259
- value,
3260
- static_cast<InstanceVoidMethodCallbackData*>(prop->data));
3261
- NAPI_THROW_IF_FAILED(env, status, Function());
3262
- } else if (prop->method == T::InstanceMethodCallbackWrapper) {
3263
- status = Napi::details::AttachData(env,
3264
- value,
3265
- static_cast<InstanceMethodCallbackData*>(prop->data));
3266
- NAPI_THROW_IF_FAILED(env, status, Function());
3267
- }
3227
+ NAPI_THROW_IF_FAILED_VOID(env, status);
3268
3228
  }
3269
3229
  }
3270
-
3271
- return Function(env, value);
3272
- }
3273
-
3274
- template <typename T>
3275
- inline Function ObjectWrap<T>::DefineClass(
3276
- Napi::Env env,
3277
- const char* utf8name,
3278
- const std::initializer_list<ClassPropertyDescriptor<T>>& properties,
3279
- void* data) {
3280
- return DefineClass(env,
3281
- utf8name,
3282
- properties.size(),
3283
- reinterpret_cast<const napi_property_descriptor*>(properties.begin()),
3284
- data);
3285
- }
3286
-
3287
- template <typename T>
3288
- inline Function ObjectWrap<T>::DefineClass(
3289
- Napi::Env env,
3290
- const char* utf8name,
3291
- const std::vector<ClassPropertyDescriptor<T>>& properties,
3292
- void* data) {
3293
- return DefineClass(env,
3294
- utf8name,
3295
- properties.size(),
3296
- reinterpret_cast<const napi_property_descriptor*>(properties.data()),
3297
- data);
3298
3230
  }
3299
3231
 
3300
3232
  template <typename T>
3301
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3233
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3302
3234
  const char* utf8name,
3303
- StaticVoidMethodCallback method,
3235
+ InstanceVoidMethodCallback method,
3304
3236
  napi_property_attributes attributes,
3305
3237
  void* data) {
3306
- StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3238
+ InstanceVoidMethodCallbackData* callbackData =
3239
+ new InstanceVoidMethodCallbackData({ method, data});
3307
3240
 
3308
3241
  napi_property_descriptor desc = napi_property_descriptor();
3309
3242
  desc.utf8name = utf8name;
3310
- desc.method = T::StaticVoidMethodCallbackWrapper;
3243
+ desc.method = T::InstanceVoidMethodCallbackWrapper;
3311
3244
  desc.data = callbackData;
3312
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3245
+ desc.attributes = attributes;
3313
3246
  return desc;
3314
3247
  }
3315
3248
 
3316
3249
  template <typename T>
3317
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3250
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3318
3251
  const char* utf8name,
3319
- StaticMethodCallback method,
3252
+ InstanceMethodCallback method,
3320
3253
  napi_property_attributes attributes,
3321
3254
  void* data) {
3322
- StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3255
+ InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3323
3256
 
3324
3257
  napi_property_descriptor desc = napi_property_descriptor();
3325
3258
  desc.utf8name = utf8name;
3326
- desc.method = T::StaticMethodCallbackWrapper;
3259
+ desc.method = T::InstanceMethodCallbackWrapper;
3327
3260
  desc.data = callbackData;
3328
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3261
+ desc.attributes = attributes;
3329
3262
  return desc;
3330
3263
  }
3331
3264
 
3332
3265
  template <typename T>
3333
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3266
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3334
3267
  Symbol name,
3335
- StaticVoidMethodCallback method,
3268
+ InstanceVoidMethodCallback method,
3336
3269
  napi_property_attributes attributes,
3337
3270
  void* data) {
3338
- StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3271
+ InstanceVoidMethodCallbackData* callbackData =
3272
+ new InstanceVoidMethodCallbackData({ method, data});
3339
3273
 
3340
3274
  napi_property_descriptor desc = napi_property_descriptor();
3341
3275
  desc.name = name;
3342
- desc.method = T::StaticVoidMethodCallbackWrapper;
3276
+ desc.method = T::InstanceVoidMethodCallbackWrapper;
3343
3277
  desc.data = callbackData;
3344
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3278
+ desc.attributes = attributes;
3345
3279
  return desc;
3346
3280
  }
3347
3281
 
3348
3282
  template <typename T>
3349
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3283
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3350
3284
  Symbol name,
3351
- StaticMethodCallback method,
3285
+ InstanceMethodCallback method,
3352
3286
  napi_property_attributes attributes,
3353
3287
  void* data) {
3354
- StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3288
+ InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3355
3289
 
3356
3290
  napi_property_descriptor desc = napi_property_descriptor();
3357
3291
  desc.name = name;
3358
- desc.method = T::StaticMethodCallbackWrapper;
3292
+ desc.method = T::InstanceMethodCallbackWrapper;
3359
3293
  desc.data = callbackData;
3360
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3294
+ desc.attributes = attributes;
3361
3295
  return desc;
3362
3296
  }
3363
3297
 
3364
3298
  template <typename T>
3365
- template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3366
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3299
+ template <typename InstanceWrap<T>::InstanceVoidMethodCallback method>
3300
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3367
3301
  const char* utf8name,
3368
3302
  napi_property_attributes attributes,
3369
3303
  void* data) {
3370
3304
  napi_property_descriptor desc = napi_property_descriptor();
3371
3305
  desc.utf8name = utf8name;
3372
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3306
+ desc.method = details::TemplatedInstanceVoidCallback<T, method>;
3373
3307
  desc.data = data;
3374
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3308
+ desc.attributes = attributes;
3375
3309
  return desc;
3376
3310
  }
3377
3311
 
3378
3312
  template <typename T>
3379
- template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3380
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3381
- Symbol name,
3313
+ template <typename InstanceWrap<T>::InstanceMethodCallback method>
3314
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3315
+ const char* utf8name,
3382
3316
  napi_property_attributes attributes,
3383
3317
  void* data) {
3384
3318
  napi_property_descriptor desc = napi_property_descriptor();
3385
- desc.name = name;
3386
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3319
+ desc.utf8name = utf8name;
3320
+ desc.method = details::TemplatedInstanceCallback<T, method>;
3387
3321
  desc.data = data;
3388
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3322
+ desc.attributes = attributes;
3389
3323
  return desc;
3390
3324
  }
3391
3325
 
3392
3326
  template <typename T>
3393
- template <typename ObjectWrap<T>::StaticMethodCallback method>
3394
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3395
- const char* utf8name,
3327
+ template <typename InstanceWrap<T>::InstanceVoidMethodCallback method>
3328
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3329
+ Symbol name,
3396
3330
  napi_property_attributes attributes,
3397
3331
  void* data) {
3398
3332
  napi_property_descriptor desc = napi_property_descriptor();
3399
- desc.utf8name = utf8name;
3400
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3333
+ desc.name = name;
3334
+ desc.method = details::TemplatedInstanceVoidCallback<T, method>;
3401
3335
  desc.data = data;
3402
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3336
+ desc.attributes = attributes;
3403
3337
  return desc;
3404
3338
  }
3405
3339
 
3406
3340
  template <typename T>
3407
- template <typename ObjectWrap<T>::StaticMethodCallback method>
3408
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3341
+ template <typename InstanceWrap<T>::InstanceMethodCallback method>
3342
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceMethod(
3409
3343
  Symbol name,
3410
3344
  napi_property_attributes attributes,
3411
3345
  void* data) {
3412
3346
  napi_property_descriptor desc = napi_property_descriptor();
3413
3347
  desc.name = name;
3414
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3348
+ desc.method = details::TemplatedInstanceCallback<T, method>;
3415
3349
  desc.data = data;
3416
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3350
+ desc.attributes = attributes;
3417
3351
  return desc;
3418
3352
  }
3419
3353
 
3420
3354
  template <typename T>
3421
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3355
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
3422
3356
  const char* utf8name,
3423
- StaticGetterCallback getter,
3424
- StaticSetterCallback setter,
3357
+ InstanceGetterCallback getter,
3358
+ InstanceSetterCallback setter,
3425
3359
  napi_property_attributes attributes,
3426
3360
  void* data) {
3427
- StaticAccessorCallbackData* callbackData =
3428
- new StaticAccessorCallbackData({ getter, setter, data });
3361
+ InstanceAccessorCallbackData* callbackData =
3362
+ new InstanceAccessorCallbackData({ getter, setter, data });
3429
3363
 
3430
3364
  napi_property_descriptor desc = napi_property_descriptor();
3431
3365
  desc.utf8name = utf8name;
3432
- desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3433
- desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3366
+ desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3367
+ desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3434
3368
  desc.data = callbackData;
3435
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3369
+ desc.attributes = attributes;
3436
3370
  return desc;
3437
3371
  }
3438
3372
 
3439
3373
  template <typename T>
3440
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3374
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
3441
3375
  Symbol name,
3442
- StaticGetterCallback getter,
3443
- StaticSetterCallback setter,
3376
+ InstanceGetterCallback getter,
3377
+ InstanceSetterCallback setter,
3444
3378
  napi_property_attributes attributes,
3445
3379
  void* data) {
3446
- StaticAccessorCallbackData* callbackData =
3447
- new StaticAccessorCallbackData({ getter, setter, data });
3380
+ InstanceAccessorCallbackData* callbackData =
3381
+ new InstanceAccessorCallbackData({ getter, setter, data });
3448
3382
 
3449
3383
  napi_property_descriptor desc = napi_property_descriptor();
3450
3384
  desc.name = name;
3451
- desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3452
- desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3385
+ desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3386
+ desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3453
3387
  desc.data = callbackData;
3454
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3388
+ desc.attributes = attributes;
3455
3389
  return desc;
3456
3390
  }
3457
3391
 
3458
3392
  template <typename T>
3459
- template <typename ObjectWrap<T>::StaticGetterCallback getter,
3460
- typename ObjectWrap<T>::StaticSetterCallback setter>
3461
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3393
+ template <typename InstanceWrap<T>::InstanceGetterCallback getter,
3394
+ typename InstanceWrap<T>::InstanceSetterCallback setter>
3395
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
3462
3396
  const char* utf8name,
3463
3397
  napi_property_attributes attributes,
3464
3398
  void* data) {
3465
3399
  napi_property_descriptor desc = napi_property_descriptor();
3466
3400
  desc.utf8name = utf8name;
3467
- desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
3468
- desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3401
+ desc.getter = details::TemplatedInstanceCallback<T, getter>;
3402
+ desc.setter = This::WrapSetter(This::SetterTag<setter>());
3469
3403
  desc.data = data;
3470
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3404
+ desc.attributes = attributes;
3471
3405
  return desc;
3472
3406
  }
3473
3407
 
3474
3408
  template <typename T>
3475
- template <typename ObjectWrap<T>::StaticGetterCallback getter,
3476
- typename ObjectWrap<T>::StaticSetterCallback setter>
3477
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3409
+ template <typename InstanceWrap<T>::InstanceGetterCallback getter,
3410
+ typename InstanceWrap<T>::InstanceSetterCallback setter>
3411
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceAccessor(
3478
3412
  Symbol name,
3479
3413
  napi_property_attributes attributes,
3480
3414
  void* data) {
3481
3415
  napi_property_descriptor desc = napi_property_descriptor();
3482
3416
  desc.name = name;
3483
- desc.getter = This::WrapStaticGetter(This::StaticGetterTag<getter>());
3484
- desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3417
+ desc.getter = details::TemplatedInstanceCallback<T, getter>;
3418
+ desc.setter = This::WrapSetter(This::SetterTag<setter>());
3485
3419
  desc.data = data;
3486
- desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3420
+ desc.attributes = attributes;
3487
3421
  return desc;
3488
3422
  }
3489
3423
 
3490
3424
  template <typename T>
3491
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3425
+ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceValue(
3492
3426
  const char* utf8name,
3493
- InstanceVoidMethodCallback method,
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>
3650
+ inline Function ObjectWrap<T>::DefineClass(
3651
+ Napi::Env env,
3652
+ const char* utf8name,
3653
+ const std::vector<ClassPropertyDescriptor<T>>& properties,
3654
+ void* data) {
3655
+ return DefineClass(env,
3656
+ utf8name,
3657
+ properties.size(),
3658
+ reinterpret_cast<const napi_property_descriptor*>(properties.data()),
3659
+ data);
3660
+ }
3661
+
3662
+ template <typename T>
3663
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3664
+ const char* utf8name,
3665
+ StaticVoidMethodCallback method,
3494
3666
  napi_property_attributes attributes,
3495
3667
  void* data) {
3496
- InstanceVoidMethodCallbackData* callbackData =
3497
- new InstanceVoidMethodCallbackData({ method, data});
3668
+ StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3498
3669
 
3499
3670
  napi_property_descriptor desc = napi_property_descriptor();
3500
3671
  desc.utf8name = utf8name;
3501
- desc.method = T::InstanceVoidMethodCallbackWrapper;
3672
+ desc.method = T::StaticVoidMethodCallbackWrapper;
3502
3673
  desc.data = callbackData;
3503
- desc.attributes = attributes;
3674
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3504
3675
  return desc;
3505
3676
  }
3506
3677
 
3507
3678
  template <typename T>
3508
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3679
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3509
3680
  const char* utf8name,
3510
- InstanceMethodCallback method,
3681
+ StaticMethodCallback method,
3511
3682
  napi_property_attributes attributes,
3512
3683
  void* data) {
3513
- InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3684
+ StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3514
3685
 
3515
3686
  napi_property_descriptor desc = napi_property_descriptor();
3516
3687
  desc.utf8name = utf8name;
3517
- desc.method = T::InstanceMethodCallbackWrapper;
3688
+ desc.method = T::StaticMethodCallbackWrapper;
3518
3689
  desc.data = callbackData;
3519
- desc.attributes = attributes;
3690
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3520
3691
  return desc;
3521
3692
  }
3522
3693
 
3523
3694
  template <typename T>
3524
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3695
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3525
3696
  Symbol name,
3526
- InstanceVoidMethodCallback method,
3697
+ StaticVoidMethodCallback method,
3527
3698
  napi_property_attributes attributes,
3528
3699
  void* data) {
3529
- InstanceVoidMethodCallbackData* callbackData =
3530
- new InstanceVoidMethodCallbackData({ method, data});
3700
+ StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });
3531
3701
 
3532
3702
  napi_property_descriptor desc = napi_property_descriptor();
3533
3703
  desc.name = name;
3534
- desc.method = T::InstanceVoidMethodCallbackWrapper;
3704
+ desc.method = T::StaticVoidMethodCallbackWrapper;
3535
3705
  desc.data = callbackData;
3536
- desc.attributes = attributes;
3706
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3537
3707
  return desc;
3538
3708
  }
3539
3709
 
3540
3710
  template <typename T>
3541
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3711
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3542
3712
  Symbol name,
3543
- InstanceMethodCallback method,
3713
+ StaticMethodCallback method,
3544
3714
  napi_property_attributes attributes,
3545
3715
  void* data) {
3546
- InstanceMethodCallbackData* callbackData = new InstanceMethodCallbackData({ method, data });
3716
+ StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });
3547
3717
 
3548
3718
  napi_property_descriptor desc = napi_property_descriptor();
3549
3719
  desc.name = name;
3550
- desc.method = T::InstanceMethodCallbackWrapper;
3720
+ desc.method = T::StaticMethodCallbackWrapper;
3551
3721
  desc.data = callbackData;
3552
- desc.attributes = attributes;
3722
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3553
3723
  return desc;
3554
3724
  }
3555
3725
 
3556
3726
  template <typename T>
3557
- template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3558
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3727
+ template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3728
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3559
3729
  const char* utf8name,
3560
3730
  napi_property_attributes attributes,
3561
3731
  void* data) {
3562
3732
  napi_property_descriptor desc = napi_property_descriptor();
3563
3733
  desc.utf8name = utf8name;
3564
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3734
+ desc.method = details::TemplatedVoidCallback<method>;
3565
3735
  desc.data = data;
3566
- desc.attributes = attributes;
3736
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3567
3737
  return desc;
3568
3738
  }
3569
3739
 
3570
3740
  template <typename T>
3571
- template <typename ObjectWrap<T>::InstanceMethodCallback method>
3572
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3573
- const char* utf8name,
3741
+ template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3742
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3743
+ Symbol name,
3574
3744
  napi_property_attributes attributes,
3575
3745
  void* data) {
3576
3746
  napi_property_descriptor desc = napi_property_descriptor();
3577
- desc.utf8name = utf8name;
3578
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3747
+ desc.name = name;
3748
+ desc.method = details::TemplatedVoidCallback<method>;
3579
3749
  desc.data = data;
3580
- desc.attributes = attributes;
3750
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3581
3751
  return desc;
3582
3752
  }
3583
3753
 
3584
3754
  template <typename T>
3585
- template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3586
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3587
- Symbol name,
3755
+ template <typename ObjectWrap<T>::StaticMethodCallback method>
3756
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3757
+ const char* utf8name,
3588
3758
  napi_property_attributes attributes,
3589
3759
  void* data) {
3590
3760
  napi_property_descriptor desc = napi_property_descriptor();
3591
- desc.name = name;
3592
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3761
+ desc.utf8name = utf8name;
3762
+ desc.method = details::TemplatedCallback<method>;
3593
3763
  desc.data = data;
3594
- desc.attributes = attributes;
3764
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3595
3765
  return desc;
3596
3766
  }
3597
3767
 
3598
3768
  template <typename T>
3599
- template <typename ObjectWrap<T>::InstanceMethodCallback method>
3600
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
3769
+ template <typename ObjectWrap<T>::StaticMethodCallback method>
3770
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
3601
3771
  Symbol name,
3602
3772
  napi_property_attributes attributes,
3603
3773
  void* data) {
3604
3774
  napi_property_descriptor desc = napi_property_descriptor();
3605
3775
  desc.name = name;
3606
- desc.method = &ObjectWrap<T>::WrappedMethod<method>;
3776
+ desc.method = details::TemplatedCallback<method>;
3607
3777
  desc.data = data;
3608
- desc.attributes = attributes;
3778
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3609
3779
  return desc;
3610
3780
  }
3611
3781
 
3612
3782
  template <typename T>
3613
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3783
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3614
3784
  const char* utf8name,
3615
- InstanceGetterCallback getter,
3616
- InstanceSetterCallback setter,
3785
+ StaticGetterCallback getter,
3786
+ StaticSetterCallback setter,
3617
3787
  napi_property_attributes attributes,
3618
3788
  void* data) {
3619
- InstanceAccessorCallbackData* callbackData =
3620
- new InstanceAccessorCallbackData({ getter, setter, data });
3789
+ StaticAccessorCallbackData* callbackData =
3790
+ new StaticAccessorCallbackData({ getter, setter, data });
3621
3791
 
3622
3792
  napi_property_descriptor desc = napi_property_descriptor();
3623
3793
  desc.utf8name = utf8name;
3624
- desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3625
- desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3794
+ desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3795
+ desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3626
3796
  desc.data = callbackData;
3627
- desc.attributes = attributes;
3797
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3628
3798
  return desc;
3629
3799
  }
3630
3800
 
3631
3801
  template <typename T>
3632
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3802
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3633
3803
  Symbol name,
3634
- InstanceGetterCallback getter,
3635
- InstanceSetterCallback setter,
3804
+ StaticGetterCallback getter,
3805
+ StaticSetterCallback setter,
3636
3806
  napi_property_attributes attributes,
3637
3807
  void* data) {
3638
- InstanceAccessorCallbackData* callbackData =
3639
- new InstanceAccessorCallbackData({ getter, setter, data });
3808
+ StaticAccessorCallbackData* callbackData =
3809
+ new StaticAccessorCallbackData({ getter, setter, data });
3640
3810
 
3641
3811
  napi_property_descriptor desc = napi_property_descriptor();
3642
3812
  desc.name = name;
3643
- desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
3644
- desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
3813
+ desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
3814
+ desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
3645
3815
  desc.data = callbackData;
3646
- desc.attributes = attributes;
3816
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3647
3817
  return desc;
3648
3818
  }
3649
3819
 
3650
3820
  template <typename T>
3651
- template <typename ObjectWrap<T>::InstanceGetterCallback getter,
3652
- typename ObjectWrap<T>::InstanceSetterCallback setter>
3653
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3821
+ template <typename ObjectWrap<T>::StaticGetterCallback getter,
3822
+ typename ObjectWrap<T>::StaticSetterCallback setter>
3823
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3654
3824
  const char* utf8name,
3655
3825
  napi_property_attributes attributes,
3656
3826
  void* data) {
3657
3827
  napi_property_descriptor desc = napi_property_descriptor();
3658
3828
  desc.utf8name = utf8name;
3659
- desc.getter = This::WrapGetter(This::GetterTag<getter>());
3660
- desc.setter = This::WrapSetter(This::SetterTag<setter>());
3829
+ desc.getter = details::TemplatedCallback<getter>;
3830
+ desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3661
3831
  desc.data = data;
3662
- desc.attributes = attributes;
3832
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3663
3833
  return desc;
3664
3834
  }
3665
3835
 
3666
3836
  template <typename T>
3667
- template <typename ObjectWrap<T>::InstanceGetterCallback getter,
3668
- typename ObjectWrap<T>::InstanceSetterCallback setter>
3669
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
3837
+ template <typename ObjectWrap<T>::StaticGetterCallback getter,
3838
+ typename ObjectWrap<T>::StaticSetterCallback setter>
3839
+ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
3670
3840
  Symbol name,
3671
3841
  napi_property_attributes attributes,
3672
3842
  void* data) {
3673
3843
  napi_property_descriptor desc = napi_property_descriptor();
3674
3844
  desc.name = name;
3675
- desc.getter = This::WrapGetter(This::GetterTag<getter>());
3676
- desc.setter = This::WrapSetter(This::SetterTag<setter>());
3845
+ desc.getter = details::TemplatedCallback<getter>;
3846
+ desc.setter = This::WrapStaticSetter(This::StaticSetterTag<setter>());
3677
3847
  desc.data = data;
3678
- desc.attributes = attributes;
3848
+ desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
3679
3849
  return desc;
3680
3850
  }
3681
3851
 
@@ -3699,30 +3869,6 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(Symbol name,
3699
3869
  return desc;
3700
3870
  }
3701
3871
 
3702
- template <typename T>
3703
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
3704
- const char* utf8name,
3705
- Napi::Value value,
3706
- napi_property_attributes attributes) {
3707
- napi_property_descriptor desc = napi_property_descriptor();
3708
- desc.utf8name = utf8name;
3709
- desc.value = value;
3710
- desc.attributes = attributes;
3711
- return desc;
3712
- }
3713
-
3714
- template <typename T>
3715
- inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
3716
- Symbol name,
3717
- Napi::Value value,
3718
- napi_property_attributes attributes) {
3719
- napi_property_descriptor desc = napi_property_descriptor();
3720
- desc.name = name;
3721
- desc.value = value;
3722
- desc.attributes = attributes;
3723
- return desc;
3724
- }
3725
-
3726
3872
  template <typename T>
3727
3873
  inline void ObjectWrap<T>::Finalize(Napi::Env /*env*/) {}
3728
3874
 
@@ -3815,68 +3961,6 @@ inline napi_value ObjectWrap<T>::StaticSetterCallbackWrapper(
3815
3961
  });
3816
3962
  }
3817
3963
 
3818
- template <typename T>
3819
- inline napi_value ObjectWrap<T>::InstanceVoidMethodCallbackWrapper(
3820
- napi_env env,
3821
- napi_callback_info info) {
3822
- return details::WrapCallback([&] {
3823
- CallbackInfo callbackInfo(env, info);
3824
- InstanceVoidMethodCallbackData* callbackData =
3825
- reinterpret_cast<InstanceVoidMethodCallbackData*>(callbackInfo.Data());
3826
- callbackInfo.SetData(callbackData->data);
3827
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3828
- auto cb = callbackData->callback;
3829
- (instance->*cb)(callbackInfo);
3830
- return nullptr;
3831
- });
3832
- }
3833
-
3834
- template <typename T>
3835
- inline napi_value ObjectWrap<T>::InstanceMethodCallbackWrapper(
3836
- napi_env env,
3837
- napi_callback_info info) {
3838
- return details::WrapCallback([&] {
3839
- CallbackInfo callbackInfo(env, info);
3840
- InstanceMethodCallbackData* callbackData =
3841
- reinterpret_cast<InstanceMethodCallbackData*>(callbackInfo.Data());
3842
- callbackInfo.SetData(callbackData->data);
3843
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3844
- auto cb = callbackData->callback;
3845
- return (instance->*cb)(callbackInfo);
3846
- });
3847
- }
3848
-
3849
- template <typename T>
3850
- inline napi_value ObjectWrap<T>::InstanceGetterCallbackWrapper(
3851
- napi_env env,
3852
- napi_callback_info info) {
3853
- return details::WrapCallback([&] {
3854
- CallbackInfo callbackInfo(env, info);
3855
- InstanceAccessorCallbackData* callbackData =
3856
- reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
3857
- callbackInfo.SetData(callbackData->data);
3858
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3859
- auto cb = callbackData->getterCallback;
3860
- return (instance->*cb)(callbackInfo);
3861
- });
3862
- }
3863
-
3864
- template <typename T>
3865
- inline napi_value ObjectWrap<T>::InstanceSetterCallbackWrapper(
3866
- napi_env env,
3867
- napi_callback_info info) {
3868
- return details::WrapCallback([&] {
3869
- CallbackInfo callbackInfo(env, info);
3870
- InstanceAccessorCallbackData* callbackData =
3871
- reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
3872
- callbackInfo.SetData(callbackData->data);
3873
- T* instance = Unwrap(callbackInfo.This().As<Object>());
3874
- auto cb = callbackData->setterCallback;
3875
- (instance->*cb)(callbackInfo, callbackInfo[0]);
3876
- return nullptr;
3877
- });
3878
- }
3879
-
3880
3964
  template <typename T>
3881
3965
  inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hint*/) {
3882
3966
  T* instance = static_cast<T*>(data);
@@ -3884,44 +3968,6 @@ inline void ObjectWrap<T>::FinalizeCallback(napi_env env, void* data, void* /*hi
3884
3968
  delete instance;
3885
3969
  }
3886
3970
 
3887
- template <typename T>
3888
- template <typename ObjectWrap<T>::StaticVoidMethodCallback method>
3889
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3890
- return details::WrapCallback([&] {
3891
- method(CallbackInfo(env, info));
3892
- return nullptr;
3893
- });
3894
- }
3895
-
3896
- template <typename T>
3897
- template <typename ObjectWrap<T>::StaticMethodCallback method>
3898
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3899
- return details::WrapCallback([&] {
3900
- return method(CallbackInfo(env, info));
3901
- });
3902
- }
3903
-
3904
- template <typename T>
3905
- template <typename ObjectWrap<T>::InstanceVoidMethodCallback method>
3906
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3907
- return details::WrapCallback([&] {
3908
- const CallbackInfo cbInfo(env, info);
3909
- T* instance = Unwrap(cbInfo.This().As<Object>());
3910
- (instance->*method)(cbInfo);
3911
- return nullptr;
3912
- });
3913
- }
3914
-
3915
- template <typename T>
3916
- template <typename ObjectWrap<T>::InstanceMethodCallback method>
3917
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3918
- return details::WrapCallback([&] {
3919
- const CallbackInfo cbInfo(env, info);
3920
- T* instance = Unwrap(cbInfo.This().As<Object>());
3921
- return (instance->*method)(cbInfo);
3922
- });
3923
- }
3924
-
3925
3971
  template <typename T>
3926
3972
  template <typename ObjectWrap<T>::StaticSetterCallback method>
3927
3973
  inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
@@ -3932,17 +3978,6 @@ inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info
3932
3978
  });
3933
3979
  }
3934
3980
 
3935
- template <typename T>
3936
- template <typename ObjectWrap<T>::InstanceSetterCallback method>
3937
- inline napi_value ObjectWrap<T>::WrappedMethod(napi_env env, napi_callback_info info) noexcept {
3938
- return details::WrapCallback([&] {
3939
- const CallbackInfo cbInfo(env, info);
3940
- T* instance = Unwrap(cbInfo.This().As<Object>());
3941
- (instance->*method)(cbInfo, cbInfo[0]);
3942
- return nullptr;
3943
- });
3944
- }
3945
-
3946
3981
  ////////////////////////////////////////////////////////////////////////////////
3947
3982
  // HandleScope class
3948
3983
  ////////////////////////////////////////////////////////////////////////////////
@@ -5000,6 +5035,49 @@ inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) {
5000
5035
  return result;
5001
5036
  }
5002
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
+
5003
5081
  } // namespace Napi
5004
5082
 
5005
5083
  #endif // SRC_NAPI_INL_H_