koffi 2.3.21-beta.2 → 2.3.21-beta.4
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/2.3.21-beta.4/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.21-beta.4/koffi_win32_arm64/koffi.node +0 -0
- package/build/{2.3.21-beta.2 → 2.3.21-beta.4}/koffi_win32_ia32/koffi.node +0 -0
- package/build/{2.3.21-beta.2 → 2.3.21-beta.4}/koffi_win32_x64/koffi.node +0 -0
- package/package.json +1 -1
- package/src/index.d.ts +6 -2
- package/src/index.js +2 -1
- package/src/koffi/src/abi_arm32.cc +3 -3
- package/src/koffi/src/abi_arm64.cc +3 -3
- package/src/koffi/src/abi_riscv64.cc +3 -3
- package/src/koffi/src/abi_x64_sysv.cc +3 -3
- package/src/koffi/src/abi_x64_win.cc +3 -3
- package/src/koffi/src/abi_x86.cc +3 -3
- package/src/koffi/src/call.hh +1 -1
- package/src/koffi/src/ffi.cc +104 -78
- package/src/koffi/src/ffi.hh +6 -1
- package/src/koffi/src/parser.cc +2 -0
- package/src/koffi/src/util.cc +74 -3
- package/src/koffi/src/util.hh +4 -0
- package/build/2.3.21-beta.2/koffi_darwin_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_darwin_x64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_freebsd_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_freebsd_ia32/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_freebsd_x64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_linux_arm32hf/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_linux_arm64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_linux_ia32/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_linux_riscv64hf64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_linux_x64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_openbsd_ia32/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_openbsd_x64/koffi.node +0 -0
- package/build/2.3.21-beta.2/koffi_win32_arm64/koffi.node +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.4}/koffi_win32_arm64/koffi.exp +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.4}/koffi_win32_arm64/koffi.lib +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.4}/koffi_win32_ia32/koffi.exp +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.4}/koffi_win32_ia32/koffi.lib +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.4}/koffi_win32_x64/koffi.exp +0 -0
- /package/build/{2.3.21-beta.2 → 2.3.21-beta.4}/koffi_win32_x64/koffi.lib +0 -0
|
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/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -93,6 +93,8 @@ declare module 'koffi' {
|
|
|
93
93
|
|
|
94
94
|
export function opaque(name: string): IKoffiCType;
|
|
95
95
|
export function opaque(): IKoffiCType;
|
|
96
|
+
/** @deprecated */ export function handle(name: string): IKoffiCType;
|
|
97
|
+
/** @deprecated */ export function handle(): IKoffiCType;
|
|
96
98
|
|
|
97
99
|
export function pointer(value: TypeSpec): IKoffiCType;
|
|
98
100
|
export function pointer(value: TypeSpec, asteriskCount: number): IKoffiCType;
|
|
@@ -105,8 +107,10 @@ declare module 'koffi' {
|
|
|
105
107
|
export function disposable(name: string, type: TypeSpec): IKoffiCType;
|
|
106
108
|
export function disposable(name: string, type: TypeSpec, freeFunction: Function): IKoffiCType;
|
|
107
109
|
|
|
108
|
-
export function
|
|
109
|
-
export function
|
|
110
|
+
export function proto(definition: string): IKoffiCType;
|
|
111
|
+
export function proto(name: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
112
|
+
/** @deprecated */ export function callback(definition: string): IKoffiCType;
|
|
113
|
+
/** @deprecated */ export function callback(name: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
110
114
|
|
|
111
115
|
export function register(callback: Function, type: TypeSpec): IKoffiRegisteredCallback;
|
|
112
116
|
export function register(thisValue: any, callback: Function, type: TypeSpec): IKoffiRegisteredCallback;
|
package/src/index.js
CHANGED
|
@@ -57,5 +57,6 @@ module.exports = {
|
|
|
57
57
|
...native,
|
|
58
58
|
|
|
59
59
|
// Deprecated functions
|
|
60
|
-
handle: util.deprecate(native.opaque, 'The koffi.handle() function was deprecated in Koffi 2.1, use koffi.opaque() instead', 'KOFFI001')
|
|
60
|
+
handle: util.deprecate(native.opaque, 'The koffi.handle() function was deprecated in Koffi 2.1, use koffi.opaque() instead', 'KOFFI001'),
|
|
61
|
+
callback: util.deprecate(native.proto, 'The koffi.callback() function was deprecated in Koffi 2.4, use koffi.proto() instead', 'KOFFI002')
|
|
61
62
|
};
|
|
@@ -456,12 +456,12 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
456
456
|
return true;
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
459
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
460
460
|
{
|
|
461
461
|
#define PERFORM_CALL(Suffix) \
|
|
462
462
|
([&]() { \
|
|
463
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(
|
|
464
|
-
: ForwardCall ## Suffix(
|
|
463
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(native, new_sp, &old_sp) \
|
|
464
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
465
465
|
return ret; \
|
|
466
466
|
})()
|
|
467
467
|
|
|
@@ -561,7 +561,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
561
561
|
return true;
|
|
562
562
|
}
|
|
563
563
|
|
|
564
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
564
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
565
565
|
{
|
|
566
566
|
#ifdef _WIN32
|
|
567
567
|
TEB *teb = GetTEB();
|
|
@@ -589,8 +589,8 @@ void CallData::Execute(const FunctionInfo *func)
|
|
|
589
589
|
|
|
590
590
|
#define PERFORM_CALL(Suffix) \
|
|
591
591
|
([&]() { \
|
|
592
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(
|
|
593
|
-
: ForwardCall ## Suffix(
|
|
592
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(native, new_sp, &old_sp) \
|
|
593
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
594
594
|
return ret; \
|
|
595
595
|
})()
|
|
596
596
|
|
|
@@ -386,12 +386,12 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
386
386
|
return true;
|
|
387
387
|
}
|
|
388
388
|
|
|
389
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
389
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
390
390
|
{
|
|
391
391
|
#define PERFORM_CALL(Suffix) \
|
|
392
392
|
([&]() { \
|
|
393
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(
|
|
394
|
-
: ForwardCall ## Suffix(
|
|
393
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(native, new_sp, &old_sp) \
|
|
394
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
395
395
|
return ret; \
|
|
396
396
|
})()
|
|
397
397
|
|
|
@@ -425,12 +425,12 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
425
425
|
return true;
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
428
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
429
429
|
{
|
|
430
430
|
#define PERFORM_CALL(Suffix) \
|
|
431
431
|
([&]() { \
|
|
432
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(
|
|
433
|
-
: ForwardCall ## Suffix(
|
|
432
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(native, new_sp, &old_sp) \
|
|
433
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
434
434
|
return ret; \
|
|
435
435
|
})()
|
|
436
436
|
|
|
@@ -224,7 +224,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
224
224
|
return true;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
227
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
228
228
|
{
|
|
229
229
|
TEB *teb = GetTEB();
|
|
230
230
|
|
|
@@ -250,8 +250,8 @@ void CallData::Execute(const FunctionInfo *func)
|
|
|
250
250
|
|
|
251
251
|
#define PERFORM_CALL(Suffix) \
|
|
252
252
|
([&]() { \
|
|
253
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(
|
|
254
|
-
: ForwardCall ## Suffix(
|
|
253
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(native, new_sp, &old_sp) \
|
|
254
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
255
255
|
return ret; \
|
|
256
256
|
})()
|
|
257
257
|
|
package/src/koffi/src/abi_x86.cc
CHANGED
|
@@ -308,7 +308,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
308
308
|
return true;
|
|
309
309
|
}
|
|
310
310
|
|
|
311
|
-
void CallData::Execute(const FunctionInfo *func)
|
|
311
|
+
void CallData::Execute(const FunctionInfo *func, void *native)
|
|
312
312
|
{
|
|
313
313
|
#ifdef _WIN32
|
|
314
314
|
TEB *teb = GetTEB();
|
|
@@ -336,8 +336,8 @@ void CallData::Execute(const FunctionInfo *func)
|
|
|
336
336
|
|
|
337
337
|
#define PERFORM_CALL(Suffix) \
|
|
338
338
|
([&]() { \
|
|
339
|
-
auto ret = (func->fast ? ForwardCallR ## Suffix(
|
|
340
|
-
: ForwardCall ## Suffix(
|
|
339
|
+
auto ret = (func->fast ? ForwardCallR ## Suffix(native, new_sp, &old_sp) \
|
|
340
|
+
: ForwardCall ## Suffix(native, new_sp, &old_sp)); \
|
|
341
341
|
return ret; \
|
|
342
342
|
})()
|
|
343
343
|
|
package/src/koffi/src/call.hh
CHANGED
|
@@ -102,7 +102,7 @@ public:
|
|
|
102
102
|
#endif
|
|
103
103
|
|
|
104
104
|
INLINE_IF_UNITY bool Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info);
|
|
105
|
-
INLINE_IF_UNITY void Execute(const FunctionInfo *func);
|
|
105
|
+
INLINE_IF_UNITY void Execute(const FunctionInfo *func, void *native);
|
|
106
106
|
INLINE_IF_UNITY Napi::Value Complete(const FunctionInfo *func);
|
|
107
107
|
|
|
108
108
|
#undef INLINE_IF_UNITY
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -204,14 +204,6 @@ static inline bool CheckAlignment(int64_t align)
|
|
|
204
204
|
return valid;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
static inline Napi::External<TypeInfo> WrapType(Napi::Env env, InstanceData *instance, const TypeInfo *type)
|
|
208
|
-
{
|
|
209
|
-
Napi::External<TypeInfo> external = Napi::External<TypeInfo>::New(env, (TypeInfo *)type);
|
|
210
|
-
SetValueTag(instance, external, &TypeInfoMarker);
|
|
211
|
-
|
|
212
|
-
return external;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
207
|
static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
|
|
216
208
|
{
|
|
217
209
|
Napi::Env env = info.Env();
|
|
@@ -275,7 +267,7 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
|
|
|
275
267
|
value = array[1u];
|
|
276
268
|
align = (int16_t)align64;
|
|
277
269
|
}
|
|
278
|
-
|
|
270
|
+
|
|
279
271
|
member.type = ResolveType(value);
|
|
280
272
|
if (!member.type)
|
|
281
273
|
return env.Null();
|
|
@@ -403,7 +395,7 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
|
|
|
403
395
|
value = array[1u];
|
|
404
396
|
align = (int16_t)align64;
|
|
405
397
|
}
|
|
406
|
-
|
|
398
|
+
|
|
407
399
|
member.type = ResolveType(value);
|
|
408
400
|
if (!member.type)
|
|
409
401
|
return env.Null();
|
|
@@ -920,10 +912,12 @@ static bool ParseClassicFunction(Napi::Env env, Napi::String name, Napi::Value r
|
|
|
920
912
|
func->parameters.Append(param);
|
|
921
913
|
}
|
|
922
914
|
|
|
915
|
+
func->required_parameters = (int8_t)func->parameters.len;
|
|
916
|
+
|
|
923
917
|
return true;
|
|
924
918
|
}
|
|
925
919
|
|
|
926
|
-
static Napi::Value
|
|
920
|
+
static Napi::Value CreateFunctionType(const Napi::CallbackInfo &info)
|
|
927
921
|
{
|
|
928
922
|
Napi::Env env = info.Env();
|
|
929
923
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
@@ -956,6 +950,12 @@ static Napi::Value CreateCallbackType(const Napi::CallbackInfo &info)
|
|
|
956
950
|
if (!AnalyseFunction(env, instance, func))
|
|
957
951
|
return env.Null();
|
|
958
952
|
|
|
953
|
+
// Adjust parameter offsets for koffi.call()
|
|
954
|
+
for (ParameterInfo ¶m: func->parameters) {
|
|
955
|
+
param.offset += 2;
|
|
956
|
+
}
|
|
957
|
+
func->required_parameters += 2;
|
|
958
|
+
|
|
959
959
|
// We cannot fail after this check
|
|
960
960
|
if (instance->types_map.Find(func->name)) {
|
|
961
961
|
ThrowError<Napi::Error>(env, "Duplicate type name '%1'", func->name);
|
|
@@ -1239,13 +1239,13 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
|
|
|
1239
1239
|
return mem;
|
|
1240
1240
|
}
|
|
1241
1241
|
|
|
1242
|
-
static Napi::Value TranslateNormalCall(const
|
|
1242
|
+
static Napi::Value TranslateNormalCall(const FunctionInfo *func, void *native,
|
|
1243
|
+
const Napi::CallbackInfo &info)
|
|
1243
1244
|
{
|
|
1244
1245
|
Napi::Env env = info.Env();
|
|
1245
1246
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1246
|
-
FunctionInfo *func = (FunctionInfo *)info.Data();
|
|
1247
1247
|
|
|
1248
|
-
if (RG_UNLIKELY(info.Length() < (uint32_t)func->
|
|
1248
|
+
if (RG_UNLIKELY(info.Length() < (uint32_t)func->required_parameters)) {
|
|
1249
1249
|
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
|
|
1250
1250
|
return env.Null();
|
|
1251
1251
|
}
|
|
@@ -1265,37 +1265,44 @@ static Napi::Value TranslateNormalCall(const Napi::CallbackInfo &info)
|
|
|
1265
1265
|
RG_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1266
1266
|
exec_call = &call;
|
|
1267
1267
|
|
|
1268
|
-
call.Execute(func);
|
|
1268
|
+
call.Execute(func, native);
|
|
1269
1269
|
}
|
|
1270
1270
|
|
|
1271
1271
|
return call.Complete(func);
|
|
1272
1272
|
}
|
|
1273
1273
|
|
|
1274
|
-
|
|
1274
|
+
Napi::Value TranslateNormalCall(const Napi::CallbackInfo &info)
|
|
1275
|
+
{
|
|
1276
|
+
FunctionInfo *func = (FunctionInfo *)info.Data();
|
|
1277
|
+
return TranslateNormalCall(func, func->native, info);
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
static Napi::Value TranslateVariadicCall(const FunctionInfo *func, void *native,
|
|
1281
|
+
const Napi::CallbackInfo &info)
|
|
1275
1282
|
{
|
|
1276
1283
|
Napi::Env env = info.Env();
|
|
1277
1284
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1278
1285
|
|
|
1279
|
-
FunctionInfo
|
|
1280
|
-
memcpy((void *)&
|
|
1281
|
-
|
|
1286
|
+
FunctionInfo copy;
|
|
1287
|
+
memcpy((void *)©, func, RG_SIZE(*func));
|
|
1288
|
+
copy.lib = nullptr;
|
|
1282
1289
|
|
|
1283
1290
|
// This makes variadic calls non-reentrant
|
|
1284
|
-
RG_DEFER_C(len =
|
|
1285
|
-
|
|
1286
|
-
|
|
1291
|
+
RG_DEFER_C(len = copy.parameters.len) {
|
|
1292
|
+
copy.parameters.RemoveFrom(len);
|
|
1293
|
+
copy.parameters.Leak();
|
|
1287
1294
|
};
|
|
1288
1295
|
|
|
1289
|
-
if (RG_UNLIKELY(info.Length() < (uint32_t)
|
|
1290
|
-
ThrowError<Napi::TypeError>(env, "Expected %1 arguments or more, got %2",
|
|
1296
|
+
if (RG_UNLIKELY(info.Length() < (uint32_t)copy.required_parameters)) {
|
|
1297
|
+
ThrowError<Napi::TypeError>(env, "Expected %1 arguments or more, got %2", copy.parameters.len, info.Length());
|
|
1291
1298
|
return env.Null();
|
|
1292
1299
|
}
|
|
1293
|
-
if (RG_UNLIKELY((info.Length() -
|
|
1300
|
+
if (RG_UNLIKELY((info.Length() - copy.required_parameters) % 2)) {
|
|
1294
1301
|
ThrowError<Napi::Error>(env, "Missing value argument for variadic call");
|
|
1295
1302
|
return env.Null();
|
|
1296
1303
|
}
|
|
1297
1304
|
|
|
1298
|
-
for (Size i =
|
|
1305
|
+
for (Size i = copy.required_parameters; i < (Size)info.Length(); i += 2) {
|
|
1299
1306
|
ParameterInfo param = {};
|
|
1300
1307
|
|
|
1301
1308
|
param.type = ResolveType(info[(uint32_t)i], ¶m.directions);
|
|
@@ -1306,11 +1313,11 @@ static Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
|
1306
1313
|
ThrowError<Napi::TypeError>(env, "Type %1 cannot be used as a parameter (maybe try %1 *)", param.type->name);
|
|
1307
1314
|
return env.Null();
|
|
1308
1315
|
}
|
|
1309
|
-
if (RG_UNLIKELY(
|
|
1316
|
+
if (RG_UNLIKELY(copy.parameters.len >= MaxParameters)) {
|
|
1310
1317
|
ThrowError<Napi::TypeError>(env, "Functions cannot have more than %1 parameters", MaxParameters);
|
|
1311
1318
|
return env.Null();
|
|
1312
1319
|
}
|
|
1313
|
-
if (RG_UNLIKELY((param.directions & 2) && ++
|
|
1320
|
+
if (RG_UNLIKELY((param.directions & 2) && ++copy.out_parameters >= MaxOutParameters)) {
|
|
1314
1321
|
ThrowError<Napi::TypeError>(env, "Functions cannot have more than %1 output parameters", MaxOutParameters);
|
|
1315
1322
|
return env.Null();
|
|
1316
1323
|
}
|
|
@@ -1318,20 +1325,20 @@ static Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
|
1318
1325
|
param.variadic = true;
|
|
1319
1326
|
param.offset = (int8_t)(i + 1);
|
|
1320
1327
|
|
|
1321
|
-
|
|
1328
|
+
copy.parameters.Append(param);
|
|
1322
1329
|
}
|
|
1323
1330
|
|
|
1324
|
-
if (RG_UNLIKELY(!AnalyseFunction(env, instance, &
|
|
1331
|
+
if (RG_UNLIKELY(!AnalyseFunction(env, instance, ©)))
|
|
1325
1332
|
return env.Null();
|
|
1326
1333
|
|
|
1327
1334
|
InstanceMemory *mem = instance->memories[0];
|
|
1328
1335
|
CallData call(env, instance, mem);
|
|
1329
1336
|
|
|
1330
|
-
if (!RG_UNLIKELY(call.Prepare(&
|
|
1337
|
+
if (!RG_UNLIKELY(call.Prepare(©, info)))
|
|
1331
1338
|
return env.Null();
|
|
1332
1339
|
|
|
1333
1340
|
if (instance->debug) {
|
|
1334
|
-
call.DumpForward(&
|
|
1341
|
+
call.DumpForward(©);
|
|
1335
1342
|
}
|
|
1336
1343
|
|
|
1337
1344
|
// Execute call
|
|
@@ -1339,23 +1346,31 @@ static Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
|
1339
1346
|
RG_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1340
1347
|
exec_call = &call;
|
|
1341
1348
|
|
|
1342
|
-
call.Execute(&
|
|
1349
|
+
call.Execute(©, native);
|
|
1343
1350
|
}
|
|
1344
1351
|
|
|
1345
|
-
return call.Complete(&
|
|
1352
|
+
return call.Complete(©);
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info)
|
|
1356
|
+
{
|
|
1357
|
+
FunctionInfo *func = (FunctionInfo *)info.Data();
|
|
1358
|
+
return TranslateVariadicCall(func, func->native, info);
|
|
1346
1359
|
}
|
|
1347
1360
|
|
|
1348
1361
|
class AsyncCall: public Napi::AsyncWorker {
|
|
1349
1362
|
Napi::Env env;
|
|
1363
|
+
|
|
1350
1364
|
const FunctionInfo *func;
|
|
1365
|
+
void *native;
|
|
1351
1366
|
|
|
1352
1367
|
CallData call;
|
|
1353
1368
|
bool prepared = false;
|
|
1354
1369
|
|
|
1355
1370
|
public:
|
|
1356
1371
|
AsyncCall(Napi::Env env, InstanceData *instance, const FunctionInfo *func,
|
|
1357
|
-
InstanceMemory *mem, Napi::Function &callback)
|
|
1358
|
-
: Napi::AsyncWorker(callback), env(env), func(func->Ref()),
|
|
1372
|
+
void *native, InstanceMemory *mem, Napi::Function &callback)
|
|
1373
|
+
: Napi::AsyncWorker(callback), env(env), func(func->Ref()), native(native),
|
|
1359
1374
|
call(env, instance, mem) {}
|
|
1360
1375
|
~AsyncCall() { func->Unref(); }
|
|
1361
1376
|
|
|
@@ -1381,7 +1396,7 @@ void AsyncCall::Execute()
|
|
|
1381
1396
|
RG_DEFER_C(prev_call = exec_call) { exec_call = prev_call; };
|
|
1382
1397
|
exec_call = &call;
|
|
1383
1398
|
|
|
1384
|
-
call.Execute(func);
|
|
1399
|
+
call.Execute(func, native);
|
|
1385
1400
|
}
|
|
1386
1401
|
}
|
|
1387
1402
|
|
|
@@ -1400,18 +1415,20 @@ void AsyncCall::OnOK()
|
|
|
1400
1415
|
callback.Call(self, RG_LEN(args), args);
|
|
1401
1416
|
}
|
|
1402
1417
|
|
|
1403
|
-
static Napi::Value TranslateAsyncCall(const
|
|
1418
|
+
static Napi::Value TranslateAsyncCall(const FunctionInfo *func, void *native,
|
|
1419
|
+
const Napi::CallbackInfo &info)
|
|
1404
1420
|
{
|
|
1421
|
+
RG_ASSERT(!func->variadic);
|
|
1422
|
+
|
|
1405
1423
|
Napi::Env env = info.Env();
|
|
1406
1424
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1407
|
-
FunctionInfo *func = (FunctionInfo *)info.Data();
|
|
1408
1425
|
|
|
1409
|
-
if (info.Length() <= (uint32_t)func->
|
|
1426
|
+
if (info.Length() <= (uint32_t)func->required_parameters) {
|
|
1410
1427
|
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len + 1, info.Length());
|
|
1411
1428
|
return env.Null();
|
|
1412
1429
|
}
|
|
1413
1430
|
|
|
1414
|
-
Napi::Function callback = info[(uint32_t)func->
|
|
1431
|
+
Napi::Function callback = info[(uint32_t)func->required_parameters].As<Napi::Function>();
|
|
1415
1432
|
|
|
1416
1433
|
if (!callback.IsFunction()) {
|
|
1417
1434
|
ThrowError<Napi::TypeError>(env, "Expected callback function as last argument, got %1", GetValueType(instance, callback));
|
|
@@ -1423,7 +1440,7 @@ static Napi::Value TranslateAsyncCall(const Napi::CallbackInfo &info)
|
|
|
1423
1440
|
ThrowError<Napi::Error>(env, "Too many asynchronous calls are running");
|
|
1424
1441
|
return env.Null();
|
|
1425
1442
|
}
|
|
1426
|
-
AsyncCall *async = new AsyncCall(env, instance, func, mem, callback);
|
|
1443
|
+
AsyncCall *async = new AsyncCall(env, instance, func, native, mem, callback);
|
|
1427
1444
|
|
|
1428
1445
|
if (async->Prepare(info) && instance->debug) {
|
|
1429
1446
|
async->DumpForward();
|
|
@@ -1433,6 +1450,12 @@ static Napi::Value TranslateAsyncCall(const Napi::CallbackInfo &info)
|
|
|
1433
1450
|
return env.Undefined();
|
|
1434
1451
|
}
|
|
1435
1452
|
|
|
1453
|
+
Napi::Value TranslateAsyncCall(const Napi::CallbackInfo &info)
|
|
1454
|
+
{
|
|
1455
|
+
FunctionInfo *func = (FunctionInfo *)info.Data();
|
|
1456
|
+
return TranslateAsyncCall(func, func->native, info);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1436
1459
|
static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConvention convention)
|
|
1437
1460
|
{
|
|
1438
1461
|
Napi::Env env = info.Env();
|
|
@@ -1478,57 +1501,31 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info, CallConve
|
|
|
1478
1501
|
#ifdef _WIN32
|
|
1479
1502
|
if (info[0].IsString()) {
|
|
1480
1503
|
if (func->decorated_name) {
|
|
1481
|
-
func->
|
|
1504
|
+
func->native = (void *)GetProcAddress((HMODULE)lib->module, func->decorated_name);
|
|
1482
1505
|
}
|
|
1483
|
-
if (!func->
|
|
1484
|
-
func->
|
|
1506
|
+
if (!func->native) {
|
|
1507
|
+
func->native = (void *)GetProcAddress((HMODULE)lib->module, func->name);
|
|
1485
1508
|
}
|
|
1486
1509
|
} else {
|
|
1487
1510
|
uint16_t ordinal = (uint16_t)info[0].As<Napi::Number>().Uint32Value();
|
|
1488
1511
|
|
|
1489
1512
|
func->decorated_name = nullptr;
|
|
1490
|
-
func->
|
|
1513
|
+
func->native = (void *)GetProcAddress((HMODULE)lib->module, (LPCSTR)(size_t)ordinal);
|
|
1491
1514
|
}
|
|
1492
1515
|
#else
|
|
1493
1516
|
if (func->decorated_name) {
|
|
1494
|
-
func->
|
|
1517
|
+
func->native = dlsym(lib->module, func->decorated_name);
|
|
1495
1518
|
}
|
|
1496
|
-
if (!func->
|
|
1497
|
-
func->
|
|
1519
|
+
if (!func->native) {
|
|
1520
|
+
func->native = dlsym(lib->module, func->name);
|
|
1498
1521
|
}
|
|
1499
1522
|
#endif
|
|
1500
|
-
if (!func->
|
|
1523
|
+
if (!func->native) {
|
|
1501
1524
|
ThrowError<Napi::Error>(env, "Cannot find function '%1' in shared library", func->name);
|
|
1502
1525
|
return env.Null();
|
|
1503
1526
|
}
|
|
1504
1527
|
|
|
1505
|
-
Napi::Function
|
|
1506
|
-
Napi::Function wrapper = Napi::Function::New(env, call, func->name, (void *)func->Ref());
|
|
1507
|
-
wrapper.AddFinalizer([](Napi::Env, FunctionInfo *func) { func->Unref(); }, func);
|
|
1508
|
-
|
|
1509
|
-
if (!func->variadic) {
|
|
1510
|
-
Napi::Function async = Napi::Function::New(env, TranslateAsyncCall, func->name, (void *)func->Ref());
|
|
1511
|
-
async.AddFinalizer([](Napi::Env, FunctionInfo *func) { func->Unref(); }, func);
|
|
1512
|
-
wrapper.Set("async", async);
|
|
1513
|
-
}
|
|
1514
|
-
|
|
1515
|
-
// Create info object
|
|
1516
|
-
{
|
|
1517
|
-
Napi::Object meta = Napi::Object::New(env);
|
|
1518
|
-
Napi::Array arguments = Napi::Array::New(env, func->parameters.len);
|
|
1519
|
-
|
|
1520
|
-
meta.Set("name", Napi::String::New(env, func->name));
|
|
1521
|
-
meta.Set("arguments", arguments);
|
|
1522
|
-
meta.Set("result", WrapType(env, instance, func->ret.type));
|
|
1523
|
-
|
|
1524
|
-
for (Size i = 0; i < func->parameters.len; i++) {
|
|
1525
|
-
const ParameterInfo ¶m = func->parameters[i];
|
|
1526
|
-
arguments.Set((uint32_t)i, WrapType(env, instance, param.type));
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
wrapper.Set("info", meta);
|
|
1530
|
-
}
|
|
1531
|
-
|
|
1528
|
+
Napi::Function wrapper = WrapFunction(env, func);
|
|
1532
1529
|
return wrapper;
|
|
1533
1530
|
}
|
|
1534
1531
|
|
|
@@ -2064,6 +2061,34 @@ static Napi::Value GetPointerAddress(const Napi::CallbackInfo &info)
|
|
|
2064
2061
|
return bigint;
|
|
2065
2062
|
}
|
|
2066
2063
|
|
|
2064
|
+
static Napi::Value CallPointerSync(const Napi::CallbackInfo &info)
|
|
2065
|
+
{
|
|
2066
|
+
Napi::Env env = info.Env();
|
|
2067
|
+
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
2068
|
+
|
|
2069
|
+
if (RG_UNLIKELY(info.Length() < 2)) {
|
|
2070
|
+
ThrowError<Napi::TypeError>(env, "Expected 2 or more arguments, got %1", info.Length());
|
|
2071
|
+
return env.Null();
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
void *ptr = nullptr;
|
|
2075
|
+
if (RG_UNLIKELY(!GetExternalPointer(env, info[0], &ptr)))
|
|
2076
|
+
return env.Null();
|
|
2077
|
+
|
|
2078
|
+
const TypeInfo *type = ResolveType(info[1]);
|
|
2079
|
+
if (RG_UNLIKELY(!type))
|
|
2080
|
+
return env.Null();
|
|
2081
|
+
if (RG_UNLIKELY(type->primitive != PrimitiveKind::Prototype)) {
|
|
2082
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for type, expected function type", GetValueType(instance, info[1]));
|
|
2083
|
+
return env.Null();
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
const FunctionInfo *proto = type->ref.proto;
|
|
2087
|
+
RG_ASSERT(!proto->variadic);
|
|
2088
|
+
|
|
2089
|
+
return TranslateNormalCall(proto, ptr, info);
|
|
2090
|
+
}
|
|
2091
|
+
|
|
2067
2092
|
extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
|
|
2068
2093
|
{
|
|
2069
2094
|
if (RG_LIKELY(exec_call)) {
|
|
@@ -2106,7 +2131,7 @@ static void SetExports(Napi::Env env, Func func)
|
|
|
2106
2131
|
func("opaque", Napi::Function::New(env, CreateOpaqueType));
|
|
2107
2132
|
func("pointer", Napi::Function::New(env, CreatePointerType));
|
|
2108
2133
|
func("array", Napi::Function::New(env, CreateArrayType));
|
|
2109
|
-
func("
|
|
2134
|
+
func("proto", Napi::Function::New(env, CreateFunctionType));
|
|
2110
2135
|
func("alias", Napi::Function::New(env, CreateTypeAlias));
|
|
2111
2136
|
|
|
2112
2137
|
func("sizeof", Napi::Function::New(env, GetTypeSize));
|
|
@@ -2130,6 +2155,7 @@ static void SetExports(Napi::Env env, Func func)
|
|
|
2130
2155
|
func("as", Napi::Function::New(env, CastValue));
|
|
2131
2156
|
func("decode", Napi::Function::New(env, DecodeValue));
|
|
2132
2157
|
func("address", Napi::Function::New(env, GetPointerAddress));
|
|
2158
|
+
func("call", Napi::Function::New(env, CallPointerSync));
|
|
2133
2159
|
|
|
2134
2160
|
func("errno", Napi::Function::New(env, GetOrSetErrNo));
|
|
2135
2161
|
|
package/src/koffi/src/ffi.hh
CHANGED
|
@@ -221,11 +221,12 @@ struct FunctionInfo {
|
|
|
221
221
|
const char *decorated_name; // Only set for some platforms/calling conventions
|
|
222
222
|
const LibraryHolder *lib = nullptr;
|
|
223
223
|
|
|
224
|
-
void *
|
|
224
|
+
void *native;
|
|
225
225
|
CallConvention convention;
|
|
226
226
|
|
|
227
227
|
ParameterInfo ret;
|
|
228
228
|
HeapArray<ParameterInfo> parameters;
|
|
229
|
+
int8_t required_parameters;
|
|
229
230
|
int8_t out_parameters;
|
|
230
231
|
bool variadic;
|
|
231
232
|
|
|
@@ -335,4 +336,8 @@ RG_STATIC_ASSERT(MaxTrampolines <= INT16_MAX);
|
|
|
335
336
|
|
|
336
337
|
extern SharedData shared;
|
|
337
338
|
|
|
339
|
+
Napi::Value TranslateNormalCall(const Napi::CallbackInfo &info);
|
|
340
|
+
Napi::Value TranslateVariadicCall(const Napi::CallbackInfo &info);
|
|
341
|
+
Napi::Value TranslateAsyncCall(const Napi::CallbackInfo &info);
|
|
342
|
+
|
|
338
343
|
}
|
package/src/koffi/src/parser.cc
CHANGED
|
@@ -99,6 +99,8 @@ bool PrototypeParser::Parse(const char *str, FunctionInfo *out_func)
|
|
|
99
99
|
}
|
|
100
100
|
Consume(")");
|
|
101
101
|
|
|
102
|
+
out_func->required_parameters = (int8_t)out_func->parameters.len;
|
|
103
|
+
|
|
102
104
|
Match(";");
|
|
103
105
|
if (offset < tokens.len) {
|
|
104
106
|
MarkError("Unexpected token '%1' after prototype", tokens[offset]);
|
package/src/koffi/src/util.cc
CHANGED
|
@@ -345,6 +345,14 @@ const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size
|
|
|
345
345
|
return MakeArrayType(instance, ref, len, hint, false);
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
+
Napi::External<TypeInfo> WrapType(Napi::Env env, InstanceData *instance, const TypeInfo *type)
|
|
349
|
+
{
|
|
350
|
+
Napi::External<TypeInfo> external = Napi::External<TypeInfo>::New(env, (TypeInfo *)type);
|
|
351
|
+
SetValueTag(instance, external, &TypeInfoMarker);
|
|
352
|
+
|
|
353
|
+
return external;
|
|
354
|
+
}
|
|
355
|
+
|
|
348
356
|
bool CanPassType(const TypeInfo *type, int directions)
|
|
349
357
|
{
|
|
350
358
|
if (directions & 2) {
|
|
@@ -1041,7 +1049,8 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1041
1049
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1042
1050
|
|
|
1043
1051
|
if (len && type->primitive != PrimitiveKind::String &&
|
|
1044
|
-
type->primitive != PrimitiveKind::String16
|
|
1052
|
+
type->primitive != PrimitiveKind::String16 &&
|
|
1053
|
+
type->primitive != PrimitiveKind::Prototype) {
|
|
1045
1054
|
if (*len >= 0) {
|
|
1046
1055
|
type = MakeArrayType(instance, type, *len);
|
|
1047
1056
|
} else {
|
|
@@ -1144,8 +1153,28 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1144
1153
|
} break;
|
|
1145
1154
|
|
|
1146
1155
|
case PrimitiveKind::Prototype: {
|
|
1147
|
-
|
|
1148
|
-
|
|
1156
|
+
const FunctionInfo *proto = type->ref.proto;
|
|
1157
|
+
RG_ASSERT(!proto->variadic);
|
|
1158
|
+
RG_ASSERT(!proto->lib);
|
|
1159
|
+
|
|
1160
|
+
FunctionInfo *func = new FunctionInfo();
|
|
1161
|
+
RG_DEFER { func->Unref(); };
|
|
1162
|
+
|
|
1163
|
+
memcpy((void *)func, proto, RG_SIZE(*proto));
|
|
1164
|
+
memset((void *)&func->parameters, 0, RG_SIZE(func->parameters));
|
|
1165
|
+
func->parameters = proto->parameters;
|
|
1166
|
+
|
|
1167
|
+
func->name = "<anonymous>";
|
|
1168
|
+
func->native = (void *)ptr;
|
|
1169
|
+
|
|
1170
|
+
// Fix back parameter offset
|
|
1171
|
+
for (ParameterInfo ¶m: func->parameters) {
|
|
1172
|
+
param.offset -= 2;
|
|
1173
|
+
}
|
|
1174
|
+
func->required_parameters -= 2;
|
|
1175
|
+
|
|
1176
|
+
Napi::Function wrapper = WrapFunction(env, func);
|
|
1177
|
+
return wrapper;
|
|
1149
1178
|
} break;
|
|
1150
1179
|
}
|
|
1151
1180
|
|
|
@@ -1155,6 +1184,48 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1155
1184
|
return env.Null();
|
|
1156
1185
|
}
|
|
1157
1186
|
|
|
1187
|
+
Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func)
|
|
1188
|
+
{
|
|
1189
|
+
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1190
|
+
|
|
1191
|
+
Napi::Function wrapper;
|
|
1192
|
+
if (func->variadic) {
|
|
1193
|
+
Napi::Function::Callback call = TranslateVariadicCall;
|
|
1194
|
+
wrapper = Napi::Function::New(env, call, func->name, (void *)func->Ref());
|
|
1195
|
+
} else {
|
|
1196
|
+
Napi::Function::Callback call = TranslateNormalCall;
|
|
1197
|
+
wrapper = Napi::Function::New(env, call, func->name, (void *)func->Ref());
|
|
1198
|
+
}
|
|
1199
|
+
wrapper.AddFinalizer([](Napi::Env, FunctionInfo *func) { func->Unref(); }, (FunctionInfo *)func);
|
|
1200
|
+
|
|
1201
|
+
if (!func->variadic) {
|
|
1202
|
+
Napi::Function::Callback call = TranslateAsyncCall;
|
|
1203
|
+
Napi::Function async = Napi::Function::New(env, call, func->name, (void *)func->Ref());
|
|
1204
|
+
|
|
1205
|
+
async.AddFinalizer([](Napi::Env, FunctionInfo *func) { func->Unref(); }, (FunctionInfo *)func);
|
|
1206
|
+
wrapper.Set("async", async);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
// Create info object
|
|
1210
|
+
{
|
|
1211
|
+
Napi::Object meta = Napi::Object::New(env);
|
|
1212
|
+
Napi::Array arguments = Napi::Array::New(env, func->parameters.len);
|
|
1213
|
+
|
|
1214
|
+
meta.Set("name", Napi::String::New(env, func->name));
|
|
1215
|
+
meta.Set("arguments", arguments);
|
|
1216
|
+
meta.Set("result", WrapType(env, instance, func->ret.type));
|
|
1217
|
+
|
|
1218
|
+
for (Size i = 0; i < func->parameters.len; i++) {
|
|
1219
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
1220
|
+
arguments.Set((uint32_t)i, WrapType(env, instance, param.type));
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
wrapper.Set("info", meta);
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
return wrapper;
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1158
1229
|
static int AnalyseFlatRec(const TypeInfo *type, int offset, int count, FunctionRef<void(const TypeInfo *type, int offset, int count)> func)
|
|
1159
1230
|
{
|
|
1160
1231
|
if (type->primitive == PrimitiveKind::Record) {
|
package/src/koffi/src/util.hh
CHANGED
|
@@ -93,6 +93,8 @@ const TypeInfo *MakePointerType(InstanceData *instance, const TypeInfo *ref, int
|
|
|
93
93
|
const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len);
|
|
94
94
|
const TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len, ArrayHint hint);
|
|
95
95
|
|
|
96
|
+
Napi::External<TypeInfo> WrapType(Napi::Env env, InstanceData *instance, const TypeInfo *type);
|
|
97
|
+
|
|
96
98
|
bool CanPassType(const TypeInfo *type, int directions);
|
|
97
99
|
bool CanReturnType(const TypeInfo *type);
|
|
98
100
|
bool CanStoreType(const TypeInfo *type);
|
|
@@ -185,6 +187,8 @@ static inline Napi::Value NewBigInt(Napi::Env env, uint64_t value)
|
|
|
185
187
|
}
|
|
186
188
|
}
|
|
187
189
|
|
|
190
|
+
Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func);
|
|
191
|
+
|
|
188
192
|
int AnalyseFlat(const TypeInfo *type, FunctionRef<void(const TypeInfo *type, int offset, int count)> func);
|
|
189
193
|
|
|
190
194
|
void DumpMemory(const char *type, Span<const uint8_t> bytes);
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|