koffi 3.0.1 → 3.1.0

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 (50) hide show
  1. package/CHANGELOG.md +32 -3
  2. package/cnoke.cjs +2 -2
  3. package/doc/benchmarks.md +1 -1
  4. package/doc/callbacks.md +7 -26
  5. package/doc/{input.md → composites.md} +161 -147
  6. package/doc/contribute.md +3 -2
  7. package/doc/index.md +0 -14
  8. package/doc/{functions.md → load.md} +54 -113
  9. package/doc/migration.md +4 -7
  10. package/doc/misc.md +0 -103
  11. package/doc/output.md +5 -11
  12. package/doc/pointers.md +76 -17
  13. package/doc/primitives.md +151 -0
  14. package/doc/start.md +3 -13
  15. package/doc/types.md +88 -0
  16. package/doc/unions.md +0 -186
  17. package/doc/values.md +134 -0
  18. package/index.d.ts +375 -308
  19. package/lib/native/base/base.cc +66 -24
  20. package/lib/native/base/base.hh +55 -153
  21. package/package.json +16 -16
  22. package/src/koffi/CMakeLists.txt +20 -17
  23. package/src/koffi/index.cjs +30 -111
  24. package/src/koffi/index.js +22 -96
  25. package/src/koffi/indirect.cjs +30 -111
  26. package/src/koffi/indirect.js +24 -24
  27. package/src/koffi/src/abi/arm64.cc +48 -62
  28. package/src/koffi/src/abi/riscv64.cc +39 -57
  29. package/src/koffi/src/abi/x64sysv.cc +39 -57
  30. package/src/koffi/src/abi/x64win.cc +48 -65
  31. package/src/koffi/src/abi/x86.cc +47 -59
  32. package/src/koffi/src/call.cc +426 -209
  33. package/src/koffi/src/call.hh +7 -11
  34. package/src/koffi/src/ffi.cc +534 -303
  35. package/src/koffi/src/ffi.hh +71 -15
  36. package/src/koffi/src/parser.cc +5 -3
  37. package/src/koffi/src/parser.hh +2 -2
  38. package/src/koffi/src/static.cjs +122 -0
  39. package/src/koffi/src/static.js +125 -0
  40. package/src/koffi/src/type.cc +725 -0
  41. package/src/koffi/src/type.hh +71 -0
  42. package/src/koffi/src/util.cc +117 -1202
  43. package/src/koffi/src/util.hh +158 -156
  44. package/src/koffi/src/uv.cc +17 -11
  45. package/src/koffi/src/uv.hh +2 -1
  46. package/vendor/node-addon-api/README.md +1 -1
  47. package/vendor/node-addon-api/napi-inl.h +213 -35
  48. package/vendor/node-addon-api/napi.h +118 -7
  49. package/doc/variables.md +0 -102
  50. package/indirect.d.ts +0 -322
@@ -6,6 +6,7 @@
6
6
  #include "lib/native/base/base.hh"
7
7
  #include "../ffi.hh"
8
8
  #include "../call.hh"
9
+ #include "../type.hh"
9
10
  #include "../util.hh"
10
11
  #if defined(_WIN32)
11
12
  #include "../win32.hh"
@@ -132,9 +133,9 @@ static HfaInfo IsHFA(const TypeInfo *type)
132
133
 
133
134
  bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
134
135
  {
135
- Size gpr_index = 0;
136
- Size vec_index = 0;
137
- Size stack_offset = 0;
136
+ int gpr_index = 0;
137
+ int vec_index = 0;
138
+ int stack_offset = 0;
138
139
 
139
140
  #if defined(_M_ARM64EC)
140
141
  int gpr_max = func->variadic ? 4 : 8;
@@ -541,8 +542,10 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
541
542
  return true;
542
543
  }
543
544
 
544
- #pragma GCC diagnostic push
545
- #pragma GCC diagnostic ignored "-Wunused-parameter"
545
+ #if defined(__GNUC__) || defined(__clang__)
546
+ #pragma GCC diagnostic push
547
+ #pragma GCC diagnostic ignored "-Wunused-parameter"
548
+ #endif
546
549
 
547
550
  namespace {
548
551
  #if defined(MUST_TAIL)
@@ -704,14 +707,9 @@ namespace {
704
707
  OP(PushAggregateReg) {
705
708
  napi_value arg = args[inst->a];
706
709
 
707
- if (!IsObject(call->env, arg)) [[unlikely]] {
708
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
709
- return call->env.Null();
710
- }
711
-
712
710
  uint8_t *ptr = base + inst->b1;
713
711
 
714
- if (!call->PushObject(arg, inst->type, ptr))
712
+ if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
715
713
  return call->env.Null();
716
714
 
717
715
  NEXT();
@@ -719,15 +717,10 @@ namespace {
719
717
  OP(PushAggregateMem) {
720
718
  napi_value arg = args[inst->a];
721
719
 
722
- if (!IsObject(call->env, arg)) [[unlikely]] {
723
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
724
- return call->env.Null();
725
- }
726
-
727
720
  uint8_t *ptr = call->AllocHeap(inst->type->size);
728
721
  *(uint8_t **)(base + inst->b1) = ptr;
729
722
 
730
- if (!call->PushObject(arg, inst->type, ptr))
723
+ if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
731
724
  return call->env.Null();
732
725
 
733
726
  NEXT();
@@ -749,7 +742,7 @@ namespace {
749
742
  #define DISPOSE(Ptr) \
750
743
  do { \
751
744
  if (inst->type->dispose) { \
752
- inst->type->dispose(call->env, inst->type, (Ptr)); \
745
+ inst->type->dispose(call->instance, inst->type, (Ptr)); \
753
746
  } \
754
747
  } while (false)
755
748
 
@@ -777,42 +770,42 @@ namespace {
777
770
  OP(RunUInt64S) { INTEGER_SWAP(GG, uint64_t); }
778
771
  OP(RunString) {
779
772
  uint64_t x0 = WRAP(ForwardCallGG(call->native, base, &call->saved_sp)).x0;
780
- napi_value value = x0 ? Napi::String::New(call->env, (const char *)x0) : call->env.Null();
773
+ napi_value value = NewString(call->env, (const char *)x0);
781
774
  DISPOSE((void *)x0);
782
775
  return value;
783
776
  }
784
777
  OP(RunString16) {
785
778
  uint64_t x0 = WRAP(ForwardCallGG(call->native, base, &call->saved_sp)).x0;
786
- napi_value value = x0 ? Napi::String::New(call->env, (const char16_t *)x0) : call->env.Null();
779
+ napi_value value = NewString(call->env, (const char16_t *)x0);
787
780
  DISPOSE((void *)x0);
788
781
  return value;
789
782
  }
790
783
  OP(RunString32) {
791
784
  uint64_t x0 = WRAP(ForwardCallGG(call->native, base, &call->saved_sp)).x0;
792
- napi_value value = x0 ? MakeStringFromUTF32(call->env, (const char32_t *)x0) : call->env.Null();
785
+ napi_value value = NewString(call->env, (const char32_t *)x0);
793
786
  DISPOSE((void *)x0);
794
787
  return value;
795
788
  }
796
789
  OP(RunPointer) {
797
790
  uint64_t x0 = WRAP(ForwardCallGG(call->native, base, &call->saved_sp)).x0;
798
- napi_value value = x0 ? WrapPointer(call->env, inst->type, (void *)x0) : call->env.Null();
791
+ napi_value value = WrapPointer(call->env, inst->type, (void *)x0);
799
792
  DISPOSE((void *)x0);
800
793
  return value;
801
794
  }
802
795
  OP(RunCallback) {
803
796
  uint64_t x0 = WRAP(ForwardCallGG(call->native, base, &call->saved_sp)).x0;
804
- return x0 ? WrapPointer(call->env, inst->type, (void *)x0) : call->env.Null();
797
+ return WrapPointer(call->env, inst->type, (void *)x0);
805
798
  }
806
799
  OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
807
800
  OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
808
801
  OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
809
802
  OP(RunFloat32) {
810
803
  float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
811
- return Napi::Number::New(call->env, (double)f);
804
+ return NewFloat(call->env, f);
812
805
  }
813
806
  OP(RunFloat64) {
814
807
  double d = WRAP(ForwardCallDDDD(call->native, base, &call->saved_sp)).d0;
815
- return Napi::Number::New(call->env, d);
808
+ return NewFloat(call->env, d);
816
809
  }
817
810
  OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
818
811
  OP(RunAggregateGG) {
@@ -853,42 +846,42 @@ namespace {
853
846
  OP(RunUInt64SX) { INTEGER_SWAP(GGX, uint64_t); }
854
847
  OP(RunStringX) {
855
848
  uint64_t x0 = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp)).x0;
856
- napi_value value = x0 ? Napi::String::New(call->env, (const char *)x0) : call->env.Null();
849
+ napi_value value = NewString(call->env, (const char *)x0);
857
850
  DISPOSE((void *)x0);
858
851
  return value;
859
852
  }
860
853
  OP(RunString16X) {
861
854
  uint64_t x0 = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp)).x0;
862
- napi_value value = x0 ? Napi::String::New(call->env, (const char16_t *)x0) : call->env.Null();
855
+ napi_value value = NewString(call->env, (const char16_t *)x0);
863
856
  DISPOSE((void *)x0);
864
857
  return value;
865
858
  }
866
859
  OP(RunString32X) {
867
860
  uint64_t x0 = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp)).x0;
868
- napi_value value = x0 ? MakeStringFromUTF32(call->env, (const char32_t *)x0) : call->env.Null();
861
+ napi_value value = NewString(call->env, (const char32_t *)x0);
869
862
  DISPOSE((void *)x0);
870
863
  return value;
871
864
  }
872
865
  OP(RunPointerX) {
873
866
  uint64_t x0 = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp)).x0;
874
- napi_value value = x0 ? WrapPointer(call->env, inst->type, (void *)x0) : call->env.Null();
867
+ napi_value value = WrapPointer(call->env, inst->type, (void *)x0);
875
868
  DISPOSE((void *)x0);
876
869
  return value;
877
870
  }
878
871
  OP(RunCallbackX) {
879
872
  uint64_t x0 = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp)).x0;
880
- return x0 ? WrapPointer(call->env, inst->type, (void *)x0) : call->env.Null();
873
+ return WrapPointer(call->env, inst->type, (void *)x0);
881
874
  }
882
875
  OP(RunRecordX) { K_UNREACHABLE(); return call->env.Null(); }
883
876
  OP(RunUnionX) { K_UNREACHABLE(); return call->env.Null(); }
884
877
  OP(RunArrayX) { K_UNREACHABLE(); return call->env.Null(); }
885
878
  OP(RunFloat32X) {
886
879
  float f = WRAP(ForwardCallFX(call->native, base, &call->saved_sp));
887
- return Napi::Number::New(call->env, (double)f);
880
+ return NewFloat(call->env, f);
888
881
  }
889
882
  OP(RunFloat64X) {
890
883
  double d = WRAP(ForwardCallDDDDX(call->native, base, &call->saved_sp)).d0;
891
- return Napi::Number::New(call->env, d);
884
+ return NewFloat(call->env, d);
892
885
  }
893
886
  OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
894
887
  OP(RunAggregateGGX) {
@@ -919,7 +912,7 @@ namespace {
919
912
  do { \
920
913
  if (inst->type->dispose) { \
921
914
  void *ptr = *(void **)base; \
922
- inst->type->dispose(call->env, inst->type, ptr); \
915
+ inst->type->dispose(call->instance, inst->type, ptr); \
923
916
  } \
924
917
  } while (false)
925
918
  #define INTEGER(CType) \
@@ -988,42 +981,42 @@ namespace {
988
981
  OP(ReturnUInt64S) { INTEGER_SWAP(uint64_t); }
989
982
  OP(ReturnString) {
990
983
  uint64_t x0 = *(uint64_t *)base;
991
- napi_value value = x0 ? Napi::String::New(call->env, (const char *)x0) : call->env.Null();
984
+ napi_value value = NewString(call->env, (const char *)x0);
992
985
  DISPOSE();
993
986
  return value;
994
987
  }
995
988
  OP(ReturnString16) {
996
989
  uint64_t x0 = *(uint64_t *)base;
997
- napi_value value = x0 ? Napi::String::New(call->env, (const char16_t *)x0) : call->env.Null();
990
+ napi_value value = NewString(call->env, (const char16_t *)x0);
998
991
  DISPOSE();
999
992
  return value;
1000
993
  }
1001
994
  OP(ReturnString32) {
1002
995
  uint64_t x0 = *(uint64_t *)base;
1003
- napi_value value = x0 ? MakeStringFromUTF32(call->env, (const char32_t *)x0) : call->env.Null();
996
+ napi_value value = NewString(call->env, (const char32_t *)x0);
1004
997
  DISPOSE();
1005
998
  return value;
1006
999
  }
1007
1000
  OP(ReturnPointer) {
1008
1001
  uint64_t x0 = *(uint64_t *)base;
1009
- napi_value value = x0 ? WrapPointer(call->env, inst->type, (void *)x0) : call->env.Null();
1002
+ napi_value value = WrapPointer(call->env, inst->type, (void *)x0);
1010
1003
  DISPOSE();
1011
1004
  return value;
1012
1005
  }
1013
1006
  OP(ReturnCallback) {
1014
1007
  uint64_t x0 = *(uint64_t *)base;
1015
- return x0 ? WrapPointer(call->env, inst->type, (void *)x0) : call->env.Null();
1008
+ return WrapPointer(call->env, inst->type, (void *)x0);
1016
1009
  }
1017
1010
  OP(ReturnRecord) { K_UNREACHABLE(); return call->env.Null(); }
1018
1011
  OP(ReturnUnion) { K_UNREACHABLE(); return call->env.Null(); }
1019
1012
  OP(ReturnArray) { K_UNREACHABLE(); return call->env.Null(); }
1020
1013
  OP(ReturnFloat32) {
1021
1014
  float f = *(float *)base;
1022
- return Napi::Number::New(call->env, (double)f);
1015
+ return NewFloat(call->env, f);
1023
1016
  }
1024
1017
  OP(ReturnFloat64) {
1025
1018
  double d = *(double *)base;
1026
- return Napi::Number::New(call->env, d);
1019
+ return NewFloat(call->env, d);
1027
1020
  }
1028
1021
  OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
1029
1022
  OP(ReturnAggregateReg) { return DecodeObject(call->instance, base, inst->type); }
@@ -1100,7 +1093,9 @@ namespace {
1100
1093
  #undef OP
1101
1094
  }
1102
1095
 
1103
- #pragma GCC diagnostic pop
1096
+ #if defined(__GNUC__) || defined(__clang__)
1097
+ #pragma GCC diagnostic pop
1098
+ #endif
1104
1099
 
1105
1100
  napi_value CallData::Run(const FunctionInfo *func, napi_value *args)
1106
1101
  {
@@ -1199,30 +1194,30 @@ void CallData::Relay(Size idx, uint8_t *sp)
1199
1194
  const uint8_t *src = in_ptr + param.abi.offset;
1200
1195
  const char *str = *(const char **)src;
1201
1196
 
1202
- arguments[i] = str ? Napi::String::New(env, str) : env.Null();
1197
+ arguments[i] = NewString(env, str);
1203
1198
 
1204
1199
  if (param.type->dispose) {
1205
- param.type->dispose(env, param.type, str);
1200
+ param.type->dispose(instance, param.type, str);
1206
1201
  }
1207
1202
  } break;
1208
1203
  case PrimitiveKind::String16: {
1209
1204
  const uint8_t *src = in_ptr + param.abi.offset;
1210
1205
  const char16_t *str16 = *(const char16_t **)src;
1211
1206
 
1212
- arguments[i] = str16 ? Napi::String::New(env, str16) : env.Null();
1207
+ arguments[i] = NewString(env, str16);
1213
1208
 
1214
1209
  if (param.type->dispose) {
1215
- param.type->dispose(env, param.type, str16);
1210
+ param.type->dispose(instance, param.type, str16);
1216
1211
  }
1217
1212
  } break;
1218
1213
  case PrimitiveKind::String32: {
1219
1214
  const uint8_t *src = in_ptr + param.abi.offset;
1220
1215
  const char32_t *str32 = *(const char32_t **)src;
1221
1216
 
1222
- arguments[i] = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
1217
+ arguments[i] = NewString(env, str32);
1223
1218
 
1224
1219
  if (param.type->dispose) {
1225
- param.type->dispose(env, param.type, str32);
1220
+ param.type->dispose(instance, param.type, str32);
1226
1221
  }
1227
1222
  } break;
1228
1223
 
@@ -1230,10 +1225,10 @@ void CallData::Relay(Size idx, uint8_t *sp)
1230
1225
  const uint8_t *src = in_ptr + param.abi.offset;
1231
1226
  void *ptr2 = *(void **)src;
1232
1227
 
1233
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
1228
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
1234
1229
 
1235
1230
  if (param.type->dispose) {
1236
- param.type->dispose(env, param.type, ptr2);
1231
+ param.type->dispose(instance, param.type, ptr2);
1237
1232
  }
1238
1233
  } break;
1239
1234
 
@@ -1250,24 +1245,20 @@ void CallData::Relay(Size idx, uint8_t *sp)
1250
1245
  const uint8_t *src = in_ptr + param.abi.offset;
1251
1246
  float f = *(float *)src;
1252
1247
 
1253
- arguments[i] = Napi::Number::New(env, (double)f);
1248
+ arguments[i] = NewFloat(env, f);
1254
1249
  } break;
1255
1250
  case PrimitiveKind::Float64: {
1256
1251
  const uint8_t *src = in_ptr + param.abi.offset;
1257
1252
  double d = *(double *)src;
1258
1253
 
1259
- arguments[i] = Napi::Number::New(env, d);
1254
+ arguments[i] = NewFloat(env, d);
1260
1255
  } break;
1261
1256
 
1262
1257
  case PrimitiveKind::Callback: {
1263
1258
  const uint8_t *src = in_ptr + param.abi.offset;
1264
1259
  void *ptr2 = *(void **)src;
1265
1260
 
1266
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
1267
-
1268
- if (param.type->dispose) {
1269
- param.type->dispose(env, param.type, ptr2);
1270
- }
1261
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
1271
1262
  } break;
1272
1263
 
1273
1264
  case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
@@ -1367,15 +1358,10 @@ void CallData::Relay(Size idx, uint8_t *sp)
1367
1358
 
1368
1359
  case PrimitiveKind::Record:
1369
1360
  case PrimitiveKind::Union: {
1370
- if (!IsObject(env, value)) [[unlikely]] {
1371
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
1372
- return;
1373
- }
1374
-
1375
1361
  uint64_t *gpr_ptr = (uint64_t *)in_ptr;
1376
1362
  uint8_t *dest = proto->ret.abi.regular ? (uint8_t *)&out_reg + proto->ret.abi.offset : (uint8_t *)gpr_ptr[8]; // x8
1377
1363
 
1378
- if (!PushObject(value, type, dest))
1364
+ if (!PushObject(value, type, dest)) [[unlikely]]
1379
1365
  return;
1380
1366
  } break;
1381
1367
  case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
@@ -6,6 +6,7 @@
6
6
  #include "lib/native/base/base.hh"
7
7
  #include "../ffi.hh"
8
8
  #include "../call.hh"
9
+ #include "../type.hh"
9
10
  #include "../util.hh"
10
11
 
11
12
  #include <napi.h>
@@ -625,13 +626,8 @@ namespace {
625
626
  OP(PushAggregateReg) {
626
627
  napi_value arg = args[inst->a];
627
628
 
628
- if (!IsObject(call->env, arg)) [[unlikely]] {
629
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
630
- return call->env.Null();
631
- }
632
-
633
629
  uint64_t buf[2] = {};
634
- if (!call->PushObject(arg, inst->type, (uint8_t *)buf))
630
+ if (!call->PushObject(arg, inst->type, (uint8_t *)buf)) [[unlikely]]
635
631
  return call->env.Null();
636
632
 
637
633
  // The second part might be useless (if object fits in one register), in
@@ -646,15 +642,10 @@ namespace {
646
642
  OP(PushAggregateMem) {
647
643
  napi_value arg = args[inst->a];
648
644
 
649
- if (!IsObject(call->env, arg)) [[unlikely]] {
650
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
651
- return call->env.Null();
652
- }
653
-
654
645
  uint8_t *ptr = call->AllocHeap(inst->type->size);
655
646
  *(uint8_t **)(base + inst->b1) = ptr;
656
647
 
657
- if (!call->PushObject(arg, inst->type, ptr))
648
+ if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
658
649
  return call->env.Null();
659
650
 
660
651
  NEXT();
@@ -678,7 +669,7 @@ namespace {
678
669
  #define DISPOSE(Ptr) \
679
670
  do { \
680
671
  if (inst->type->dispose) { \
681
- inst->type->dispose(call->env, inst->type, (Ptr)); \
672
+ inst->type->dispose(call->instance, inst->type, (Ptr)); \
682
673
  } \
683
674
  } while (false)
684
675
 
@@ -706,42 +697,42 @@ namespace {
706
697
  OP(RunUInt64S) { INTEGER_SWAP(GG, uint64_t); }
707
698
  OP(RunString) {
708
699
  uint64_t a0 = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).a0);
709
- napi_value value = a0 ? Napi::String::New(call->env, (const char *)a0) : call->env.Null();
700
+ napi_value value = NewString(call->env, (const char *)a0);
710
701
  DISPOSE((void *)a0);
711
702
  return value;
712
703
  }
713
704
  OP(RunString16) {
714
705
  uint64_t a0 = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).a0);
715
- napi_value value = a0 ? Napi::String::New(call->env, (const char16_t *)a0) : call->env.Null();
706
+ napi_value value = NewString(call->env, (const char16_t *)a0);
716
707
  DISPOSE((void *)a0);
717
708
  return value;
718
709
  }
719
710
  OP(RunString32) {
720
711
  uint64_t a0 = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).a0);
721
- napi_value value = a0 ? MakeStringFromUTF32(call->env, (const char32_t *)a0) : call->env.Null();
712
+ napi_value value = NewString(call->env, (const char32_t *)a0);
722
713
  DISPOSE((void *)a0);
723
714
  return value;
724
715
  }
725
716
  OP(RunPointer) {
726
717
  uint64_t a0 = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).a0);
727
- napi_value value = a0 ? WrapPointer(call->env, inst->type, (void *)a0) : call->env.Null();
718
+ napi_value value = WrapPointer(call->env, inst->type, (void *)a0);
728
719
  DISPOSE((void *)a0);
729
720
  return value;
730
721
  }
731
722
  OP(RunCallback) {
732
723
  uint64_t a0 = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).a0);
733
- return a0 ? WrapPointer(call->env, inst->type, (void *)a0) : call->env.Null();
724
+ return WrapPointer(call->env, inst->type, (void *)a0);
734
725
  }
735
726
  OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
736
727
  OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
737
728
  OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
738
729
  OP(RunFloat32) {
739
730
  float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
740
- return Napi::Number::New(call->env, (double)f);
731
+ return NewFloat(call->env, f);
741
732
  }
742
733
  OP(RunFloat64) {
743
734
  double d = WRAP(ForwardCallDD(call->native, base, &call->saved_sp).fa0);
744
- return Napi::Number::New(call->env, d);
735
+ return NewFloat(call->env, d);
745
736
  }
746
737
  OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
747
738
  OP(RunAggregateGG) {
@@ -790,42 +781,42 @@ namespace {
790
781
  OP(RunUInt64SX) { INTEGER_SWAP(GGX, uint64_t); }
791
782
  OP(RunStringX) {
792
783
  uint64_t a0 = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).a0);
793
- napi_value value = a0 ? Napi::String::New(call->env, (const char *)a0) : call->env.Null();
784
+ napi_value value = NewString(call->env, (const char *)a0);
794
785
  DISPOSE((void *)a0);
795
786
  return value;
796
787
  }
797
788
  OP(RunString16X) {
798
789
  uint64_t a0 = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).a0);
799
- napi_value value = a0 ? Napi::String::New(call->env, (const char16_t *)a0) : call->env.Null();
790
+ napi_value value = NewString(call->env, (const char16_t *)a0);
800
791
  DISPOSE((void *)a0);
801
792
  return value;
802
793
  }
803
794
  OP(RunString32X) {
804
795
  uint64_t a0 = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).a0);
805
- napi_value value = a0 ? MakeStringFromUTF32(call->env, (const char32_t *)a0) : call->env.Null();
796
+ napi_value value = NewString(call->env, (const char32_t *)a0);
806
797
  DISPOSE((void *)a0);
807
798
  return value;
808
799
  }
809
800
  OP(RunPointerX) {
810
801
  uint64_t a0 = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).a0);
811
- napi_value value = a0 ? WrapPointer(call->env, inst->type, (void *)a0) : call->env.Null();
802
+ napi_value value = WrapPointer(call->env, inst->type, (void *)a0);
812
803
  DISPOSE((void *)a0);
813
804
  return value;
814
805
  }
815
806
  OP(RunCallbackX) {
816
807
  uint64_t a0 = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).a0);
817
- return a0 ? WrapPointer(call->env, inst->type, (void *)a0) : call->env.Null();
808
+ return WrapPointer(call->env, inst->type, (void *)a0);
818
809
  }
819
810
  OP(RunRecordX) { K_UNREACHABLE(); return call->env.Null(); }
820
811
  OP(RunUnionX) { K_UNREACHABLE(); return call->env.Null(); }
821
812
  OP(RunArrayX) { K_UNREACHABLE(); return call->env.Null(); }
822
813
  OP(RunFloat32X) {
823
814
  float f = WRAP(ForwardCallFX(call->native, base, &call->saved_sp));
824
- return Napi::Number::New(call->env, (double)f);
815
+ return NewFloat(call->env, f);
825
816
  }
826
817
  OP(RunFloat64X) {
827
818
  double d = WRAP(ForwardCallDDX(call->native, base, &call->saved_sp).fa0);
828
- return Napi::Number::New(call->env, d);
819
+ return NewFloat(call->env, d);
829
820
  }
830
821
  OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
831
822
  OP(RunAggregateGGX) {
@@ -864,7 +855,7 @@ namespace {
864
855
  do { \
865
856
  if (inst->type->dispose) { \
866
857
  void *ptr = *(void **)base; \
867
- inst->type->dispose(call->env, inst->type, ptr); \
858
+ inst->type->dispose(call->instance, inst->type, ptr); \
868
859
  } \
869
860
  } while (false)
870
861
  #define INTEGER(CType) \
@@ -927,42 +918,42 @@ namespace {
927
918
  OP(ReturnUInt64S) { INTEGER_SWAP(uint64_t); }
928
919
  OP(ReturnString) {
929
920
  uint64_t a0 = *(uint64_t *)base;
930
- napi_value value = a0 ? Napi::String::New(call->env, (const char *)a0) : call->env.Null();
921
+ napi_value value = NewString(call->env, (const char *)a0);
931
922
  DISPOSE();
932
923
  return value;
933
924
  }
934
925
  OP(ReturnString16) {
935
926
  uint64_t a0 = *(uint64_t *)base;
936
- napi_value value = a0 ? Napi::String::New(call->env, (const char16_t *)a0) : call->env.Null();
927
+ napi_value value = NewString(call->env, (const char16_t *)a0);
937
928
  DISPOSE();
938
929
  return value;
939
930
  }
940
931
  OP(ReturnString32) {
941
932
  uint64_t a0 = *(uint64_t *)base;
942
- napi_value value = a0 ? MakeStringFromUTF32(call->env, (const char32_t *)a0) : call->env.Null();
933
+ napi_value value = NewString(call->env, (const char32_t *)a0);
943
934
  DISPOSE();
944
935
  return value;
945
936
  }
946
937
  OP(ReturnPointer) {
947
938
  uint64_t a0 = *(uint64_t *)base;
948
- napi_value value = a0 ? WrapPointer(call->env, inst->type, (void *)a0) : call->env.Null();
939
+ napi_value value = WrapPointer(call->env, inst->type, (void *)a0);
949
940
  DISPOSE();
950
941
  return value;
951
942
  }
952
943
  OP(ReturnCallback) {
953
944
  uint64_t a0 = *(uint64_t *)base;
954
- return a0 ? WrapPointer(call->env, inst->type, (void *)a0) : call->env.Null();
945
+ return WrapPointer(call->env, inst->type, (void *)a0);
955
946
  }
956
947
  OP(ReturnRecord) { K_UNREACHABLE(); return call->env.Null(); }
957
948
  OP(ReturnUnion) { K_UNREACHABLE(); return call->env.Null(); }
958
949
  OP(ReturnArray) { K_UNREACHABLE(); return call->env.Null(); }
959
950
  OP(ReturnFloat32) {
960
951
  float f = *(float *)base;
961
- return Napi::Number::New(call->env, (double)f);
952
+ return NewFloat(call->env, f);
962
953
  }
963
954
  OP(ReturnFloat64) {
964
955
  double d = *(double *)base;
965
- return Napi::Number::New(call->env, d);
956
+ return NewFloat(call->env, d);
966
957
  }
967
958
  OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
968
959
  OP(ReturnAggregateReg) { return DecodeObject(call->instance, (const uint8_t *)base, inst->type); }
@@ -1132,30 +1123,30 @@ void CallData::Relay(Size idx, uint8_t *sp)
1132
1123
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1133
1124
  const char *str = *(const char **)src;
1134
1125
 
1135
- arguments[i] = str ? Napi::String::New(env, str) : env.Null();
1126
+ arguments[i] = NewString(env, str);
1136
1127
 
1137
1128
  if (param.type->dispose) {
1138
- param.type->dispose(env, param.type, str);
1129
+ param.type->dispose(instance, param.type, str);
1139
1130
  }
1140
1131
  } break;
1141
1132
  case PrimitiveKind::String16: {
1142
1133
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1143
1134
  const char16_t *str16 = *(const char16_t **)src;
1144
1135
 
1145
- arguments[i] = str16 ? Napi::String::New(env, str16) : env.Null();
1136
+ arguments[i] = NewString(env, str16);
1146
1137
 
1147
1138
  if (param.type->dispose) {
1148
- param.type->dispose(env, param.type, str16);
1139
+ param.type->dispose(instance, param.type, str16);
1149
1140
  }
1150
1141
  } break;
1151
1142
  case PrimitiveKind::String32: {
1152
1143
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1153
1144
  const char32_t *str32 = *(const char32_t **)src;
1154
1145
 
1155
- arguments[i] = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
1146
+ arguments[i] = NewString(env, str32);
1156
1147
 
1157
1148
  if (param.type->dispose) {
1158
- param.type->dispose(env, param.type, str32);
1149
+ param.type->dispose(instance, param.type, str32);
1159
1150
  }
1160
1151
  } break;
1161
1152
 
@@ -1163,10 +1154,10 @@ void CallData::Relay(Size idx, uint8_t *sp)
1163
1154
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1164
1155
  void *ptr2 = *(void **)src;
1165
1156
 
1166
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
1157
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
1167
1158
 
1168
1159
  if (param.type->dispose) {
1169
- param.type->dispose(env, param.type, ptr2);
1160
+ param.type->dispose(instance, param.type, ptr2);
1170
1161
  }
1171
1162
  } break;
1172
1163
 
@@ -1189,24 +1180,20 @@ void CallData::Relay(Size idx, uint8_t *sp)
1189
1180
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1190
1181
  float f = *(float *)src;
1191
1182
 
1192
- arguments[i] = Napi::Number::New(env, (double)f);
1183
+ arguments[i] = NewFloat(env, f);
1193
1184
  } break;
1194
1185
  case PrimitiveKind::Float64: {
1195
1186
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1196
1187
  double d = *(double *)src;
1197
1188
 
1198
- arguments[i] = Napi::Number::New(env, d);
1189
+ arguments[i] = NewFloat(env, d);
1199
1190
  } break;
1200
1191
 
1201
1192
  case PrimitiveKind::Callback: {
1202
1193
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1203
1194
  void *ptr2 = *(void **)src;
1204
1195
 
1205
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
1206
-
1207
- if (param.type->dispose) {
1208
- param.type->dispose(env, param.type, ptr2);
1209
- }
1196
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
1210
1197
  } break;
1211
1198
 
1212
1199
  case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
@@ -1301,14 +1288,9 @@ void CallData::Relay(Size idx, uint8_t *sp)
1301
1288
  } break;
1302
1289
  case PrimitiveKind::Record:
1303
1290
  case PrimitiveKind::Union: {
1304
- if (!IsObject(env, value)) [[unlikely]] {
1305
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
1306
- return;
1307
- }
1308
-
1309
1291
  if (proto->ret.abi.method != AbiMethod::Memory) {
1310
1292
  uint64_t buf[2];
1311
- if (!PushObject(value, type, (uint8_t *)buf))
1293
+ if (!PushObject(value, type, (uint8_t *)buf)) [[unlikely]]
1312
1294
  return;
1313
1295
 
1314
1296
  memcpy((uint8_t *)&out_reg + proto->ret.abi.offsets[0], (const uint8_t *)buf, 8);
@@ -1317,7 +1299,7 @@ void CallData::Relay(Size idx, uint8_t *sp)
1317
1299
  uint64_t *gpr_ptr = (uint64_t *)in_ptr;
1318
1300
  uint8_t *dest = (uint8_t *)gpr_ptr[0]; // a0
1319
1301
 
1320
- if (!PushObject(value, type, dest))
1302
+ if (!PushObject(value, type, dest)) [[unlikely]]
1321
1303
  return;
1322
1304
  }
1323
1305
  } break;