koffi 1.3.2 → 1.3.5

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.
Files changed (103) hide show
  1. package/CMakeLists.txt +27 -3
  2. package/ChangeLog.md +46 -14
  3. package/build/qemu/1.3.5/koffi_darwin_arm64.tar.gz +0 -0
  4. package/build/qemu/1.3.5/koffi_darwin_x64.tar.gz +0 -0
  5. package/build/qemu/1.3.5/koffi_freebsd_arm64.tar.gz +0 -0
  6. package/build/qemu/1.3.5/koffi_freebsd_ia32.tar.gz +0 -0
  7. package/build/qemu/1.3.5/koffi_freebsd_x64.tar.gz +0 -0
  8. package/build/qemu/1.3.5/koffi_linux_arm32hf.tar.gz +0 -0
  9. package/build/qemu/1.3.5/koffi_linux_arm64.tar.gz +0 -0
  10. package/build/qemu/1.3.5/koffi_linux_ia32.tar.gz +0 -0
  11. package/build/qemu/1.3.5/koffi_linux_riscv64hf64.tar.gz +0 -0
  12. package/build/qemu/1.3.5/koffi_linux_x64.tar.gz +0 -0
  13. package/build/qemu/1.3.5/koffi_openbsd_ia32.tar.gz +0 -0
  14. package/build/qemu/1.3.5/koffi_openbsd_x64.tar.gz +0 -0
  15. package/build/qemu/1.3.5/koffi_win32_arm64.tar.gz +0 -0
  16. package/build/qemu/1.3.5/koffi_win32_ia32.tar.gz +0 -0
  17. package/build/qemu/1.3.5/koffi_win32_x64.tar.gz +0 -0
  18. package/doc/_static/perf_linux_20220623.png +0 -0
  19. package/doc/_static/perf_linux_20220623_2.png +0 -0
  20. package/doc/_static/perf_windows_20220623.png +0 -0
  21. package/doc/_static/perf_windows_20220623_2.png +0 -0
  22. package/doc/benchmarks.md +40 -36
  23. package/doc/benchmarks.xlsx +0 -0
  24. package/doc/changes.md +2 -0
  25. package/doc/conf.py +10 -3
  26. package/doc/contribute.md +16 -0
  27. package/doc/dist/doctrees/benchmarks.doctree +0 -0
  28. package/doc/dist/doctrees/changes.doctree +0 -0
  29. package/doc/dist/doctrees/contribute.doctree +0 -0
  30. package/doc/dist/doctrees/environment.pickle +0 -0
  31. package/doc/dist/doctrees/functions.doctree +0 -0
  32. package/doc/dist/doctrees/index.doctree +0 -0
  33. package/doc/dist/doctrees/memory.doctree +0 -0
  34. package/doc/dist/doctrees/platforms.doctree +0 -0
  35. package/doc/dist/doctrees/start.doctree +0 -0
  36. package/doc/dist/doctrees/types.doctree +0 -0
  37. package/doc/dist/html/_sources/benchmarks.md.txt +40 -36
  38. package/doc/dist/html/_sources/changes.md.txt +2 -0
  39. package/doc/dist/html/_sources/contribute.md.txt +16 -0
  40. package/doc/dist/html/_sources/functions.md.txt +18 -14
  41. package/doc/dist/html/_sources/index.rst.txt +2 -1
  42. package/doc/dist/html/_sources/memory.md.txt +6 -3
  43. package/doc/dist/html/_sources/platforms.md.txt +2 -0
  44. package/doc/dist/html/_sources/start.md.txt +3 -3
  45. package/doc/dist/html/_sources/types.md.txt +10 -8
  46. package/doc/dist/html/_static/perf_linux_20220623.png +0 -0
  47. package/doc/dist/html/_static/perf_linux_20220623_2.png +0 -0
  48. package/doc/dist/html/_static/perf_windows_20220623.png +0 -0
  49. package/doc/dist/html/_static/perf_windows_20220623_2.png +0 -0
  50. package/doc/dist/html/_static/pygments.css +54 -54
  51. package/doc/dist/html/benchmarks.html +52 -20
  52. package/doc/dist/html/changes.html +391 -0
  53. package/doc/dist/html/contribute.html +24 -2
  54. package/doc/dist/html/functions.html +83 -84
  55. package/doc/dist/html/genindex.html +1 -0
  56. package/doc/dist/html/index.html +18 -3
  57. package/doc/dist/html/memory.html +11 -5
  58. package/doc/dist/html/objects.inv +0 -0
  59. package/doc/dist/html/platforms.html +3 -1
  60. package/doc/dist/html/search.html +1 -0
  61. package/doc/dist/html/searchindex.js +1 -1
  62. package/doc/dist/html/start.html +48 -47
  63. package/doc/dist/html/types.html +161 -159
  64. package/doc/functions.md +18 -14
  65. package/doc/index.rst +2 -1
  66. package/doc/memory.md +6 -3
  67. package/doc/platforms.md +2 -0
  68. package/doc/start.md +3 -3
  69. package/doc/types.md +10 -8
  70. package/package.json +2 -2
  71. package/qemu/qemu.js +1 -0
  72. package/qemu/registry/machines.json +6 -11
  73. package/src/abi_arm32.cc +9 -9
  74. package/src/abi_arm64.cc +9 -9
  75. package/src/abi_riscv64.cc +9 -9
  76. package/src/abi_x64_sysv.cc +9 -9
  77. package/src/abi_x64_win.cc +9 -9
  78. package/src/abi_x86.cc +9 -9
  79. package/src/call.cc +8 -7
  80. package/src/call.hh +6 -0
  81. package/src/ffi.cc +73 -22
  82. package/src/ffi.hh +11 -4
  83. package/src/parser.cc +1 -1
  84. package/src/util.hh +21 -1
  85. package/test/async.js +1 -1
  86. package/test/misc.c +20 -0
  87. package/test/sync.js +13 -3
  88. package/vendor/libcc/libcc.hh +1 -1
  89. package/build/qemu/1.3.2/koffi_darwin_arm64.tar.gz +0 -0
  90. package/build/qemu/1.3.2/koffi_darwin_x64.tar.gz +0 -0
  91. package/build/qemu/1.3.2/koffi_freebsd_arm64.tar.gz +0 -0
  92. package/build/qemu/1.3.2/koffi_freebsd_ia32.tar.gz +0 -0
  93. package/build/qemu/1.3.2/koffi_freebsd_x64.tar.gz +0 -0
  94. package/build/qemu/1.3.2/koffi_linux_arm32hf.tar.gz +0 -0
  95. package/build/qemu/1.3.2/koffi_linux_arm64.tar.gz +0 -0
  96. package/build/qemu/1.3.2/koffi_linux_ia32.tar.gz +0 -0
  97. package/build/qemu/1.3.2/koffi_linux_riscv64hf64.tar.gz +0 -0
  98. package/build/qemu/1.3.2/koffi_linux_x64.tar.gz +0 -0
  99. package/build/qemu/1.3.2/koffi_openbsd_ia32.tar.gz +0 -0
  100. package/build/qemu/1.3.2/koffi_openbsd_x64.tar.gz +0 -0
  101. package/build/qemu/1.3.2/koffi_win32_arm64.tar.gz +0 -0
  102. package/build/qemu/1.3.2/koffi_win32_ia32.tar.gz +0 -0
  103. package/build/qemu/1.3.2/koffi_win32_x64.tar.gz +0 -0
package/src/ffi.cc CHANGED
@@ -43,7 +43,7 @@ namespace RG {
43
43
  // Value does not matter, the tag system uses memory addresses
44
44
  const int TypeInfoMarker = 0xDEADBEEF;
45
45
 
46
- static bool ChangeMemorySize(Napi::Value value, Size *out_size)
46
+ static bool ChangeMemorySize(const char *name, Napi::Value value, Size *out_size)
47
47
  {
48
48
  const Size MinSize = Kibibytes(1);
49
49
  const Size MaxSize = Mebibytes(16);
@@ -51,14 +51,16 @@ static bool ChangeMemorySize(Napi::Value value, Size *out_size)
51
51
  Napi::Env env = value.Env();
52
52
 
53
53
  if (!value.IsNumber()) {
54
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for memory size, expected number");
55
- return env.Null();
54
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
55
+
56
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for '%2', expected number", GetValueType(instance, value), name);
57
+ return false;
56
58
  }
57
59
 
58
60
  int64_t size = value.As<Napi::Number>().Int64Value();
59
61
 
60
62
  if (size < MinSize || size > MaxSize) {
61
- ThrowError<Napi::Error>(env, "Memory size must be between %1 and %2", FmtMemSize(MinSize), FmtMemSize(MaxSize));
63
+ ThrowError<Napi::Error>(env, "Setting '%1' must be between %2 and %3", name, FmtMemSize(MinSize), FmtMemSize(MaxSize));
62
64
  return false;
63
65
  }
64
66
 
@@ -66,6 +68,28 @@ static bool ChangeMemorySize(Napi::Value value, Size *out_size)
66
68
  return true;
67
69
  }
68
70
 
71
+ static bool ChangeAsyncLimit(const char *name, Napi::Value value, int max, int *out_limit)
72
+ {
73
+ Napi::Env env = value.Env();
74
+
75
+ if (!value.IsNumber()) {
76
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
77
+
78
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for '%2', expected number", GetValueType(instance, value), name);
79
+ return false;
80
+ }
81
+
82
+ int64_t n = value.As<Napi::Number>().Int64Value();
83
+
84
+ if (n < 0 || n > max) {
85
+ ThrowError<Napi::Error>(env, "Setting '%1' must be between 0 and %2", name, max);
86
+ return false;
87
+ }
88
+
89
+ *out_limit = (int)n;
90
+ return true;
91
+ }
92
+
69
93
  static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
70
94
  {
71
95
  Napi::Env env = info.Env();
@@ -82,6 +106,13 @@ static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
82
106
  return env.Null();
83
107
  }
84
108
 
109
+ Size sync_stack_size = instance->sync_stack_size;
110
+ Size sync_heap_size = instance->sync_heap_size;
111
+ Size async_stack_size = instance->async_stack_size;
112
+ Size async_heap_size = instance->async_heap_size;
113
+ int resident_async_pools = instance->resident_async_pools;
114
+ int max_async_calls = resident_async_pools + instance->max_temporaries;
115
+
85
116
  Napi::Object obj = info[0].As<Napi::Object>();
86
117
  Napi::Array keys = obj.GetPropertyNames();
87
118
 
@@ -90,38 +121,40 @@ static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
90
121
  Napi::Value value = obj[key];
91
122
 
92
123
  if (key == "sync_stack_size") {
93
- if (!ChangeMemorySize(value, &instance->sync_stack_size))
124
+ if (!ChangeMemorySize(key.c_str(), value, &sync_stack_size))
94
125
  return env.Null();
95
126
  } else if (key == "sync_heap_size") {
96
- if (!ChangeMemorySize(value, &instance->sync_heap_size))
127
+ if (!ChangeMemorySize(key.c_str(), value, &sync_heap_size))
97
128
  return env.Null();
98
129
  } else if (key == "async_stack_size") {
99
- if (!ChangeMemorySize(value, &instance->async_stack_size))
130
+ if (!ChangeMemorySize(key.c_str(), value, &async_stack_size))
100
131
  return env.Null();
101
132
  } else if (key == "async_heap_size") {
102
- if (!ChangeMemorySize(value, &instance->async_heap_size))
133
+ if (!ChangeMemorySize(key.c_str(), value, &async_heap_size))
103
134
  return env.Null();
104
135
  } else if (key == "resident_async_pools") {
105
- RG_STATIC_ASSERT(DefaultResidentAsyncPools <= RG_LEN(instance->memories.data));
106
-
107
- if (!value.IsNumber()) {
108
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for resident_async_pools, expected number");
136
+ if (!ChangeAsyncLimit(key.c_str(), value, RG_LEN(instance->memories.data) - 1, &resident_async_pools))
109
137
  return env.Null();
110
- }
111
-
112
- int64_t n = value.As<Napi::Number>().Int64Value();
113
-
114
- if (n < 0 || n > RG_LEN(instance->memories.data)) {
115
- ThrowError<Napi::Error>(env, "Parameter resident_async_pools must be between 0 and %1", RG_LEN(instance->memories.data));
138
+ } else if (key == "max_async_calls") {
139
+ if (!ChangeAsyncLimit(key.c_str(), value, MaxAsyncCalls, &max_async_calls))
116
140
  return env.Null();
117
- }
118
-
119
- instance->resident_async_pools = (int)n;
120
141
  } else {
121
142
  ThrowError<Napi::Error>(env, "Unexpected config member '%1'", key.c_str());
122
143
  return env.Null();
123
144
  }
124
145
  }
146
+
147
+ if (max_async_calls < resident_async_pools) {
148
+ ThrowError<Napi::Error>(env, "Setting max_async_calls must be >= to resident_async_pools");
149
+ return env.Null();
150
+ }
151
+
152
+ instance->sync_stack_size = sync_stack_size;
153
+ instance->sync_heap_size = sync_heap_size;
154
+ instance->async_stack_size = async_stack_size;
155
+ instance->async_heap_size = async_heap_size;
156
+ instance->resident_async_pools = resident_async_pools;
157
+ instance->max_temporaries = max_async_calls - resident_async_pools;
125
158
  }
126
159
 
127
160
  Napi::Object obj = Napi::Object::New(env);
@@ -131,6 +164,7 @@ static Napi::Value GetSetConfig(const Napi::CallbackInfo &info)
131
164
  obj.Set("async_stack_size", instance->async_stack_size);
132
165
  obj.Set("async_heap_size", instance->async_heap_size);
133
166
  obj.Set("resident_async_pools", instance->resident_async_pools);
167
+ obj.Set("max_async_calls", instance->resident_async_pools + instance->max_temporaries);
134
168
 
135
169
  return obj;
136
170
  }
@@ -616,6 +650,9 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
616
650
  return mem;
617
651
  }
618
652
 
653
+ if (RG_UNLIKELY(instance->temporaries >= instance->max_temporaries))
654
+ return nullptr;
655
+
619
656
  InstanceMemory *mem = new InstanceMemory();
620
657
 
621
658
  mem->stack.len = stack_size;
@@ -628,6 +665,11 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
628
665
  #endif
629
666
  RG_CRITICAL(mem->stack.ptr, "Failed to allocate %1 of memory", mem->stack.len);
630
667
 
668
+ #ifdef __OpenBSD__
669
+ // Make sure the SP points inside the MAP_STACK area, or (void) functions may crash on OpenBSD i386
670
+ mem->stack.len -= 16;
671
+ #endif
672
+
631
673
  mem->heap.len = heap_size;
632
674
  #ifdef _WIN32
633
675
  mem->heap.ptr = (uint8_t *)VirtualAlloc(nullptr, mem->heap.len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
@@ -636,9 +678,13 @@ static InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, S
636
678
  #endif
637
679
  RG_CRITICAL(mem->heap.ptr, "Failed to allocate %1 of memory", mem->heap.len);
638
680
 
681
+ mem->depth = 0;
682
+
639
683
  if (instance->memories.len <= instance->resident_async_pools) {
640
684
  instance->memories.Append(mem);
685
+ mem->temporary = false;
641
686
  } else {
687
+ instance->temporaries++;
642
688
  mem->temporary = true;
643
689
  }
644
690
 
@@ -804,11 +850,15 @@ static Napi::Value TranslateAsyncCall(const Napi::CallbackInfo &info)
804
850
  Napi::Function callback = info[(uint32_t)func->parameters.len].As<Napi::Function>();
805
851
 
806
852
  if (!callback.IsFunction()) {
807
- ThrowError<Napi::TypeError>(env, "Expected callback function as last arguments, got %1", GetValueType(instance, callback));
853
+ ThrowError<Napi::TypeError>(env, "Expected callback function as last argument, got %1", GetValueType(instance, callback));
808
854
  return env.Null();
809
855
  }
810
856
 
811
857
  InstanceMemory *mem = AllocateMemory(instance, instance->async_stack_size, instance->async_heap_size);
858
+ if (RG_UNLIKELY(!mem)) {
859
+ ThrowError<Napi::Error>(env, "Too many asynchronous calls are running");
860
+ return env.Null();
861
+ }
812
862
  AsyncCall *async = new AsyncCall(env, instance, func, mem, callback);
813
863
 
814
864
  if (async->Prepare(info) && instance->debug) {
@@ -917,6 +967,7 @@ static Napi::Value LoadSharedLibrary(const Napi::CallbackInfo &info)
917
967
 
918
968
  if (!instance->memories.len) {
919
969
  AllocateMemory(instance, instance->sync_stack_size, instance->sync_heap_size);
970
+ RG_ASSERT(instance->memories.len);
920
971
  }
921
972
 
922
973
  // Load shared library
package/src/ffi.hh CHANGED
@@ -21,10 +21,12 @@ namespace RG {
21
21
 
22
22
  static const Size DefaultSyncStackSize = Mebibytes(1);
23
23
  static const Size DefaultSyncHeapSize = Mebibytes(2);
24
- static const Size DefaultAsyncStackSize = Kibibytes(512);
25
- static const Size DefaultAsyncHeapSize = Mebibytes(1);
24
+ static const Size DefaultAsyncStackSize = Kibibytes(256);
25
+ static const Size DefaultAsyncHeapSize = Kibibytes(512);
26
26
  static const int DefaultResidentAsyncPools = 2;
27
+ static const int DefaultMaxAsyncCalls = 64;
27
28
 
29
+ static const int MaxAsyncCalls = 256;
28
30
  static const Size MaxParameters = 32;
29
31
  static const Size MaxOutParameters = 4;
30
32
  static const Size MaxTrampolines = 16;
@@ -216,7 +218,8 @@ struct InstanceData {
216
218
  bool debug;
217
219
  uint64_t tag_lower;
218
220
 
219
- LocalArray<InstanceMemory *, 16> memories;
221
+ LocalArray<InstanceMemory *, 9> memories;
222
+ int temporaries = 0;
220
223
 
221
224
  TrampolineInfo trampolines[MaxTrampolines];
222
225
  uint32_t free_trampolines = UINT32_MAX;
@@ -228,7 +231,11 @@ struct InstanceData {
228
231
  Size async_stack_size = DefaultAsyncStackSize;
229
232
  Size async_heap_size = DefaultAsyncHeapSize;
230
233
  int resident_async_pools = DefaultResidentAsyncPools;
234
+ int max_temporaries = DefaultMaxAsyncCalls - DefaultResidentAsyncPools;
231
235
  };
232
- RG_STATIC_ASSERT(MaxTrampolines <= 32);
236
+ RG_STATIC_ASSERT(DefaultResidentAsyncPools <= RG_LEN(InstanceData::memories.data) - 1);
237
+ RG_STATIC_ASSERT(DefaultMaxAsyncCalls >= DefaultResidentAsyncPools);
238
+ RG_STATIC_ASSERT(MaxAsyncCalls >= DefaultMaxAsyncCalls);
239
+ RG_STATIC_ASSERT(MaxTrampolines <= 16);
233
240
 
234
241
  }
package/src/parser.cc CHANGED
@@ -44,7 +44,7 @@ bool PrototypeParser::Parse(const char *str, FunctionInfo *out_func)
44
44
  out_func->name = ParseIdentifier();
45
45
 
46
46
  Consume("(");
47
- if (offset < tokens.len && tokens[offset] != ")") {
47
+ if (offset < tokens.len && tokens[offset] != ")" && !Match("void")) {
48
48
  for (;;) {
49
49
  ParameterInfo param = {};
50
50
 
package/src/util.hh CHANGED
@@ -89,7 +89,7 @@ static inline bool IsObject(Napi::Value value)
89
89
  int GetTypedArrayType(const TypeInfo *type);
90
90
 
91
91
  template <typename T>
92
- T CopyNumber(const Napi::Value &value)
92
+ T CopyNumber(Napi::Value value)
93
93
  {
94
94
  RG_ASSERT(value.IsNumber() || value.IsBigInt());
95
95
 
@@ -105,6 +105,26 @@ T CopyNumber(const Napi::Value &value)
105
105
  RG_UNREACHABLE();
106
106
  }
107
107
 
108
+ static inline Napi::Value NewBigInt(Napi::Env env, int64_t value)
109
+ {
110
+ if (value <= 9007199254740992ll && value >= -9007199254740992ll) {
111
+ double d = (double)value;
112
+ return Napi::Number::New(env, d);
113
+ } else {
114
+ return Napi::BigInt::New(env, value);
115
+ }
116
+ }
117
+
118
+ static inline Napi::Value NewBigInt(Napi::Env env, uint64_t value)
119
+ {
120
+ if (value <= 9007199254740992ull) {
121
+ double d = (double)value;
122
+ return Napi::Number::New(env, d);
123
+ } else {
124
+ return Napi::BigInt::New(env, value);
125
+ }
126
+ }
127
+
108
128
  int AnalyseFlat(const TypeInfo *type, FunctionRef<void(const TypeInfo *type, int offset, int count)> func);
109
129
 
110
130
  int IsHFA(const TypeInfo *type, int min, int max);
package/test/async.js CHANGED
@@ -51,7 +51,7 @@ async function test() {
51
51
  let promises = [];
52
52
 
53
53
  // Issue several async calls
54
- for (let i = 0; i < 64; i++) {
54
+ for (let i = 0; i < 32; i++) {
55
55
  let p = new Promise((resolve, reject) => {
56
56
  try {
57
57
  ConcatenateToInt1.async(5, 6, 1, 2, 3, 9, 4, 4, 0, 6, 8, 7, (err, res) => {
package/test/misc.c CHANGED
@@ -129,6 +129,26 @@ typedef struct IntContainer {
129
129
  int len;
130
130
  } IntContainer;
131
131
 
132
+ EXPORT int8_t GetMinusOne1(void)
133
+ {
134
+ return -1;
135
+ }
136
+
137
+ EXPORT int16_t GetMinusOne2(void)
138
+ {
139
+ return -1;
140
+ }
141
+
142
+ EXPORT int32_t GetMinusOne4(void)
143
+ {
144
+ return -1;
145
+ }
146
+
147
+ EXPORT int64_t GetMinusOne8(void)
148
+ {
149
+ return -1;
150
+ }
151
+
132
152
  EXPORT void FillPack1(int a, Pack1 *p)
133
153
  {
134
154
  p->a = a;
package/test/sync.js CHANGED
@@ -122,6 +122,10 @@ async function test() {
122
122
  let lib_filename = path.dirname(__filename) + '/build/misc' + koffi.extension;
123
123
  let lib = koffi.load(lib_filename);
124
124
 
125
+ const GetMinusOne1 = lib.func('int8_t GetMinusOne1(void)');
126
+ const GetMinusOne2 = lib.func('int16_t GetMinusOne2(void)');
127
+ const GetMinusOne4 = lib.func('int32_t GetMinusOne4(void)');
128
+ const GetMinusOne8 = lib.func('int64_t GetMinusOne8(void)');
125
129
  const FillPack1 = lib.func('FillPack1', 'void', ['int', koffi.out(koffi.pointer(Pack1))]);
126
130
  const RetPack1 = lib.func('RetPack1', Pack1, ['int']);
127
131
  const AddPack1 = lib.fastcall('AddPack1', 'void', ['int', koffi.inout(koffi.pointer(Pack1))]);
@@ -172,6 +176,12 @@ async function test() {
172
176
  const FillRange = lib.func('void FillRange(int init, int step, _Out_ int *out, int len)');
173
177
  const MultiplyIntegers = lib.func('void MultiplyIntegers(int multiplier, _Inout_ int *values, int len)');
174
178
 
179
+ // Simple signed value returns
180
+ assert.equal(GetMinusOne1(), -1);
181
+ assert.equal(GetMinusOne2(), -1);
182
+ assert.equal(GetMinusOne4(), -1);
183
+ assert.equal(GetMinusOne8(), -1);
184
+
175
185
  // Simple tests with Pack1
176
186
  {
177
187
  let p = {};
@@ -250,9 +260,9 @@ async function test() {
250
260
 
251
261
  // Many parameters
252
262
  {
253
- assert.equal(ConcatenateToInt1(5, 6, 1, 2, 3, 9, 4, 4, 0, 6, 8, 7), 561239440687n);
254
- assert.equal(ConcatenateToInt4(5, 6, 1, 2, 3, 9, 4, 4, 0, 6, 8, 7), 561239440687n);
255
- assert.equal(ConcatenateToInt8(5, 6, 1, 2, 3, 9, 4, 4, 0, 6, 8, 7), 561239440687n);
263
+ assert.equal(ConcatenateToInt1(5, 6, 1, 2, 3, 9, 4, 4, 0, 6, 8, 7), 561239440687);
264
+ assert.equal(ConcatenateToInt4(5, 6, 1, 2, 3, 9, 4, 4, 0, 6, 8, 7), 561239440687);
265
+ assert.equal(ConcatenateToInt8(5, 6, 1, 2, 3, 9, 4, 4, 0, 6, 8, 7), 561239440687);
256
266
  assert.equal(ConcatenateToStr1(5, 6, 1, 2, 3, 9, 4, 4, {i: 0, j: 6, k: 8}, 7), '561239440687');
257
267
  assert.equal(ConcatenateToStr4(5, 6, 1, 2, 3, 9, 4, 4, {i: 0, j: 6, k: 8}, 7), '561239440687');
258
268
  assert.equal(ConcatenateToStr8(5, 6, 1, 2, 3, 9, 4, 4, {i: 0, j: 6, k: 8}, 7), '561239440687');
@@ -3049,7 +3049,7 @@ public:
3049
3049
 
3050
3050
  int repeat = 1;
3051
3051
  int pad_len = 0;
3052
- char pad_char;
3052
+ char pad_char = 0;
3053
3053
 
3054
3054
  FmtArg() = default;
3055
3055
  FmtArg(std::nullptr_t) : type(FmtType::Str1) { u.str1 = "(null)"; }