koffi 2.12.4 → 2.12.5-beta.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/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_armhf/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_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/doc/pages/contribute.md +1 -1
- package/index.d.ts +19 -13
- package/index.js +8 -9
- package/indirect.js +8 -9
- package/package.json +1 -2
- package/src/koffi/src/ffi.cc +59 -35
- package/src/koffi/src/parser.cc +18 -21
- package/src/koffi/src/parser.hh +2 -3
|
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/doc/pages/contribute.md
CHANGED
|
@@ -123,7 +123,7 @@ node qemu.js info debian_x64
|
|
|
123
123
|
|
|
124
124
|
First, you must update the code in three steps:
|
|
125
125
|
|
|
126
|
-
- Change the version
|
|
126
|
+
- Change the version number in `package.json`
|
|
127
127
|
- Add an entry to `CHANGELOG` to summarize the changes since last release
|
|
128
128
|
- Commit theses changes with the message *Bump Koffi to X.Y.Z*
|
|
129
129
|
|
package/index.d.ts
CHANGED
|
@@ -82,14 +82,14 @@ export interface IKoffiLib {
|
|
|
82
82
|
unload(): void;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
export function struct(name: string, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
85
|
+
export function struct(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
86
86
|
export function struct(ref: IKoffiCType, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
87
87
|
export function struct(def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
88
|
-
export function pack(name: string, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
88
|
+
export function pack(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
89
89
|
export function pack(ref: IKoffiCType, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
90
90
|
export function pack(def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
91
91
|
|
|
92
|
-
export function union(name: string, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
92
|
+
export function union(name: string | null | undefined, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
93
93
|
export function union(ref: IKoffiCType, def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
94
94
|
export function union(def: Record<string, TypeSpecWithAlignment>): IKoffiCType;
|
|
95
95
|
|
|
@@ -100,28 +100,34 @@ export class Union {
|
|
|
100
100
|
|
|
101
101
|
export function array(ref: TypeSpec, len: number, hint?: ArrayHint | null): IKoffiCType;
|
|
102
102
|
|
|
103
|
-
export function opaque(name: string): IKoffiCType;
|
|
103
|
+
export function opaque(name: string | null | undefined): IKoffiCType;
|
|
104
104
|
export function opaque(): IKoffiCType;
|
|
105
|
-
/** @deprecated */ export function handle(name: string): IKoffiCType;
|
|
105
|
+
/** @deprecated */ export function handle(name: string | null | undefined): IKoffiCType;
|
|
106
106
|
/** @deprecated */ export function handle(): IKoffiCType;
|
|
107
107
|
|
|
108
108
|
export function pointer(ref: TypeSpec): IKoffiCType;
|
|
109
|
-
export function pointer(ref: TypeSpec,
|
|
110
|
-
export function pointer(name: string, ref: TypeSpec
|
|
109
|
+
export function pointer(ref: TypeSpec, count: number): IKoffiCType;
|
|
110
|
+
export function pointer(name: string | null | undefined, ref: TypeSpec): IKoffiCType;
|
|
111
|
+
export function pointer(name: string | null | undefined, ref: TypeSpec, count: number): IKoffiCType;
|
|
111
112
|
|
|
112
113
|
export function out(type: TypeSpec): IKoffiCType;
|
|
113
114
|
export function inout(type: TypeSpec): IKoffiCType;
|
|
114
115
|
|
|
115
116
|
export function disposable(type: TypeSpec): IKoffiCType;
|
|
116
|
-
export function disposable(
|
|
117
|
-
export function disposable(name: string, type: TypeSpec
|
|
117
|
+
export function disposable(type: TypeSpec, freeFunction: Function): IKoffiCType;
|
|
118
|
+
export function disposable(name: string | null | undefined, type: TypeSpec): IKoffiCType;
|
|
119
|
+
export function disposable(name: string | null | undefined, type: TypeSpec, freeFunction: Function): IKoffiCType;
|
|
118
120
|
|
|
119
121
|
export function proto(definition: string): IKoffiCType;
|
|
120
|
-
export function proto(
|
|
121
|
-
export function proto(convention: string,
|
|
122
|
+
export function proto(result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
123
|
+
export function proto(convention: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
124
|
+
export function proto(name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
125
|
+
export function proto(convention: string, name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
122
126
|
/** @deprecated */ export function callback(definition: string): IKoffiCType;
|
|
123
|
-
/** @deprecated */ export function callback(
|
|
124
|
-
/** @deprecated */ export function callback(convention: string,
|
|
127
|
+
/** @deprecated */ export function callback(result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
128
|
+
/** @deprecated */ export function callback(convention: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
129
|
+
/** @deprecated */ export function callback(name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
130
|
+
/** @deprecated */ export function callback(convention: string, name: string | null | undefined, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
|
|
125
131
|
|
|
126
132
|
export function register(callback: Function, type: TypeSpec): IKoffiRegisteredCallback;
|
|
127
133
|
export function register(thisValue: any, callback: Function, type: TypeSpec): IKoffiRegisteredCallback;
|
package/index.js
CHANGED
|
@@ -4,9 +4,9 @@ var __commonJS = (cb, mod3) => function __require() {
|
|
|
4
4
|
return mod3 || (0, cb[__getOwnPropNames(cb)[0]])((mod3 = { exports: {} }).exports, mod3), mod3.exports;
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
//
|
|
7
|
+
// bin/Koffi/package/src/cnoke/src/tools.js
|
|
8
8
|
var require_tools = __commonJS({
|
|
9
|
-
"
|
|
9
|
+
"bin/Koffi/package/src/cnoke/src/tools.js"(exports2, module2) {
|
|
10
10
|
"use strict";
|
|
11
11
|
var crypto = require("crypto");
|
|
12
12
|
var fs2 = require("fs");
|
|
@@ -397,13 +397,12 @@ var require_tools = __commonJS({
|
|
|
397
397
|
}
|
|
398
398
|
});
|
|
399
399
|
|
|
400
|
-
//
|
|
400
|
+
// bin/Koffi/package/src/koffi/package.json
|
|
401
401
|
var require_package = __commonJS({
|
|
402
|
-
"
|
|
402
|
+
"bin/Koffi/package/src/koffi/package.json"(exports2, module2) {
|
|
403
403
|
module2.exports = {
|
|
404
404
|
name: "koffi",
|
|
405
|
-
version: "2.12.
|
|
406
|
-
stable: "2.12.4",
|
|
405
|
+
version: "2.12.5-beta.2",
|
|
407
406
|
description: "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
408
407
|
keywords: [
|
|
409
408
|
"foreign",
|
|
@@ -444,9 +443,9 @@ var require_package = __commonJS({
|
|
|
444
443
|
}
|
|
445
444
|
});
|
|
446
445
|
|
|
447
|
-
//
|
|
446
|
+
// bin/Koffi/package/src/koffi/src/init.js
|
|
448
447
|
var require_init = __commonJS({
|
|
449
|
-
"
|
|
448
|
+
"bin/Koffi/package/src/koffi/src/init.js"(exports, module) {
|
|
450
449
|
var fs = require("fs");
|
|
451
450
|
var path = require("path");
|
|
452
451
|
var util = require("util");
|
|
@@ -529,7 +528,7 @@ var require_init = __commonJS({
|
|
|
529
528
|
}
|
|
530
529
|
});
|
|
531
530
|
|
|
532
|
-
//
|
|
531
|
+
// bin/Koffi/package/src/koffi/index.js
|
|
533
532
|
var { detect: detect2, init: init2 } = require_init();
|
|
534
533
|
var triplet2 = detect2();
|
|
535
534
|
var native2 = null;
|
package/indirect.js
CHANGED
|
@@ -4,9 +4,9 @@ var __commonJS = (cb, mod3) => function __require() {
|
|
|
4
4
|
return mod3 || (0, cb[__getOwnPropNames(cb)[0]])((mod3 = { exports: {} }).exports, mod3), mod3.exports;
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
//
|
|
7
|
+
// bin/Koffi/package/src/cnoke/src/tools.js
|
|
8
8
|
var require_tools = __commonJS({
|
|
9
|
-
"
|
|
9
|
+
"bin/Koffi/package/src/cnoke/src/tools.js"(exports2, module2) {
|
|
10
10
|
"use strict";
|
|
11
11
|
var crypto = require("crypto");
|
|
12
12
|
var fs2 = require("fs");
|
|
@@ -397,13 +397,12 @@ var require_tools = __commonJS({
|
|
|
397
397
|
}
|
|
398
398
|
});
|
|
399
399
|
|
|
400
|
-
//
|
|
400
|
+
// bin/Koffi/package/src/koffi/package.json
|
|
401
401
|
var require_package = __commonJS({
|
|
402
|
-
"
|
|
402
|
+
"bin/Koffi/package/src/koffi/package.json"(exports2, module2) {
|
|
403
403
|
module2.exports = {
|
|
404
404
|
name: "koffi",
|
|
405
|
-
version: "2.12.
|
|
406
|
-
stable: "2.12.4",
|
|
405
|
+
version: "2.12.5-beta.2",
|
|
407
406
|
description: "Fast and simple C FFI (foreign function interface) for Node.js",
|
|
408
407
|
keywords: [
|
|
409
408
|
"foreign",
|
|
@@ -444,9 +443,9 @@ var require_package = __commonJS({
|
|
|
444
443
|
}
|
|
445
444
|
});
|
|
446
445
|
|
|
447
|
-
//
|
|
446
|
+
// bin/Koffi/package/src/koffi/src/init.js
|
|
448
447
|
var require_init = __commonJS({
|
|
449
|
-
"
|
|
448
|
+
"bin/Koffi/package/src/koffi/src/init.js"(exports, module) {
|
|
450
449
|
var fs = require("fs");
|
|
451
450
|
var path = require("path");
|
|
452
451
|
var util = require("util");
|
|
@@ -529,7 +528,7 @@ var require_init = __commonJS({
|
|
|
529
528
|
}
|
|
530
529
|
});
|
|
531
530
|
|
|
532
|
-
//
|
|
531
|
+
// bin/Koffi/package/src/koffi/indirect.js
|
|
533
532
|
var { detect: detect2, init: init2 } = require_init();
|
|
534
533
|
var triplet2 = detect2();
|
|
535
534
|
var mod2 = init2(triplet2, null);
|
package/package.json
CHANGED
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -242,24 +242,25 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
|
|
|
242
242
|
return env.Null();
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
bool
|
|
245
|
+
bool skip = (info.Length() > 1);
|
|
246
|
+
bool named = skip && !IsNullOrUndefined(info[0]);
|
|
246
247
|
bool redefine = named && CheckValueTag(instance, info[0], &TypeInfoMarker);
|
|
247
248
|
|
|
248
249
|
if (named && !info[0].IsString() && !redefine) {
|
|
249
250
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, info[0]));
|
|
250
251
|
return env.Null();
|
|
251
252
|
}
|
|
252
|
-
if (!IsObject(info[
|
|
253
|
+
if (!IsObject(info[skip])) {
|
|
253
254
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for members, expected object", GetValueType(instance, info[1]));
|
|
254
255
|
return env.Null();
|
|
255
256
|
}
|
|
256
257
|
|
|
257
258
|
Napi::String name = info[0].As<Napi::String>();
|
|
258
|
-
Napi::Object obj = info[
|
|
259
|
+
Napi::Object obj = info[skip].As<Napi::Object>();
|
|
259
260
|
Napi::Array keys = GetOwnPropertyNames(obj);
|
|
260
261
|
|
|
261
262
|
RG_DEFER_NC(err_guard, count = instance->types.count) {
|
|
262
|
-
Size start = count + !
|
|
263
|
+
Size start = count + !skip;
|
|
263
264
|
|
|
264
265
|
for (Size i = start; i < instance->types.count; i++) {
|
|
265
266
|
const TypeInfo *it = &instance->types[i];
|
|
@@ -409,24 +410,25 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
|
|
|
409
410
|
return env.Null();
|
|
410
411
|
}
|
|
411
412
|
|
|
412
|
-
bool
|
|
413
|
+
bool skip = (info.Length() > 1);
|
|
414
|
+
bool named = skip && !IsNullOrUndefined(info[0]);
|
|
413
415
|
bool redefine = named && CheckValueTag(instance, info[0], &TypeInfoMarker);
|
|
414
416
|
|
|
415
417
|
if (named && !info[0].IsString() && !redefine) {
|
|
416
418
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, info[0]));
|
|
417
419
|
return env.Null();
|
|
418
420
|
}
|
|
419
|
-
if (!IsObject(info[
|
|
421
|
+
if (!IsObject(info[skip])) {
|
|
420
422
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for members, expected object", GetValueType(instance, info[1]));
|
|
421
423
|
return env.Null();
|
|
422
424
|
}
|
|
423
425
|
|
|
424
426
|
Napi::String name = info[0].As<Napi::String>();
|
|
425
|
-
Napi::Object obj = info[
|
|
427
|
+
Napi::Object obj = info[skip].As<Napi::Object>();
|
|
426
428
|
Napi::Array keys = GetOwnPropertyNames(obj);
|
|
427
429
|
|
|
428
430
|
RG_DEFER_NC(err_guard, count = instance->types.count) {
|
|
429
|
-
Size start = count + !
|
|
431
|
+
Size start = count + !skip;
|
|
430
432
|
|
|
431
433
|
for (Size i = start; i < instance->types.count; i++) {
|
|
432
434
|
const TypeInfo *it = &instance->types[i];
|
|
@@ -584,7 +586,7 @@ static Napi::Value CreateOpaqueType(const Napi::CallbackInfo &info)
|
|
|
584
586
|
Napi::Env env = info.Env();
|
|
585
587
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
586
588
|
|
|
587
|
-
bool named = (info.Length() >= 1);
|
|
589
|
+
bool named = (info.Length() >= 1) && !IsNullOrUndefined(info[0]);
|
|
588
590
|
|
|
589
591
|
if (named && !info[0].IsString()) {
|
|
590
592
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, info[0]));
|
|
@@ -621,7 +623,8 @@ static Napi::Value CreatePointerType(const Napi::CallbackInfo &info)
|
|
|
621
623
|
return env.Null();
|
|
622
624
|
}
|
|
623
625
|
|
|
624
|
-
bool
|
|
626
|
+
bool skip = (info.Length() > 1) && !info[1].IsNumber();
|
|
627
|
+
bool named = skip && !IsNullOrUndefined(info[0]);
|
|
625
628
|
|
|
626
629
|
if (named && !info[0].IsString()) {
|
|
627
630
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, info[0]));
|
|
@@ -630,18 +633,18 @@ static Napi::Value CreatePointerType(const Napi::CallbackInfo &info)
|
|
|
630
633
|
|
|
631
634
|
std::string name = named ? info[0].As<Napi::String>() : std::string();
|
|
632
635
|
|
|
633
|
-
const TypeInfo *type = ResolveType(info[
|
|
636
|
+
const TypeInfo *type = ResolveType(info[skip]);
|
|
634
637
|
if (!type)
|
|
635
638
|
return env.Null();
|
|
636
639
|
|
|
637
640
|
int count = 0;
|
|
638
|
-
if (info.Length() >= 2u +
|
|
639
|
-
if (!info[1 +
|
|
640
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for count, expected number", GetValueType(instance, info[1 +
|
|
641
|
+
if (info.Length() >= 2u + skip) {
|
|
642
|
+
if (!info[1 + skip].IsNumber()) {
|
|
643
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for count, expected number", GetValueType(instance, info[1 + skip]));
|
|
641
644
|
return env.Null();
|
|
642
645
|
}
|
|
643
646
|
|
|
644
|
-
count = info[1 +
|
|
647
|
+
count = info[1 + skip].As<Napi::Number>();
|
|
645
648
|
|
|
646
649
|
if (count < 1 || count > 4) {
|
|
647
650
|
ThrowError<Napi::TypeError>(env, "Value of count must be between 1 and 4");
|
|
@@ -727,7 +730,8 @@ static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
|
|
|
727
730
|
return env.Null();
|
|
728
731
|
}
|
|
729
732
|
|
|
730
|
-
bool
|
|
733
|
+
bool skip = (info.Length() > 1) && !info[1].IsFunction();
|
|
734
|
+
bool named = skip && !IsNullOrUndefined(info[0]);
|
|
731
735
|
|
|
732
736
|
if (named && !info[0].IsString()) {
|
|
733
737
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, info[0]));
|
|
@@ -736,7 +740,7 @@ static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
|
|
|
736
740
|
|
|
737
741
|
Napi::String name = info[0].As<Napi::String>();
|
|
738
742
|
|
|
739
|
-
const TypeInfo *src = ResolveType(info[
|
|
743
|
+
const TypeInfo *src = ResolveType(info[skip]);
|
|
740
744
|
if (!src)
|
|
741
745
|
return env.Null();
|
|
742
746
|
if (src->primitive != PrimitiveKind::Pointer &&
|
|
@@ -753,8 +757,8 @@ static Napi::Value CreateDisposableType(const Napi::CallbackInfo &info)
|
|
|
753
757
|
|
|
754
758
|
DisposeFunc *dispose;
|
|
755
759
|
Napi::Function dispose_func;
|
|
756
|
-
if (info.Length() >= 2u +
|
|
757
|
-
Napi::Function func = info[1 +
|
|
760
|
+
if (info.Length() >= 2u + skip && !IsNullOrUndefined(info[1 + skip])) {
|
|
761
|
+
Napi::Function func = info[1 + skip].As<Napi::Function>();
|
|
758
762
|
|
|
759
763
|
if (!func.IsFunction()) {
|
|
760
764
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for func, expected function", GetValueType(instance, func));
|
|
@@ -989,8 +993,10 @@ static Napi::Value CreateArrayType(const Napi::CallbackInfo &info)
|
|
|
989
993
|
return WrapType(env, instance, type);
|
|
990
994
|
}
|
|
991
995
|
|
|
992
|
-
static bool ParseClassicFunction(const Napi::CallbackInfo &info, FunctionInfo *out_func)
|
|
996
|
+
static bool ParseClassicFunction(const Napi::CallbackInfo &info, bool concrete, FunctionInfo *out_func)
|
|
993
997
|
{
|
|
998
|
+
RG_ASSERT(info.Length() >= 2);
|
|
999
|
+
|
|
994
1000
|
Napi::Env env = info.Env();
|
|
995
1001
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
996
1002
|
|
|
@@ -1000,14 +1006,21 @@ static bool ParseClassicFunction(const Napi::CallbackInfo &info, FunctionInfo *o
|
|
|
1000
1006
|
|
|
1001
1007
|
// Detect optional call convention
|
|
1002
1008
|
if (name.IsString() && DetectCallConvention(name.Utf8Value().c_str(), &out_func->convention)) {
|
|
1003
|
-
if (info.Length() <
|
|
1004
|
-
ThrowError<Napi::TypeError>(env, "Expected 4 arguments, got %1", info.Length());
|
|
1009
|
+
if (info.Length() < 3) {
|
|
1010
|
+
ThrowError<Napi::TypeError>(env, "Expected 3 or 4 arguments, got %1", info.Length());
|
|
1005
1011
|
return false;
|
|
1006
1012
|
}
|
|
1007
1013
|
|
|
1008
1014
|
name = info[1u].As<Napi::String>();
|
|
1009
1015
|
ret = info[2u];
|
|
1010
|
-
parameters = info[3u].As<Napi::Array>();
|
|
1016
|
+
parameters = (info.Length() >= 4 ? info[3u] : env.Null()).As<Napi::Array>();
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
bool named = parameters.IsArray();
|
|
1020
|
+
|
|
1021
|
+
if (!named) {
|
|
1022
|
+
parameters = ret.As<Napi::Array>();
|
|
1023
|
+
ret = name;
|
|
1011
1024
|
}
|
|
1012
1025
|
|
|
1013
1026
|
#if defined(_WIN32)
|
|
@@ -1017,11 +1030,16 @@ static bool ParseClassicFunction(const Napi::CallbackInfo &info, FunctionInfo *o
|
|
|
1017
1030
|
}
|
|
1018
1031
|
#endif
|
|
1019
1032
|
if (!name.IsString()) {
|
|
1020
|
-
|
|
1021
|
-
|
|
1033
|
+
if (!concrete && IsNullOrUndefined(name)) {
|
|
1034
|
+
named = false;
|
|
1035
|
+
} else {
|
|
1036
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string or integer", GetValueType(instance, name));
|
|
1037
|
+
return false;
|
|
1038
|
+
}
|
|
1022
1039
|
}
|
|
1023
1040
|
|
|
1024
|
-
|
|
1041
|
+
// Leave anonymous naming responsibility to caller
|
|
1042
|
+
out_func->name = named ? DuplicateString(name.Utf8Value().c_str(), &instance->str_alloc).ptr : nullptr;
|
|
1025
1043
|
|
|
1026
1044
|
out_func->ret.type = ResolveType(ret);
|
|
1027
1045
|
if (!out_func->ret.type)
|
|
@@ -1085,8 +1103,8 @@ static Napi::Value CreateFunctionType(const Napi::CallbackInfo &info)
|
|
|
1085
1103
|
FunctionInfo *func = instance->callbacks.AppendDefault();
|
|
1086
1104
|
RG_DEFER_N(err_guard) { instance->callbacks.RemoveLast(1); };
|
|
1087
1105
|
|
|
1088
|
-
if (info.Length() >=
|
|
1089
|
-
if (!ParseClassicFunction(info, func))
|
|
1106
|
+
if (info.Length() >= 2) {
|
|
1107
|
+
if (!ParseClassicFunction(info, false, func))
|
|
1090
1108
|
return env.Null();
|
|
1091
1109
|
} else if (info.Length() >= 1) {
|
|
1092
1110
|
if (!info[0].IsString()) {
|
|
@@ -1095,13 +1113,19 @@ static Napi::Value CreateFunctionType(const Napi::CallbackInfo &info)
|
|
|
1095
1113
|
}
|
|
1096
1114
|
|
|
1097
1115
|
std::string proto = info[0u].As<Napi::String>();
|
|
1098
|
-
if (!ParsePrototype(env, proto.c_str(), func))
|
|
1116
|
+
if (!ParsePrototype(env, proto.c_str(), false, func))
|
|
1099
1117
|
return env.Null();
|
|
1100
1118
|
} else {
|
|
1101
|
-
ThrowError<Napi::TypeError>(env, "Expected 1
|
|
1119
|
+
ThrowError<Napi::TypeError>(env, "Expected 1 to 4 arguments, got %1", info.Length());
|
|
1102
1120
|
return env.Null();
|
|
1103
1121
|
}
|
|
1104
1122
|
|
|
1123
|
+
bool named = func->name;
|
|
1124
|
+
|
|
1125
|
+
if (!named) {
|
|
1126
|
+
func->name = Fmt(&instance->str_alloc, "<anonymous_%1>", instance->types.count).ptr;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1105
1129
|
if (!AnalyseFunction(env, instance, func))
|
|
1106
1130
|
return env.Null();
|
|
1107
1131
|
|
|
@@ -1112,7 +1136,7 @@ static Napi::Value CreateFunctionType(const Napi::CallbackInfo &info)
|
|
|
1112
1136
|
func->required_parameters += 2;
|
|
1113
1137
|
|
|
1114
1138
|
// We cannot fail after this check
|
|
1115
|
-
if (instance->types_map.Find(func->name)) {
|
|
1139
|
+
if (named && instance->types_map.Find(func->name)) {
|
|
1116
1140
|
ThrowError<Napi::Error>(env, "Duplicate type name '%1'", func->name);
|
|
1117
1141
|
return env.Null();
|
|
1118
1142
|
}
|
|
@@ -1648,8 +1672,8 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info)
|
|
|
1648
1672
|
|
|
1649
1673
|
func->lib = lib->Ref();
|
|
1650
1674
|
|
|
1651
|
-
if (info.Length() >=
|
|
1652
|
-
if (!ParseClassicFunction(info, func))
|
|
1675
|
+
if (info.Length() >= 2) {
|
|
1676
|
+
if (!ParseClassicFunction(info, true, func))
|
|
1653
1677
|
return env.Null();
|
|
1654
1678
|
} else if (info.Length() >= 1) {
|
|
1655
1679
|
if (!info[0].IsString()) {
|
|
@@ -1658,10 +1682,10 @@ static Napi::Value FindLibraryFunction(const Napi::CallbackInfo &info)
|
|
|
1658
1682
|
}
|
|
1659
1683
|
|
|
1660
1684
|
std::string proto = info[0u].As<Napi::String>();
|
|
1661
|
-
if (!ParsePrototype(env, proto.c_str(), func))
|
|
1685
|
+
if (!ParsePrototype(env, proto.c_str(), true, func))
|
|
1662
1686
|
return env.Null();
|
|
1663
1687
|
} else {
|
|
1664
|
-
ThrowError<Napi::TypeError>(env, "Expected 1
|
|
1688
|
+
ThrowError<Napi::TypeError>(env, "Expected 1 to 4 arguments, got %1", info.Length());
|
|
1665
1689
|
return env.Null();
|
|
1666
1690
|
}
|
|
1667
1691
|
|
package/src/koffi/src/parser.cc
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
namespace RG {
|
|
29
29
|
|
|
30
|
-
bool PrototypeParser::Parse(const char *str, FunctionInfo *out_func)
|
|
30
|
+
bool PrototypeParser::Parse(const char *str, bool concrete, FunctionInfo *out_func)
|
|
31
31
|
{
|
|
32
32
|
tokens.Clear();
|
|
33
33
|
offset = 0;
|
|
@@ -41,7 +41,21 @@ bool PrototypeParser::Parse(const char *str, FunctionInfo *out_func)
|
|
|
41
41
|
return false;
|
|
42
42
|
}
|
|
43
43
|
offset += (offset < tokens.len && DetectCallConvention(tokens[offset], &out_func->convention));
|
|
44
|
-
|
|
44
|
+
|
|
45
|
+
if (offset >= tokens.len) {
|
|
46
|
+
MarkError("Unexpected end of prototype, expected identifier");
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
if (IsIdentifier(tokens[offset])) {
|
|
50
|
+
Span<const char> tok = tokens[offset++];
|
|
51
|
+
out_func->name = DuplicateString(tok, &instance->str_alloc).ptr;
|
|
52
|
+
} else if (!concrete) {
|
|
53
|
+
// Leave anonymous naming responsibility to caller
|
|
54
|
+
out_func->name = nullptr;
|
|
55
|
+
} else {
|
|
56
|
+
MarkError("Unexpected token '%1', expected identifier", tokens[offset]);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
45
59
|
|
|
46
60
|
Consume("(");
|
|
47
61
|
offset += (offset + 1 < tokens.len && tokens[offset] == "void" && tokens[offset + 1] == ")");
|
|
@@ -169,23 +183,6 @@ const TypeInfo *PrototypeParser::ParseType(int *out_directions)
|
|
|
169
183
|
return instance->void_type;
|
|
170
184
|
}
|
|
171
185
|
|
|
172
|
-
const char *PrototypeParser::ParseIdentifier()
|
|
173
|
-
{
|
|
174
|
-
if (offset >= tokens.len) {
|
|
175
|
-
MarkError("Unexpected end of prototype, expected identifier");
|
|
176
|
-
return "";
|
|
177
|
-
}
|
|
178
|
-
if (!IsIdentifier(tokens[offset])) {
|
|
179
|
-
MarkError("Unexpected token '%1', expected identifier", tokens[offset]);
|
|
180
|
-
return "";
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
Span<const char> tok = tokens[offset++];
|
|
184
|
-
const char *ident = DuplicateString(tok, &instance->str_alloc).ptr;
|
|
185
|
-
|
|
186
|
-
return ident;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
186
|
bool PrototypeParser::Consume(const char *expect)
|
|
190
187
|
{
|
|
191
188
|
if (offset >= tokens.len) {
|
|
@@ -217,10 +214,10 @@ bool PrototypeParser::IsIdentifier(Span<const char> tok) const
|
|
|
217
214
|
return IsAsciiAlpha(tok[0]) || tok[0] == '_';
|
|
218
215
|
}
|
|
219
216
|
|
|
220
|
-
bool ParsePrototype(Napi::Env env, const char *str, FunctionInfo *out_func)
|
|
217
|
+
bool ParsePrototype(Napi::Env env, const char *str, bool concrete, FunctionInfo *out_func)
|
|
221
218
|
{
|
|
222
219
|
PrototypeParser parser(env);
|
|
223
|
-
return parser.Parse(str, out_func);
|
|
220
|
+
return parser.Parse(str, concrete, out_func);
|
|
224
221
|
}
|
|
225
222
|
|
|
226
223
|
}
|
package/src/koffi/src/parser.hh
CHANGED
|
@@ -44,13 +44,12 @@ class PrototypeParser {
|
|
|
44
44
|
public:
|
|
45
45
|
PrototypeParser(Napi::Env env) : env(env), instance(env.GetInstanceData<InstanceData>()) {}
|
|
46
46
|
|
|
47
|
-
bool Parse(const char *str, FunctionInfo *out_func);
|
|
47
|
+
bool Parse(const char *str, bool concrete, FunctionInfo *out_func);
|
|
48
48
|
|
|
49
49
|
private:
|
|
50
50
|
void Tokenize(const char *str);
|
|
51
51
|
|
|
52
52
|
const TypeInfo *ParseType(int *out_directions);
|
|
53
|
-
const char *ParseIdentifier();
|
|
54
53
|
|
|
55
54
|
bool Consume(const char *expect);
|
|
56
55
|
bool Match(const char *expect);
|
|
@@ -68,6 +67,6 @@ private:
|
|
|
68
67
|
}
|
|
69
68
|
};
|
|
70
69
|
|
|
71
|
-
bool ParsePrototype(Napi::Env env, const char *str, FunctionInfo *out_func);
|
|
70
|
+
bool ParsePrototype(Napi::Env env, const char *str, bool concrete, FunctionInfo *out_func);
|
|
72
71
|
|
|
73
72
|
}
|