koffi 3.0.0 → 3.0.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.
- package/CHANGELOG.md +20 -1
- package/README.md +5 -4
- package/cnoke.cjs +10 -10
- package/doc/benchmarks.md +24 -47
- package/doc/callbacks.md +4 -13
- package/doc/contribute.md +4 -4
- package/doc/index.md +3 -2
- package/doc/migration.md +100 -0
- package/doc/start.md +7 -5
- package/index.d.ts +53 -5
- package/index.js +2 -1
- package/indirect.js +2 -1
- package/package.json +20 -18
- package/src/koffi/CMakeLists.txt +20 -12
- package/src/koffi/index.cjs +92 -129
- package/src/koffi/index.js +128 -113
- package/src/koffi/indirect.cjs +91 -128
- package/src/koffi/indirect.js +129 -40
- package/src/koffi/src/abi/arm64.cc +30 -29
- package/src/koffi/src/abi/riscv64.cc +30 -29
- package/src/koffi/src/abi/x64sysv.cc +26 -25
- package/src/koffi/src/abi/x64win.cc +64 -63
- package/src/koffi/src/abi/x86.cc +67 -65
- package/src/koffi/src/call.cc +210 -99
- package/src/koffi/src/call.hh +2 -1
- package/src/koffi/src/ffi.cc +403 -237
- package/src/koffi/src/ffi.hh +46 -7
- package/src/koffi/src/parser.cc +3 -1
- package/src/koffi/src/primitives.inc +1 -4
- package/src/koffi/src/static.cjs +122 -0
- package/src/koffi/src/static.js +122 -0
- package/src/koffi/src/type.cc +715 -0
- package/src/koffi/src/type.hh +71 -0
- package/src/koffi/src/util.cc +189 -1120
- package/src/koffi/src/util.hh +85 -125
- package/src/koffi/src/uv.cc +16 -10
- package/src/koffi/src/uv.hh +2 -1
package/src/koffi/src/util.hh
CHANGED
|
@@ -10,51 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
namespace K {
|
|
12
12
|
|
|
13
|
-
// #define EXTERNAL_POINTERS
|
|
14
|
-
|
|
15
|
-
#if defined(_MSC_VER)
|
|
16
|
-
#define FORCE_INLINE __forceinline
|
|
17
|
-
#else
|
|
18
|
-
#define FORCE_INLINE __attribute__((always_inline)) inline
|
|
19
|
-
#endif
|
|
20
|
-
#if defined(UNITY_BUILD)
|
|
21
|
-
#define INLINE_UNITY FORCE_INLINE
|
|
22
|
-
#else
|
|
23
|
-
#define INLINE_UNITY
|
|
24
|
-
#endif
|
|
25
|
-
|
|
26
|
-
#if defined(__GNUC__) || defined(__clang__)
|
|
27
|
-
#if __has_attribute(musttail) && __has_attribute(preserve_none)
|
|
28
|
-
#define MUST_TAIL __attribute__((musttail))
|
|
29
|
-
#define PRESERVE_NONE __attribute__((preserve_none))
|
|
30
|
-
#elif __has_attribute(musttail) && !defined(__clang__)
|
|
31
|
-
// GCC regalloc seems better, so the generated code is not too bad even without preserve_none
|
|
32
|
-
#define MUST_TAIL __attribute__((musttail))
|
|
33
|
-
#define PRESERVE_NONE
|
|
34
|
-
#endif
|
|
35
|
-
#endif
|
|
36
|
-
|
|
37
|
-
extern const napi_type_tag LibraryHandleMarker;
|
|
38
|
-
extern const napi_type_tag TypeObjectMarker;
|
|
39
|
-
extern const napi_type_tag DirectionMarker;
|
|
40
|
-
extern const napi_type_tag UnionValueMarker;
|
|
41
|
-
extern const napi_type_tag CastMarker;
|
|
42
|
-
|
|
43
|
-
class TypeObject: public Napi::ObjectWrap<TypeObject> {
|
|
44
|
-
const TypeInfo *type;
|
|
45
|
-
|
|
46
|
-
mutable Napi::Object members;
|
|
47
|
-
|
|
48
|
-
public:
|
|
49
|
-
static Napi::Function InitClass(Napi::Env env);
|
|
50
|
-
|
|
51
|
-
TypeObject(const Napi::CallbackInfo &info);
|
|
52
|
-
|
|
53
|
-
void Finalize(Napi::BasicEnv env) override;
|
|
54
|
-
|
|
55
|
-
const TypeInfo *GetType() { return type; }
|
|
56
|
-
};
|
|
57
|
-
|
|
58
13
|
class UnionValue: public Napi::ObjectWrap<UnionValue> {
|
|
59
14
|
InstanceData *instance;
|
|
60
15
|
const TypeInfo *type;
|
|
@@ -64,7 +19,7 @@ class UnionValue: public Napi::ObjectWrap<UnionValue> {
|
|
|
64
19
|
HeapArray<uint8_t> raw;
|
|
65
20
|
|
|
66
21
|
public:
|
|
67
|
-
static Napi::Function InitClass(
|
|
22
|
+
static Napi::Function InitClass(InstanceData *instance, const TypeInfo *type);
|
|
68
23
|
|
|
69
24
|
UnionValue(const Napi::CallbackInfo &info);
|
|
70
25
|
|
|
@@ -91,58 +46,14 @@ void ThrowError(Napi::Env env, const char *msg, Args... args)
|
|
|
91
46
|
err.ThrowAsJavaScriptException();
|
|
92
47
|
}
|
|
93
48
|
|
|
94
|
-
static FORCE_INLINE bool IsInteger(const TypeInfo *type)
|
|
95
|
-
{
|
|
96
|
-
bool integer = ((int)type->primitive >= (int)PrimitiveKind::Int8 &&
|
|
97
|
-
(int)type->primitive <= (int)PrimitiveKind::UInt64);
|
|
98
|
-
return integer;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
static FORCE_INLINE bool IsFloat(const TypeInfo *type)
|
|
102
|
-
{
|
|
103
|
-
bool fp = (type->primitive == PrimitiveKind::Float32 ||
|
|
104
|
-
type->primitive == PrimitiveKind::Float64);
|
|
105
|
-
return fp;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
static FORCE_INLINE bool IsRegularSize(Size size, Size max)
|
|
109
|
-
{
|
|
110
|
-
bool regular = (size <= max && !(size & (size - 1)));
|
|
111
|
-
return regular;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
int ResolveDirections(Span<const char> str);
|
|
115
|
-
const TypeInfo *ResolveType(Napi::Value value, int *out_directions = nullptr);
|
|
116
|
-
const TypeInfo *ResolveType(Napi::Env env, Span<const char> str);
|
|
117
|
-
|
|
118
|
-
TypeInfo *MakePointerType(InstanceData *instance, const TypeInfo *ref, int count = 1);
|
|
119
|
-
TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len);
|
|
120
|
-
TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len, ArrayHint hint);
|
|
121
|
-
|
|
122
|
-
Napi::Object WrapType(Napi::Env env, const TypeInfo *type, bool freeze = true);
|
|
123
|
-
|
|
124
|
-
const TypeInfo *ReshapeType(InstanceData *instance, const TypeInfo *type, int32_t stride, uint16_t flags);
|
|
125
|
-
|
|
126
|
-
bool CanPassType(const TypeInfo *type, int directions);
|
|
127
|
-
bool CanReturnType(const TypeInfo *type);
|
|
128
|
-
bool CanStoreType(const TypeInfo *type);
|
|
129
|
-
|
|
130
49
|
static FORCE_INLINE napi_valuetype GetKindOf(napi_env env, napi_value value)
|
|
131
50
|
{
|
|
132
51
|
napi_valuetype kind = napi_undefined;
|
|
133
|
-
napi_typeof(env, value, &kind);
|
|
52
|
+
NAPI_OK(napi_typeof(env, value, &kind));
|
|
134
53
|
|
|
135
54
|
return kind;
|
|
136
55
|
}
|
|
137
56
|
|
|
138
|
-
static FORCE_INLINE napi_valuetype GetKindOf(Napi::Value value)
|
|
139
|
-
{
|
|
140
|
-
return GetKindOf(value.Env(), value);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Can be slow, only use for error messages
|
|
144
|
-
const char *GetValueType(const InstanceData *instance, napi_value value);
|
|
145
|
-
|
|
146
57
|
void SetValueTag(napi_env env, napi_value value, const void *marker);
|
|
147
58
|
bool CheckValueTag(napi_env env, napi_value value, const void *marker);
|
|
148
59
|
|
|
@@ -201,9 +112,7 @@ static FORCE_INLINE bool IsBuffer(napi_env env, napi_value value)
|
|
|
201
112
|
static FORCE_INLINE napi_value GetReferenceValue(napi_env env, napi_ref ref)
|
|
202
113
|
{
|
|
203
114
|
napi_value value;
|
|
204
|
-
|
|
205
|
-
napi_status status = napi_get_reference_value(env, ref, &value);
|
|
206
|
-
K_ASSERT(status == napi_ok);
|
|
115
|
+
NAPI_OK(napi_get_reference_value(env, ref, &value));
|
|
207
116
|
|
|
208
117
|
return value;
|
|
209
118
|
}
|
|
@@ -211,9 +120,7 @@ static FORCE_INLINE napi_value GetReferenceValue(napi_env env, napi_ref ref)
|
|
|
211
120
|
static FORCE_INLINE uint32_t GetArrayLength(napi_env env, napi_value array)
|
|
212
121
|
{
|
|
213
122
|
uint32_t length = 0;
|
|
214
|
-
|
|
215
|
-
napi_status status = napi_get_array_length(env, array, &length);
|
|
216
|
-
K_ASSERT(status == napi_ok);
|
|
123
|
+
NAPI_OK(napi_get_array_length(env, array, &length));
|
|
217
124
|
|
|
218
125
|
return length;
|
|
219
126
|
}
|
|
@@ -305,6 +212,62 @@ static FORCE_INLINE bool TryPointer(napi_env env, napi_value value, void **out_p
|
|
|
305
212
|
return false;
|
|
306
213
|
}
|
|
307
214
|
|
|
215
|
+
static FORCE_INLINE bool TryPointer(napi_env env, napi_value value, void **out_ptr, Size *out_len)
|
|
216
|
+
{
|
|
217
|
+
// Fast path for BigInt
|
|
218
|
+
{
|
|
219
|
+
uint64_t u64;
|
|
220
|
+
bool lossless;
|
|
221
|
+
napi_status status = napi_get_value_bigint_uint64(env, value, &u64, &lossless);
|
|
222
|
+
|
|
223
|
+
if (status == napi_ok) {
|
|
224
|
+
*out_ptr = (void *)(uintptr_t)u64;
|
|
225
|
+
*out_len = -1;
|
|
226
|
+
|
|
227
|
+
return true;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (size_t len = 0; node_api_get_buffer_info(env, value, out_ptr, &len) == napi_ok) {
|
|
232
|
+
*out_len = (Size)len;
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
napi_valuetype kind = GetKindOf(env, value);
|
|
237
|
+
|
|
238
|
+
if (IsNullOrUndefined(kind)) {
|
|
239
|
+
*out_ptr = nullptr;
|
|
240
|
+
*out_len = -1;
|
|
241
|
+
|
|
242
|
+
return true;
|
|
243
|
+
} else if (kind == napi_number) {
|
|
244
|
+
int64_t i;
|
|
245
|
+
napi_status status = napi_get_value_int64(env, value, &i);
|
|
246
|
+
K_ASSERT(status == napi_ok);
|
|
247
|
+
|
|
248
|
+
*out_ptr = (void *)(uintptr_t)i;
|
|
249
|
+
*out_len = -1;
|
|
250
|
+
|
|
251
|
+
return true;
|
|
252
|
+
#if defined(EXTERNAL_POINTERS)
|
|
253
|
+
} else if (kind == napi_external) {
|
|
254
|
+
Napi::External<void> external = Napi::External<void>(env, value);
|
|
255
|
+
|
|
256
|
+
*out_ptr = (void *)external.Data();
|
|
257
|
+
*out_len = -1;
|
|
258
|
+
|
|
259
|
+
return true;
|
|
260
|
+
#endif
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (size_t len = 0; napi_get_arraybuffer_info(env, value, out_ptr, &len) == napi_ok) {
|
|
264
|
+
*out_len = (Size)len;
|
|
265
|
+
return true;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
|
|
308
271
|
static FORCE_INLINE bool TryPointer(napi_env env, napi_value value, void **out_ptr, napi_valuetype *out_kind)
|
|
309
272
|
{
|
|
310
273
|
// Fast path for BigInt
|
|
@@ -403,19 +366,15 @@ Napi::String MakeStringFromUTF32(Napi::Env env, const char32_t *ptr, Size len);
|
|
|
403
366
|
static inline Napi::String MakeStringFromUTF32(Napi::Env env, const char32_t *ptr)
|
|
404
367
|
{ return MakeStringFromUTF32(env, ptr, NullTerminatedLength(ptr)); }
|
|
405
368
|
|
|
406
|
-
|
|
407
|
-
void DecodeObject(
|
|
369
|
+
napi_value DecodeObject(InstanceData *instance, const uint8_t *origin, const TypeInfo *type);
|
|
370
|
+
void DecodeObject(InstanceData *instance, napi_value obj, const uint8_t *origin, const TypeInfo *type);
|
|
408
371
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
void DecodeElements(
|
|
372
|
+
napi_value DecodeArray(InstanceData *instance, const uint8_t *origin, const TypeInfo *type);
|
|
373
|
+
napi_value DecodeArray(InstanceData *instance, const uint8_t *origin, const TypeInfo *type, uint32_t len);
|
|
374
|
+
void DecodeElements(InstanceData *instance, napi_value array, const uint8_t *origin, const TypeInfo *type, uint32_t len);
|
|
412
375
|
INLINE_UNITY void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *type);
|
|
413
376
|
|
|
414
|
-
|
|
415
|
-
Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, const Size *len = nullptr);
|
|
416
|
-
|
|
417
|
-
bool Encode(Napi::Value ref, Size offset, Napi::Value value, const TypeInfo *type, const Size *len = nullptr);
|
|
418
|
-
bool Encode(Napi::Env env, uint8_t *ptr, Napi::Value value, const TypeInfo *type, const Size *len = nullptr);
|
|
377
|
+
napi_value Decode(InstanceData *instance, const uint8_t *ptr, const TypeInfo *type);
|
|
419
378
|
|
|
420
379
|
static FORCE_INLINE napi_value NewInt(Napi::Env env, char i) { napi_value value; napi_create_int32(env, (int32_t)i, &value); return value; }
|
|
421
380
|
static FORCE_INLINE napi_value NewInt(Napi::Env env, signed char i) { napi_value value; napi_create_int32(env, (int32_t)i, &value); return value; }
|
|
@@ -434,22 +393,24 @@ static FORCE_INLINE napi_value NewInt(Napi::Env env, T i)
|
|
|
434
393
|
{
|
|
435
394
|
static_assert(sizeof(T) == 8);
|
|
436
395
|
|
|
396
|
+
napi_value value;
|
|
397
|
+
|
|
437
398
|
if constexpr (std::is_signed_v<T>) {
|
|
438
399
|
if (i <= 9007199254740992ll && i >= -9007199254740992ll) {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
return Napi::Value(env, value);
|
|
400
|
+
NAPI_OK(napi_create_int64(env, (int64_t)i, &value));
|
|
401
|
+
return value;
|
|
442
402
|
}
|
|
443
403
|
|
|
444
|
-
|
|
404
|
+
NAPI_OK(napi_create_bigint_int64(env, (int64_t)i, &value));
|
|
405
|
+
return value;
|
|
445
406
|
} else {
|
|
446
407
|
if (i <= 9007199254740992ull) {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
return Napi::Value(env, value);
|
|
408
|
+
NAPI_OK(napi_create_int64(env, (int64_t)i, &value));
|
|
409
|
+
return value;
|
|
450
410
|
}
|
|
451
411
|
|
|
452
|
-
|
|
412
|
+
NAPI_OK(napi_create_bigint_uint64(env, (uint64_t)i, &value));
|
|
413
|
+
return value;
|
|
453
414
|
}
|
|
454
415
|
}
|
|
455
416
|
|
|
@@ -466,22 +427,21 @@ static FORCE_INLINE Napi::Array GetOwnPropertyNames(napi_env env, napi_value obj
|
|
|
466
427
|
return Napi::Array(env, result);
|
|
467
428
|
}
|
|
468
429
|
|
|
469
|
-
|
|
470
|
-
|
|
430
|
+
napi_value DescribeFunction(Napi::Env env, const FunctionInfo *func);
|
|
431
|
+
napi_value WrapFunction(Napi::Env env, const FunctionInfo *func);
|
|
471
432
|
|
|
472
|
-
static FORCE_INLINE
|
|
433
|
+
static FORCE_INLINE napi_value WrapPointer(Napi::Env env, const TypeInfo *ref, void *ptr)
|
|
473
434
|
{
|
|
435
|
+
napi_value value;
|
|
436
|
+
|
|
474
437
|
#if defined(EXTERNAL_POINTERS)
|
|
475
|
-
|
|
476
|
-
return external;
|
|
438
|
+
NAPI_OK(napi_create_external(env, ptr, nullptr, nullptr, &value));
|
|
477
439
|
#else
|
|
478
|
-
|
|
479
|
-
return big;
|
|
440
|
+
NAPI_OK(napi_create_bigint_uint64(env, (uint64_t)(uintptr_t)ptr, &value));
|
|
480
441
|
#endif
|
|
481
|
-
}
|
|
482
442
|
|
|
483
|
-
|
|
484
|
-
|
|
443
|
+
return value;
|
|
444
|
+
}
|
|
485
445
|
|
|
486
446
|
bool DetectCallConvention(Span<const char> name, CallConvention *out_convention);
|
|
487
447
|
|
package/src/koffi/src/uv.cc
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
|
|
3
|
-
#include "
|
|
3
|
+
#include "lib/native/base/base.hh"
|
|
4
|
+
#include "type.hh"
|
|
4
5
|
#include "util.hh"
|
|
6
|
+
#include "uv.hh"
|
|
7
|
+
|
|
8
|
+
#include <napi.h>
|
|
5
9
|
|
|
6
10
|
namespace K {
|
|
7
11
|
|
|
8
|
-
Napi::Function PollHandle::InitClass(
|
|
12
|
+
Napi::Function PollHandle::InitClass(InstanceData *instance)
|
|
9
13
|
{
|
|
14
|
+
Napi::Env env = instance->env;
|
|
15
|
+
|
|
10
16
|
// node-addon-api wants std::vector
|
|
11
17
|
std::vector<Napi::ClassPropertyDescriptor<PollHandle>> properties = {
|
|
12
|
-
InstanceMethod("start", &PollHandle::Start),
|
|
13
|
-
InstanceMethod("stop", &PollHandle::Stop),
|
|
14
|
-
InstanceMethod("close", &PollHandle::Close),
|
|
15
|
-
InstanceMethod("unref", &PollHandle::Unref),
|
|
16
|
-
InstanceMethod("ref", &PollHandle::Ref)
|
|
18
|
+
InstanceMethod("start", &PollHandle::Start, napi_default, instance),
|
|
19
|
+
InstanceMethod("stop", &PollHandle::Stop, napi_default, instance),
|
|
20
|
+
InstanceMethod("close", &PollHandle::Close, napi_default, instance),
|
|
21
|
+
InstanceMethod("unref", &PollHandle::Unref, napi_default, instance),
|
|
22
|
+
InstanceMethod("ref", &PollHandle::Ref, napi_default, instance)
|
|
17
23
|
};
|
|
18
24
|
|
|
19
25
|
if (Napi::Value dispose = env.RunScript("Symbol.dispose"); !IsNullOrUndefined(env, dispose)) {
|
|
@@ -21,7 +27,7 @@ Napi::Function PollHandle::InitClass(Napi::Env env)
|
|
|
21
27
|
properties.push_back(prop);
|
|
22
28
|
}
|
|
23
29
|
|
|
24
|
-
Napi::Function constructor = DefineClass(env, "PollHandle", properties);
|
|
30
|
+
Napi::Function constructor = DefineClass(env, "PollHandle", properties, instance);
|
|
25
31
|
return constructor;
|
|
26
32
|
}
|
|
27
33
|
|
|
@@ -62,7 +68,7 @@ PollHandle::PollHandle(const Napi::CallbackInfo &info)
|
|
|
62
68
|
|
|
63
69
|
void PollHandle::Start(const Napi::CallbackInfo &info)
|
|
64
70
|
{
|
|
65
|
-
InstanceData *instance =
|
|
71
|
+
InstanceData *instance = (InstanceData *)info.Data();
|
|
66
72
|
|
|
67
73
|
bool has_opts = (info.Length() >= 2 && info[0].IsObject());
|
|
68
74
|
|
|
@@ -165,7 +171,7 @@ void PollHandle::OnPoll(uv_poll_t *h, int status, int events)
|
|
|
165
171
|
Napi::Value Poll(const Napi::CallbackInfo &info)
|
|
166
172
|
{
|
|
167
173
|
Napi::Env env = info.Env();
|
|
168
|
-
InstanceData *instance =
|
|
174
|
+
InstanceData *instance = (InstanceData *)info.Data();
|
|
169
175
|
|
|
170
176
|
bool has_opts = (info.Length() >= 3 && info[1].IsObject());
|
|
171
177
|
|
package/src/koffi/src/uv.hh
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
#pragma once
|
|
4
4
|
|
|
5
5
|
#include "lib/native/base/base.hh"
|
|
6
|
+
#include "ffi.hh"
|
|
6
7
|
|
|
7
8
|
#include <napi.h>
|
|
8
9
|
|
|
@@ -88,7 +89,7 @@ class PollHandle: public Napi::ObjectWrap<PollHandle> {
|
|
|
88
89
|
Napi::FunctionReference callback;
|
|
89
90
|
|
|
90
91
|
public:
|
|
91
|
-
static Napi::Function InitClass(
|
|
92
|
+
static Napi::Function InitClass(InstanceData *instance);
|
|
92
93
|
|
|
93
94
|
PollHandle(const Napi::CallbackInfo &info);
|
|
94
95
|
|