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/ffi.hh
CHANGED
|
@@ -9,6 +9,37 @@
|
|
|
9
9
|
|
|
10
10
|
namespace K {
|
|
11
11
|
|
|
12
|
+
// #define EXTERNAL_POINTERS
|
|
13
|
+
// #define EXTERNAL_TYPES
|
|
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
|
+
#define NAPI_OK(Call) \
|
|
38
|
+
do { \
|
|
39
|
+
napi_status status = (Call); \
|
|
40
|
+
K_ASSERT(status == napi_ok); \
|
|
41
|
+
} while (false)
|
|
42
|
+
|
|
12
43
|
static const Size DefaultSyncStackSize = Mebibytes(1);
|
|
13
44
|
static const Size DefaultSyncHeapSize = Mebibytes(2);
|
|
14
45
|
static const Size DefaultAsyncStackSize = Kibibytes(128);
|
|
@@ -47,11 +78,13 @@ enum class TypeFlag {
|
|
|
47
78
|
enum class ArrayHint {
|
|
48
79
|
Array,
|
|
49
80
|
Typed,
|
|
81
|
+
Buffer,
|
|
50
82
|
String
|
|
51
83
|
};
|
|
52
84
|
static const char *const ArrayHintNames[] = {
|
|
53
85
|
"Array",
|
|
54
86
|
"Typed",
|
|
87
|
+
"Buffer",
|
|
55
88
|
"String"
|
|
56
89
|
};
|
|
57
90
|
|
|
@@ -66,11 +99,6 @@ struct RecordMember {
|
|
|
66
99
|
struct TypeInfo {
|
|
67
100
|
const char *name;
|
|
68
101
|
|
|
69
|
-
// Make sure primitive ends up as the upper N-API tag value when we cast TypeInfo pointers to
|
|
70
|
-
// napi_type_tag pointers. Yes, I want to do this. We don't do strict aliasing here.
|
|
71
|
-
// N.B. Some node versions don't like when one of the two tag values is 0, so make sure
|
|
72
|
-
// this does not happen! It would happen if primitive is 0 and size is 0. To avoid this
|
|
73
|
-
// situation, PrimitiveKind::Void (the only type with size 0) is explictly not 0.
|
|
74
102
|
alignas(8) PrimitiveKind primitive;
|
|
75
103
|
int32_t size;
|
|
76
104
|
int16_t align;
|
|
@@ -123,7 +151,7 @@ class LibraryHandle: public Napi::ObjectWrap<LibraryHandle> {
|
|
|
123
151
|
LibraryHolder *lib = nullptr;
|
|
124
152
|
|
|
125
153
|
public:
|
|
126
|
-
static Napi::Function InitClass(
|
|
154
|
+
static Napi::Function InitClass(InstanceData *instance);
|
|
127
155
|
|
|
128
156
|
LibraryHandle(const Napi::CallbackInfo &info);
|
|
129
157
|
|
|
@@ -309,8 +337,11 @@ struct InstanceData {
|
|
|
309
337
|
const TypeInfo *str16_type;
|
|
310
338
|
const TypeInfo *str32_type;
|
|
311
339
|
|
|
340
|
+
Napi::ObjectReference object_constructor;
|
|
312
341
|
Napi::FunctionReference construct_lib;
|
|
342
|
+
#if !defined(EXTERNAL_TYPES)
|
|
313
343
|
Napi::FunctionReference construct_type;
|
|
344
|
+
#endif
|
|
314
345
|
Napi::FunctionReference construct_poll;
|
|
315
346
|
Napi::Reference<Napi::Symbol> active_symbol;
|
|
316
347
|
|
|
@@ -388,12 +419,20 @@ struct SharedData {
|
|
|
388
419
|
};
|
|
389
420
|
static_assert(MaxTrampolines <= INT16_MAX);
|
|
390
421
|
|
|
422
|
+
extern const napi_type_tag LibraryHandleMarker;
|
|
423
|
+
extern const napi_type_tag TypeObjectMarker;
|
|
424
|
+
extern const napi_type_tag DirectionMarker;
|
|
425
|
+
extern const napi_type_tag UnionValueMarker;
|
|
426
|
+
extern const napi_type_tag CastMarker;
|
|
427
|
+
|
|
391
428
|
extern SharedData shared;
|
|
392
429
|
|
|
393
|
-
// Some
|
|
430
|
+
// Some Node-API functions are loaded dynamically to work around bugs or because they are recent
|
|
394
431
|
extern napi_status (NAPI_CDECL *node_api_get_buffer_info)(napi_env env, napi_value value, void **data, size_t *length);
|
|
395
432
|
extern napi_status (NAPI_CDECL *node_api_create_property_key_utf8)(napi_env env, const char* str, size_t length, napi_value* result);
|
|
396
433
|
extern napi_status (NAPI_CDECL *node_api_post_finalizer)(node_api_basic_env env, napi_finalize finalize_cb, void* finalize_data, void* finalize_hint);
|
|
434
|
+
extern napi_status (NAPI_CDECL *node_api_create_object_with_properties)(napi_env env, napi_value prototype_or_null, const napi_value *property_names,
|
|
435
|
+
const napi_value *property_values, size_t property_count, napi_value *result);
|
|
397
436
|
extern napi_value (*translate_zero_call)(napi_env env, napi_callback_info info);
|
|
398
437
|
|
|
399
438
|
InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, Size heap_size);
|
package/src/koffi/src/parser.cc
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
#include "lib/native/base/base.hh"
|
|
5
5
|
#include "ffi.hh"
|
|
6
6
|
#include "parser.hh"
|
|
7
|
+
#include "type.hh"
|
|
8
|
+
#include "util.hh"
|
|
7
9
|
|
|
8
10
|
#include <napi.h>
|
|
9
11
|
|
|
@@ -159,7 +161,7 @@ const TypeInfo *PrototypeParser::ParseType(int *out_directions)
|
|
|
159
161
|
|
|
160
162
|
while (offset >= start) {
|
|
161
163
|
Span<const char> str = MakeSpan(tokens[start].ptr, tokens[offset].end() - tokens[start].ptr);
|
|
162
|
-
const TypeInfo *type = ResolveType(
|
|
164
|
+
const TypeInfo *type = ResolveType(instance, str);
|
|
163
165
|
|
|
164
166
|
if (type) {
|
|
165
167
|
offset++;
|
|
@@ -5,11 +5,8 @@
|
|
|
5
5
|
#error Please define PRIMITIVE() before including primitives.inc
|
|
6
6
|
#endif
|
|
7
7
|
|
|
8
|
-
// Void is explictly not first so that it is not 0, for reasons related to N-API type tags.
|
|
9
|
-
// Look at TypeInfo definition for more information!
|
|
10
|
-
|
|
11
|
-
PRIMITIVE(Bool)
|
|
12
8
|
PRIMITIVE(Void)
|
|
9
|
+
PRIMITIVE(Bool)
|
|
13
10
|
PRIMITIVE(Int8)
|
|
14
11
|
PRIMITIVE(UInt8)
|
|
15
12
|
PRIMITIVE(Int16)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 Niels Martignène <niels.martignene@protonmail.com>
|
|
3
|
+
|
|
4
|
+
function loadStatic(pkg) {
|
|
5
|
+
let native = null;
|
|
6
|
+
|
|
7
|
+
if (pkg == 'linux-arm64') {
|
|
8
|
+
try {
|
|
9
|
+
native = require('@koromix/koffi-linux-arm64');
|
|
10
|
+
} catch (err) {
|
|
11
|
+
// Go on
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (pkg == 'linux-ia32') {
|
|
16
|
+
try {
|
|
17
|
+
native = require('@koromix/koffi-linux-ia32');
|
|
18
|
+
} catch (err) {
|
|
19
|
+
// Go on
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (pkg == 'linux-x64') {
|
|
24
|
+
try {
|
|
25
|
+
native = require('@koromix/koffi-linux-x64');
|
|
26
|
+
} catch (err) {
|
|
27
|
+
// Go on
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (pkg == 'linux-riscv64') {
|
|
32
|
+
try {
|
|
33
|
+
native = require('@koromix/koffi-linux-riscv64');
|
|
34
|
+
} catch (err) {
|
|
35
|
+
// Go on
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (pkg == 'freebsd-ia32') {
|
|
40
|
+
try {
|
|
41
|
+
native = require('@koromix/koffi-freebsd-ia32');
|
|
42
|
+
} catch (err) {
|
|
43
|
+
// Go on
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (pkg == 'freebsd-x64') {
|
|
48
|
+
try {
|
|
49
|
+
native = require('@koromix/koffi-freebsd-x64');
|
|
50
|
+
} catch (err) {
|
|
51
|
+
// Go on
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (pkg == 'freebsd-arm64') {
|
|
56
|
+
try {
|
|
57
|
+
native = require('@koromix/koffi-freebsd-arm64');
|
|
58
|
+
} catch (err) {
|
|
59
|
+
// Go on
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (pkg == 'openbsd-ia32') {
|
|
64
|
+
try {
|
|
65
|
+
native = require('@koromix/koffi-openbsd-ia32');
|
|
66
|
+
} catch (err) {
|
|
67
|
+
// Go on
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (pkg == 'openbsd-x64') {
|
|
72
|
+
try {
|
|
73
|
+
native = require('@koromix/koffi-openbsd-x64');
|
|
74
|
+
} catch (err) {
|
|
75
|
+
// Go on
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (pkg == 'win32-ia32') {
|
|
80
|
+
try {
|
|
81
|
+
native = require('@koromix/koffi-win32-ia32');
|
|
82
|
+
} catch (err) {
|
|
83
|
+
// Go on
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (pkg == 'win32-x64') {
|
|
88
|
+
try {
|
|
89
|
+
native = require('@koromix/koffi-win32-x64');
|
|
90
|
+
} catch (err) {
|
|
91
|
+
// Go on
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (pkg == 'darwin-x64') {
|
|
96
|
+
try {
|
|
97
|
+
native = require('@koromix/koffi-darwin-x64');
|
|
98
|
+
} catch (err) {
|
|
99
|
+
// Go on
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (pkg == 'darwin-arm64') {
|
|
104
|
+
try {
|
|
105
|
+
native = require('@koromix/koffi-darwin-arm64');
|
|
106
|
+
} catch (err) {
|
|
107
|
+
// Go on
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (pkg == 'linux-loong64') {
|
|
112
|
+
try {
|
|
113
|
+
native = require('@koromix/koffi-linux-loong64');
|
|
114
|
+
} catch (err) {
|
|
115
|
+
// Go on
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return native;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
module.exports = { loadStatic };
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 Niels Martignène <niels.martignene@protonmail.com>
|
|
3
|
+
|
|
4
|
+
function loadStatic(pkg) {
|
|
5
|
+
let native = null;
|
|
6
|
+
|
|
7
|
+
if (pkg == 'linux-arm64') {
|
|
8
|
+
try {
|
|
9
|
+
native = require('@koromix/koffi-linux-arm64');
|
|
10
|
+
} catch (err) {
|
|
11
|
+
// Go on
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (pkg == 'linux-ia32') {
|
|
16
|
+
try {
|
|
17
|
+
native = require('@koromix/koffi-linux-ia32');
|
|
18
|
+
} catch (err) {
|
|
19
|
+
// Go on
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (pkg == 'linux-x64') {
|
|
24
|
+
try {
|
|
25
|
+
native = require('@koromix/koffi-linux-x64');
|
|
26
|
+
} catch (err) {
|
|
27
|
+
// Go on
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (pkg == 'linux-riscv64') {
|
|
32
|
+
try {
|
|
33
|
+
native = require('@koromix/koffi-linux-riscv64');
|
|
34
|
+
} catch (err) {
|
|
35
|
+
// Go on
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (pkg == 'freebsd-ia32') {
|
|
40
|
+
try {
|
|
41
|
+
native = require('@koromix/koffi-freebsd-ia32');
|
|
42
|
+
} catch (err) {
|
|
43
|
+
// Go on
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (pkg == 'freebsd-x64') {
|
|
48
|
+
try {
|
|
49
|
+
native = require('@koromix/koffi-freebsd-x64');
|
|
50
|
+
} catch (err) {
|
|
51
|
+
// Go on
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (pkg == 'freebsd-arm64') {
|
|
56
|
+
try {
|
|
57
|
+
native = require('@koromix/koffi-freebsd-arm64');
|
|
58
|
+
} catch (err) {
|
|
59
|
+
// Go on
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (pkg == 'openbsd-ia32') {
|
|
64
|
+
try {
|
|
65
|
+
native = require('@koromix/koffi-openbsd-ia32');
|
|
66
|
+
} catch (err) {
|
|
67
|
+
// Go on
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (pkg == 'openbsd-x64') {
|
|
72
|
+
try {
|
|
73
|
+
native = require('@koromix/koffi-openbsd-x64');
|
|
74
|
+
} catch (err) {
|
|
75
|
+
// Go on
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (pkg == 'win32-ia32') {
|
|
80
|
+
try {
|
|
81
|
+
native = require('@koromix/koffi-win32-ia32');
|
|
82
|
+
} catch (err) {
|
|
83
|
+
// Go on
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (pkg == 'win32-x64') {
|
|
88
|
+
try {
|
|
89
|
+
native = require('@koromix/koffi-win32-x64');
|
|
90
|
+
} catch (err) {
|
|
91
|
+
// Go on
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (pkg == 'darwin-x64') {
|
|
96
|
+
try {
|
|
97
|
+
native = require('@koromix/koffi-darwin-x64');
|
|
98
|
+
} catch (err) {
|
|
99
|
+
// Go on
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (pkg == 'darwin-arm64') {
|
|
104
|
+
try {
|
|
105
|
+
native = require('@koromix/koffi-darwin-arm64');
|
|
106
|
+
} catch (err) {
|
|
107
|
+
// Go on
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (pkg == 'linux-loong64') {
|
|
112
|
+
try {
|
|
113
|
+
native = require('@koromix/koffi-linux-loong64');
|
|
114
|
+
} catch (err) {
|
|
115
|
+
// Go on
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return native;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export { loadStatic }
|