koffi 2.16.1 → 3.0.0-alpha.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 +2 -2
- package/README.md +8 -8
- 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_ia32/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_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/doc/benchmarks.md +33 -33
- package/doc/benchmarks.xlsx +0 -0
- package/doc/contribute.md +37 -25
- package/doc/index.md +8 -8
- package/doc/variables.md +1 -1
- package/index.d.ts +11 -9
- package/index.js +1 -634
- package/indirect.js +1 -533
- package/lib/native/base/base.cc +63 -85
- package/lib/native/base/base.hh +178 -151
- package/package.json +3 -4
- package/src/build.js +1178 -0
- package/src/koffi/CMakeLists.txt +97 -34
- package/src/koffi/index.js +359 -0
- package/src/koffi/indirect.js +216 -0
- package/src/koffi/src/{abi_arm32.cc → abi/arm32.cc} +279 -275
- package/src/koffi/src/{abi_arm32_asm.S → abi/arm32_asm.S} +2 -5
- package/src/koffi/src/abi/arm64.cc +1511 -0
- package/src/koffi/src/{abi_arm64_asm.S → abi/arm64_asm.S} +44 -23
- package/src/koffi/src/{abi_arm64_asm.asm → abi/arm64_asm.asm} +32 -25
- package/src/koffi/src/{abi_loong64_asm.S → abi/loong64_asm.S} +1 -5
- package/src/koffi/src/{abi_riscv64.cc → abi/riscv64.cc} +279 -273
- package/src/koffi/src/{abi_riscv64_asm.S → abi/riscv64_asm.S} +1 -4
- package/src/koffi/src/abi/x64sysv.cc +1456 -0
- package/src/koffi/src/{abi_x64_sysv_asm.S → abi/x64sysv_asm.S} +30 -33
- package/src/koffi/src/abi/x64win.cc +1121 -0
- package/src/koffi/src/{abi_x64_win_asm.S → abi/x64win_asm.S} +8 -12
- package/src/koffi/src/{abi_x64_win_asm.asm → abi/x64win_asm.asm} +11 -14
- package/src/koffi/src/abi/x86.cc +1233 -0
- package/src/koffi/src/{abi_x86_asm.S → abi/x86_asm.S} +49 -25
- package/src/koffi/src/{abi_x86_asm.asm → abi/x86_asm.asm} +11 -14
- package/src/koffi/src/call.cc +458 -598
- package/src/koffi/src/call.hh +61 -82
- package/src/koffi/src/ffi.cc +595 -309
- package/src/koffi/src/ffi.hh +103 -89
- package/src/koffi/src/parser.cc +0 -4
- package/src/koffi/src/primitives.inc +39 -0
- package/src/koffi/{tools/write_trampolines.js → src/trampolines.js} +1 -1
- package/src/koffi/src/util.cc +503 -446
- package/src/koffi/src/util.hh +269 -57
- package/src/koffi/src/uv.cc +2 -2
- package/src/koffi/src/uv.def +3 -0
- package/src/koffi/src/win32.hh +30 -1
- package/vendor/node-addon-api/napi-inl.h +4 -0
- package/vendor/node-addon-api/napi.h +1 -0
- package/build/koffi/linux_armhf/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/win32_arm64/koffi.exp +0 -0
- package/build/koffi/win32_arm64/koffi.lib +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/doc/platforms.md +0 -36
- package/src/cnoke/LICENSE.txt +0 -22
- package/src/cnoke/README.md +0 -99
- package/src/cnoke/assets/FindCNoke.cmake +0 -127
- package/src/cnoke/assets/toolchains.json +0 -126
- package/src/cnoke/assets/win_delay_hook.c +0 -36
- package/src/cnoke/cnoke.js +0 -170
- package/src/cnoke/package.json +0 -24
- package/src/cnoke/src/builder.js +0 -511
- package/src/cnoke/src/index.js +0 -10
- package/src/cnoke/src/tools.js +0 -407
- package/src/koffi/src/abi_arm64.cc +0 -1295
- package/src/koffi/src/abi_x64_sysv.cc +0 -939
- package/src/koffi/src/abi_x64_win.cc +0 -715
- package/src/koffi/src/abi_x86.cc +0 -860
- package/src/koffi/src/init.js +0 -105
- /package/src/koffi/src/{abi_loong64.cc → abi/loong64.cc} +0 -0
package/src/koffi/src/util.cc
CHANGED
|
@@ -13,22 +13,22 @@ namespace K {
|
|
|
13
13
|
// Value does not matter, the tag system uses memory addresses
|
|
14
14
|
const napi_type_tag TypeInfoMarker = { 0x1cc449675b294374, 0xbb13a50e97dcb017 };
|
|
15
15
|
const napi_type_tag CastMarker = { 0x77f459614a0a412f, 0x80b3dda1341dc8df };
|
|
16
|
-
const napi_type_tag
|
|
16
|
+
const napi_type_tag UnionClassMarker = { 0x5eaf2245526a4c7d, 0x8c86c9ee2b96ffc8 };
|
|
17
17
|
|
|
18
|
-
Napi::Function
|
|
18
|
+
Napi::Function UnionClass::InitClass(Napi::Env env, const TypeInfo *type)
|
|
19
19
|
{
|
|
20
20
|
K_ASSERT(type->primitive == PrimitiveKind::Union);
|
|
21
21
|
|
|
22
22
|
// node-addon-api wants std::vector
|
|
23
|
-
std::vector<Napi::ClassPropertyDescriptor<
|
|
23
|
+
std::vector<Napi::ClassPropertyDescriptor<UnionClass>> properties;
|
|
24
24
|
properties.reserve(type->members.len);
|
|
25
25
|
|
|
26
26
|
for (Size i = 0; i < type->members.len; i++) {
|
|
27
27
|
const RecordMember &member = type->members[i];
|
|
28
28
|
|
|
29
29
|
napi_property_attributes attr = (napi_property_attributes)(napi_writable | napi_enumerable);
|
|
30
|
-
Napi::ClassPropertyDescriptor<
|
|
31
|
-
&
|
|
30
|
+
Napi::ClassPropertyDescriptor<UnionClass> prop = InstanceAccessor(member.name, &UnionClass::Getter,
|
|
31
|
+
&UnionClass::Setter, attr, (void *)i);
|
|
32
32
|
|
|
33
33
|
properties.push_back(prop);
|
|
34
34
|
}
|
|
@@ -37,25 +37,39 @@ Napi::Function MagicUnion::InitClass(Napi::Env env, const TypeInfo *type)
|
|
|
37
37
|
return constructor;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
: Napi::ObjectWrap<
|
|
40
|
+
UnionClass::UnionClass(const Napi::CallbackInfo &info)
|
|
41
|
+
: Napi::ObjectWrap<UnionClass>(info), type((const TypeInfo *)info.Data())
|
|
42
42
|
{
|
|
43
43
|
Napi::Env env = info.Env();
|
|
44
|
-
|
|
44
|
+
instance = env.GetInstanceData<InstanceData>();
|
|
45
|
+
}
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
void UnionClass::Finalize(Napi::BasicEnv env)
|
|
48
|
+
{
|
|
49
|
+
napi_ref ref = (napi_ref)*this;
|
|
50
|
+
|
|
51
|
+
if (node_api_post_finalizer) {
|
|
52
|
+
node_api_post_finalizer(env, [](napi_env env, void *data, void *) {
|
|
53
|
+
napi_ref ref = (napi_ref)data;
|
|
54
|
+
napi_delete_reference(env, ref);
|
|
55
|
+
}, (void *)ref, nullptr);
|
|
56
|
+
} else {
|
|
57
|
+
napi_delete_reference(env, ref);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
SuppressDestruct();
|
|
47
61
|
}
|
|
48
62
|
|
|
49
|
-
void
|
|
63
|
+
void UnionClass::SetRaw(const uint8_t *ptr)
|
|
50
64
|
{
|
|
51
65
|
raw.RemoveFrom(0);
|
|
52
66
|
raw.Append(MakeSpan(ptr, type->size));
|
|
53
67
|
|
|
54
|
-
Value().Set(active_symbol.Value(), Env().Undefined());
|
|
68
|
+
Value().Set(instance->active_symbol.Value(), Env().Undefined());
|
|
55
69
|
active_idx = -1;
|
|
56
70
|
}
|
|
57
71
|
|
|
58
|
-
Napi::Value
|
|
72
|
+
Napi::Value UnionClass::Getter(const Napi::CallbackInfo &info)
|
|
59
73
|
{
|
|
60
74
|
Size idx = (Size)info.Data();
|
|
61
75
|
const RecordMember &member = type->members[idx];
|
|
@@ -63,7 +77,7 @@ Napi::Value MagicUnion::Getter(const Napi::CallbackInfo &info)
|
|
|
63
77
|
Napi::Value value;
|
|
64
78
|
|
|
65
79
|
if (idx == active_idx) {
|
|
66
|
-
value = Value().Get(active_symbol.Value());
|
|
80
|
+
value = Value().Get(instance->active_symbol.Value());
|
|
67
81
|
} else {
|
|
68
82
|
Napi::Env env = info.Env();
|
|
69
83
|
|
|
@@ -74,7 +88,7 @@ Napi::Value MagicUnion::Getter(const Napi::CallbackInfo &info)
|
|
|
74
88
|
|
|
75
89
|
value = Decode(env, raw.ptr, member.type);
|
|
76
90
|
|
|
77
|
-
Value().Set(active_symbol.Value(), value);
|
|
91
|
+
Value().Set(instance->active_symbol.Value(), value);
|
|
78
92
|
active_idx = idx;
|
|
79
93
|
}
|
|
80
94
|
|
|
@@ -82,11 +96,11 @@ Napi::Value MagicUnion::Getter(const Napi::CallbackInfo &info)
|
|
|
82
96
|
return value;
|
|
83
97
|
}
|
|
84
98
|
|
|
85
|
-
void
|
|
99
|
+
void UnionClass::Setter(const Napi::CallbackInfo &info, const Napi::Value &value)
|
|
86
100
|
{
|
|
87
101
|
Size idx = (Size)info.Data();
|
|
88
102
|
|
|
89
|
-
Value().Set(active_symbol.Value(), value);
|
|
103
|
+
Value().Set(instance->active_symbol.Value(), value);
|
|
90
104
|
active_idx = idx;
|
|
91
105
|
|
|
92
106
|
raw.Clear();
|
|
@@ -180,8 +194,8 @@ const TypeInfo *ResolveType(Napi::Value value, int *out_directions)
|
|
|
180
194
|
}
|
|
181
195
|
|
|
182
196
|
return type;
|
|
183
|
-
} else if (CheckValueTag(value, &TypeInfoMarker)) {
|
|
184
|
-
Napi::External<TypeInfo> external =
|
|
197
|
+
} else if (GetKindOf(env, value) == napi_external && CheckValueTag(env, value, &TypeInfoMarker)) {
|
|
198
|
+
Napi::External<TypeInfo> external = Napi::External<TypeInfo>(env, value);
|
|
185
199
|
const TypeInfo *raw = external.Data();
|
|
186
200
|
|
|
187
201
|
const TypeInfo *type = AlignDown(raw, 4);
|
|
@@ -458,7 +472,7 @@ TypeInfo *MakeArrayType(InstanceData *instance, const TypeInfo *ref, Size len, A
|
|
|
458
472
|
Napi::External<TypeInfo> WrapType(Napi::Env env, const TypeInfo *type)
|
|
459
473
|
{
|
|
460
474
|
Napi::External<TypeInfo> external = Napi::External<TypeInfo>::New(env, (TypeInfo *)type);
|
|
461
|
-
SetValueTag(external, &TypeInfoMarker);
|
|
475
|
+
SetValueTag(env, external, &TypeInfoMarker);
|
|
462
476
|
|
|
463
477
|
return external;
|
|
464
478
|
}
|
|
@@ -520,26 +534,31 @@ bool CanStoreType(const TypeInfo *type)
|
|
|
520
534
|
return true;
|
|
521
535
|
}
|
|
522
536
|
|
|
523
|
-
const char *GetValueType(const InstanceData *instance,
|
|
537
|
+
const char *GetValueType(const InstanceData *instance, napi_value value)
|
|
524
538
|
{
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
ValueCast *cast = external.Data();
|
|
539
|
+
Napi::Env env = instance->env;
|
|
540
|
+
napi_valuetype kind = GetKindOf(env, value);
|
|
528
541
|
|
|
529
|
-
|
|
530
|
-
|
|
542
|
+
if (kind == napi_external) {
|
|
543
|
+
if (CheckValueTag(env, value, &CastMarker)) {
|
|
544
|
+
Napi::External<ValueCast> external = Napi::External<ValueCast>(env, value);
|
|
545
|
+
ValueCast *cast = external.Data();
|
|
546
|
+
|
|
547
|
+
return cast->type->name;
|
|
548
|
+
}
|
|
531
549
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
550
|
+
if (CheckValueTag(env, value, &TypeInfoMarker))
|
|
551
|
+
return "Type";
|
|
552
|
+
for (const TypeInfo &type: instance->types) {
|
|
553
|
+
if (type.ref.type && CheckValueTag(env, value, type.ref.type))
|
|
554
|
+
return type.name;
|
|
555
|
+
}
|
|
537
556
|
}
|
|
538
557
|
|
|
539
|
-
if (
|
|
558
|
+
if (IsArray(env, value)) {
|
|
540
559
|
return "Array";
|
|
541
|
-
} else if (
|
|
542
|
-
Napi::TypedArray array =
|
|
560
|
+
} else if (IsTypedArray(env, value)) {
|
|
561
|
+
Napi::TypedArray array = Napi::TypedArray(env, value);
|
|
543
562
|
|
|
544
563
|
switch (array.TypedArrayType()) {
|
|
545
564
|
case napi_int8_array: return "Int8Array";
|
|
@@ -555,13 +574,13 @@ const char *GetValueType(const InstanceData *instance, Napi::Value value)
|
|
|
555
574
|
case napi_bigint64_array: return "BigInt64Array";
|
|
556
575
|
case napi_biguint64_array: return "BigUint64Array";
|
|
557
576
|
}
|
|
558
|
-
} else if (
|
|
577
|
+
} else if (IsArrayBuffer(env, value)) {
|
|
559
578
|
return "ArrayBuffer";
|
|
560
|
-
} else if (
|
|
579
|
+
} else if (IsBuffer(env, value)) {
|
|
561
580
|
return "Buffer";
|
|
562
581
|
}
|
|
563
582
|
|
|
564
|
-
switch (
|
|
583
|
+
switch (kind) {
|
|
565
584
|
case napi_undefined: return "Undefined";
|
|
566
585
|
case napi_null: return "Null";
|
|
567
586
|
case napi_boolean: return "Boolean";
|
|
@@ -578,7 +597,7 @@ const char *GetValueType(const InstanceData *instance, Napi::Value value)
|
|
|
578
597
|
return "Unknown";
|
|
579
598
|
}
|
|
580
599
|
|
|
581
|
-
void SetValueTag(
|
|
600
|
+
void SetValueTag(napi_env env, napi_value value, const void *marker)
|
|
582
601
|
{
|
|
583
602
|
static_assert(K_SIZE(TypeInfo) >= 16);
|
|
584
603
|
|
|
@@ -593,18 +612,18 @@ void SetValueTag(Napi::Value value, const void *marker)
|
|
|
593
612
|
// and the few other markers we use, such as CastMarker, are actual const napi_type_tag structs.
|
|
594
613
|
const napi_type_tag *tag = (const napi_type_tag *)marker;
|
|
595
614
|
|
|
596
|
-
napi_status status = napi_type_tag_object(
|
|
615
|
+
napi_status status = napi_type_tag_object(env, value, tag);
|
|
597
616
|
K_ASSERT(status == napi_ok);
|
|
598
617
|
}
|
|
599
618
|
|
|
600
|
-
bool CheckValueTag(
|
|
619
|
+
bool CheckValueTag(napi_env env, napi_value value, const void *marker)
|
|
601
620
|
{
|
|
621
|
+
K_ASSERT(IsObject(env, value) || GetKindOf(env, value) == napi_external);
|
|
622
|
+
|
|
602
623
|
bool match = false;
|
|
603
624
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
napi_check_object_type_tag(value.Env(), value, tag, &match);
|
|
607
|
-
}
|
|
625
|
+
const napi_type_tag *tag = (const napi_type_tag *)marker;
|
|
626
|
+
napi_check_object_type_tag(env, value, tag, &match);
|
|
608
627
|
|
|
609
628
|
return match;
|
|
610
629
|
}
|
|
@@ -662,16 +681,17 @@ Napi::Object DecodeObject(Napi::Env env, const uint8_t *origin, const TypeInfo *
|
|
|
662
681
|
// We can't decode unions because we don't know which member is valid
|
|
663
682
|
if (type->primitive == PrimitiveKind::Union) {
|
|
664
683
|
Napi::Object wrapper = type->construct.New({}).As<Napi::Object>();
|
|
665
|
-
SetValueTag(wrapper, &
|
|
684
|
+
SetValueTag(env, wrapper, &UnionClassMarker);
|
|
666
685
|
|
|
667
|
-
|
|
686
|
+
UnionClass *u = UnionClass::Unwrap(wrapper);
|
|
668
687
|
u->SetRaw(origin);
|
|
669
688
|
|
|
670
689
|
return wrapper;
|
|
671
690
|
}
|
|
672
691
|
|
|
673
692
|
Napi::Object obj = Napi::Object::New(env);
|
|
674
|
-
DecodeObject(obj, origin, type);
|
|
693
|
+
DecodeObject(env, obj, origin, type);
|
|
694
|
+
|
|
675
695
|
return obj;
|
|
676
696
|
}
|
|
677
697
|
|
|
@@ -689,52 +709,64 @@ static uint32_t DecodeDynamicLength(const uint8_t *origin, const RecordMember &b
|
|
|
689
709
|
return (uint32_t)u;
|
|
690
710
|
} break;
|
|
691
711
|
case PrimitiveKind::Int16: {
|
|
692
|
-
int16_t i
|
|
712
|
+
int16_t i;
|
|
713
|
+
memcpy(&i, src, 2);
|
|
693
714
|
return (uint32_t)i;
|
|
694
715
|
} break;
|
|
695
716
|
case PrimitiveKind::Int16S: {
|
|
696
|
-
int16_t i
|
|
697
|
-
|
|
717
|
+
int16_t i;
|
|
718
|
+
memcpy(&i, src, 2);
|
|
719
|
+
return (uint32_t)ReverseBytes(i);
|
|
698
720
|
} break;
|
|
699
721
|
case PrimitiveKind::UInt16: {
|
|
700
|
-
uint16_t u
|
|
722
|
+
uint16_t u;
|
|
723
|
+
memcpy(&u, src, 2);
|
|
701
724
|
return (uint32_t)u;
|
|
702
725
|
} break;
|
|
703
726
|
case PrimitiveKind::UInt16S: {
|
|
704
|
-
uint16_t u
|
|
705
|
-
|
|
727
|
+
uint16_t u;
|
|
728
|
+
memcpy(&u, src, 2);
|
|
729
|
+
return (uint32_t)ReverseBytes(u);
|
|
706
730
|
} break;
|
|
707
731
|
case PrimitiveKind::Int32: {
|
|
708
|
-
int32_t i
|
|
732
|
+
int32_t i;
|
|
733
|
+
memcpy(&i, src, 4);
|
|
709
734
|
return (uint32_t)i;
|
|
710
735
|
} break;
|
|
711
736
|
case PrimitiveKind::Int32S: {
|
|
712
|
-
int32_t i
|
|
713
|
-
|
|
737
|
+
int32_t i;
|
|
738
|
+
memcpy(&i, src, 4);
|
|
739
|
+
return (uint32_t)ReverseBytes(i);
|
|
714
740
|
} break;
|
|
715
741
|
case PrimitiveKind::UInt32: {
|
|
716
|
-
uint32_t u
|
|
742
|
+
uint32_t u;
|
|
743
|
+
memcpy(&u, src, 4);
|
|
717
744
|
return (uint32_t)u;
|
|
718
745
|
} break;
|
|
719
746
|
case PrimitiveKind::UInt32S: {
|
|
720
|
-
uint32_t u
|
|
721
|
-
|
|
747
|
+
uint32_t u;
|
|
748
|
+
memcpy(&u, src, 4);
|
|
749
|
+
return (uint32_t)ReverseBytes(u);
|
|
722
750
|
} break;
|
|
723
751
|
case PrimitiveKind::Int64: {
|
|
724
|
-
int64_t i
|
|
752
|
+
int64_t i;
|
|
753
|
+
memcpy(&i, src, 8);
|
|
725
754
|
return (uint32_t)i;
|
|
726
755
|
} break;
|
|
727
756
|
case PrimitiveKind::Int64S: {
|
|
728
|
-
int64_t i
|
|
729
|
-
|
|
757
|
+
int64_t i;
|
|
758
|
+
memcpy(&i, src, 8);
|
|
759
|
+
return (uint32_t)ReverseBytes(i);
|
|
730
760
|
} break;
|
|
731
761
|
case PrimitiveKind::UInt64: {
|
|
732
|
-
uint64_t u
|
|
762
|
+
uint64_t u;
|
|
763
|
+
memcpy(&u, src, 8);
|
|
733
764
|
return (uint32_t)u;
|
|
734
765
|
} break;
|
|
735
766
|
case PrimitiveKind::UInt64S: {
|
|
736
|
-
uint64_t u
|
|
737
|
-
|
|
767
|
+
uint64_t u;
|
|
768
|
+
memcpy(&u, src, 8);
|
|
769
|
+
return (uint32_t)ReverseBytes(u);
|
|
738
770
|
} break;
|
|
739
771
|
|
|
740
772
|
case PrimitiveKind::Void:
|
|
@@ -755,15 +787,25 @@ static uint32_t DecodeDynamicLength(const uint8_t *origin, const RecordMember &b
|
|
|
755
787
|
K_UNREACHABLE();
|
|
756
788
|
}
|
|
757
789
|
|
|
758
|
-
void
|
|
790
|
+
static inline void SetMemberValue(napi_env env, napi_value obj, const RecordMember &member, napi_value value)
|
|
759
791
|
{
|
|
760
|
-
|
|
792
|
+
if (member.key) {
|
|
793
|
+
napi_value key = nullptr;
|
|
794
|
+
napi_get_reference_value(env, member.key, &key);
|
|
761
795
|
|
|
762
|
-
|
|
796
|
+
napi_status status = napi_set_property(env, obj, key, value);
|
|
797
|
+
K_ASSERT(status == napi_ok);
|
|
798
|
+
} else {
|
|
799
|
+
napi_status status = napi_set_named_property(env, obj, member.name, value);
|
|
800
|
+
K_ASSERT(status == napi_ok);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
763
803
|
|
|
764
|
-
|
|
765
|
-
|
|
804
|
+
void DecodeObject(Napi::Env env, napi_value obj, const uint8_t *origin, const TypeInfo *type)
|
|
805
|
+
{
|
|
806
|
+
K_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
766
807
|
|
|
808
|
+
for (const RecordMember &member: type->members) {
|
|
767
809
|
const uint8_t *src = origin + member.offset;
|
|
768
810
|
|
|
769
811
|
switch (member.type->primitive) {
|
|
@@ -771,119 +813,133 @@ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type)
|
|
|
771
813
|
|
|
772
814
|
case PrimitiveKind::Bool: {
|
|
773
815
|
bool b = *(bool *)src;
|
|
774
|
-
obj
|
|
816
|
+
SetMemberValue(env, obj, member, Napi::Boolean::New(env, b));
|
|
775
817
|
} break;
|
|
776
818
|
case PrimitiveKind::Int8: {
|
|
777
|
-
|
|
778
|
-
obj
|
|
819
|
+
int8_t i = *(int8_t *)src;
|
|
820
|
+
SetMemberValue(env, obj, member, NewInt(env, i));
|
|
779
821
|
} break;
|
|
780
822
|
case PrimitiveKind::UInt8: {
|
|
781
|
-
|
|
782
|
-
obj
|
|
823
|
+
uint8_t u = *(uint8_t *)src;
|
|
824
|
+
SetMemberValue(env, obj, member, NewInt(env, u));
|
|
783
825
|
} break;
|
|
784
826
|
case PrimitiveKind::Int16: {
|
|
785
|
-
|
|
786
|
-
|
|
827
|
+
int16_t i;
|
|
828
|
+
memcpy(&i, src, 2);
|
|
829
|
+
SetMemberValue(env, obj, member, NewInt(env, i));
|
|
787
830
|
} break;
|
|
788
831
|
case PrimitiveKind::Int16S: {
|
|
789
|
-
int16_t
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
832
|
+
int16_t i;
|
|
833
|
+
memcpy(&i, src, 2);
|
|
834
|
+
SetMemberValue(env, obj, member, NewInt(env, ReverseBytes(i)));
|
|
793
835
|
} break;
|
|
794
836
|
case PrimitiveKind::UInt16: {
|
|
795
|
-
|
|
796
|
-
|
|
837
|
+
uint16_t u;
|
|
838
|
+
memcpy(&u, src, 2);
|
|
839
|
+
SetMemberValue(env, obj, member, NewInt(env, u));
|
|
797
840
|
} break;
|
|
798
841
|
case PrimitiveKind::UInt16S: {
|
|
799
|
-
uint16_t
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
842
|
+
uint16_t u;
|
|
843
|
+
memcpy(&u, src, 2);
|
|
844
|
+
SetMemberValue(env, obj, member, NewInt(env, ReverseBytes(u)));
|
|
803
845
|
} break;
|
|
804
846
|
case PrimitiveKind::Int32: {
|
|
805
|
-
|
|
806
|
-
|
|
847
|
+
int32_t i;
|
|
848
|
+
memcpy(&i, src, 4);
|
|
849
|
+
SetMemberValue(env, obj, member, NewInt(env, i));
|
|
807
850
|
} break;
|
|
808
851
|
case PrimitiveKind::Int32S: {
|
|
809
|
-
int32_t
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
852
|
+
int32_t i;
|
|
853
|
+
memcpy(&i, src, 4);
|
|
854
|
+
SetMemberValue(env, obj, member, NewInt(env, ReverseBytes(i)));
|
|
813
855
|
} break;
|
|
814
856
|
case PrimitiveKind::UInt32: {
|
|
815
|
-
|
|
816
|
-
|
|
857
|
+
uint32_t u;
|
|
858
|
+
memcpy(&u, src, 4);
|
|
859
|
+
SetMemberValue(env, obj, member, NewInt(env, u));
|
|
817
860
|
} break;
|
|
818
861
|
case PrimitiveKind::UInt32S: {
|
|
819
|
-
uint32_t
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
862
|
+
uint32_t u;
|
|
863
|
+
memcpy(&u, src, 4);
|
|
864
|
+
SetMemberValue(env, obj, member, NewInt(env, ReverseBytes(u)));
|
|
823
865
|
} break;
|
|
824
866
|
case PrimitiveKind::Int64: {
|
|
825
|
-
int64_t
|
|
826
|
-
|
|
867
|
+
int64_t i;
|
|
868
|
+
memcpy(&i, src, 8);
|
|
869
|
+
SetMemberValue(env, obj, member, NewInt(env, i));
|
|
827
870
|
} break;
|
|
828
871
|
case PrimitiveKind::Int64S: {
|
|
829
|
-
int64_t
|
|
830
|
-
|
|
872
|
+
int64_t i;
|
|
873
|
+
memcpy(&i, src, 8);
|
|
874
|
+
SetMemberValue(env, obj, member, NewInt(env, ReverseBytes(i)));
|
|
831
875
|
} break;
|
|
832
876
|
case PrimitiveKind::UInt64: {
|
|
833
|
-
uint64_t
|
|
834
|
-
|
|
877
|
+
uint64_t u;
|
|
878
|
+
memcpy(&u, src, 8);
|
|
879
|
+
SetMemberValue(env, obj, member, NewInt(env, u));
|
|
835
880
|
} break;
|
|
836
881
|
case PrimitiveKind::UInt64S: {
|
|
837
|
-
uint64_t
|
|
838
|
-
|
|
882
|
+
uint64_t u;
|
|
883
|
+
memcpy(&u, src, 8);
|
|
884
|
+
SetMemberValue(env, obj, member, NewInt(env, ReverseBytes(u)));
|
|
839
885
|
} break;
|
|
840
886
|
case PrimitiveKind::String: {
|
|
841
|
-
const char *str
|
|
842
|
-
|
|
887
|
+
const char *str;
|
|
888
|
+
memcpy(&str, src, K_SIZE(void *));
|
|
889
|
+
SetMemberValue(env, obj, member, str ? Napi::String::New(env, str) : env.Null());
|
|
843
890
|
|
|
844
891
|
if (member.type->dispose) {
|
|
845
892
|
member.type->dispose(env, member.type, str);
|
|
846
893
|
}
|
|
847
894
|
} break;
|
|
848
895
|
case PrimitiveKind::String16: {
|
|
849
|
-
const char16_t *str16
|
|
850
|
-
|
|
896
|
+
const char16_t *str16;
|
|
897
|
+
memcpy(&str16, src, K_SIZE(void *));
|
|
898
|
+
SetMemberValue(env, obj, member, str16 ? Napi::String::New(env, str16) : env.Null());
|
|
851
899
|
|
|
852
900
|
if (member.type->dispose) {
|
|
853
901
|
member.type->dispose(env, member.type, str16);
|
|
854
902
|
}
|
|
855
903
|
} break;
|
|
856
904
|
case PrimitiveKind::String32: {
|
|
857
|
-
const char32_t *str32
|
|
858
|
-
|
|
905
|
+
const char32_t *str32;
|
|
906
|
+
memcpy(&str32, src, K_SIZE(void *));
|
|
907
|
+
SetMemberValue(env, obj, member, str32 ? MakeStringFromUTF32(env, str32) : env.Null());
|
|
859
908
|
} break;
|
|
860
|
-
case PrimitiveKind::Pointer:
|
|
861
|
-
|
|
862
|
-
|
|
909
|
+
case PrimitiveKind::Pointer: {
|
|
910
|
+
void *ptr2;
|
|
911
|
+
memcpy(&ptr2, src, K_SIZE(void *));
|
|
863
912
|
|
|
864
913
|
if (member.countedby >= 0) {
|
|
865
914
|
const RecordMember &by = type->members[member.countedby];
|
|
866
915
|
uint32_t len = DecodeDynamicLength(origin, by);
|
|
867
916
|
|
|
868
917
|
Napi::Value value = DecodeArray(env, (const uint8_t *)ptr2, member.type, len);
|
|
869
|
-
obj
|
|
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);
|
|
918
|
+
SetMemberValue(env, obj, member, value);
|
|
875
919
|
} else {
|
|
876
|
-
|
|
920
|
+
Napi::Value p = ptr2 ? WrapPointer(env, member.type->ref.type, ptr2) : env.Null();
|
|
921
|
+
SetMemberValue(env, obj, member, p);
|
|
877
922
|
}
|
|
878
923
|
|
|
879
924
|
if (member.type->dispose) {
|
|
880
925
|
member.type->dispose(env, member.type, ptr2);
|
|
881
926
|
}
|
|
882
927
|
} break;
|
|
928
|
+
case PrimitiveKind::Callback: {
|
|
929
|
+
void *ptr2;
|
|
930
|
+
memcpy(&ptr2, src, K_SIZE(void *));
|
|
931
|
+
|
|
932
|
+
Napi::Value p = ptr2 ? WrapCallback(env, member.type->ref.type, ptr2) : env.Null();
|
|
933
|
+
SetMemberValue(env, obj, member, p);
|
|
934
|
+
|
|
935
|
+
if (member.type->dispose) {
|
|
936
|
+
member.type->dispose(env, member.type, ptr2);
|
|
937
|
+
}
|
|
938
|
+
} break;
|
|
883
939
|
case PrimitiveKind::Record:
|
|
884
940
|
case PrimitiveKind::Union: {
|
|
885
941
|
Napi::Object obj2 = DecodeObject(env, src, member.type);
|
|
886
|
-
obj
|
|
942
|
+
SetMemberValue(env, obj, member, obj2);
|
|
887
943
|
} break;
|
|
888
944
|
case PrimitiveKind::Array: {
|
|
889
945
|
if (member.countedby >= 0) {
|
|
@@ -896,19 +952,21 @@ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type)
|
|
|
896
952
|
len = std::min(len, max);
|
|
897
953
|
|
|
898
954
|
Napi::Value value = DecodeArray(env, src, member.type, len);
|
|
899
|
-
obj
|
|
955
|
+
SetMemberValue(env, obj, member, value);
|
|
900
956
|
} else {
|
|
901
957
|
Napi::Value value = DecodeArray(env, src, member.type);
|
|
902
|
-
obj
|
|
958
|
+
SetMemberValue(env, obj, member, value);
|
|
903
959
|
}
|
|
904
960
|
} break;
|
|
905
961
|
case PrimitiveKind::Float32: {
|
|
906
|
-
float f
|
|
907
|
-
|
|
962
|
+
float f;
|
|
963
|
+
memcpy(&f, src, 4);
|
|
964
|
+
SetMemberValue(env, obj, member, Napi::Number::New(env, (double)f));
|
|
908
965
|
} break;
|
|
909
966
|
case PrimitiveKind::Float64: {
|
|
910
|
-
double d
|
|
911
|
-
|
|
967
|
+
double d;
|
|
968
|
+
memcpy(&d, src, 8);
|
|
969
|
+
SetMemberValue(env, obj, member, Napi::Number::New(env, d));
|
|
912
970
|
} break;
|
|
913
971
|
|
|
914
972
|
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
@@ -916,208 +974,129 @@ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type)
|
|
|
916
974
|
}
|
|
917
975
|
}
|
|
918
976
|
|
|
977
|
+
Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type)
|
|
978
|
+
{
|
|
979
|
+
K_ASSERT(type->primitive == PrimitiveKind::Array);
|
|
980
|
+
|
|
981
|
+
uint32_t len = type->size / type->ref.type->size;
|
|
982
|
+
return DecodeArray(env, origin, type, len);
|
|
983
|
+
}
|
|
984
|
+
|
|
919
985
|
Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type, uint32_t len)
|
|
920
986
|
{
|
|
921
|
-
|
|
987
|
+
K_ASSERT(type->primitive == PrimitiveKind::Array || type->primitive == PrimitiveKind::Pointer);
|
|
922
988
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
offset = AlignLen(offset, type->ref.type->align); \
|
|
929
|
-
\
|
|
930
|
-
const uint8_t *src = origin + offset; \
|
|
931
|
-
\
|
|
932
|
-
SetCode \
|
|
933
|
-
\
|
|
934
|
-
offset += type->ref.type->size; \
|
|
935
|
-
} \
|
|
936
|
-
\
|
|
937
|
-
return array; \
|
|
938
|
-
} while (false)
|
|
939
|
-
#define POP_NUMBER_ARRAY(TypedArrayType, CType) \
|
|
940
|
-
do { \
|
|
941
|
-
if (type->hint == ArrayHint::Array) { \
|
|
942
|
-
POP_ARRAY({ \
|
|
943
|
-
double d = (double)*(CType *)src; \
|
|
944
|
-
array.Set(i, Napi::Number::New(env, d)); \
|
|
945
|
-
}); \
|
|
946
|
-
} else { \
|
|
947
|
-
Napi::TypedArrayType array = Napi::TypedArrayType::New(env, len); \
|
|
948
|
-
Span<uint8_t> buffer = MakeSpan((uint8_t *)array.ArrayBuffer().Data(), (Size)len * K_SIZE(CType)); \
|
|
949
|
-
\
|
|
950
|
-
DecodeBuffer(buffer, origin, type->ref.type); \
|
|
951
|
-
\
|
|
952
|
-
return array; \
|
|
953
|
-
} \
|
|
954
|
-
} while (false)
|
|
955
|
-
#define POP_NUMBER_ARRAY_SWAP(TypedArrayType, CType) \
|
|
956
|
-
do { \
|
|
957
|
-
if (type->hint == ArrayHint::Array) { \
|
|
958
|
-
POP_ARRAY({ \
|
|
959
|
-
CType v = *(CType *)src; \
|
|
960
|
-
double d = (double)ReverseBytes(v); \
|
|
961
|
-
array.Set(i, Napi::Number::New(env, d)); \
|
|
962
|
-
}); \
|
|
963
|
-
} else { \
|
|
989
|
+
const TypeInfo *ref = type->ref.type;
|
|
990
|
+
|
|
991
|
+
if (type->hint == ArrayHint::Typed) {
|
|
992
|
+
#define POP_TYPEDARRAY(TypedArrayType, CType) \
|
|
993
|
+
do { \
|
|
964
994
|
Napi::TypedArrayType array = Napi::TypedArrayType::New(env, len); \
|
|
965
995
|
Span<uint8_t> buffer = MakeSpan((uint8_t *)array.ArrayBuffer().Data(), (Size)len * K_SIZE(CType)); \
|
|
966
996
|
\
|
|
967
|
-
DecodeBuffer(buffer, origin,
|
|
997
|
+
DecodeBuffer(buffer, origin, ref); \
|
|
968
998
|
\
|
|
969
999
|
return array; \
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1000
|
+
} while (false)
|
|
1001
|
+
|
|
1002
|
+
switch (ref->primitive) {
|
|
1003
|
+
case PrimitiveKind::Int8: { POP_TYPEDARRAY(Int8Array, int8_t); } break;
|
|
1004
|
+
case PrimitiveKind::UInt8: { POP_TYPEDARRAY(Uint8Array, uint8_t); } break;
|
|
1005
|
+
case PrimitiveKind::Int16: { POP_TYPEDARRAY(Int16Array, int16_t); } break;
|
|
1006
|
+
case PrimitiveKind::Int16S: { POP_TYPEDARRAY(Int16Array, int16_t); } break;
|
|
1007
|
+
case PrimitiveKind::UInt16: { POP_TYPEDARRAY(Uint16Array, uint16_t); } break;
|
|
1008
|
+
case PrimitiveKind::UInt16S: { POP_TYPEDARRAY(Uint16Array, uint16_t); } break;
|
|
1009
|
+
case PrimitiveKind::Int32: { POP_TYPEDARRAY(Int32Array, int32_t); } break;
|
|
1010
|
+
case PrimitiveKind::Int32S: { POP_TYPEDARRAY(Int32Array, int32_t); } break;
|
|
1011
|
+
case PrimitiveKind::UInt32: { POP_TYPEDARRAY(Uint32Array, uint32_t); } break;
|
|
1012
|
+
case PrimitiveKind::UInt32S: { POP_TYPEDARRAY(Uint32Array, uint32_t); } break;
|
|
1013
|
+
case PrimitiveKind::Float32: { POP_TYPEDARRAY(Float32Array, float); } break;
|
|
1014
|
+
case PrimitiveKind::Float64: { POP_TYPEDARRAY(Float64Array, double); } break;
|
|
1015
|
+
|
|
1016
|
+
case PrimitiveKind::Void:
|
|
1017
|
+
case PrimitiveKind::Bool:
|
|
1018
|
+
case PrimitiveKind::Int64:
|
|
1019
|
+
case PrimitiveKind::Int64S:
|
|
1020
|
+
case PrimitiveKind::UInt64:
|
|
1021
|
+
case PrimitiveKind::UInt64S:
|
|
1022
|
+
case PrimitiveKind::String:
|
|
1023
|
+
case PrimitiveKind::String16:
|
|
1024
|
+
case PrimitiveKind::String32:
|
|
1025
|
+
case PrimitiveKind::Pointer:
|
|
1026
|
+
case PrimitiveKind::Callback:
|
|
1027
|
+
case PrimitiveKind::Record:
|
|
1028
|
+
case PrimitiveKind::Union:
|
|
1029
|
+
case PrimitiveKind::Array:
|
|
1030
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
1031
|
+
}
|
|
975
1032
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
});
|
|
981
|
-
} break;
|
|
982
|
-
case PrimitiveKind::Int8: {
|
|
983
|
-
if (type->hint == ArrayHint::String) {
|
|
1033
|
+
#undef POP_TYPEDARRAY
|
|
1034
|
+
} else if (type->hint == ArrayHint::String) {
|
|
1035
|
+
switch (ref->primitive) {
|
|
1036
|
+
case PrimitiveKind::Int8: {
|
|
984
1037
|
const char *ptr = (const char *)origin;
|
|
985
1038
|
size_t count = strnlen(ptr, (size_t)len);
|
|
986
1039
|
|
|
987
1040
|
Napi::String str = Napi::String::New(env, ptr, count);
|
|
988
1041
|
return str;
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
POP_NUMBER_ARRAY(Int8Array, int8_t);
|
|
992
|
-
} break;
|
|
993
|
-
case PrimitiveKind::UInt8: { POP_NUMBER_ARRAY(Uint8Array, uint8_t); } break;
|
|
994
|
-
case PrimitiveKind::Int16: {
|
|
995
|
-
if (type->hint == ArrayHint::String) {
|
|
1042
|
+
} break;
|
|
1043
|
+
case PrimitiveKind::Int16: {
|
|
996
1044
|
const char16_t *ptr = (const char16_t *)origin;
|
|
997
1045
|
Size count = NullTerminatedLength(ptr, len);
|
|
998
1046
|
|
|
999
1047
|
Napi::String str = Napi::String::New(env, ptr, count);
|
|
1000
1048
|
return str;
|
|
1001
|
-
}
|
|
1002
|
-
|
|
1003
|
-
POP_NUMBER_ARRAY(Int16Array, int16_t);
|
|
1004
|
-
} break;
|
|
1005
|
-
case PrimitiveKind::Int16S: { POP_NUMBER_ARRAY_SWAP(Int16Array, int16_t); } break;
|
|
1006
|
-
case PrimitiveKind::UInt16: { POP_NUMBER_ARRAY(Uint16Array, uint16_t); } break;
|
|
1007
|
-
case PrimitiveKind::UInt16S: { POP_NUMBER_ARRAY_SWAP(Uint16Array, uint16_t); } break;
|
|
1008
|
-
case PrimitiveKind::Int32: {
|
|
1009
|
-
if (type->hint == ArrayHint::String) {
|
|
1049
|
+
} break;
|
|
1050
|
+
case PrimitiveKind::Int32: {
|
|
1010
1051
|
const char32_t *ptr = (const char32_t *)origin;
|
|
1011
1052
|
Size count = NullTerminatedLength(ptr, len);
|
|
1012
1053
|
|
|
1013
1054
|
Napi::String str = MakeStringFromUTF32(env, ptr, count);
|
|
1014
1055
|
return str;
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
POP_NUMBER_ARRAY(Int32Array, int32_t);
|
|
1018
|
-
} break;
|
|
1019
|
-
case PrimitiveKind::Int32S: { POP_NUMBER_ARRAY_SWAP(Int32Array, int32_t); } break;
|
|
1020
|
-
case PrimitiveKind::UInt32: { POP_NUMBER_ARRAY(Uint32Array, uint32_t); } break;
|
|
1021
|
-
case PrimitiveKind::UInt32S: { POP_NUMBER_ARRAY_SWAP(Uint32Array, uint32_t); } break;
|
|
1022
|
-
case PrimitiveKind::Int64: {
|
|
1023
|
-
POP_ARRAY({
|
|
1024
|
-
int64_t v = *(int64_t *)src;
|
|
1025
|
-
array.Set(i, NewBigInt(env, v));
|
|
1026
|
-
});
|
|
1027
|
-
} break;
|
|
1028
|
-
case PrimitiveKind::Int64S: {
|
|
1029
|
-
POP_ARRAY({
|
|
1030
|
-
int64_t v = ReverseBytes(*(int64_t *)src);
|
|
1031
|
-
array.Set(i, NewBigInt(env, v));
|
|
1032
|
-
});
|
|
1033
|
-
} break;
|
|
1034
|
-
case PrimitiveKind::UInt64: {
|
|
1035
|
-
POP_ARRAY({
|
|
1036
|
-
uint64_t v = *(uint64_t *)src;
|
|
1037
|
-
array.Set(i, NewBigInt(env, v));
|
|
1038
|
-
});
|
|
1039
|
-
} break;
|
|
1040
|
-
case PrimitiveKind::UInt64S: {
|
|
1041
|
-
POP_ARRAY({
|
|
1042
|
-
uint64_t v = ReverseBytes(*(uint64_t *)src);
|
|
1043
|
-
array.Set(i, NewBigInt(env, v));
|
|
1044
|
-
});
|
|
1045
|
-
} break;
|
|
1046
|
-
case PrimitiveKind::String: {
|
|
1047
|
-
POP_ARRAY({
|
|
1048
|
-
const char *str = *(const char **)src;
|
|
1049
|
-
array.Set(i, str ? Napi::String::New(env, str) : env.Null());
|
|
1050
|
-
});
|
|
1051
|
-
} break;
|
|
1052
|
-
case PrimitiveKind::String16: {
|
|
1053
|
-
POP_ARRAY({
|
|
1054
|
-
const char16_t *str16 = *(const char16_t **)src;
|
|
1055
|
-
array.Set(i, str16 ? Napi::String::New(env, str16) : env.Null());
|
|
1056
|
-
});
|
|
1057
|
-
} break;
|
|
1058
|
-
case PrimitiveKind::String32: {
|
|
1059
|
-
POP_ARRAY({
|
|
1060
|
-
const char32_t *str32 = *(const char32_t **)src;
|
|
1061
|
-
array.Set(i, str32 ? MakeStringFromUTF32(env, str32) : env.Null());
|
|
1062
|
-
});
|
|
1063
|
-
} break;
|
|
1064
|
-
case PrimitiveKind::Pointer:
|
|
1065
|
-
case PrimitiveKind::Callback: {
|
|
1066
|
-
POP_ARRAY({
|
|
1067
|
-
void *ptr2 = *(void **)src;
|
|
1056
|
+
} break;
|
|
1068
1057
|
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1058
|
+
case PrimitiveKind::Void:
|
|
1059
|
+
case PrimitiveKind::Bool:
|
|
1060
|
+
case PrimitiveKind::UInt8:
|
|
1061
|
+
case PrimitiveKind::Int16S:
|
|
1062
|
+
case PrimitiveKind::UInt16:
|
|
1063
|
+
case PrimitiveKind::UInt16S:
|
|
1064
|
+
case PrimitiveKind::Int32S:
|
|
1065
|
+
case PrimitiveKind::UInt32:
|
|
1066
|
+
case PrimitiveKind::UInt32S:
|
|
1067
|
+
case PrimitiveKind::Int64:
|
|
1068
|
+
case PrimitiveKind::Int64S:
|
|
1069
|
+
case PrimitiveKind::UInt64:
|
|
1070
|
+
case PrimitiveKind::UInt64S:
|
|
1071
|
+
case PrimitiveKind::String:
|
|
1072
|
+
case PrimitiveKind::String16:
|
|
1073
|
+
case PrimitiveKind::String32:
|
|
1074
|
+
case PrimitiveKind::Pointer:
|
|
1075
|
+
case PrimitiveKind::Callback:
|
|
1076
|
+
case PrimitiveKind::Record:
|
|
1077
|
+
case PrimitiveKind::Union:
|
|
1078
|
+
case PrimitiveKind::Array:
|
|
1079
|
+
case PrimitiveKind::Float32:
|
|
1080
|
+
case PrimitiveKind::Float64:
|
|
1081
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
1082
|
+
}
|
|
1083
|
+
} else {
|
|
1084
|
+
K_ASSERT(type->hint == ArrayHint::Array);
|
|
1072
1085
|
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
array.Set(i, env.Null());
|
|
1076
|
-
}
|
|
1077
|
-
});
|
|
1078
|
-
} break;
|
|
1079
|
-
case PrimitiveKind::Record:
|
|
1080
|
-
case PrimitiveKind::Union: {
|
|
1081
|
-
POP_ARRAY({
|
|
1082
|
-
Napi::Object obj = DecodeObject(env, src, type->ref.type);
|
|
1083
|
-
array.Set(i, obj);
|
|
1084
|
-
});
|
|
1085
|
-
} break;
|
|
1086
|
-
case PrimitiveKind::Array: {
|
|
1087
|
-
POP_ARRAY({
|
|
1088
|
-
Napi::Value value = DecodeArray(env, src, type->ref.type);
|
|
1089
|
-
array.Set(i, value);
|
|
1090
|
-
});
|
|
1091
|
-
} break;
|
|
1092
|
-
case PrimitiveKind::Float32: { POP_NUMBER_ARRAY(Float32Array, float); } break;
|
|
1093
|
-
case PrimitiveKind::Float64: { POP_NUMBER_ARRAY(Float64Array, double); } break;
|
|
1086
|
+
Napi::Array array = Napi::Array::New(env);
|
|
1087
|
+
DecodeElements(env, array, origin, type->ref.type, len);
|
|
1094
1088
|
|
|
1095
|
-
|
|
1089
|
+
return array;
|
|
1096
1090
|
}
|
|
1097
1091
|
|
|
1098
|
-
#undef POP_NUMBER_ARRAY_SWAP
|
|
1099
|
-
#undef POP_NUMBER_ARRAY
|
|
1100
|
-
#undef POP_ARRAY
|
|
1101
|
-
|
|
1102
1092
|
K_UNREACHABLE();
|
|
1103
1093
|
}
|
|
1104
1094
|
|
|
1105
|
-
|
|
1106
|
-
{
|
|
1107
|
-
K_ASSERT(type->primitive == PrimitiveKind::Array);
|
|
1108
|
-
|
|
1109
|
-
uint32_t len = type->size / type->ref.type->size;
|
|
1110
|
-
return DecodeArray(env, origin, type, len);
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
|
-
void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo *ref)
|
|
1095
|
+
void DecodeElements(Napi::Env env, napi_value array, const uint8_t *origin, const TypeInfo *ref, uint32_t len)
|
|
1114
1096
|
{
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
K_ASSERT(array.IsArray());
|
|
1097
|
+
K_ASSERT(IsArray(env, array));
|
|
1118
1098
|
|
|
1119
1099
|
Size offset = 0;
|
|
1120
|
-
uint32_t len = array.Length();
|
|
1121
1100
|
|
|
1122
1101
|
#define POP_ARRAY(SetCode) \
|
|
1123
1102
|
do { \
|
|
@@ -1131,19 +1110,19 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
|
|
|
1131
1110
|
offset += ref->size; \
|
|
1132
1111
|
} \
|
|
1133
1112
|
} while (false)
|
|
1134
|
-
|
|
1113
|
+
|
|
1114
|
+
#define POP_INTEGERS(CType) \
|
|
1135
1115
|
do { \
|
|
1136
1116
|
POP_ARRAY({ \
|
|
1137
|
-
|
|
1138
|
-
array
|
|
1117
|
+
CType v = *(CType *)src; \
|
|
1118
|
+
napi_set_element(env, array, i, NewInt(env, v)); \
|
|
1139
1119
|
}); \
|
|
1140
1120
|
} while (false)
|
|
1141
|
-
#define
|
|
1121
|
+
#define POP_INTEGERS_SWAP(CType) \
|
|
1142
1122
|
do { \
|
|
1143
1123
|
POP_ARRAY({ \
|
|
1144
1124
|
CType v = *(CType *)src; \
|
|
1145
|
-
|
|
1146
|
-
array.Set(i, Napi::Number::New(env, d)); \
|
|
1125
|
+
napi_set_element(env, array, i, NewInt(env, ReverseBytes(v))); \
|
|
1147
1126
|
}); \
|
|
1148
1127
|
} while (false)
|
|
1149
1128
|
|
|
@@ -1153,47 +1132,27 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
|
|
|
1153
1132
|
case PrimitiveKind::Bool: {
|
|
1154
1133
|
POP_ARRAY({
|
|
1155
1134
|
bool b = *(bool *)src;
|
|
1156
|
-
array
|
|
1157
|
-
});
|
|
1158
|
-
} break;
|
|
1159
|
-
case PrimitiveKind::Int8: { POP_NUMBER_ARRAY(int8_t); } break;
|
|
1160
|
-
case PrimitiveKind::UInt8: { POP_NUMBER_ARRAY(uint8_t); } break;
|
|
1161
|
-
case PrimitiveKind::Int16: { POP_NUMBER_ARRAY(int16_t); } break;
|
|
1162
|
-
case PrimitiveKind::Int16S: { POP_NUMBER_ARRAY_SWAP(int16_t); } break;
|
|
1163
|
-
case PrimitiveKind::UInt16: { POP_NUMBER_ARRAY(uint16_t); } break;
|
|
1164
|
-
case PrimitiveKind::UInt16S: { POP_NUMBER_ARRAY_SWAP(uint16_t); } break;
|
|
1165
|
-
case PrimitiveKind::Int32: { POP_NUMBER_ARRAY(int32_t); } break;
|
|
1166
|
-
case PrimitiveKind::Int32S: { POP_NUMBER_ARRAY_SWAP(int32_t); } break;
|
|
1167
|
-
case PrimitiveKind::UInt32: { POP_NUMBER_ARRAY(uint32_t); } break;
|
|
1168
|
-
case PrimitiveKind::UInt32S: { POP_NUMBER_ARRAY_SWAP(uint32_t); } break;
|
|
1169
|
-
case PrimitiveKind::Int64: {
|
|
1170
|
-
POP_ARRAY({
|
|
1171
|
-
int64_t v = *(int64_t *)src;
|
|
1172
|
-
array.Set(i, NewBigInt(env, v));
|
|
1173
|
-
});
|
|
1174
|
-
} break;
|
|
1175
|
-
case PrimitiveKind::Int64S: {
|
|
1176
|
-
POP_ARRAY({
|
|
1177
|
-
int64_t v = ReverseBytes(*(int64_t *)src);
|
|
1178
|
-
array.Set(i, NewBigInt(env, v));
|
|
1179
|
-
});
|
|
1180
|
-
} break;
|
|
1181
|
-
case PrimitiveKind::UInt64: {
|
|
1182
|
-
POP_ARRAY({
|
|
1183
|
-
uint64_t v = *(uint64_t *)src;
|
|
1184
|
-
array.Set(i, NewBigInt(env, v));
|
|
1185
|
-
});
|
|
1186
|
-
} break;
|
|
1187
|
-
case PrimitiveKind::UInt64S: {
|
|
1188
|
-
POP_ARRAY({
|
|
1189
|
-
uint64_t v = ReverseBytes(*(uint64_t *)src);
|
|
1190
|
-
array.Set(i, NewBigInt(env, v));
|
|
1135
|
+
napi_set_element(env, array, i, Napi::Boolean::New(env, b));
|
|
1191
1136
|
});
|
|
1192
1137
|
} break;
|
|
1138
|
+
case PrimitiveKind::Int8: { POP_INTEGERS(int8_t); } break;
|
|
1139
|
+
case PrimitiveKind::UInt8: { POP_INTEGERS(uint8_t); } break;
|
|
1140
|
+
case PrimitiveKind::Int16: { POP_INTEGERS(int16_t); } break;
|
|
1141
|
+
case PrimitiveKind::Int16S: { POP_INTEGERS_SWAP(int16_t); } break;
|
|
1142
|
+
case PrimitiveKind::UInt16: { POP_INTEGERS(uint16_t); } break;
|
|
1143
|
+
case PrimitiveKind::UInt16S: { POP_INTEGERS_SWAP(uint16_t); } break;
|
|
1144
|
+
case PrimitiveKind::Int32: { POP_INTEGERS(int32_t); } break;
|
|
1145
|
+
case PrimitiveKind::Int32S: { POP_INTEGERS_SWAP(int32_t); } break;
|
|
1146
|
+
case PrimitiveKind::UInt32: { POP_INTEGERS(uint32_t); } break;
|
|
1147
|
+
case PrimitiveKind::UInt32S: { POP_INTEGERS_SWAP(uint32_t); } break;
|
|
1148
|
+
case PrimitiveKind::Int64: { POP_INTEGERS(int64_t); } break;
|
|
1149
|
+
case PrimitiveKind::Int64S: { POP_INTEGERS_SWAP(int64_t); } break;
|
|
1150
|
+
case PrimitiveKind::UInt64: { POP_INTEGERS(uint64_t); } break;
|
|
1151
|
+
case PrimitiveKind::UInt64S: { POP_INTEGERS_SWAP(uint64_t); } break;
|
|
1193
1152
|
case PrimitiveKind::String: {
|
|
1194
1153
|
POP_ARRAY({
|
|
1195
1154
|
const char *str = *(const char **)src;
|
|
1196
|
-
array
|
|
1155
|
+
napi_set_element(env, array, i, str ? Napi::String::New(env, str) : env.Null());
|
|
1197
1156
|
|
|
1198
1157
|
if (ref->dispose) {
|
|
1199
1158
|
ref->dispose(env, ref, str);
|
|
@@ -1203,7 +1162,7 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
|
|
|
1203
1162
|
case PrimitiveKind::String16: {
|
|
1204
1163
|
POP_ARRAY({
|
|
1205
1164
|
const char16_t *str16 = *(const char16_t **)src;
|
|
1206
|
-
array
|
|
1165
|
+
napi_set_element(env, array, i, str16 ? Napi::String::New(env, str16) : env.Null());
|
|
1207
1166
|
|
|
1208
1167
|
if (ref->dispose) {
|
|
1209
1168
|
ref->dispose(env, ref, str16);
|
|
@@ -1213,26 +1172,31 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
|
|
|
1213
1172
|
case PrimitiveKind::String32: {
|
|
1214
1173
|
POP_ARRAY({
|
|
1215
1174
|
const char32_t *str32 = *(const char32_t **)src;
|
|
1216
|
-
array
|
|
1175
|
+
napi_set_element(env, array, i, str32 ? MakeStringFromUTF32(env, str32) : env.Null());
|
|
1217
1176
|
|
|
1218
1177
|
if (ref->dispose) {
|
|
1219
1178
|
ref->dispose(env, ref, str32);
|
|
1220
1179
|
}
|
|
1221
1180
|
});
|
|
1222
1181
|
} break;
|
|
1223
|
-
case PrimitiveKind::Pointer:
|
|
1224
|
-
case PrimitiveKind::Callback: {
|
|
1182
|
+
case PrimitiveKind::Pointer: {
|
|
1225
1183
|
POP_ARRAY({
|
|
1226
1184
|
void *ptr2 = *(void **)src;
|
|
1227
1185
|
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
SetValueTag(external, ref->ref.marker);
|
|
1186
|
+
Napi::Value p = ptr2 ? WrapPointer(env, ref->ref.type, ptr2) : env.Null();
|
|
1187
|
+
napi_set_element(env, array, i, p);
|
|
1231
1188
|
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
array.Set(i, env.Null());
|
|
1189
|
+
if (ref->dispose) {
|
|
1190
|
+
ref->dispose(env, ref, ptr2);
|
|
1235
1191
|
}
|
|
1192
|
+
});
|
|
1193
|
+
} break;
|
|
1194
|
+
case PrimitiveKind::Callback: {
|
|
1195
|
+
POP_ARRAY({
|
|
1196
|
+
void *ptr2 = *(void **)src;
|
|
1197
|
+
|
|
1198
|
+
Napi::Value p = ptr2 ? WrapCallback(env, ref->ref.type, ptr2) : env.Null();
|
|
1199
|
+
napi_set_element(env, array, i, p);
|
|
1236
1200
|
|
|
1237
1201
|
if (ref->dispose) {
|
|
1238
1202
|
ref->dispose(env, ref, ptr2);
|
|
@@ -1243,23 +1207,38 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
|
|
|
1243
1207
|
case PrimitiveKind::Union: {
|
|
1244
1208
|
POP_ARRAY({
|
|
1245
1209
|
Napi::Object obj = DecodeObject(env, src, ref);
|
|
1246
|
-
array
|
|
1210
|
+
napi_set_element(env, array, i, obj);
|
|
1247
1211
|
});
|
|
1248
1212
|
} break;
|
|
1249
1213
|
case PrimitiveKind::Array: {
|
|
1250
1214
|
POP_ARRAY({
|
|
1251
1215
|
Napi::Value value = DecodeArray(env, src, ref);
|
|
1252
|
-
array
|
|
1216
|
+
napi_set_element(env, array, i, value);
|
|
1217
|
+
});
|
|
1218
|
+
} break;
|
|
1219
|
+
case PrimitiveKind::Float32: {
|
|
1220
|
+
POP_ARRAY({
|
|
1221
|
+
float f;
|
|
1222
|
+
memcpy(&f, src, 4);
|
|
1223
|
+
|
|
1224
|
+
napi_set_element(env, array, i, Napi::Number::New(env, (double)f));
|
|
1225
|
+
});
|
|
1226
|
+
} break;
|
|
1227
|
+
case PrimitiveKind::Float64: {
|
|
1228
|
+
POP_ARRAY({
|
|
1229
|
+
double d;
|
|
1230
|
+
memcpy(&d, src, 8);
|
|
1231
|
+
|
|
1232
|
+
napi_set_element(env, array, i, Napi::Number::New(env, d));
|
|
1253
1233
|
});
|
|
1254
1234
|
} break;
|
|
1255
|
-
case PrimitiveKind::Float32: { POP_NUMBER_ARRAY(float); } break;
|
|
1256
|
-
case PrimitiveKind::Float64: { POP_NUMBER_ARRAY(double); } break;
|
|
1257
1235
|
|
|
1258
1236
|
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
1259
1237
|
}
|
|
1260
1238
|
|
|
1261
|
-
#undef
|
|
1262
|
-
#undef
|
|
1239
|
+
#undef POP_INTEGERS_SWAP
|
|
1240
|
+
#undef POP_INTEGERS
|
|
1241
|
+
|
|
1263
1242
|
#undef POP_ARRAY
|
|
1264
1243
|
}
|
|
1265
1244
|
|
|
@@ -1294,14 +1273,9 @@ Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, const S
|
|
|
1294
1273
|
Napi::Env env = value.Env();
|
|
1295
1274
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1296
1275
|
|
|
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);
|
|
1276
|
+
const uint8_t *src = nullptr;
|
|
1304
1277
|
|
|
1278
|
+
if (Span<uint8_t> buffer = {}; TryBuffer(env, value, &buffer)) {
|
|
1305
1279
|
if (offset < 0) [[unlikely]] {
|
|
1306
1280
|
ThrowError<Napi::Error>(env, "Offset must be >= 0");
|
|
1307
1281
|
return env.Null();
|
|
@@ -1312,17 +1286,19 @@ Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, const S
|
|
|
1312
1286
|
return env.Null();
|
|
1313
1287
|
}
|
|
1314
1288
|
|
|
1315
|
-
|
|
1289
|
+
src = (const uint8_t *)buffer.ptr;
|
|
1290
|
+
} else if (void *ptr = nullptr; TryPointer(env, value, &ptr)) {
|
|
1291
|
+
src = (const uint8_t *)ptr;
|
|
1316
1292
|
} else {
|
|
1317
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for variable, expected
|
|
1293
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for variable, expected pointer", GetValueType(instance, value));
|
|
1318
1294
|
return env.Null();
|
|
1319
1295
|
}
|
|
1320
1296
|
|
|
1321
|
-
if (!
|
|
1297
|
+
if (!src)
|
|
1322
1298
|
return env.Null();
|
|
1323
|
-
|
|
1299
|
+
src += offset;
|
|
1324
1300
|
|
|
1325
|
-
Napi::Value ret = Decode(env,
|
|
1301
|
+
Napi::Value ret = Decode(env, src, type, len);
|
|
1326
1302
|
return ret;
|
|
1327
1303
|
}
|
|
1328
1304
|
|
|
@@ -1345,17 +1321,17 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1345
1321
|
} break;
|
|
1346
1322
|
case PrimitiveKind::Int16:
|
|
1347
1323
|
case PrimitiveKind::UInt16: {
|
|
1348
|
-
Size count = NullTerminatedLength((const char16_t *)ptr
|
|
1324
|
+
Size count = NullTerminatedLength((const char16_t *)ptr);
|
|
1349
1325
|
type = MakeArrayType(instance, type, count);
|
|
1350
1326
|
} break;
|
|
1351
1327
|
case PrimitiveKind::Int32:
|
|
1352
1328
|
case PrimitiveKind::UInt32: {
|
|
1353
|
-
Size count = NullTerminatedLength((const char32_t *)ptr
|
|
1329
|
+
Size count = NullTerminatedLength((const char32_t *)ptr);
|
|
1354
1330
|
type = MakeArrayType(instance, type, count);
|
|
1355
1331
|
} break;
|
|
1356
1332
|
|
|
1357
1333
|
case PrimitiveKind::Pointer: {
|
|
1358
|
-
Size count = NullTerminatedLength((const void **)ptr
|
|
1334
|
+
Size count = NullTerminatedLength((const void **)ptr);
|
|
1359
1335
|
type = MakeArrayType(instance, type, count);
|
|
1360
1336
|
} break;
|
|
1361
1337
|
|
|
@@ -1388,20 +1364,20 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1388
1364
|
bool v = *(bool *)ptr;
|
|
1389
1365
|
return Napi::Boolean::New(env, v);
|
|
1390
1366
|
} break;
|
|
1391
|
-
case PrimitiveKind::Int8: { RETURN_INT(int8_t,
|
|
1392
|
-
case PrimitiveKind::UInt8: { RETURN_INT(uint8_t,
|
|
1393
|
-
case PrimitiveKind::Int16: { RETURN_INT(int16_t,
|
|
1394
|
-
case PrimitiveKind::Int16S: { RETURN_INT_SWAP(int16_t,
|
|
1395
|
-
case PrimitiveKind::UInt16: { RETURN_INT(uint16_t,
|
|
1396
|
-
case PrimitiveKind::UInt16S: { RETURN_INT_SWAP(uint16_t,
|
|
1397
|
-
case PrimitiveKind::Int32: { RETURN_INT(int32_t,
|
|
1398
|
-
case PrimitiveKind::Int32S: { RETURN_INT_SWAP(int32_t,
|
|
1399
|
-
case PrimitiveKind::UInt32: { RETURN_INT(uint32_t,
|
|
1400
|
-
case PrimitiveKind::UInt32S: { RETURN_INT_SWAP(uint32_t,
|
|
1401
|
-
case PrimitiveKind::Int64: { RETURN_INT(int64_t,
|
|
1402
|
-
case PrimitiveKind::Int64S: { RETURN_INT_SWAP(int64_t,
|
|
1403
|
-
case PrimitiveKind::UInt64: { RETURN_INT(uint64_t,
|
|
1404
|
-
case PrimitiveKind::UInt64S: { RETURN_INT_SWAP(uint64_t,
|
|
1367
|
+
case PrimitiveKind::Int8: { RETURN_INT(int8_t, NewInt); } break;
|
|
1368
|
+
case PrimitiveKind::UInt8: { RETURN_INT(uint8_t, NewInt); } break;
|
|
1369
|
+
case PrimitiveKind::Int16: { RETURN_INT(int16_t, NewInt); } break;
|
|
1370
|
+
case PrimitiveKind::Int16S: { RETURN_INT_SWAP(int16_t, NewInt); } break;
|
|
1371
|
+
case PrimitiveKind::UInt16: { RETURN_INT(uint16_t, NewInt); } break;
|
|
1372
|
+
case PrimitiveKind::UInt16S: { RETURN_INT_SWAP(uint16_t, NewInt); } break;
|
|
1373
|
+
case PrimitiveKind::Int32: { RETURN_INT(int32_t, NewInt); } break;
|
|
1374
|
+
case PrimitiveKind::Int32S: { RETURN_INT_SWAP(int32_t, NewInt); } break;
|
|
1375
|
+
case PrimitiveKind::UInt32: { RETURN_INT(uint32_t, NewInt); } break;
|
|
1376
|
+
case PrimitiveKind::UInt32S: { RETURN_INT_SWAP(uint32_t, NewInt); } break;
|
|
1377
|
+
case PrimitiveKind::Int64: { RETURN_INT(int64_t, NewInt); } break;
|
|
1378
|
+
case PrimitiveKind::Int64S: { RETURN_INT_SWAP(int64_t, NewInt); } break;
|
|
1379
|
+
case PrimitiveKind::UInt64: { RETURN_INT(uint64_t, NewInt); } break;
|
|
1380
|
+
case PrimitiveKind::UInt64S: { RETURN_INT_SWAP(uint64_t, NewInt); } break;
|
|
1405
1381
|
case PrimitiveKind::String: {
|
|
1406
1382
|
if (len) {
|
|
1407
1383
|
const char *str = *(const char **)ptr;
|
|
@@ -1429,10 +1405,13 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1429
1405
|
return str32 ? MakeStringFromUTF32(env, str32) : env.Null();
|
|
1430
1406
|
}
|
|
1431
1407
|
} break;
|
|
1432
|
-
case PrimitiveKind::Pointer:
|
|
1408
|
+
case PrimitiveKind::Pointer: {
|
|
1409
|
+
void *ptr2 = *(void **)ptr;
|
|
1410
|
+
return ptr2 ? WrapPointer(env, type->ref.type, ptr2) : env.Null();
|
|
1411
|
+
} break;
|
|
1433
1412
|
case PrimitiveKind::Callback: {
|
|
1434
1413
|
void *ptr2 = *(void **)ptr;
|
|
1435
|
-
return ptr2 ?
|
|
1414
|
+
return ptr2 ? WrapCallback(env, type->ref.type, ptr2) : env.Null();
|
|
1436
1415
|
} break;
|
|
1437
1416
|
case PrimitiveKind::Record:
|
|
1438
1417
|
case PrimitiveKind::Union: {
|
|
@@ -1444,11 +1423,15 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1444
1423
|
return array;
|
|
1445
1424
|
} break;
|
|
1446
1425
|
case PrimitiveKind::Float32: {
|
|
1447
|
-
float f
|
|
1448
|
-
|
|
1426
|
+
float f;
|
|
1427
|
+
memcpy(&f, ptr, 4);
|
|
1428
|
+
|
|
1429
|
+
return Napi::Number::New(env, (double)f);
|
|
1449
1430
|
} break;
|
|
1450
1431
|
case PrimitiveKind::Float64: {
|
|
1451
|
-
double d
|
|
1432
|
+
double d;
|
|
1433
|
+
memcpy(&d, ptr, 8);
|
|
1434
|
+
|
|
1452
1435
|
return Napi::Number::New(env, d);
|
|
1453
1436
|
} break;
|
|
1454
1437
|
|
|
@@ -1462,16 +1445,14 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
|
|
|
1462
1445
|
|
|
1463
1446
|
memcpy((void *)func, proto, K_SIZE(*proto));
|
|
1464
1447
|
memset((void *)&func->parameters, 0, K_SIZE(func->parameters));
|
|
1465
|
-
func->
|
|
1448
|
+
memset((void *)&func->sync, 0, K_SIZE(func->sync));
|
|
1449
|
+
memset((void *)&func->async, 0, K_SIZE(func->async));
|
|
1466
1450
|
|
|
1467
1451
|
func->name = "<anonymous>";
|
|
1468
1452
|
func->native = (void *)ptr;
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
param.offset -= 2;
|
|
1473
|
-
}
|
|
1474
|
-
func->required_parameters -= 2;
|
|
1453
|
+
func->parameters = proto->parameters;
|
|
1454
|
+
func->sync = proto->sync;
|
|
1455
|
+
func->async = proto->async;
|
|
1475
1456
|
|
|
1476
1457
|
Napi::Function wrapper = WrapFunction(env, func);
|
|
1477
1458
|
return wrapper;
|
|
@@ -1489,14 +1470,9 @@ bool Encode(Napi::Value ref, Size offset, Napi::Value value, const TypeInfo *typ
|
|
|
1489
1470
|
Napi::Env env = ref.Env();
|
|
1490
1471
|
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1491
1472
|
|
|
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);
|
|
1473
|
+
uint8_t *dest = nullptr;
|
|
1499
1474
|
|
|
1475
|
+
if (Span<uint8_t> buffer = {}; TryBuffer(env, ref, &buffer)) {
|
|
1500
1476
|
if (offset < 0) [[unlikely]] {
|
|
1501
1477
|
ThrowError<Napi::Error>(env, "Offset must be >= 0");
|
|
1502
1478
|
return env.Null();
|
|
@@ -1507,19 +1483,21 @@ bool Encode(Napi::Value ref, Size offset, Napi::Value value, const TypeInfo *typ
|
|
|
1507
1483
|
return env.Null();
|
|
1508
1484
|
}
|
|
1509
1485
|
|
|
1510
|
-
|
|
1486
|
+
dest = (uint8_t *)buffer.ptr;
|
|
1487
|
+
} else if (void *ptr = nullptr; TryPointer(env, ref, &ptr)) {
|
|
1488
|
+
dest = (uint8_t *)ptr;
|
|
1511
1489
|
} else {
|
|
1512
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for reference, expected
|
|
1490
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for reference, expected pointer", GetValueType(instance, ref));
|
|
1513
1491
|
return env.Null();
|
|
1514
1492
|
}
|
|
1515
1493
|
|
|
1516
|
-
if (!
|
|
1494
|
+
if (!dest) [[unlikely]] {
|
|
1517
1495
|
ThrowError<Napi::Error>(env, "Cannot encode data in NULL pointer");
|
|
1518
1496
|
return env.Null();
|
|
1519
1497
|
}
|
|
1520
|
-
|
|
1498
|
+
dest += offset;
|
|
1521
1499
|
|
|
1522
|
-
return Encode(env,
|
|
1500
|
+
return Encode(env, dest, value, type, len);
|
|
1523
1501
|
}
|
|
1524
1502
|
|
|
1525
1503
|
bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *type, const Size *len)
|
|
@@ -1539,26 +1517,26 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1539
1517
|
}
|
|
1540
1518
|
|
|
1541
1519
|
InstanceMemory mem = {};
|
|
1542
|
-
CallData call(env, instance, &mem);
|
|
1520
|
+
CallData call(env, instance, &mem, nullptr);
|
|
1543
1521
|
|
|
1544
1522
|
#define PUSH_INTEGER(CType) \
|
|
1545
1523
|
do { \
|
|
1546
|
-
|
|
1524
|
+
CType v; \
|
|
1525
|
+
if (!TryNumber(env, value, &v)) [[unlikely]] { \
|
|
1547
1526
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
1548
1527
|
return false; \
|
|
1549
1528
|
} \
|
|
1550
1529
|
\
|
|
1551
|
-
CType v = GetNumber<CType>(value); \
|
|
1552
1530
|
*(CType *)origin = v; \
|
|
1553
1531
|
} while (false)
|
|
1554
1532
|
#define PUSH_INTEGER_SWAP(CType) \
|
|
1555
1533
|
do { \
|
|
1556
|
-
|
|
1534
|
+
CType v; \
|
|
1535
|
+
if (!TryNumber(env, value, &v)) [[unlikely]] { \
|
|
1557
1536
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
1558
1537
|
return false; \
|
|
1559
1538
|
} \
|
|
1560
1539
|
\
|
|
1561
|
-
CType v = GetNumber<CType>(value); \
|
|
1562
1540
|
*(CType *)origin = ReverseBytes(v); \
|
|
1563
1541
|
} while (false)
|
|
1564
1542
|
|
|
@@ -1566,12 +1544,14 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1566
1544
|
case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
|
|
1567
1545
|
|
|
1568
1546
|
case PrimitiveKind::Bool: {
|
|
1569
|
-
|
|
1547
|
+
bool b;
|
|
1548
|
+
napi_status status = napi_get_value_bool(env, value, &b);
|
|
1549
|
+
|
|
1550
|
+
if (status != napi_ok) [[unlikely]] {
|
|
1570
1551
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
1571
1552
|
return false;
|
|
1572
1553
|
}
|
|
1573
1554
|
|
|
1574
|
-
bool b = value.As<Napi::Boolean>();
|
|
1575
1555
|
*(bool *)origin = b;
|
|
1576
1556
|
} break;
|
|
1577
1557
|
case PrimitiveKind::Int8: { PUSH_INTEGER(int8_t); } break;
|
|
@@ -1614,7 +1594,7 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1614
1594
|
} break;
|
|
1615
1595
|
case PrimitiveKind::Record:
|
|
1616
1596
|
case PrimitiveKind::Union: {
|
|
1617
|
-
if (!IsObject(value)) [[unlikely]] {
|
|
1597
|
+
if (!IsObject(env, value)) [[unlikely]] {
|
|
1618
1598
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
1619
1599
|
return false;
|
|
1620
1600
|
}
|
|
@@ -1626,11 +1606,10 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1626
1606
|
} break;
|
|
1627
1607
|
case PrimitiveKind::Array: {
|
|
1628
1608
|
if (value.IsArray()) {
|
|
1629
|
-
Napi::Array array =
|
|
1609
|
+
Napi::Array array = Napi::Array(env, value);
|
|
1630
1610
|
if (!call.PushNormalArray(array, type, type->size, origin))
|
|
1631
1611
|
return false;
|
|
1632
|
-
} else if (
|
|
1633
|
-
Span<const uint8_t> buffer = GetRawBuffer(value);
|
|
1612
|
+
} else if (Span<uint8_t> buffer = {}; TryBuffer(env, value, &buffer)) {
|
|
1634
1613
|
call.PushBuffer(buffer, type, origin);
|
|
1635
1614
|
} else if (value.IsString()) {
|
|
1636
1615
|
if (!call.PushStringArray(value, type, origin))
|
|
@@ -1641,35 +1620,31 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1641
1620
|
}
|
|
1642
1621
|
} break;
|
|
1643
1622
|
case PrimitiveKind::Float32: {
|
|
1644
|
-
|
|
1623
|
+
float f;
|
|
1624
|
+
if (!TryNumber(env, value, &f)) [[unlikely]] {
|
|
1645
1625
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
1646
1626
|
return false;
|
|
1647
1627
|
}
|
|
1648
1628
|
|
|
1649
|
-
|
|
1650
|
-
*(float *)origin = f;
|
|
1629
|
+
memcpy(origin, &f, 4);
|
|
1651
1630
|
} break;
|
|
1652
1631
|
case PrimitiveKind::Float64: {
|
|
1653
|
-
|
|
1632
|
+
double d;
|
|
1633
|
+
if (!TryNumber(env, value, &d)) [[unlikely]] {
|
|
1654
1634
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
1655
1635
|
return false;
|
|
1656
1636
|
}
|
|
1657
1637
|
|
|
1658
|
-
|
|
1659
|
-
*(double *)origin = d;
|
|
1638
|
+
memcpy(origin, &d, 8);
|
|
1660
1639
|
} break;
|
|
1661
1640
|
case PrimitiveKind::Callback: {
|
|
1662
1641
|
void *ptr;
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
} else if (IsNullOrUndefined(value)) {
|
|
1670
|
-
ptr = nullptr;
|
|
1671
|
-
} else {
|
|
1672
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
1642
|
+
if (!TryPointer(env, value, &ptr)) [[unlikely]] {
|
|
1643
|
+
if (value.IsFunction()) {
|
|
1644
|
+
ThrowError<Napi::Error>(env, "Cannot encode non-registered callback");
|
|
1645
|
+
} else {
|
|
1646
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
1647
|
+
}
|
|
1673
1648
|
return false;
|
|
1674
1649
|
}
|
|
1675
1650
|
|
|
@@ -1683,15 +1658,53 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1683
1658
|
#undef PUSH_INTEGER
|
|
1684
1659
|
|
|
1685
1660
|
// Keep memory around if any was allocated
|
|
1686
|
-
if (
|
|
1687
|
-
|
|
1661
|
+
if (mem.allocator.IsUsed()) {
|
|
1662
|
+
LinkedAllocator *copy = instance->encode_map.FindValue(origin, nullptr);
|
|
1688
1663
|
|
|
1689
1664
|
if (!copy) {
|
|
1690
1665
|
copy = instance->encode_allocators.AppendDefault();
|
|
1691
1666
|
instance->encode_map.Set(origin, copy);
|
|
1692
1667
|
}
|
|
1693
1668
|
|
|
1694
|
-
std::swap(
|
|
1669
|
+
std::swap(mem.allocator, *copy);
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
return true;
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
static bool CanTypeAcceptCallbacks(const TypeInfo *type)
|
|
1676
|
+
{
|
|
1677
|
+
if (type->primitive == PrimitiveKind::Pointer)
|
|
1678
|
+
return true;
|
|
1679
|
+
if (type->primitive == PrimitiveKind::Callback)
|
|
1680
|
+
return true;
|
|
1681
|
+
|
|
1682
|
+
if (type->primitive == PrimitiveKind::Record ||
|
|
1683
|
+
type->primitive == PrimitiveKind::Union) {
|
|
1684
|
+
for (const RecordMember &member: type->members) {
|
|
1685
|
+
if (CanTypeAcceptCallbacks(member.type))
|
|
1686
|
+
return false;
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
return true;
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
static bool CanUseFastCall(const FunctionInfo *func)
|
|
1694
|
+
{
|
|
1695
|
+
if (func->parameters.len > 6)
|
|
1696
|
+
return false;
|
|
1697
|
+
|
|
1698
|
+
// Fast calls basically skip CallData::Finalize(), which handles output arguments
|
|
1699
|
+
// and temporary callback trampolines. If the function does not use any
|
|
1700
|
+
// output argument and cannot accept callbacks (so no pointer or callback arguments),
|
|
1701
|
+
// we can skip finalization!
|
|
1702
|
+
|
|
1703
|
+
for (const ParameterInfo ¶m: func->parameters) {
|
|
1704
|
+
if (param.directions & 2)
|
|
1705
|
+
return false;
|
|
1706
|
+
if (CanTypeAcceptCallbacks(param.type))
|
|
1707
|
+
return false;
|
|
1695
1708
|
}
|
|
1696
1709
|
|
|
1697
1710
|
return true;
|
|
@@ -1700,20 +1713,38 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
|
|
|
1700
1713
|
Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func)
|
|
1701
1714
|
{
|
|
1702
1715
|
Napi::Function wrapper;
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1716
|
+
|
|
1717
|
+
// Pick appropriate wrapper
|
|
1718
|
+
{
|
|
1719
|
+
napi_value value;
|
|
1720
|
+
|
|
1721
|
+
if (func->variadic) {
|
|
1722
|
+
napi_status status = napi_create_function(env, func->name, NAPI_AUTO_LENGTH, TranslateVariadicCall, (void *)func->Ref(), &value);
|
|
1723
|
+
K_ASSERT(status == napi_ok);
|
|
1724
|
+
} else if (!func->parameters.len) {
|
|
1725
|
+
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1726
|
+
napi_status status = napi_create_function(env, func->name, NAPI_AUTO_LENGTH, instance->translate_zero_call, (void *)func->Ref(), &value);
|
|
1727
|
+
K_ASSERT(status == napi_ok);
|
|
1728
|
+
} else if (CanUseFastCall(func)) {
|
|
1729
|
+
napi_status status = napi_create_function(env, func->name, NAPI_AUTO_LENGTH, TranslateFastCall, (void *)func->Ref(), &value);
|
|
1730
|
+
K_ASSERT(status == napi_ok);
|
|
1731
|
+
} else {
|
|
1732
|
+
napi_status status = napi_create_function(env, func->name, NAPI_AUTO_LENGTH, TranslateNormalCall, (void *)func->Ref(), &value);
|
|
1733
|
+
K_ASSERT(status == napi_ok);
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
wrapper = Napi::Function(env, value);
|
|
1737
|
+
wrapper.AddFinalizer([](Napi::Env, FunctionInfo *func) { func->Unref(); }, (FunctionInfo *)func);
|
|
1709
1738
|
}
|
|
1710
|
-
wrapper.AddFinalizer([](Napi::Env, FunctionInfo *func) { func->Unref(); }, (FunctionInfo *)func);
|
|
1711
1739
|
|
|
1712
1740
|
if (!func->variadic) {
|
|
1713
|
-
|
|
1714
|
-
|
|
1741
|
+
napi_value value;
|
|
1742
|
+
napi_status status = napi_create_function(env, func->name, NAPI_AUTO_LENGTH, TranslateAsyncCall, (void *)func->Ref(), &value);
|
|
1743
|
+
K_ASSERT(status == napi_ok);
|
|
1715
1744
|
|
|
1745
|
+
Napi::Function async = Napi::Function(env, value);
|
|
1716
1746
|
async.AddFinalizer([](Napi::Env, FunctionInfo *func) { func->Unref(); }, (FunctionInfo *)func);
|
|
1747
|
+
|
|
1717
1748
|
wrapper.Set("async", async);
|
|
1718
1749
|
}
|
|
1719
1750
|
|
|
@@ -1737,6 +1768,32 @@ Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func)
|
|
|
1737
1768
|
return wrapper;
|
|
1738
1769
|
}
|
|
1739
1770
|
|
|
1771
|
+
Napi::Value WrapPointer(Napi::Env env, const TypeInfo *ref, void *ptr)
|
|
1772
|
+
{
|
|
1773
|
+
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1774
|
+
|
|
1775
|
+
if (instance->config.fast_pointers) {
|
|
1776
|
+
Napi::BigInt big = Napi::BigInt::New(env, (uint64_t)(uintptr_t)ptr);
|
|
1777
|
+
return big;
|
|
1778
|
+
} else {
|
|
1779
|
+
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
1780
|
+
return external;
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
Napi::Value WrapCallback(Napi::Env env, const TypeInfo *ref, void *ptr)
|
|
1785
|
+
{
|
|
1786
|
+
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
1787
|
+
|
|
1788
|
+
if (instance->config.fast_callbacks) {
|
|
1789
|
+
Napi::BigInt big = Napi::BigInt::New(env, (uint64_t)(uintptr_t)ptr);
|
|
1790
|
+
return big;
|
|
1791
|
+
} else {
|
|
1792
|
+
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
1793
|
+
return external;
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1740
1797
|
bool DetectCallConvention(Span<const char> name, CallConvention *out_convention)
|
|
1741
1798
|
{
|
|
1742
1799
|
if (name == "__cdecl") {
|