koffi 2.3.3 → 2.3.5

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 (192) hide show
  1. package/CHANGELOG.md +19 -3
  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 +2 -2
  6. package/src/core/libcc/libcc.cc +2 -2
  7. package/src/koffi/build/2.3.5/koffi_darwin_arm64.tar.gz +0 -0
  8. package/src/koffi/build/2.3.5/koffi_darwin_x64.tar.gz +0 -0
  9. package/src/koffi/build/2.3.5/koffi_freebsd_arm64.tar.gz +0 -0
  10. package/src/koffi/build/2.3.5/koffi_freebsd_ia32.tar.gz +0 -0
  11. package/src/koffi/build/2.3.5/koffi_freebsd_x64.tar.gz +0 -0
  12. package/src/koffi/build/2.3.5/koffi_linux_arm32hf.tar.gz +0 -0
  13. package/src/koffi/build/2.3.5/koffi_linux_arm64.tar.gz +0 -0
  14. package/src/koffi/build/2.3.5/koffi_linux_ia32.tar.gz +0 -0
  15. package/src/koffi/build/2.3.5/koffi_linux_riscv64hf64.tar.gz +0 -0
  16. package/src/koffi/build/2.3.5/koffi_linux_x64.tar.gz +0 -0
  17. package/src/koffi/build/2.3.5/koffi_openbsd_ia32.tar.gz +0 -0
  18. package/src/koffi/build/2.3.5/koffi_openbsd_x64.tar.gz +0 -0
  19. package/src/koffi/build/2.3.5/koffi_win32_arm64.tar.gz +0 -0
  20. package/src/koffi/build/2.3.5/koffi_win32_ia32.tar.gz +0 -0
  21. package/src/koffi/build/2.3.5/koffi_win32_x64.tar.gz +0 -0
  22. package/src/koffi/src/abi_arm32.cc +43 -14
  23. package/src/koffi/src/abi_arm64.cc +95 -21
  24. package/src/koffi/src/abi_riscv64.cc +125 -64
  25. package/src/koffi/src/abi_x64_sysv.cc +38 -20
  26. package/src/koffi/src/abi_x64_win.cc +11 -5
  27. package/src/koffi/src/abi_x86.cc +14 -7
  28. package/src/koffi/src/call.cc +114 -44
  29. package/src/koffi/src/call.hh +6 -4
  30. package/src/koffi/src/ffi.cc +172 -147
  31. package/src/koffi/src/ffi.hh +18 -10
  32. package/src/koffi/src/index.d.ts +28 -7
  33. package/src/koffi/src/util.cc +261 -69
  34. package/src/koffi/src/util.hh +34 -8
  35. package/vendor/node-addon-api/CHANGELOG.md +122 -9
  36. package/vendor/node-addon-api/CONTRIBUTING.md +10 -10
  37. package/vendor/node-addon-api/README.md +36 -12
  38. package/vendor/node-addon-api/benchmark/function_args.cc +95 -62
  39. package/vendor/node-addon-api/benchmark/function_args.js +6 -6
  40. package/vendor/node-addon-api/benchmark/index.js +1 -1
  41. package/vendor/node-addon-api/benchmark/property_descriptor.cc +27 -34
  42. package/vendor/node-addon-api/benchmark/property_descriptor.js +5 -4
  43. package/vendor/node-addon-api/doc/async_operations.md +1 -1
  44. package/vendor/node-addon-api/doc/async_worker_variants.md +23 -2
  45. package/vendor/node-addon-api/doc/cmake-js.md +1 -1
  46. package/vendor/node-addon-api/doc/error_handling.md +3 -3
  47. package/vendor/node-addon-api/doc/external.md +7 -0
  48. package/vendor/node-addon-api/doc/handle_scope.md +14 -0
  49. package/vendor/node-addon-api/doc/hierarchy.md +1 -1
  50. package/vendor/node-addon-api/doc/object.md +27 -0
  51. package/vendor/node-addon-api/index.js +3 -3
  52. package/vendor/node-addon-api/napi-inl.deprecated.h +121 -127
  53. package/vendor/node-addon-api/napi-inl.h +1178 -1144
  54. package/vendor/node-addon-api/napi.h +2786 -2675
  55. package/vendor/node-addon-api/package.json +42 -1
  56. package/vendor/node-addon-api/test/addon.cc +8 -6
  57. package/vendor/node-addon-api/test/addon_build/index.js +9 -9
  58. package/vendor/node-addon-api/test/addon_build/tpl/addon.cc +2 -1
  59. package/vendor/node-addon-api/test/addon_build/tpl/index.js +4 -4
  60. package/vendor/node-addon-api/test/addon_data.cc +12 -13
  61. package/vendor/node-addon-api/test/array_buffer.js +3 -2
  62. package/vendor/node-addon-api/test/async_progress_queue_worker.cc +13 -3
  63. package/vendor/node-addon-api/test/async_progress_queue_worker.js +5 -5
  64. package/vendor/node-addon-api/test/async_progress_worker.cc +65 -9
  65. package/vendor/node-addon-api/test/async_progress_worker.js +14 -9
  66. package/vendor/node-addon-api/test/async_worker.cc +236 -3
  67. package/vendor/node-addon-api/test/async_worker.js +122 -37
  68. package/vendor/node-addon-api/test/async_worker_nocallback.js +9 -3
  69. package/vendor/node-addon-api/test/async_worker_persistent.js +2 -2
  70. package/vendor/node-addon-api/test/basic_types/array.js +3 -4
  71. package/vendor/node-addon-api/test/basic_types/boolean.cc +4 -2
  72. package/vendor/node-addon-api/test/basic_types/boolean.js +1 -2
  73. package/vendor/node-addon-api/test/basic_types/number.cc +12 -6
  74. package/vendor/node-addon-api/test/basic_types/number.js +19 -18
  75. package/vendor/node-addon-api/test/basic_types/value.cc +52 -1
  76. package/vendor/node-addon-api/test/basic_types/value.js +44 -21
  77. package/vendor/node-addon-api/test/bigint.cc +2 -1
  78. package/vendor/node-addon-api/test/binding.cc +11 -5
  79. package/vendor/node-addon-api/test/binding.gyp +3 -1
  80. package/vendor/node-addon-api/test/buffer.cc +46 -38
  81. package/vendor/node-addon-api/test/buffer.js +12 -12
  82. package/vendor/node-addon-api/test/callbackInfo.cc +27 -0
  83. package/vendor/node-addon-api/test/callbackInfo.js +9 -0
  84. package/vendor/node-addon-api/test/callbackscope.cc +19 -2
  85. package/vendor/node-addon-api/test/callbackscope.js +20 -20
  86. package/vendor/node-addon-api/test/common/index.js +37 -4
  87. package/vendor/node-addon-api/test/dataview/dataview.js +5 -5
  88. package/vendor/node-addon-api/test/dataview/dataview_read_write.js +14 -12
  89. package/vendor/node-addon-api/test/date.cc +2 -1
  90. package/vendor/node-addon-api/test/date.js +2 -2
  91. package/vendor/node-addon-api/test/env_cleanup.cc +12 -0
  92. package/vendor/node-addon-api/test/env_cleanup.js +38 -39
  93. package/vendor/node-addon-api/test/error.cc +6 -5
  94. package/vendor/node-addon-api/test/error_terminating_environment.js +64 -60
  95. package/vendor/node-addon-api/test/external.cc +36 -32
  96. package/vendor/node-addon-api/test/external.js +43 -46
  97. package/vendor/node-addon-api/test/function.cc +58 -44
  98. package/vendor/node-addon-api/test/function.js +4 -0
  99. package/vendor/node-addon-api/test/function_reference.cc +15 -13
  100. package/vendor/node-addon-api/test/globalObject/global_object_delete_property.js +50 -53
  101. package/vendor/node-addon-api/test/globalObject/global_object_get_property.js +33 -34
  102. package/vendor/node-addon-api/test/globalObject/global_object_has_own_property.js +38 -40
  103. package/vendor/node-addon-api/test/globalObject/global_object_set_property.js +47 -49
  104. package/vendor/node-addon-api/test/handlescope.cc +29 -3
  105. package/vendor/node-addon-api/test/handlescope.js +5 -3
  106. package/vendor/node-addon-api/test/index.js +1 -5
  107. package/vendor/node-addon-api/test/maybe/check.cc +49 -3
  108. package/vendor/node-addon-api/test/maybe/index.js +19 -7
  109. package/vendor/node-addon-api/test/memory_management.cc +9 -8
  110. package/vendor/node-addon-api/test/memory_management.js +2 -2
  111. package/vendor/node-addon-api/test/movable_callbacks.js +2 -2
  112. package/vendor/node-addon-api/test/name.js +3 -3
  113. package/vendor/node-addon-api/test/napi_child.js +2 -2
  114. package/vendor/node-addon-api/test/object/delete_property.js +7 -7
  115. package/vendor/node-addon-api/test/object/finalizer.cc +13 -12
  116. package/vendor/node-addon-api/test/object/finalizer.js +2 -2
  117. package/vendor/node-addon-api/test/object/get_property.js +6 -6
  118. package/vendor/node-addon-api/test/object/has_own_property.js +3 -3
  119. package/vendor/node-addon-api/test/object/has_property.js +4 -4
  120. package/vendor/node-addon-api/test/object/object.cc +191 -111
  121. package/vendor/node-addon-api/test/object/object.js +53 -52
  122. package/vendor/node-addon-api/test/object/object_deprecated.cc +24 -20
  123. package/vendor/node-addon-api/test/object/object_deprecated.js +3 -8
  124. package/vendor/node-addon-api/test/object/object_freeze_seal.js +54 -54
  125. package/vendor/node-addon-api/test/object/object_type_tag.cc +39 -0
  126. package/vendor/node-addon-api/test/object/object_type_tag.js +55 -0
  127. package/vendor/node-addon-api/test/object/subscript_operator.js +2 -2
  128. package/vendor/node-addon-api/test/object_reference.js +100 -100
  129. package/vendor/node-addon-api/test/objectwrap.cc +41 -34
  130. package/vendor/node-addon-api/test/objectwrap.js +23 -19
  131. package/vendor/node-addon-api/test/objectwrap_constructor_exception.cc +5 -5
  132. package/vendor/node-addon-api/test/objectwrap_constructor_exception.js +1 -1
  133. package/vendor/node-addon-api/test/objectwrap_multiple_inheritance.cc +7 -7
  134. package/vendor/node-addon-api/test/objectwrap_multiple_inheritance.js +1 -1
  135. package/vendor/node-addon-api/test/objectwrap_removewrap.js +24 -32
  136. package/vendor/node-addon-api/test/objectwrap_worker_thread.js +5 -4
  137. package/vendor/node-addon-api/test/promise.cc +7 -0
  138. package/vendor/node-addon-api/test/promise.js +3 -1
  139. package/vendor/node-addon-api/test/reference.cc +1 -1
  140. package/vendor/node-addon-api/test/reference.js +2 -2
  141. package/vendor/node-addon-api/test/run_script.cc +1 -1
  142. package/vendor/node-addon-api/test/symbol.js +59 -66
  143. package/vendor/node-addon-api/test/testUtil.js +6 -6
  144. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function.cc +64 -29
  145. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function.js +71 -34
  146. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ctx.cc +111 -19
  147. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ctx.js +2 -1
  148. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_existing_tsfn.cc +36 -26
  149. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_existing_tsfn.js +5 -5
  150. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ptr.cc +3 -2
  151. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_ptr.js +1 -1
  152. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_sum.cc +47 -32
  153. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_sum.js +3 -3
  154. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_unref.cc +22 -9
  155. package/vendor/node-addon-api/test/threadsafe_function/threadsafe_function_unref.js +76 -31
  156. package/vendor/node-addon-api/test/thunking_manual.cc +61 -74
  157. package/vendor/node-addon-api/test/thunking_manual.js +6 -7
  158. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function.cc +20 -20
  159. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function.js +19 -19
  160. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ctx.cc +57 -5
  161. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ctx.js +2 -0
  162. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_existing_tsfn.js +5 -5
  163. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ptr.cc +5 -1
  164. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_ptr.js +4 -3
  165. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_sum.js +3 -3
  166. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_unref.cc +14 -0
  167. package/vendor/node-addon-api/test/typed_threadsafe_function/typed_threadsafe_function_unref.js +76 -31
  168. package/vendor/node-addon-api/test/typedarray-bigint.js +2 -2
  169. package/vendor/node-addon-api/test/typedarray.cc +263 -70
  170. package/vendor/node-addon-api/test/typedarray.js +44 -10
  171. package/vendor/node-addon-api/test/version_management.cc +16 -15
  172. package/vendor/node-addon-api/test/version_management.js +18 -20
  173. package/vendor/node-addon-api/tools/check-napi.js +13 -14
  174. package/vendor/node-addon-api/tools/conversion.js +161 -169
  175. package/vendor/node-addon-api/tools/eslint-format.js +9 -1
  176. package/vendor/node-addon-api/unit-test/README.md +4 -4
  177. package/koffi-2.3.3.tgz +0 -0
  178. package/src/koffi/build/2.3.3/koffi_darwin_arm64.tar.gz +0 -0
  179. package/src/koffi/build/2.3.3/koffi_darwin_x64.tar.gz +0 -0
  180. package/src/koffi/build/2.3.3/koffi_freebsd_arm64.tar.gz +0 -0
  181. package/src/koffi/build/2.3.3/koffi_freebsd_ia32.tar.gz +0 -0
  182. package/src/koffi/build/2.3.3/koffi_freebsd_x64.tar.gz +0 -0
  183. package/src/koffi/build/2.3.3/koffi_linux_arm32hf.tar.gz +0 -0
  184. package/src/koffi/build/2.3.3/koffi_linux_arm64.tar.gz +0 -0
  185. package/src/koffi/build/2.3.3/koffi_linux_ia32.tar.gz +0 -0
  186. package/src/koffi/build/2.3.3/koffi_linux_riscv64hf64.tar.gz +0 -0
  187. package/src/koffi/build/2.3.3/koffi_linux_x64.tar.gz +0 -0
  188. package/src/koffi/build/2.3.3/koffi_openbsd_ia32.tar.gz +0 -0
  189. package/src/koffi/build/2.3.3/koffi_openbsd_x64.tar.gz +0 -0
  190. package/src/koffi/build/2.3.3/koffi_win32_arm64.tar.gz +0 -0
  191. package/src/koffi/build/2.3.3/koffi_win32_ia32.tar.gz +0 -0
  192. package/src/koffi/build/2.3.3/koffi_win32_x64.tar.gz +0 -0
package/CHANGELOG.md CHANGED
@@ -4,7 +4,23 @@
4
4
 
5
5
  ### Koffi 2.3
6
6
 
7
- #### Koffi 2.3.3
7
+ #### Koffi 2.3.5
8
+
9
+ **Main fixes:**
10
+
11
+ - Fix rare random crashes with async callbacks
12
+ - Fix some bugs with RISC-V 64 ABI
13
+
14
+ **Other changes:**
15
+
16
+ - Expose array type hint in `koffi.introspect()`
17
+ - Add missing `koffi.array()` export in TS definition
18
+ - Make KoffiFunction more flexible in TS definition ([@insraq](https://github.com/insraq))
19
+ - Add a KoffiFunc<T> helper type in TS typing ([@insraq](https://github.com/insraq))
20
+ - Mark optional properties in TS TypeInfo class
21
+ - Minor performance improvements
22
+
23
+ #### Koffi 2.3.4
8
24
 
9
25
  **Main fixes:**
10
26
 
@@ -37,7 +53,7 @@
37
53
 
38
54
  - Allow buffers (TypedArray or ArrayBuffer) values for input and/or output pointer arguments (for polymorphic arguments)
39
55
  - Support opaque buffers (TypedArray or ArrayBuffer) values in `koffi.decode()` to [decode output buffers](calls.md#output-buffers)
40
- - Decode non-string types as arrays when an [explicit length is passed to koffi.decode()](callbacks.md#pointer-arguments)
56
+ - Decode non-string types as arrays when an [explicit length is passed to koffi.decode()](callbacks.md#decoding-pointer-arguments)
41
57
 
42
58
  **Other changes:**
43
59
 
@@ -100,7 +116,7 @@
100
116
 
101
117
  **New features:**
102
118
 
103
- - Add [koffi.decode()](callbacks.md#pointer-arguments) for callback pointer arguments
119
+ - Add [koffi.decode()](callbacks.md#decoding-pointer-arguments) for callback pointer arguments
104
120
  - Support transparent [output string parameters](calls.md#output-parameters)
105
121
  - Add `koffi.offsetof()` utility function
106
122
  - Support optional *this* binding in `koffi.register()`
package/doc/changelog.md CHANGED
@@ -1 +1,5 @@
1
+ ---
2
+ tocdepth: 3
3
+ ---
4
+
1
5
  {{ "```{include} " ~ root ~ "/CHANGELOG.md" ~ "\n```" }}
package/doc/index.rst CHANGED
@@ -11,7 +11,6 @@ Koffi is a **fast and easy-to-use C FFI module for Node.js**, featuring:
11
11
  * Javascript functions can be used as C callbacks (since 1.2.0)
12
12
  * Well-tested code base for :ref:`popular OS/architecture combinations<Supported platforms>`
13
13
 
14
-
15
14
  Koffi requires a recent `Node.js <https://nodejs.org/>`_ version with N-API version 8 support, see :ref:`this page<Node.js>` for more information.
16
15
 
17
16
  The source code is available here: https://github.com/Koromix/rygel/ (in the *src/koffi* subdirectory).
@@ -20,7 +19,7 @@ Table of contents
20
19
  -----------------
21
20
 
22
21
  .. toctree::
23
- :maxdepth: 2
22
+ :maxdepth: 3
24
23
 
25
24
  platforms
26
25
  start
package/doc/types.md CHANGED
@@ -339,7 +339,7 @@ Fixed-size arrays are declared with `koffi.array(type, length)`. Just like in C,
339
339
  Koffi applies the following conversion rules when passing arrays to/from C:
340
340
 
341
341
  - **JS to C**: Koffi can take a normal Array (e.g. `[1, 2]`) or a TypedArray of the correct type (e.g. `Uint8Array` for an array of `uint8_t` numbers)
342
- - **C to JS** (return value, output parameters, callbacks): Koffi will use a TypedArray if possible. But you can change this behavior when you create the array type with the optional hint argument: `koffi.array('uint8_t', 64, 'array')`. For non-number types, such as arrays of strings or structs, Koffi creates normal arrays.
342
+ - **C to JS** (return value, output parameters, callbacks): Koffi will use a TypedArray if possible. But you can change this behavior when you create the array type with the optional hint argument: `koffi.array('uint8_t', 64, 'Array')`. For non-number types, such as arrays of strings or structs, Koffi creates normal arrays.
343
343
 
344
344
  See the example below:
345
345
 
@@ -353,7 +353,7 @@ const Foo1 = koffi.struct('Foo', {
353
353
  });
354
354
  const Foo2 = koffi.struct('Foo', {
355
355
  i: 'int',
356
- a16: koffi.array('int16_t', 8, 'array')
356
+ a16: koffi.array('int16_t', 8, 'Array')
357
357
  });
358
358
 
359
359
  // Uses an hypothetical C function that just returns the struct passed as a parameter
@@ -371,7 +371,7 @@ Koffi can also convert JS strings to fixed-sized arrays in the following cases:
371
371
  - **char arrays** are filled with the UTF-8 encoded string, truncated if needed. The buffer is always NUL-terminated.
372
372
  - **char16 (or char16_t) arrays** are filled with the UTF-16 encoded string, truncated if needed. The buffer is always NUL-terminated.
373
373
 
374
- The reverse case is also true, Koffi can convert a C fixed-size buffer to a JS string. This happens by default for char, char16 and char16_t arrays, but you can also explicitly ask for this with the `string` array hint (e.g. `koffi.array('char', 8, 'string')`).
374
+ The reverse case is also true, Koffi can convert a C fixed-size buffer to a JS string. This happens by default for char, char16 and char16_t arrays, but you can also explicitly ask for this with the `String` array hint (e.g. `koffi.array('char', 8, 'String')`).
375
375
 
376
376
  ### Array pointers (dynamic arrays)
377
377
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "2.3.3",
4
- "stable": "2.3.3",
3
+ "version": "2.3.5",
4
+ "stable": "2.3.5",
5
5
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
6
6
  "keywords": [
7
7
  "foreign",
@@ -4048,8 +4048,8 @@ static void DefaultSignalHandler(int signal)
4048
4048
 
4049
4049
  RG_INIT(SetupDefaultHandlers)
4050
4050
  {
4051
- int ret = setpgid(0, 0);
4052
- RG_ASSERT(!ret);
4051
+ // Best effort
4052
+ setpgid(0, 0);
4053
4053
 
4054
4054
  SetSignalHandler(SIGINT, DefaultSignalHandler);
4055
4055
  SetSignalHandler(SIGTERM, DefaultSignalHandler);
@@ -54,12 +54,32 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
54
54
 
55
55
  #include "abi_trampolines.inc"
56
56
 
57
- static inline int IsHFA(const TypeInfo *type)
57
+ static int IsHFA(const TypeInfo *type)
58
58
  {
59
59
  #ifdef __ARM_PCS_VFP
60
- return IsHFA(type, 1, 4);
60
+ bool float32 = false;
61
+ bool float64 = false;
62
+ int count = 0;
63
+
64
+ count = AnalyseFlat(type, [&](const TypeInfo *type, int, int) {
65
+ if (type->primitive == PrimitiveKind::Float32) {
66
+ float32 = true;
67
+ } else if (type->primitive == PrimitiveKind::Float64) {
68
+ float64 = true;
69
+ } else {
70
+ float32 = true;
71
+ float64 = true;
72
+ }
73
+ });
74
+
75
+ if (count < 1 || count > 4)
76
+ return 0;
77
+ if (float32 && float64)
78
+ return 0;
79
+
80
+ return count;
61
81
  #else
62
- return false;
82
+ return 0;
63
83
  #endif
64
84
  }
65
85
 
@@ -67,9 +87,11 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
67
87
  {
68
88
  if (int hfa = IsHFA(func->ret.type); hfa) {
69
89
  func->ret.vec_count = hfa;
70
- } else if (func->ret.type->primitive != PrimitiveKind::Record ||
71
- func->ret.type->size <= 4) {
90
+ } else if (func->ret.type->primitive != PrimitiveKind::Record &&
91
+ func->ret.type->primitive != PrimitiveKind::Union) {
72
92
  func->ret.gpr_count = (func->ret.type->size > 4) ? 2 : 1;
93
+ } else if (func->ret.type->size <= 4) {
94
+ func->ret.gpr_count = 1;
73
95
  } else {
74
96
  func->ret.use_memory = true;
75
97
  }
@@ -118,7 +140,8 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
118
140
  started_stack = true;
119
141
  }
120
142
  } break;
121
- case PrimitiveKind::Record: {
143
+ case PrimitiveKind::Record:
144
+ case PrimitiveKind::Union: {
122
145
  int hfa = IsHFA(param.type);
123
146
 
124
147
  if (hfa) {
@@ -319,7 +342,8 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
319
342
 
320
343
  *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
321
344
  } break;
322
- case PrimitiveKind::Record: {
345
+ case PrimitiveKind::Record:
346
+ case PrimitiveKind::Union: {
323
347
  if (RG_UNLIKELY(!IsObject(value))) {
324
348
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
325
349
  return false;
@@ -455,7 +479,8 @@ void CallData::Execute(const FunctionInfo *func)
455
479
  case PrimitiveKind::String16:
456
480
  case PrimitiveKind::Pointer:
457
481
  case PrimitiveKind::Callback: { result.u64 = PERFORM_CALL(GG); } break;
458
- case PrimitiveKind::Record: {
482
+ case PrimitiveKind::Record:
483
+ case PrimitiveKind::Union: {
459
484
  if (func->ret.vec_count) {
460
485
  HfaRet ret = PERFORM_CALL(DDDD);
461
486
  memcpy(&result.buf, &ret, RG_SIZE(ret));
@@ -513,7 +538,8 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
513
538
  return env.Null();
514
539
  }
515
540
  } break;
516
- case PrimitiveKind::Record: {
541
+ case PrimitiveKind::Record:
542
+ case PrimitiveKind::Union: {
517
543
  const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
518
544
  : (const uint8_t *)&result.buf;
519
545
 
@@ -709,7 +735,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
709
735
  param.type->dispose(env, param.type, ptr2);
710
736
  }
711
737
  } break;
712
- case PrimitiveKind::Record: {
738
+ case PrimitiveKind::Record:
739
+ case PrimitiveKind::Union: {
713
740
  if (param.vec_count) {
714
741
  Napi::Object obj = DecodeObject(env, (const uint8_t *)vec_ptr, param.type);
715
742
  arguments.Append(obj);
@@ -893,7 +920,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
893
920
 
894
921
  if (CheckValueTag(instance, value, type->ref.marker)) {
895
922
  ptr = value.As<Napi::External<uint8_t>>().Data();
896
- } else if (IsObject(value) && type->ref.type->primitive == PrimitiveKind::Record) {
923
+ } else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
924
+ type->ref.type->primitive == PrimitiveKind::Union)) {
897
925
  Napi::Object obj = value.As<Napi::Object>();
898
926
 
899
927
  ptr = AllocHeap(type->ref.type->size, 16);
@@ -909,7 +937,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
909
937
 
910
938
  out_reg->r0 = (uint32_t)ptr;
911
939
  } break;
912
- case PrimitiveKind::Record: {
940
+ case PrimitiveKind::Record:
941
+ case PrimitiveKind::Union: {
913
942
  if (RG_UNLIKELY(!IsObject(value))) {
914
943
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
915
944
  return;
@@ -921,8 +950,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
921
950
  if (!PushObject(obj, type, return_ptr))
922
951
  return;
923
952
  out_reg->r0 = (uint32_t)return_ptr;
924
- } else if (proto->ret.vec_count) { // HFA
925
- PushObject(obj, type, (uint8_t *)&out_reg->d0, 8);
953
+ } else if (proto->ret.vec_count) {
954
+ PushObject(obj, type, (uint8_t *)&out_reg->d0);
926
955
  } else {
927
956
  PushObject(obj, type, (uint8_t *)&out_reg->r0);
928
957
  }
@@ -25,6 +25,11 @@
25
25
 
26
26
  namespace RG {
27
27
 
28
+ struct HfaInfo {
29
+ int count;
30
+ bool float32;
31
+ };
32
+
28
33
  struct X0X1Ret {
29
34
  uint64_t x0;
30
35
  uint64_t x1;
@@ -59,15 +64,61 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
59
64
 
60
65
  #include "abi_trampolines.inc"
61
66
 
62
- static inline int IsHFA(const TypeInfo *type)
67
+ static HfaInfo IsHFA(const TypeInfo *type)
68
+ {
69
+ bool float32 = false;
70
+ bool float64 = false;
71
+ int count = 0;
72
+
73
+ count = AnalyseFlat(type, [&](const TypeInfo *type, int, int) {
74
+ if (type->primitive == PrimitiveKind::Float32) {
75
+ float32 = true;
76
+ } else if (type->primitive == PrimitiveKind::Float64) {
77
+ float64 = true;
78
+ } else {
79
+ float32 = true;
80
+ float64 = true;
81
+ }
82
+ });
83
+
84
+ HfaInfo info = {};
85
+
86
+ if (count < 1 || count > 4)
87
+ return info;
88
+ if (float32 && float64)
89
+ return info;
90
+
91
+ info.count = count;
92
+ info.float32 = float32;
93
+
94
+ return info;
95
+ }
96
+
97
+ static inline void ExpandFloats(uint8_t *ptr, Size len, Size bytes)
98
+ {
99
+ for (Size i = len - 1; i >= 0; i--) {
100
+ const uint8_t *src = ptr + i * bytes;
101
+ uint8_t *dest = ptr + i * 8;
102
+
103
+ memmove(dest, src, bytes);
104
+ }
105
+ }
106
+
107
+ static inline void CompactFloats(uint8_t *ptr, Size len, Size bytes)
63
108
  {
64
- return IsHFA(type, 1, 4);
109
+ for (Size i = 0; i < len; i++) {
110
+ const uint8_t *src = ptr + i * 8;
111
+ uint8_t *dest = ptr + i * bytes;
112
+
113
+ memmove(dest, src, bytes);
114
+ }
65
115
  }
66
116
 
67
117
  bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
68
118
  {
69
- if (int hfa = IsHFA(func->ret.type); hfa) {
70
- func->ret.vec_count = (int8_t)hfa;
119
+ if (HfaInfo hfa = IsHFA(func->ret.type); hfa.count) {
120
+ func->ret.vec_count = (int8_t)hfa.count;
121
+ func->ret.vec_bytes = hfa.float32 ? 4 : 8;
71
122
  } else if (func->ret.type->size <= 16) {
72
123
  func->ret.gpr_count = (int8_t)((func->ret.type->size + 7) / 8);
73
124
  } else {
@@ -115,8 +166,9 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
115
166
  gpr_avail--;
116
167
  }
117
168
  } break;
118
- case PrimitiveKind::Record: {
119
- int hfa = IsHFA(param.type);
169
+ case PrimitiveKind::Record:
170
+ case PrimitiveKind::Union: {
171
+ HfaInfo hfa = IsHFA(param.type);
120
172
 
121
173
  #ifdef _M_ARM64EC
122
174
  if (func->variadic) {
@@ -137,7 +189,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
137
189
 
138
190
  #if defined(_WIN32)
139
191
  if (param.variadic) {
140
- hfa = 0;
192
+ hfa.count = 0;
141
193
  }
142
194
  #elif defined(__APPLE__)
143
195
  if (param.variadic) {
@@ -146,10 +198,11 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
146
198
  }
147
199
  #endif
148
200
 
149
- if (hfa) {
150
- if (hfa <= vec_avail) {
151
- param.vec_count = (int8_t)hfa;
152
- vec_avail -= hfa;
201
+ if (hfa.count) {
202
+ if (hfa.count <= vec_avail) {
203
+ param.vec_count = (int8_t)hfa.count;
204
+ param.vec_bytes = hfa.float32 ? 4 : 8;
205
+ vec_avail -= hfa.count;
153
206
  } else {
154
207
  vec_avail = 0;
155
208
  }
@@ -364,7 +417,8 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
364
417
  #endif
365
418
  *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
366
419
  } break;
367
- case PrimitiveKind::Record: {
420
+ case PrimitiveKind::Record:
421
+ case PrimitiveKind::Union: {
368
422
  if (RG_UNLIKELY(!IsObject(value))) {
369
423
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
370
424
  return false;
@@ -373,8 +427,12 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
373
427
  Napi::Object obj = value.As<Napi::Object>();
374
428
 
375
429
  if (param.vec_count) { // HFA
376
- if (!PushObject(obj, param.type, (uint8_t *)vec_ptr, 8))
430
+ uint8_t *ptr = (uint8_t *)vec_ptr;
431
+
432
+ if (!PushObject(obj, param.type, ptr))
377
433
  return false;
434
+ ExpandFloats(ptr, param.vec_count, param.vec_bytes);
435
+
378
436
  vec_ptr += param.vec_count;
379
437
  } else if (!param.use_memory) {
380
438
  if (param.gpr_count) {
@@ -544,7 +602,8 @@ void CallData::Execute(const FunctionInfo *func)
544
602
  case PrimitiveKind::String16:
545
603
  case PrimitiveKind::Pointer:
546
604
  case PrimitiveKind::Callback: { result.u64 = PERFORM_CALL(GG).x0; } break;
547
- case PrimitiveKind::Record: {
605
+ case PrimitiveKind::Record:
606
+ case PrimitiveKind::Union: {
548
607
  if (func->ret.gpr_count) {
549
608
  X0X1Ret ret = PERFORM_CALL(GG);
550
609
  memcpy(&result.buf, &ret, RG_SIZE(ret));
@@ -605,9 +664,14 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
605
664
  return env.Null();
606
665
  }
607
666
  } break;
608
- case PrimitiveKind::Record: {
667
+ case PrimitiveKind::Record:
668
+ case PrimitiveKind::Union: {
609
669
  if (func->ret.vec_count) { // HFA
610
- Napi::Object obj = DecodeObject(env, (const uint8_t *)&result.buf, func->ret.type, 8);
670
+ uint8_t *ptr = (uint8_t *)&result.buf;
671
+
672
+ CompactFloats(ptr, func->ret.vec_count, func->ret.vec_bytes);
673
+
674
+ Napi::Object obj = DecodeObject(env, ptr, func->ret.type);
611
675
  return obj;
612
676
  } else {
613
677
  const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
@@ -973,9 +1037,14 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
973
1037
  param.type->dispose(env, param.type, ptr2);
974
1038
  }
975
1039
  } break;
976
- case PrimitiveKind::Record: {
1040
+ case PrimitiveKind::Record:
1041
+ case PrimitiveKind::Union: {
977
1042
  if (param.vec_count) { // HFA
978
- Napi::Object obj = DecodeObject(env, (uint8_t *)vec_ptr, param.type, 8);
1043
+ uint8_t *ptr = (uint8_t *)vec_ptr;
1044
+
1045
+ CompactFloats(ptr, param.vec_count, param.vec_bytes);
1046
+
1047
+ Napi::Object obj = DecodeObject(env, ptr, param.type);
979
1048
  arguments.Append(obj);
980
1049
 
981
1050
  vec_ptr += param.vec_count;
@@ -1133,7 +1202,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
1133
1202
 
1134
1203
  if (CheckValueTag(instance, value, type->ref.marker)) {
1135
1204
  ptr = value.As<Napi::External<uint8_t>>().Data();
1136
- } else if (IsObject(value) && type->ref.type->primitive == PrimitiveKind::Record) {
1205
+ } else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
1206
+ type->ref.type->primitive == PrimitiveKind::Union)) {
1137
1207
  Napi::Object obj = value.As<Napi::Object>();
1138
1208
 
1139
1209
  ptr = AllocHeap(type->ref.type->size, 16);
@@ -1149,7 +1219,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
1149
1219
 
1150
1220
  out_reg->x0 = (uint64_t)ptr;
1151
1221
  } break;
1152
- case PrimitiveKind::Record: {
1222
+ case PrimitiveKind::Record:
1223
+ case PrimitiveKind::Union: {
1153
1224
  if (RG_UNLIKELY(!IsObject(value))) {
1154
1225
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
1155
1226
  return;
@@ -1162,7 +1233,10 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool async,
1162
1233
  return;
1163
1234
  out_reg->x0 = (uint64_t)return_ptr;
1164
1235
  } else if (proto->ret.vec_count) { // HFA
1165
- PushObject(obj, type, (uint8_t *)&out_reg->d0, 8);
1236
+ uint8_t *ptr = (uint8_t *)&out_reg->d0;
1237
+
1238
+ ExpandFloats(ptr, proto->ret.vec_count, proto->ret.vec_bytes);
1239
+ PushObject(obj, type, ptr);
1166
1240
  } else {
1167
1241
  PushObject(obj, type, (uint8_t *)&out_reg->x0);
1168
1242
  }