koffi 2.2.6-beta.1 → 2.2.6-beta.3
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/doc/callbacks.md +3 -1
- package/package.json +1 -1
- package/src/koffi/NUMERO SEQUENCE = PREFIXE ET SUFFIXE +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_darwin_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_darwin_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_freebsd_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_freebsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_freebsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_linux_arm32hf.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_linux_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_linux_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_linux_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_openbsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_openbsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_win32_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_win32_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.3/koffi_win32_x64.tar.gz +0 -0
- package/src/koffi/src/call.cc +24 -28
- package/src/koffi/src/call.hh +1 -1
- package/src/koffi/src/ffi.cc +4 -5
- package/src/koffi/src/util.cc +14 -15
- package/src/koffi/src/util.hh +23 -1
- package/src/koffi/build/2.2.6-beta.1/koffi_darwin_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_darwin_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_freebsd_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_freebsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_freebsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_linux_arm32hf.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_linux_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_linux_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_linux_riscv64hf64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_linux_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_openbsd_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_openbsd_x64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_win32_arm64.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_win32_ia32.tar.gz +0 -0
- package/src/koffi/build/2.2.6-beta.1/koffi_win32_x64.tar.gz +0 -0
package/doc/callbacks.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Callbacks
|
|
2
2
|
|
|
3
|
+
## Callback types
|
|
4
|
+
|
|
3
5
|
In order to pass a JS function to a C function expecting a callback, you must first create a callback type with the expected return type and parameters. The syntax is similar to the one used to load functions from a shared library.
|
|
4
6
|
|
|
5
7
|
```js
|
|
@@ -24,7 +26,7 @@ Now, you must use them through a pointer: `void CallIt(CallbackType func)` in Ko
|
|
|
24
26
|
Consult the [migration guide](migration.md) for more information.
|
|
25
27
|
```
|
|
26
28
|
|
|
27
|
-
##
|
|
29
|
+
## Transient and registered callbacks
|
|
28
30
|
|
|
29
31
|
Koffi only uses predefined static trampolines, and does not need to generate code at runtime, which makes it compatible with platforms with hardened W^X migitations (such as PaX mprotect). However, this imposes some restrictions on the maximum number of callbacks, and their duration.
|
|
30
32
|
|
package/package.json
CHANGED
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/src/koffi/src/call.cc
CHANGED
|
@@ -511,8 +511,10 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
|
|
|
511
511
|
|
|
512
512
|
if (!PushNormalArray(array, len, member.type, dest, realign))
|
|
513
513
|
return false;
|
|
514
|
-
} else if (
|
|
515
|
-
|
|
514
|
+
} else if (IsRawBuffer(value)) {
|
|
515
|
+
Span<const uint8_t> buffer = GetRawBuffer(value);
|
|
516
|
+
|
|
517
|
+
if (!PushBuffer(buffer, member.type->size, member.type, dest, realign))
|
|
516
518
|
return false;
|
|
517
519
|
} else if (value.IsString() && !realign) {
|
|
518
520
|
if (!PushStringArray(value, member.type, dest))
|
|
@@ -748,8 +750,10 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type
|
|
|
748
750
|
|
|
749
751
|
if (!PushNormalArray(array2, len2, ref, dest, realign))
|
|
750
752
|
return false;
|
|
751
|
-
} else if (
|
|
752
|
-
|
|
753
|
+
} else if (IsRawBuffer(value)) {
|
|
754
|
+
Span<const uint8_t> buffer = GetRawBuffer(value);
|
|
755
|
+
|
|
756
|
+
if (!PushBuffer(buffer, ref->size, ref, dest, realign))
|
|
753
757
|
return false;
|
|
754
758
|
} else if (value.IsString() && !realign) {
|
|
755
759
|
if (!PushStringArray(value, ref, dest))
|
|
@@ -815,16 +819,10 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type
|
|
|
815
819
|
return true;
|
|
816
820
|
}
|
|
817
821
|
|
|
818
|
-
bool CallData::
|
|
822
|
+
bool CallData::PushBuffer(Span<const uint8_t> buffer, Size size, const TypeInfo *type, uint8_t *origin, int16_t realign)
|
|
819
823
|
{
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
Napi::ArrayBuffer buffer = value.IsTypedArray() ? value.As<Napi::TypedArray>().ArrayBuffer()
|
|
823
|
-
: value.As<Napi::ArrayBuffer>();
|
|
824
|
-
const uint8_t *ptr = (const uint8_t *)buffer.Data();
|
|
825
|
-
|
|
826
|
-
if (RG_UNLIKELY(buffer.ByteLength() != (size_t)size)) {
|
|
827
|
-
ThrowError<Napi::Error>(env, "Expected array or buffer of size %1, got %2", size, buffer.ByteLength());
|
|
824
|
+
if (RG_UNLIKELY(buffer.len != size)) {
|
|
825
|
+
ThrowError<Napi::Error>(env, "Expected array or buffer of size %1, got %2", size, buffer.len);
|
|
828
826
|
return false;
|
|
829
827
|
}
|
|
830
828
|
|
|
@@ -832,17 +830,17 @@ bool CallData::PushArrayBuffer(Napi::Value value, Size size, const TypeInfo *typ
|
|
|
832
830
|
Size offset = 0;
|
|
833
831
|
Size step = type->ref.type->size;
|
|
834
832
|
|
|
835
|
-
for (Size i = 0; i <
|
|
833
|
+
for (Size i = 0; i < buffer.len; i += step) {
|
|
836
834
|
offset = AlignLen(offset, realign);
|
|
837
835
|
|
|
838
836
|
uint8_t *dest = origin + offset;
|
|
839
|
-
const uint8_t *src = ptr + i;
|
|
837
|
+
const uint8_t *src = buffer.ptr + i;
|
|
840
838
|
|
|
841
839
|
memcpy(dest, src, step);
|
|
842
840
|
offset += step;
|
|
843
841
|
}
|
|
844
842
|
} else {
|
|
845
|
-
memcpy_safe(origin, ptr, (size_t)buffer.
|
|
843
|
+
memcpy_safe(origin, buffer.ptr, (size_t)buffer.len);
|
|
846
844
|
}
|
|
847
845
|
|
|
848
846
|
return true;
|
|
@@ -922,21 +920,18 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
922
920
|
if (!PushNormalArray(array, len, type, ptr))
|
|
923
921
|
return false;
|
|
924
922
|
} else {
|
|
925
|
-
|
|
923
|
+
memset_safe(ptr, 0, size);
|
|
926
924
|
}
|
|
927
|
-
} else if (
|
|
928
|
-
|
|
929
|
-
: value.As<Napi::ArrayBuffer>();
|
|
930
|
-
|
|
931
|
-
Size size = (Size)buffer.ByteLength();
|
|
925
|
+
} else if (IsRawBuffer(value)) {
|
|
926
|
+
Span<const uint8_t> buffer = GetRawBuffer(value);
|
|
932
927
|
|
|
933
|
-
ptr = AllocHeap(
|
|
928
|
+
ptr = AllocHeap(buffer.len, 16);
|
|
934
929
|
|
|
935
930
|
if (directions & 1) {
|
|
936
|
-
if (!
|
|
931
|
+
if (!PushBuffer(buffer, buffer.len, type, ptr))
|
|
937
932
|
return false;
|
|
938
933
|
} else {
|
|
939
|
-
|
|
934
|
+
memset_safe(ptr, 0, (size_t)buffer.len);
|
|
940
935
|
}
|
|
941
936
|
} else if (RG_LIKELY(type->ref.type->primitive == PrimitiveKind::Record)) {
|
|
942
937
|
Napi::Object obj = value.As<Napi::Object>();
|
|
@@ -948,7 +943,7 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
|
|
|
948
943
|
if (!PushObject(obj, type->ref.type, ptr))
|
|
949
944
|
return false;
|
|
950
945
|
} else {
|
|
951
|
-
|
|
946
|
+
memset_safe(ptr, 0, type->size);
|
|
952
947
|
}
|
|
953
948
|
} else {
|
|
954
949
|
goto unexpected;
|
|
@@ -995,8 +990,9 @@ void CallData::PopOutArguments()
|
|
|
995
990
|
if (value.IsArray()) {
|
|
996
991
|
Napi::Array array(env, value);
|
|
997
992
|
DecodeNormalArray(array, out.ptr, out.type);
|
|
998
|
-
} else if (
|
|
999
|
-
|
|
993
|
+
} else if (IsRawBuffer(value)) {
|
|
994
|
+
Span<uint8_t> buffer = GetRawBuffer(value);
|
|
995
|
+
DecodeBuffer(buffer, out.ptr, out.type);
|
|
1000
996
|
} else {
|
|
1001
997
|
Napi::Object obj(env, value);
|
|
1002
998
|
DecodeObject(obj, out.ptr, out.type);
|
package/src/koffi/src/call.hh
CHANGED
|
@@ -103,7 +103,7 @@ private:
|
|
|
103
103
|
Size PushString16Value(Napi::Value value, const char16_t **out_str16);
|
|
104
104
|
bool PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origin, int16_t realign = 0);
|
|
105
105
|
bool PushNormalArray(Napi::Array array, Size len, const TypeInfo *type, uint8_t *origin, int16_t realign = 0);
|
|
106
|
-
bool
|
|
106
|
+
bool PushBuffer(Span<const uint8_t> buffer, Size size, const TypeInfo *type, uint8_t *origin, int16_t realign = 0);
|
|
107
107
|
bool PushStringArray(Napi::Value value, const TypeInfo *type, uint8_t *origin);
|
|
108
108
|
bool PushPointer(Napi::Value value, const TypeInfo *type, int directions, void **out_ptr);
|
|
109
109
|
|
package/src/koffi/src/ffi.cc
CHANGED
|
@@ -1854,17 +1854,16 @@ static Napi::Value DecodeValue(const Napi::CallbackInfo &info)
|
|
|
1854
1854
|
if (value.IsExternal()) {
|
|
1855
1855
|
Napi::External<void> external = value.As<Napi::External<void>>();
|
|
1856
1856
|
ptr = (const uint8_t *)external.Data();
|
|
1857
|
-
} else if (
|
|
1858
|
-
|
|
1859
|
-
: value.As<Napi::ArrayBuffer>();
|
|
1857
|
+
} else if (IsRawBuffer(value)) {
|
|
1858
|
+
Span<uint8_t> buffer = GetRawBuffer(value);
|
|
1860
1859
|
|
|
1861
|
-
if (RG_UNLIKELY(
|
|
1860
|
+
if (RG_UNLIKELY(buffer.len - offset < type->size)) {
|
|
1862
1861
|
ThrowError<Napi::Error>(env, "Expected buffer with size superior or equal to type %1 (%2 bytes)",
|
|
1863
1862
|
type->name, type->size + offset);
|
|
1864
1863
|
return env.Null();
|
|
1865
1864
|
}
|
|
1866
1865
|
|
|
1867
|
-
ptr = (const uint8_t *)buffer.
|
|
1866
|
+
ptr = (const uint8_t *)buffer.ptr;
|
|
1868
1867
|
} else {
|
|
1869
1868
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for variable, expected external or TypedArray", GetValueType(instance, info[0]));
|
|
1870
1869
|
return env.Null();
|
package/src/koffi/src/util.cc
CHANGED
|
@@ -251,6 +251,8 @@ const char *GetValueType(const InstanceData *instance, Napi::Value value)
|
|
|
251
251
|
}
|
|
252
252
|
} else if (value.IsArrayBuffer()) {
|
|
253
253
|
return "ArrayBuffer";
|
|
254
|
+
} else if (value.IsBuffer()) {
|
|
255
|
+
return "Buffer";
|
|
254
256
|
}
|
|
255
257
|
|
|
256
258
|
switch (value.Type()) {
|
|
@@ -503,7 +505,9 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
503
505
|
}); \
|
|
504
506
|
} else { \
|
|
505
507
|
Napi::TypedArrayType array = Napi::TypedArrayType::New(env, len); \
|
|
506
|
-
|
|
508
|
+
Span<uint8_t> buffer = MakeSpan((uint8_t *)array.ArrayBuffer().Data(), (Size)len * RG_SIZE(CType)); \
|
|
509
|
+
\
|
|
510
|
+
DecodeBuffer(buffer, origin, type->ref.type, realign); \
|
|
507
511
|
\
|
|
508
512
|
return array; \
|
|
509
513
|
} \
|
|
@@ -518,7 +522,9 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
|
|
|
518
522
|
}); \
|
|
519
523
|
} else { \
|
|
520
524
|
Napi::TypedArrayType array = Napi::TypedArrayType::New(env, len); \
|
|
521
|
-
|
|
525
|
+
Span<uint8_t> buffer = MakeSpan((uint8_t *)array.ArrayBuffer().Data(), (Size)len * RG_SIZE(CType)); \
|
|
526
|
+
\
|
|
527
|
+
DecodeBuffer(buffer, origin, type->ref.type, realign); \
|
|
522
528
|
\
|
|
523
529
|
return array; \
|
|
524
530
|
} \
|
|
@@ -787,36 +793,29 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
|
|
|
787
793
|
#undef POP_ARRAY
|
|
788
794
|
}
|
|
789
795
|
|
|
790
|
-
void
|
|
796
|
+
void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *ref, int16_t realign)
|
|
791
797
|
{
|
|
792
|
-
RG_ASSERT(value.IsTypedArray() || value.IsArrayBuffer());
|
|
793
|
-
|
|
794
|
-
Napi::ArrayBuffer buffer = value.IsTypedArray() ? value.As<Napi::TypedArray>().ArrayBuffer()
|
|
795
|
-
: value.As<Napi::ArrayBuffer>();
|
|
796
|
-
uint8_t *ptr = (uint8_t *)buffer.Data();
|
|
797
|
-
Size size = (Size)buffer.ByteLength();
|
|
798
|
-
|
|
799
798
|
if (realign) {
|
|
800
799
|
Size offset = 0;
|
|
801
800
|
Size step = ref->size;
|
|
802
801
|
|
|
803
|
-
for (Size i = 0; i <
|
|
802
|
+
for (Size i = 0; i < buffer.len; i += step) {
|
|
804
803
|
offset = AlignLen(offset, realign);
|
|
805
804
|
|
|
806
|
-
uint8_t *dest = ptr + i;
|
|
805
|
+
uint8_t *dest = buffer.ptr + i;
|
|
807
806
|
const uint8_t *src = origin + offset;
|
|
808
807
|
|
|
809
808
|
memcpy(dest, src, step);
|
|
810
809
|
offset += step;
|
|
811
810
|
}
|
|
812
811
|
} else {
|
|
813
|
-
memcpy_safe(ptr, origin, (size_t)
|
|
812
|
+
memcpy_safe(buffer.ptr, origin, (size_t)buffer.len);
|
|
814
813
|
}
|
|
815
814
|
|
|
816
815
|
#define SWAP(CType) \
|
|
817
816
|
do { \
|
|
818
|
-
CType *data = (CType *)ptr; \
|
|
819
|
-
Size len =
|
|
817
|
+
CType *data = (CType *)buffer.ptr; \
|
|
818
|
+
Size len = buffer.len / RG_SIZE(CType); \
|
|
820
819
|
\
|
|
821
820
|
for (Size i = 0; i < len; i++) { \
|
|
822
821
|
data[i] = ReverseBytes(data[i]); \
|
package/src/koffi/src/util.hh
CHANGED
|
@@ -77,6 +77,28 @@ static inline bool IsObject(Napi::Value value)
|
|
|
77
77
|
return value.IsObject() && !IsNullOrUndefined(value) && !value.IsArray();
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
static inline bool IsRawBuffer(Napi::Value value)
|
|
81
|
+
{
|
|
82
|
+
return value.IsTypedArray() || value.IsArrayBuffer();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static inline Span<uint8_t> GetRawBuffer(Napi::Value value)
|
|
86
|
+
{
|
|
87
|
+
if (value.IsTypedArray()) {
|
|
88
|
+
Napi::TypedArray array = value.As<Napi::TypedArray>();
|
|
89
|
+
Napi::ArrayBuffer buffer = array.ArrayBuffer();
|
|
90
|
+
Size offset = array.ByteOffset();
|
|
91
|
+
|
|
92
|
+
return MakeSpan((uint8_t *)buffer.Data() + offset, (Size)array.ByteLength());
|
|
93
|
+
} else if (value.IsArrayBuffer()) {
|
|
94
|
+
Napi::ArrayBuffer buffer = value.As<Napi::ArrayBuffer>();
|
|
95
|
+
|
|
96
|
+
return MakeSpan((uint8_t *)buffer.Data(), (Size)buffer.ByteLength());
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
RG_UNREACHABLE();
|
|
100
|
+
}
|
|
101
|
+
|
|
80
102
|
int GetTypedArrayType(const TypeInfo *type);
|
|
81
103
|
|
|
82
104
|
template <typename T>
|
|
@@ -100,7 +122,7 @@ Napi::Object DecodeObject(Napi::Env env, const uint8_t *origin, const TypeInfo *
|
|
|
100
122
|
void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type, int16_t realign = 0);
|
|
101
123
|
Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *type, int16_t realign = 0);
|
|
102
124
|
void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo *ref, int16_t realign = 0);
|
|
103
|
-
void
|
|
125
|
+
void DecodeBuffer(Span<uint8_t> buffer, const uint8_t *origin, const TypeInfo *ref, int16_t realign = 0);
|
|
104
126
|
|
|
105
127
|
static inline Napi::Value NewBigInt(Napi::Env env, int64_t value)
|
|
106
128
|
{
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|