koffi 3.0.0 → 3.0.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 +9 -1
- package/README.md +5 -4
- package/cnoke.cjs +3 -3
- package/doc/benchmarks.md +23 -46
- package/doc/callbacks.md +4 -13
- package/doc/contribute.md +3 -3
- package/doc/index.md +3 -2
- package/doc/migration.md +100 -0
- package/doc/start.md +7 -5
- package/index.d.ts +308 -308
- package/index.js +2 -1
- package/indirect.d.ts +322 -0
- package/indirect.js +2 -1
- package/package.json +20 -18
- package/src/koffi/CMakeLists.txt +19 -12
- package/src/koffi/index.cjs +65 -16
- package/src/koffi/index.js +105 -16
- package/src/koffi/indirect.cjs +65 -16
- package/src/koffi/indirect.js +105 -16
- package/src/koffi/src/abi/arm64.cc +29 -29
- package/src/koffi/src/abi/riscv64.cc +29 -29
- package/src/koffi/src/abi/x64sysv.cc +25 -25
- package/src/koffi/src/abi/x64win.cc +63 -63
- package/src/koffi/src/abi/x86.cc +66 -65
- package/src/koffi/src/call.cc +2 -2
- package/src/koffi/src/ffi.cc +64 -8
- package/src/koffi/src/ffi.hh +9 -6
- package/src/koffi/src/primitives.inc +1 -4
- package/src/koffi/src/util.cc +175 -121
- package/src/koffi/src/util.hh +13 -14
package/src/koffi/src/util.cc
CHANGED
|
@@ -17,6 +17,8 @@ const napi_type_tag DirectionMarker = { 0xf9c306238b480580, 0xc2e168524a0823f5 }
|
|
|
17
17
|
const napi_type_tag UnionValueMarker = { 0x5eaf2245526a4c7d, 0x8c86c9ee2b96ffc8 };
|
|
18
18
|
const napi_type_tag CastMarker = { 0x77f459614a0a412f, 0x80b3dda1341dc8df };
|
|
19
19
|
|
|
20
|
+
#if !defined(EXTERNAL_TYPES)
|
|
21
|
+
|
|
20
22
|
Napi::Function TypeObject::InitClass(Napi::Env env)
|
|
21
23
|
{
|
|
22
24
|
Napi::Function constructor = DefineClass(env, "TypeObject", {});
|
|
@@ -43,6 +45,8 @@ void TypeObject::Finalize(Napi::BasicEnv env)
|
|
|
43
45
|
SuppressDestruct();
|
|
44
46
|
}
|
|
45
47
|
|
|
48
|
+
#endif
|
|
49
|
+
|
|
46
50
|
Napi::Function UnionValue::InitClass(Napi::Env env, const TypeInfo *type)
|
|
47
51
|
{
|
|
48
52
|
K_ASSERT(type->primitive == PrimitiveKind::Union);
|
|
@@ -104,7 +108,7 @@ Napi::Value UnionValue::Getter(const Napi::CallbackInfo &info)
|
|
|
104
108
|
Size idx = (Size)info.Data();
|
|
105
109
|
const RecordMember &member = type->members[idx];
|
|
106
110
|
|
|
107
|
-
|
|
111
|
+
napi_value value = nullptr;
|
|
108
112
|
|
|
109
113
|
if (idx == active_idx) {
|
|
110
114
|
value = Value().Get(instance->active_symbol.Value());
|
|
@@ -116,14 +120,14 @@ Napi::Value UnionValue::Getter(const Napi::CallbackInfo &info)
|
|
|
116
120
|
return env.Null();
|
|
117
121
|
}
|
|
118
122
|
|
|
119
|
-
value = Decode(
|
|
123
|
+
value = Decode(instance, raw.ptr, member.type);
|
|
120
124
|
|
|
121
125
|
Value().Set(instance->active_symbol.Value(), value);
|
|
122
126
|
active_idx = idx;
|
|
123
127
|
}
|
|
124
128
|
|
|
125
|
-
K_ASSERT(
|
|
126
|
-
return value;
|
|
129
|
+
K_ASSERT(value);
|
|
130
|
+
return Napi::Value(info.Env(), value);
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
void UnionValue::Setter(const Napi::CallbackInfo &info, const Napi::Value &value)
|
|
@@ -240,6 +244,16 @@ const TypeInfo *ResolveType(Napi::Value value, int *out_directions)
|
|
|
240
244
|
}
|
|
241
245
|
|
|
242
246
|
return type;
|
|
247
|
+
#if defined(EXTERNAL_TYPES)
|
|
248
|
+
} else if (kind == napi_external && CheckValueTag(env, value, &TypeObjectMarker)) {
|
|
249
|
+
Napi::External<TypeInfo> external = Napi::External<TypeInfo>(env, value);
|
|
250
|
+
const TypeInfo *type = external.Data();
|
|
251
|
+
|
|
252
|
+
if (out_directions) {
|
|
253
|
+
*out_directions = 1;
|
|
254
|
+
}
|
|
255
|
+
return type;
|
|
256
|
+
#else
|
|
243
257
|
} else if (kind == napi_object && CheckValueTag(env, value, &TypeObjectMarker)) {
|
|
244
258
|
TypeObject *defn = nullptr;
|
|
245
259
|
napi_unwrap(env, value, (void **)&defn);
|
|
@@ -248,6 +262,7 @@ const TypeInfo *ResolveType(Napi::Value value, int *out_directions)
|
|
|
248
262
|
*out_directions = 1;
|
|
249
263
|
}
|
|
250
264
|
return defn->GetType();
|
|
265
|
+
#endif
|
|
251
266
|
} else {
|
|
252
267
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value as type specifier, expected string or type", GetValueType(instance, value));
|
|
253
268
|
return nullptr;
|
|
@@ -513,14 +528,18 @@ TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len, A
|
|
|
513
528
|
return MakeArrayType(instance, ref, len, hint, false);
|
|
514
529
|
}
|
|
515
530
|
|
|
516
|
-
Napi::
|
|
531
|
+
Napi::Value WrapType(Napi::Env env, const TypeInfo *type, bool freeze)
|
|
517
532
|
{
|
|
518
533
|
if (type->defn.IsEmpty()) {
|
|
534
|
+
#if defined(EXTERNAL_TYPES)
|
|
535
|
+
Napi::Object defn = Napi::Object::New(env);
|
|
536
|
+
#else
|
|
519
537
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
520
538
|
|
|
521
539
|
Napi::External<TypeInfo> external = Napi::External<TypeInfo>::New(env, (TypeInfo *)type);
|
|
522
540
|
Napi::Object defn = instance->construct_type.New({ external });
|
|
523
541
|
SetValueTag(env, defn, &TypeObjectMarker);
|
|
542
|
+
#endif
|
|
524
543
|
|
|
525
544
|
defn.Set("name", Napi::String::New(env, type->name));
|
|
526
545
|
defn.Set("primitive", PrimitiveKindNames[(int)type->primitive]);
|
|
@@ -592,7 +611,14 @@ Napi::Object WrapType(Napi::Env env, const TypeInfo *type, bool freeze)
|
|
|
592
611
|
}
|
|
593
612
|
}
|
|
594
613
|
|
|
614
|
+
#if defined(EXTERNAL_TYPES)
|
|
615
|
+
Napi::External<TypeInfo> external = Napi::External<TypeInfo>::New(env, (TypeInfo *)type);
|
|
616
|
+
SetValueTag(env, external, &TypeObjectMarker);
|
|
617
|
+
|
|
618
|
+
return external;
|
|
619
|
+
#else
|
|
595
620
|
return type->defn.Value();
|
|
621
|
+
#endif
|
|
596
622
|
}
|
|
597
623
|
|
|
598
624
|
const TypeInfo *ReshapeType(InstanceData *instance, const TypeInfo *type, int32_t stride, uint16_t flags)
|
|
@@ -868,23 +894,6 @@ Napi::String MakeStringFromUTF32(Napi::Env env, const char32_t *ptr, Size len)
|
|
|
868
894
|
return str;
|
|
869
895
|
}
|
|
870
896
|
|
|
871
|
-
Napi::Object DecodeObject(Napi::Env env, const uint8_t *origin, const TypeInfo *type)
|
|
872
|
-
{
|
|
873
|
-
// We can't decode unions because we don't know which member is valid
|
|
874
|
-
if (type->primitive == PrimitiveKind::Union) {
|
|
875
|
-
Napi::External<void> external = Napi::External<void>::New(env, (void *)origin);
|
|
876
|
-
Napi::Object wrapper = type->construct.New({ external }).As<Napi::Object>();
|
|
877
|
-
SetValueTag(env, wrapper, &UnionValueMarker);
|
|
878
|
-
|
|
879
|
-
return wrapper;
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
Napi::Object obj = Napi::Object::New(env);
|
|
883
|
-
DecodeObject(env, obj, origin, type);
|
|
884
|
-
|
|
885
|
-
return obj;
|
|
886
|
-
}
|
|
887
|
-
|
|
888
897
|
static uint32_t DecodeDynamicLength(const uint8_t *origin, const RecordMember &by)
|
|
889
898
|
{
|
|
890
899
|
const uint8_t *src = origin + by.offset;
|
|
@@ -977,27 +986,16 @@ static uint32_t DecodeDynamicLength(const uint8_t *origin, const RecordMember &b
|
|
|
977
986
|
K_UNREACHABLE();
|
|
978
987
|
}
|
|
979
988
|
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
if (member.key) {
|
|
983
|
-
napi_value key = nullptr;
|
|
984
|
-
napi_get_reference_value(env, member.key, &key);
|
|
985
|
-
|
|
986
|
-
napi_status status = napi_set_property(env, obj, key, value);
|
|
987
|
-
K_ASSERT(status == napi_ok);
|
|
988
|
-
} else {
|
|
989
|
-
napi_status status = napi_set_named_property(env, obj, member.name, value);
|
|
990
|
-
K_ASSERT(status == napi_ok);
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const TypeInfo *type)
|
|
989
|
+
template <typename SetFunc>
|
|
990
|
+
static FORCE_INLINE void DecodeObject(InstanceData *instance, const uint8_t *origin, const TypeInfo *type, SetFunc set)
|
|
995
991
|
{
|
|
996
992
|
K_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
997
993
|
|
|
994
|
+
Napi::Env env = instance->env;
|
|
998
995
|
Span<const RecordMember> members = type->members;
|
|
999
996
|
|
|
1000
|
-
for (
|
|
997
|
+
for (Size i = 0; i < members.len; i++) {
|
|
998
|
+
const RecordMember &member = members[i];
|
|
1001
999
|
const uint8_t *src = origin + member.offset;
|
|
1002
1000
|
|
|
1003
1001
|
switch (member.type->primitive) {
|
|
@@ -1005,80 +1003,80 @@ void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const Ty
|
|
|
1005
1003
|
|
|
1006
1004
|
case PrimitiveKind::Bool: {
|
|
1007
1005
|
bool b = *(bool *)src;
|
|
1008
|
-
|
|
1006
|
+
set(i, member, Napi::Boolean::New(env, b));
|
|
1009
1007
|
} break;
|
|
1010
1008
|
case PrimitiveKind::Int8: {
|
|
1011
|
-
int8_t
|
|
1012
|
-
|
|
1009
|
+
int8_t v = *(int8_t *)src;
|
|
1010
|
+
set(i, member, NewInt(env, v));
|
|
1013
1011
|
} break;
|
|
1014
1012
|
case PrimitiveKind::UInt8: {
|
|
1015
|
-
uint8_t
|
|
1016
|
-
|
|
1013
|
+
uint8_t v = *(uint8_t *)src;
|
|
1014
|
+
set(i, member, NewInt(env, v));
|
|
1017
1015
|
} break;
|
|
1018
1016
|
case PrimitiveKind::Int16: {
|
|
1019
|
-
int16_t
|
|
1020
|
-
memcpy(&
|
|
1021
|
-
|
|
1017
|
+
int16_t v;
|
|
1018
|
+
memcpy(&v, src, 2);
|
|
1019
|
+
set(i, member, NewInt(env, v));
|
|
1022
1020
|
} break;
|
|
1023
1021
|
case PrimitiveKind::Int16S: {
|
|
1024
|
-
int16_t
|
|
1025
|
-
memcpy(&
|
|
1026
|
-
|
|
1022
|
+
int16_t v;
|
|
1023
|
+
memcpy(&v, src, 2);
|
|
1024
|
+
set(i, member, NewInt(env, ReverseBytes(v)));
|
|
1027
1025
|
} break;
|
|
1028
1026
|
case PrimitiveKind::UInt16: {
|
|
1029
|
-
uint16_t
|
|
1030
|
-
memcpy(&
|
|
1031
|
-
|
|
1027
|
+
uint16_t v;
|
|
1028
|
+
memcpy(&v, src, 2);
|
|
1029
|
+
set(i, member, NewInt(env, v));
|
|
1032
1030
|
} break;
|
|
1033
1031
|
case PrimitiveKind::UInt16S: {
|
|
1034
|
-
uint16_t
|
|
1035
|
-
memcpy(&
|
|
1036
|
-
|
|
1032
|
+
uint16_t v;
|
|
1033
|
+
memcpy(&v, src, 2);
|
|
1034
|
+
set(i, member, NewInt(env, ReverseBytes(v)));
|
|
1037
1035
|
} break;
|
|
1038
1036
|
case PrimitiveKind::Int32: {
|
|
1039
|
-
int32_t
|
|
1040
|
-
memcpy(&
|
|
1041
|
-
|
|
1037
|
+
int32_t v;
|
|
1038
|
+
memcpy(&v, src, 4);
|
|
1039
|
+
set(i, member, NewInt(env, v));
|
|
1042
1040
|
} break;
|
|
1043
1041
|
case PrimitiveKind::Int32S: {
|
|
1044
|
-
int32_t
|
|
1045
|
-
memcpy(&
|
|
1046
|
-
|
|
1042
|
+
int32_t v;
|
|
1043
|
+
memcpy(&v, src, 4);
|
|
1044
|
+
set(i, member, NewInt(env, ReverseBytes(v)));
|
|
1047
1045
|
} break;
|
|
1048
1046
|
case PrimitiveKind::UInt32: {
|
|
1049
|
-
uint32_t
|
|
1050
|
-
memcpy(&
|
|
1051
|
-
|
|
1047
|
+
uint32_t v;
|
|
1048
|
+
memcpy(&v, src, 4);
|
|
1049
|
+
set(i, member, NewInt(env, v));
|
|
1052
1050
|
} break;
|
|
1053
1051
|
case PrimitiveKind::UInt32S: {
|
|
1054
|
-
uint32_t
|
|
1055
|
-
memcpy(&
|
|
1056
|
-
|
|
1052
|
+
uint32_t v;
|
|
1053
|
+
memcpy(&v, src, 4);
|
|
1054
|
+
set(i, member, NewInt(env, ReverseBytes(v)));
|
|
1057
1055
|
} break;
|
|
1058
1056
|
case PrimitiveKind::Int64: {
|
|
1059
|
-
int64_t
|
|
1060
|
-
memcpy(&
|
|
1061
|
-
|
|
1057
|
+
int64_t v;
|
|
1058
|
+
memcpy(&v, src, 8);
|
|
1059
|
+
set(i, member, NewInt(env, v));
|
|
1062
1060
|
} break;
|
|
1063
1061
|
case PrimitiveKind::Int64S: {
|
|
1064
|
-
int64_t
|
|
1065
|
-
memcpy(&
|
|
1066
|
-
|
|
1062
|
+
int64_t v;
|
|
1063
|
+
memcpy(&v, src, 8);
|
|
1064
|
+
set(i, member, NewInt(env, ReverseBytes(v)));
|
|
1067
1065
|
} break;
|
|
1068
1066
|
case PrimitiveKind::UInt64: {
|
|
1069
|
-
uint64_t
|
|
1070
|
-
memcpy(&
|
|
1071
|
-
|
|
1067
|
+
uint64_t v;
|
|
1068
|
+
memcpy(&v, src, 8);
|
|
1069
|
+
set(i, member, NewInt(env, v));
|
|
1072
1070
|
} break;
|
|
1073
1071
|
case PrimitiveKind::UInt64S: {
|
|
1074
|
-
uint64_t
|
|
1075
|
-
memcpy(&
|
|
1076
|
-
|
|
1072
|
+
uint64_t v;
|
|
1073
|
+
memcpy(&v, src, 8);
|
|
1074
|
+
set(i, member, NewInt(env, ReverseBytes(v)));
|
|
1077
1075
|
} break;
|
|
1078
1076
|
case PrimitiveKind::String: {
|
|
1079
1077
|
const char *str;
|
|
1080
1078
|
memcpy(&str, src, K_SIZE(void *));
|
|
1081
|
-
|
|
1079
|
+
set(i, member, str ? Napi::String::New(env, str) : env.Null());
|
|
1082
1080
|
|
|
1083
1081
|
if (member.type->dispose) {
|
|
1084
1082
|
member.type->dispose(env, member.type, str);
|
|
@@ -1087,7 +1085,7 @@ void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const Ty
|
|
|
1087
1085
|
case PrimitiveKind::String16: {
|
|
1088
1086
|
const char16_t *str16;
|
|
1089
1087
|
memcpy(&str16, src, K_SIZE(void *));
|
|
1090
|
-
|
|
1088
|
+
set(i, member, str16 ? Napi::String::New(env, str16) : env.Null());
|
|
1091
1089
|
|
|
1092
1090
|
if (member.type->dispose) {
|
|
1093
1091
|
member.type->dispose(env, member.type, str16);
|
|
@@ -1096,7 +1094,7 @@ void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const Ty
|
|
|
1096
1094
|
case PrimitiveKind::String32: {
|
|
1097
1095
|
const char32_t *str32;
|
|
1098
1096
|
memcpy(&str32, src, K_SIZE(void *));
|
|
1099
|
-
|
|
1097
|
+
set(i, member, str32 ? MakeStringFromUTF32(env, str32) : env.Null());
|
|
1100
1098
|
} break;
|
|
1101
1099
|
case PrimitiveKind::Pointer: {
|
|
1102
1100
|
void *ptr2;
|
|
@@ -1106,11 +1104,11 @@ void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const Ty
|
|
|
1106
1104
|
const RecordMember &by = members[member.countedby];
|
|
1107
1105
|
uint32_t len = DecodeDynamicLength(origin, by);
|
|
1108
1106
|
|
|
1109
|
-
|
|
1110
|
-
|
|
1107
|
+
napi_value value = DecodeArray(instance, (const uint8_t *)ptr2, member.type, len);
|
|
1108
|
+
set(i, member, value);
|
|
1111
1109
|
} else {
|
|
1112
|
-
|
|
1113
|
-
|
|
1110
|
+
napi_value p = ptr2 ? WrapPointer(env, member.type->ref.type, ptr2) : env.Null();
|
|
1111
|
+
set(i, member, p);
|
|
1114
1112
|
}
|
|
1115
1113
|
|
|
1116
1114
|
if (member.type->dispose) {
|
|
@@ -1121,8 +1119,8 @@ void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const Ty
|
|
|
1121
1119
|
void *ptr2;
|
|
1122
1120
|
memcpy(&ptr2, src, K_SIZE(void *));
|
|
1123
1121
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1122
|
+
napi_value p = ptr2 ? WrapPointer(env, member.type->ref.type, ptr2) : env.Null();
|
|
1123
|
+
set(i, member, p);
|
|
1126
1124
|
|
|
1127
1125
|
if (member.type->dispose) {
|
|
1128
1126
|
member.type->dispose(env, member.type, ptr2);
|
|
@@ -1130,8 +1128,8 @@ void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const Ty
|
|
|
1130
1128
|
} break;
|
|
1131
1129
|
case PrimitiveKind::Record:
|
|
1132
1130
|
case PrimitiveKind::Union: {
|
|
1133
|
-
|
|
1134
|
-
|
|
1131
|
+
napi_value obj2 = DecodeObject(instance, src, member.type);
|
|
1132
|
+
set(i, member, obj2);
|
|
1135
1133
|
} break;
|
|
1136
1134
|
case PrimitiveKind::Array: {
|
|
1137
1135
|
if (member.countedby >= 0) {
|
|
@@ -1143,22 +1141,22 @@ void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const Ty
|
|
|
1143
1141
|
// Silently truncate result
|
|
1144
1142
|
len = std::min(len, max);
|
|
1145
1143
|
|
|
1146
|
-
|
|
1147
|
-
|
|
1144
|
+
napi_value value = DecodeArray(instance, src, member.type, len);
|
|
1145
|
+
set(i, member, value);
|
|
1148
1146
|
} else {
|
|
1149
|
-
|
|
1150
|
-
|
|
1147
|
+
napi_value value = DecodeArray(instance, src, member.type);
|
|
1148
|
+
set(i, member, value);
|
|
1151
1149
|
}
|
|
1152
1150
|
} break;
|
|
1153
1151
|
case PrimitiveKind::Float32: {
|
|
1154
1152
|
float f;
|
|
1155
1153
|
memcpy(&f, src, 4);
|
|
1156
|
-
|
|
1154
|
+
set(i, member, Napi::Number::New(env, (double)f));
|
|
1157
1155
|
} break;
|
|
1158
1156
|
case PrimitiveKind::Float64: {
|
|
1159
1157
|
double d;
|
|
1160
1158
|
memcpy(&d, src, 8);
|
|
1161
|
-
|
|
1159
|
+
set(i, member, Napi::Number::New(env, d));
|
|
1162
1160
|
} break;
|
|
1163
1161
|
|
|
1164
1162
|
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
@@ -1166,18 +1164,77 @@ void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const Ty
|
|
|
1166
1164
|
}
|
|
1167
1165
|
}
|
|
1168
1166
|
|
|
1169
|
-
|
|
1167
|
+
napi_value DecodeObject(InstanceData *instance, const uint8_t *origin, const TypeInfo *type)
|
|
1168
|
+
{
|
|
1169
|
+
Napi::Env env = instance->env;
|
|
1170
|
+
|
|
1171
|
+
// We can't decode unions because we don't know which member is valid
|
|
1172
|
+
if (type->primitive == PrimitiveKind::Union) {
|
|
1173
|
+
Napi::External<void> external = Napi::External<void>::New(env, (void *)origin);
|
|
1174
|
+
Napi::Object wrapper = type->construct.New({ external }).As<Napi::Object>();
|
|
1175
|
+
SetValueTag(env, wrapper, &UnionValueMarker);
|
|
1176
|
+
|
|
1177
|
+
return wrapper;
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
// Only supported in recent Node versions, and still experimental at this time
|
|
1181
|
+
if (node_api_create_object_with_properties && type->members.len <= 256) {
|
|
1182
|
+
napi_value properties[256];
|
|
1183
|
+
napi_value values[256];
|
|
1184
|
+
|
|
1185
|
+
DecodeObject(instance, origin, type, [&](Size i, const RecordMember &member, napi_value value) {
|
|
1186
|
+
napi_status status = napi_get_reference_value(env, member.key, &properties[i]);
|
|
1187
|
+
K_ASSERT(status == napi_ok);
|
|
1188
|
+
|
|
1189
|
+
values[i] = value;
|
|
1190
|
+
});
|
|
1191
|
+
|
|
1192
|
+
napi_value obj;
|
|
1193
|
+
napi_status status = node_api_create_object_with_properties(env, instance->object_constructor.Value(), properties, values, type->members.len, &obj);
|
|
1194
|
+
K_ASSERT(status == napi_ok);
|
|
1195
|
+
|
|
1196
|
+
return obj;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
Napi::Object obj = Napi::Object::New(env);
|
|
1200
|
+
DecodeObject(instance, obj, origin, type);
|
|
1201
|
+
|
|
1202
|
+
return obj;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
void DecodeObject(InstanceData *instance, napi_value obj, const uint8_t *origin, const TypeInfo *type)
|
|
1206
|
+
{
|
|
1207
|
+
Napi::Env env = instance->env;
|
|
1208
|
+
|
|
1209
|
+
if (node_api_create_property_key_utf8) {
|
|
1210
|
+
DecodeObject(instance, origin, type, [&](Size i, const RecordMember &member, napi_value value) {
|
|
1211
|
+
napi_value key = nullptr;
|
|
1212
|
+
napi_get_reference_value(env, member.key, &key);
|
|
1213
|
+
|
|
1214
|
+
napi_status status = napi_set_property(env, obj, key, value);
|
|
1215
|
+
K_ASSERT(status == napi_ok);
|
|
1216
|
+
});
|
|
1217
|
+
} else {
|
|
1218
|
+
DecodeObject(instance, origin, type, [&](Size i, const RecordMember &member, napi_value value) {
|
|
1219
|
+
napi_status status = napi_set_named_property(env, obj, member.name, value);
|
|
1220
|
+
K_ASSERT(status == napi_ok);
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
napi_value DecodeArray(InstanceData *instance, const uint8_t *origin, const TypeInfo *type)
|
|
1170
1226
|
{
|
|
1171
1227
|
K_ASSERT(type->primitive == PrimitiveKind::Array);
|
|
1172
1228
|
|
|
1173
1229
|
uint32_t len = type->size / type->ref.stride;
|
|
1174
|
-
return DecodeArray(
|
|
1230
|
+
return DecodeArray(instance, origin, type, len);
|
|
1175
1231
|
}
|
|
1176
1232
|
|
|
1177
|
-
|
|
1233
|
+
napi_value DecodeArray(InstanceData *instance, const uint8_t *origin, const TypeInfo *type, uint32_t len)
|
|
1178
1234
|
{
|
|
1179
1235
|
K_ASSERT(type->primitive == PrimitiveKind::Array || type->primitive == PrimitiveKind::Pointer);
|
|
1180
1236
|
|
|
1237
|
+
Napi::Env env = instance->env;
|
|
1181
1238
|
const TypeInfo *ref = type->ref.type;
|
|
1182
1239
|
int32_t stride = type->ref.stride;
|
|
1183
1240
|
|
|
@@ -1279,7 +1336,7 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
1279
1336
|
K_ASSERT(type->hint == ArrayHint::Array);
|
|
1280
1337
|
|
|
1281
1338
|
Napi::Array array = Napi::Array::New(env);
|
|
1282
|
-
DecodeElements(
|
|
1339
|
+
DecodeElements(instance, array, origin, type, len);
|
|
1283
1340
|
|
|
1284
1341
|
return array;
|
|
1285
1342
|
}
|
|
@@ -1287,10 +1344,11 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
1287
1344
|
K_UNREACHABLE();
|
|
1288
1345
|
}
|
|
1289
1346
|
|
|
1290
|
-
void DecodeElements(
|
|
1347
|
+
void DecodeElements(InstanceData *instance, napi_value array, const uint8_t *origin, const TypeInfo *type, uint32_t len)
|
|
1291
1348
|
{
|
|
1292
|
-
K_ASSERT(IsArray(env, array));
|
|
1349
|
+
K_ASSERT(IsArray(instance->env, array));
|
|
1293
1350
|
|
|
1351
|
+
Napi::Env env = instance->env;
|
|
1294
1352
|
const TypeInfo *ref = type->ref.type;
|
|
1295
1353
|
int32_t stride = type->ref.stride;
|
|
1296
1354
|
|
|
@@ -1377,7 +1435,7 @@ void DecodeElements(Napi::Env env, napi_value array, const uint8_t *origin, cons
|
|
|
1377
1435
|
POP_ARRAY({
|
|
1378
1436
|
void *ptr2 = *(void **)src;
|
|
1379
1437
|
|
|
1380
|
-
|
|
1438
|
+
napi_value p = ptr2 ? WrapPointer(env, ref->ref.type, ptr2) : env.Null();
|
|
1381
1439
|
napi_set_element(env, array, i, p);
|
|
1382
1440
|
|
|
1383
1441
|
if (ref->dispose) {
|
|
@@ -1389,7 +1447,7 @@ void DecodeElements(Napi::Env env, napi_value array, const uint8_t *origin, cons
|
|
|
1389
1447
|
POP_ARRAY({
|
|
1390
1448
|
void *ptr2 = *(void **)src;
|
|
1391
1449
|
|
|
1392
|
-
|
|
1450
|
+
napi_value p = ptr2 ? WrapPointer(env, ref->ref.type, ptr2) : env.Null();
|
|
1393
1451
|
napi_set_element(env, array, i, p);
|
|
1394
1452
|
|
|
1395
1453
|
if (ref->dispose) {
|
|
@@ -1400,13 +1458,13 @@ void DecodeElements(Napi::Env env, napi_value array, const uint8_t *origin, cons
|
|
|
1400
1458
|
case PrimitiveKind::Record:
|
|
1401
1459
|
case PrimitiveKind::Union: {
|
|
1402
1460
|
POP_ARRAY({
|
|
1403
|
-
|
|
1461
|
+
napi_value obj = DecodeObject(instance, src, ref);
|
|
1404
1462
|
napi_set_element(env, array, i, obj);
|
|
1405
1463
|
});
|
|
1406
1464
|
} break;
|
|
1407
1465
|
case PrimitiveKind::Array: {
|
|
1408
1466
|
POP_ARRAY({
|
|
1409
|
-
|
|
1467
|
+
napi_value value = DecodeArray(instance, src, ref);
|
|
1410
1468
|
napi_set_element(env, array, i, value);
|
|
1411
1469
|
});
|
|
1412
1470
|
} break;
|
|
@@ -1476,7 +1534,7 @@ void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *t
|
|
|
1476
1534
|
#undef SWAP
|
|
1477
1535
|
}
|
|
1478
1536
|
|
|
1479
|
-
|
|
1537
|
+
napi_value Decode(Napi::Value value, Size offset, const TypeInfo *type, const Size *len)
|
|
1480
1538
|
{
|
|
1481
1539
|
Napi::Env env = value.Env();
|
|
1482
1540
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
@@ -1506,13 +1564,12 @@ Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, const S
|
|
|
1506
1564
|
return env.Null();
|
|
1507
1565
|
src += offset;
|
|
1508
1566
|
|
|
1509
|
-
|
|
1510
|
-
return ret;
|
|
1567
|
+
return Decode(instance, src, type, len);
|
|
1511
1568
|
}
|
|
1512
1569
|
|
|
1513
|
-
|
|
1570
|
+
napi_value Decode(InstanceData *instance, const uint8_t *ptr, const TypeInfo *type, const Size *len)
|
|
1514
1571
|
{
|
|
1515
|
-
|
|
1572
|
+
Napi::Env env = instance->env;
|
|
1516
1573
|
|
|
1517
1574
|
if (len && type->primitive != PrimitiveKind::String &&
|
|
1518
1575
|
type->primitive != PrimitiveKind::String16 &&
|
|
@@ -1554,12 +1611,12 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1554
1611
|
#define RETURN_INT(Type, NewCall) \
|
|
1555
1612
|
do { \
|
|
1556
1613
|
Type v = *(Type *)ptr; \
|
|
1557
|
-
return
|
|
1614
|
+
return NewCall(env, v); \
|
|
1558
1615
|
} while (false)
|
|
1559
1616
|
#define RETURN_INT_SWAP(Type, NewCall) \
|
|
1560
1617
|
do { \
|
|
1561
1618
|
Type v = ReverseBytes(*(Type *)ptr); \
|
|
1562
|
-
return
|
|
1619
|
+
return NewCall(env, v); \
|
|
1563
1620
|
} while (false)
|
|
1564
1621
|
|
|
1565
1622
|
switch (type->primitive) {
|
|
@@ -1622,12 +1679,9 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1622
1679
|
return ptr2 ? WrapPointer(env, type->ref.type, ptr2) : env.Null();
|
|
1623
1680
|
} break;
|
|
1624
1681
|
case PrimitiveKind::Record:
|
|
1625
|
-
case PrimitiveKind::Union: {
|
|
1626
|
-
Napi::Object obj = DecodeObject(env, ptr, type);
|
|
1627
|
-
return obj;
|
|
1628
|
-
} break;
|
|
1682
|
+
case PrimitiveKind::Union: { return DecodeObject(instance, ptr, type); } break;
|
|
1629
1683
|
case PrimitiveKind::Array: {
|
|
1630
|
-
|
|
1684
|
+
napi_value array = DecodeArray(instance, ptr, type);
|
|
1631
1685
|
return array;
|
|
1632
1686
|
} break;
|
|
1633
1687
|
case PrimitiveKind::Float32: {
|
|
@@ -1704,12 +1758,12 @@ bool Encode(Napi::Value ref, Size offset, Napi::Value value, const TypeInfo *typ
|
|
|
1704
1758
|
}
|
|
1705
1759
|
dest += offset;
|
|
1706
1760
|
|
|
1707
|
-
return Encode(
|
|
1761
|
+
return Encode(instance, dest, value, type, len);
|
|
1708
1762
|
}
|
|
1709
1763
|
|
|
1710
|
-
bool Encode(
|
|
1764
|
+
bool Encode(InstanceData *instance, uint8_t *origin, Napi::Value value, const TypeInfo *type, const Size *len)
|
|
1711
1765
|
{
|
|
1712
|
-
|
|
1766
|
+
Napi::Env env = instance->env;
|
|
1713
1767
|
|
|
1714
1768
|
if (len && type->primitive != PrimitiveKind::String &&
|
|
1715
1769
|
type->primitive != PrimitiveKind::String16 &&
|
package/src/koffi/src/util.hh
CHANGED
|
@@ -10,8 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
namespace K {
|
|
12
12
|
|
|
13
|
-
// #define EXTERNAL_POINTERS
|
|
14
|
-
|
|
15
13
|
#if defined(_MSC_VER)
|
|
16
14
|
#define FORCE_INLINE __forceinline
|
|
17
15
|
#else
|
|
@@ -40,6 +38,8 @@ extern const napi_type_tag DirectionMarker;
|
|
|
40
38
|
extern const napi_type_tag UnionValueMarker;
|
|
41
39
|
extern const napi_type_tag CastMarker;
|
|
42
40
|
|
|
41
|
+
#if !defined(EXTERNAL_TYPES)
|
|
42
|
+
|
|
43
43
|
class TypeObject: public Napi::ObjectWrap<TypeObject> {
|
|
44
44
|
const TypeInfo *type;
|
|
45
45
|
|
|
@@ -55,6 +55,8 @@ public:
|
|
|
55
55
|
const TypeInfo *GetType() { return type; }
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
+
#endif
|
|
59
|
+
|
|
58
60
|
class UnionValue: public Napi::ObjectWrap<UnionValue> {
|
|
59
61
|
InstanceData *instance;
|
|
60
62
|
const TypeInfo *type;
|
|
@@ -119,7 +121,7 @@ TypeInfo *MakePointerType(InstanceData *instance, const TypeInfo *ref, int count
|
|
|
119
121
|
TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len);
|
|
120
122
|
TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len, ArrayHint hint);
|
|
121
123
|
|
|
122
|
-
Napi::
|
|
124
|
+
Napi::Value WrapType(Napi::Env env, const TypeInfo *type, bool freeze = true);
|
|
123
125
|
|
|
124
126
|
const TypeInfo *ReshapeType(InstanceData *instance, const TypeInfo *type, int32_t stride, uint16_t flags);
|
|
125
127
|
|
|
@@ -403,19 +405,19 @@ Napi::String MakeStringFromUTF32(Napi::Env env, const char32_t *ptr, Size len);
|
|
|
403
405
|
static inline Napi::String MakeStringFromUTF32(Napi::Env env, const char32_t *ptr)
|
|
404
406
|
{ return MakeStringFromUTF32(env, ptr, NullTerminatedLength(ptr)); }
|
|
405
407
|
|
|
406
|
-
|
|
407
|
-
void DecodeObject(
|
|
408
|
+
napi_value DecodeObject(InstanceData *instance, const uint8_t *origin, const TypeInfo *type);
|
|
409
|
+
void DecodeObject(InstanceData *instance, napi_value obj, const uint8_t *origin, const TypeInfo *type);
|
|
408
410
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
void DecodeElements(
|
|
411
|
+
napi_value DecodeArray(InstanceData *instance, const uint8_t *origin, const TypeInfo *type);
|
|
412
|
+
napi_value DecodeArray(InstanceData *instance, const uint8_t *origin, const TypeInfo *type, uint32_t len);
|
|
413
|
+
void DecodeElements(InstanceData *instance, napi_value array, const uint8_t *origin, const TypeInfo *type, uint32_t len);
|
|
412
414
|
INLINE_UNITY void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *type);
|
|
413
415
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
+
napi_value Decode(Napi::Value value, Size offset, const TypeInfo *type, const Size *len = nullptr);
|
|
417
|
+
napi_value Decode(InstanceData *instance, const uint8_t *ptr, const TypeInfo *type, const Size *len = nullptr);
|
|
416
418
|
|
|
417
419
|
bool Encode(Napi::Value ref, Size offset, Napi::Value value, const TypeInfo *type, const Size *len = nullptr);
|
|
418
|
-
bool Encode(
|
|
420
|
+
bool Encode(InstanceData *instance, uint8_t *ptr, Napi::Value value, const TypeInfo *type, const Size *len = nullptr);
|
|
419
421
|
|
|
420
422
|
static FORCE_INLINE napi_value NewInt(Napi::Env env, char i) { napi_value value; napi_create_int32(env, (int32_t)i, &value); return value; }
|
|
421
423
|
static FORCE_INLINE napi_value NewInt(Napi::Env env, signed char i) { napi_value value; napi_create_int32(env, (int32_t)i, &value); return value; }
|
|
@@ -480,9 +482,6 @@ static FORCE_INLINE Napi::Value WrapPointer(Napi::Env env, const TypeInfo *ref,
|
|
|
480
482
|
#endif
|
|
481
483
|
}
|
|
482
484
|
|
|
483
|
-
Napi::Value INLINE_UNITY WrapPointer(Napi::Env env, const TypeInfo *ref, void *ptr);
|
|
484
|
-
Napi::Value INLINE_UNITY WrapPointer(Napi::Env env, const TypeInfo *ref, void *ptr);
|
|
485
|
-
|
|
486
485
|
bool DetectCallConvention(Span<const char> name, CallConvention *out_convention);
|
|
487
486
|
|
|
488
487
|
int AnalyseFlat(const TypeInfo *type, FunctionRef<void(const TypeInfo *type, int offset, int count)> func);
|