koffi 2.15.1 → 2.16.0-beta.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/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/index.d.ts +11 -9
- package/index.js +8 -8
- package/indirect.js +8 -8
- package/package.json +1 -1
- package/src/koffi/src/abi_arm32.cc +222 -219
- package/src/koffi/src/abi_arm32_asm.S +1 -29
- package/src/koffi/src/abi_arm64.cc +257 -235
- package/src/koffi/src/abi_arm64_asm.S +1 -32
- package/src/koffi/src/abi_arm64_asm.asm +1 -23
- package/src/koffi/src/abi_loong64_asm.S +1 -25
- package/src/koffi/src/abi_riscv64.cc +220 -217
- package/src/koffi/src/abi_riscv64_asm.S +1 -25
- package/src/koffi/src/abi_x64_sysv.cc +196 -192
- package/src/koffi/src/abi_x64_sysv_asm.S +1 -31
- package/src/koffi/src/abi_x64_win.cc +188 -172
- package/src/koffi/src/abi_x64_win_asm.S +1 -19
- package/src/koffi/src/abi_x64_win_asm.asm +1 -21
- package/src/koffi/src/abi_x86.cc +224 -189
- package/src/koffi/src/abi_x86_asm.S +6 -25
- package/src/koffi/src/abi_x86_asm.asm +9 -22
- package/src/koffi/src/call.cc +246 -428
- package/src/koffi/src/call.hh +9 -8
- package/src/koffi/src/ffi.cc +140 -87
- package/src/koffi/src/ffi.hh +12 -58
- package/src/koffi/src/primitives.inc +39 -0
- package/src/koffi/src/trampolines/armasm.inc +0 -32770
- package/src/koffi/src/trampolines/gnu.inc +0 -24578
- package/src/koffi/src/trampolines/masm32.inc +0 -32770
- package/src/koffi/src/trampolines/masm64.inc +0 -32770
- package/src/koffi/src/trampolines/prototypes.inc +16385 -16385
- package/src/koffi/src/util.cc +149 -107
- package/src/koffi/src/util.hh +76 -40
package/src/koffi/src/util.cc
CHANGED
|
@@ -532,7 +532,7 @@ const char *GetValueType(const InstanceData *instance, Napi::Value value)
|
|
|
532
532
|
if (CheckValueTag(value, &TypeInfoMarker))
|
|
533
533
|
return "Type";
|
|
534
534
|
for (const TypeInfo &type: instance->types) {
|
|
535
|
-
if (type.ref.
|
|
535
|
+
if (type.ref.type && CheckValueTag(value, type.ref.type))
|
|
536
536
|
return type.name;
|
|
537
537
|
}
|
|
538
538
|
|
|
@@ -857,8 +857,7 @@ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type)
|
|
|
857
857
|
const char32_t *str32 = *(const char32_t **)src;
|
|
858
858
|
obj.Set(member.name, str32 ? MakeStringFromUTF32(env, str32) : env.Null());
|
|
859
859
|
} break;
|
|
860
|
-
case PrimitiveKind::Pointer:
|
|
861
|
-
case PrimitiveKind::Callback: {
|
|
860
|
+
case PrimitiveKind::Pointer: {
|
|
862
861
|
void *ptr2 = *(void **)src;
|
|
863
862
|
|
|
864
863
|
if (member.countedby >= 0) {
|
|
@@ -867,19 +866,25 @@ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type)
|
|
|
867
866
|
|
|
868
867
|
Napi::Value value = DecodeArray(env, (const uint8_t *)ptr2, member.type, len);
|
|
869
868
|
obj.Set(member.name, value);
|
|
870
|
-
} else if (ptr2) {
|
|
871
|
-
Napi::External<void> external = Napi::External<void>::New(env, ptr2);
|
|
872
|
-
SetValueTag(external, member.type->ref.marker);
|
|
873
|
-
|
|
874
|
-
obj.Set(member.name, external);
|
|
875
869
|
} else {
|
|
876
|
-
|
|
870
|
+
Napi::Value p = ptr2 ? WrapPointer(env, member.type->ref.type, ptr2) : env.Null();
|
|
871
|
+
obj.Set(member.name, p);
|
|
877
872
|
}
|
|
878
873
|
|
|
879
874
|
if (member.type->dispose) {
|
|
880
875
|
member.type->dispose(env, member.type, ptr2);
|
|
881
876
|
}
|
|
882
877
|
} break;
|
|
878
|
+
case PrimitiveKind::Callback: {
|
|
879
|
+
void *ptr2 = *(void **)src;
|
|
880
|
+
|
|
881
|
+
Napi::Value p = ptr2 ? WrapCallback(env, member.type->ref.type, ptr2) : env.Null();
|
|
882
|
+
obj.Set(member.name, p);
|
|
883
|
+
|
|
884
|
+
if (member.type->dispose) {
|
|
885
|
+
member.type->dispose(env, member.type, ptr2);
|
|
886
|
+
}
|
|
887
|
+
} break;
|
|
883
888
|
case PrimitiveKind::Record:
|
|
884
889
|
case PrimitiveKind::Union: {
|
|
885
890
|
Napi::Object obj2 = DecodeObject(env, src, member.type);
|
|
@@ -936,7 +941,8 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
936
941
|
\
|
|
937
942
|
return array; \
|
|
938
943
|
} while (false)
|
|
939
|
-
|
|
944
|
+
|
|
945
|
+
#define POP_NUMBERS(TypedArrayType, CType) \
|
|
940
946
|
do { \
|
|
941
947
|
if (type->hint == ArrayHint::Array) { \
|
|
942
948
|
POP_ARRAY({ \
|
|
@@ -952,7 +958,7 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
952
958
|
return array; \
|
|
953
959
|
} \
|
|
954
960
|
} while (false)
|
|
955
|
-
#define
|
|
961
|
+
#define POP_NUMBERS_SWAP(TypedArrayType, CType) \
|
|
956
962
|
do { \
|
|
957
963
|
if (type->hint == ArrayHint::Array) { \
|
|
958
964
|
POP_ARRAY({ \
|
|
@@ -988,9 +994,9 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
988
994
|
return str;
|
|
989
995
|
}
|
|
990
996
|
|
|
991
|
-
|
|
997
|
+
POP_NUMBERS(Int8Array, int8_t);
|
|
992
998
|
} break;
|
|
993
|
-
case PrimitiveKind::UInt8: {
|
|
999
|
+
case PrimitiveKind::UInt8: { POP_NUMBERS(Uint8Array, uint8_t); } break;
|
|
994
1000
|
case PrimitiveKind::Int16: {
|
|
995
1001
|
if (type->hint == ArrayHint::String) {
|
|
996
1002
|
const char16_t *ptr = (const char16_t *)origin;
|
|
@@ -1000,11 +1006,11 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
1000
1006
|
return str;
|
|
1001
1007
|
}
|
|
1002
1008
|
|
|
1003
|
-
|
|
1009
|
+
POP_NUMBERS(Int16Array, int16_t);
|
|
1004
1010
|
} break;
|
|
1005
|
-
case PrimitiveKind::Int16S: {
|
|
1006
|
-
case PrimitiveKind::UInt16: {
|
|
1007
|
-
case PrimitiveKind::UInt16S: {
|
|
1011
|
+
case PrimitiveKind::Int16S: { POP_NUMBERS_SWAP(Int16Array, int16_t); } break;
|
|
1012
|
+
case PrimitiveKind::UInt16: { POP_NUMBERS(Uint16Array, uint16_t); } break;
|
|
1013
|
+
case PrimitiveKind::UInt16S: { POP_NUMBERS_SWAP(Uint16Array, uint16_t); } break;
|
|
1008
1014
|
case PrimitiveKind::Int32: {
|
|
1009
1015
|
if (type->hint == ArrayHint::String) {
|
|
1010
1016
|
const char32_t *ptr = (const char32_t *)origin;
|
|
@@ -1014,11 +1020,11 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
1014
1020
|
return str;
|
|
1015
1021
|
}
|
|
1016
1022
|
|
|
1017
|
-
|
|
1023
|
+
POP_NUMBERS(Int32Array, int32_t);
|
|
1018
1024
|
} break;
|
|
1019
|
-
case PrimitiveKind::Int32S: {
|
|
1020
|
-
case PrimitiveKind::UInt32: {
|
|
1021
|
-
case PrimitiveKind::UInt32S: {
|
|
1025
|
+
case PrimitiveKind::Int32S: { POP_NUMBERS_SWAP(Int32Array, int32_t); } break;
|
|
1026
|
+
case PrimitiveKind::UInt32: { POP_NUMBERS(Uint32Array, uint32_t); } break;
|
|
1027
|
+
case PrimitiveKind::UInt32S: { POP_NUMBERS_SWAP(Uint32Array, uint32_t); } break;
|
|
1022
1028
|
case PrimitiveKind::Int64: {
|
|
1023
1029
|
POP_ARRAY({
|
|
1024
1030
|
int64_t v = *(int64_t *)src;
|
|
@@ -1061,19 +1067,20 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
1061
1067
|
array.Set(i, str32 ? MakeStringFromUTF32(env, str32) : env.Null());
|
|
1062
1068
|
});
|
|
1063
1069
|
} break;
|
|
1064
|
-
case PrimitiveKind::Pointer:
|
|
1065
|
-
case PrimitiveKind::Callback: {
|
|
1070
|
+
case PrimitiveKind::Pointer: {
|
|
1066
1071
|
POP_ARRAY({
|
|
1067
1072
|
void *ptr2 = *(void **)src;
|
|
1068
1073
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1074
|
+
Napi::Value p = ptr2 ? WrapPointer(env, type->ref.type->ref.type, ptr2) : env.Null();
|
|
1075
|
+
array.Set(i, p);
|
|
1076
|
+
});
|
|
1077
|
+
} break;
|
|
1078
|
+
case PrimitiveKind::Callback: {
|
|
1079
|
+
POP_ARRAY({
|
|
1080
|
+
void *ptr2 = *(void **)src;
|
|
1072
1081
|
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
array.Set(i, env.Null());
|
|
1076
|
-
}
|
|
1082
|
+
Napi::Value p = ptr2 ? WrapCallback(env, type->ref.type->ref.type, ptr2) : env.Null();
|
|
1083
|
+
array.Set(i, p);
|
|
1077
1084
|
});
|
|
1078
1085
|
} break;
|
|
1079
1086
|
case PrimitiveKind::Record:
|
|
@@ -1089,14 +1096,15 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
1089
1096
|
array.Set(i, value);
|
|
1090
1097
|
});
|
|
1091
1098
|
} break;
|
|
1092
|
-
case PrimitiveKind::Float32: {
|
|
1093
|
-
case PrimitiveKind::Float64: {
|
|
1099
|
+
case PrimitiveKind::Float32: { POP_NUMBERS(Float32Array, float); } break;
|
|
1100
|
+
case PrimitiveKind::Float64: { POP_NUMBERS(Float64Array, double); } break;
|
|
1094
1101
|
|
|
1095
1102
|
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
1096
1103
|
}
|
|
1097
1104
|
|
|
1098
|
-
#undef
|
|
1099
|
-
#undef
|
|
1105
|
+
#undef POP_NUMBERS_SWAP
|
|
1106
|
+
#undef POP_NUMBERS
|
|
1107
|
+
|
|
1100
1108
|
#undef POP_ARRAY
|
|
1101
1109
|
|
|
1102
1110
|
K_UNREACHABLE();
|
|
@@ -1131,14 +1139,15 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
|
|
|
1131
1139
|
offset += ref->size; \
|
|
1132
1140
|
} \
|
|
1133
1141
|
} while (false)
|
|
1134
|
-
|
|
1142
|
+
|
|
1143
|
+
#define POP_NUMBERS(CType) \
|
|
1135
1144
|
do { \
|
|
1136
1145
|
POP_ARRAY({ \
|
|
1137
1146
|
double d = (double)*(CType *)src; \
|
|
1138
1147
|
array.Set(i, Napi::Number::New(env, d)); \
|
|
1139
1148
|
}); \
|
|
1140
1149
|
} while (false)
|
|
1141
|
-
#define
|
|
1150
|
+
#define POP_NUMBERS_SWAP(CType) \
|
|
1142
1151
|
do { \
|
|
1143
1152
|
POP_ARRAY({ \
|
|
1144
1153
|
CType v = *(CType *)src; \
|
|
@@ -1156,16 +1165,16 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
|
|
|
1156
1165
|
array.Set(i, Napi::Boolean::New(env, b));
|
|
1157
1166
|
});
|
|
1158
1167
|
} break;
|
|
1159
|
-
case PrimitiveKind::Int8: {
|
|
1160
|
-
case PrimitiveKind::UInt8: {
|
|
1161
|
-
case PrimitiveKind::Int16: {
|
|
1162
|
-
case PrimitiveKind::Int16S: {
|
|
1163
|
-
case PrimitiveKind::UInt16: {
|
|
1164
|
-
case PrimitiveKind::UInt16S: {
|
|
1165
|
-
case PrimitiveKind::Int32: {
|
|
1166
|
-
case PrimitiveKind::Int32S: {
|
|
1167
|
-
case PrimitiveKind::UInt32: {
|
|
1168
|
-
case PrimitiveKind::UInt32S: {
|
|
1168
|
+
case PrimitiveKind::Int8: { POP_NUMBERS(int8_t); } break;
|
|
1169
|
+
case PrimitiveKind::UInt8: { POP_NUMBERS(uint8_t); } break;
|
|
1170
|
+
case PrimitiveKind::Int16: { POP_NUMBERS(int16_t); } break;
|
|
1171
|
+
case PrimitiveKind::Int16S: { POP_NUMBERS_SWAP(int16_t); } break;
|
|
1172
|
+
case PrimitiveKind::UInt16: { POP_NUMBERS(uint16_t); } break;
|
|
1173
|
+
case PrimitiveKind::UInt16S: { POP_NUMBERS_SWAP(uint16_t); } break;
|
|
1174
|
+
case PrimitiveKind::Int32: { POP_NUMBERS(int32_t); } break;
|
|
1175
|
+
case PrimitiveKind::Int32S: { POP_NUMBERS_SWAP(int32_t); } break;
|
|
1176
|
+
case PrimitiveKind::UInt32: { POP_NUMBERS(uint32_t); } break;
|
|
1177
|
+
case PrimitiveKind::UInt32S: { POP_NUMBERS_SWAP(uint32_t); } break;
|
|
1169
1178
|
case PrimitiveKind::Int64: {
|
|
1170
1179
|
POP_ARRAY({
|
|
1171
1180
|
int64_t v = *(int64_t *)src;
|
|
@@ -1220,19 +1229,24 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
|
|
|
1220
1229
|
}
|
|
1221
1230
|
});
|
|
1222
1231
|
} break;
|
|
1223
|
-
case PrimitiveKind::Pointer:
|
|
1224
|
-
case PrimitiveKind::Callback: {
|
|
1232
|
+
case PrimitiveKind::Pointer: {
|
|
1225
1233
|
POP_ARRAY({
|
|
1226
1234
|
void *ptr2 = *(void **)src;
|
|
1227
1235
|
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
SetValueTag(external, ref->ref.marker);
|
|
1236
|
+
Napi::Value p = ptr2 ? WrapPointer(env, ref->ref.type, ptr2) : env.Null();
|
|
1237
|
+
array.Set(i, p);
|
|
1231
1238
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
array.Set(i, env.Null());
|
|
1239
|
+
if (ref->dispose) {
|
|
1240
|
+
ref->dispose(env, ref, ptr2);
|
|
1235
1241
|
}
|
|
1242
|
+
});
|
|
1243
|
+
} break;
|
|
1244
|
+
case PrimitiveKind::Callback: {
|
|
1245
|
+
POP_ARRAY({
|
|
1246
|
+
void *ptr2 = *(void **)src;
|
|
1247
|
+
|
|
1248
|
+
Napi::Value p = ptr2 ? WrapCallback(env, ref->ref.type, ptr2) : env.Null();
|
|
1249
|
+
array.Set(i, p);
|
|
1236
1250
|
|
|
1237
1251
|
if (ref->dispose) {
|
|
1238
1252
|
ref->dispose(env, ref, ptr2);
|
|
@@ -1252,14 +1266,15 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
|
|
|
1252
1266
|
array.Set(i, value);
|
|
1253
1267
|
});
|
|
1254
1268
|
} break;
|
|
1255
|
-
case PrimitiveKind::Float32: {
|
|
1256
|
-
case PrimitiveKind::Float64: {
|
|
1269
|
+
case PrimitiveKind::Float32: { POP_NUMBERS(float); } break;
|
|
1270
|
+
case PrimitiveKind::Float64: { POP_NUMBERS(double); } break;
|
|
1257
1271
|
|
|
1258
1272
|
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
1259
1273
|
}
|
|
1260
1274
|
|
|
1261
|
-
#undef
|
|
1262
|
-
#undef
|
|
1275
|
+
#undef POP_NUMBERS_SWAP
|
|
1276
|
+
#undef POP_NUMBERS
|
|
1277
|
+
|
|
1263
1278
|
#undef POP_ARRAY
|
|
1264
1279
|
}
|
|
1265
1280
|
|
|
@@ -1294,14 +1309,9 @@ Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, const S
|
|
|
1294
1309
|
Napi::Env env = value.Env();
|
|
1295
1310
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1296
1311
|
|
|
1297
|
-
const uint8_t *
|
|
1298
|
-
|
|
1299
|
-
if (value.IsExternal()) {
|
|
1300
|
-
Napi::External<void> external = value.As<Napi::External<void>>();
|
|
1301
|
-
ptr = (const uint8_t *)external.Data();
|
|
1302
|
-
} else if (IsRawBuffer(value)) {
|
|
1303
|
-
Span<uint8_t> buffer = GetRawBuffer(value);
|
|
1312
|
+
const uint8_t *src = nullptr;
|
|
1304
1313
|
|
|
1314
|
+
if (Span<uint8_t> buffer = {}; TryBuffer(value, &buffer)) {
|
|
1305
1315
|
if (offset < 0) [[unlikely]] {
|
|
1306
1316
|
ThrowError<Napi::Error>(env, "Offset must be >= 0");
|
|
1307
1317
|
return env.Null();
|
|
@@ -1312,17 +1322,19 @@ Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, const S
|
|
|
1312
1322
|
return env.Null();
|
|
1313
1323
|
}
|
|
1314
1324
|
|
|
1315
|
-
|
|
1325
|
+
src = (const uint8_t *)buffer.ptr;
|
|
1326
|
+
} else if (void *ptr = nullptr; TryPointer(value, &ptr)) {
|
|
1327
|
+
src = (const uint8_t *)ptr;
|
|
1316
1328
|
} else {
|
|
1317
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for variable, expected
|
|
1329
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for variable, expected pointer", GetValueType(instance, value));
|
|
1318
1330
|
return env.Null();
|
|
1319
1331
|
}
|
|
1320
1332
|
|
|
1321
|
-
if (!
|
|
1333
|
+
if (!src)
|
|
1322
1334
|
return env.Null();
|
|
1323
|
-
|
|
1335
|
+
src += offset;
|
|
1324
1336
|
|
|
1325
|
-
Napi::Value ret = Decode(env,
|
|
1337
|
+
Napi::Value ret = Decode(env, src, type, len);
|
|
1326
1338
|
return ret;
|
|
1327
1339
|
}
|
|
1328
1340
|
|
|
@@ -1429,10 +1441,13 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1429
1441
|
return str32 ? MakeStringFromUTF32(env, str32) : env.Null();
|
|
1430
1442
|
}
|
|
1431
1443
|
} break;
|
|
1432
|
-
case PrimitiveKind::Pointer:
|
|
1444
|
+
case PrimitiveKind::Pointer: {
|
|
1445
|
+
void *ptr2 = *(void **)ptr;
|
|
1446
|
+
return ptr2 ? WrapPointer(env, type->ref.type, ptr2) : env.Null();
|
|
1447
|
+
} break;
|
|
1433
1448
|
case PrimitiveKind::Callback: {
|
|
1434
1449
|
void *ptr2 = *(void **)ptr;
|
|
1435
|
-
return ptr2 ?
|
|
1450
|
+
return ptr2 ? WrapCallback(env, type->ref.type, ptr2) : env.Null();
|
|
1436
1451
|
} break;
|
|
1437
1452
|
case PrimitiveKind::Record:
|
|
1438
1453
|
case PrimitiveKind::Union: {
|
|
@@ -1462,10 +1477,12 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1462
1477
|
|
|
1463
1478
|
memcpy((void *)func, proto, K_SIZE(*proto));
|
|
1464
1479
|
memset((void *)&func->parameters, 0, K_SIZE(func->parameters));
|
|
1465
|
-
func->
|
|
1480
|
+
memset((void *)&func->primitives, 0, K_SIZE(func->primitives));
|
|
1466
1481
|
|
|
1467
1482
|
func->name = "<anonymous>";
|
|
1468
1483
|
func->native = (void *)ptr;
|
|
1484
|
+
func->parameters = proto->parameters;
|
|
1485
|
+
func->primitives = proto->primitives;
|
|
1469
1486
|
|
|
1470
1487
|
// Fix back parameter offset
|
|
1471
1488
|
for (ParameterInfo ¶m: func->parameters) {
|
|
@@ -1489,14 +1506,9 @@ bool Encode(Napi::Value ref, Size offset, Napi::Value value, const TypeInfo *typ
|
|
|
1489
1506
|
Napi::Env env = ref.Env();
|
|
1490
1507
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1491
1508
|
|
|
1492
|
-
uint8_t *
|
|
1493
|
-
|
|
1494
|
-
if (ref.IsExternal()) {
|
|
1495
|
-
Napi::External<void> external = ref.As<Napi::External<void>>();
|
|
1496
|
-
ptr = (uint8_t *)external.Data();
|
|
1497
|
-
} else if (IsRawBuffer(ref)) {
|
|
1498
|
-
Span<uint8_t> buffer = GetRawBuffer(ref);
|
|
1509
|
+
uint8_t *dest = nullptr;
|
|
1499
1510
|
|
|
1511
|
+
if (Span<uint8_t> buffer = {}; TryBuffer(ref, &buffer)) {
|
|
1500
1512
|
if (offset < 0) [[unlikely]] {
|
|
1501
1513
|
ThrowError<Napi::Error>(env, "Offset must be >= 0");
|
|
1502
1514
|
return env.Null();
|
|
@@ -1507,19 +1519,21 @@ bool Encode(Napi::Value ref, Size offset, Napi::Value value, const TypeInfo *typ
|
|
|
1507
1519
|
return env.Null();
|
|
1508
1520
|
}
|
|
1509
1521
|
|
|
1510
|
-
|
|
1522
|
+
dest = (uint8_t *)buffer.ptr;
|
|
1523
|
+
} else if (void *ptr = nullptr; TryPointer(ref, &ptr)) {
|
|
1524
|
+
dest = (uint8_t *)ptr;
|
|
1511
1525
|
} else {
|
|
1512
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for reference, expected
|
|
1526
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for reference, expected pointer", GetValueType(instance, ref));
|
|
1513
1527
|
return env.Null();
|
|
1514
1528
|
}
|
|
1515
1529
|
|
|
1516
|
-
if (!
|
|
1530
|
+
if (!dest) [[unlikely]] {
|
|
1517
1531
|
ThrowError<Napi::Error>(env, "Cannot encode data in NULL pointer");
|
|
1518
1532
|
return env.Null();
|
|
1519
1533
|
}
|
|
1520
|
-
|
|
1534
|
+
dest += offset;
|
|
1521
1535
|
|
|
1522
|
-
return Encode(env,
|
|
1536
|
+
return Encode(env, dest, value, type, len);
|
|
1523
1537
|
}
|
|
1524
1538
|
|
|
1525
1539
|
bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *type, const Size *len)
|
|
@@ -1543,22 +1557,24 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1543
1557
|
|
|
1544
1558
|
#define PUSH_INTEGER(CType) \
|
|
1545
1559
|
do { \
|
|
1546
|
-
|
|
1560
|
+
CType v; \
|
|
1561
|
+
\
|
|
1562
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
1547
1563
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
1548
1564
|
return false; \
|
|
1549
1565
|
} \
|
|
1550
1566
|
\
|
|
1551
|
-
CType v = GetNumber<CType>(value); \
|
|
1552
1567
|
*(CType *)origin = v; \
|
|
1553
1568
|
} while (false)
|
|
1554
1569
|
#define PUSH_INTEGER_SWAP(CType) \
|
|
1555
1570
|
do { \
|
|
1556
|
-
|
|
1571
|
+
CType v; \
|
|
1572
|
+
\
|
|
1573
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
1557
1574
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
1558
1575
|
return false; \
|
|
1559
1576
|
} \
|
|
1560
1577
|
\
|
|
1561
|
-
CType v = GetNumber<CType>(value); \
|
|
1562
1578
|
*(CType *)origin = ReverseBytes(v); \
|
|
1563
1579
|
} while (false)
|
|
1564
1580
|
|
|
@@ -1566,12 +1582,14 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1566
1582
|
case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
|
|
1567
1583
|
|
|
1568
1584
|
case PrimitiveKind::Bool: {
|
|
1569
|
-
|
|
1585
|
+
bool b;
|
|
1586
|
+
napi_status status = napi_get_value_bool(env, value, &b);
|
|
1587
|
+
|
|
1588
|
+
if (status != napi_ok) [[unlikely]] {
|
|
1570
1589
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
1571
1590
|
return false;
|
|
1572
1591
|
}
|
|
1573
1592
|
|
|
1574
|
-
bool b = value.As<Napi::Boolean>();
|
|
1575
1593
|
*(bool *)origin = b;
|
|
1576
1594
|
} break;
|
|
1577
1595
|
case PrimitiveKind::Int8: { PUSH_INTEGER(int8_t); } break;
|
|
@@ -1629,8 +1647,7 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1629
1647
|
Napi::Array array = value.As<Napi::Array>();
|
|
1630
1648
|
if (!call.PushNormalArray(array, type, type->size, origin))
|
|
1631
1649
|
return false;
|
|
1632
|
-
} else if (
|
|
1633
|
-
Span<const uint8_t> buffer = GetRawBuffer(value);
|
|
1650
|
+
} else if (Span<uint8_t> buffer = {}; TryBuffer(value, &buffer)) {
|
|
1634
1651
|
call.PushBuffer(buffer, type, origin);
|
|
1635
1652
|
} else if (value.IsString()) {
|
|
1636
1653
|
if (!call.PushStringArray(value, type, origin))
|
|
@@ -1641,35 +1658,34 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1641
1658
|
}
|
|
1642
1659
|
} break;
|
|
1643
1660
|
case PrimitiveKind::Float32: {
|
|
1644
|
-
|
|
1661
|
+
float f;
|
|
1662
|
+
|
|
1663
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
1645
1664
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
1646
1665
|
return false;
|
|
1647
1666
|
}
|
|
1648
1667
|
|
|
1649
|
-
float f = GetNumber<float>(value);
|
|
1650
1668
|
*(float *)origin = f;
|
|
1651
1669
|
} break;
|
|
1652
1670
|
case PrimitiveKind::Float64: {
|
|
1653
|
-
|
|
1671
|
+
double d;
|
|
1672
|
+
|
|
1673
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
1654
1674
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
1655
1675
|
return false;
|
|
1656
1676
|
}
|
|
1657
1677
|
|
|
1658
|
-
double d = GetNumber<double>(value);
|
|
1659
1678
|
*(double *)origin = d;
|
|
1660
1679
|
} break;
|
|
1661
1680
|
case PrimitiveKind::Callback: {
|
|
1662
1681
|
void *ptr;
|
|
1663
1682
|
|
|
1664
|
-
if (value
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
ptr = nullptr;
|
|
1671
|
-
} else {
|
|
1672
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
1683
|
+
if (!TryPointer(value, &ptr)) [[unlikely]] {
|
|
1684
|
+
if (value.IsFunction()) {
|
|
1685
|
+
ThrowError<Napi::Error>(env, "Cannot encode non-registered callback");
|
|
1686
|
+
} else {
|
|
1687
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
1688
|
+
}
|
|
1673
1689
|
return false;
|
|
1674
1690
|
}
|
|
1675
1691
|
|
|
@@ -1741,6 +1757,32 @@ Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func)
|
|
|
1741
1757
|
return wrapper;
|
|
1742
1758
|
}
|
|
1743
1759
|
|
|
1760
|
+
Napi::Value WrapPointer(Napi::Env env, const TypeInfo *ref, void *ptr)
|
|
1761
|
+
{
|
|
1762
|
+
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1763
|
+
|
|
1764
|
+
if (instance->config.fast_pointers) {
|
|
1765
|
+
Napi::BigInt big = Napi::BigInt::New(env, (uint64_t)(uintptr_t)ptr);
|
|
1766
|
+
return big;
|
|
1767
|
+
} else {
|
|
1768
|
+
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
1769
|
+
return external;
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
Napi::Value WrapCallback(Napi::Env env, const TypeInfo *ref, void *ptr)
|
|
1774
|
+
{
|
|
1775
|
+
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1776
|
+
|
|
1777
|
+
if (instance->config.fast_callbacks) {
|
|
1778
|
+
Napi::BigInt big = Napi::BigInt::New(env, (uint64_t)(uintptr_t)ptr);
|
|
1779
|
+
return big;
|
|
1780
|
+
} else {
|
|
1781
|
+
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
1782
|
+
return external;
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1744
1786
|
bool DetectCallConvention(Span<const char> name, CallConvention *out_convention)
|
|
1745
1787
|
{
|
|
1746
1788
|
if (name == "__cdecl") {
|
|
@@ -1797,7 +1839,7 @@ void DumpMemory(const char *type, Span<const uint8_t> bytes)
|
|
|
1797
1839
|
PrintLn(StdErr, "%1 at 0x%2 (%3):", type, bytes.ptr, FmtMemSize(bytes.len));
|
|
1798
1840
|
|
|
1799
1841
|
for (const uint8_t *ptr = bytes.begin(); ptr < bytes.end();) {
|
|
1800
|
-
Print(StdErr, " [0x%1 %2 %3] ",
|
|
1842
|
+
Print(StdErr, " [0x%1 %2 %3] ", FmtHex((uintptr_t)ptr, 16),
|
|
1801
1843
|
FmtInt((ptr - bytes.begin()) / sizeof(void *), 4, ' '),
|
|
1802
1844
|
FmtInt(ptr - bytes.begin(), 4, ' '));
|
|
1803
1845
|
for (int i = 0; ptr < bytes.end() && i < (int)sizeof(void *); i++, ptr++) {
|
package/src/koffi/src/util.hh
CHANGED
|
@@ -98,64 +98,97 @@ static inline bool IsObject(Napi::Value value)
|
|
|
98
98
|
return value.IsObject() && !IsNullOrUndefined(value) && !value.IsArray();
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return value.IsTypedArray() || value.IsArrayBuffer();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
static inline Span<uint8_t> GetRawBuffer(Napi::Value value)
|
|
101
|
+
template <typename T>
|
|
102
|
+
bool TryNumber(Napi::Value value, T *out_value)
|
|
107
103
|
{
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
104
|
+
// Assume number first
|
|
105
|
+
{
|
|
106
|
+
T v;
|
|
107
|
+
napi_status status;
|
|
108
|
+
|
|
109
|
+
if constexpr (std::is_same_v<T, double>) {
|
|
110
|
+
status = napi_get_value_double(value.Env(), value, &v);
|
|
111
|
+
} else if constexpr (std::is_same_v<T, float>) {
|
|
112
|
+
double d;
|
|
113
|
+
status = napi_get_value_double(value.Env(), value, &d);
|
|
114
|
+
v = (float)d;
|
|
115
|
+
} else {
|
|
116
|
+
int64_t i64;
|
|
117
|
+
status = napi_get_value_int64(value.Env(), value, &i64);
|
|
118
|
+
v = (T)i64;
|
|
119
|
+
}
|
|
112
120
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
case napi_int8_array: { length *= 1; } break;
|
|
117
|
-
case napi_uint8_array: { length *= 1; } break;
|
|
118
|
-
case napi_uint8_clamped_array: { length *= 1; } break;
|
|
119
|
-
case napi_int16_array: { length *= 2; } break;
|
|
120
|
-
case napi_uint16_array: { length *= 2; } break;
|
|
121
|
-
case napi_int32_array: { length *= 4; } break;
|
|
122
|
-
case napi_uint32_array: { length *= 4; } break;
|
|
123
|
-
case napi_float16_array: { length *= 2; } break;
|
|
124
|
-
case napi_float32_array: { length *= 4; } break;
|
|
125
|
-
case napi_float64_array: { length *= 8; } break;
|
|
126
|
-
case napi_bigint64_array: { length *= 8; } break;
|
|
127
|
-
case napi_biguint64_array: { length *= 8; } break;
|
|
121
|
+
if (status == napi_ok) [[likely]] {
|
|
122
|
+
*out_value = v;
|
|
123
|
+
return true;
|
|
128
124
|
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (value.IsBigInt()) {
|
|
128
|
+
Napi::BigInt bigint = value.As<Napi::BigInt>();
|
|
129
|
+
|
|
130
|
+
bool lossless;
|
|
131
|
+
*out_value = (T)bigint.Uint64Value(&lossless);
|
|
132
|
+
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
129
138
|
|
|
130
|
-
|
|
139
|
+
static inline bool TryPointer(Napi::Value value, void **out_ptr)
|
|
140
|
+
{
|
|
141
|
+
if (IsNullOrUndefined(value)) {
|
|
142
|
+
*out_ptr = nullptr;
|
|
143
|
+
return true;
|
|
144
|
+
} else if (uintptr_t ptr = 0; TryNumber(value, &ptr)) {
|
|
145
|
+
*out_ptr = (void *)ptr;
|
|
146
|
+
return true;
|
|
147
|
+
} else if (value.IsTypedArray()) {
|
|
148
|
+
napi_get_typedarray_info(value.Env(), value, nullptr, nullptr, out_ptr, nullptr, nullptr);
|
|
149
|
+
return true;
|
|
150
|
+
} else if (value.IsExternal()) {
|
|
151
|
+
Napi::External<void> external = value.As<Napi::External<void>>();
|
|
152
|
+
|
|
153
|
+
*out_ptr = (void *)external.Data();
|
|
154
|
+
return true;
|
|
131
155
|
} else if (value.IsArrayBuffer()) {
|
|
132
156
|
Napi::ArrayBuffer buffer = value.As<Napi::ArrayBuffer>();
|
|
133
157
|
|
|
134
|
-
|
|
158
|
+
*out_ptr = (void *)buffer.Data();
|
|
159
|
+
return true;
|
|
135
160
|
}
|
|
136
161
|
|
|
137
|
-
|
|
162
|
+
return false;
|
|
138
163
|
}
|
|
139
164
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
template <typename T>
|
|
143
|
-
T GetNumber(Napi::Value value)
|
|
165
|
+
static inline bool TryBuffer(Napi::Value value, Span<uint8_t> *out_buffer)
|
|
144
166
|
{
|
|
145
|
-
|
|
167
|
+
// Before somewhere around Node 20.12, napi_get_buffer_info() would assert/crash
|
|
168
|
+
// when used with something it did not support, instead of returning napi_invalid_arg.
|
|
169
|
+
// So we need to call napi_is_buffer(), at least for now.
|
|
146
170
|
|
|
147
|
-
if (value.
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
Napi::BigInt bigint = value.As<Napi::BigInt>();
|
|
171
|
+
if (value.IsBuffer()) {
|
|
172
|
+
void *ptr = nullptr;
|
|
173
|
+
size_t length = 0;
|
|
151
174
|
|
|
152
|
-
|
|
153
|
-
|
|
175
|
+
// Assume it works
|
|
176
|
+
napi_get_buffer_info(value.Env(), value, &ptr, &length);
|
|
177
|
+
|
|
178
|
+
*out_buffer = MakeSpan((uint8_t *)ptr, (Size)length);
|
|
179
|
+
return true;
|
|
180
|
+
} else if (value.IsArrayBuffer()) {
|
|
181
|
+
Napi::ArrayBuffer buffer = value.As<Napi::ArrayBuffer>();
|
|
182
|
+
|
|
183
|
+
*out_buffer = MakeSpan((uint8_t *)buffer.Data(), (Size)buffer.ByteLength());
|
|
184
|
+
return true;
|
|
154
185
|
}
|
|
155
186
|
|
|
156
|
-
|
|
187
|
+
return false;
|
|
157
188
|
}
|
|
158
189
|
|
|
190
|
+
int GetTypedArrayType(const TypeInfo *type);
|
|
191
|
+
|
|
159
192
|
template <typename T>
|
|
160
193
|
Size NullTerminatedLength(const T *ptr)
|
|
161
194
|
{
|
|
@@ -227,6 +260,9 @@ static inline Napi::Array GetOwnPropertyNames(Napi::Object obj)
|
|
|
227
260
|
|
|
228
261
|
Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func);
|
|
229
262
|
|
|
263
|
+
Napi::Value WrapPointer(Napi::Env env, const TypeInfo *ref, void *ptr);
|
|
264
|
+
Napi::Value WrapCallback(Napi::Env env, const TypeInfo *ref, void *ptr);
|
|
265
|
+
|
|
230
266
|
bool DetectCallConvention(Span<const char> name, CallConvention *out_convention);
|
|
231
267
|
|
|
232
268
|
int AnalyseFlat(const TypeInfo *type, FunctionRef<void(const TypeInfo *type, int offset, int count)> func);
|