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