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.
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
@@ -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 numbers in `package.json` (version and stable for stable releases)
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, asteriskCount?: number): IKoffiCType;
110
- export function pointer(name: string, ref: TypeSpec, asteriskCount?: number): IKoffiCType;
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(name: string, type: TypeSpec): IKoffiCType;
117
- export function disposable(name: string, type: TypeSpec, freeFunction: Function): IKoffiCType;
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(name: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
121
- export function proto(convention: string, name: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
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(name: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
124
- /** @deprecated */ export function callback(convention: string, name: string, result: TypeSpec, arguments: TypeSpec[]): IKoffiCType;
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
- // ../../bin/Koffi/package/src/cnoke/src/tools.js
7
+ // bin/Koffi/package/src/cnoke/src/tools.js
8
8
  var require_tools = __commonJS({
9
- "../../bin/Koffi/package/src/cnoke/src/tools.js"(exports2, module2) {
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
- // ../../bin/Koffi/package/src/koffi/package.json
400
+ // bin/Koffi/package/src/koffi/package.json
401
401
  var require_package = __commonJS({
402
- "../../bin/Koffi/package/src/koffi/package.json"(exports2, module2) {
402
+ "bin/Koffi/package/src/koffi/package.json"(exports2, module2) {
403
403
  module2.exports = {
404
404
  name: "koffi",
405
- version: "2.12.4",
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
- // ../../bin/Koffi/package/src/koffi/src/init.js
446
+ // bin/Koffi/package/src/koffi/src/init.js
448
447
  var require_init = __commonJS({
449
- "../../bin/Koffi/package/src/koffi/src/init.js"(exports, module) {
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
- // ../../bin/Koffi/package/src/koffi/index.js
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
- // ../../bin/Koffi/package/src/cnoke/src/tools.js
7
+ // bin/Koffi/package/src/cnoke/src/tools.js
8
8
  var require_tools = __commonJS({
9
- "../../bin/Koffi/package/src/cnoke/src/tools.js"(exports2, module2) {
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
- // ../../bin/Koffi/package/src/koffi/package.json
400
+ // bin/Koffi/package/src/koffi/package.json
401
401
  var require_package = __commonJS({
402
- "../../bin/Koffi/package/src/koffi/package.json"(exports2, module2) {
402
+ "bin/Koffi/package/src/koffi/package.json"(exports2, module2) {
403
403
  module2.exports = {
404
404
  name: "koffi",
405
- version: "2.12.4",
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
- // ../../bin/Koffi/package/src/koffi/src/init.js
446
+ // bin/Koffi/package/src/koffi/src/init.js
448
447
  var require_init = __commonJS({
449
- "../../bin/Koffi/package/src/koffi/src/init.js"(exports, module) {
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
- // ../../bin/Koffi/package/src/koffi/indirect.js
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
@@ -1,7 +1,6 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "2.12.4",
4
- "stable": "2.12.4",
3
+ "version": "2.12.5-beta.2",
5
4
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
6
5
  "keywords": [
7
6
  "foreign",
@@ -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 named = info.Length() > 1;
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[named])) {
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[named].As<Napi::Object>();
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 + !named;
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 named = info.Length() > 1;
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[named])) {
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[named].As<Napi::Object>();
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 + !named;
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 named = (info.Length() >= 2 && !info[1].IsNumber());
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[named]);
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 + named) {
639
- if (!info[1 + named].IsNumber()) {
640
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for count, expected number", GetValueType(instance, info[1 + named]));
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 + named].As<Napi::Number>();
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 named = (info.Length() >= 2 && !info[1].IsFunction());
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[named]);
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 + named && !IsNullOrUndefined(info[1 + named])) {
757
- Napi::Function func = info[1 + named].As<Napi::Function>();
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() < 4) {
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
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string or integer", GetValueType(instance, name));
1021
- return false;
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
- out_func->name = DuplicateString(name.ToString().Utf8Value().c_str(), &instance->str_alloc).ptr;
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() >= 3) {
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 or 3 arguments, got %1", info.Length());
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() >= 3) {
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 or 3 arguments, got %1", info.Length());
1688
+ ThrowError<Napi::TypeError>(env, "Expected 1 to 4 arguments, got %1", info.Length());
1665
1689
  return env.Null();
1666
1690
  }
1667
1691
 
@@ -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
- out_func->name = ParseIdentifier();
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
  }
@@ -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
  }