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
@@ -20,6 +20,83 @@
20
20
 
21
21
  namespace RG {
22
22
 
23
+ // Value does not matter, the tag system uses memory addresses
24
+ const int TypeInfoMarker = 0xDEADBEEF;
25
+ const int CastMarker = 0xDEADBEEF;
26
+ const int MagicUnionMarker = 0xDEADBEEF;
27
+
28
+ Napi::Function MagicUnion::InitClass(Napi::Env env, const TypeInfo *type)
29
+ {
30
+ RG_ASSERT(type->primitive == PrimitiveKind::Union);
31
+
32
+ // node-addon-api wants std::vector
33
+ std::vector<Napi::ClassPropertyDescriptor<MagicUnion>> properties;
34
+ properties.reserve(type->members.len);
35
+
36
+ for (Size i = 0; i < type->members.len; i++) {
37
+ const RecordMember &member = type->members[i];
38
+
39
+ napi_property_attributes attr = (napi_property_attributes)(napi_writable | napi_enumerable);
40
+ Napi::ClassPropertyDescriptor<MagicUnion> prop = InstanceAccessor(member.name, &MagicUnion::Getter,
41
+ &MagicUnion::Setter, attr, (void *)i);
42
+
43
+ properties.push_back(prop);
44
+ }
45
+
46
+ Napi::Function constructor = DefineClass(env, type->name, properties, (void *)type);
47
+ return constructor;
48
+ }
49
+
50
+ MagicUnion::MagicUnion(const Napi::CallbackInfo &info)
51
+ : Napi::ObjectWrap<MagicUnion>(info), type((const TypeInfo *)info.Data())
52
+ {
53
+ }
54
+
55
+ void MagicUnion::SetRaw(const uint8_t *ptr)
56
+ {
57
+ raw = ptr;
58
+
59
+ active_idx = -1;
60
+ Value().Set("__active", Env().Undefined());
61
+ }
62
+
63
+ Napi::Value MagicUnion::Getter(const Napi::CallbackInfo &info)
64
+ {
65
+ Size idx = (Size)info.Data();
66
+ const RecordMember &member = type->members[idx];
67
+
68
+ Napi::Value value;
69
+
70
+ if (idx == active_idx) {
71
+ value = Value().Get("__active");
72
+ } else {
73
+ Napi::Env env = info.Env();
74
+
75
+ if (RG_UNLIKELY(!raw)) {
76
+ ThrowError<Napi::Error>(env, "Cannont convert %1 union value", active_idx < 0 ? "empty" : "assigned");
77
+ return env.Null();
78
+ }
79
+
80
+ value = Decode(env, raw, member.type);
81
+
82
+ Value().Set("__active", value);
83
+ active_idx = idx;
84
+ }
85
+
86
+ RG_ASSERT(!value.IsEmpty());
87
+ return value;
88
+ }
89
+
90
+ void MagicUnion::Setter(const Napi::CallbackInfo &info, const Napi::Value &value)
91
+ {
92
+ Size idx = (Size)info.Data();
93
+
94
+ Value().Set("__active", value);
95
+ active_idx = idx;
96
+
97
+ raw = nullptr;
98
+ }
99
+
23
100
  const TypeInfo *ResolveType(Napi::Value value, int *out_directions)
24
101
  {
25
102
  Napi::Env env = value.Env();
@@ -216,7 +293,7 @@ const TypeInfo *MakePointerType(InstanceData *instance, const TypeInfo *ref, int
216
293
  }
217
294
 
218
295
  static const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len,
219
- TypeInfo::ArrayHint hint, bool insert)
296
+ ArrayHint hint, bool insert)
220
297
  {
221
298
  RG_ASSERT(len > 0);
222
299
  RG_ASSERT(len <= instance->config.max_type_size / ref->size);
@@ -242,19 +319,19 @@ static const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref
242
319
 
243
320
  const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len)
244
321
  {
245
- TypeInfo::ArrayHint hint = {};
322
+ ArrayHint hint = {};
246
323
 
247
324
  if (TestStr(ref->name, "char") || TestStr(ref->name, "char16") ||
248
325
  TestStr(ref->name, "char16_t")) {
249
- hint = TypeInfo::ArrayHint::String;
326
+ hint = ArrayHint::String;
250
327
  } else {
251
- hint = TypeInfo::ArrayHint::TypedArray;
328
+ hint = ArrayHint::Typed;
252
329
  }
253
330
 
254
331
  return MakeArrayType(instance, ref, len, hint, true);
255
332
  }
256
333
 
257
- const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len, TypeInfo::ArrayHint hint)
334
+ const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len, ArrayHint hint)
258
335
  {
259
336
  return MakeArrayType(instance, ref, len, hint, false);
260
337
  }
@@ -402,14 +479,27 @@ int GetTypedArrayType(const TypeInfo *type)
402
479
  RG_UNREACHABLE();
403
480
  }
404
481
 
405
- Napi::Object DecodeObject(Napi::Env env, const uint8_t *origin, const TypeInfo *type, int16_t realign)
482
+ Napi::Object DecodeObject(Napi::Env env, const uint8_t *origin, const TypeInfo *type)
406
483
  {
484
+ // We can't decode unions because we don't know which member is valid
485
+ if (type->primitive == PrimitiveKind::Union) {
486
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
487
+
488
+ Napi::Object wrapper = type->construct.New({}).As<Napi::Object>();
489
+ SetValueTag(instance, wrapper, &MagicUnionMarker);
490
+
491
+ MagicUnion *u = MagicUnion::Unwrap(wrapper);
492
+ u->SetRaw(origin);
493
+
494
+ return wrapper;
495
+ }
496
+
407
497
  Napi::Object obj = Napi::Object::New(env);
408
- DecodeObject(obj, origin, type, realign);
498
+ DecodeObject(obj, origin, type);
409
499
  return obj;
410
500
  }
411
501
 
412
- void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type, int16_t realign)
502
+ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type)
413
503
  {
414
504
  Napi::Env env = obj.Env();
415
505
  InstanceData *instance = env.GetInstanceData<InstanceData>();
@@ -419,8 +509,7 @@ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type,
419
509
  for (Size i = 0; i < type->members.len; i++) {
420
510
  const RecordMember &member = type->members[i];
421
511
 
422
- Size offset = realign ? (i * realign) : member.offset;
423
- const uint8_t *src = origin + offset;
512
+ const uint8_t *src = origin + member.offset;
424
513
 
425
514
  switch (member.type->primitive) {
426
515
  case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
@@ -526,12 +615,13 @@ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type,
526
615
  member.type->dispose(env, member.type, ptr2);
527
616
  }
528
617
  } break;
529
- case PrimitiveKind::Record: {
530
- Napi::Object obj2 = DecodeObject(env, src, member.type, realign);
618
+ case PrimitiveKind::Record:
619
+ case PrimitiveKind::Union: {
620
+ Napi::Object obj2 = DecodeObject(env, src, member.type);
531
621
  obj.Set(member.name, obj2);
532
622
  } break;
533
623
  case PrimitiveKind::Array: {
534
- Napi::Value value = DecodeArray(env, src, member.type, realign);
624
+ Napi::Value value = DecodeArray(env, src, member.type);
535
625
  obj.Set(member.name, value);
536
626
  } break;
537
627
  case PrimitiveKind::Float32: {
@@ -559,7 +649,7 @@ static Size WideStringLength(const char16_t *str16, Size max)
559
649
  return len;
560
650
  }
561
651
 
562
- Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type, int16_t realign)
652
+ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type)
563
653
  {
564
654
  InstanceData *instance = env.GetInstanceData<InstanceData>();
565
655
 
@@ -573,8 +663,7 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
573
663
  Napi::Array array = Napi::Array::New(env); \
574
664
  \
575
665
  for (uint32_t i = 0; i < len; i++) { \
576
- int16_t align = std::max(realign, type->ref.type->align); \
577
- offset = AlignLen(offset, align); \
666
+ offset = AlignLen(offset, type->ref.type->align); \
578
667
  \
579
668
  const uint8_t *src = origin + offset; \
580
669
  \
@@ -587,7 +676,7 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
587
676
  } while (false)
588
677
  #define POP_NUMBER_ARRAY(TypedArrayType, CType) \
589
678
  do { \
590
- if (type->hint == TypeInfo::ArrayHint::Array) { \
679
+ if (type->hint == ArrayHint::Array) { \
591
680
  POP_ARRAY({ \
592
681
  double d = (double)*(CType *)src; \
593
682
  array.Set(i, Napi::Number::New(env, d)); \
@@ -596,14 +685,14 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
596
685
  Napi::TypedArrayType array = Napi::TypedArrayType::New(env, len); \
597
686
  Span<uint8_t> buffer = MakeSpan((uint8_t *)array.ArrayBuffer().Data(), (Size)len * RG_SIZE(CType)); \
598
687
  \
599
- DecodeBuffer(buffer, origin, type->ref.type, realign); \
688
+ DecodeBuffer(buffer, origin, type->ref.type); \
600
689
  \
601
690
  return array; \
602
691
  } \
603
692
  } while (false)
604
693
  #define POP_NUMBER_ARRAY_SWAP(TypedArrayType, CType) \
605
694
  do { \
606
- if (type->hint == TypeInfo::ArrayHint::Array) { \
695
+ if (type->hint == ArrayHint::Array) { \
607
696
  POP_ARRAY({ \
608
697
  CType v = *(CType *)src; \
609
698
  double d = (double)ReverseBytes(v); \
@@ -613,7 +702,7 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
613
702
  Napi::TypedArrayType array = Napi::TypedArrayType::New(env, len); \
614
703
  Span<uint8_t> buffer = MakeSpan((uint8_t *)array.ArrayBuffer().Data(), (Size)len * RG_SIZE(CType)); \
615
704
  \
616
- DecodeBuffer(buffer, origin, type->ref.type, realign); \
705
+ DecodeBuffer(buffer, origin, type->ref.type); \
617
706
  \
618
707
  return array; \
619
708
  } \
@@ -629,9 +718,7 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
629
718
  });
630
719
  } break;
631
720
  case PrimitiveKind::Int8: {
632
- if (type->hint == TypeInfo::ArrayHint::String) {
633
- RG_ASSERT(!realign);
634
-
721
+ if (type->hint == ArrayHint::String) {
635
722
  const char *ptr = (const char *)origin;
636
723
  size_t count = strnlen(ptr, (size_t)len);
637
724
 
@@ -643,9 +730,7 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
643
730
  } break;
644
731
  case PrimitiveKind::UInt8: { POP_NUMBER_ARRAY(Uint8Array, uint8_t); } break;
645
732
  case PrimitiveKind::Int16: {
646
- if (type->hint == TypeInfo::ArrayHint::String) {
647
- RG_ASSERT(!realign);
648
-
733
+ if (type->hint == ArrayHint::String) {
649
734
  const char16_t *ptr = (const char16_t *)origin;
650
735
  Size count = WideStringLength(ptr, len);
651
736
 
@@ -713,15 +798,16 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
713
798
  }
714
799
  });
715
800
  } break;
716
- case PrimitiveKind::Record: {
801
+ case PrimitiveKind::Record:
802
+ case PrimitiveKind::Union: {
717
803
  POP_ARRAY({
718
- Napi::Object obj = DecodeObject(env, src, type->ref.type, realign);
804
+ Napi::Object obj = DecodeObject(env, src, type->ref.type);
719
805
  array.Set(i, obj);
720
806
  });
721
807
  } break;
722
808
  case PrimitiveKind::Array: {
723
809
  POP_ARRAY({
724
- Napi::Value value = DecodeArray(env, src, type->ref.type, realign);
810
+ Napi::Value value = DecodeArray(env, src, type->ref.type);
725
811
  array.Set(i, value);
726
812
  });
727
813
  } break;
@@ -738,7 +824,7 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
738
824
  RG_UNREACHABLE();
739
825
  }
740
826
 
741
- void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo *ref, int16_t realign)
827
+ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo *ref)
742
828
  {
743
829
  Napi::Env env = array.Env();
744
830
  InstanceData *instance = env.GetInstanceData<InstanceData>();
@@ -751,8 +837,7 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
751
837
  #define POP_ARRAY(SetCode) \
752
838
  do { \
753
839
  for (uint32_t i = 0; i < len; i++) { \
754
- int16_t align = std::max(realign, ref->align); \
755
- offset = AlignLen(offset, align); \
840
+ offset = AlignLen(offset, ref->align); \
756
841
  \
757
842
  const uint8_t *src = origin + offset; \
758
843
  \
@@ -859,15 +944,16 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
859
944
  }
860
945
  });
861
946
  } break;
862
- case PrimitiveKind::Record: {
947
+ case PrimitiveKind::Record:
948
+ case PrimitiveKind::Union: {
863
949
  POP_ARRAY({
864
- Napi::Object obj = DecodeObject(env, src, ref, realign);
950
+ Napi::Object obj = DecodeObject(env, src, ref);
865
951
  array.Set(i, obj);
866
952
  });
867
953
  } break;
868
954
  case PrimitiveKind::Array: {
869
955
  POP_ARRAY({
870
- Napi::Value value = DecodeArray(env, src, ref, realign);
956
+ Napi::Value value = DecodeArray(env, src, ref);
871
957
  array.Set(i, value);
872
958
  });
873
959
  } break;
@@ -882,24 +968,10 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
882
968
  #undef POP_ARRAY
883
969
  }
884
970
 
885
- void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *ref, int16_t realign)
971
+ void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *ref)
886
972
  {
887
- if (realign) {
888
- Size offset = 0;
889
- Size step = ref->size;
890
-
891
- for (Size i = 0; i < buffer.len; i += step) {
892
- offset = AlignLen(offset, realign);
893
-
894
- uint8_t *dest = buffer.ptr + i;
895
- const uint8_t *src = origin + offset;
896
-
897
- memcpy(dest, src, step);
898
- offset += step;
899
- }
900
- } else {
901
- memcpy_safe(buffer.ptr, origin, (size_t)buffer.len);
902
- }
973
+ // Go fast brrrrr!
974
+ memcpy_safe(buffer.ptr, origin, (size_t)buffer.len);
903
975
 
904
976
  #define SWAP(CType) \
905
977
  do { \
@@ -922,6 +994,136 @@ void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *r
922
994
  #undef SWAP
923
995
  }
924
996
 
997
+ Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, Size len)
998
+ {
999
+ Napi::Env env = value.Env();
1000
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
1001
+
1002
+ const uint8_t *ptr = nullptr;
1003
+
1004
+ if (value.IsExternal()) {
1005
+ Napi::External<void> external = value.As<Napi::External<void>>();
1006
+ ptr = (const uint8_t *)external.Data();
1007
+ } else if (IsRawBuffer(value)) {
1008
+ Span<uint8_t> buffer = GetRawBuffer(value);
1009
+
1010
+ if (RG_UNLIKELY(buffer.len - offset < type->size)) {
1011
+ ThrowError<Napi::Error>(env, "Expected buffer with size superior or equal to type %1 (%2 bytes)",
1012
+ type->name, type->size + offset);
1013
+ return env.Null();
1014
+ }
1015
+
1016
+ ptr = (const uint8_t *)buffer.ptr;
1017
+ } else {
1018
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for variable, expected external or TypedArray", GetValueType(instance, value));
1019
+ return env.Null();
1020
+ }
1021
+
1022
+ if (!ptr)
1023
+ return env.Null();
1024
+ ptr += offset;
1025
+
1026
+ Napi::Value ret = Decode(env, ptr, type, len);
1027
+ return ret;
1028
+ }
1029
+
1030
+ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, Size len)
1031
+ {
1032
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
1033
+
1034
+ if (len >= 0 && type->primitive != PrimitiveKind::String &&
1035
+ type->primitive != PrimitiveKind::String16) {
1036
+ type = MakeArrayType(instance, type, len);
1037
+ }
1038
+
1039
+ #define RETURN_INT(Type, NewCall) \
1040
+ do { \
1041
+ Type v = *(Type *)ptr; \
1042
+ return NewCall(env, v); \
1043
+ } while (false)
1044
+ #define RETURN_INT_SWAP(Type, NewCall) \
1045
+ do { \
1046
+ Type v = ReverseBytes(*(Type *)ptr); \
1047
+ return NewCall(env, v); \
1048
+ } while (false)
1049
+
1050
+ switch (type->primitive) {
1051
+ case PrimitiveKind::Void: {
1052
+ ThrowError<Napi::TypeError>(env, "Cannot decode value of type %1", type->name);
1053
+ return env.Null();
1054
+ } break;
1055
+
1056
+ case PrimitiveKind::Bool: {
1057
+ bool v = *(bool *)ptr;
1058
+ return Napi::Boolean::New(env, v);
1059
+ } break;
1060
+ case PrimitiveKind::Int8: { RETURN_INT(int8_t, Napi::Number::New); } break;
1061
+ case PrimitiveKind::UInt8: { RETURN_INT(uint8_t, Napi::Number::New); } break;
1062
+ case PrimitiveKind::Int16: { RETURN_INT(int16_t, Napi::Number::New); } break;
1063
+ case PrimitiveKind::Int16S: { RETURN_INT_SWAP(int16_t, Napi::Number::New); } break;
1064
+ case PrimitiveKind::UInt16: { RETURN_INT(uint16_t, Napi::Number::New); } break;
1065
+ case PrimitiveKind::UInt16S: { RETURN_INT_SWAP(uint16_t, Napi::Number::New); } break;
1066
+ case PrimitiveKind::Int32: { RETURN_INT(int32_t, Napi::Number::New); } break;
1067
+ case PrimitiveKind::Int32S: { RETURN_INT_SWAP(int32_t, Napi::Number::New); } break;
1068
+ case PrimitiveKind::UInt32: { RETURN_INT(uint32_t, Napi::Number::New); } break;
1069
+ case PrimitiveKind::UInt32S: { RETURN_INT_SWAP(uint32_t, Napi::Number::New); } break;
1070
+ case PrimitiveKind::Int64: { RETURN_INT(int64_t, NewBigInt); } break;
1071
+ case PrimitiveKind::Int64S: { RETURN_INT_SWAP(int64_t, NewBigInt); } break;
1072
+ case PrimitiveKind::UInt64: { RETURN_INT(uint64_t, NewBigInt); } break;
1073
+ case PrimitiveKind::UInt64S: { RETURN_INT_SWAP(uint64_t, NewBigInt); } break;
1074
+ case PrimitiveKind::String: {
1075
+ if (len >= 0) {
1076
+ const char *str = *(const char **)ptr;
1077
+ return str ? Napi::String::New(env, str, len) : env.Null();
1078
+ } else {
1079
+ const char *str = *(const char **)ptr;
1080
+ return str ? Napi::String::New(env, str) : env.Null();
1081
+ }
1082
+ } break;
1083
+ case PrimitiveKind::String16: {
1084
+ if (len >= 0) {
1085
+ const char16_t *str16 = *(const char16_t **)ptr;
1086
+ return str16 ? Napi::String::New(env, str16, len) : env.Null();
1087
+ } else {
1088
+ const char16_t *str16 = *(const char16_t **)ptr;
1089
+ return str16 ? Napi::String::New(env, str16) : env.Null();
1090
+ }
1091
+ } break;
1092
+ case PrimitiveKind::Pointer:
1093
+ case PrimitiveKind::Callback: {
1094
+ void *ptr2 = *(void **)ptr;
1095
+ return ptr2 ? Napi::External<void>::New(env, ptr2, [](Napi::Env, void *) {}) : env.Null();
1096
+ } break;
1097
+ case PrimitiveKind::Record:
1098
+ case PrimitiveKind::Union: {
1099
+ Napi::Object obj = DecodeObject(env, ptr, type);
1100
+ return obj;
1101
+ } break;
1102
+ case PrimitiveKind::Array: {
1103
+ Napi::Value array = DecodeArray(env, ptr, type);
1104
+ return array;
1105
+ } break;
1106
+ case PrimitiveKind::Float32: {
1107
+ float f = *(float *)ptr;
1108
+ return Napi::Number::New(env, f);
1109
+ } break;
1110
+ case PrimitiveKind::Float64: {
1111
+ double d = *(double *)ptr;
1112
+ return Napi::Number::New(env, d);
1113
+ } break;
1114
+
1115
+ case PrimitiveKind::Prototype: {
1116
+ ThrowError<Napi::TypeError>(env, "Cannot decode value of type %1", type->name);
1117
+ return env.Null();
1118
+ } break;
1119
+ }
1120
+
1121
+ #undef RETURN_BIGINT
1122
+ #undef RETURN_INT
1123
+
1124
+ return env.Null();
1125
+ }
1126
+
925
1127
  static int AnalyseFlatRec(const TypeInfo *type, int offset, int count, FunctionRef<void(const TypeInfo *type, int offset, int count)> func)
926
1128
  {
927
1129
  if (type->primitive == PrimitiveKind::Record) {
@@ -930,6 +1132,13 @@ static int AnalyseFlatRec(const TypeInfo *type, int offset, int count, FunctionR
930
1132
  offset = AnalyseFlatRec(member.type, offset, 1, func);
931
1133
  }
932
1134
  }
1135
+ } else if (type->primitive == PrimitiveKind::Union) {
1136
+ for (int i = 0; i < count; i++) {
1137
+ for (const RecordMember &member: type->members) {
1138
+ AnalyseFlatRec(member.type, offset, 1, func);
1139
+ }
1140
+ }
1141
+ offset += count;
933
1142
  } else if (type->primitive == PrimitiveKind::Array) {
934
1143
  count *= type->size / type->ref.type->size;
935
1144
  offset = AnalyseFlatRec(type->ref.type, offset, count, func);
@@ -946,23 +1155,6 @@ int AnalyseFlat(const TypeInfo *type, FunctionRef<void(const TypeInfo *type, int
946
1155
  return AnalyseFlatRec(type, 0, 1, func);
947
1156
  }
948
1157
 
949
- int IsHFA(const TypeInfo *type, int min, int max)
950
- {
951
- uint32_t primitives = 0;
952
- int count = 0;
953
-
954
- count = AnalyseFlat(type, [&](const TypeInfo *type, int, int) {
955
- if (IsFloat(type)) {
956
- primitives |= 1u << (int)type->primitive;
957
- } else {
958
- primitives = UINT32_MAX;
959
- }
960
- });
961
-
962
- bool hfa = (count >= min && count <= max && PopCount(primitives) == 1);
963
- return hfa ? count : 0;
964
- }
965
-
966
1158
  void DumpMemory(const char *type, Span<const uint8_t> bytes)
967
1159
  {
968
1160
  if (bytes.len) {
@@ -23,6 +23,31 @@ struct InstanceData;
23
23
  struct TypeInfo;
24
24
  struct FunctionInfo;
25
25
 
26
+ extern const int TypeInfoMarker;
27
+ extern const int CastMarker;
28
+ extern const int MagicUnionMarker;
29
+
30
+ class MagicUnion: public Napi::ObjectWrap<MagicUnion> {
31
+ const TypeInfo *type;
32
+
33
+ Size active_idx = -1;
34
+ const uint8_t *raw = nullptr;
35
+
36
+ public:
37
+ static Napi::Function InitClass(Napi::Env env, const TypeInfo *type);
38
+
39
+ MagicUnion(const Napi::CallbackInfo &info);
40
+
41
+ const RecordMember *GetMember() const { return (active_idx >= 0) ? &type->members[active_idx] : nullptr; }
42
+
43
+ void SetRaw(const uint8_t *ptr);
44
+ const uint8_t *GetRaw() const { return raw; }
45
+
46
+ private:
47
+ Napi::Value Getter(const Napi::CallbackInfo &info);
48
+ void Setter(const Napi::CallbackInfo &info, const Napi::Value &value);
49
+ };
50
+
26
51
  template <typename T, typename... Args>
27
52
  void ThrowError(Napi::Env env, const char *msg, Args... args)
28
53
  {
@@ -58,7 +83,7 @@ const TypeInfo *ResolveType(Napi::Env env, Span<const char> str, int *out_direct
58
83
 
59
84
  const TypeInfo *MakePointerType(InstanceData *instance, const TypeInfo *ref, int count = 1);
60
85
  const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len);
61
- const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len, TypeInfo::ArrayHint hint);
86
+ const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len, ArrayHint hint);
62
87
 
63
88
  bool CanPassType(const TypeInfo *type, int directions);
64
89
  bool CanReturnType(const TypeInfo *type);
@@ -121,11 +146,14 @@ T GetNumber(Napi::Value value)
121
146
  RG_UNREACHABLE();
122
147
  }
123
148
 
124
- Napi::Object DecodeObject(Napi::Env env, const uint8_t *origin, const TypeInfo *type, int16_t realign = 0);
125
- void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type, int16_t realign = 0);
126
- Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type, int16_t realign = 0);
127
- void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo *ref, int16_t realign = 0);
128
- void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *ref, int16_t realign = 0);
149
+ Napi::Object DecodeObject(Napi::Env env, const uint8_t *origin, const TypeInfo *type);
150
+ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type);
151
+ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type);
152
+ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo *ref);
153
+ void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *ref);
154
+
155
+ Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, Size len = -1);
156
+ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, Size len = -1);
129
157
 
130
158
  static inline Napi::Value NewBigInt(Napi::Env env, int64_t value)
131
159
  {
@@ -149,8 +177,6 @@ static inline Napi::Value NewBigInt(Napi::Env env, uint64_t value)
149
177
 
150
178
  int AnalyseFlat(const TypeInfo *type, FunctionRef<void(const TypeInfo *type, int offset, int count)> func);
151
179
 
152
- int IsHFA(const TypeInfo *type, int min, int max);
153
-
154
180
  void DumpMemory(const char *type, Span<const uint8_t> bytes);
155
181
 
156
182
  }