koffi 2.14.0 → 2.14.1
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/CHANGELOG.md +7 -1
- package/README.md +1 -1
- 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/index.md +43 -4
- package/doc/pages/platforms.md +8 -19
- package/doc/pages.ini +0 -7
- package/doc/static/perf_windows.png +0 -0
- package/index.js +3 -2
- package/indirect.js +3 -2
- package/package.json +3 -2
- package/src/cnoke/src/builder.js +1 -2
- package/src/core/base/base.cc +791 -555
- package/src/core/base/base.hh +577 -450
- package/src/core/base/crc.inc +1 -1
- package/src/core/base/crc_gen.py +1 -1
- package/src/core/base/unicode.inc +1 -1
- package/src/core/base/unicode_gen.py +1 -1
- package/src/koffi/src/abi_arm32.cc +24 -24
- package/src/koffi/src/abi_arm64.cc +29 -29
- package/src/koffi/src/abi_riscv64.cc +27 -27
- package/src/koffi/src/abi_x64_sysv.cc +29 -29
- package/src/koffi/src/abi_x64_win.cc +20 -20
- package/src/koffi/src/abi_x86.cc +26 -26
- package/src/koffi/src/call.cc +82 -236
- package/src/koffi/src/call.hh +6 -6
- package/src/koffi/src/ffi.cc +60 -60
- package/src/koffi/src/ffi.hh +9 -9
- package/src/koffi/src/parser.cc +2 -2
- package/src/koffi/src/parser.hh +1 -1
- package/src/koffi/src/trampolines/prototypes.inc +1 -1
- package/src/koffi/src/util.cc +43 -43
- package/src/koffi/src/util.hh +5 -5
- package/src/koffi/src/win32.cc +5 -5
- package/src/koffi/src/win32.hh +1 -1
package/src/koffi/src/call.cc
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
#include <napi.h>
|
|
28
28
|
|
|
29
|
-
namespace
|
|
29
|
+
namespace K {
|
|
30
30
|
|
|
31
31
|
struct RelayContext {
|
|
32
32
|
CallData *call;
|
|
@@ -49,8 +49,8 @@ CallData::CallData(Napi::Env env, InstanceData *instance, InstanceMemory *mem)
|
|
|
49
49
|
mem->generation += !mem->depth;
|
|
50
50
|
mem->depth++;
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
K_ASSERT(AlignUp(mem->stack.ptr, 16) == mem->stack.ptr);
|
|
53
|
+
K_ASSERT(AlignUp(mem->stack.end(), 16) == mem->stack.end());
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
CallData::~CallData()
|
|
@@ -77,8 +77,8 @@ void CallData::Dispose()
|
|
|
77
77
|
int16_t idx = used_trampolines[i];
|
|
78
78
|
TrampolineInfo *trampoline = &shared.trampolines[idx];
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
K_ASSERT(trampoline->instance == instance);
|
|
81
|
+
K_ASSERT(!trampoline->func.IsEmpty());
|
|
82
82
|
|
|
83
83
|
trampoline->instance = nullptr;
|
|
84
84
|
trampoline->func.Reset();
|
|
@@ -147,6 +147,7 @@ void CallData::RelayAsync(napi_env, napi_value, void *, void *udata)
|
|
|
147
147
|
|
|
148
148
|
bool CallData::PushString(Napi::Value value, int directions, const char **out_str)
|
|
149
149
|
{
|
|
150
|
+
// Fast path
|
|
150
151
|
if (value.IsString()) {
|
|
151
152
|
if (directions & 2) [[unlikely]] {
|
|
152
153
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, value));
|
|
@@ -155,62 +156,41 @@ bool CallData::PushString(Napi::Value value, int directions, const char **out_st
|
|
|
155
156
|
|
|
156
157
|
PushStringValue(value, out_str);
|
|
157
158
|
return true;
|
|
158
|
-
}
|
|
159
|
-
*out_str = nullptr;
|
|
160
|
-
return true;
|
|
161
|
-
} else if (value.IsArray()) {
|
|
162
|
-
Napi::Array array = value.As<Napi::Array>();
|
|
159
|
+
}
|
|
163
160
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
161
|
+
return PushPointer(value, instance->str_type, directions, (void **)out_str);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
bool CallData::PushString16(Napi::Value value, int directions, const char16_t **out_str16)
|
|
165
|
+
{
|
|
166
|
+
// Fast path
|
|
167
|
+
if (value.IsString()) {
|
|
168
|
+
if (directions & 2) [[unlikely]] {
|
|
169
169
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, value));
|
|
170
170
|
return false;
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
value
|
|
173
|
+
PushString16Value(value, out_str16);
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
174
176
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
177
|
+
return PushPointer(value, instance->str16_type, directions, (void **)out_str16);
|
|
178
|
+
}
|
|
179
179
|
|
|
180
|
-
|
|
181
|
-
|
|
180
|
+
bool CallData::PushString32(Napi::Value value, int directions, const char32_t **out_str32)
|
|
181
|
+
{
|
|
182
|
+
// Fast path
|
|
183
|
+
if (value.IsString()) {
|
|
184
|
+
if (directions & 2) [[unlikely]] {
|
|
185
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, value));
|
|
182
186
|
return false;
|
|
183
|
-
|
|
184
|
-
// Create array type
|
|
185
|
-
TypeInfo *type;
|
|
186
|
-
{
|
|
187
|
-
type = AllocateOne<TypeInfo>(&call_alloc, (int)AllocFlag::Zero);
|
|
188
|
-
|
|
189
|
-
type->name = "<temporary>";
|
|
190
|
-
|
|
191
|
-
type->primitive = PrimitiveKind::Array;
|
|
192
|
-
type->align = 1;
|
|
193
|
-
type->size = (int32_t)len;
|
|
194
|
-
type->ref.type = instance->char_type;
|
|
195
|
-
type->hint = ArrayHint::String;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
// Prepare output argument
|
|
199
|
-
{
|
|
200
|
-
OutArgument *out = out_arguments.AppendDefault();
|
|
201
|
-
|
|
202
|
-
napi_status status = napi_create_reference(env, array, 1, &out->ref);
|
|
203
|
-
RG_ASSERT(status == napi_ok);
|
|
204
|
-
|
|
205
|
-
out->kind = OutArgument::Kind::Array;
|
|
206
|
-
out->ptr = (const uint8_t *)*out_str;
|
|
207
|
-
out->type = type;
|
|
208
187
|
}
|
|
209
188
|
|
|
189
|
+
PushString32Value(value, out_str32);
|
|
210
190
|
return true;
|
|
211
|
-
} else {
|
|
212
|
-
return PushPointer(value, instance->str_type, directions, (void **)out_str);
|
|
213
191
|
}
|
|
192
|
+
|
|
193
|
+
return PushPointer(value, instance->str32_type, directions, (void **)out_str32);
|
|
214
194
|
}
|
|
215
195
|
|
|
216
196
|
Size CallData::PushStringValue(Napi::Value value, const char **out_str)
|
|
@@ -223,7 +203,7 @@ Size CallData::PushStringValue(Napi::Value value, const char **out_str)
|
|
|
223
203
|
buf.len = std::max((Size)0, mem->heap.len - Kibibytes(32));
|
|
224
204
|
|
|
225
205
|
status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
226
|
-
|
|
206
|
+
K_ASSERT(status == napi_ok);
|
|
227
207
|
|
|
228
208
|
len++;
|
|
229
209
|
|
|
@@ -232,13 +212,13 @@ Size CallData::PushStringValue(Napi::Value value, const char **out_str)
|
|
|
232
212
|
mem->heap.len -= (Size)len;
|
|
233
213
|
} else {
|
|
234
214
|
status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
|
|
235
|
-
|
|
215
|
+
K_ASSERT(status == napi_ok);
|
|
236
216
|
|
|
237
217
|
len++;
|
|
238
218
|
buf = AllocateSpan<char>(&call_alloc, (Size)len);
|
|
239
219
|
|
|
240
220
|
status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
241
|
-
|
|
221
|
+
K_ASSERT(status == napi_ok);
|
|
242
222
|
|
|
243
223
|
len++;
|
|
244
224
|
}
|
|
@@ -247,74 +227,6 @@ Size CallData::PushStringValue(Napi::Value value, const char **out_str)
|
|
|
247
227
|
return (Size)len;
|
|
248
228
|
}
|
|
249
229
|
|
|
250
|
-
bool CallData::PushString16(Napi::Value value, int directions, const char16_t **out_str16)
|
|
251
|
-
{
|
|
252
|
-
if (value.IsString()) {
|
|
253
|
-
if (directions & 2) [[unlikely]] {
|
|
254
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
|
|
255
|
-
return false;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
PushString16Value(value, out_str16);
|
|
259
|
-
return true;
|
|
260
|
-
} else if (IsNullOrUndefined(value)) {
|
|
261
|
-
*out_str16 = nullptr;
|
|
262
|
-
return true;
|
|
263
|
-
} else if (value.IsArray()) {
|
|
264
|
-
Napi::Array array = value.As<Napi::Array>();
|
|
265
|
-
|
|
266
|
-
if (!(directions & 2)) [[unlikely]] {
|
|
267
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
|
|
268
|
-
return false;
|
|
269
|
-
}
|
|
270
|
-
if (array.Length() != 1) [[unlikely]] {
|
|
271
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, value));
|
|
272
|
-
return false;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
value = array[0u];
|
|
276
|
-
|
|
277
|
-
if (!value.IsString()) [[unlikely]] {
|
|
278
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, array[0u]));
|
|
279
|
-
return false;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
Size len = PushString16Value(value, out_str16);
|
|
283
|
-
if (len < 0) [[unlikely]]
|
|
284
|
-
return false;
|
|
285
|
-
|
|
286
|
-
// Create array type
|
|
287
|
-
TypeInfo *type;
|
|
288
|
-
{
|
|
289
|
-
type = AllocateOne<TypeInfo>(&call_alloc, (int)AllocFlag::Zero);
|
|
290
|
-
|
|
291
|
-
type->name = "<temporary>";
|
|
292
|
-
|
|
293
|
-
type->primitive = PrimitiveKind::Array;
|
|
294
|
-
type->align = 2;
|
|
295
|
-
type->size = (int32_t)(len * 2);
|
|
296
|
-
type->ref.type = instance->char16_type;
|
|
297
|
-
type->hint = ArrayHint::String;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Prepare output argument
|
|
301
|
-
{
|
|
302
|
-
OutArgument *out = out_arguments.AppendDefault();
|
|
303
|
-
|
|
304
|
-
napi_status status = napi_create_reference(env, array, 1, &out->ref);
|
|
305
|
-
RG_ASSERT(status == napi_ok);
|
|
306
|
-
|
|
307
|
-
out->kind = OutArgument::Kind::Array;
|
|
308
|
-
out->ptr = (const uint8_t *)*out_str16;
|
|
309
|
-
out->type = type;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
return true;
|
|
313
|
-
} else {
|
|
314
|
-
return PushPointer(value, instance->str16_type, directions, (void **)out_str16);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
230
|
Size CallData::PushString16Value(Napi::Value value, const char16_t **out_str16)
|
|
319
231
|
{
|
|
320
232
|
Span<char16_t> buf;
|
|
@@ -326,7 +238,7 @@ Size CallData::PushString16Value(Napi::Value value, const char16_t **out_str16)
|
|
|
326
238
|
buf.len = std::max((Size)0, mem->heap.len - Kibibytes(32)) / 2;
|
|
327
239
|
|
|
328
240
|
status = napi_get_value_string_utf16(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
329
|
-
|
|
241
|
+
K_ASSERT(status == napi_ok);
|
|
330
242
|
|
|
331
243
|
len++;
|
|
332
244
|
|
|
@@ -335,13 +247,13 @@ Size CallData::PushString16Value(Napi::Value value, const char16_t **out_str16)
|
|
|
335
247
|
mem->heap.len -= (Size)len * 2;
|
|
336
248
|
} else {
|
|
337
249
|
status = napi_get_value_string_utf16(env, value, nullptr, 0, &len);
|
|
338
|
-
|
|
250
|
+
K_ASSERT(status == napi_ok);
|
|
339
251
|
|
|
340
252
|
len++;
|
|
341
253
|
buf = AllocateSpan<char16_t>(&call_alloc, (Size)len);
|
|
342
254
|
|
|
343
255
|
status = napi_get_value_string_utf16(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
344
|
-
|
|
256
|
+
K_ASSERT(status == napi_ok);
|
|
345
257
|
|
|
346
258
|
len++;
|
|
347
259
|
}
|
|
@@ -350,74 +262,6 @@ Size CallData::PushString16Value(Napi::Value value, const char16_t **out_str16)
|
|
|
350
262
|
return (Size)len;
|
|
351
263
|
}
|
|
352
264
|
|
|
353
|
-
bool CallData::PushString32(Napi::Value value, int directions, const char32_t **out_str32)
|
|
354
|
-
{
|
|
355
|
-
if (value.IsString()) {
|
|
356
|
-
if (directions & 2) [[unlikely]] {
|
|
357
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
|
|
358
|
-
return false;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
PushString32Value(value, out_str32);
|
|
362
|
-
return true;
|
|
363
|
-
} else if (IsNullOrUndefined(value)) {
|
|
364
|
-
*out_str32 = nullptr;
|
|
365
|
-
return true;
|
|
366
|
-
} else if (value.IsArray()) {
|
|
367
|
-
Napi::Array array = value.As<Napi::Array>();
|
|
368
|
-
|
|
369
|
-
if (!(directions & 2)) [[unlikely]] {
|
|
370
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
|
|
371
|
-
return false;
|
|
372
|
-
}
|
|
373
|
-
if (array.Length() != 1) [[unlikely]] {
|
|
374
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, value));
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
value = array[0u];
|
|
379
|
-
|
|
380
|
-
if (!value.IsString()) [[unlikely]] {
|
|
381
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, array[0u]));
|
|
382
|
-
return false;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
Size len = PushString32Value(value, out_str32);
|
|
386
|
-
if (len < 0) [[unlikely]]
|
|
387
|
-
return false;
|
|
388
|
-
|
|
389
|
-
// Create array type
|
|
390
|
-
TypeInfo *type;
|
|
391
|
-
{
|
|
392
|
-
type = AllocateOne<TypeInfo>(&call_alloc, (int)AllocFlag::Zero);
|
|
393
|
-
|
|
394
|
-
type->name = "<temporary>";
|
|
395
|
-
|
|
396
|
-
type->primitive = PrimitiveKind::Array;
|
|
397
|
-
type->align = 4;
|
|
398
|
-
type->size = (int32_t)(len * 4);
|
|
399
|
-
type->ref.type = instance->char32_type;
|
|
400
|
-
type->hint = ArrayHint::String;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// Prepare output argument
|
|
404
|
-
{
|
|
405
|
-
OutArgument *out = out_arguments.AppendDefault();
|
|
406
|
-
|
|
407
|
-
napi_status status = napi_create_reference(env, array, 1, &out->ref);
|
|
408
|
-
RG_ASSERT(status == napi_ok);
|
|
409
|
-
|
|
410
|
-
out->kind = OutArgument::Kind::Array;
|
|
411
|
-
out->ptr = (const uint8_t *)*out_str32;
|
|
412
|
-
out->type = type;
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
return true;
|
|
416
|
-
} else {
|
|
417
|
-
return PushPointer(value, instance->str32_type, directions, (void **)out_str32);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
|
|
421
265
|
Size CallData::PushString32Value(Napi::Value value, const char32_t **out_str32)
|
|
422
266
|
{
|
|
423
267
|
Span<char32_t> buf;
|
|
@@ -463,8 +307,8 @@ Size CallData::PushString32Value(Napi::Value value, const char32_t **out_str32)
|
|
|
463
307
|
|
|
464
308
|
bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origin)
|
|
465
309
|
{
|
|
466
|
-
|
|
467
|
-
|
|
310
|
+
K_ASSERT(IsObject(obj));
|
|
311
|
+
K_ASSERT(type->primitive == PrimitiveKind::Record ||
|
|
468
312
|
type->primitive == PrimitiveKind::Union);
|
|
469
313
|
|
|
470
314
|
Span<const RecordMember> members = {};
|
|
@@ -514,7 +358,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
514
358
|
}
|
|
515
359
|
}
|
|
516
360
|
} else {
|
|
517
|
-
|
|
361
|
+
K_UNREACHABLE();
|
|
518
362
|
}
|
|
519
363
|
|
|
520
364
|
MemSet(origin, 0, type->size);
|
|
@@ -536,7 +380,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
536
380
|
uint8_t *dest = origin + member.offset;
|
|
537
381
|
|
|
538
382
|
switch (member.type->primitive) {
|
|
539
|
-
case PrimitiveKind::Void: {
|
|
383
|
+
case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
|
|
540
384
|
|
|
541
385
|
case PrimitiveKind::Bool: {
|
|
542
386
|
if (!value.IsBoolean()) [[unlikely]] {
|
|
@@ -754,7 +598,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
754
598
|
*(void **)dest = ptr;
|
|
755
599
|
} break;
|
|
756
600
|
|
|
757
|
-
case PrimitiveKind::Prototype: {
|
|
601
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
758
602
|
}
|
|
759
603
|
}
|
|
760
604
|
|
|
@@ -763,7 +607,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
763
607
|
|
|
764
608
|
bool CallData::PushNormalArray(Napi::Array array, const TypeInfo *type, Size size, uint8_t *origin)
|
|
765
609
|
{
|
|
766
|
-
|
|
610
|
+
K_ASSERT(array.IsArray());
|
|
767
611
|
|
|
768
612
|
const TypeInfo *ref = type->ref.type;
|
|
769
613
|
Size len = (Size)array.Length();
|
|
@@ -992,7 +836,7 @@ bool CallData::PushNormalArray(Napi::Array array, const TypeInfo *type, Size siz
|
|
|
992
836
|
}
|
|
993
837
|
} break;
|
|
994
838
|
|
|
995
|
-
case PrimitiveKind::Prototype: {
|
|
839
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
996
840
|
}
|
|
997
841
|
|
|
998
842
|
#undef PUSH_ARRAY
|
|
@@ -1011,7 +855,7 @@ void CallData::PushBuffer(Span<const uint8_t> buffer, const TypeInfo *type, uint
|
|
|
1011
855
|
#define SWAP(CType) \
|
|
1012
856
|
do { \
|
|
1013
857
|
CType *data = (CType *)origin; \
|
|
1014
|
-
Size len = buffer.len /
|
|
858
|
+
Size len = buffer.len / K_SIZE(CType); \
|
|
1015
859
|
\
|
|
1016
860
|
for (Size i = 0; i < len; i++) { \
|
|
1017
861
|
data[i] = ReverseBytes(data[i]); \
|
|
@@ -1035,19 +879,19 @@ void CallData::PushBuffer(Span<const uint8_t> buffer, const TypeInfo *type, uint
|
|
|
1035
879
|
|
|
1036
880
|
bool CallData::PushStringArray(Napi::Value obj, const TypeInfo *type, uint8_t *origin)
|
|
1037
881
|
{
|
|
1038
|
-
|
|
1039
|
-
|
|
882
|
+
K_ASSERT(obj.IsString());
|
|
883
|
+
K_ASSERT(type->primitive == PrimitiveKind::Array);
|
|
1040
884
|
|
|
1041
885
|
size_t encoded = 0;
|
|
1042
886
|
|
|
1043
887
|
switch (type->ref.type->primitive) {
|
|
1044
888
|
case PrimitiveKind::Int8: {
|
|
1045
889
|
napi_status status = napi_get_value_string_utf8(env, obj, (char *)origin, type->size, &encoded);
|
|
1046
|
-
|
|
890
|
+
K_ASSERT(status == napi_ok);
|
|
1047
891
|
} break;
|
|
1048
892
|
case PrimitiveKind::Int16: {
|
|
1049
893
|
napi_status status = napi_get_value_string_utf16(env, obj, (char16_t *)origin, type->size / 2, &encoded);
|
|
1050
|
-
|
|
894
|
+
K_ASSERT(status == napi_ok);
|
|
1051
895
|
|
|
1052
896
|
encoded *= 2;
|
|
1053
897
|
} break;
|
|
@@ -1073,6 +917,8 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
1073
917
|
type = cast->type;
|
|
1074
918
|
}
|
|
1075
919
|
|
|
920
|
+
const TypeInfo *ref = type->ref.type;
|
|
921
|
+
|
|
1076
922
|
switch (value.Type()) {
|
|
1077
923
|
case napi_undefined:
|
|
1078
924
|
case napi_null: {
|
|
@@ -1081,14 +927,14 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
1081
927
|
} break;
|
|
1082
928
|
|
|
1083
929
|
case napi_external: {
|
|
1084
|
-
|
|
930
|
+
K_ASSERT(type->primitive == PrimitiveKind::Pointer ||
|
|
1085
931
|
type->primitive == PrimitiveKind::String ||
|
|
1086
932
|
type->primitive == PrimitiveKind::String16 ||
|
|
1087
933
|
type->primitive == PrimitiveKind::String32);
|
|
1088
934
|
|
|
1089
935
|
if (!CheckValueTag(instance, value, type->ref.marker) &&
|
|
1090
936
|
!CheckValueTag(instance, value, instance->void_type) &&
|
|
1091
|
-
|
|
937
|
+
ref != instance->void_type) [[unlikely]]
|
|
1092
938
|
goto unexpected;
|
|
1093
939
|
|
|
1094
940
|
*out_ptr = value.As<Napi::External<uint8_t>>().Data();
|
|
@@ -1103,29 +949,29 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
1103
949
|
|
|
1104
950
|
if (value.IsArray()) {
|
|
1105
951
|
Napi::Array array = value.As<Napi::Array>();
|
|
1106
|
-
Size len = PushIndirectString(array,
|
|
952
|
+
Size len = PushIndirectString(array, ref, &ptr);
|
|
1107
953
|
|
|
1108
954
|
if (len >= 0) {
|
|
1109
|
-
if (!
|
|
955
|
+
if (!ref->size && ref != instance->void_type) [[unlikely]] {
|
|
1110
956
|
ThrowError<Napi::TypeError>(env, "Cannot pass [string] value to %1", type->name);
|
|
1111
957
|
return false;
|
|
1112
958
|
}
|
|
1113
959
|
|
|
1114
|
-
switch (
|
|
960
|
+
switch (ref->size) {
|
|
1115
961
|
default: { out_kind = OutArgument::Kind::String; } break;
|
|
1116
962
|
case 2: { out_kind = OutArgument::Kind::String16; } break;
|
|
1117
963
|
case 4: { out_kind = OutArgument::Kind::String32; } break;
|
|
1118
964
|
}
|
|
1119
965
|
out_max_len = len;
|
|
1120
966
|
} else {
|
|
1121
|
-
if (!
|
|
967
|
+
if (!ref->size) [[unlikely]] {
|
|
1122
968
|
ThrowError<Napi::TypeError>(env, "Cannot pass %1 value to %2, use koffi.as()",
|
|
1123
|
-
|
|
969
|
+
ref != instance->void_type ? "opaque" : "ambiguous", type->name);
|
|
1124
970
|
return false;
|
|
1125
971
|
}
|
|
1126
972
|
|
|
1127
973
|
Size len = (Size)array.Length();
|
|
1128
|
-
Size size = len *
|
|
974
|
+
Size size = len * ref->size;
|
|
1129
975
|
|
|
1130
976
|
ptr = AllocHeap(size, 16);
|
|
1131
977
|
|
|
@@ -1146,24 +992,24 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
1146
992
|
directions = 1;
|
|
1147
993
|
|
|
1148
994
|
out_kind = OutArgument::Kind::Buffer;
|
|
1149
|
-
} else if (
|
|
1150
|
-
|
|
995
|
+
} else if (ref->primitive == PrimitiveKind::Record ||
|
|
996
|
+
ref->primitive == PrimitiveKind::Union) [[likely]] {
|
|
1151
997
|
Napi::Object obj = value.As<Napi::Object>();
|
|
1152
|
-
|
|
998
|
+
K_ASSERT(IsObject(value));
|
|
1153
999
|
|
|
1154
|
-
ptr = AllocHeap(
|
|
1000
|
+
ptr = AllocHeap(ref->size, 16);
|
|
1155
1001
|
|
|
1156
|
-
if (
|
|
1002
|
+
if (ref->primitive == PrimitiveKind::Union &&
|
|
1157
1003
|
(directions & 2) && !CheckValueTag(instance, obj, &MagicUnionMarker)) [[unlikely]] {
|
|
1158
1004
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected union value", GetValueType(instance, obj));
|
|
1159
1005
|
return false;
|
|
1160
1006
|
}
|
|
1161
1007
|
|
|
1162
1008
|
if (directions & 1) {
|
|
1163
|
-
if (!PushObject(obj,
|
|
1009
|
+
if (!PushObject(obj, ref, ptr))
|
|
1164
1010
|
return false;
|
|
1165
1011
|
} else {
|
|
1166
|
-
MemSet(ptr, 0,
|
|
1012
|
+
MemSet(ptr, 0, ref->size);
|
|
1167
1013
|
}
|
|
1168
1014
|
|
|
1169
1015
|
out_kind = OutArgument::Kind::Object;
|
|
@@ -1175,11 +1021,11 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
1175
1021
|
OutArgument *out = out_arguments.AppendDefault();
|
|
1176
1022
|
|
|
1177
1023
|
napi_status status = napi_create_reference(env, value, 1, &out->ref);
|
|
1178
|
-
|
|
1024
|
+
K_ASSERT(status == napi_ok);
|
|
1179
1025
|
|
|
1180
1026
|
out->kind = out_kind;
|
|
1181
1027
|
out->ptr = ptr;
|
|
1182
|
-
out->type =
|
|
1028
|
+
out->type = ref;
|
|
1183
1029
|
out->max_len = out_max_len;
|
|
1184
1030
|
}
|
|
1185
1031
|
|
|
@@ -1188,21 +1034,21 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
1188
1034
|
} break;
|
|
1189
1035
|
|
|
1190
1036
|
case napi_string: {
|
|
1191
|
-
|
|
1037
|
+
K_ASSERT(type->primitive == PrimitiveKind::Pointer);
|
|
1192
1038
|
|
|
1193
1039
|
if (directions & 2) [[unlikely]]
|
|
1194
1040
|
goto unexpected;
|
|
1195
1041
|
|
|
1196
|
-
if (
|
|
1042
|
+
if (ref == instance->void_type) {
|
|
1197
1043
|
PushStringValue(value, (const char **)out_ptr);
|
|
1198
1044
|
return true;
|
|
1199
|
-
} else if (
|
|
1045
|
+
} else if (ref->primitive == PrimitiveKind::Int8) {
|
|
1200
1046
|
PushStringValue(value, (const char **)out_ptr);
|
|
1201
1047
|
return true;
|
|
1202
|
-
} else if (
|
|
1048
|
+
} else if (ref->primitive == PrimitiveKind::Int16) {
|
|
1203
1049
|
PushString16Value(value, (const char16_t **)out_ptr);
|
|
1204
1050
|
return true;
|
|
1205
|
-
} else if (
|
|
1051
|
+
} else if (ref->primitive == PrimitiveKind::Int32) {
|
|
1206
1052
|
PushString32Value(value, (const char32_t **)out_ptr);
|
|
1207
1053
|
return true;
|
|
1208
1054
|
} else {
|
|
@@ -1324,7 +1170,7 @@ void *CallData::ReserveTrampoline(const FunctionInfo *proto, Napi::Function func
|
|
|
1324
1170
|
return env.Null();
|
|
1325
1171
|
}
|
|
1326
1172
|
if (!used_trampolines.Available()) [[unlikely]] {
|
|
1327
|
-
ThrowError<Napi::Error>(env, "This call uses too many temporary callbacks (max = %1)",
|
|
1173
|
+
ThrowError<Napi::Error>(env, "This call uses too many temporary callbacks (max = %1)", K_LEN(used_trampolines.data));
|
|
1328
1174
|
return env.Null();
|
|
1329
1175
|
}
|
|
1330
1176
|
|
|
@@ -1413,7 +1259,7 @@ static inline Napi::Value GetReferenceValue(Napi::Env env, napi_ref ref)
|
|
|
1413
1259
|
napi_value value;
|
|
1414
1260
|
|
|
1415
1261
|
napi_status status = napi_get_reference_value(env, ref, &value);
|
|
1416
|
-
|
|
1262
|
+
K_ASSERT(status == napi_ok);
|
|
1417
1263
|
|
|
1418
1264
|
return Napi::Value(env, value);
|
|
1419
1265
|
}
|
|
@@ -1422,18 +1268,18 @@ void CallData::PopOutArguments()
|
|
|
1422
1268
|
{
|
|
1423
1269
|
for (const OutArgument &out: out_arguments) {
|
|
1424
1270
|
Napi::Value value = GetReferenceValue(env, out.ref);
|
|
1425
|
-
|
|
1271
|
+
K_ASSERT(!value.IsEmpty());
|
|
1426
1272
|
|
|
1427
1273
|
switch (out.kind) {
|
|
1428
1274
|
case OutArgument::Kind::Array: {
|
|
1429
|
-
|
|
1275
|
+
K_ASSERT(value.IsArray());
|
|
1430
1276
|
|
|
1431
1277
|
Napi::Array array(env, value);
|
|
1432
1278
|
DecodeNormalArray(array, out.ptr, out.type);
|
|
1433
1279
|
} break;
|
|
1434
1280
|
|
|
1435
1281
|
case OutArgument::Kind::Buffer: {
|
|
1436
|
-
|
|
1282
|
+
K_ASSERT(IsRawBuffer(value));
|
|
1437
1283
|
|
|
1438
1284
|
Span<uint8_t> buffer = GetRawBuffer(value);
|
|
1439
1285
|
DecodeBuffer(buffer, out.ptr, out.type);
|
|
@@ -1442,8 +1288,8 @@ void CallData::PopOutArguments()
|
|
|
1442
1288
|
case OutArgument::Kind::String: {
|
|
1443
1289
|
Napi::Array array(env, value);
|
|
1444
1290
|
|
|
1445
|
-
|
|
1446
|
-
|
|
1291
|
+
K_ASSERT(array.IsArray());
|
|
1292
|
+
K_ASSERT(array.Length() == 1);
|
|
1447
1293
|
|
|
1448
1294
|
Size len = strnlen((const char *)out.ptr, out.max_len);
|
|
1449
1295
|
Napi::String str = Napi::String::New(env, (const char *)out.ptr, len);
|
|
@@ -1454,8 +1300,8 @@ void CallData::PopOutArguments()
|
|
|
1454
1300
|
case OutArgument::Kind::String16: {
|
|
1455
1301
|
Napi::Array array(env, value);
|
|
1456
1302
|
|
|
1457
|
-
|
|
1458
|
-
|
|
1303
|
+
K_ASSERT(array.IsArray());
|
|
1304
|
+
K_ASSERT(array.Length() == 1);
|
|
1459
1305
|
|
|
1460
1306
|
Size len = NullTerminatedLength((const char16_t *)out.ptr, out.max_len);
|
|
1461
1307
|
Napi::String str = Napi::String::New(env, (const char16_t *)out.ptr, len);
|
|
@@ -1466,8 +1312,8 @@ void CallData::PopOutArguments()
|
|
|
1466
1312
|
case OutArgument::Kind::String32: {
|
|
1467
1313
|
Napi::Array array(env, value);
|
|
1468
1314
|
|
|
1469
|
-
|
|
1470
|
-
|
|
1315
|
+
K_ASSERT(array.IsArray());
|
|
1316
|
+
K_ASSERT(array.Length() == 1);
|
|
1471
1317
|
|
|
1472
1318
|
Size len = NullTerminatedLength((const char32_t *)out.ptr, out.max_len);
|
|
1473
1319
|
Napi::String str = MakeStringFromUTF32(env, (const char32_t *)out.ptr, len);
|
package/src/koffi/src/call.hh
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
|
|
28
28
|
#include <napi.h>
|
|
29
29
|
|
|
30
|
-
namespace
|
|
30
|
+
namespace K {
|
|
31
31
|
|
|
32
32
|
bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func);
|
|
33
33
|
|
|
@@ -115,10 +115,10 @@ public:
|
|
|
115
115
|
void DumpForward(const FunctionInfo *func) const;
|
|
116
116
|
|
|
117
117
|
bool PushString(Napi::Value value, int directions, const char **out_str);
|
|
118
|
-
Size PushStringValue(Napi::Value value, const char **out_str);
|
|
119
118
|
bool PushString16(Napi::Value value, int directions, const char16_t **out_str16);
|
|
120
|
-
Size PushString16Value(Napi::Value value, const char16_t **out_str16);
|
|
121
119
|
bool PushString32(Napi::Value value, int directions, const char32_t **out_str32);
|
|
120
|
+
Size PushStringValue(Napi::Value value, const char **out_str);
|
|
121
|
+
Size PushString16Value(Napi::Value value, const char16_t **out_str16);
|
|
122
122
|
Size PushString32Value(Napi::Value value, const char32_t **out_str32);
|
|
123
123
|
bool PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origin);
|
|
124
124
|
bool PushNormalArray(Napi::Array array, const TypeInfo *type, Size size, uint8_t *origin);
|
|
@@ -155,7 +155,7 @@ inline bool CallData::AllocStack(Size size, Size align, T **out_ptr)
|
|
|
155
155
|
return false;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
#if defined(
|
|
158
|
+
#if defined(K_DEBUG)
|
|
159
159
|
MemSet(ptr, 0, delta);
|
|
160
160
|
#endif
|
|
161
161
|
|
|
@@ -172,7 +172,7 @@ inline T *CallData::AllocHeap(Size size, Size align)
|
|
|
172
172
|
Size delta = size + (ptr - mem->heap.ptr);
|
|
173
173
|
|
|
174
174
|
if (size < 4096 && delta <= mem->heap.len) [[likely]] {
|
|
175
|
-
#if defined(
|
|
175
|
+
#if defined(K_DEBUG)
|
|
176
176
|
MemSet(mem->heap.ptr, 0, delta);
|
|
177
177
|
#endif
|
|
178
178
|
|
|
@@ -181,7 +181,7 @@ inline T *CallData::AllocHeap(Size size, Size align)
|
|
|
181
181
|
|
|
182
182
|
return ptr;
|
|
183
183
|
} else {
|
|
184
|
-
#if defined(
|
|
184
|
+
#if defined(K_DEBUG)
|
|
185
185
|
int flags = (int)AllocFlag::Zero;
|
|
186
186
|
#else
|
|
187
187
|
int flags = 0;
|