koffi 2.2.6-beta.1 → 2.2.6-beta.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.
Files changed (38) hide show
  1. package/doc/callbacks.md +3 -1
  2. package/package.json +1 -1
  3. package/src/koffi/NUMERO SEQUENCE = PREFIXE ET SUFFIXE +0 -0
  4. package/src/koffi/build/2.2.6-beta.2/koffi_darwin_arm64.tar.gz +0 -0
  5. package/src/koffi/build/2.2.6-beta.2/koffi_darwin_x64.tar.gz +0 -0
  6. package/src/koffi/build/2.2.6-beta.2/koffi_freebsd_arm64.tar.gz +0 -0
  7. package/src/koffi/build/2.2.6-beta.2/koffi_freebsd_ia32.tar.gz +0 -0
  8. package/src/koffi/build/2.2.6-beta.2/koffi_freebsd_x64.tar.gz +0 -0
  9. package/src/koffi/build/2.2.6-beta.2/koffi_linux_arm32hf.tar.gz +0 -0
  10. package/src/koffi/build/2.2.6-beta.2/koffi_linux_arm64.tar.gz +0 -0
  11. package/src/koffi/build/2.2.6-beta.2/koffi_linux_ia32.tar.gz +0 -0
  12. package/src/koffi/build/2.2.6-beta.2/koffi_linux_riscv64hf64.tar.gz +0 -0
  13. package/src/koffi/build/2.2.6-beta.2/koffi_linux_x64.tar.gz +0 -0
  14. package/src/koffi/build/2.2.6-beta.2/koffi_openbsd_ia32.tar.gz +0 -0
  15. package/src/koffi/build/2.2.6-beta.2/koffi_openbsd_x64.tar.gz +0 -0
  16. package/src/koffi/build/2.2.6-beta.2/koffi_win32_arm64.tar.gz +0 -0
  17. package/src/koffi/build/2.2.6-beta.2/koffi_win32_ia32.tar.gz +0 -0
  18. package/src/koffi/build/2.2.6-beta.2/koffi_win32_x64.tar.gz +0 -0
  19. package/src/koffi/src/call.cc +24 -28
  20. package/src/koffi/src/call.hh +1 -1
  21. package/src/koffi/src/ffi.cc +4 -5
  22. package/src/koffi/src/util.cc +14 -15
  23. package/src/koffi/src/util.hh +23 -1
  24. package/src/koffi/build/2.2.6-beta.1/koffi_darwin_arm64.tar.gz +0 -0
  25. package/src/koffi/build/2.2.6-beta.1/koffi_darwin_x64.tar.gz +0 -0
  26. package/src/koffi/build/2.2.6-beta.1/koffi_freebsd_arm64.tar.gz +0 -0
  27. package/src/koffi/build/2.2.6-beta.1/koffi_freebsd_ia32.tar.gz +0 -0
  28. package/src/koffi/build/2.2.6-beta.1/koffi_freebsd_x64.tar.gz +0 -0
  29. package/src/koffi/build/2.2.6-beta.1/koffi_linux_arm32hf.tar.gz +0 -0
  30. package/src/koffi/build/2.2.6-beta.1/koffi_linux_arm64.tar.gz +0 -0
  31. package/src/koffi/build/2.2.6-beta.1/koffi_linux_ia32.tar.gz +0 -0
  32. package/src/koffi/build/2.2.6-beta.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  33. package/src/koffi/build/2.2.6-beta.1/koffi_linux_x64.tar.gz +0 -0
  34. package/src/koffi/build/2.2.6-beta.1/koffi_openbsd_ia32.tar.gz +0 -0
  35. package/src/koffi/build/2.2.6-beta.1/koffi_openbsd_x64.tar.gz +0 -0
  36. package/src/koffi/build/2.2.6-beta.1/koffi_win32_arm64.tar.gz +0 -0
  37. package/src/koffi/build/2.2.6-beta.1/koffi_win32_ia32.tar.gz +0 -0
  38. 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
- ## Callback types
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "2.2.6-beta.1",
3
+ "version": "2.2.6-beta.2",
4
4
  "stable": "2.2.5",
5
5
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
6
6
  "keywords": [
File without changes
@@ -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 (value.IsTypedArray() || value.IsArrayBuffer()) {
515
- if (!PushArrayBuffer(value, member.type->size, member.type, dest, realign))
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 (value.IsTypedArray() || value.IsArrayBuffer()) {
752
- if (!PushArrayBuffer(value, ref->size, ref, dest, realign))
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::PushArrayBuffer(Napi::Value value, Size size, const TypeInfo *type, uint8_t *origin, int16_t realign)
822
+ bool CallData::PushBuffer(Span<const uint8_t> buffer, Size size, const TypeInfo *type, uint8_t *origin, int16_t realign)
819
823
  {
820
- RG_ASSERT(value.IsTypedArray() || value.IsArrayBuffer());
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 < size; i += step) {
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.ByteLength());
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
- memset(ptr, 0, size);
923
+ memset_safe(ptr, 0, size);
926
924
  }
927
- } else if (value.IsTypedArray() || value.IsArrayBuffer()) {
928
- Napi::ArrayBuffer buffer = value.IsTypedArray() ? value.As<Napi::TypedArray>().ArrayBuffer()
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(size, 16);
928
+ ptr = AllocHeap(buffer.len, 16);
934
929
 
935
930
  if (directions & 1) {
936
- if (!PushArrayBuffer(buffer, size, type, ptr))
931
+ if (!PushBuffer(buffer, buffer.len, type, ptr))
937
932
  return false;
938
933
  } else {
939
- memset(ptr, 0, size);
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
- memset(ptr, 0, type->size);
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 (value.IsTypedArray() || value.IsArrayBuffer()) {
999
- DecodeArrayBuffer(value, out.ptr, out.type);
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);
@@ -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 PushArrayBuffer(Napi::Value value, Size size, const TypeInfo *type, uint8_t *origin, int16_t realign = 0);
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
 
@@ -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 (value.IsTypedArray() || value.IsArrayBuffer()) {
1858
- Napi::ArrayBuffer buffer = value.IsTypedArray() ? value.As<Napi::TypedArray>().ArrayBuffer()
1859
- : value.As<Napi::ArrayBuffer>();
1857
+ } else if (IsRawBuffer(value)) {
1858
+ Span<uint8_t> buffer = GetRawBuffer(value);
1860
1859
 
1861
- if (RG_UNLIKELY((Size)buffer.ByteLength() - offset < type->size)) {
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.Data();
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();
@@ -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
- DecodeArrayBuffer(array, origin, type->ref.type, realign); \
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
- DecodeArrayBuffer(array, origin, type->ref.type, realign); \
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 DecodeArrayBuffer(Napi::Value value, const uint8_t *origin, const TypeInfo *ref, int16_t realign)
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 < size; i += step) {
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)size);
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 = size / RG_SIZE(CType); \
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]); \
@@ -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)buffer.ByteLength() - offset);
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 DecodeArrayBuffer(Napi::Value value, const uint8_t *origin, const TypeInfo *ref, int16_t realign = 0);
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
  {