koffi 2.16.1 → 3.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/CHANGELOG.md +2 -2
  2. package/README.md +8 -8
  3. package/build/koffi/darwin_arm64/koffi.node +0 -0
  4. package/build/koffi/darwin_x64/koffi.node +0 -0
  5. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  6. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  7. package/build/koffi/freebsd_x64/koffi.node +0 -0
  8. package/build/koffi/linux_arm64/koffi.node +0 -0
  9. package/build/koffi/linux_ia32/koffi.node +0 -0
  10. package/build/koffi/linux_x64/koffi.node +0 -0
  11. package/build/koffi/musl_arm64/koffi.node +0 -0
  12. package/build/koffi/musl_x64/koffi.node +0 -0
  13. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  14. package/build/koffi/openbsd_x64/koffi.node +0 -0
  15. package/build/koffi/win32_ia32/koffi.node +0 -0
  16. package/build/koffi/win32_x64/koffi.node +0 -0
  17. package/doc/benchmarks.md +33 -33
  18. package/doc/benchmarks.xlsx +0 -0
  19. package/doc/contribute.md +37 -25
  20. package/doc/index.md +8 -8
  21. package/doc/variables.md +1 -1
  22. package/index.d.ts +11 -9
  23. package/index.js +1 -634
  24. package/indirect.js +1 -533
  25. package/lib/native/base/base.cc +63 -85
  26. package/lib/native/base/base.hh +178 -151
  27. package/package.json +3 -4
  28. package/src/build.js +1178 -0
  29. package/src/koffi/CMakeLists.txt +97 -34
  30. package/src/koffi/index.js +359 -0
  31. package/src/koffi/indirect.js +216 -0
  32. package/src/koffi/src/{abi_arm32.cc → abi/arm32.cc} +279 -275
  33. package/src/koffi/src/{abi_arm32_asm.S → abi/arm32_asm.S} +2 -5
  34. package/src/koffi/src/abi/arm64.cc +1511 -0
  35. package/src/koffi/src/{abi_arm64_asm.S → abi/arm64_asm.S} +44 -23
  36. package/src/koffi/src/{abi_arm64_asm.asm → abi/arm64_asm.asm} +32 -25
  37. package/src/koffi/src/{abi_loong64_asm.S → abi/loong64_asm.S} +1 -5
  38. package/src/koffi/src/{abi_riscv64.cc → abi/riscv64.cc} +279 -273
  39. package/src/koffi/src/{abi_riscv64_asm.S → abi/riscv64_asm.S} +1 -4
  40. package/src/koffi/src/abi/x64sysv.cc +1456 -0
  41. package/src/koffi/src/{abi_x64_sysv_asm.S → abi/x64sysv_asm.S} +30 -33
  42. package/src/koffi/src/abi/x64win.cc +1121 -0
  43. package/src/koffi/src/{abi_x64_win_asm.S → abi/x64win_asm.S} +8 -12
  44. package/src/koffi/src/{abi_x64_win_asm.asm → abi/x64win_asm.asm} +11 -14
  45. package/src/koffi/src/abi/x86.cc +1233 -0
  46. package/src/koffi/src/{abi_x86_asm.S → abi/x86_asm.S} +49 -25
  47. package/src/koffi/src/{abi_x86_asm.asm → abi/x86_asm.asm} +11 -14
  48. package/src/koffi/src/call.cc +458 -598
  49. package/src/koffi/src/call.hh +61 -82
  50. package/src/koffi/src/ffi.cc +595 -309
  51. package/src/koffi/src/ffi.hh +103 -89
  52. package/src/koffi/src/parser.cc +0 -4
  53. package/src/koffi/src/primitives.inc +39 -0
  54. package/src/koffi/{tools/write_trampolines.js → src/trampolines.js} +1 -1
  55. package/src/koffi/src/util.cc +503 -446
  56. package/src/koffi/src/util.hh +269 -57
  57. package/src/koffi/src/uv.cc +2 -2
  58. package/src/koffi/src/uv.def +3 -0
  59. package/src/koffi/src/win32.hh +30 -1
  60. package/vendor/node-addon-api/napi-inl.h +4 -0
  61. package/vendor/node-addon-api/napi.h +1 -0
  62. package/build/koffi/linux_armhf/koffi.node +0 -0
  63. package/build/koffi/linux_loong64/koffi.node +0 -0
  64. package/build/koffi/linux_riscv64d/koffi.node +0 -0
  65. package/build/koffi/win32_arm64/koffi.exp +0 -0
  66. package/build/koffi/win32_arm64/koffi.lib +0 -0
  67. package/build/koffi/win32_arm64/koffi.node +0 -0
  68. package/doc/platforms.md +0 -36
  69. package/src/cnoke/LICENSE.txt +0 -22
  70. package/src/cnoke/README.md +0 -99
  71. package/src/cnoke/assets/FindCNoke.cmake +0 -127
  72. package/src/cnoke/assets/toolchains.json +0 -126
  73. package/src/cnoke/assets/win_delay_hook.c +0 -36
  74. package/src/cnoke/cnoke.js +0 -170
  75. package/src/cnoke/package.json +0 -24
  76. package/src/cnoke/src/builder.js +0 -511
  77. package/src/cnoke/src/index.js +0 -10
  78. package/src/cnoke/src/tools.js +0 -407
  79. package/src/koffi/src/abi_arm64.cc +0 -1295
  80. package/src/koffi/src/abi_x64_sysv.cc +0 -939
  81. package/src/koffi/src/abi_x64_win.cc +0 -715
  82. package/src/koffi/src/abi_x86.cc +0 -860
  83. package/src/koffi/src/init.js +0 -105
  84. /package/src/koffi/src/{abi_loong64.cc → abi/loong64.cc} +0 -0
@@ -10,14 +10,36 @@
10
10
 
11
11
  namespace K {
12
12
 
13
+ #if defined(_MSC_VER)
14
+ #define FORCE_INLINE __forceinline
15
+ #else
16
+ #define FORCE_INLINE __attribute__((always_inline)) inline
17
+ #endif
18
+ #if defined(UNITY_BUILD)
19
+ #define INLINE_UNITY FORCE_INLINE
20
+ #else
21
+ #define INLINE_UNITY
22
+ #endif
23
+
24
+ #if defined(__GNUC__) || defined(__clang__)
25
+ #if __has_attribute(musttail) && __has_attribute(preserve_none)
26
+ #define MUST_TAIL __attribute__((musttail))
27
+ #define PRESERVE_NONE __attribute__((preserve_none))
28
+ #elif __has_attribute(musttail) && !defined(__clang__)
29
+ // GCC regalloc seems better, so the generated code is not too bad even without preserve_none
30
+ #define MUST_TAIL __attribute__((musttail))
31
+ #define PRESERVE_NONE
32
+ #endif
33
+ #endif
34
+
13
35
  extern const napi_type_tag TypeInfoMarker;
14
36
  extern const napi_type_tag CastMarker;
15
- extern const napi_type_tag MagicUnionMarker;
37
+ extern const napi_type_tag UnionClassMarker;
16
38
 
17
- class MagicUnion: public Napi::ObjectWrap<MagicUnion> {
39
+ class UnionClass: public Napi::ObjectWrap<UnionClass> {
40
+ InstanceData *instance;
18
41
  const TypeInfo *type;
19
42
 
20
- Napi::Reference<Napi::Symbol> active_symbol;
21
43
  Size active_idx = -1;
22
44
 
23
45
  HeapArray<uint8_t> raw;
@@ -25,7 +47,9 @@ class MagicUnion: public Napi::ObjectWrap<MagicUnion> {
25
47
  public:
26
48
  static Napi::Function InitClass(Napi::Env env, const TypeInfo *type);
27
49
 
28
- MagicUnion(const Napi::CallbackInfo &info);
50
+ UnionClass(const Napi::CallbackInfo &info);
51
+
52
+ void Finalize(Napi::BasicEnv env) override;
29
53
 
30
54
  const TypeInfo *GetType() { return type; }
31
55
  const RecordMember *GetMember() const { return (active_idx >= 0) ? &type->members[active_idx] : nullptr; }
@@ -48,21 +72,21 @@ void ThrowError(Napi::Env env, const char *msg, Args... args)
48
72
  err.ThrowAsJavaScriptException();
49
73
  }
50
74
 
51
- static inline bool IsInteger(const TypeInfo *type)
75
+ static FORCE_INLINE bool IsInteger(const TypeInfo *type)
52
76
  {
53
77
  bool integer = ((int)type->primitive >= (int)PrimitiveKind::Int8 &&
54
78
  (int)type->primitive <= (int)PrimitiveKind::UInt64);
55
79
  return integer;
56
80
  }
57
81
 
58
- static inline bool IsFloat(const TypeInfo *type)
82
+ static FORCE_INLINE bool IsFloat(const TypeInfo *type)
59
83
  {
60
84
  bool fp = (type->primitive == PrimitiveKind::Float32 ||
61
85
  type->primitive == PrimitiveKind::Float64);
62
86
  return fp;
63
87
  }
64
88
 
65
- static inline bool IsRegularSize(Size size, Size max)
89
+ static FORCE_INLINE bool IsRegularSize(Size size, Size max)
66
90
  {
67
91
  bool regular = (size <= max && !(size & (size - 1)));
68
92
  return regular;
@@ -82,65 +106,235 @@ bool CanPassType(const TypeInfo *type, int directions);
82
106
  bool CanReturnType(const TypeInfo *type);
83
107
  bool CanStoreType(const TypeInfo *type);
84
108
 
109
+ static FORCE_INLINE napi_valuetype GetKindOf(napi_env env, napi_value value)
110
+ {
111
+ napi_valuetype kind = napi_undefined;
112
+ napi_typeof(env, value, &kind);
113
+
114
+ return kind;
115
+ }
116
+
117
+ static FORCE_INLINE napi_valuetype GetKindOf(Napi::Value value)
118
+ {
119
+ return GetKindOf(value.Env(), value);
120
+ }
121
+
85
122
  // Can be slow, only use for error messages
86
- const char *GetValueType(const InstanceData *instance, Napi::Value value);
123
+ const char *GetValueType(const InstanceData *instance, napi_value value);
87
124
 
88
- void SetValueTag(Napi::Value value, const void *marker);
89
- bool CheckValueTag(Napi::Value value, const void *marker);
125
+ void SetValueTag(napi_env env, napi_value value, const void *marker);
126
+ bool CheckValueTag(napi_env env, napi_value value, const void *marker);
90
127
 
91
- static inline bool IsNullOrUndefined(Napi::Value value)
128
+ static FORCE_INLINE bool IsNullOrUndefined(napi_valuetype kind)
92
129
  {
93
- return value.IsNull() || value.IsUndefined();
130
+ return kind == napi_null || kind == napi_undefined;
94
131
  }
95
132
 
96
- static inline bool IsObject(Napi::Value value)
133
+ static FORCE_INLINE bool IsNullOrUndefined(napi_env env, napi_value value)
97
134
  {
98
- return value.IsObject() && !IsNullOrUndefined(value) && !value.IsArray();
135
+ napi_valuetype kind = GetKindOf(env, value);
136
+ return IsNullOrUndefined(kind);
99
137
  }
100
138
 
101
- static inline bool IsRawBuffer(Napi::Value value)
139
+ static FORCE_INLINE bool IsArray(napi_env env, napi_value value)
102
140
  {
103
- return value.IsTypedArray() || value.IsArrayBuffer();
141
+ bool array = false;
142
+ napi_is_array(env, value, &array);
143
+
144
+ return array;
104
145
  }
105
146
 
106
- static inline Span<uint8_t> GetRawBuffer(Napi::Value value)
147
+ static FORCE_INLINE bool IsObject(napi_env env, napi_value value)
107
148
  {
108
- if (value.IsBuffer()) {
109
- void *ptr = nullptr;
110
- size_t length = 0;
149
+ if (GetKindOf(env, value) != napi_object)
150
+ return false;
151
+ if (IsArray(env, value))
152
+ return false;
111
153
 
112
- // Assume it works
113
- napi_get_buffer_info(value.Env(), value, &ptr, &length);
154
+ return true;
155
+ }
114
156
 
115
- return MakeSpan((uint8_t *)ptr, (Size)length);
116
- } else if (value.IsArrayBuffer()) {
117
- Napi::ArrayBuffer buffer = value.As<Napi::ArrayBuffer>();
157
+ static FORCE_INLINE bool IsTypedArray(napi_env env, napi_value value)
158
+ {
159
+ bool typedarray = false;
160
+ napi_is_typedarray(env, value, &typedarray);
161
+ return typedarray;
162
+ }
118
163
 
119
- return MakeSpan((uint8_t *)buffer.Data(), (Size)buffer.ByteLength());
120
- }
164
+ static FORCE_INLINE bool IsArrayBuffer(napi_env env, napi_value value)
165
+ {
166
+ bool arraybuffer = false;
167
+ napi_is_arraybuffer(env, value, &arraybuffer);
168
+ return arraybuffer;
169
+ }
121
170
 
122
- K_UNREACHABLE();
171
+ static FORCE_INLINE bool IsBuffer(napi_env env, napi_value value)
172
+ {
173
+ bool buffer = false;
174
+ napi_is_buffer(env, value, &buffer);
175
+ return buffer;
123
176
  }
124
177
 
125
- int GetTypedArrayType(const TypeInfo *type);
178
+ static FORCE_INLINE napi_value GetReferenceValue(napi_env env, napi_ref ref)
179
+ {
180
+ napi_value value;
126
181
 
127
- template <typename T>
128
- T GetNumber(Napi::Value value)
182
+ napi_status status = napi_get_reference_value(env, ref, &value);
183
+ K_ASSERT(status == napi_ok);
184
+
185
+ return value;
186
+ }
187
+
188
+ static FORCE_INLINE uint32_t GetArrayLength(napi_env env, napi_value array)
129
189
  {
130
- K_ASSERT(value.IsNumber() || value.IsBigInt());
190
+ uint32_t length = 0;
131
191
 
132
- if (value.IsNumber()) [[likely]] {
133
- return (T)value.As<Napi::Number>().DoubleValue();
134
- } else if (value.IsBigInt()) {
135
- Napi::BigInt bigint = value.As<Napi::BigInt>();
192
+ napi_status status = napi_get_array_length(env, array, &length);
193
+ K_ASSERT(status == napi_ok);
194
+
195
+ return length;
196
+ }
197
+
198
+ template <typename T>
199
+ static FORCE_INLINE bool TryNumber(napi_env env, napi_value value, T *out_value)
200
+ {
201
+ T v;
202
+ napi_status status;
203
+
204
+ // Assume number first
205
+ if constexpr (std::is_same_v<T, double>) {
206
+ status = napi_get_value_double(env, value, &v);
207
+ } else if constexpr (std::is_same_v<T, float>) {
208
+ double d;
209
+ status = napi_get_value_double(env, value, &d);
210
+ v = (float)d;
211
+ } else {
212
+ int64_t i64;
213
+ status = napi_get_value_int64(env, value, &i64);
214
+ v = (T)i64;
215
+ }
216
+ if (status == napi_ok) [[likely]] {
217
+ *out_value = v;
218
+ return true;
219
+ }
136
220
 
221
+ // Maybe a BigInt?
222
+ if constexpr (std::is_signed_v<T>) {
223
+ int64_t i64;
137
224
  bool lossless;
138
- return (T)bigint.Uint64Value(&lossless);
225
+ status = napi_get_value_bigint_int64(env, value, &i64, &lossless);
226
+ v = (T)i64;
227
+ } else {
228
+ uint64_t u64;
229
+ bool lossless;
230
+ status = napi_get_value_bigint_uint64(env, value, &u64, &lossless);
231
+ v = (T)u64;
232
+ }
233
+ if (status == napi_ok) {
234
+ *out_value = v;
235
+ return true;
139
236
  }
140
237
 
141
- K_UNREACHABLE();
238
+ return false;
142
239
  }
143
240
 
241
+ static FORCE_INLINE bool TryPointer(napi_env env, napi_value value, void **out_ptr)
242
+ {
243
+ if (uintptr_t ptr = 0; TryNumber(env, value, &ptr)) {
244
+ *out_ptr = (void *)ptr;
245
+ return true;
246
+ }
247
+
248
+ napi_valuetype kind = GetKindOf(env, value);
249
+
250
+ if (IsNullOrUndefined(kind)) {
251
+ *out_ptr = nullptr;
252
+ return true;
253
+ } else if (IsTypedArray(env, value)) {
254
+ napi_get_typedarray_info(env, value, nullptr, nullptr, out_ptr, nullptr, nullptr);
255
+ return true;
256
+ } else if (kind == napi_external) {
257
+ Napi::External<void> external = Napi::External<void>(env, value);
258
+
259
+ *out_ptr = (void *)external.Data();
260
+ return true;
261
+ } else if (IsArrayBuffer(env, value)) {
262
+ Napi::ArrayBuffer buffer = Napi::ArrayBuffer(env, value);
263
+
264
+ *out_ptr = (void *)buffer.Data();
265
+ return true;
266
+ }
267
+
268
+ return false;
269
+ }
270
+
271
+ static FORCE_INLINE bool TryPointer(napi_env env, napi_value value, void **out_ptr, bool *out_external)
272
+ {
273
+ if (uintptr_t ptr = 0; TryNumber(env, value, &ptr)) {
274
+ *out_ptr = (void *)ptr;
275
+ *out_external = false;
276
+
277
+ return true;
278
+ }
279
+
280
+ napi_valuetype kind = GetKindOf(env, value);
281
+
282
+ if (IsNullOrUndefined(kind)) {
283
+ *out_ptr = nullptr;
284
+ *out_external = false;
285
+
286
+ return true;
287
+ } else if (IsTypedArray(env, value)) {
288
+ napi_get_typedarray_info(env, value, nullptr, nullptr, out_ptr, nullptr, nullptr);
289
+ *out_external = false;
290
+
291
+ return true;
292
+ } else if (kind == napi_external) {
293
+ Napi::External<void> external = Napi::External<void>(env, value);
294
+
295
+ *out_ptr = (void *)external.Data();
296
+ *out_external = true;
297
+
298
+ return true;
299
+ } else if (IsArrayBuffer(env, value)) {
300
+ Napi::ArrayBuffer buffer = Napi::ArrayBuffer(env, value);
301
+
302
+ *out_ptr = (void *)buffer.Data();
303
+ *out_external = false;
304
+
305
+ return true;
306
+ }
307
+
308
+ return false;
309
+ }
310
+
311
+ static FORCE_INLINE bool TryBuffer(napi_env env, napi_value value, Span<uint8_t> *out_buffer)
312
+ {
313
+ // Before somewhere around Node 20.12, napi_get_buffer_info() would assert/crash
314
+ // when used with something it did not support, instead of returning napi_invalid_arg.
315
+ // So we need to call napi_is_buffer(), at least for now.
316
+
317
+ if (IsBuffer(env, value)) {
318
+ void *ptr = nullptr;
319
+ size_t length = 0;
320
+
321
+ // Assume it works
322
+ napi_get_buffer_info(env, value, &ptr, &length);
323
+
324
+ *out_buffer = MakeSpan((uint8_t *)ptr, (Size)length);
325
+ return true;
326
+ } else if (IsArrayBuffer(env, value)) {
327
+ Napi::ArrayBuffer buffer = Napi::ArrayBuffer(env, value);
328
+
329
+ *out_buffer = MakeSpan((uint8_t *)buffer.Data(), (Size)buffer.ByteLength());
330
+ return true;
331
+ }
332
+
333
+ return false;
334
+ }
335
+
336
+ int GetTypedArrayType(const TypeInfo *type);
337
+
144
338
  template <typename T>
145
339
  Size NullTerminatedLength(const T *ptr)
146
340
  {
@@ -165,10 +359,10 @@ static inline Napi::String MakeStringFromUTF32(Napi::Env env, const char32_t *pt
165
359
  { return MakeStringFromUTF32(env, ptr, NullTerminatedLength(ptr)); }
166
360
 
167
361
  Napi::Object DecodeObject(Napi::Env env, const uint8_t *origin, const TypeInfo *type);
168
- void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type);
169
- Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type, uint32_t len);
362
+ void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const TypeInfo *type);
170
363
  Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type);
171
- void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo *ref);
364
+ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type, uint32_t len);
365
+ void DecodeElements(Napi::Env env, napi_value array, const uint8_t *origin, const TypeInfo *ref, uint32_t len);
172
366
  void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *ref);
173
367
 
174
368
  Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, const Size *len = nullptr);
@@ -177,29 +371,44 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
177
371
  bool Encode(Napi::Value ref, Size offset, Napi::Value value, const TypeInfo *type, const Size *len = nullptr);
178
372
  bool Encode(Napi::Env env, uint8_t *ptr, Napi::Value value, const TypeInfo *type, const Size *len = nullptr);
179
373
 
180
- static inline Napi::Value NewBigInt(Napi::Env env, int64_t value)
181
- {
182
- if (value <= 9007199254740992ll && value >= -9007199254740992ll) {
183
- double d = (double)value;
184
- return Napi::Number::New(env, d);
185
- } else {
186
- return Napi::BigInt::New(env, value);
187
- }
188
- }
374
+ static FORCE_INLINE Napi::Value NewInt(Napi::Env env, int8_t i)
375
+ { napi_value value; napi_create_int32(env, (int32_t)i, &value); return Napi::Value(env, value); }
376
+ static FORCE_INLINE Napi::Value NewInt(Napi::Env env, uint8_t i)
377
+ { napi_value value; napi_create_uint32(env, (uint32_t)i, &value); return Napi::Value(env, value); }
378
+ static FORCE_INLINE Napi::Value NewInt(Napi::Env env, int16_t i)
379
+ { napi_value value; napi_create_int32(env, (int32_t)i, &value); return Napi::Value(env, value); }
380
+ static FORCE_INLINE Napi::Value NewInt(Napi::Env env, uint16_t i)
381
+ { napi_value value; napi_create_uint32(env, (uint32_t)i, &value); return Napi::Value(env, value); }
382
+ static FORCE_INLINE Napi::Value NewInt(Napi::Env env, int32_t i)
383
+ { napi_value value; napi_create_int32(env, i, &value); return Napi::Value(env, value); }
384
+ static FORCE_INLINE Napi::Value NewInt(Napi::Env env, uint32_t i)
385
+ { napi_value value; napi_create_uint32(env, i, &value); return Napi::Value(env, value); }
189
386
 
190
- static inline Napi::Value NewBigInt(Napi::Env env, uint64_t value)
387
+ template <typename T>
388
+ static FORCE_INLINE Napi::Value NewInt(Napi::Env env, T i)
191
389
  {
192
- if (value <= 9007199254740992ull) {
193
- double d = (double)value;
194
- return Napi::Number::New(env, d);
390
+ static_assert(sizeof(T) == 8);
391
+
392
+ if constexpr (std::is_signed_v<T>) {
393
+ if (i <= 9007199254740992ll && i >= -9007199254740992ll) {
394
+ napi_value value;
395
+ napi_create_int64(env, (int64_t)i, &value);
396
+ return Napi::Value(env, value);
397
+ }
195
398
  } else {
196
- return Napi::BigInt::New(env, value);
399
+ if (i <= 9007199254740992ull) {
400
+ napi_value value;
401
+ napi_create_int64(env, (int64_t)i, &value);
402
+ return Napi::Value(env, value);
403
+ }
197
404
  }
405
+
406
+ return Napi::BigInt::New(env, i);
198
407
  }
199
408
 
200
- static inline Napi::Array GetOwnPropertyNames(Napi::Object obj)
409
+ static FORCE_INLINE Napi::Array GetOwnPropertyNames(napi_env env, napi_value obj)
201
410
  {
202
- Napi::Env env = obj.Env();
411
+ K_ASSERT(IsObject(env, obj));
203
412
 
204
413
  napi_value result;
205
414
  napi_status status = napi_get_all_property_names(env, obj, napi_key_own_only,
@@ -212,6 +421,9 @@ static inline Napi::Array GetOwnPropertyNames(Napi::Object obj)
212
421
 
213
422
  Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func);
214
423
 
424
+ Napi::Value INLINE_UNITY WrapPointer(Napi::Env env, const TypeInfo *ref, void *ptr);
425
+ Napi::Value INLINE_UNITY WrapCallback(Napi::Env env, const TypeInfo *ref, void *ptr);
426
+
215
427
  bool DetectCallConvention(Span<const char> name, CallConvention *out_convention);
216
428
 
217
429
  int AnalyseFlat(const TypeInfo *type, FunctionRef<void(const TypeInfo *type, int offset, int count)> func);
@@ -143,7 +143,7 @@ void PollHandle::OnPoll(uv_poll_t *h, int status, int events)
143
143
  obj.Set("writable", !!(events & UV_WRITABLE));
144
144
  obj.Set("disconnect", !!(events & UV_DISCONNECT));
145
145
 
146
- napi_value args[] = { Napi::Number::New(env, status), obj };
146
+ napi_value args[] = { NewInt(env, (int32_t)status), obj };
147
147
  poll->callback.Call(poll->Value(), K_LEN(args), args);
148
148
  }
149
149
 
@@ -171,7 +171,7 @@ Napi::Value Poll(const Napi::CallbackInfo &info)
171
171
  int fd = info[0].As<Napi::Number>().Int32Value();
172
172
 
173
173
  Napi::Function ctor = PollHandle::Define(env);
174
- Napi::Object inst = ctor.New({ Napi::Number::New(env, fd) });
174
+ Napi::Object inst = ctor.New({ NewInt(env, (int32_t)fd) });
175
175
  Napi::Function start = inst.Get("start").As<Napi::Function>();
176
176
 
177
177
  if (env.IsExceptionPending()) [[unlikely]]
@@ -8,3 +8,6 @@ uv_poll_init
8
8
  uv_poll_init_socket
9
9
  uv_poll_start
10
10
  uv_poll_stop
11
+ uv_dlopen
12
+ uv_dlclose
13
+ uv_dlsym
@@ -49,7 +49,7 @@ struct PE_NT_HEADERS {
49
49
  // ... OptionalHeader;
50
50
  };
51
51
 
52
- #if _WIN64
52
+ #if defined(_WIN64)
53
53
 
54
54
  struct TEB {
55
55
  void *ExceptionList;
@@ -107,6 +107,35 @@ static inline TEB *GetTEB()
107
107
  return teb;
108
108
  }
109
109
 
110
+ #if defined(_WIN64)
111
+ #define ADJUST_TEB(Teb, Low, High) \
112
+ K_DEFER_C(base = (Teb)->StackBase, \
113
+ limit = (Teb)->StackLimit, \
114
+ dealloc = (Teb)->DeallocationStack) { \
115
+ (Teb)->StackBase = base; \
116
+ (Teb)->StackLimit = limit; \
117
+ (Teb)->DeallocationStack = dealloc; \
118
+ }; \
119
+ (Teb)->StackBase = (High); \
120
+ (Teb)->StackLimit = (Low); \
121
+ (Teb)->DeallocationStack = (Low);
122
+ #else
123
+ #define ADJUST_TEB(Teb, Low, High) \
124
+ K_DEFER_C(base = (Teb)->StackBase, \
125
+ limit = (Teb)->StackLimit, \
126
+ dealloc = (Teb)->DeallocationStack, \
127
+ seh = (Teb)->ExceptionList) { \
128
+ (Teb)->StackBase = base; \
129
+ (Teb)->StackLimit = limit; \
130
+ (Teb)->DeallocationStack = dealloc; \
131
+ (Teb)->ExceptionList = seh; \
132
+ }; \
133
+ (Teb)->StackBase = (High); \
134
+ (Teb)->StackLimit = (Low); \
135
+ (Teb)->DeallocationStack = (Low); \
136
+ (Teb)->ExceptionList = (High) - K_SIZE(SehFrame);
137
+ #endif
138
+
110
139
  extern const HashMap<int, const char *> WindowsMachineNames;
111
140
 
112
141
  void *LoadWindowsLibrary(Napi::Env env, Span<const char> path); // Returns HANDLE
@@ -4094,6 +4094,10 @@ inline const Value CallbackInfo::operator[](size_t index) const {
4094
4094
  return index < _argc ? Value(_env, _argv[index]) : Env().Undefined();
4095
4095
  }
4096
4096
 
4097
+ inline napi_value *CallbackInfo::First() const {
4098
+ return _argv;
4099
+ }
4100
+
4097
4101
  inline Value CallbackInfo::This() const {
4098
4102
  if (_this == nullptr) {
4099
4103
  return Env().Undefined();
@@ -1977,6 +1977,7 @@ class CallbackInfo {
1977
1977
  bool IsConstructCall() const;
1978
1978
  size_t Length() const;
1979
1979
  const Value operator[](size_t index) const;
1980
+ napi_value *First() const;
1980
1981
  Value This() const;
1981
1982
  void* Data() const;
1982
1983
  void SetData(void* data);
Binary file
Binary file
Binary file
Binary file
package/doc/platforms.md DELETED
@@ -1,36 +0,0 @@
1
- # Node.js
2
-
3
- Koffi requires a recent [Node.js](https://nodejs.org/) version with [N-API](https://nodejs.org/api/n-api.html) version 8 support:
4
-
5
- - Node < 12.22.0 is not supported
6
- - _Node 12.x_: Node 12.22.0 or newer
7
- - _Node 14.x_: Node 14.17.0 or newer
8
- - _Node 15.x_: Node 15.12.0 or newer
9
- - Node 16.0.0 or later versions
10
-
11
- Use [NVM](https://github.com/nvm-sh/nvm) to install more recent Node versions on older Linux distributions.
12
-
13
- # Supported platforms
14
-
15
- The following combinations of OS and architectures __are officially supported and tested__ at the moment:
16
-
17
- ISA / OS | Windows | Linux (glibc) | Linux (musl) | macOS | FreeBSD | OpenBSD
18
- ------------------ | ----------- | ------------- | ------------ | ----------- | ----------- | --------
19
- x86 (IA32) [^1] | ✅ Yes | ✅ Yes | 🟨 Probably | ⬜️ *N/A* | ✅ Yes | ✅ Yes
20
- x86_64 (AMD64) | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes
21
- ARM32 LE [^2] | ⬜️ *N/A* | ✅ Yes | 🟨 Probably | ⬜️ *N/A* | 🟨 Probably | 🟨 Probably
22
- ARM64 (AArch64) LE | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes | 🟨 Probably
23
- RISC-V 64 [^3] | ⬜️ *N/A* | ✅ Yes | 🟨 Probably | ⬜️ *N/A* | 🟨 Probably | 🟨 Probably
24
- LoongArch64 | ⬜️ *N/A* | ✅ Yes | 🟨 Probably | ⬜️ *N/A* | 🟨 Probably | 🟨 Probably
25
-
26
- <div class="legend">✅ Yes | 🟨 Probably | ⬜️ Not applicable</div>
27
-
28
- [^1]: The following call conventions are supported for forward calls: cdecl, stdcall, MS fastcall, thiscall. Only cdecl and stdcall can be used for C to JS callbacks.
29
- [^2]: The prebuilt binary uses the hard float ABI and expects a VFP coprocessor. Build from source to use Koffi with a different ABI (softfp, soft).
30
- [^3]: The prebuilt binary uses the LP64D (double-precision float) ABI. The LP64 ABI is supported in theory if you build Koffi from source (untested), the LP64F ABI is not supported.
31
-
32
- For all fully supported platforms (green check marks), a prebuilt binary is included in the NPM package which means you can install Koffi without a C++ compiler.
33
-
34
- <style>
35
- table td:not(:first-child) { text-align: center; }
36
- </style>
@@ -1,22 +0,0 @@
1
- MIT License
2
-
3
- Copyright (C) 2025 Niels Martignène <niels.martignene@protonmail.com>
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy of
6
- this software and associated documentation files (the “Software”), to deal in
7
- the Software without restriction, including without limitation the rights to use,
8
- copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
9
- Software, and to permit persons to whom the Software is furnished to do so,
10
- subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
16
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
- OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
- OTHER DEALINGS IN THE SOFTWARE.