koffi 3.0.0-alpha.11 → 3.0.0-alpha.12
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/build/koffi/darwin_arm64/koffi.node +0 -0
- package/build/koffi/darwin_x64/koffi.node +0 -0
- package/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/build/koffi/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm64/koffi.node +0 -0
- package/build/koffi/linux_ia32/koffi.node +0 -0
- package/build/koffi/linux_loong64/koffi.node +0 -0
- package/build/koffi/linux_riscv64d/koffi.node +0 -0
- package/build/koffi/linux_x64/koffi.node +0 -0
- package/build/koffi/musl_arm64/koffi.node +0 -0
- package/build/koffi/musl_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/koffi/openbsd_x64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.exp +0 -0
- package/build/koffi/win32_ia32/koffi.lib +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.exp +0 -0
- package/build/koffi/win32_x64/koffi.lib +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/index.d.ts +36 -5
- package/lib/native/base/base.cc +3 -0
- package/package.json +1 -1
- package/src/koffi/index.cjs +1 -1
- package/src/koffi/index.js +1 -1
- package/src/koffi/indirect.cjs +1 -1
- package/src/koffi/indirect.js +1 -1
- package/src/koffi/src/abi/arm64.cc +4 -4
- package/src/koffi/src/abi/riscv64.cc +11 -8
- package/src/koffi/src/abi/x64sysv.cc +27 -20
- package/src/koffi/src/abi/x64win.cc +10 -7
- package/src/koffi/src/abi/x86.cc +12 -6
- package/src/koffi/src/call.cc +67 -20
- package/src/koffi/src/call.hh +1 -0
- package/src/koffi/src/ffi.cc +45 -15
- package/src/koffi/src/ffi.hh +2 -1
- package/src/koffi/src/util.cc +9 -0
- package/src/koffi/src/util.hh +12 -29
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/index.d.ts
CHANGED
|
@@ -121,18 +121,49 @@ export function register(callback: Function, type: TypeSpec): bigint;
|
|
|
121
121
|
export function unregister(callback: bigint): void;
|
|
122
122
|
|
|
123
123
|
export function as(value: any, type: TypeSpec): IKoffiPointerCast;
|
|
124
|
-
export function decode(value: any, type: TypeSpec): any;
|
|
125
|
-
export function decode(value: any, type: TypeSpec, len: number): any;
|
|
126
|
-
export function decode(value: any, offset: number, type: TypeSpec): any;
|
|
127
|
-
export function decode(value: any, offset: number, type: TypeSpec, len: number): any;
|
|
128
124
|
export function address(value: any): bigint;
|
|
129
125
|
export function call(value: any, type: TypeSpec, ...args: any[]): any;
|
|
126
|
+
export function view(ref: any, len: number): ArrayBuffer;
|
|
127
|
+
|
|
128
|
+
export const decode: {
|
|
129
|
+
(value: any, type: TypeSpec): any;
|
|
130
|
+
(value: any, type: TypeSpec, len: number): any;
|
|
131
|
+
(value: any, offset: number, type: TypeSpec): any;
|
|
132
|
+
(value: any, offset: number, type: TypeSpec, len: number): any;
|
|
133
|
+
|
|
134
|
+
char(ptr: any): number;
|
|
135
|
+
short(ptr: any): number;
|
|
136
|
+
int(ptr: any): number;
|
|
137
|
+
long(ptr: any): number | bigint;
|
|
138
|
+
longlong(ptr: any): number | bigint;
|
|
139
|
+
uchar(ptr: any): number;
|
|
140
|
+
ushort(ptr: any): number;
|
|
141
|
+
uint(ptr: any): number;
|
|
142
|
+
ulong(ptr: any): number | bigint;
|
|
143
|
+
ulonglong(ptr: any): number | bigint;
|
|
144
|
+
|
|
145
|
+
int8(ptr: any): number;
|
|
146
|
+
int16(ptr: any): number;
|
|
147
|
+
int32(ptr: any): number;
|
|
148
|
+
int64(ptr: any): number | bigint;
|
|
149
|
+
uint8(ptr: any): number;
|
|
150
|
+
uint16(ptr: any): number;
|
|
151
|
+
uint32(ptr: any): number;
|
|
152
|
+
uint64(ptr: any): number | bigint;
|
|
153
|
+
|
|
154
|
+
float(ptr: any): number;
|
|
155
|
+
double(ptr: any): number;
|
|
156
|
+
|
|
157
|
+
string(ptr: any, length?: number | bigint | null): string;
|
|
158
|
+
string16(ptr: any, length?: number | bigint | null): string;
|
|
159
|
+
string32(ptr: any, length?: number | bigint | null): string;
|
|
160
|
+
};
|
|
161
|
+
|
|
130
162
|
export function encode(ref: any, type: TypeSpec, value: any): void;
|
|
131
163
|
export function encode(ref: any, type: TypeSpec, value: any, len: number): void;
|
|
132
164
|
export function encode(ref: any, offset: number, type: TypeSpec): void;
|
|
133
165
|
export function encode(ref: any, offset: number, type: TypeSpec, value: any): void;
|
|
134
166
|
export function encode(ref: any, offset: number, type: TypeSpec, value: any, len: number): void;
|
|
135
|
-
export function view(ref: any, len: number): ArrayBuffer;
|
|
136
167
|
|
|
137
168
|
export function type(type: TypeSpec): TypeObject;
|
|
138
169
|
export function sizeof(type: TypeSpec): number;
|
package/lib/native/base/base.cc
CHANGED
|
@@ -2082,6 +2082,9 @@ bool GetDebugFlag(const char *name)
|
|
|
2082
2082
|
if (!ParseBool(debug, &ret, K_DEFAULT_PARSE_FLAGS & ~(int)ParseFlag::Log)) {
|
|
2083
2083
|
LogError("Environment variable '%1' is not a boolean", name);
|
|
2084
2084
|
}
|
|
2085
|
+
if (ret) {
|
|
2086
|
+
LogWarning("Debug flag '%1' is in effect", name);
|
|
2087
|
+
}
|
|
2085
2088
|
return ret;
|
|
2086
2089
|
} else {
|
|
2087
2090
|
return false;
|
package/package.json
CHANGED
package/src/koffi/index.cjs
CHANGED
|
@@ -131,7 +131,7 @@ var init_abi = __esm({
|
|
|
131
131
|
var package_default;
|
|
132
132
|
var init_package = __esm({
|
|
133
133
|
"package.json"() {
|
|
134
|
-
package_default = { name: "koffi", version: "3.0.0-alpha.
|
|
134
|
+
package_default = { name: "koffi", version: "3.0.0-alpha.12", cnoke: { api: "../../vendor/node-api-headers", output: "../../bin/Koffi/{{ toolchain }}", node: 16, napi: 8 } };
|
|
135
135
|
}
|
|
136
136
|
});
|
|
137
137
|
|
package/src/koffi/index.js
CHANGED
|
@@ -94,7 +94,7 @@ function decodeElfHeader(buf) {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
// package.json
|
|
97
|
-
var package_default = { name: "koffi", version: "3.0.0-alpha.
|
|
97
|
+
var package_default = { name: "koffi", version: "3.0.0-alpha.12", cnoke: { api: "../../vendor/node-api-headers", output: "../../bin/Koffi/{{ toolchain }}", node: 16, napi: 8 } };
|
|
98
98
|
|
|
99
99
|
// src/init.js
|
|
100
100
|
var requireNative = createRequire(import.meta.url);
|
package/src/koffi/indirect.cjs
CHANGED
|
@@ -131,7 +131,7 @@ var init_abi = __esm({
|
|
|
131
131
|
var package_default;
|
|
132
132
|
var init_package = __esm({
|
|
133
133
|
"package.json"() {
|
|
134
|
-
package_default = { name: "koffi", version: "3.0.0-alpha.
|
|
134
|
+
package_default = { name: "koffi", version: "3.0.0-alpha.12", cnoke: { api: "../../vendor/node-api-headers", output: "../../bin/Koffi/{{ toolchain }}", node: 16, napi: 8 } };
|
|
135
135
|
}
|
|
136
136
|
});
|
|
137
137
|
|
package/src/koffi/indirect.js
CHANGED
|
@@ -94,7 +94,7 @@ function decodeElfHeader(buf) {
|
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
// package.json
|
|
97
|
-
var package_default = { name: "koffi", version: "3.0.0-alpha.
|
|
97
|
+
var package_default = { name: "koffi", version: "3.0.0-alpha.12", cnoke: { api: "../../vendor/node-api-headers", output: "../../bin/Koffi/{{ toolchain }}", node: 16, napi: 8 } };
|
|
98
98
|
|
|
99
99
|
// src/init.js
|
|
100
100
|
var requireNative = createRequire(import.meta.url);
|
|
@@ -948,8 +948,8 @@ namespace {
|
|
|
948
948
|
OP(CallStack) {
|
|
949
949
|
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
950
950
|
*(uint8_t **)(base + 8 * 8) = ptr; // x8
|
|
951
|
-
|
|
952
|
-
*(uint8_t **)base = ptr;
|
|
951
|
+
WRAP(ForwardCallGG(call->native, base, &call->saved_sp));
|
|
952
|
+
*(uint8_t **)base = ptr;
|
|
953
953
|
return nullptr;
|
|
954
954
|
}
|
|
955
955
|
OP(CallGGX) {
|
|
@@ -962,8 +962,8 @@ namespace {
|
|
|
962
962
|
OP(CallStackX) {
|
|
963
963
|
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
964
964
|
*(uint8_t **)(base + 8 * 8) = ptr; // x8
|
|
965
|
-
|
|
966
|
-
*(uint8_t **)base = ptr;
|
|
965
|
+
WRAP(ForwardCallGGX(call->native, base, &call->saved_sp));
|
|
966
|
+
*(uint8_t **)base = ptr;
|
|
967
967
|
return nullptr;
|
|
968
968
|
}
|
|
969
969
|
|
|
@@ -82,7 +82,8 @@ enum class AbiOpcode {
|
|
|
82
82
|
CallStackX,
|
|
83
83
|
#define PRIMITIVE(Name) Return ## Name,
|
|
84
84
|
#include "../primitives.inc"
|
|
85
|
-
|
|
85
|
+
ReturnAggregateReg,
|
|
86
|
+
ReturnAggregateStack
|
|
86
87
|
};
|
|
87
88
|
|
|
88
89
|
enum class AbiMethod {
|
|
@@ -411,7 +412,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
411
412
|
|
|
412
413
|
func->sync.Append({ .op = Code2Op(run), .a = (int32_t)func->ret.type->size, .type = func->ret.type });
|
|
413
414
|
func->async.Append({ .op = Code2Op(call), .a = (int32_t)func->ret.type->size });
|
|
414
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
415
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateStack), .type = func->ret.type });
|
|
415
416
|
} break;
|
|
416
417
|
|
|
417
418
|
case AbiMethod::Gpr:
|
|
@@ -422,7 +423,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
422
423
|
|
|
423
424
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
424
425
|
func->async.Append({ .op = Code2Op(call) });
|
|
425
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
426
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
426
427
|
} break;
|
|
427
428
|
case AbiMethod::Vec:
|
|
428
429
|
case AbiMethod::VecVec: {
|
|
@@ -431,7 +432,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
431
432
|
|
|
432
433
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
433
434
|
func->async.Append({ .op = Code2Op(call) });
|
|
434
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
435
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
435
436
|
} break;
|
|
436
437
|
case AbiMethod::GprVec: {
|
|
437
438
|
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateGDX : AbiOpcode::RunAggregateGD;
|
|
@@ -439,7 +440,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
439
440
|
|
|
440
441
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
441
442
|
func->async.Append({ .op = Code2Op(call) });
|
|
442
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
443
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
443
444
|
} break;
|
|
444
445
|
case AbiMethod::VecGpr: {
|
|
445
446
|
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateDGX : AbiOpcode::RunAggregateDG;
|
|
@@ -447,7 +448,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
447
448
|
|
|
448
449
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
449
450
|
func->async.Append({ .op = Code2Op(call) });
|
|
450
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
451
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
451
452
|
} break;
|
|
452
453
|
}
|
|
453
454
|
} break;
|
|
@@ -964,7 +965,8 @@ namespace {
|
|
|
964
965
|
return Napi::Number::New(call->env, d);
|
|
965
966
|
}
|
|
966
967
|
OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
967
|
-
OP(
|
|
968
|
+
OP(ReturnAggregateReg) { return DecodeObject(call->env, (const uint8_t *)base, inst->type); }
|
|
969
|
+
OP(ReturnAggregateStack) {
|
|
968
970
|
uint64_t a0 = *(uint64_t *)base;
|
|
969
971
|
return DecodeObject(call->env, (const uint8_t *)a0, inst->type);
|
|
970
972
|
}
|
|
@@ -1009,7 +1011,8 @@ namespace {
|
|
|
1009
1011
|
HandleCallStackX,
|
|
1010
1012
|
#define PRIMITIVE(Name) HandleReturn ## Name,
|
|
1011
1013
|
#include "../primitives.inc"
|
|
1012
|
-
|
|
1014
|
+
HandleReturnAggregateReg,
|
|
1015
|
+
HandleReturnAggregateStack
|
|
1013
1016
|
};
|
|
1014
1017
|
|
|
1015
1018
|
FORCE_INLINE napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiInstruction *inst)
|
|
@@ -82,7 +82,8 @@ enum class AbiOpcode {
|
|
|
82
82
|
CallStackX,
|
|
83
83
|
#define PRIMITIVE(Name) Return ## Name,
|
|
84
84
|
#include "../primitives.inc"
|
|
85
|
-
|
|
85
|
+
ReturnAggregateReg,
|
|
86
|
+
ReturnAggregateStack
|
|
86
87
|
};
|
|
87
88
|
|
|
88
89
|
enum class AbiMethod {
|
|
@@ -454,9 +455,9 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
454
455
|
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateStackX : AbiOpcode::RunAggregateStack;
|
|
455
456
|
AbiOpcode call = func->forward_fp ? AbiOpcode::CallStackX : AbiOpcode::CallStack;
|
|
456
457
|
|
|
457
|
-
func->sync.Append({ .op = Code2Op(run), .a = (int32_t)func->
|
|
458
|
-
func->async.Append({ .op = Code2Op(call), .a = (int32_t)func->
|
|
459
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
458
|
+
func->sync.Append({ .op = Code2Op(run), .a = (int32_t)func->ret.type->size, .type = func->ret.type });
|
|
459
|
+
func->async.Append({ .op = Code2Op(call), .a = (int32_t)func->ret.type->size });
|
|
460
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateStack), .type = func->ret.type });
|
|
460
461
|
|
|
461
462
|
// Allocate stack space for return value
|
|
462
463
|
func->stk_size += AlignLen(func->ret.type->size, 16);
|
|
@@ -467,7 +468,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
467
468
|
|
|
468
469
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
469
470
|
func->async.Append({ .op = Code2Op(call) });
|
|
470
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
471
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
471
472
|
} break;
|
|
472
473
|
case AbiMethod::GprGpr: {
|
|
473
474
|
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateGGX : AbiOpcode::RunAggregateGG;
|
|
@@ -475,7 +476,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
475
476
|
|
|
476
477
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
477
478
|
func->async.Append({ .op = Code2Op(call) });
|
|
478
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
479
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
479
480
|
} break;
|
|
480
481
|
case AbiMethod::Xmm: {
|
|
481
482
|
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateDDX : AbiOpcode::RunAggregateDD;
|
|
@@ -483,7 +484,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
483
484
|
|
|
484
485
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
485
486
|
func->async.Append({ .op = Code2Op(call) });
|
|
486
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
487
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
487
488
|
} break;
|
|
488
489
|
case AbiMethod::XmmXmm: {
|
|
489
490
|
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateDDX : AbiOpcode::RunAggregateDD;
|
|
@@ -491,7 +492,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
491
492
|
|
|
492
493
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
493
494
|
func->async.Append({ .op = Code2Op(call) });
|
|
494
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
495
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
495
496
|
} break;
|
|
496
497
|
case AbiMethod::GprXmm: {
|
|
497
498
|
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateGDX : AbiOpcode::RunAggregateGD;
|
|
@@ -499,7 +500,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
499
500
|
|
|
500
501
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
501
502
|
func->async.Append({ .op = Code2Op(call) });
|
|
502
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
503
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
503
504
|
} break;
|
|
504
505
|
case AbiMethod::XmmGpr: {
|
|
505
506
|
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateDGX : AbiOpcode::RunAggregateDG;
|
|
@@ -507,7 +508,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
507
508
|
|
|
508
509
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
509
510
|
func->async.Append({ .op = Code2Op(call) });
|
|
510
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
511
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
511
512
|
} break;
|
|
512
513
|
}
|
|
513
514
|
} break;
|
|
@@ -815,9 +816,10 @@ namespace {
|
|
|
815
816
|
return DecodeObject(call->env, (const uint8_t *)&ret, inst->type);
|
|
816
817
|
}
|
|
817
818
|
OP(RunAggregateStack) {
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
819
|
+
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
820
|
+
*(uint8_t **)base = ptr;
|
|
821
|
+
WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
|
|
822
|
+
return DecodeObject(call->env, ptr, inst->type);
|
|
821
823
|
}
|
|
822
824
|
OP(RunVoidX) {
|
|
823
825
|
WRAP(ForwardCallGGX(call->native, base, &call->saved_sp));
|
|
@@ -898,9 +900,10 @@ namespace {
|
|
|
898
900
|
return DecodeObject(call->env, (const uint8_t *)&ret, inst->type);
|
|
899
901
|
}
|
|
900
902
|
OP(RunAggregateStackX) {
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
903
|
+
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
904
|
+
*(uint8_t **)base = ptr;
|
|
905
|
+
WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
|
|
906
|
+
return DecodeObject(call->env, ptr, inst->type);
|
|
904
907
|
}
|
|
905
908
|
|
|
906
909
|
#undef DISPOSE
|
|
@@ -941,7 +944,8 @@ namespace {
|
|
|
941
944
|
OP(CallGD) { CALL(GD); return nullptr; }
|
|
942
945
|
OP(CallDD) { CALL(DD); return nullptr; }
|
|
943
946
|
OP(CallStack) {
|
|
944
|
-
|
|
947
|
+
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
948
|
+
*(uint8_t **)base = ptr;
|
|
945
949
|
CALL(GG);
|
|
946
950
|
return nullptr;
|
|
947
951
|
}
|
|
@@ -951,7 +955,8 @@ namespace {
|
|
|
951
955
|
OP(CallGDX) { CALL(GDX); return nullptr; }
|
|
952
956
|
OP(CallDDX) { CALL(DDX); return nullptr; }
|
|
953
957
|
OP(CallStackX) {
|
|
954
|
-
|
|
958
|
+
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
959
|
+
*(uint8_t **)base = ptr;
|
|
955
960
|
CALL(GGX);
|
|
956
961
|
return nullptr;
|
|
957
962
|
}
|
|
@@ -1015,7 +1020,8 @@ namespace {
|
|
|
1015
1020
|
return Napi::Number::New(call->env, d);
|
|
1016
1021
|
}
|
|
1017
1022
|
OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
1018
|
-
OP(
|
|
1023
|
+
OP(ReturnAggregateReg) { return DecodeObject(call->env, base, inst->type); }
|
|
1024
|
+
OP(ReturnAggregateStack) {
|
|
1019
1025
|
uint64_t rax = *(uint64_t *)base;
|
|
1020
1026
|
return DecodeObject(call->env, (const uint8_t *)rax, inst->type);
|
|
1021
1027
|
}
|
|
@@ -1060,7 +1066,8 @@ namespace {
|
|
|
1060
1066
|
HandleCallStackX,
|
|
1061
1067
|
#define PRIMITIVE(Name) HandleReturn ## Name,
|
|
1062
1068
|
#include "../primitives.inc"
|
|
1063
|
-
|
|
1069
|
+
HandleReturnAggregateReg,
|
|
1070
|
+
HandleReturnAggregateStack
|
|
1064
1071
|
};
|
|
1065
1072
|
|
|
1066
1073
|
FORCE_INLINE napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiInstruction *inst)
|
|
@@ -49,7 +49,8 @@ enum class AbiOpcode {
|
|
|
49
49
|
CallStackX,
|
|
50
50
|
#define PRIMITIVE(Name) Return ## Name,
|
|
51
51
|
#include "../primitives.inc"
|
|
52
|
-
|
|
52
|
+
ReturnAggregateReg,
|
|
53
|
+
ReturnAggregateStack
|
|
53
54
|
};
|
|
54
55
|
|
|
55
56
|
namespace {
|
|
@@ -172,14 +173,14 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
172
173
|
|
|
173
174
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
174
175
|
func->async.Append({ .op = Code2Op(call) });
|
|
175
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
176
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
176
177
|
} else {
|
|
177
178
|
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateStackX : AbiOpcode::RunAggregateStack;
|
|
178
179
|
AbiOpcode call = func->forward_fp ? AbiOpcode::CallStackX : AbiOpcode::CallStack;
|
|
179
180
|
|
|
180
181
|
func->sync.Append({ .op = Code2Op(run), .a = (int32_t)func->ret.type->size, .type = func->ret.type });
|
|
181
182
|
func->async.Append({ .op = Code2Op(call), .a = (int32_t)func->ret.type->size });
|
|
182
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
183
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateStack), .type = func->ret.type });
|
|
183
184
|
}
|
|
184
185
|
} break;
|
|
185
186
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
@@ -597,7 +598,7 @@ namespace {
|
|
|
597
598
|
OP(CallD) { CALL(D); return nullptr; }
|
|
598
599
|
OP(CallStack) {
|
|
599
600
|
*(uint8_t **)base = call->AllocHeap(inst->a);
|
|
600
|
-
|
|
601
|
+
WRAP(ForwardCallG(call->native, (uint8_t *)base, &call->saved_sp));
|
|
601
602
|
return nullptr;
|
|
602
603
|
}
|
|
603
604
|
OP(CallGX) { CALL(GX); return nullptr; }
|
|
@@ -605,7 +606,7 @@ namespace {
|
|
|
605
606
|
OP(CallDX) { CALL(DX); return nullptr; }
|
|
606
607
|
OP(CallStackX) {
|
|
607
608
|
*(uint8_t **)base = call->AllocHeap(inst->a);
|
|
608
|
-
|
|
609
|
+
WRAP(ForwardCallGX(call->native, (uint8_t *)base, &call->saved_sp));
|
|
609
610
|
return nullptr;
|
|
610
611
|
}
|
|
611
612
|
|
|
@@ -668,7 +669,8 @@ namespace {
|
|
|
668
669
|
return Napi::Number::New(call->env, d);
|
|
669
670
|
}
|
|
670
671
|
OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
671
|
-
OP(
|
|
672
|
+
OP(ReturnAggregateReg) { return DecodeObject(call->env, (const uint8_t *)base, inst->type); }
|
|
673
|
+
OP(ReturnAggregateStack) {
|
|
672
674
|
uint64_t rax = *(uint64_t *)base;
|
|
673
675
|
return DecodeObject(call->env, (const uint8_t *)rax, inst->type);
|
|
674
676
|
}
|
|
@@ -703,7 +705,8 @@ namespace {
|
|
|
703
705
|
HandleCallStackX,
|
|
704
706
|
#define PRIMITIVE(Name) HandleReturn ## Name,
|
|
705
707
|
#include "../primitives.inc"
|
|
706
|
-
|
|
708
|
+
HandleReturnAggregateReg,
|
|
709
|
+
HandleReturnAggregateStack
|
|
707
710
|
};
|
|
708
711
|
|
|
709
712
|
FORCE_INLINE napi_value RunLoop(CallData *call, napi_value *args, uint64_t *base, const AbiInstruction *inst)
|
package/src/koffi/src/abi/x86.cc
CHANGED
|
@@ -60,7 +60,8 @@ enum class AbiOpcode {
|
|
|
60
60
|
CallStackR,
|
|
61
61
|
#define PRIMITIVE(Name) Return ## Name,
|
|
62
62
|
#include "../primitives.inc"
|
|
63
|
-
|
|
63
|
+
ReturnAggregateReg,
|
|
64
|
+
ReturnAggregateStack
|
|
64
65
|
};
|
|
65
66
|
|
|
66
67
|
static inline void *Code2Op(AbiOpcode code)
|
|
@@ -207,7 +208,7 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
|
|
|
207
208
|
|
|
208
209
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
209
210
|
func->async.Append({ .op = Code2Op(call) });
|
|
210
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
211
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
211
212
|
|
|
212
213
|
break;
|
|
213
214
|
} else if (member.type->primitive == PrimitiveKind::Float64) {
|
|
@@ -216,7 +217,7 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
|
|
|
216
217
|
|
|
217
218
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
218
219
|
func->async.Append({ .op = Code2Op(call) });
|
|
219
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
220
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
220
221
|
|
|
221
222
|
break;
|
|
222
223
|
}
|
|
@@ -229,14 +230,14 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
|
|
|
229
230
|
|
|
230
231
|
func->sync.Append({ .op = Code2Op(run), .type = func->ret.type });
|
|
231
232
|
func->async.Append({ .op = Code2Op(call) });
|
|
232
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
233
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
233
234
|
} else {
|
|
234
235
|
AbiOpcode run = fast ? AbiOpcode::RunAggregateStackR : AbiOpcode::RunAggregateStack;
|
|
235
236
|
AbiOpcode call = fast ? AbiOpcode::CallStackR : AbiOpcode::CallStack;
|
|
236
237
|
|
|
237
238
|
func->sync.Append({ .op = Code2Op(run), .a = (int32_t)func->ret.type->size, .type = func->ret.type });
|
|
238
239
|
func->async.Append({ .op = Code2Op(call), .a = (int32_t)func->ret.type->size });
|
|
239
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
240
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateStack), .type = func->ret.type });
|
|
240
241
|
}
|
|
241
242
|
} break;
|
|
242
243
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
@@ -793,8 +794,13 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
|
|
|
793
794
|
return Napi::Number::New(call->env, d);
|
|
794
795
|
}
|
|
795
796
|
OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
796
|
-
OP(
|
|
797
|
+
OP(ReturnAggregateReg) { return DecodeObject(call->env, (const uint8_t *)base, inst->type); }
|
|
798
|
+
OP(ReturnAggregateStack) {
|
|
799
|
+
#if defined(_WIN32)
|
|
800
|
+
uint32_t eax = *(uint32_t *)(base + 4);
|
|
801
|
+
#else
|
|
797
802
|
uint32_t eax = *(uint32_t *)base;
|
|
803
|
+
#endif
|
|
798
804
|
return DecodeObject(call->env, (const uint8_t *)eax, inst->type);
|
|
799
805
|
}
|
|
800
806
|
|
package/src/koffi/src/call.cc
CHANGED
|
@@ -1220,15 +1220,12 @@ bool CallData::CheckDynamicLength(napi_value obj, Size element, const char *coun
|
|
|
1220
1220
|
}
|
|
1221
1221
|
|
|
1222
1222
|
// Get actual size
|
|
1223
|
-
if (
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
size =
|
|
1229
|
-
} else if (IsArrayBuffer(env, value)) {
|
|
1230
|
-
Napi::ArrayBuffer buffer = Napi::ArrayBuffer(env, value);
|
|
1231
|
-
size = buffer.ByteLength();
|
|
1223
|
+
if (uint32_t len = 0; napi_get_array_length(env, value, &len) == napi_ok) {
|
|
1224
|
+
size = (int64_t)len * element;
|
|
1225
|
+
} else if (size_t len = 0; node_api_get_buffer_info(env, value, nullptr, &len) == napi_ok) {
|
|
1226
|
+
size = (int64_t)len;
|
|
1227
|
+
} else if (size_t len = 0; napi_get_arraybuffer_info(env, value, nullptr, &len) == napi_ok) {
|
|
1228
|
+
size = (int64_t)len;
|
|
1232
1229
|
} else if (!IsNullOrUndefined(env, value)) {
|
|
1233
1230
|
size = element;
|
|
1234
1231
|
} else {
|
|
@@ -1245,7 +1242,7 @@ bool CallData::CheckDynamicLength(napi_value obj, Size element, const char *coun
|
|
|
1245
1242
|
|
|
1246
1243
|
#if defined(K_DEBUG)
|
|
1247
1244
|
|
|
1248
|
-
static bool
|
|
1245
|
+
static bool IsDebugCallsEnabled()
|
|
1249
1246
|
{
|
|
1250
1247
|
static bool debug = GetDebugFlag("DEBUG_CALLS");
|
|
1251
1248
|
return debug;
|
|
@@ -1253,7 +1250,7 @@ static bool IsDebugEnabled()
|
|
|
1253
1250
|
|
|
1254
1251
|
void CallData::DebugCall(const FunctionInfo *func)
|
|
1255
1252
|
{
|
|
1256
|
-
if (!
|
|
1253
|
+
if (!IsDebugCallsEnabled())
|
|
1257
1254
|
return;
|
|
1258
1255
|
|
|
1259
1256
|
PrintLn(StdErr, "%!..+---- %1 (%2) ----%!0", func->name, CallConventionNames[(int)func->convention]);
|
|
@@ -1271,7 +1268,7 @@ void CallData::DebugCall(const FunctionInfo *func)
|
|
|
1271
1268
|
|
|
1272
1269
|
void CallData::DebugForward()
|
|
1273
1270
|
{
|
|
1274
|
-
if (!
|
|
1271
|
+
if (!IsDebugCallsEnabled())
|
|
1275
1272
|
return;
|
|
1276
1273
|
|
|
1277
1274
|
Span<const uint8_t> stack = MakeSpan(mem->stack.end, prev_stack - mem->stack.end);
|
|
@@ -1382,13 +1379,12 @@ napi_value TranslateFastCall(napi_env env, napi_callback_info info)
|
|
|
1382
1379
|
napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func);
|
|
1383
1380
|
K_ASSERT(status == napi_ok);
|
|
1384
1381
|
|
|
1385
|
-
InstanceData *instance = func->instance;
|
|
1386
|
-
|
|
1387
1382
|
if (count < (size_t)func->required_parameters) [[unlikely]] {
|
|
1388
1383
|
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, count);
|
|
1389
1384
|
return Napi::Env(env).Null();
|
|
1390
1385
|
}
|
|
1391
1386
|
|
|
1387
|
+
InstanceData *instance = func->instance;
|
|
1392
1388
|
InstanceMemory *mem = instance->memories[0];
|
|
1393
1389
|
CallData call(env, instance, mem, func->native);
|
|
1394
1390
|
|
|
@@ -1405,13 +1401,12 @@ napi_value TranslateFastCall(napi_env env, napi_callback_info info)
|
|
|
1405
1401
|
|
|
1406
1402
|
static FORCE_INLINE napi_value TranslateNormalCall(napi_env env, const FunctionInfo *func, void *native, napi_value *args, Size count)
|
|
1407
1403
|
{
|
|
1408
|
-
InstanceData *instance = func->instance;
|
|
1409
|
-
|
|
1410
1404
|
if (count < func->required_parameters) [[unlikely]] {
|
|
1411
1405
|
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, count);
|
|
1412
1406
|
return Napi::Env(env).Null();
|
|
1413
1407
|
}
|
|
1414
1408
|
|
|
1409
|
+
InstanceData *instance = func->instance;
|
|
1415
1410
|
InstanceMemory *mem = instance->memories[0];
|
|
1416
1411
|
CallData call(env, instance, mem, native);
|
|
1417
1412
|
|
|
@@ -1447,13 +1442,68 @@ napi_value TranslateNormalCall(napi_env env, napi_callback_info info)
|
|
|
1447
1442
|
return TranslateNormalCall(env, func, func->native, args, (Size)count);
|
|
1448
1443
|
}
|
|
1449
1444
|
|
|
1450
|
-
static napi_value
|
|
1445
|
+
static FORCE_INLINE napi_value TranslateNormalCallDebugAsync(napi_env env, const FunctionInfo *func, void *native, napi_value *args, Size count)
|
|
1451
1446
|
{
|
|
1447
|
+
if (count < func->required_parameters) [[unlikely]] {
|
|
1448
|
+
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, count);
|
|
1449
|
+
return Napi::Env(env).Null();
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
1452
|
InstanceData *instance = func->instance;
|
|
1453
|
+
InstanceMemory *mem = instance->memories[0];
|
|
1454
|
+
CallData call(env, instance, mem, native);
|
|
1455
|
+
|
|
1456
|
+
K_DEFER_C(prev_call = instance->sync_call) { instance->sync_call = prev_call; };
|
|
1457
|
+
instance->sync_call = &call;
|
|
1458
|
+
|
|
1459
|
+
call.DebugCall(func);
|
|
1460
|
+
|
|
1461
|
+
// The async call code partly works differently, with Yield and Return instructions which do not
|
|
1462
|
+
// get used for normal sync calls. To exercise them, we also run the sync tests using async
|
|
1463
|
+
// instructions, by setting DEBUG_ASYNC=1.
|
|
1464
|
+
|
|
1465
|
+
napi_value ret;
|
|
1466
|
+
if (call.PrepareAsync(func, args)) {
|
|
1467
|
+
call.ExecuteAsync();
|
|
1468
|
+
ret = call.EndAsync();
|
|
1469
|
+
} else {
|
|
1470
|
+
ret = Napi::Env(env).Null();
|
|
1471
|
+
}
|
|
1472
|
+
call.Finalize();
|
|
1473
|
+
|
|
1474
|
+
return ret;
|
|
1475
|
+
}
|
|
1453
1476
|
|
|
1477
|
+
napi_value TranslateNormalCallDebugAsync(napi_env env, napi_callback_info info)
|
|
1478
|
+
{
|
|
1479
|
+
static_assert(MaxParameters >= 8);
|
|
1480
|
+
|
|
1481
|
+
napi_value args[MaxParameters];
|
|
1482
|
+
size_t count = 8;
|
|
1483
|
+
FunctionInfo *func;
|
|
1484
|
+
|
|
1485
|
+
napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func);
|
|
1486
|
+
K_ASSERT(status == napi_ok);
|
|
1487
|
+
|
|
1488
|
+
if (count > 8) {
|
|
1489
|
+
napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, nullptr);
|
|
1490
|
+
K_ASSERT(status == napi_ok);
|
|
1491
|
+
|
|
1492
|
+
count = std::min(count, (size_t)MaxParameters);
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
return TranslateNormalCallDebugAsync(env, func, func->native, args, count);
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
static napi_value TranslateVariadicCall(napi_env env, const FunctionInfo *func, void *native, napi_value *args, Size count)
|
|
1499
|
+
{
|
|
1454
1500
|
FunctionInfo *variadic = nullptr;
|
|
1455
1501
|
K_DEFER_N(err_guard) { delete variadic; };
|
|
1456
1502
|
|
|
1503
|
+
InstanceData *instance = func->instance;
|
|
1504
|
+
InstanceMemory *mem = instance->memories[0];
|
|
1505
|
+
CallData call(env, instance, mem, native);
|
|
1506
|
+
|
|
1457
1507
|
// Try cached function
|
|
1458
1508
|
{
|
|
1459
1509
|
FunctionInfo *prev = instance->variadic_func;
|
|
@@ -1531,9 +1581,6 @@ static napi_value TranslateVariadicCall(napi_env env, const FunctionInfo *func,
|
|
|
1531
1581
|
return Napi::Env(env).Null();
|
|
1532
1582
|
}
|
|
1533
1583
|
|
|
1534
|
-
InstanceMemory *mem = instance->memories[0];
|
|
1535
|
-
CallData call(env, instance, mem, native);
|
|
1536
|
-
|
|
1537
1584
|
K_DEFER_C(prev_call = instance->sync_call) { instance->sync_call = prev_call; };
|
|
1538
1585
|
instance->sync_call = &call;
|
|
1539
1586
|
|
package/src/koffi/src/call.hh
CHANGED
|
@@ -170,6 +170,7 @@ bool InitAsyncBroker(Napi::Env env, InstanceData *instance);
|
|
|
170
170
|
napi_value TranslateZeroCall(napi_env env, napi_callback_info info);
|
|
171
171
|
napi_value TranslateFastCall(napi_env env, napi_callback_info info);
|
|
172
172
|
napi_value TranslateNormalCall(napi_env env, napi_callback_info info);
|
|
173
|
+
napi_value TranslateNormalCallDebugAsync(napi_env env, napi_callback_info info);
|
|
173
174
|
napi_value TranslateVariadicCall(napi_env env, napi_callback_info info);
|
|
174
175
|
napi_value TranslateAsyncCall(napi_env env, napi_callback_info info);
|
|
175
176
|
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -37,7 +37,8 @@ namespace K {
|
|
|
37
37
|
|
|
38
38
|
SharedData shared;
|
|
39
39
|
|
|
40
|
-
//
|
|
40
|
+
// Some N-API functions are loaded dynamically to work around bugs or because they are recent
|
|
41
|
+
napi_status (NAPI_CDECL *node_api_get_buffer_info)(napi_env env, napi_value value, void **data, size_t *length);
|
|
41
42
|
napi_status (NAPI_CDECL *node_api_create_property_key_utf8)(napi_env env, const char* str, size_t length, napi_value* result);
|
|
42
43
|
napi_status (NAPI_CDECL *node_api_post_finalizer)(node_api_basic_env env, napi_finalize finalize_cb, void* finalize_data, void* finalize_hint);
|
|
43
44
|
napi_value (*translate_zero_call)(napi_env env, napi_callback_info info);
|
|
@@ -2365,30 +2366,40 @@ static inline PrimitiveKind GetBigEndianPrimitive(PrimitiveKind kind)
|
|
|
2365
2366
|
#endif
|
|
2366
2367
|
}
|
|
2367
2368
|
|
|
2368
|
-
static bool
|
|
2369
|
+
static bool CanCallNapiGetBufferInfoDirectly(const napi_node_version &node, uint32_t napi)
|
|
2369
2370
|
{
|
|
2370
|
-
|
|
2371
|
-
|
|
2371
|
+
if (napi >= 10)
|
|
2372
|
+
return true;
|
|
2373
|
+
if (node.major >= 22)
|
|
2374
|
+
return true;
|
|
2372
2375
|
|
|
2373
|
-
|
|
2376
|
+
// Made by looking at the git history of each release branch
|
|
2377
|
+
if (node.major == 21 && node.minor >= 7)
|
|
2378
|
+
return true;
|
|
2379
|
+
if (node.major == 20 && node.minor >= 12)
|
|
2380
|
+
return true;
|
|
2381
|
+
|
|
2382
|
+
return false;
|
|
2374
2383
|
}
|
|
2375
2384
|
|
|
2376
|
-
static bool
|
|
2385
|
+
static bool CanReferencePrimitiveValues(const napi_node_version &node, uint32_t napi)
|
|
2377
2386
|
{
|
|
2378
|
-
|
|
2379
|
-
|
|
2387
|
+
return napi >= 10;
|
|
2388
|
+
}
|
|
2380
2389
|
|
|
2381
|
-
|
|
2390
|
+
static bool CanDeleteReferenceInFinalizer(const napi_node_version &node, uint32_t napi)
|
|
2391
|
+
{
|
|
2392
|
+
if (node.major >= 24)
|
|
2382
2393
|
return true;
|
|
2383
2394
|
|
|
2384
2395
|
// Made by looking at the git history of each release branch
|
|
2385
|
-
if (
|
|
2396
|
+
if (node.major == 23 && node.minor >= 5)
|
|
2386
2397
|
return true;
|
|
2387
|
-
if (
|
|
2398
|
+
if (node.major == 22 && node.minor >= 13)
|
|
2388
2399
|
return true;
|
|
2389
|
-
if (
|
|
2400
|
+
if (node.major == 20 && node.minor >= 19)
|
|
2390
2401
|
return true;
|
|
2391
|
-
if (
|
|
2402
|
+
if (node.major == 20 && node.minor == 18 && node.patch >= 3)
|
|
2392
2403
|
return true;
|
|
2393
2404
|
|
|
2394
2405
|
return false;
|
|
@@ -2421,13 +2432,32 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
|
|
|
2421
2432
|
#define SYMBOL(Symbol) ((decltype(Symbol))dlsym(h, K_STRINGIFY(Symbol)))
|
|
2422
2433
|
#endif
|
|
2423
2434
|
|
|
2424
|
-
|
|
2435
|
+
const napi_node_version *node_version = nullptr;
|
|
2436
|
+
uint32_t napi_version = 0;
|
|
2437
|
+
napi_get_node_version(env, &node_version);
|
|
2438
|
+
napi_get_version(env, &napi_version);
|
|
2439
|
+
|
|
2440
|
+
if (CanCallNapiGetBufferInfoDirectly(*node_version, napi_version)) {
|
|
2441
|
+
node_api_get_buffer_info = napi_get_buffer_info;
|
|
2442
|
+
} else {
|
|
2443
|
+
// Before Node 20.12, napi_get_buffer_info() would assert/crash
|
|
2444
|
+
// when used with something it did not support, instead of returning napi_invalid_arg.
|
|
2445
|
+
// So we need to call napi_is_buffer() for old versions before trying napi_get_buffer_info().
|
|
2446
|
+
|
|
2447
|
+
node_api_get_buffer_info = [](napi_env env, napi_value value, void **data, size_t *length) {
|
|
2448
|
+
if (!IsBuffer(env, value))
|
|
2449
|
+
return napi_invalid_arg;
|
|
2450
|
+
return napi_get_buffer_info(env, value, data, length);
|
|
2451
|
+
};
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2454
|
+
if (CanReferencePrimitiveValues(*node_version, napi_version)) {
|
|
2425
2455
|
// We can't use optimized property keys in older versions because we need to create
|
|
2426
2456
|
// references to them, but napi_create_reference() was not usable with primitive values.
|
|
2427
2457
|
node_api_create_property_key_utf8 = SYMBOL(node_api_create_property_key_utf8);
|
|
2428
2458
|
}
|
|
2429
2459
|
|
|
2430
|
-
if (!CanDeleteReferenceInFinalizer(
|
|
2460
|
+
if (!CanDeleteReferenceInFinalizer(*node_version, napi_version)) {
|
|
2431
2461
|
// napi_delete_reference cannot be safely used in older Node versions because it
|
|
2432
2462
|
// errors out (or even asserts) if it gets called in a finalizer. In this case,
|
|
2433
2463
|
// use experimental API to try to run it later.
|
package/src/koffi/src/ffi.hh
CHANGED
|
@@ -390,7 +390,8 @@ static_assert(MaxTrampolines <= INT16_MAX);
|
|
|
390
390
|
|
|
391
391
|
extern SharedData shared;
|
|
392
392
|
|
|
393
|
-
//
|
|
393
|
+
// Some N-API functions are loaded dynamically to work around bugs or because they are recent
|
|
394
|
+
extern napi_status (NAPI_CDECL *node_api_get_buffer_info)(napi_env env, napi_value value, void **data, size_t *length);
|
|
394
395
|
extern napi_status (NAPI_CDECL *node_api_create_property_key_utf8)(napi_env env, const char* str, size_t length, napi_value* result);
|
|
395
396
|
extern napi_status (NAPI_CDECL *node_api_post_finalizer)(node_api_basic_env env, napi_finalize finalize_cb, void* finalize_data, void* finalize_hint);
|
|
396
397
|
extern napi_value (*translate_zero_call)(napi_env env, napi_callback_info info);
|
package/src/koffi/src/util.cc
CHANGED
|
@@ -1948,6 +1948,12 @@ Napi::Object DescribeFunction(Napi::Env env, const FunctionInfo *func)
|
|
|
1948
1948
|
return meta;
|
|
1949
1949
|
}
|
|
1950
1950
|
|
|
1951
|
+
static bool IsDebugAsyncEnabled()
|
|
1952
|
+
{
|
|
1953
|
+
static bool debug = GetDebugFlag("DEBUG_ASYNC");
|
|
1954
|
+
return debug;
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1951
1957
|
Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func)
|
|
1952
1958
|
{
|
|
1953
1959
|
Napi::Function wrapper;
|
|
@@ -1959,6 +1965,9 @@ Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func)
|
|
|
1959
1965
|
if (func->variadic) {
|
|
1960
1966
|
napi_status status = napi_create_function(env, func->name, NAPI_AUTO_LENGTH, TranslateVariadicCall, (void *)func->Ref(), &value);
|
|
1961
1967
|
K_ASSERT(status == napi_ok);
|
|
1968
|
+
} else if (IsDebugAsyncEnabled()) {
|
|
1969
|
+
napi_status status = napi_create_function(env, func->name, NAPI_AUTO_LENGTH, TranslateNormalCallDebugAsync, (void *)func->Ref(), &value);
|
|
1970
|
+
K_ASSERT(status == napi_ok);
|
|
1962
1971
|
} else if (!func->parameters.len) {
|
|
1963
1972
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1964
1973
|
napi_status status = napi_create_function(env, func->name, NAPI_AUTO_LENGTH, instance->translate_zero_call, (void *)func->Ref(), &value);
|
package/src/koffi/src/util.hh
CHANGED
|
@@ -275,10 +275,8 @@ static FORCE_INLINE bool TryPointer(napi_env env, napi_value value, void **out_p
|
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
-
if (
|
|
279
|
-
napi_get_typedarray_info(env, value, nullptr, nullptr, out_ptr, nullptr, nullptr);
|
|
278
|
+
if (node_api_get_buffer_info(env, value, out_ptr, nullptr) == napi_ok)
|
|
280
279
|
return true;
|
|
281
|
-
}
|
|
282
280
|
|
|
283
281
|
napi_valuetype kind = GetKindOf(env, value);
|
|
284
282
|
|
|
@@ -299,12 +297,10 @@ static FORCE_INLINE bool TryPointer(napi_env env, napi_value value, void **out_p
|
|
|
299
297
|
*out_ptr = (void *)external.Data();
|
|
300
298
|
return true;
|
|
301
299
|
#endif
|
|
302
|
-
}
|
|
303
|
-
Napi::ArrayBuffer buffer = Napi::ArrayBuffer(env, value);
|
|
300
|
+
}
|
|
304
301
|
|
|
305
|
-
|
|
302
|
+
if (napi_get_arraybuffer_info(env, value, out_ptr, nullptr) == napi_ok)
|
|
306
303
|
return true;
|
|
307
|
-
}
|
|
308
304
|
|
|
309
305
|
return false;
|
|
310
306
|
}
|
|
@@ -325,10 +321,8 @@ static FORCE_INLINE bool TryPointer(napi_env env, napi_value value, void **out_p
|
|
|
325
321
|
}
|
|
326
322
|
}
|
|
327
323
|
|
|
328
|
-
if (
|
|
329
|
-
napi_get_typedarray_info(env, value, nullptr, nullptr, out_ptr, nullptr, nullptr);
|
|
324
|
+
if (node_api_get_buffer_info(env, value, out_ptr, nullptr) == napi_ok) {
|
|
330
325
|
*out_kind = napi_object;
|
|
331
|
-
|
|
332
326
|
return true;
|
|
333
327
|
}
|
|
334
328
|
|
|
@@ -357,12 +351,10 @@ static FORCE_INLINE bool TryPointer(napi_env env, napi_value value, void **out_p
|
|
|
357
351
|
|
|
358
352
|
return true;
|
|
359
353
|
#endif
|
|
360
|
-
}
|
|
361
|
-
Napi::ArrayBuffer buffer = Napi::ArrayBuffer(env, value);
|
|
354
|
+
}
|
|
362
355
|
|
|
363
|
-
|
|
356
|
+
if (napi_get_arraybuffer_info(env, value, out_ptr, nullptr) == napi_ok) {
|
|
364
357
|
*out_kind = napi_object;
|
|
365
|
-
|
|
366
358
|
return true;
|
|
367
359
|
}
|
|
368
360
|
|
|
@@ -372,23 +364,14 @@ static FORCE_INLINE bool TryPointer(napi_env env, napi_value value, void **out_p
|
|
|
372
364
|
|
|
373
365
|
static FORCE_INLINE bool TryBuffer(napi_env env, napi_value value, Span<uint8_t> *out_buffer)
|
|
374
366
|
{
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
// So we need to call napi_is_buffer(), at least for now.
|
|
378
|
-
|
|
379
|
-
if (IsBuffer(env, value)) {
|
|
380
|
-
void *ptr = nullptr;
|
|
381
|
-
size_t length = 0;
|
|
367
|
+
void *ptr = nullptr;
|
|
368
|
+
size_t len = 0;
|
|
382
369
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
*out_buffer = MakeSpan((uint8_t *)ptr, (Size)length);
|
|
370
|
+
if (node_api_get_buffer_info(env, value, &ptr, &len) == napi_ok) {
|
|
371
|
+
*out_buffer = MakeSpan((uint8_t *)ptr, (Size)len);
|
|
387
372
|
return true;
|
|
388
|
-
} else if (
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
*out_buffer = MakeSpan((uint8_t *)buffer.Data(), (Size)buffer.ByteLength());
|
|
373
|
+
} else if (napi_get_arraybuffer_info(env, value, &ptr, &len) == napi_ok) {
|
|
374
|
+
*out_buffer = MakeSpan((uint8_t *)ptr, (Size)len);
|
|
392
375
|
return true;
|
|
393
376
|
}
|
|
394
377
|
|