koffi 3.0.1 → 3.0.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/CHANGELOG.md +11 -0
- package/cnoke.cjs +7 -7
- package/doc/benchmarks.md +1 -1
- package/doc/contribute.md +1 -1
- package/index.d.ts +356 -308
- package/package.json +16 -16
- package/src/koffi/CMakeLists.txt +1 -0
- package/src/koffi/index.cjs +30 -116
- package/src/koffi/index.js +27 -101
- package/src/koffi/indirect.cjs +29 -115
- package/src/koffi/indirect.js +28 -28
- package/src/koffi/src/abi/arm64.cc +1 -0
- package/src/koffi/src/abi/riscv64.cc +1 -0
- package/src/koffi/src/abi/x64sysv.cc +1 -0
- package/src/koffi/src/abi/x64win.cc +1 -0
- package/src/koffi/src/abi/x86.cc +1 -0
- package/src/koffi/src/call.cc +208 -97
- package/src/koffi/src/call.hh +2 -1
- package/src/koffi/src/ffi.cc +347 -237
- package/src/koffi/src/ffi.hh +37 -1
- package/src/koffi/src/parser.cc +3 -1
- package/src/koffi/src/static.cjs +122 -0
- package/src/koffi/src/static.js +122 -0
- package/src/koffi/src/type.cc +715 -0
- package/src/koffi/src/type.hh +71 -0
- package/src/koffi/src/util.cc +56 -1041
- package/src/koffi/src/util.hh +80 -119
- package/src/koffi/src/uv.cc +16 -10
- package/src/koffi/src/uv.hh +2 -1
- package/indirect.d.ts +0 -322
package/src/koffi/src/call.cc
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
#include "lib/native/base/base.hh"
|
|
5
5
|
#include "call.hh"
|
|
6
6
|
#include "ffi.hh"
|
|
7
|
+
#include "type.hh"
|
|
7
8
|
#include "util.hh"
|
|
8
9
|
#if defined(_WIN32)
|
|
9
10
|
#include "win32.hh"
|
|
@@ -71,15 +72,6 @@ void CallData::Finalize()
|
|
|
71
72
|
DecodeElements(instance, value, out.ptr, out.type, len);
|
|
72
73
|
} break;
|
|
73
74
|
|
|
74
|
-
case OutArgument::Kind::Buffer: {
|
|
75
|
-
Span<uint8_t> buffer;
|
|
76
|
-
|
|
77
|
-
bool success = TryBuffer(env, value, &buffer);
|
|
78
|
-
K_ASSERT(success);
|
|
79
|
-
|
|
80
|
-
DecodeBuffer(buffer, out.ptr, out.type);
|
|
81
|
-
} break;
|
|
82
|
-
|
|
83
75
|
case OutArgument::Kind::String: {
|
|
84
76
|
K_ASSERT(IsArray(env, value));
|
|
85
77
|
K_ASSERT(GetArrayLength(env, value) == 1);
|
|
@@ -113,7 +105,7 @@ void CallData::Finalize()
|
|
|
113
105
|
case OutArgument::Kind::Object: {
|
|
114
106
|
if (CheckValueTag(env, value, &UnionValueMarker)) {
|
|
115
107
|
UnionValue *u = nullptr;
|
|
116
|
-
napi_unwrap(env, value, (void **)&u);
|
|
108
|
+
NAPI_OK(napi_unwrap(env, value, (void **)&u));
|
|
117
109
|
|
|
118
110
|
u->SetRaw(out.ptr);
|
|
119
111
|
} else {
|
|
@@ -183,7 +175,7 @@ void CallData::RelayAsync(Size idx, uint8_t *sp)
|
|
|
183
175
|
.sp = sp
|
|
184
176
|
};
|
|
185
177
|
|
|
186
|
-
napi_call_threadsafe_function(instance->broker, &ctx, napi_tsfn_blocking);
|
|
178
|
+
NAPI_OK(napi_call_threadsafe_function(instance->broker, &ctx, napi_tsfn_blocking));
|
|
187
179
|
|
|
188
180
|
// Wait until it executes
|
|
189
181
|
std::unique_lock<std::mutex> lock(ctx.mutex);
|
|
@@ -198,8 +190,8 @@ napi_value CallData::CallCallback(const TrampolineInfo *trampoline, const napi_v
|
|
|
198
190
|
napi_value func;
|
|
199
191
|
napi_value value;
|
|
200
192
|
|
|
201
|
-
napi_get_undefined(env, &recv);
|
|
202
|
-
napi_get_reference_value(env, trampoline->func, &func);
|
|
193
|
+
NAPI_OK(napi_get_undefined(env, &recv));
|
|
194
|
+
NAPI_OK(napi_get_reference_value(env, trampoline->func, &func));
|
|
203
195
|
|
|
204
196
|
napi_status status = napi_call_function(env, recv, func, (size_t)count, args, &value);
|
|
205
197
|
if (status == napi_pending_exception) [[unlikely]]
|
|
@@ -257,7 +249,6 @@ bool CallData::PushString32(napi_value value, int directions, const char32_t **o
|
|
|
257
249
|
Size CallData::PushStringValue(napi_value value, const char **out_str)
|
|
258
250
|
{
|
|
259
251
|
size_t len;
|
|
260
|
-
napi_status status;
|
|
261
252
|
|
|
262
253
|
size_t available = (size_t)(mem->heap.end - mem->heap.ptr);
|
|
263
254
|
char *ptr = (char *)mem->heap.ptr;
|
|
@@ -266,7 +257,7 @@ Size CallData::PushStringValue(napi_value value, const char **out_str)
|
|
|
266
257
|
if (available >= 4096) [[likely]] {
|
|
267
258
|
char *ptr = (char *)mem->heap.ptr;
|
|
268
259
|
|
|
269
|
-
status = napi_get_value_string_utf8(env, value, ptr, 4096, &len);
|
|
260
|
+
napi_status status = napi_get_value_string_utf8(env, value, ptr, 4096, &len);
|
|
270
261
|
if (status == napi_string_expected)
|
|
271
262
|
return -1;
|
|
272
263
|
K_ASSERT(status == napi_ok);
|
|
@@ -285,14 +276,12 @@ Size CallData::PushStringValue(napi_value value, const char **out_str)
|
|
|
285
276
|
}
|
|
286
277
|
}
|
|
287
278
|
|
|
288
|
-
|
|
289
|
-
K_ASSERT(status == napi_ok);
|
|
279
|
+
NAPI_OK(napi_get_value_string_utf8(env, value, nullptr, 0, &len));
|
|
290
280
|
|
|
291
281
|
len++;
|
|
292
282
|
|
|
293
283
|
if (len <= available) {
|
|
294
|
-
|
|
295
|
-
K_ASSERT(status == napi_ok);
|
|
284
|
+
NAPI_OK(napi_get_value_string_utf8(env, value, ptr, len, nullptr));
|
|
296
285
|
|
|
297
286
|
mem->heap.ptr += (Size)AlignLen(len, 16);
|
|
298
287
|
|
|
@@ -302,8 +291,7 @@ Size CallData::PushStringValue(napi_value value, const char **out_str)
|
|
|
302
291
|
Span<char> buf = AllocateSpan<char>(&mem->allocator, (Size)len);
|
|
303
292
|
release_alloc |= (prev_stack == mem->stack.end);
|
|
304
293
|
|
|
305
|
-
|
|
306
|
-
K_ASSERT(status == napi_ok);
|
|
294
|
+
NAPI_OK(napi_get_value_string_utf8(env, value, buf.ptr, len, nullptr));
|
|
307
295
|
|
|
308
296
|
*out_str = buf.ptr;
|
|
309
297
|
return (Size)len;
|
|
@@ -314,9 +302,8 @@ Size CallData::PushString16Value(napi_value value, const char16_t **out_str16)
|
|
|
314
302
|
{
|
|
315
303
|
size_t len = 0;
|
|
316
304
|
Span<char16_t> buf;
|
|
317
|
-
napi_status status;
|
|
318
305
|
|
|
319
|
-
status = napi_get_value_string_utf16(env, value, nullptr, 0, &len);
|
|
306
|
+
napi_status status = napi_get_value_string_utf16(env, value, nullptr, 0, &len);
|
|
320
307
|
if (status == napi_string_expected)
|
|
321
308
|
return -1;
|
|
322
309
|
K_ASSERT(status == napi_ok);
|
|
@@ -327,16 +314,14 @@ Size CallData::PushString16Value(napi_value value, const char16_t **out_str16)
|
|
|
327
314
|
buf.len = (mem->heap.end - mem->heap.ptr) / 2;
|
|
328
315
|
|
|
329
316
|
if (len <= (size_t)buf.len) {
|
|
330
|
-
|
|
331
|
-
K_ASSERT(status == napi_ok);
|
|
317
|
+
NAPI_OK(napi_get_value_string_utf16(env, value, buf.ptr, len, nullptr));
|
|
332
318
|
|
|
333
319
|
mem->heap.ptr += (Size)AlignLen(len * 2, 16);
|
|
334
320
|
} else {
|
|
335
321
|
buf = AllocateSpan<char16_t>(&mem->allocator, (Size)len);
|
|
336
322
|
release_alloc |= (prev_stack == mem->stack.end);
|
|
337
323
|
|
|
338
|
-
|
|
339
|
-
K_ASSERT(status == napi_ok);
|
|
324
|
+
NAPI_OK(napi_get_value_string_utf16(env, value, buf.ptr, len, nullptr));
|
|
340
325
|
}
|
|
341
326
|
|
|
342
327
|
*out_str16 = buf.ptr;
|
|
@@ -652,7 +637,7 @@ bool CallData::PushNormalArray(Napi::Array array, const TypeInfo *type, Size siz
|
|
|
652
637
|
#define PUSH_ARRAY(SetCode) \
|
|
653
638
|
do { \
|
|
654
639
|
for (Size i = 0; i < len; i++) { \
|
|
655
|
-
|
|
640
|
+
napi_value value = array[(uint32_t)i].AsValue(); \
|
|
656
641
|
\
|
|
657
642
|
uint8_t *dest = origin + offset; \
|
|
658
643
|
SetCode \
|
|
@@ -744,11 +729,6 @@ bool CallData::PushNormalArray(Napi::Array array, const TypeInfo *type, Size siz
|
|
|
744
729
|
} break;
|
|
745
730
|
case PrimitiveKind::Pointer: {
|
|
746
731
|
PUSH_ARRAY({
|
|
747
|
-
if (!IsObject(env, value)) [[unlikely]] {
|
|
748
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
749
|
-
return false;
|
|
750
|
-
}
|
|
751
|
-
|
|
752
732
|
void *ptr;
|
|
753
733
|
if (!PushPointer(value, ref, 1, &ptr)) [[unlikely]]
|
|
754
734
|
return false;
|
|
@@ -770,17 +750,17 @@ bool CallData::PushNormalArray(Napi::Array array, const TypeInfo *type, Size siz
|
|
|
770
750
|
} break;
|
|
771
751
|
case PrimitiveKind::Array: {
|
|
772
752
|
for (Size i = 0; i < len; i++) {
|
|
773
|
-
|
|
753
|
+
napi_value value = array[(uint32_t)i].AsValue();
|
|
774
754
|
|
|
775
755
|
uint8_t *dest = origin + offset;
|
|
776
756
|
|
|
777
|
-
if (
|
|
778
|
-
Napi::Array
|
|
779
|
-
if (!PushNormalArray(
|
|
757
|
+
if (IsArray(env, value)) {
|
|
758
|
+
Napi::Array array = Napi::Array(env, value);
|
|
759
|
+
if (!PushNormalArray(array, ref, (Size)ref->size, dest))
|
|
780
760
|
return false;
|
|
781
761
|
} else if (Span<uint8_t> buffer = {}; TryBuffer(env, value, &buffer)) {
|
|
782
762
|
PushBuffer(buffer, ref, dest);
|
|
783
|
-
} else if (value
|
|
763
|
+
} else if (GetKindOf(env, value) == napi_string) {
|
|
784
764
|
if (!PushStringArray(value, ref, dest))
|
|
785
765
|
return false;
|
|
786
766
|
} else {
|
|
@@ -814,19 +794,13 @@ bool CallData::PushNormalArray(Napi::Array array, const TypeInfo *type, Size siz
|
|
|
814
794
|
});
|
|
815
795
|
} break;
|
|
816
796
|
case PrimitiveKind::Callback: {
|
|
817
|
-
|
|
818
|
-
Napi::Value value = array[(uint32_t)i];
|
|
819
|
-
|
|
820
|
-
uint8_t *dest = origin + offset;
|
|
821
|
-
|
|
797
|
+
PUSH_ARRAY({
|
|
822
798
|
void *ptr;
|
|
823
799
|
if (!PushCallback(value, ref, &ptr))
|
|
824
800
|
return false;
|
|
825
801
|
|
|
826
|
-
*(void **)dest = ptr;
|
|
827
|
-
|
|
828
|
-
offset += stride;
|
|
829
|
-
}
|
|
802
|
+
*(const void **)dest = ptr;
|
|
803
|
+
});
|
|
830
804
|
} break;
|
|
831
805
|
|
|
832
806
|
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
@@ -893,14 +867,9 @@ bool CallData::PushStringArray(napi_value value, const TypeInfo *type, uint8_t *
|
|
|
893
867
|
size_t encoded = 0;
|
|
894
868
|
|
|
895
869
|
switch (type->ref.type->primitive) {
|
|
896
|
-
case PrimitiveKind::Int8: {
|
|
897
|
-
napi_status status = napi_get_value_string_utf8(env, value, (char *)origin, type->size, &encoded);
|
|
898
|
-
K_ASSERT(status == napi_ok);
|
|
899
|
-
} break;
|
|
870
|
+
case PrimitiveKind::Int8: { NAPI_OK(napi_get_value_string_utf8(env, value, (char *)origin, type->size, &encoded)); } break;
|
|
900
871
|
case PrimitiveKind::Int16: {
|
|
901
|
-
|
|
902
|
-
K_ASSERT(status == napi_ok);
|
|
903
|
-
|
|
872
|
+
NAPI_OK(napi_get_value_string_utf16(env, value, (char16_t *)origin, type->size / 2, &encoded));
|
|
904
873
|
encoded *= 2;
|
|
905
874
|
} break;
|
|
906
875
|
|
|
@@ -933,7 +902,7 @@ restart:
|
|
|
933
902
|
Napi::External<ValueCast> external = Napi::External<ValueCast>(env, value);
|
|
934
903
|
ValueCast *cast = external.Data();
|
|
935
904
|
|
|
936
|
-
napi_get_reference_value(env, cast->ref, &value);
|
|
905
|
+
NAPI_OK(napi_get_reference_value(env, cast->ref, &value));
|
|
937
906
|
type = cast->type;
|
|
938
907
|
|
|
939
908
|
goto restart;
|
|
@@ -1029,8 +998,7 @@ bool CallData::PushPointerSlow(napi_value value, napi_valuetype kind, const Type
|
|
|
1029
998
|
if (directions & 2) {
|
|
1030
999
|
OutArgument *out = out_arguments.AppendDefault();
|
|
1031
1000
|
|
|
1032
|
-
|
|
1033
|
-
K_ASSERT(status == napi_ok);
|
|
1001
|
+
NAPI_OK(napi_create_reference(env, value, 1, &out->ref));
|
|
1034
1002
|
|
|
1035
1003
|
out->kind = out_kind;
|
|
1036
1004
|
out->ptr = (const uint8_t *)ptr;
|
|
@@ -1062,8 +1030,7 @@ bool CallData::PushPointerSlow(napi_value value, napi_valuetype kind, const Type
|
|
|
1062
1030
|
if (directions & 2) {
|
|
1063
1031
|
OutArgument *out = out_arguments.AppendDefault();
|
|
1064
1032
|
|
|
1065
|
-
|
|
1066
|
-
K_ASSERT(status == napi_ok);
|
|
1033
|
+
NAPI_OK(napi_create_reference(env, value, 1, &out->ref));
|
|
1067
1034
|
|
|
1068
1035
|
out->kind = OutArgument::Kind::Object;
|
|
1069
1036
|
out->ptr = (const uint8_t *)ptr;
|
|
@@ -1107,7 +1074,7 @@ restart:
|
|
|
1107
1074
|
Napi::External<ValueCast> external = Napi::External<ValueCast>(env, value);
|
|
1108
1075
|
ValueCast *cast = external.Data();
|
|
1109
1076
|
|
|
1110
|
-
napi_get_reference_value(env, cast->ref, &value);
|
|
1077
|
+
NAPI_OK(napi_get_reference_value(env, cast->ref, &value));
|
|
1111
1078
|
type = cast->type;
|
|
1112
1079
|
|
|
1113
1080
|
goto restart;
|
|
@@ -1132,7 +1099,7 @@ restart:
|
|
|
1132
1099
|
Napi::External<ValueCast> external = Napi::External<ValueCast>(env, value);
|
|
1133
1100
|
ValueCast *cast = external.Data();
|
|
1134
1101
|
|
|
1135
|
-
napi_get_reference_value(env, cast->ref, &value);
|
|
1102
|
+
NAPI_OK(napi_get_reference_value(env, cast->ref, &value));
|
|
1136
1103
|
type = cast->type;
|
|
1137
1104
|
|
|
1138
1105
|
goto restart;
|
|
@@ -1148,7 +1115,7 @@ Size CallData::PushIndirectString(Napi::Array array, const TypeInfo *ref, void *
|
|
|
1148
1115
|
if (array.Length() != 1)
|
|
1149
1116
|
return -1;
|
|
1150
1117
|
|
|
1151
|
-
|
|
1118
|
+
napi_value value = array[0u].AsValue();
|
|
1152
1119
|
|
|
1153
1120
|
if (ref == instance->void_type) {
|
|
1154
1121
|
return PushStringValue(value, (const char **)out_ptr);
|
|
@@ -1192,7 +1159,7 @@ void *CallData::ReserveTrampoline(const FunctionInfo *proto, Napi::Function func
|
|
|
1192
1159
|
trampoline->instance = instance;
|
|
1193
1160
|
trampoline->stack0 = instance->memories[0]->stack0;
|
|
1194
1161
|
trampoline->proto = proto;
|
|
1195
|
-
napi_create_reference(env, func, 1, &trampoline->func);
|
|
1162
|
+
NAPI_OK(napi_create_reference(env, func, 1, &trampoline->func));
|
|
1196
1163
|
|
|
1197
1164
|
void *ptr = GetTrampoline(idx);
|
|
1198
1165
|
|
|
@@ -1305,13 +1272,12 @@ void InitTranslateZeroCall(Napi::Env env)
|
|
|
1305
1272
|
|
|
1306
1273
|
Napi::Object self = Napi::Object::New(env);
|
|
1307
1274
|
|
|
1308
|
-
napi_status status;
|
|
1309
1275
|
napi_value func;
|
|
1310
1276
|
napi_value ret;
|
|
1311
1277
|
|
|
1312
|
-
|
|
1278
|
+
auto cb = [](napi_env env, napi_callback_info info) {
|
|
1313
1279
|
napi_value self;
|
|
1314
|
-
napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr);
|
|
1280
|
+
NAPI_OK(napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr));
|
|
1315
1281
|
|
|
1316
1282
|
napi_value *ptr = (napi_value *)info;
|
|
1317
1283
|
|
|
@@ -1322,11 +1288,10 @@ void InitTranslateZeroCall(Napi::Env env)
|
|
|
1322
1288
|
}
|
|
1323
1289
|
|
|
1324
1290
|
return self;
|
|
1325
|
-
}
|
|
1326
|
-
K_ASSERT(status == napi_ok);
|
|
1291
|
+
};
|
|
1327
1292
|
|
|
1328
|
-
|
|
1329
|
-
|
|
1293
|
+
NAPI_OK(napi_create_function(env, nullptr, 0, cb, nullptr, &func));
|
|
1294
|
+
NAPI_OK(napi_call_function(env, self, func, 0, nullptr, &ret));
|
|
1330
1295
|
}
|
|
1331
1296
|
|
|
1332
1297
|
bool InitAsyncBroker(Napi::Env env, InstanceData *instance)
|
|
@@ -1339,7 +1304,8 @@ bool InitAsyncBroker(Napi::Env env, InstanceData *instance)
|
|
|
1339
1304
|
LogError("Failed to create async callback broker");
|
|
1340
1305
|
return false;
|
|
1341
1306
|
}
|
|
1342
|
-
|
|
1307
|
+
|
|
1308
|
+
NAPI_OK(napi_unref_threadsafe_function(env, instance->broker));
|
|
1343
1309
|
}
|
|
1344
1310
|
|
|
1345
1311
|
return true;
|
|
@@ -1376,8 +1342,7 @@ napi_value TranslateFastCall(napi_env env, napi_callback_info info)
|
|
|
1376
1342
|
size_t count = 6;
|
|
1377
1343
|
FunctionInfo *func;
|
|
1378
1344
|
|
|
1379
|
-
|
|
1380
|
-
K_ASSERT(status == napi_ok);
|
|
1345
|
+
NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func));
|
|
1381
1346
|
|
|
1382
1347
|
if (count < (size_t)func->required_parameters) [[unlikely]] {
|
|
1383
1348
|
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, count);
|
|
@@ -1429,13 +1394,10 @@ napi_value TranslateNormalCall(napi_env env, napi_callback_info info)
|
|
|
1429
1394
|
size_t count = 8;
|
|
1430
1395
|
FunctionInfo *func;
|
|
1431
1396
|
|
|
1432
|
-
|
|
1433
|
-
K_ASSERT(status == napi_ok);
|
|
1397
|
+
NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func));
|
|
1434
1398
|
|
|
1435
1399
|
if (count > 8) {
|
|
1436
|
-
|
|
1437
|
-
K_ASSERT(status == napi_ok);
|
|
1438
|
-
|
|
1400
|
+
NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
|
|
1439
1401
|
count = std::min(count, (size_t)MaxParameters);
|
|
1440
1402
|
}
|
|
1441
1403
|
|
|
@@ -1482,13 +1444,10 @@ napi_value TranslateNormalCallDebugAsync(napi_env env, napi_callback_info info)
|
|
|
1482
1444
|
size_t count = 8;
|
|
1483
1445
|
FunctionInfo *func;
|
|
1484
1446
|
|
|
1485
|
-
|
|
1486
|
-
K_ASSERT(status == napi_ok);
|
|
1447
|
+
NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func));
|
|
1487
1448
|
|
|
1488
1449
|
if (count > 8) {
|
|
1489
|
-
|
|
1490
|
-
K_ASSERT(status == napi_ok);
|
|
1491
|
-
|
|
1450
|
+
NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
|
|
1492
1451
|
count = std::min(count, (size_t)MaxParameters);
|
|
1493
1452
|
}
|
|
1494
1453
|
|
|
@@ -1517,7 +1476,7 @@ static napi_value TranslateVariadicCall(napi_env env, const FunctionInfo *func,
|
|
|
1517
1476
|
|
|
1518
1477
|
for (Size i = prev->required_parameters, j = prev->required_parameters; i < (Size)count; i += 2, j++) {
|
|
1519
1478
|
int directions;
|
|
1520
|
-
const TypeInfo *type = ResolveType(
|
|
1479
|
+
const TypeInfo *type = ResolveType(instance, args[i], &directions);
|
|
1521
1480
|
|
|
1522
1481
|
if (type != prev->parameters[j].type || directions != prev->parameters[j].directions) [[unlikely]] {
|
|
1523
1482
|
match = false;
|
|
@@ -1558,7 +1517,7 @@ static napi_value TranslateVariadicCall(napi_env env, const FunctionInfo *func,
|
|
|
1558
1517
|
for (Size i = variadic->required_parameters; i < count; i += 2) {
|
|
1559
1518
|
ParameterInfo param = {};
|
|
1560
1519
|
|
|
1561
|
-
param.type = ResolveType(
|
|
1520
|
+
param.type = ResolveType(instance, args[i], ¶m.directions);
|
|
1562
1521
|
|
|
1563
1522
|
if (!param.type) [[unlikely]]
|
|
1564
1523
|
return Napi::Env(env).Null();
|
|
@@ -1607,13 +1566,10 @@ napi_value TranslateVariadicCall(napi_env env, napi_callback_info info)
|
|
|
1607
1566
|
size_t count = 8;
|
|
1608
1567
|
FunctionInfo *func;
|
|
1609
1568
|
|
|
1610
|
-
|
|
1611
|
-
K_ASSERT(status == napi_ok);
|
|
1569
|
+
NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func));
|
|
1612
1570
|
|
|
1613
1571
|
if (count > 8) {
|
|
1614
|
-
|
|
1615
|
-
K_ASSERT(status == napi_ok);
|
|
1616
|
-
|
|
1572
|
+
NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
|
|
1617
1573
|
count = std::min(count, (size_t)MaxParameters);
|
|
1618
1574
|
}
|
|
1619
1575
|
|
|
@@ -1703,13 +1659,10 @@ napi_value TranslateAsyncCall(napi_env env, napi_callback_info info)
|
|
|
1703
1659
|
size_t count = 6;
|
|
1704
1660
|
FunctionInfo *func;
|
|
1705
1661
|
|
|
1706
|
-
|
|
1707
|
-
K_ASSERT(status == napi_ok);
|
|
1662
|
+
NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func));
|
|
1708
1663
|
|
|
1709
1664
|
if (count > 6) {
|
|
1710
|
-
|
|
1711
|
-
K_ASSERT(status == napi_ok);
|
|
1712
|
-
|
|
1665
|
+
NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
|
|
1713
1666
|
count = std::min(count, (size_t)MaxParameters);
|
|
1714
1667
|
}
|
|
1715
1668
|
|
|
@@ -1800,7 +1753,7 @@ extern "C" void RelayCallback(Size idx, uint8_t *sp)
|
|
|
1800
1753
|
K_DEFER { call.Finalize(); };
|
|
1801
1754
|
|
|
1802
1755
|
napi_handle_scope scope;
|
|
1803
|
-
napi_open_handle_scope(env, &scope);
|
|
1756
|
+
NAPI_OK(napi_open_handle_scope(env, &scope));
|
|
1804
1757
|
K_DEFER { napi_close_handle_scope(env, scope); };
|
|
1805
1758
|
|
|
1806
1759
|
call.Relay(idx, sp);
|
|
@@ -1839,7 +1792,7 @@ extern "C" void RelayDirect(CallData *call, Size idx, uint8_t *sp)
|
|
|
1839
1792
|
// Relay the call
|
|
1840
1793
|
{
|
|
1841
1794
|
napi_handle_scope scope;
|
|
1842
|
-
napi_open_handle_scope(call->env, &scope);
|
|
1795
|
+
NAPI_OK(napi_open_handle_scope(call->env, &scope));
|
|
1843
1796
|
K_DEFER { napi_close_handle_scope(call->env, scope); };
|
|
1844
1797
|
|
|
1845
1798
|
call->Relay(idx, sp);
|
|
@@ -1874,4 +1827,162 @@ void *GetTrampoline(int idx)
|
|
|
1874
1827
|
return (void *)(TrampolineStart + TrampolineSize * idx);
|
|
1875
1828
|
}
|
|
1876
1829
|
|
|
1830
|
+
bool Encode(InstanceData *instance, uint8_t *origin, napi_value value, const TypeInfo *type)
|
|
1831
|
+
{
|
|
1832
|
+
Napi::Env env = instance->env;
|
|
1833
|
+
|
|
1834
|
+
InstanceMemory mem = {};
|
|
1835
|
+
CallData call(env, instance, &mem, nullptr);
|
|
1836
|
+
|
|
1837
|
+
#define PUSH_INTEGER(CType) \
|
|
1838
|
+
do { \
|
|
1839
|
+
CType v; \
|
|
1840
|
+
if (!TryNumber(env, value, &v)) [[unlikely]] { \
|
|
1841
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
1842
|
+
return false; \
|
|
1843
|
+
} \
|
|
1844
|
+
\
|
|
1845
|
+
*(CType *)origin = v; \
|
|
1846
|
+
} while (false)
|
|
1847
|
+
#define PUSH_INTEGER_SWAP(CType) \
|
|
1848
|
+
do { \
|
|
1849
|
+
CType v; \
|
|
1850
|
+
if (!TryNumber(env, value, &v)) [[unlikely]] { \
|
|
1851
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
1852
|
+
return false; \
|
|
1853
|
+
} \
|
|
1854
|
+
\
|
|
1855
|
+
*(CType *)origin = ReverseBytes(v); \
|
|
1856
|
+
} while (false)
|
|
1857
|
+
|
|
1858
|
+
switch (type->primitive) {
|
|
1859
|
+
case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
|
|
1860
|
+
|
|
1861
|
+
case PrimitiveKind::Bool: {
|
|
1862
|
+
bool b;
|
|
1863
|
+
napi_status status = napi_get_value_bool(env, value, &b);
|
|
1864
|
+
|
|
1865
|
+
if (status != napi_ok) [[unlikely]] {
|
|
1866
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
1867
|
+
return false;
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
*(bool *)origin = b;
|
|
1871
|
+
} break;
|
|
1872
|
+
case PrimitiveKind::Int8: { PUSH_INTEGER(int8_t); } break;
|
|
1873
|
+
case PrimitiveKind::UInt8: { PUSH_INTEGER(uint8_t); } break;
|
|
1874
|
+
case PrimitiveKind::Int16: { PUSH_INTEGER(int16_t); } break;
|
|
1875
|
+
case PrimitiveKind::Int16S: { PUSH_INTEGER_SWAP(int16_t); } break;
|
|
1876
|
+
case PrimitiveKind::UInt16: { PUSH_INTEGER(uint16_t); } break;
|
|
1877
|
+
case PrimitiveKind::UInt16S: { PUSH_INTEGER_SWAP(uint16_t); } break;
|
|
1878
|
+
case PrimitiveKind::Int32: { PUSH_INTEGER(int32_t); } break;
|
|
1879
|
+
case PrimitiveKind::Int32S: { PUSH_INTEGER_SWAP(int32_t); } break;
|
|
1880
|
+
case PrimitiveKind::UInt32: { PUSH_INTEGER(uint32_t); } break;
|
|
1881
|
+
case PrimitiveKind::UInt32S: { PUSH_INTEGER_SWAP(uint32_t); } break;
|
|
1882
|
+
case PrimitiveKind::Int64: { PUSH_INTEGER(int64_t); } break;
|
|
1883
|
+
case PrimitiveKind::Int64S: { PUSH_INTEGER_SWAP(int64_t); } break;
|
|
1884
|
+
case PrimitiveKind::UInt64: { PUSH_INTEGER(uint64_t); } break;
|
|
1885
|
+
case PrimitiveKind::UInt64S: { PUSH_INTEGER_SWAP(uint64_t); } break;
|
|
1886
|
+
case PrimitiveKind::String: {
|
|
1887
|
+
const char *str;
|
|
1888
|
+
if (!call.PushString(value, 1, &str)) [[unlikely]]
|
|
1889
|
+
return false;
|
|
1890
|
+
*(const char **)origin = str;
|
|
1891
|
+
} break;
|
|
1892
|
+
case PrimitiveKind::String16: {
|
|
1893
|
+
const char16_t *str16;
|
|
1894
|
+
if (!call.PushString16(value, 1, &str16)) [[unlikely]]
|
|
1895
|
+
return false;
|
|
1896
|
+
*(const char16_t **)origin = str16;
|
|
1897
|
+
} break;
|
|
1898
|
+
case PrimitiveKind::String32: {
|
|
1899
|
+
const char32_t *str32;
|
|
1900
|
+
if (!call.PushString32(value, 1, &str32)) [[unlikely]]
|
|
1901
|
+
return false;
|
|
1902
|
+
*(const char32_t **)origin = str32;
|
|
1903
|
+
} break;
|
|
1904
|
+
case PrimitiveKind::Pointer: {
|
|
1905
|
+
void *ptr;
|
|
1906
|
+
if (!call.PushPointer(value, type, 1, &ptr)) [[unlikely]]
|
|
1907
|
+
return false;
|
|
1908
|
+
*(void **)origin = ptr;
|
|
1909
|
+
} break;
|
|
1910
|
+
case PrimitiveKind::Record:
|
|
1911
|
+
case PrimitiveKind::Union: {
|
|
1912
|
+
if (!IsObject(env, value)) [[unlikely]] {
|
|
1913
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
1914
|
+
return false;
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
if (!call.PushObject(value, type, origin))
|
|
1918
|
+
return false;
|
|
1919
|
+
} break;
|
|
1920
|
+
case PrimitiveKind::Array: {
|
|
1921
|
+
if (IsArray(env, value)) {
|
|
1922
|
+
Napi::Array array = Napi::Array(env, value);
|
|
1923
|
+
if (!call.PushNormalArray(array, type, type->size, origin))
|
|
1924
|
+
return false;
|
|
1925
|
+
} else if (Span<uint8_t> buffer = {}; TryBuffer(env, value, &buffer)) {
|
|
1926
|
+
call.PushBuffer(buffer, type, origin);
|
|
1927
|
+
} else if (GetKindOf(env, value) == napi_string) {
|
|
1928
|
+
if (!call.PushStringArray(value, type, origin))
|
|
1929
|
+
return false;
|
|
1930
|
+
} else {
|
|
1931
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected array", GetValueType(instance, value));
|
|
1932
|
+
return false;
|
|
1933
|
+
}
|
|
1934
|
+
} break;
|
|
1935
|
+
case PrimitiveKind::Float32: {
|
|
1936
|
+
float f;
|
|
1937
|
+
if (!TryNumber(env, value, &f)) [[unlikely]] {
|
|
1938
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
1939
|
+
return false;
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
memcpy(origin, &f, 4);
|
|
1943
|
+
} break;
|
|
1944
|
+
case PrimitiveKind::Float64: {
|
|
1945
|
+
double d;
|
|
1946
|
+
if (!TryNumber(env, value, &d)) [[unlikely]] {
|
|
1947
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
1948
|
+
return false;
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
memcpy(origin, &d, 8);
|
|
1952
|
+
} break;
|
|
1953
|
+
case PrimitiveKind::Callback: {
|
|
1954
|
+
void *ptr;
|
|
1955
|
+
if (!TryPointer(env, value, &ptr)) [[unlikely]] {
|
|
1956
|
+
if (GetKindOf(env, value) == napi_function) {
|
|
1957
|
+
ThrowError<Napi::Error>(env, "Cannot encode non-registered callback");
|
|
1958
|
+
} else {
|
|
1959
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
1960
|
+
}
|
|
1961
|
+
return false;
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
*(void **)origin = ptr;
|
|
1965
|
+
} break;
|
|
1966
|
+
|
|
1967
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
#undef PUSH_INTEGER_SWAP
|
|
1971
|
+
#undef PUSH_INTEGER
|
|
1972
|
+
|
|
1973
|
+
// Keep memory around if any was allocated
|
|
1974
|
+
if (mem.allocator.IsUsed()) {
|
|
1975
|
+
LinkedAllocator *copy = instance->encode_map.FindValue(origin, nullptr);
|
|
1976
|
+
|
|
1977
|
+
if (!copy) {
|
|
1978
|
+
copy = instance->encode_allocators.AppendDefault();
|
|
1979
|
+
instance->encode_map.Set(origin, copy);
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1982
|
+
std::swap(mem.allocator, *copy);
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
return true;
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1877
1988
|
}
|
package/src/koffi/src/call.hh
CHANGED
|
@@ -21,7 +21,6 @@ struct alignas(8) CallData {
|
|
|
21
21
|
struct OutArgument {
|
|
22
22
|
enum class Kind {
|
|
23
23
|
Array,
|
|
24
|
-
Buffer,
|
|
25
24
|
String,
|
|
26
25
|
String16,
|
|
27
26
|
String32,
|
|
@@ -180,4 +179,6 @@ void PerformAsyncRelay(napi_env env, napi_value callback, void *ctx, void *udata
|
|
|
180
179
|
|
|
181
180
|
void *GetTrampoline(int idx);
|
|
182
181
|
|
|
182
|
+
bool Encode(InstanceData *instance, uint8_t *ptr, napi_value value, const TypeInfo *type);
|
|
183
|
+
|
|
183
184
|
}
|