koffi 2.15.0 → 2.16.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/build/koffi/darwin_arm64/koffi.node +0 -0
  3. package/build/koffi/darwin_x64/koffi.node +0 -0
  4. package/build/koffi/freebsd_arm64/koffi.node +0 -0
  5. package/build/koffi/freebsd_ia32/koffi.node +0 -0
  6. package/build/koffi/freebsd_x64/koffi.node +0 -0
  7. package/build/koffi/linux_arm64/koffi.node +0 -0
  8. package/build/koffi/linux_armhf/koffi.node +0 -0
  9. package/build/koffi/linux_ia32/koffi.node +0 -0
  10. package/build/koffi/linux_loong64/koffi.node +0 -0
  11. package/build/koffi/linux_riscv64d/koffi.node +0 -0
  12. package/build/koffi/linux_x64/koffi.node +0 -0
  13. package/build/koffi/musl_arm64/koffi.node +0 -0
  14. package/build/koffi/musl_x64/koffi.node +0 -0
  15. package/build/koffi/openbsd_ia32/koffi.node +0 -0
  16. package/build/koffi/openbsd_x64/koffi.node +0 -0
  17. package/build/koffi/win32_arm64/koffi.node +0 -0
  18. package/build/koffi/win32_ia32/koffi.node +0 -0
  19. package/build/koffi/win32_x64/koffi.node +0 -0
  20. package/doc/pages/index.md +4 -2
  21. package/doc/pages/misc.md +2 -0
  22. package/doc/templates/code.html +1 -2
  23. package/doc/templates/page.html +1 -2
  24. package/index.d.ts +11 -9
  25. package/index.js +9 -9
  26. package/indirect.js +9 -9
  27. package/lib/native/base/base.cc +79 -44
  28. package/lib/native/base/base.hh +31 -33
  29. package/package.json +2 -2
  30. package/src/cnoke/assets/FindCNoke.cmake +16 -10
  31. package/src/cnoke/assets/win_delay_hook.c +4 -0
  32. package/src/cnoke/src/builder.js +49 -46
  33. package/src/koffi/CMakeLists.txt +18 -8
  34. package/src/koffi/src/abi_arm32.cc +222 -219
  35. package/src/koffi/src/abi_arm32_asm.S +1 -29
  36. package/src/koffi/src/abi_arm64.cc +257 -235
  37. package/src/koffi/src/abi_arm64_asm.S +1 -32
  38. package/src/koffi/src/abi_arm64_asm.asm +1 -23
  39. package/src/koffi/src/abi_loong64_asm.S +1 -25
  40. package/src/koffi/src/abi_riscv64.cc +220 -217
  41. package/src/koffi/src/abi_riscv64_asm.S +1 -25
  42. package/src/koffi/src/abi_x64_sysv.cc +196 -192
  43. package/src/koffi/src/abi_x64_sysv_asm.S +1 -31
  44. package/src/koffi/src/abi_x64_win.cc +188 -172
  45. package/src/koffi/src/abi_x64_win_asm.S +144 -0
  46. package/src/koffi/src/abi_x64_win_asm.asm +1 -21
  47. package/src/koffi/src/abi_x86.cc +224 -189
  48. package/src/koffi/src/abi_x86_asm.S +6 -25
  49. package/src/koffi/src/abi_x86_asm.asm +9 -22
  50. package/src/koffi/src/call.cc +246 -428
  51. package/src/koffi/src/call.hh +9 -8
  52. package/src/koffi/src/ffi.cc +142 -88
  53. package/src/koffi/src/ffi.hh +13 -59
  54. package/src/koffi/src/primitives.inc +39 -0
  55. package/src/koffi/src/trampolines/armasm.inc +0 -32770
  56. package/src/koffi/src/trampolines/gnu.inc +0 -24578
  57. package/src/koffi/src/trampolines/masm32.inc +0 -32770
  58. package/src/koffi/src/trampolines/masm64.inc +0 -32770
  59. package/src/koffi/src/trampolines/prototypes.inc +16385 -16385
  60. package/src/koffi/src/util.cc +155 -112
  61. package/src/koffi/src/util.hh +77 -40
  62. package/vendor/node-api-headers/CHANGELOG.md +22 -0
  63. package/vendor/node-api-headers/README.md +6 -17
  64. package/vendor/node-api-headers/include/js_native_api.h +3 -13
  65. package/vendor/node-api-headers/include/js_native_api_types.h +15 -0
  66. package/vendor/node-api-headers/include/node_api.h +0 -4
  67. package/vendor/node-api-headers/include/node_api_types.h +6 -0
  68. package/vendor/node-api-headers/package.json +1 -1
  69. package/vendor/node-api-headers/scripts/update-headers.js +6 -0
@@ -43,7 +43,7 @@ MagicUnion::MagicUnion(const Napi::CallbackInfo &info)
43
43
  Napi::Env env = info.Env();
44
44
  InstanceData *instance = env.GetInstanceData<InstanceData>();
45
45
 
46
- active_symbol = instance->active_symbol;
46
+ active_symbol.Reset(instance->active_symbol.Value(), 1);
47
47
  }
48
48
 
49
49
  void MagicUnion::SetRaw(const uint8_t *ptr)
@@ -51,7 +51,7 @@ void MagicUnion::SetRaw(const uint8_t *ptr)
51
51
  raw.RemoveFrom(0);
52
52
  raw.Append(MakeSpan(ptr, type->size));
53
53
 
54
- Value().Set(active_symbol, Env().Undefined());
54
+ Value().Set(active_symbol.Value(), Env().Undefined());
55
55
  active_idx = -1;
56
56
  }
57
57
 
@@ -63,7 +63,7 @@ Napi::Value MagicUnion::Getter(const Napi::CallbackInfo &info)
63
63
  Napi::Value value;
64
64
 
65
65
  if (idx == active_idx) {
66
- value = Value().Get(active_symbol);
66
+ value = Value().Get(active_symbol.Value());
67
67
  } else {
68
68
  Napi::Env env = info.Env();
69
69
 
@@ -74,7 +74,7 @@ Napi::Value MagicUnion::Getter(const Napi::CallbackInfo &info)
74
74
 
75
75
  value = Decode(env, raw.ptr, member.type);
76
76
 
77
- Value().Set(active_symbol, value);
77
+ Value().Set(active_symbol.Value(), value);
78
78
  active_idx = idx;
79
79
  }
80
80
 
@@ -86,7 +86,7 @@ void MagicUnion::Setter(const Napi::CallbackInfo &info, const Napi::Value &value
86
86
  {
87
87
  Size idx = (Size)info.Data();
88
88
 
89
- Value().Set(active_symbol, value);
89
+ Value().Set(active_symbol.Value(), value);
90
90
  active_idx = idx;
91
91
 
92
92
  raw.Clear();
@@ -532,7 +532,7 @@ const char *GetValueType(const InstanceData *instance, Napi::Value value)
532
532
  if (CheckValueTag(value, &TypeInfoMarker))
533
533
  return "Type";
534
534
  for (const TypeInfo &type: instance->types) {
535
- if (type.ref.marker && CheckValueTag(value, type.ref.marker))
535
+ if (type.ref.type && CheckValueTag(value, type.ref.type))
536
536
  return type.name;
537
537
  }
538
538
 
@@ -549,6 +549,7 @@ const char *GetValueType(const InstanceData *instance, Napi::Value value)
549
549
  case napi_uint16_array: return "Uint16Array";
550
550
  case napi_int32_array: return "Int32Array";
551
551
  case napi_uint32_array: return "Uint32Array";
552
+ case napi_float16_array: return "Float16Array";
552
553
  case napi_float32_array: return "Float32Array";
553
554
  case napi_float64_array: return "Float64Array";
554
555
  case napi_bigint64_array: return "BigInt64Array";
@@ -856,8 +857,7 @@ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type)
856
857
  const char32_t *str32 = *(const char32_t **)src;
857
858
  obj.Set(member.name, str32 ? MakeStringFromUTF32(env, str32) : env.Null());
858
859
  } break;
859
- case PrimitiveKind::Pointer:
860
- case PrimitiveKind::Callback: {
860
+ case PrimitiveKind::Pointer: {
861
861
  void *ptr2 = *(void **)src;
862
862
 
863
863
  if (member.countedby >= 0) {
@@ -866,19 +866,25 @@ void DecodeObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type)
866
866
 
867
867
  Napi::Value value = DecodeArray(env, (const uint8_t *)ptr2, member.type, len);
868
868
  obj.Set(member.name, value);
869
- } else if (ptr2) {
870
- Napi::External<void> external = Napi::External<void>::New(env, ptr2);
871
- SetValueTag(external, member.type->ref.marker);
872
-
873
- obj.Set(member.name, external);
874
869
  } else {
875
- obj.Set(member.name, env.Null());
870
+ Napi::Value p = ptr2 ? WrapPointer(env, member.type->ref.type, ptr2) : env.Null();
871
+ obj.Set(member.name, p);
876
872
  }
877
873
 
878
874
  if (member.type->dispose) {
879
875
  member.type->dispose(env, member.type, ptr2);
880
876
  }
881
877
  } break;
878
+ case PrimitiveKind::Callback: {
879
+ void *ptr2 = *(void **)src;
880
+
881
+ Napi::Value p = ptr2 ? WrapCallback(env, member.type->ref.type, ptr2) : env.Null();
882
+ obj.Set(member.name, p);
883
+
884
+ if (member.type->dispose) {
885
+ member.type->dispose(env, member.type, ptr2);
886
+ }
887
+ } break;
882
888
  case PrimitiveKind::Record:
883
889
  case PrimitiveKind::Union: {
884
890
  Napi::Object obj2 = DecodeObject(env, src, member.type);
@@ -935,7 +941,8 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
935
941
  \
936
942
  return array; \
937
943
  } while (false)
938
- #define POP_NUMBER_ARRAY(TypedArrayType, CType) \
944
+
945
+ #define POP_NUMBERS(TypedArrayType, CType) \
939
946
  do { \
940
947
  if (type->hint == ArrayHint::Array) { \
941
948
  POP_ARRAY({ \
@@ -951,7 +958,7 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
951
958
  return array; \
952
959
  } \
953
960
  } while (false)
954
- #define POP_NUMBER_ARRAY_SWAP(TypedArrayType, CType) \
961
+ #define POP_NUMBERS_SWAP(TypedArrayType, CType) \
955
962
  do { \
956
963
  if (type->hint == ArrayHint::Array) { \
957
964
  POP_ARRAY({ \
@@ -987,9 +994,9 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
987
994
  return str;
988
995
  }
989
996
 
990
- POP_NUMBER_ARRAY(Int8Array, int8_t);
997
+ POP_NUMBERS(Int8Array, int8_t);
991
998
  } break;
992
- case PrimitiveKind::UInt8: { POP_NUMBER_ARRAY(Uint8Array, uint8_t); } break;
999
+ case PrimitiveKind::UInt8: { POP_NUMBERS(Uint8Array, uint8_t); } break;
993
1000
  case PrimitiveKind::Int16: {
994
1001
  if (type->hint == ArrayHint::String) {
995
1002
  const char16_t *ptr = (const char16_t *)origin;
@@ -999,11 +1006,11 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
999
1006
  return str;
1000
1007
  }
1001
1008
 
1002
- POP_NUMBER_ARRAY(Int16Array, int16_t);
1009
+ POP_NUMBERS(Int16Array, int16_t);
1003
1010
  } break;
1004
- case PrimitiveKind::Int16S: { POP_NUMBER_ARRAY_SWAP(Int16Array, int16_t); } break;
1005
- case PrimitiveKind::UInt16: { POP_NUMBER_ARRAY(Uint16Array, uint16_t); } break;
1006
- case PrimitiveKind::UInt16S: { POP_NUMBER_ARRAY_SWAP(Uint16Array, uint16_t); } break;
1011
+ case PrimitiveKind::Int16S: { POP_NUMBERS_SWAP(Int16Array, int16_t); } break;
1012
+ case PrimitiveKind::UInt16: { POP_NUMBERS(Uint16Array, uint16_t); } break;
1013
+ case PrimitiveKind::UInt16S: { POP_NUMBERS_SWAP(Uint16Array, uint16_t); } break;
1007
1014
  case PrimitiveKind::Int32: {
1008
1015
  if (type->hint == ArrayHint::String) {
1009
1016
  const char32_t *ptr = (const char32_t *)origin;
@@ -1013,11 +1020,11 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
1013
1020
  return str;
1014
1021
  }
1015
1022
 
1016
- POP_NUMBER_ARRAY(Int32Array, int32_t);
1023
+ POP_NUMBERS(Int32Array, int32_t);
1017
1024
  } break;
1018
- case PrimitiveKind::Int32S: { POP_NUMBER_ARRAY_SWAP(Int32Array, int32_t); } break;
1019
- case PrimitiveKind::UInt32: { POP_NUMBER_ARRAY(Uint32Array, uint32_t); } break;
1020
- case PrimitiveKind::UInt32S: { POP_NUMBER_ARRAY_SWAP(Uint32Array, uint32_t); } break;
1025
+ case PrimitiveKind::Int32S: { POP_NUMBERS_SWAP(Int32Array, int32_t); } break;
1026
+ case PrimitiveKind::UInt32: { POP_NUMBERS(Uint32Array, uint32_t); } break;
1027
+ case PrimitiveKind::UInt32S: { POP_NUMBERS_SWAP(Uint32Array, uint32_t); } break;
1021
1028
  case PrimitiveKind::Int64: {
1022
1029
  POP_ARRAY({
1023
1030
  int64_t v = *(int64_t *)src;
@@ -1060,19 +1067,20 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
1060
1067
  array.Set(i, str32 ? MakeStringFromUTF32(env, str32) : env.Null());
1061
1068
  });
1062
1069
  } break;
1063
- case PrimitiveKind::Pointer:
1064
- case PrimitiveKind::Callback: {
1070
+ case PrimitiveKind::Pointer: {
1065
1071
  POP_ARRAY({
1066
1072
  void *ptr2 = *(void **)src;
1067
1073
 
1068
- if (ptr2) {
1069
- Napi::External<void> external = Napi::External<void>::New(env, ptr2);
1070
- SetValueTag(external, type->ref.type->ref.marker);
1074
+ Napi::Value p = ptr2 ? WrapPointer(env, type->ref.type->ref.type, ptr2) : env.Null();
1075
+ array.Set(i, p);
1076
+ });
1077
+ } break;
1078
+ case PrimitiveKind::Callback: {
1079
+ POP_ARRAY({
1080
+ void *ptr2 = *(void **)src;
1071
1081
 
1072
- array.Set(i, external);
1073
- } else {
1074
- array.Set(i, env.Null());
1075
- }
1082
+ Napi::Value p = ptr2 ? WrapCallback(env, type->ref.type->ref.type, ptr2) : env.Null();
1083
+ array.Set(i, p);
1076
1084
  });
1077
1085
  } break;
1078
1086
  case PrimitiveKind::Record:
@@ -1088,14 +1096,15 @@ Napi::Value DecodeArray(Napi::Env env, const uint8_t *origin, const TypeInfo *ty
1088
1096
  array.Set(i, value);
1089
1097
  });
1090
1098
  } break;
1091
- case PrimitiveKind::Float32: { POP_NUMBER_ARRAY(Float32Array, float); } break;
1092
- case PrimitiveKind::Float64: { POP_NUMBER_ARRAY(Float64Array, double); } break;
1099
+ case PrimitiveKind::Float32: { POP_NUMBERS(Float32Array, float); } break;
1100
+ case PrimitiveKind::Float64: { POP_NUMBERS(Float64Array, double); } break;
1093
1101
 
1094
1102
  case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
1095
1103
  }
1096
1104
 
1097
- #undef POP_NUMBER_ARRAY_SWAP
1098
- #undef POP_NUMBER_ARRAY
1105
+ #undef POP_NUMBERS_SWAP
1106
+ #undef POP_NUMBERS
1107
+
1099
1108
  #undef POP_ARRAY
1100
1109
 
1101
1110
  K_UNREACHABLE();
@@ -1130,14 +1139,15 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
1130
1139
  offset += ref->size; \
1131
1140
  } \
1132
1141
  } while (false)
1133
- #define POP_NUMBER_ARRAY(CType) \
1142
+
1143
+ #define POP_NUMBERS(CType) \
1134
1144
  do { \
1135
1145
  POP_ARRAY({ \
1136
1146
  double d = (double)*(CType *)src; \
1137
1147
  array.Set(i, Napi::Number::New(env, d)); \
1138
1148
  }); \
1139
1149
  } while (false)
1140
- #define POP_NUMBER_ARRAY_SWAP(CType) \
1150
+ #define POP_NUMBERS_SWAP(CType) \
1141
1151
  do { \
1142
1152
  POP_ARRAY({ \
1143
1153
  CType v = *(CType *)src; \
@@ -1155,16 +1165,16 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
1155
1165
  array.Set(i, Napi::Boolean::New(env, b));
1156
1166
  });
1157
1167
  } break;
1158
- case PrimitiveKind::Int8: { POP_NUMBER_ARRAY(int8_t); } break;
1159
- case PrimitiveKind::UInt8: { POP_NUMBER_ARRAY(uint8_t); } break;
1160
- case PrimitiveKind::Int16: { POP_NUMBER_ARRAY(int16_t); } break;
1161
- case PrimitiveKind::Int16S: { POP_NUMBER_ARRAY_SWAP(int16_t); } break;
1162
- case PrimitiveKind::UInt16: { POP_NUMBER_ARRAY(uint16_t); } break;
1163
- case PrimitiveKind::UInt16S: { POP_NUMBER_ARRAY_SWAP(uint16_t); } break;
1164
- case PrimitiveKind::Int32: { POP_NUMBER_ARRAY(int32_t); } break;
1165
- case PrimitiveKind::Int32S: { POP_NUMBER_ARRAY_SWAP(int32_t); } break;
1166
- case PrimitiveKind::UInt32: { POP_NUMBER_ARRAY(uint32_t); } break;
1167
- case PrimitiveKind::UInt32S: { POP_NUMBER_ARRAY_SWAP(uint32_t); } break;
1168
+ case PrimitiveKind::Int8: { POP_NUMBERS(int8_t); } break;
1169
+ case PrimitiveKind::UInt8: { POP_NUMBERS(uint8_t); } break;
1170
+ case PrimitiveKind::Int16: { POP_NUMBERS(int16_t); } break;
1171
+ case PrimitiveKind::Int16S: { POP_NUMBERS_SWAP(int16_t); } break;
1172
+ case PrimitiveKind::UInt16: { POP_NUMBERS(uint16_t); } break;
1173
+ case PrimitiveKind::UInt16S: { POP_NUMBERS_SWAP(uint16_t); } break;
1174
+ case PrimitiveKind::Int32: { POP_NUMBERS(int32_t); } break;
1175
+ case PrimitiveKind::Int32S: { POP_NUMBERS_SWAP(int32_t); } break;
1176
+ case PrimitiveKind::UInt32: { POP_NUMBERS(uint32_t); } break;
1177
+ case PrimitiveKind::UInt32S: { POP_NUMBERS_SWAP(uint32_t); } break;
1168
1178
  case PrimitiveKind::Int64: {
1169
1179
  POP_ARRAY({
1170
1180
  int64_t v = *(int64_t *)src;
@@ -1219,19 +1229,24 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
1219
1229
  }
1220
1230
  });
1221
1231
  } break;
1222
- case PrimitiveKind::Pointer:
1223
- case PrimitiveKind::Callback: {
1232
+ case PrimitiveKind::Pointer: {
1224
1233
  POP_ARRAY({
1225
1234
  void *ptr2 = *(void **)src;
1226
1235
 
1227
- if (ptr2) {
1228
- Napi::External<void> external = Napi::External<void>::New(env, ptr2);
1229
- SetValueTag(external, ref->ref.marker);
1236
+ Napi::Value p = ptr2 ? WrapPointer(env, ref->ref.type, ptr2) : env.Null();
1237
+ array.Set(i, p);
1230
1238
 
1231
- array.Set(i, external);
1232
- } else {
1233
- array.Set(i, env.Null());
1239
+ if (ref->dispose) {
1240
+ ref->dispose(env, ref, ptr2);
1234
1241
  }
1242
+ });
1243
+ } break;
1244
+ case PrimitiveKind::Callback: {
1245
+ POP_ARRAY({
1246
+ void *ptr2 = *(void **)src;
1247
+
1248
+ Napi::Value p = ptr2 ? WrapCallback(env, ref->ref.type, ptr2) : env.Null();
1249
+ array.Set(i, p);
1235
1250
 
1236
1251
  if (ref->dispose) {
1237
1252
  ref->dispose(env, ref, ptr2);
@@ -1251,14 +1266,15 @@ void DecodeNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo
1251
1266
  array.Set(i, value);
1252
1267
  });
1253
1268
  } break;
1254
- case PrimitiveKind::Float32: { POP_NUMBER_ARRAY(float); } break;
1255
- case PrimitiveKind::Float64: { POP_NUMBER_ARRAY(double); } break;
1269
+ case PrimitiveKind::Float32: { POP_NUMBERS(float); } break;
1270
+ case PrimitiveKind::Float64: { POP_NUMBERS(double); } break;
1256
1271
 
1257
1272
  case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
1258
1273
  }
1259
1274
 
1260
- #undef POP_NUMBER_ARRAY_SWAP
1261
- #undef POP_NUMBER_ARRAY
1275
+ #undef POP_NUMBERS_SWAP
1276
+ #undef POP_NUMBERS
1277
+
1262
1278
  #undef POP_ARRAY
1263
1279
  }
1264
1280
 
@@ -1293,14 +1309,9 @@ Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, const S
1293
1309
  Napi::Env env = value.Env();
1294
1310
  InstanceData *instance = env.GetInstanceData<InstanceData>();
1295
1311
 
1296
- const uint8_t *ptr = nullptr;
1297
-
1298
- if (value.IsExternal()) {
1299
- Napi::External<void> external = value.As<Napi::External<void>>();
1300
- ptr = (const uint8_t *)external.Data();
1301
- } else if (IsRawBuffer(value)) {
1302
- Span<uint8_t> buffer = GetRawBuffer(value);
1312
+ const uint8_t *src = nullptr;
1303
1313
 
1314
+ if (Span<uint8_t> buffer = {}; TryBuffer(value, &buffer)) {
1304
1315
  if (offset < 0) [[unlikely]] {
1305
1316
  ThrowError<Napi::Error>(env, "Offset must be >= 0");
1306
1317
  return env.Null();
@@ -1311,17 +1322,19 @@ Napi::Value Decode(Napi::Value value, Size offset, const TypeInfo *type, const S
1311
1322
  return env.Null();
1312
1323
  }
1313
1324
 
1314
- ptr = (const uint8_t *)buffer.ptr;
1325
+ src = (const uint8_t *)buffer.ptr;
1326
+ } else if (void *ptr = nullptr; TryPointer(value, &ptr)) {
1327
+ src = (const uint8_t *)ptr;
1315
1328
  } else {
1316
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for variable, expected external or TypedArray", GetValueType(instance, value));
1329
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for variable, expected pointer", GetValueType(instance, value));
1317
1330
  return env.Null();
1318
1331
  }
1319
1332
 
1320
- if (!ptr)
1333
+ if (!src)
1321
1334
  return env.Null();
1322
- ptr += offset;
1335
+ src += offset;
1323
1336
 
1324
- Napi::Value ret = Decode(env, ptr, type, len);
1337
+ Napi::Value ret = Decode(env, src, type, len);
1325
1338
  return ret;
1326
1339
  }
1327
1340
 
@@ -1428,10 +1441,13 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
1428
1441
  return str32 ? MakeStringFromUTF32(env, str32) : env.Null();
1429
1442
  }
1430
1443
  } break;
1431
- case PrimitiveKind::Pointer:
1444
+ case PrimitiveKind::Pointer: {
1445
+ void *ptr2 = *(void **)ptr;
1446
+ return ptr2 ? WrapPointer(env, type->ref.type, ptr2) : env.Null();
1447
+ } break;
1432
1448
  case PrimitiveKind::Callback: {
1433
1449
  void *ptr2 = *(void **)ptr;
1434
- return ptr2 ? Napi::External<void>::New(env, ptr2, [](Napi::Env, void *) {}) : env.Null();
1450
+ return ptr2 ? WrapCallback(env, type->ref.type, ptr2) : env.Null();
1435
1451
  } break;
1436
1452
  case PrimitiveKind::Record:
1437
1453
  case PrimitiveKind::Union: {
@@ -1461,10 +1477,12 @@ Napi::Value Decode(Napi::Env env, const uint8_t *ptr, const TypeInfo *type, cons
1461
1477
 
1462
1478
  memcpy((void *)func, proto, K_SIZE(*proto));
1463
1479
  memset((void *)&func->parameters, 0, K_SIZE(func->parameters));
1464
- func->parameters = proto->parameters;
1480
+ memset((void *)&func->primitives, 0, K_SIZE(func->primitives));
1465
1481
 
1466
1482
  func->name = "<anonymous>";
1467
1483
  func->native = (void *)ptr;
1484
+ func->parameters = proto->parameters;
1485
+ func->primitives = proto->primitives;
1468
1486
 
1469
1487
  // Fix back parameter offset
1470
1488
  for (ParameterInfo &param: func->parameters) {
@@ -1488,14 +1506,9 @@ bool Encode(Napi::Value ref, Size offset, Napi::Value value, const TypeInfo *typ
1488
1506
  Napi::Env env = ref.Env();
1489
1507
  InstanceData *instance = env.GetInstanceData<InstanceData>();
1490
1508
 
1491
- uint8_t *ptr = nullptr;
1492
-
1493
- if (ref.IsExternal()) {
1494
- Napi::External<void> external = ref.As<Napi::External<void>>();
1495
- ptr = (uint8_t *)external.Data();
1496
- } else if (IsRawBuffer(ref)) {
1497
- Span<uint8_t> buffer = GetRawBuffer(ref);
1509
+ uint8_t *dest = nullptr;
1498
1510
 
1511
+ if (Span<uint8_t> buffer = {}; TryBuffer(ref, &buffer)) {
1499
1512
  if (offset < 0) [[unlikely]] {
1500
1513
  ThrowError<Napi::Error>(env, "Offset must be >= 0");
1501
1514
  return env.Null();
@@ -1506,19 +1519,21 @@ bool Encode(Napi::Value ref, Size offset, Napi::Value value, const TypeInfo *typ
1506
1519
  return env.Null();
1507
1520
  }
1508
1521
 
1509
- ptr = (uint8_t *)buffer.ptr;
1522
+ dest = (uint8_t *)buffer.ptr;
1523
+ } else if (void *ptr = nullptr; TryPointer(ref, &ptr)) {
1524
+ dest = (uint8_t *)ptr;
1510
1525
  } else {
1511
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for reference, expected external or TypedArray", GetValueType(instance, ref));
1526
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for reference, expected pointer", GetValueType(instance, ref));
1512
1527
  return env.Null();
1513
1528
  }
1514
1529
 
1515
- if (!ptr) [[unlikely]] {
1530
+ if (!dest) [[unlikely]] {
1516
1531
  ThrowError<Napi::Error>(env, "Cannot encode data in NULL pointer");
1517
1532
  return env.Null();
1518
1533
  }
1519
- ptr += offset;
1534
+ dest += offset;
1520
1535
 
1521
- return Encode(env, ptr, value, type, len);
1536
+ return Encode(env, dest, value, type, len);
1522
1537
  }
1523
1538
 
1524
1539
  bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *type, const Size *len)
@@ -1542,22 +1557,24 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
1542
1557
 
1543
1558
  #define PUSH_INTEGER(CType) \
1544
1559
  do { \
1545
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
1560
+ CType v; \
1561
+ \
1562
+ if (!TryNumber(value, &v)) [[unlikely]] { \
1546
1563
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
1547
1564
  return false; \
1548
1565
  } \
1549
1566
  \
1550
- CType v = GetNumber<CType>(value); \
1551
1567
  *(CType *)origin = v; \
1552
1568
  } while (false)
1553
1569
  #define PUSH_INTEGER_SWAP(CType) \
1554
1570
  do { \
1555
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] { \
1571
+ CType v; \
1572
+ \
1573
+ if (!TryNumber(value, &v)) [[unlikely]] { \
1556
1574
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
1557
1575
  return false; \
1558
1576
  } \
1559
1577
  \
1560
- CType v = GetNumber<CType>(value); \
1561
1578
  *(CType *)origin = ReverseBytes(v); \
1562
1579
  } while (false)
1563
1580
 
@@ -1565,12 +1582,14 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
1565
1582
  case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
1566
1583
 
1567
1584
  case PrimitiveKind::Bool: {
1568
- if (!value.IsBoolean()) [[unlikely]] {
1585
+ bool b;
1586
+ napi_status status = napi_get_value_bool(env, value, &b);
1587
+
1588
+ if (status != napi_ok) [[unlikely]] {
1569
1589
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
1570
1590
  return false;
1571
1591
  }
1572
1592
 
1573
- bool b = value.As<Napi::Boolean>();
1574
1593
  *(bool *)origin = b;
1575
1594
  } break;
1576
1595
  case PrimitiveKind::Int8: { PUSH_INTEGER(int8_t); } break;
@@ -1628,8 +1647,7 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
1628
1647
  Napi::Array array = value.As<Napi::Array>();
1629
1648
  if (!call.PushNormalArray(array, type, type->size, origin))
1630
1649
  return false;
1631
- } else if (IsRawBuffer(value)) {
1632
- Span<const uint8_t> buffer = GetRawBuffer(value);
1650
+ } else if (Span<uint8_t> buffer = {}; TryBuffer(value, &buffer)) {
1633
1651
  call.PushBuffer(buffer, type, origin);
1634
1652
  } else if (value.IsString()) {
1635
1653
  if (!call.PushStringArray(value, type, origin))
@@ -1640,35 +1658,34 @@ bool Encode(Napi::Env env, uint8_t *origin, Napi::Value value, const TypeInfo *t
1640
1658
  }
1641
1659
  } break;
1642
1660
  case PrimitiveKind::Float32: {
1643
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
1661
+ float f;
1662
+
1663
+ if (!TryNumber(value, &f)) [[unlikely]] {
1644
1664
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
1645
1665
  return false;
1646
1666
  }
1647
1667
 
1648
- float f = GetNumber<float>(value);
1649
1668
  *(float *)origin = f;
1650
1669
  } break;
1651
1670
  case PrimitiveKind::Float64: {
1652
- if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
1671
+ double d;
1672
+
1673
+ if (!TryNumber(value, &d)) [[unlikely]] {
1653
1674
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
1654
1675
  return false;
1655
1676
  }
1656
1677
 
1657
- double d = GetNumber<double>(value);
1658
1678
  *(double *)origin = d;
1659
1679
  } break;
1660
1680
  case PrimitiveKind::Callback: {
1661
1681
  void *ptr;
1662
1682
 
1663
- if (value.IsFunction()) {
1664
- ThrowError<Napi::Error>(env, "Cannot encode non-registered callback");
1665
- return false;
1666
- } else if (CheckValueTag(value, type->ref.marker)) {
1667
- ptr = value.As<Napi::External<void>>().Data();
1668
- } else if (IsNullOrUndefined(value)) {
1669
- ptr = nullptr;
1670
- } else {
1671
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
1683
+ if (!TryPointer(value, &ptr)) [[unlikely]] {
1684
+ if (value.IsFunction()) {
1685
+ ThrowError<Napi::Error>(env, "Cannot encode non-registered callback");
1686
+ } else {
1687
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
1688
+ }
1672
1689
  return false;
1673
1690
  }
1674
1691
 
@@ -1740,6 +1757,32 @@ Napi::Function WrapFunction(Napi::Env env, const FunctionInfo *func)
1740
1757
  return wrapper;
1741
1758
  }
1742
1759
 
1760
+ Napi::Value WrapPointer(Napi::Env env, const TypeInfo *ref, void *ptr)
1761
+ {
1762
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
1763
+
1764
+ if (instance->config.fast_pointers) {
1765
+ Napi::BigInt big = Napi::BigInt::New(env, (uint64_t)(uintptr_t)ptr);
1766
+ return big;
1767
+ } else {
1768
+ Napi::External<void> external = Napi::External<void>::New(env, ptr);
1769
+ return external;
1770
+ }
1771
+ }
1772
+
1773
+ Napi::Value WrapCallback(Napi::Env env, const TypeInfo *ref, void *ptr)
1774
+ {
1775
+ InstanceData *instance = env.GetInstanceData<InstanceData>();
1776
+
1777
+ if (instance->config.fast_callbacks) {
1778
+ Napi::BigInt big = Napi::BigInt::New(env, (uint64_t)(uintptr_t)ptr);
1779
+ return big;
1780
+ } else {
1781
+ Napi::External<void> external = Napi::External<void>::New(env, ptr);
1782
+ return external;
1783
+ }
1784
+ }
1785
+
1743
1786
  bool DetectCallConvention(Span<const char> name, CallConvention *out_convention)
1744
1787
  {
1745
1788
  if (name == "__cdecl") {
@@ -1796,7 +1839,7 @@ void DumpMemory(const char *type, Span<const uint8_t> bytes)
1796
1839
  PrintLn(StdErr, "%1 at 0x%2 (%3):", type, bytes.ptr, FmtMemSize(bytes.len));
1797
1840
 
1798
1841
  for (const uint8_t *ptr = bytes.begin(); ptr < bytes.end();) {
1799
- Print(StdErr, " [0x%1 %2 %3] ", FmtInt((uintptr_t)ptr, 16),
1842
+ Print(StdErr, " [0x%1 %2 %3] ", FmtHex((uintptr_t)ptr, 16),
1800
1843
  FmtInt((ptr - bytes.begin()) / sizeof(void *), 4, ' '),
1801
1844
  FmtInt(ptr - bytes.begin(), 4, ' '));
1802
1845
  for (int i = 0; ptr < bytes.end() && i < (int)sizeof(void *); i++, ptr++) {