koffi 3.0.1 → 3.1.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +32 -3
  2. package/cnoke.cjs +2 -2
  3. package/doc/benchmarks.md +1 -1
  4. package/doc/callbacks.md +7 -26
  5. package/doc/{input.md → composites.md} +161 -147
  6. package/doc/contribute.md +3 -2
  7. package/doc/index.md +0 -14
  8. package/doc/{functions.md → load.md} +54 -113
  9. package/doc/migration.md +4 -7
  10. package/doc/misc.md +0 -103
  11. package/doc/output.md +5 -11
  12. package/doc/pointers.md +76 -17
  13. package/doc/primitives.md +151 -0
  14. package/doc/start.md +3 -13
  15. package/doc/types.md +88 -0
  16. package/doc/unions.md +0 -186
  17. package/doc/values.md +134 -0
  18. package/index.d.ts +375 -308
  19. package/lib/native/base/base.cc +66 -24
  20. package/lib/native/base/base.hh +55 -153
  21. package/package.json +16 -16
  22. package/src/koffi/CMakeLists.txt +20 -17
  23. package/src/koffi/index.cjs +30 -111
  24. package/src/koffi/index.js +22 -96
  25. package/src/koffi/indirect.cjs +30 -111
  26. package/src/koffi/indirect.js +24 -24
  27. package/src/koffi/src/abi/arm64.cc +48 -62
  28. package/src/koffi/src/abi/riscv64.cc +39 -57
  29. package/src/koffi/src/abi/x64sysv.cc +39 -57
  30. package/src/koffi/src/abi/x64win.cc +48 -65
  31. package/src/koffi/src/abi/x86.cc +47 -59
  32. package/src/koffi/src/call.cc +426 -209
  33. package/src/koffi/src/call.hh +7 -11
  34. package/src/koffi/src/ffi.cc +534 -303
  35. package/src/koffi/src/ffi.hh +71 -15
  36. package/src/koffi/src/parser.cc +5 -3
  37. package/src/koffi/src/parser.hh +2 -2
  38. package/src/koffi/src/static.cjs +122 -0
  39. package/src/koffi/src/static.js +125 -0
  40. package/src/koffi/src/type.cc +725 -0
  41. package/src/koffi/src/type.hh +71 -0
  42. package/src/koffi/src/util.cc +117 -1202
  43. package/src/koffi/src/util.hh +158 -156
  44. package/src/koffi/src/uv.cc +17 -11
  45. package/src/koffi/src/uv.hh +2 -1
  46. package/vendor/node-addon-api/README.md +1 -1
  47. package/vendor/node-addon-api/napi-inl.h +213 -35
  48. package/vendor/node-addon-api/napi.h +118 -7
  49. package/doc/variables.md +0 -102
  50. package/indirect.d.ts +0 -322
@@ -18,9 +18,16 @@
18
18
  #if NAPI_HAS_THREADS
19
19
  #include <mutex>
20
20
  #endif // NAPI_HAS_THREADS
21
+ #include <string_view>
21
22
  #include <type_traits>
22
23
  #include <utility>
23
24
 
25
+ #if defined(__clang__) || defined(__GNUC__)
26
+ #define NAPI_NO_SANITIZE_VPTR __attribute__((no_sanitize("vptr")))
27
+ #else
28
+ #define NAPI_NO_SANITIZE_VPTR
29
+ #endif
30
+
24
31
  namespace Napi {
25
32
 
26
33
  #ifdef NAPI_CPP_CUSTOM_NAMESPACE
@@ -80,9 +87,9 @@ inline napi_status AttachData(napi_env env,
80
87
  // and rethrow them as JavaScript exceptions before returning from the callback.
81
88
  template <typename Callable>
82
89
  #ifdef NODE_ADDON_API_CPP_EXCEPTIONS_ALL
83
- inline napi_value WrapPointer(napi_env env, Callable callback) {
90
+ inline napi_value WrapCallback(napi_env env, Callable callback) {
84
91
  #else
85
- inline napi_value WrapPointer(napi_env, Callable callback) {
92
+ inline napi_value WrapCallback(napi_env, Callable callback) {
86
93
  #endif
87
94
  #ifdef NODE_ADDON_API_CPP_EXCEPTIONS
88
95
  try {
@@ -160,7 +167,7 @@ inline void WrapVoidCallback(napi_env, Callable callback) {
160
167
  template <typename Callable, typename Return>
161
168
  struct CallbackData {
162
169
  static inline napi_value Wrapper(napi_env env, napi_callback_info info) {
163
- return details::WrapPointer(env, [&] {
170
+ return details::WrapCallback(env, [&] {
164
171
  CallbackInfo callbackInfo(env, info);
165
172
  CallbackData* callbackData =
166
173
  static_cast<CallbackData*>(callbackInfo.Data());
@@ -176,7 +183,7 @@ struct CallbackData {
176
183
  template <typename Callable>
177
184
  struct CallbackData<Callable, void> {
178
185
  static inline napi_value Wrapper(napi_env env, napi_callback_info info) {
179
- return details::WrapPointer(env, [&] {
186
+ return details::WrapCallback(env, [&] {
180
187
  CallbackInfo callbackInfo(env, info);
181
188
  CallbackData* callbackData =
182
189
  static_cast<CallbackData*>(callbackInfo.Data());
@@ -193,7 +200,7 @@ struct CallbackData<Callable, void> {
193
200
  template <void (*Callback)(const CallbackInfo& info)>
194
201
  napi_value TemplatedVoidCallback(napi_env env,
195
202
  napi_callback_info info) NAPI_NOEXCEPT {
196
- return details::WrapPointer(env, [&] {
203
+ return details::WrapCallback(env, [&] {
197
204
  CallbackInfo cbInfo(env, info);
198
205
  Callback(cbInfo);
199
206
  return nullptr;
@@ -203,7 +210,7 @@ napi_value TemplatedVoidCallback(napi_env env,
203
210
  template <Napi::Value (*Callback)(const CallbackInfo& info)>
204
211
  napi_value TemplatedCallback(napi_env env,
205
212
  napi_callback_info info) NAPI_NOEXCEPT {
206
- return details::WrapPointer(env, [&] {
213
+ return details::WrapCallback(env, [&] {
207
214
  CallbackInfo cbInfo(env, info);
208
215
  // MSVC requires to copy 'Callback' function pointer to a local variable
209
216
  // before invoking it.
@@ -213,23 +220,23 @@ napi_value TemplatedCallback(napi_env env,
213
220
  }
214
221
 
215
222
  template <typename T,
216
- Napi::Value (T::*UnWrapPointer)(const CallbackInfo& info)>
223
+ Napi::Value (T::*UnwrapCallback)(const CallbackInfo& info)>
217
224
  napi_value TemplatedInstanceCallback(napi_env env,
218
225
  napi_callback_info info) NAPI_NOEXCEPT {
219
- return details::WrapPointer(env, [&] {
226
+ return details::WrapCallback(env, [&] {
220
227
  CallbackInfo cbInfo(env, info);
221
228
  T* instance = T::Unwrap(cbInfo.This().As<Object>());
222
- return instance ? (instance->*UnWrapPointer)(cbInfo) : Napi::Value();
229
+ return instance ? (instance->*UnwrapCallback)(cbInfo) : Napi::Value();
223
230
  });
224
231
  }
225
232
 
226
- template <typename T, void (T::*UnWrapPointer)(const CallbackInfo& info)>
233
+ template <typename T, void (T::*UnwrapCallback)(const CallbackInfo& info)>
227
234
  napi_value TemplatedInstanceVoidCallback(napi_env env, napi_callback_info info)
228
235
  NAPI_NOEXCEPT {
229
- return details::WrapPointer(env, [&] {
236
+ return details::WrapCallback(env, [&] {
230
237
  CallbackInfo cbInfo(env, info);
231
238
  T* instance = T::Unwrap(cbInfo.This().As<Object>());
232
- if (instance) (instance->*UnWrapPointer)(cbInfo);
239
+ if (instance) (instance->*UnwrapCallback)(cbInfo);
233
240
  return nullptr;
234
241
  });
235
242
  }
@@ -444,7 +451,7 @@ template <typename Getter, typename Setter>
444
451
  struct AccessorCallbackData {
445
452
  static inline napi_value GetterWrapper(napi_env env,
446
453
  napi_callback_info info) {
447
- return details::WrapPointer(env, [&] {
454
+ return details::WrapCallback(env, [&] {
448
455
  CallbackInfo callbackInfo(env, info);
449
456
  AccessorCallbackData* callbackData =
450
457
  static_cast<AccessorCallbackData*>(callbackInfo.Data());
@@ -455,7 +462,7 @@ struct AccessorCallbackData {
455
462
 
456
463
  static inline napi_value SetterWrapper(napi_env env,
457
464
  napi_callback_info info) {
458
- return details::WrapPointer(env, [&] {
465
+ return details::WrapCallback(env, [&] {
459
466
  CallbackInfo callbackInfo(env, info);
460
467
  AccessorCallbackData* callbackData =
461
468
  static_cast<AccessorCallbackData*>(callbackInfo.Data());
@@ -546,7 +553,7 @@ class HasBasicFinalizer {
546
553
  inline napi_value RegisterModule(napi_env env,
547
554
  napi_value exports,
548
555
  ModuleRegisterCallback registerCallback) {
549
- return details::WrapPointer(env, [&] {
556
+ return details::WrapCallback(env, [&] {
550
557
  return napi_value(
551
558
  registerCallback(Napi::Env(env), Napi::Object(env, exports)));
552
559
  });
@@ -934,6 +941,19 @@ inline bool Value::IsExternal() const {
934
941
  return Type() == napi_external;
935
942
  }
936
943
 
944
+ #ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
945
+ inline bool Value::IsSharedArrayBuffer() const {
946
+ if (IsEmpty()) {
947
+ return false;
948
+ }
949
+
950
+ bool result;
951
+ napi_status status = node_api_is_sharedarraybuffer(_env, _value, &result);
952
+ NAPI_THROW_IF_FAILED(_env, status, false);
953
+ return result;
954
+ }
955
+ #endif
956
+
937
957
  template <typename T>
938
958
  inline T Value::As() const {
939
959
  #ifdef NODE_ADDON_API_ENABLE_TYPE_CHECK_ON_AS
@@ -1180,6 +1200,13 @@ inline Date Date::New(napi_env env, double val) {
1180
1200
  return Date(env, value);
1181
1201
  }
1182
1202
 
1203
+ inline Date Date::New(napi_env env, std::chrono::system_clock::time_point tp) {
1204
+ using namespace std::chrono;
1205
+ auto ms = static_cast<double>(
1206
+ duration_cast<milliseconds>(tp.time_since_epoch()).count());
1207
+ return Date::New(env, ms);
1208
+ }
1209
+
1183
1210
  inline void Date::CheckCast(napi_env env, napi_value value) {
1184
1211
  NAPI_CHECK(value != nullptr, "Date::CheckCast", "empty value");
1185
1212
 
@@ -1236,6 +1263,10 @@ inline String String::New(napi_env env, const std::u16string& val) {
1236
1263
  return String::New(env, val.c_str(), val.size());
1237
1264
  }
1238
1265
 
1266
+ inline String String::New(napi_env env, std::string_view val) {
1267
+ return String::New(env, val.data(), val.size());
1268
+ }
1269
+
1239
1270
  inline String String::New(napi_env env, const char* val) {
1240
1271
  // TODO(@gabrielschulhof) Remove if-statement when core's error handling is
1241
1272
  // available in all supported versions.
@@ -1345,6 +1376,11 @@ inline Symbol Symbol::New(napi_env env, const std::string& description) {
1345
1376
  return Symbol::New(env, descriptionValue);
1346
1377
  }
1347
1378
 
1379
+ inline Symbol Symbol::New(napi_env env, std::string_view description) {
1380
+ napi_value descriptionValue = String::New(env, description);
1381
+ return Symbol::New(env, descriptionValue);
1382
+ }
1383
+
1348
1384
  inline Symbol Symbol::New(napi_env env, String description) {
1349
1385
  napi_value descriptionValue = description;
1350
1386
  return Symbol::New(env, descriptionValue);
@@ -1386,6 +1422,12 @@ inline MaybeOrValue<Symbol> Symbol::For(napi_env env,
1386
1422
  return Symbol::For(env, descriptionValue);
1387
1423
  }
1388
1424
 
1425
+ inline MaybeOrValue<Symbol> Symbol::For(napi_env env,
1426
+ std::string_view description) {
1427
+ napi_value descriptionValue = String::New(env, description);
1428
+ return Symbol::For(env, descriptionValue);
1429
+ }
1430
+
1389
1431
  inline MaybeOrValue<Symbol> Symbol::For(napi_env env, const char* description) {
1390
1432
  napi_value descriptionValue = String::New(env, description);
1391
1433
  return Symbol::For(env, descriptionValue);
@@ -1947,6 +1989,19 @@ inline MaybeOrValue<bool> Object::Seal() const {
1947
1989
  }
1948
1990
  #endif // NAPI_VERSION >= 8
1949
1991
 
1992
+ inline MaybeOrValue<Object> Object::GetPrototype() const {
1993
+ napi_value result;
1994
+ napi_status status = napi_get_prototype(_env, _value, &result);
1995
+ NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Object(_env, result), Object);
1996
+ }
1997
+
1998
+ #ifdef NODE_API_EXPERIMENTAL_HAS_SET_PROTOTYPE
1999
+ inline MaybeOrValue<bool> Object::SetPrototype(const Object& value) const {
2000
+ napi_status status = node_api_set_prototype(_env, _value, value);
2001
+ NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool);
2002
+ }
2003
+ #endif
2004
+
1950
2005
  ////////////////////////////////////////////////////////////////////////////////
1951
2006
  // External class
1952
2007
  ////////////////////////////////////////////////////////////////////////////////
@@ -2068,6 +2123,55 @@ inline uint32_t Array::Length() const {
2068
2123
  return result;
2069
2124
  }
2070
2125
 
2126
+ #ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2127
+ ////////////////////////////////////////////////////////////////////////////////
2128
+ // SharedArrayBuffer class
2129
+ ////////////////////////////////////////////////////////////////////////////////
2130
+
2131
+ inline SharedArrayBuffer::SharedArrayBuffer() : Object() {}
2132
+
2133
+ inline SharedArrayBuffer::SharedArrayBuffer(napi_env env, napi_value value)
2134
+ : Object(env, value) {}
2135
+
2136
+ inline void SharedArrayBuffer::CheckCast(napi_env env, napi_value value) {
2137
+ NAPI_CHECK(value != nullptr, "SharedArrayBuffer::CheckCast", "empty value");
2138
+
2139
+ bool result;
2140
+ napi_status status = node_api_is_sharedarraybuffer(env, value, &result);
2141
+ NAPI_CHECK(status == napi_ok,
2142
+ "SharedArrayBuffer::CheckCast",
2143
+ "node_api_is_sharedarraybuffer failed");
2144
+ NAPI_CHECK(
2145
+ result, "SharedArrayBuffer::CheckCast", "value is not sharedarraybuffer");
2146
+ }
2147
+
2148
+ inline SharedArrayBuffer SharedArrayBuffer::New(napi_env env,
2149
+ size_t byteLength) {
2150
+ napi_value value;
2151
+ void* data;
2152
+ napi_status status =
2153
+ node_api_create_sharedarraybuffer(env, byteLength, &data, &value);
2154
+ NAPI_THROW_IF_FAILED(env, status, SharedArrayBuffer());
2155
+
2156
+ return SharedArrayBuffer(env, value);
2157
+ }
2158
+
2159
+ inline void* SharedArrayBuffer::Data() {
2160
+ void* data;
2161
+ napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr);
2162
+ NAPI_THROW_IF_FAILED(_env, status, nullptr);
2163
+ return data;
2164
+ }
2165
+
2166
+ inline size_t SharedArrayBuffer::ByteLength() {
2167
+ size_t length;
2168
+ napi_status status =
2169
+ napi_get_arraybuffer_info(_env, _value, nullptr, &length);
2170
+ NAPI_THROW_IF_FAILED(_env, status, 0);
2171
+ return length;
2172
+ }
2173
+ #endif // NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2174
+
2071
2175
  ////////////////////////////////////////////////////////////////////////////////
2072
2176
  // ArrayBuffer class
2073
2177
  ////////////////////////////////////////////////////////////////////////////////
@@ -2221,6 +2325,39 @@ inline DataView DataView::New(napi_env env,
2221
2325
  return DataView(env, value);
2222
2326
  }
2223
2327
 
2328
+ #ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2329
+ inline DataView DataView::New(napi_env env,
2330
+ Napi::SharedArrayBuffer arrayBuffer) {
2331
+ return New(env, arrayBuffer, 0, arrayBuffer.ByteLength());
2332
+ }
2333
+
2334
+ inline DataView DataView::New(napi_env env,
2335
+ Napi::SharedArrayBuffer arrayBuffer,
2336
+ size_t byteOffset) {
2337
+ if (byteOffset > arrayBuffer.ByteLength()) {
2338
+ NAPI_THROW(RangeError::New(
2339
+ env, "Start offset is outside the bounds of the buffer"),
2340
+ DataView());
2341
+ }
2342
+ return New(
2343
+ env, arrayBuffer, byteOffset, arrayBuffer.ByteLength() - byteOffset);
2344
+ }
2345
+
2346
+ inline DataView DataView::New(napi_env env,
2347
+ Napi::SharedArrayBuffer arrayBuffer,
2348
+ size_t byteOffset,
2349
+ size_t byteLength) {
2350
+ if (byteOffset + byteLength > arrayBuffer.ByteLength()) {
2351
+ NAPI_THROW(RangeError::New(env, "Invalid DataView length"), DataView());
2352
+ }
2353
+ napi_value value;
2354
+ napi_status status =
2355
+ napi_create_dataview(env, byteLength, arrayBuffer, byteOffset, &value);
2356
+ NAPI_THROW_IF_FAILED(env, status, DataView());
2357
+ return DataView(env, value);
2358
+ }
2359
+ #endif // NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2360
+
2224
2361
  inline void DataView::CheckCast(napi_env env, napi_value value) {
2225
2362
  NAPI_CHECK(value != nullptr, "DataView::CheckCast", "empty value");
2226
2363
 
@@ -2244,6 +2381,10 @@ inline DataView::DataView(napi_env env, napi_value value) : Object(env, value) {
2244
2381
  }
2245
2382
 
2246
2383
  inline Napi::ArrayBuffer DataView::ArrayBuffer() const {
2384
+ return Buffer().As<Napi::ArrayBuffer>();
2385
+ }
2386
+
2387
+ inline Napi::Value DataView::Buffer() const {
2247
2388
  napi_value arrayBuffer;
2248
2389
  napi_status status = napi_get_dataview_info(_env,
2249
2390
  _value /* dataView */,
@@ -2251,8 +2392,8 @@ inline Napi::ArrayBuffer DataView::ArrayBuffer() const {
2251
2392
  nullptr /* data */,
2252
2393
  &arrayBuffer /* arrayBuffer */,
2253
2394
  nullptr /* byteOffset */);
2254
- NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer());
2255
- return Napi::ArrayBuffer(_env, arrayBuffer);
2395
+ NAPI_THROW_IF_FAILED(_env, status, Napi::Value());
2396
+ return Napi::Value(_env, arrayBuffer);
2256
2397
  }
2257
2398
 
2258
2399
  inline size_t DataView::ByteOffset() const {
@@ -2453,6 +2594,14 @@ inline Napi::ArrayBuffer TypedArray::ArrayBuffer() const {
2453
2594
  return Napi::ArrayBuffer(_env, arrayBuffer);
2454
2595
  }
2455
2596
 
2597
+ inline Napi::Value TypedArray::Buffer() const {
2598
+ napi_value arrayBuffer;
2599
+ napi_status status = napi_get_typedarray_info(
2600
+ _env, _value, nullptr, nullptr, nullptr, &arrayBuffer, nullptr);
2601
+ NAPI_THROW_IF_FAILED(_env, status, Napi::Value());
2602
+ return Napi::Value(_env, arrayBuffer);
2603
+ }
2604
+
2456
2605
  ////////////////////////////////////////////////////////////////////////////////
2457
2606
  // TypedArrayOf<T> class
2458
2607
  ////////////////////////////////////////////////////////////////////////////////
@@ -2504,6 +2653,28 @@ inline TypedArrayOf<T> TypedArrayOf<T>::New(napi_env env,
2504
2653
  bufferOffset));
2505
2654
  }
2506
2655
 
2656
+ #ifdef NODE_API_EXPERIMENTAL_HAS_SHAREDARRAYBUFFER
2657
+ template <typename T>
2658
+ inline TypedArrayOf<T> TypedArrayOf<T>::New(napi_env env,
2659
+ size_t elementLength,
2660
+ Napi::SharedArrayBuffer arrayBuffer,
2661
+ size_t bufferOffset,
2662
+ napi_typedarray_type type) {
2663
+ napi_value value;
2664
+ napi_status status = napi_create_typedarray(
2665
+ env, type, elementLength, arrayBuffer, bufferOffset, &value);
2666
+ NAPI_THROW_IF_FAILED(env, status, TypedArrayOf<T>());
2667
+
2668
+ return TypedArrayOf<T>(
2669
+ env,
2670
+ value,
2671
+ type,
2672
+ elementLength,
2673
+ reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(arrayBuffer.Data()) +
2674
+ bufferOffset));
2675
+ }
2676
+ #endif
2677
+
2507
2678
  template <typename T>
2508
2679
  inline TypedArrayOf<T>::TypedArrayOf() : TypedArray(), _data(nullptr) {}
2509
2680
 
@@ -3741,8 +3912,8 @@ inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
3741
3912
  return Value().Set(utf8name, value);
3742
3913
  }
3743
3914
 
3744
- inline MaybeOrValue<bool> ObjectReference::Set(const std::string& utf8name,
3745
- std::string& utf8value) const {
3915
+ inline MaybeOrValue<bool> ObjectReference::Set(
3916
+ const std::string& utf8name, const std::string& utf8value) const {
3746
3917
  HandleScope scope(_env);
3747
3918
  return Value().Set(utf8name, utf8value);
3748
3919
  }
@@ -4649,7 +4820,7 @@ inline ClassPropertyDescriptor<T> InstanceWrap<T>::InstanceValue(
4649
4820
  template <typename T>
4650
4821
  inline napi_value InstanceWrap<T>::InstanceVoidMethodCallbackWrapper(
4651
4822
  napi_env env, napi_callback_info info) {
4652
- return details::WrapPointer(env, [&] {
4823
+ return details::WrapCallback(env, [&] {
4653
4824
  CallbackInfo callbackInfo(env, info);
4654
4825
  InstanceVoidMethodCallbackData* callbackData =
4655
4826
  reinterpret_cast<InstanceVoidMethodCallbackData*>(callbackInfo.Data());
@@ -4664,7 +4835,7 @@ inline napi_value InstanceWrap<T>::InstanceVoidMethodCallbackWrapper(
4664
4835
  template <typename T>
4665
4836
  inline napi_value InstanceWrap<T>::InstanceMethodCallbackWrapper(
4666
4837
  napi_env env, napi_callback_info info) {
4667
- return details::WrapPointer(env, [&] {
4838
+ return details::WrapCallback(env, [&] {
4668
4839
  CallbackInfo callbackInfo(env, info);
4669
4840
  InstanceMethodCallbackData* callbackData =
4670
4841
  reinterpret_cast<InstanceMethodCallbackData*>(callbackInfo.Data());
@@ -4678,7 +4849,7 @@ inline napi_value InstanceWrap<T>::InstanceMethodCallbackWrapper(
4678
4849
  template <typename T>
4679
4850
  inline napi_value InstanceWrap<T>::InstanceGetterCallbackWrapper(
4680
4851
  napi_env env, napi_callback_info info) {
4681
- return details::WrapPointer(env, [&] {
4852
+ return details::WrapCallback(env, [&] {
4682
4853
  CallbackInfo callbackInfo(env, info);
4683
4854
  InstanceAccessorCallbackData* callbackData =
4684
4855
  reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
@@ -4692,7 +4863,7 @@ inline napi_value InstanceWrap<T>::InstanceGetterCallbackWrapper(
4692
4863
  template <typename T>
4693
4864
  inline napi_value InstanceWrap<T>::InstanceSetterCallbackWrapper(
4694
4865
  napi_env env, napi_callback_info info) {
4695
- return details::WrapPointer(env, [&] {
4866
+ return details::WrapCallback(env, [&] {
4696
4867
  CallbackInfo callbackInfo(env, info);
4697
4868
  InstanceAccessorCallbackData* callbackData =
4698
4869
  reinterpret_cast<InstanceAccessorCallbackData*>(callbackInfo.Data());
@@ -4708,7 +4879,7 @@ template <typename T>
4708
4879
  template <typename InstanceWrap<T>::InstanceSetterCallback method>
4709
4880
  inline napi_value InstanceWrap<T>::WrappedMethod(
4710
4881
  napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
4711
- return details::WrapPointer(env, [&] {
4882
+ return details::WrapCallback(env, [&] {
4712
4883
  const CallbackInfo cbInfo(env, info);
4713
4884
  T* instance = T::Unwrap(cbInfo.This().As<Object>());
4714
4885
  if (instance) (instance->*method)(cbInfo, cbInfo[0]);
@@ -4721,7 +4892,8 @@ inline napi_value InstanceWrap<T>::WrappedMethod(
4721
4892
  ////////////////////////////////////////////////////////////////////////////////
4722
4893
 
4723
4894
  template <typename T>
4724
- inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
4895
+ inline NAPI_NO_SANITIZE_VPTR ObjectWrap<T>::ObjectWrap(
4896
+ const Napi::CallbackInfo& callbackInfo) {
4725
4897
  napi_env env = callbackInfo.Env();
4726
4898
  napi_value wrapper = callbackInfo.This();
4727
4899
  napi_status status;
@@ -4735,7 +4907,7 @@ inline ObjectWrap<T>::ObjectWrap(const Napi::CallbackInfo& callbackInfo) {
4735
4907
  }
4736
4908
 
4737
4909
  template <typename T>
4738
- inline ObjectWrap<T>::~ObjectWrap() {
4910
+ inline NAPI_NO_SANITIZE_VPTR ObjectWrap<T>::~ObjectWrap() {
4739
4911
  // If the JS object still exists at this point, remove the finalizer added
4740
4912
  // through `napi_wrap()`.
4741
4913
  if (!IsEmpty() && !_finalized) {
@@ -4748,8 +4920,12 @@ inline ObjectWrap<T>::~ObjectWrap() {
4748
4920
  }
4749
4921
  }
4750
4922
 
4923
+ // with RTTI turned on, modern compilers check to see if virtual function
4924
+ // pointers are stripped of RTTI by void casts. this is intrinsic to how Unwrap
4925
+ // works, so we inject a compiler pragma to turn off that check just for the
4926
+ // affected methods. this compiler check is on by default in Android NDK 29.
4751
4927
  template <typename T>
4752
- inline T* ObjectWrap<T>::Unwrap(Object wrapper) {
4928
+ inline NAPI_NO_SANITIZE_VPTR T* ObjectWrap<T>::Unwrap(Object wrapper) {
4753
4929
  void* unwrapped;
4754
4930
  napi_status status = napi_unwrap(wrapper.Env(), wrapper, &unwrapped);
4755
4931
  NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr);
@@ -5102,11 +5278,11 @@ inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
5102
5278
 
5103
5279
  bool isConstructCall = (new_target != nullptr);
5104
5280
  if (!isConstructCall) {
5105
- return details::WrapPointer(
5281
+ return details::WrapCallback(
5106
5282
  env, [&] { return T::OnCalledAsFunction(CallbackInfo(env, info)); });
5107
5283
  }
5108
5284
 
5109
- napi_value wrapper = details::WrapPointer(env, [&] {
5285
+ napi_value wrapper = details::WrapCallback(env, [&] {
5110
5286
  CallbackInfo callbackInfo(env, info);
5111
5287
  T* instance = new T(callbackInfo);
5112
5288
  #ifdef NODE_ADDON_API_CPP_EXCEPTIONS
@@ -5130,7 +5306,7 @@ inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
5130
5306
  template <typename T>
5131
5307
  inline napi_value ObjectWrap<T>::StaticVoidMethodCallbackWrapper(
5132
5308
  napi_env env, napi_callback_info info) {
5133
- return details::WrapPointer(env, [&] {
5309
+ return details::WrapCallback(env, [&] {
5134
5310
  CallbackInfo callbackInfo(env, info);
5135
5311
  StaticVoidMethodCallbackData* callbackData =
5136
5312
  reinterpret_cast<StaticVoidMethodCallbackData*>(callbackInfo.Data());
@@ -5143,7 +5319,7 @@ inline napi_value ObjectWrap<T>::StaticVoidMethodCallbackWrapper(
5143
5319
  template <typename T>
5144
5320
  inline napi_value ObjectWrap<T>::StaticMethodCallbackWrapper(
5145
5321
  napi_env env, napi_callback_info info) {
5146
- return details::WrapPointer(env, [&] {
5322
+ return details::WrapCallback(env, [&] {
5147
5323
  CallbackInfo callbackInfo(env, info);
5148
5324
  StaticMethodCallbackData* callbackData =
5149
5325
  reinterpret_cast<StaticMethodCallbackData*>(callbackInfo.Data());
@@ -5155,7 +5331,7 @@ inline napi_value ObjectWrap<T>::StaticMethodCallbackWrapper(
5155
5331
  template <typename T>
5156
5332
  inline napi_value ObjectWrap<T>::StaticGetterCallbackWrapper(
5157
5333
  napi_env env, napi_callback_info info) {
5158
- return details::WrapPointer(env, [&] {
5334
+ return details::WrapCallback(env, [&] {
5159
5335
  CallbackInfo callbackInfo(env, info);
5160
5336
  StaticAccessorCallbackData* callbackData =
5161
5337
  reinterpret_cast<StaticAccessorCallbackData*>(callbackInfo.Data());
@@ -5167,7 +5343,7 @@ inline napi_value ObjectWrap<T>::StaticGetterCallbackWrapper(
5167
5343
  template <typename T>
5168
5344
  inline napi_value ObjectWrap<T>::StaticSetterCallbackWrapper(
5169
5345
  napi_env env, napi_callback_info info) {
5170
- return details::WrapPointer(env, [&] {
5346
+ return details::WrapCallback(env, [&] {
5171
5347
  CallbackInfo callbackInfo(env, info);
5172
5348
  StaticAccessorCallbackData* callbackData =
5173
5349
  reinterpret_cast<StaticAccessorCallbackData*>(callbackInfo.Data());
@@ -5238,7 +5414,7 @@ template <typename T>
5238
5414
  template <typename ObjectWrap<T>::StaticSetterCallback method>
5239
5415
  inline napi_value ObjectWrap<T>::WrappedMethod(
5240
5416
  napi_env env, napi_callback_info info) NAPI_NOEXCEPT {
5241
- return details::WrapPointer(env, [&] {
5417
+ return details::WrapCallback(env, [&] {
5242
5418
  const CallbackInfo cbInfo(env, info);
5243
5419
  // MSVC requires to copy 'method' function pointer to a local variable
5244
5420
  // before invoking it.
@@ -5559,7 +5735,7 @@ inline void AsyncWorker::OnAsyncWorkComplete(napi_env env,
5559
5735
  inline void AsyncWorker::OnWorkComplete(Napi::Env env, napi_status status) {
5560
5736
  if (status != napi_cancelled) {
5561
5737
  HandleScope scope(_env);
5562
- details::WrapPointer(env, [&] {
5738
+ details::WrapCallback(env, [&] {
5563
5739
  if (_error.size() == 0) {
5564
5740
  OnOK();
5565
5741
  } else {
@@ -7030,4 +7206,6 @@ inline void BasicEnv::PostFinalizer(FinalizerType finalizeCallback,
7030
7206
 
7031
7207
  } // namespace Napi
7032
7208
 
7209
+ #undef NAPI_NO_SANITIZE_VPTR
7210
+
7033
7211
  #endif // SRC_NAPI_INL_H_