koffi 2.3.4 → 2.3.6-beta.1

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 (206) hide show
  1. package/CHANGELOG.md +25 -2
  2. package/doc/changelog.md +4 -0
  3. package/doc/index.rst +1 -2
  4. package/doc/types.md +3 -3
  5. package/package.json +5 -5
  6. package/src/cnoke/cnoke.js +40 -834
  7. package/src/cnoke/package.json +1 -0
  8. package/src/cnoke/src/builder.js +447 -0
  9. package/src/cnoke/src/index.js +20 -0
  10. package/src/cnoke/src/tools.js +401 -0
  11. package/src/core/libcc/libcc.cc +2 -2
  12. package/src/koffi/build/2.3.6-beta.1/koffi_darwin_arm64/koffi.node +0 -0
  13. package/src/koffi/build/2.3.6-beta.1/koffi_darwin_x64/koffi.node +0 -0
  14. package/src/koffi/build/2.3.6-beta.1/koffi_freebsd_arm64/koffi.node +0 -0
  15. package/src/koffi/build/2.3.6-beta.1/koffi_freebsd_ia32/koffi.node +0 -0
  16. package/src/koffi/build/2.3.6-beta.1/koffi_freebsd_x64/koffi.node +0 -0
  17. package/src/koffi/build/2.3.6-beta.1/koffi_linux_arm32hf/koffi.node +0 -0
  18. package/src/koffi/build/2.3.6-beta.1/koffi_linux_arm64/koffi.node +0 -0
  19. package/src/koffi/build/2.3.6-beta.1/koffi_linux_ia32/koffi.node +0 -0
  20. package/src/koffi/build/2.3.6-beta.1/koffi_linux_riscv64hf64/koffi.node +0 -0
  21. package/src/koffi/build/2.3.6-beta.1/koffi_linux_x64/koffi.node +0 -0
  22. package/src/koffi/build/2.3.6-beta.1/koffi_openbsd_ia32/koffi.node +0 -0
  23. package/src/koffi/build/2.3.6-beta.1/koffi_openbsd_x64/koffi.node +0 -0
  24. package/src/koffi/build/2.3.6-beta.1/koffi_win32_arm64/koffi.exp +0 -0
  25. package/src/koffi/build/2.3.6-beta.1/koffi_win32_arm64/koffi.lib +0 -0
  26. package/src/koffi/build/2.3.6-beta.1/koffi_win32_arm64/koffi.node +0 -0
  27. package/src/koffi/build/2.3.6-beta.1/koffi_win32_arm64/koffi.pdb +0 -0
  28. package/src/koffi/build/2.3.6-beta.1/koffi_win32_ia32/koffi.exp +0 -0
  29. package/src/koffi/build/2.3.6-beta.1/koffi_win32_ia32/koffi.lib +0 -0
  30. package/src/koffi/build/2.3.6-beta.1/koffi_win32_ia32/koffi.node +0 -0
  31. package/src/koffi/build/2.3.6-beta.1/koffi_win32_ia32/koffi.pdb +0 -0
  32. package/src/koffi/build/2.3.6-beta.1/koffi_win32_x64/koffi.exp +0 -0
  33. package/src/koffi/build/2.3.6-beta.1/koffi_win32_x64/koffi.lib +0 -0
  34. package/src/koffi/build/2.3.6-beta.1/koffi_win32_x64/koffi.node +0 -0
  35. package/src/koffi/build/2.3.6-beta.1/koffi_win32_x64/koffi.pdb +0 -0
  36. package/src/koffi/src/abi_arm32.cc +43 -14
  37. package/src/koffi/src/abi_arm64.cc +95 -21
  38. package/src/koffi/src/abi_riscv64.cc +125 -64
  39. package/src/koffi/src/abi_x64_sysv.cc +38 -20
  40. package/src/koffi/src/abi_x64_win.cc +11 -5
  41. package/src/koffi/src/abi_x86.cc +14 -7
  42. package/src/koffi/src/call.cc +114 -44
  43. package/src/koffi/src/call.hh +6 -4
  44. package/src/koffi/src/ffi.cc +172 -147
  45. package/src/koffi/src/ffi.hh +18 -10
  46. package/src/koffi/src/index.d.ts +28 -7
  47. package/src/koffi/src/index.js +23 -4
  48. package/src/koffi/src/util.cc +261 -69
  49. package/src/koffi/src/util.hh +34 -8
  50. package/vendor/node-addon-api/CHANGELOG.md +122 -9
  51. package/vendor/node-addon-api/CONTRIBUTING.md +10 -10
  52. package/vendor/node-addon-api/README.md +36 -12
  53. package/vendor/node-addon-api/benchmark/function_args.cc +95 -62
  54. package/vendor/node-addon-api/benchmark/function_args.js +6 -6
  55. package/vendor/node-addon-api/benchmark/index.js +1 -1
  56. package/vendor/node-addon-api/benchmark/property_descriptor.cc +27 -34
  57. package/vendor/node-addon-api/benchmark/property_descriptor.js +5 -4
  58. package/vendor/node-addon-api/doc/async_operations.md +1 -1
  59. package/vendor/node-addon-api/doc/async_worker_variants.md +23 -2
  60. package/vendor/node-addon-api/doc/cmake-js.md +1 -1
  61. package/vendor/node-addon-api/doc/error_handling.md +3 -3
  62. package/vendor/node-addon-api/doc/external.md +7 -0
  63. package/vendor/node-addon-api/doc/handle_scope.md +14 -0
  64. package/vendor/node-addon-api/doc/hierarchy.md +1 -1
  65. package/vendor/node-addon-api/doc/object.md +27 -0
  66. package/vendor/node-addon-api/index.js +3 -3
  67. package/vendor/node-addon-api/napi-inl.deprecated.h +121 -127
  68. package/vendor/node-addon-api/napi-inl.h +1178 -1144
  69. package/vendor/node-addon-api/napi.h +2786 -2675
  70. package/vendor/node-addon-api/package.json +42 -1
  71. package/vendor/node-addon-api/test/addon.cc +8 -6
  72. package/vendor/node-addon-api/test/addon_build/index.js +9 -9
  73. package/vendor/node-addon-api/test/addon_build/tpl/addon.cc +2 -1
  74. package/vendor/node-addon-api/test/addon_build/tpl/index.js +4 -4
  75. package/vendor/node-addon-api/test/addon_data.cc +12 -13
  76. package/vendor/node-addon-api/test/array_buffer.js +3 -2
  77. package/vendor/node-addon-api/test/async_progress_queue_worker.cc +13 -3
  78. package/vendor/node-addon-api/test/async_progress_queue_worker.js +5 -5
  79. package/vendor/node-addon-api/test/async_progress_worker.cc +65 -9
  80. package/vendor/node-addon-api/test/async_progress_worker.js +14 -9
  81. package/vendor/node-addon-api/test/async_worker.cc +236 -3
  82. package/vendor/node-addon-api/test/async_worker.js +122 -37
  83. package/vendor/node-addon-api/test/async_worker_nocallback.js +9 -3
  84. package/vendor/node-addon-api/test/async_worker_persistent.js +2 -2
  85. package/vendor/node-addon-api/test/basic_types/array.js +3 -4
  86. package/vendor/node-addon-api/test/basic_types/boolean.cc +4 -2
  87. package/vendor/node-addon-api/test/basic_types/boolean.js +1 -2
  88. package/vendor/node-addon-api/test/basic_types/number.cc +12 -6
  89. package/vendor/node-addon-api/test/basic_types/number.js +19 -18
  90. package/vendor/node-addon-api/test/basic_types/value.cc +52 -1
  91. package/vendor/node-addon-api/test/basic_types/value.js +44 -21
  92. package/vendor/node-addon-api/test/bigint.cc +2 -1
  93. package/vendor/node-addon-api/test/binding.cc +11 -5
  94. package/vendor/node-addon-api/test/binding.gyp +3 -1
  95. package/vendor/node-addon-api/test/buffer.cc +46 -38
  96. package/vendor/node-addon-api/test/buffer.js +12 -12
  97. package/vendor/node-addon-api/test/callbackInfo.cc +27 -0
  98. package/vendor/node-addon-api/test/callbackInfo.js +9 -0
  99. package/vendor/node-addon-api/test/callbackscope.cc +19 -2
  100. package/vendor/node-addon-api/test/callbackscope.js +20 -20
  101. package/vendor/node-addon-api/test/common/index.js +37 -4
  102. package/vendor/node-addon-api/test/dataview/dataview.js +5 -5
  103. package/vendor/node-addon-api/test/dataview/dataview_read_write.js +14 -12
  104. package/vendor/node-addon-api/test/date.cc +2 -1
  105. package/vendor/node-addon-api/test/date.js +2 -2
  106. package/vendor/node-addon-api/test/env_cleanup.cc +12 -0
  107. package/vendor/node-addon-api/test/env_cleanup.js +38 -39
  108. package/vendor/node-addon-api/test/error.cc +6 -5
  109. package/vendor/node-addon-api/test/error_terminating_environment.js +64 -60
  110. package/vendor/node-addon-api/test/external.cc +36 -32
  111. package/vendor/node-addon-api/test/external.js +43 -46
  112. package/vendor/node-addon-api/test/function.cc +58 -44
  113. package/vendor/node-addon-api/test/function.js +4 -0
  114. package/vendor/node-addon-api/test/function_reference.cc +15 -13
  115. package/vendor/node-addon-api/test/globalObject/global_object_delete_property.js +50 -53
  116. package/vendor/node-addon-api/test/globalObject/global_object_get_property.js +33 -34
  117. package/vendor/node-addon-api/test/globalObject/global_object_has_own_property.js +38 -40
  118. package/vendor/node-addon-api/test/globalObject/global_object_set_property.js +47 -49
  119. package/vendor/node-addon-api/test/handlescope.cc +29 -3
  120. package/vendor/node-addon-api/test/handlescope.js +5 -3
  121. package/vendor/node-addon-api/test/index.js +1 -5
  122. package/vendor/node-addon-api/test/maybe/check.cc +49 -3
  123. package/vendor/node-addon-api/test/maybe/index.js +19 -7
  124. package/vendor/node-addon-api/test/memory_management.cc +9 -8
  125. package/vendor/node-addon-api/test/memory_management.js +2 -2
  126. package/vendor/node-addon-api/test/movable_callbacks.js +2 -2
  127. package/vendor/node-addon-api/test/name.js +3 -3
  128. package/vendor/node-addon-api/test/napi_child.js +2 -2
  129. package/vendor/node-addon-api/test/object/delete_property.js +7 -7
  130. package/vendor/node-addon-api/test/object/finalizer.cc +13 -12
  131. package/vendor/node-addon-api/test/object/finalizer.js +2 -2
  132. package/vendor/node-addon-api/test/object/get_property.js +6 -6
  133. package/vendor/node-addon-api/test/object/has_own_property.js +3 -3
  134. package/vendor/node-addon-api/test/object/has_property.js +4 -4
  135. package/vendor/node-addon-api/test/object/object.cc +191 -111
  136. package/vendor/node-addon-api/test/object/object.js +53 -52
  137. package/vendor/node-addon-api/test/object/object_deprecated.cc +24 -20
  138. package/vendor/node-addon-api/test/object/object_deprecated.js +3 -8
  139. package/vendor/node-addon-api/test/object/object_freeze_seal.js +54 -54
  140. package/vendor/node-addon-api/test/object/object_type_tag.cc +39 -0
  141. package/vendor/node-addon-api/test/object/object_type_tag.js +55 -0
  142. package/vendor/node-addon-api/test/object/subscript_operator.js +2 -2
  143. package/vendor/node-addon-api/test/object_reference.js +100 -100
  144. package/vendor/node-addon-api/test/objectwrap.cc +41 -34
  145. package/vendor/node-addon-api/test/objectwrap.js +23 -19
  146. package/vendor/node-addon-api/test/objectwrap_constructor_exception.cc +5 -5
  147. package/vendor/node-addon-api/test/objectwrap_constructor_exception.js +1 -1
  148. package/vendor/node-addon-api/test/objectwrap_multiple_inheritance.cc +7 -7
  149. package/vendor/node-addon-api/test/objectwrap_multiple_inheritance.js +1 -1
  150. package/vendor/node-addon-api/test/objectwrap_removewrap.js +24 -32
  151. package/vendor/node-addon-api/test/objectwrap_worker_thread.js +5 -4
  152. package/vendor/node-addon-api/test/promise.cc +7 -0
  153. package/vendor/node-addon-api/test/promise.js +3 -1
  154. package/vendor/node-addon-api/test/reference.cc +1 -1
  155. package/vendor/node-addon-api/test/reference.js +2 -2
  156. package/vendor/node-addon-api/test/run_script.cc +1 -1
  157. package/vendor/node-addon-api/test/symbol.js +59 -66
  158. package/vendor/node-addon-api/test/testUtil.js +6 -6
  159. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function.cc +64 -29
  160. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function.js +71 -34
  161. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ctx.cc +111 -19
  162. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ctx.js +2 -1
  163. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_existing_tsfn.cc +36 -26
  164. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_existing_tsfn.js +5 -5
  165. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ptr.cc +3 -2
  166. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ptr.js +1 -1
  167. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_sum.cc +47 -32
  168. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_sum.js +3 -3
  169. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_unref.cc +22 -9
  170. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_unref.js +76 -31
  171. package/vendor/node-addon-api/test/thunking_manual.cc +61 -74
  172. package/vendor/node-addon-api/test/thunking_manual.js +6 -7
  173. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function.cc +20 -20
  174. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function.js +19 -19
  175. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ctx.cc +57 -5
  176. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ctx.js +2 -0
  177. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_existing_tsfn.js +5 -5
  178. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ptr.cc +5 -1
  179. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ptr.js +4 -3
  180. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_sum.js +3 -3
  181. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_unref.cc +14 -0
  182. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_unref.js +76 -31
  183. package/vendor/node-addon-api/test/typedarray-bigint.js +2 -2
  184. package/vendor/node-addon-api/test/typedarray.cc +263 -70
  185. package/vendor/node-addon-api/test/typedarray.js +44 -10
  186. package/vendor/node-addon-api/test/version_management.cc +16 -15
  187. package/vendor/node-addon-api/test/version_management.js +18 -20
  188. package/vendor/node-addon-api/tools/check-napi.js +13 -14
  189. package/vendor/node-addon-api/tools/conversion.js +161 -169
  190. package/vendor/node-addon-api/tools/eslint-format.js +9 -1
  191. package/vendor/node-addon-api/unit-test/README.md +4 -4
  192. package/src/koffi/build/2.3.4/koffi_darwin_arm64.tar.gz +0 -0
  193. package/src/koffi/build/2.3.4/koffi_darwin_x64.tar.gz +0 -0
  194. package/src/koffi/build/2.3.4/koffi_freebsd_arm64.tar.gz +0 -0
  195. package/src/koffi/build/2.3.4/koffi_freebsd_ia32.tar.gz +0 -0
  196. package/src/koffi/build/2.3.4/koffi_freebsd_x64.tar.gz +0 -0
  197. package/src/koffi/build/2.3.4/koffi_linux_arm32hf.tar.gz +0 -0
  198. package/src/koffi/build/2.3.4/koffi_linux_arm64.tar.gz +0 -0
  199. package/src/koffi/build/2.3.4/koffi_linux_ia32.tar.gz +0 -0
  200. package/src/koffi/build/2.3.4/koffi_linux_riscv64hf64.tar.gz +0 -0
  201. package/src/koffi/build/2.3.4/koffi_linux_x64.tar.gz +0 -0
  202. package/src/koffi/build/2.3.4/koffi_openbsd_ia32.tar.gz +0 -0
  203. package/src/koffi/build/2.3.4/koffi_openbsd_x64.tar.gz +0 -0
  204. package/src/koffi/build/2.3.4/koffi_win32_arm64.tar.gz +0 -0
  205. package/src/koffi/build/2.3.4/koffi_win32_ia32.tar.gz +0 -0
  206. package/src/koffi/build/2.3.4/koffi_win32_x64.tar.gz +0 -0
@@ -143,7 +143,8 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
143
143
 
144
144
  *(void **)(args_ptr++) = ptr;
145
145
  } break;
146
- case PrimitiveKind::Record: {
146
+ case PrimitiveKind::Record:
147
+ case PrimitiveKind::Union: {
147
148
  if (RG_UNLIKELY(!IsObject(value))) {
148
149
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
149
150
  return false;
@@ -261,6 +262,7 @@ void CallData::Execute(const FunctionInfo *func)
261
262
  case PrimitiveKind::String16:
262
263
  case PrimitiveKind::Pointer:
263
264
  case PrimitiveKind::Record:
265
+ case PrimitiveKind::Union:
264
266
  case PrimitiveKind::Callback: { result.u64 = PERFORM_CALL(G); } break;
265
267
  case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
266
268
  case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
@@ -312,7 +314,8 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
312
314
  return env.Null();
313
315
  }
314
316
  } break;
315
- case PrimitiveKind::Record: {
317
+ case PrimitiveKind::Record:
318
+ case PrimitiveKind::Union: {
316
319
  const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
317
320
  : (const uint8_t *)&result.buf;
318
321
 
@@ -529,7 +532,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
529
532
  param.type->dispose(env, param.type, ptr2);
530
533
  }
531
534
  } break;
532
- case PrimitiveKind::Record: {
535
+ case PrimitiveKind::Record:
536
+ case PrimitiveKind::Union: {
533
537
  uint8_t *ptr;
534
538
  if (param.regular) {
535
539
  ptr = (uint8_t *)(j < 4 ? gpr_ptr + j : args_ptr);
@@ -641,7 +645,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
641
645
 
642
646
  if (CheckValueTag(instance, value, type->ref.marker)) {
643
647
  ptr = value.As<Napi::External<uint8_t>>().Data();
644
- } else if (IsObject(value) && type->ref.type->primitive == PrimitiveKind::Record) {
648
+ } else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
649
+ type->ref.type->primitive == PrimitiveKind::Union)) {
645
650
  Napi::Object obj = value.As<Napi::Object>();
646
651
 
647
652
  ptr = AllocHeap(type->ref.type->size, 16);
@@ -657,7 +662,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
657
662
 
658
663
  out_reg->rax = (uint64_t)ptr;
659
664
  } break;
660
- case PrimitiveKind::Record: {
665
+ case PrimitiveKind::Record:
666
+ case PrimitiveKind::Union: {
661
667
  if (RG_UNLIKELY(!IsObject(value))) {
662
668
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
663
669
  return;
@@ -61,7 +61,8 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
61
61
  (func->convention == CallConvention::Thiscall) ? 1 : 0;
62
62
  func->fast = fast;
63
63
 
64
- if (func->ret.type->primitive != PrimitiveKind::Record) {
64
+ if (func->ret.type->primitive != PrimitiveKind::Record &&
65
+ func->ret.type->primitive != PrimitiveKind::Union) {
65
66
  func->ret.trivial = true;
66
67
  #if defined(_WIN32) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
67
68
  } else {
@@ -224,7 +225,8 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
224
225
 
225
226
  *(void **)((param.fast ? fast_ptr : args_ptr)++) = ptr;
226
227
  } break;
227
- case PrimitiveKind::Record: {
228
+ case PrimitiveKind::Record:
229
+ case PrimitiveKind::Union: {
228
230
  if (RG_UNLIKELY(!IsObject(value))) {
229
231
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
230
232
  return false;
@@ -346,7 +348,8 @@ void CallData::Execute(const FunctionInfo *func)
346
348
  case PrimitiveKind::String:
347
349
  case PrimitiveKind::String16:
348
350
  case PrimitiveKind::Pointer:
349
- case PrimitiveKind::Record:
351
+ case PrimitiveKind::Record:
352
+ case PrimitiveKind::Union:
350
353
  case PrimitiveKind::Callback: { result.u64 = PERFORM_CALL(G); } break;
351
354
  case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
352
355
  case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
@@ -398,7 +401,8 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
398
401
  return env.Null();
399
402
  }
400
403
  } break;
401
- case PrimitiveKind::Record: {
404
+ case PrimitiveKind::Record:
405
+ case PrimitiveKind::Union: {
402
406
  const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
403
407
  : (const uint8_t *)&result.buf;
404
408
 
@@ -617,7 +621,8 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool async, BackRe
617
621
  param.type->dispose(env, param.type, ptr2);
618
622
  }
619
623
  } break;
620
- case PrimitiveKind::Record: {
624
+ case PrimitiveKind::Record:
625
+ case PrimitiveKind::Union: {
621
626
  RG_ASSERT(!param.fast);
622
627
 
623
628
  uint8_t *ptr = (uint8_t *)args_ptr;
@@ -750,7 +755,8 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool async, BackRe
750
755
 
751
756
  if (CheckValueTag(instance, value, type->ref.marker)) {
752
757
  ptr = value.As<Napi::External<uint8_t>>().Data();
753
- } else if (IsObject(value) && type->ref.type->primitive == PrimitiveKind::Record) {
758
+ } else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
759
+ type->ref.type->primitive == PrimitiveKind::Union)) {
754
760
  Napi::Object obj = value.As<Napi::Object>();
755
761
 
756
762
  ptr = AllocHeap(type->ref.type->size, 16);
@@ -766,7 +772,8 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool async, BackRe
766
772
 
767
773
  out_reg->eax = (uint32_t)ptr;
768
774
  } break;
769
- case PrimitiveKind::Record: {
775
+ case PrimitiveKind::Record:
776
+ case PrimitiveKind::Union: {
770
777
  if (RG_UNLIKELY(!IsObject(value))) {
771
778
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
772
779
  return;
@@ -22,6 +22,7 @@ namespace RG {
22
22
 
23
23
  struct RelayContext {
24
24
  CallData *call;
25
+ bool dispose_call;
25
26
 
26
27
  Size idx;
27
28
  uint8_t *own_sp;
@@ -45,6 +46,14 @@ CallData::CallData(Napi::Env env, InstanceData *instance, InstanceMemory *mem)
45
46
  }
46
47
 
47
48
  CallData::~CallData()
49
+ {
50
+ if (!instance)
51
+ return;
52
+
53
+ Dispose();
54
+ }
55
+
56
+ void CallData::Dispose()
48
57
  {
49
58
  for (const OutArgument &out: out_arguments) {
50
59
  napi_delete_reference(env, out.ref);
@@ -71,14 +80,18 @@ CallData::~CallData()
71
80
 
72
81
  instance->temporaries -= mem->temporary;
73
82
 
74
- if (!--mem->depth && mem->temporary) {
75
- delete mem;
83
+ if (!--mem->depth) {
84
+ mem->busy = false;
85
+
86
+ if (mem->temporary) {
87
+ delete mem;
88
+ }
76
89
  }
77
90
 
78
91
  instance = nullptr;
79
92
  }
80
93
 
81
- void CallData::RelaySafe(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
94
+ void CallData::RelaySafe(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool dispose_call, BackRegisters *out_reg)
82
95
  {
83
96
  if (std::this_thread::get_id() != instance->main_thread_id) {
84
97
  // JS/V8 is single-threaded, and runs on main_thread_id. Forward the call
@@ -87,6 +100,7 @@ void CallData::RelaySafe(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegi
87
100
  RelayContext ctx;
88
101
 
89
102
  ctx.call = this;
103
+ ctx.dispose_call = dispose_call;
90
104
  ctx.idx = idx;
91
105
  ctx.own_sp = own_sp;
92
106
  ctx.caller_sp = caller_sp;
@@ -100,6 +114,7 @@ void CallData::RelaySafe(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegi
100
114
  ctx.cv.wait(lock);
101
115
  }
102
116
  } else {
117
+ RG_ASSERT(!dispose_call);
103
118
  Relay(idx, own_sp, caller_sp, false, out_reg);
104
119
  }
105
120
  }
@@ -110,6 +125,10 @@ void CallData::RelayAsync(napi_env, napi_value, void *, void *udata)
110
125
 
111
126
  ctx->call->Relay(ctx->idx, ctx->own_sp, ctx->caller_sp, true, ctx->out_reg);
112
127
 
128
+ if (ctx->dispose_call) {
129
+ ctx->call->Dispose();
130
+ }
131
+
113
132
  // We're done!
114
133
  std::lock_guard<std::mutex> lock(ctx->mutex);
115
134
  ctx->done = true;
@@ -163,7 +182,7 @@ bool CallData::PushString(Napi::Value value, int directions, const char **out_st
163
182
  type->align = 1;
164
183
  type->size = (int32_t)len;
165
184
  type->ref.type = instance->char_type;
166
- type->hint = TypeInfo::ArrayHint::String;
185
+ type->hint = ArrayHint::String;
167
186
  }
168
187
 
169
188
  // Prepare output argument
@@ -264,7 +283,7 @@ bool CallData::PushString16(Napi::Value value, int directions, const char16_t **
264
283
  type->align = 1;
265
284
  type->size = (int32_t)(len * 2);
266
285
  type->ref.type = instance->char16_type;
267
- type->hint = TypeInfo::ArrayHint::String;
286
+ type->hint = ArrayHint::String;
268
287
  }
269
288
 
270
289
  // Prepare output argument
@@ -318,13 +337,44 @@ Size CallData::PushString16Value(Napi::Value value, const char16_t **out_str16)
318
337
  return (Size)len;
319
338
  }
320
339
 
321
- bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origin, int16_t realign)
340
+ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origin)
322
341
  {
323
342
  RG_ASSERT(IsObject(obj));
324
- RG_ASSERT(type->primitive == PrimitiveKind::Record);
343
+ RG_ASSERT(type->primitive == PrimitiveKind::Record ||
344
+ type->primitive == PrimitiveKind::Union);
345
+
346
+ Span<const RecordMember> members = {};
347
+
348
+ if (type->primitive == PrimitiveKind::Record) {
349
+ members = type->members;
350
+ } else if (type->primitive == PrimitiveKind::Union) {
351
+ if (RG_UNLIKELY(!CheckValueTag(instance, obj, &MagicUnionMarker))) {
352
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected union value", GetValueType(instance, obj));
353
+ return false;
354
+ }
355
+
356
+ MagicUnion *u = MagicUnion::Unwrap(obj);
357
+ const uint8_t *raw = u->GetRaw();
358
+
359
+ // Fast path: encoded value already exists, just copy!
360
+ if (raw) {
361
+ memcpy(origin, raw, type->size);
362
+ return true;
363
+ }
364
+
365
+ members.ptr = u->GetMember();
366
+ members.len = 1;
325
367
 
326
- for (Size i = 0; i < type->members.len; i++) {
327
- const RecordMember &member = type->members[i];
368
+ if (RG_UNLIKELY(!members.ptr)) {
369
+ ThrowError<Napi::Error>(env, "Cannot use ambiguous empty union");
370
+ return false;
371
+ }
372
+ } else {
373
+ RG_UNREACHABLE();
374
+ }
375
+
376
+ for (Size i = 0; i < members.len; i++) {
377
+ const RecordMember &member = members[i];
328
378
  Napi::Value value = obj.Get(member.name);
329
379
 
330
380
  if (RG_UNLIKELY(value.IsUndefined())) {
@@ -332,8 +382,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
332
382
  return false;
333
383
  }
334
384
 
335
- Size offset = realign ? (i * realign) : member.offset;
336
- uint8_t *dest = origin + offset;
385
+ uint8_t *dest = origin + member.offset;
337
386
 
338
387
  switch (member.type->primitive) {
339
388
  case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
@@ -494,14 +543,15 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
494
543
 
495
544
  *(void **)dest = ptr;
496
545
  } break;
497
- case PrimitiveKind::Record: {
546
+ case PrimitiveKind::Record:
547
+ case PrimitiveKind::Union: {
498
548
  if (RG_UNLIKELY(!IsObject(value))) {
499
549
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
500
550
  return false;
501
551
  }
502
552
 
503
553
  Napi::Object obj2 = value.As<Napi::Object>();
504
- if (!PushObject(obj2, member.type, dest, realign))
554
+ if (!PushObject(obj2, member.type, dest))
505
555
  return false;
506
556
  } break;
507
557
  case PrimitiveKind::Array: {
@@ -509,14 +559,14 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
509
559
  Napi::Array array = value.As<Napi::Array>();
510
560
  Size len = (Size)member.type->size / member.type->ref.type->size;
511
561
 
512
- if (!PushNormalArray(array, len, member.type, dest, realign))
562
+ if (!PushNormalArray(array, len, member.type, dest))
513
563
  return false;
514
564
  } else if (IsRawBuffer(value)) {
515
565
  Span<const uint8_t> buffer = GetRawBuffer(value);
516
566
 
517
- if (!PushBuffer(buffer, member.type->size, member.type, dest, realign))
567
+ if (!PushBuffer(buffer, member.type->size, member.type, dest))
518
568
  return false;
519
- } else if (value.IsString() && !realign) {
569
+ } else if (value.IsString()) {
520
570
  if (!PushStringArray(value, member.type, dest))
521
571
  return false;
522
572
  } else {
@@ -571,7 +621,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
571
621
  return true;
572
622
  }
573
623
 
574
- bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type, uint8_t *origin, int16_t realign)
624
+ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type, uint8_t *origin)
575
625
  {
576
626
  RG_ASSERT(array.IsArray());
577
627
 
@@ -589,9 +639,7 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type
589
639
  for (Size i = 0; i < len; i++) { \
590
640
  Napi::Value value = array[(uint32_t)i]; \
591
641
  \
592
- int16_t align = std::max(ref->align, realign); \
593
- \
594
- offset = AlignLen(offset, align); \
642
+ offset = AlignLen(offset, ref->align); \
595
643
  uint8_t *dest = origin + offset; \
596
644
  \
597
645
  if (RG_UNLIKELY(!(Check))) { \
@@ -728,10 +776,11 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type
728
776
  *(const void **)dest = ptr;
729
777
  });
730
778
  } break;
731
- case PrimitiveKind::Record: {
779
+ case PrimitiveKind::Record:
780
+ case PrimitiveKind::Union: {
732
781
  PUSH_ARRAY(IsObject(value), "object", {
733
782
  Napi::Object obj2 = value.As<Napi::Object>();
734
- if (!PushObject(obj2, ref, dest, realign))
783
+ if (!PushObject(obj2, ref, dest))
735
784
  return false;
736
785
  });
737
786
  } break;
@@ -739,8 +788,7 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type
739
788
  for (Size i = 0; i < len; i++) {
740
789
  Napi::Value value = array[(uint32_t)i];
741
790
 
742
- int16_t align = std::max(ref->align, realign);
743
- offset = AlignLen(offset, align);
791
+ offset = AlignLen(offset, ref->align);
744
792
 
745
793
  uint8_t *dest = origin + offset;
746
794
 
@@ -748,14 +796,14 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type
748
796
  Napi::Array array2 = value.As<Napi::Array>();
749
797
  Size len2 = (Size)ref->size / ref->ref.type->size;
750
798
 
751
- if (!PushNormalArray(array2, len2, ref, dest, realign))
799
+ if (!PushNormalArray(array2, len2, ref, dest))
752
800
  return false;
753
801
  } else if (IsRawBuffer(value)) {
754
802
  Span<const uint8_t> buffer = GetRawBuffer(value);
755
803
 
756
- if (!PushBuffer(buffer, ref->size, ref, dest, realign))
804
+ if (!PushBuffer(buffer, ref->size, ref, dest))
757
805
  return false;
758
- } else if (value.IsString() && !realign) {
806
+ } else if (value.IsString()) {
759
807
  if (!PushStringArray(value, ref, dest))
760
808
  return false;
761
809
  } else {
@@ -782,8 +830,7 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type
782
830
  for (Size i = 0; i < len; i++) {
783
831
  Napi::Value value = array[(uint32_t)i];
784
832
 
785
- int16_t align = std::max(ref->align, realign);
786
- offset = AlignLen(offset, align);
833
+ offset = AlignLen(offset, ref->align);
787
834
 
788
835
  uint8_t *dest = origin + offset;
789
836
 
@@ -819,30 +866,40 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type
819
866
  return true;
820
867
  }
821
868
 
822
- bool CallData::PushBuffer(Span<const uint8_t> buffer, Size size, const TypeInfo *type, uint8_t *origin, int16_t realign)
869
+ bool CallData::PushBuffer(Span<const uint8_t> buffer, Size size, const TypeInfo *type, uint8_t *origin)
823
870
  {
824
871
  if (RG_UNLIKELY(buffer.len != size)) {
825
872
  ThrowError<Napi::Error>(env, "Expected array or buffer of size %1, got %2", size, buffer.len);
826
873
  return false;
827
874
  }
828
875
 
829
- if (realign) {
830
- Size offset = 0;
831
- Size step = type->ref.type->size;
876
+ // Go fast yeaaaah :)
877
+ memcpy_safe(origin, buffer.ptr, (size_t)buffer.len);
832
878
 
833
- for (Size i = 0; i < buffer.len; i += step) {
834
- offset = AlignLen(offset, realign);
879
+ #define SWAP(CType) \
880
+ do { \
881
+ CType *data = (CType *)origin; \
882
+ Size len = buffer.len / RG_SIZE(CType); \
883
+ \
884
+ for (Size i = 0; i < len; i++) { \
885
+ data[i] = ReverseBytes(data[i]); \
886
+ } \
887
+ } while (false)
835
888
 
836
- uint8_t *dest = origin + offset;
837
- const uint8_t *src = buffer.ptr + i;
889
+ if (type->primitive == PrimitiveKind::Array || type->primitive == PrimitiveKind::Pointer) {
890
+ const TypeInfo *ref = type->ref.type;
838
891
 
839
- memcpy(dest, src, step);
840
- offset += step;
892
+ if (ref->primitive == PrimitiveKind::Int16S || ref->primitive == PrimitiveKind::UInt16S) {
893
+ SWAP(uint16_t);
894
+ } else if (ref->primitive == PrimitiveKind::Int32S || ref->primitive == PrimitiveKind::UInt32S) {
895
+ SWAP(uint32_t);
896
+ } else if (ref->primitive == PrimitiveKind::Int64S || ref->primitive == PrimitiveKind::UInt64S) {
897
+ SWAP(uint64_t);
841
898
  }
842
- } else {
843
- memcpy_safe(origin, buffer.ptr, (size_t)buffer.len);
844
899
  }
845
900
 
901
+ #undef SWAP
902
+
846
903
  return true;
847
904
  }
848
905
 
@@ -941,7 +998,8 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
941
998
  ptr = buffer.ptr;
942
999
  directions = 1;
943
1000
  }
944
- } else if (RG_LIKELY(type->ref.type->primitive == PrimitiveKind::Record)) {
1001
+ } else if (RG_LIKELY(type->ref.type->primitive == PrimitiveKind::Record ||
1002
+ type->ref.type->primitive == PrimitiveKind::Union)) {
945
1003
  if (RG_UNLIKELY(!type->ref.type->size)) {
946
1004
  ThrowError<Napi::TypeError>(env, "Cannot pass %1 value to void *, use koffi.as()",
947
1005
  type->ref.type != instance->void_type ? "opaque" : "ambiguous");
@@ -957,6 +1015,12 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
957
1015
  if (!PushObject(obj, type->ref.type, ptr))
958
1016
  return false;
959
1017
  } else {
1018
+ if (RG_UNLIKELY(type->ref.type->primitive == PrimitiveKind::Union &&
1019
+ !CheckValueTag(instance, obj, &MagicUnionMarker))) {
1020
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected union value", GetValueType(instance, obj));
1021
+ return false;
1022
+ }
1023
+
960
1024
  memset_safe(ptr, 0, type->size);
961
1025
  }
962
1026
  } else {
@@ -1008,8 +1072,14 @@ void CallData::PopOutArguments()
1008
1072
  Span<uint8_t> buffer = GetRawBuffer(value);
1009
1073
  DecodeBuffer(buffer, out.ptr, out.type);
1010
1074
  } else {
1011
- Napi::Object obj(env, value);
1012
- DecodeObject(obj, out.ptr, out.type);
1075
+ Napi::Object obj = value.As<Napi::Object>();
1076
+
1077
+ if (CheckValueTag(instance, value, &MagicUnionMarker)) {
1078
+ MagicUnion *u = MagicUnion::Unwrap(obj);
1079
+ u->SetRaw(out.ptr);
1080
+ } else {
1081
+ DecodeObject(obj, out.ptr, out.type);
1082
+ }
1013
1083
  }
1014
1084
  }
1015
1085
  }
@@ -69,6 +69,8 @@ public:
69
69
  CallData(Napi::Env env, InstanceData *instance, InstanceMemory *mem);
70
70
  ~CallData();
71
71
 
72
+ void Dispose();
73
+
72
74
  #ifdef UNITY_BUILD
73
75
  #ifdef _MSC_VER
74
76
  #define INLINE_IF_UNITY __forceinline
@@ -86,7 +88,7 @@ public:
86
88
  #undef INLINE_IF_UNITY
87
89
 
88
90
  void Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async, BackRegisters *out_reg);
89
- void RelaySafe(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg);
91
+ void RelaySafe(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool dispose_call, BackRegisters *out_reg);
90
92
  static void RelayAsync(napi_env, napi_value, void *, void *udata);
91
93
 
92
94
  void DumpForward(const FunctionInfo *func) const;
@@ -101,9 +103,9 @@ private:
101
103
  Size PushStringValue(Napi::Value value, const char **out_str);
102
104
  bool PushString16(Napi::Value value, int directions, const char16_t **out_str16);
103
105
  Size PushString16Value(Napi::Value value, const char16_t **out_str16);
104
- bool PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origin, int16_t realign = 0);
105
- bool PushNormalArray(Napi::Array array, Size len, const TypeInfo *type, uint8_t *origin, int16_t realign = 0);
106
- bool PushBuffer(Span<const uint8_t> buffer, Size size, const TypeInfo *type, uint8_t *origin, int16_t realign = 0);
106
+ bool PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origin);
107
+ bool PushNormalArray(Napi::Array array, Size len, const TypeInfo *type, uint8_t *origin);
108
+ bool PushBuffer(Span<const uint8_t> buffer, Size size, const TypeInfo *type, uint8_t *origin);
107
109
  bool PushStringArray(Napi::Value value, const TypeInfo *type, uint8_t *origin);
108
110
  bool PushPointer(Napi::Value value, const TypeInfo *type, int directions, void **out_ptr);
109
111