koffi 3.0.2 → 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 (47) hide show
  1. package/CHANGELOG.md +25 -7
  2. package/cnoke.cjs +9 -9
  3. package/doc/benchmarks.md +2 -2
  4. package/doc/callbacks.md +7 -26
  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 +66 -24
  20. package/lib/native/base/base.hh +55 -153
  21. package/package.json +15 -15
  22. package/src/koffi/CMakeLists.txt +19 -17
  23. package/src/koffi/index.cjs +15 -10
  24. package/src/koffi/index.js +6 -6
  25. package/src/koffi/indirect.cjs +15 -10
  26. package/src/koffi/indirect.js +6 -6
  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.js +3 -0
  39. package/src/koffi/src/type.cc +43 -33
  40. package/src/koffi/src/type.hh +1 -1
  41. package/src/koffi/src/util.cc +73 -173
  42. package/src/koffi/src/util.hh +84 -43
  43. package/src/koffi/src/uv.cc +1 -1
  44. package/vendor/node-addon-api/README.md +1 -1
  45. package/vendor/node-addon-api/napi-inl.h +213 -35
  46. package/vendor/node-addon-api/napi.h +118 -7
  47. package/doc/variables.md +0 -102
@@ -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;
@@ -684,13 +684,8 @@ namespace {
684
684
  OP(PushAggregateReg) {
685
685
  napi_value arg = args[inst->a];
686
686
 
687
- if (!IsObject(call->env, arg)) [[unlikely]] {
688
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, args[inst->a]));
689
- return call->env.Null();
690
- }
691
-
692
687
  uint64_t buf[2];
693
- if (!call->PushObject(arg, inst->type, (uint8_t *)buf))
688
+ if (!call->PushObject(arg, inst->type, (uint8_t *)buf)) [[unlikely]]
694
689
  return call->env.Null();
695
690
 
696
691
  // The second part might be useless (if object fits in one register), in
@@ -705,12 +700,7 @@ namespace {
705
700
  OP(PushAggregateStack) {
706
701
  napi_value arg = args[inst->a];
707
702
 
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
- if (!call->PushObject(arg, inst->type, base + inst->b1))
703
+ if (!call->PushObject(arg, inst->type, base + inst->b1)) [[unlikely]]
714
704
  return call->env.Null();
715
705
 
716
706
  NEXT();
@@ -734,7 +724,7 @@ namespace {
734
724
  #define DISPOSE(Ptr) \
735
725
  do { \
736
726
  if (inst->type->dispose) { \
737
- inst->type->dispose(call->env, inst->type, (Ptr)); \
727
+ inst->type->dispose(call->instance, inst->type, (Ptr)); \
738
728
  } \
739
729
  } while (false)
740
730
 
@@ -762,42 +752,42 @@ namespace {
762
752
  OP(RunUInt64S) { INTEGER_SWAP(GG, uint64_t); }
763
753
  OP(RunString) {
764
754
  uint64_t rax = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
765
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
755
+ napi_value value = NewString(call->env, (const char *)rax);
766
756
  DISPOSE((void *)rax);
767
757
  return value;
768
758
  }
769
759
  OP(RunString16) {
770
760
  uint64_t rax = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
771
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
761
+ napi_value value = NewString(call->env, (const char16_t *)rax);
772
762
  DISPOSE((void *)rax);
773
763
  return value;
774
764
  }
775
765
  OP(RunString32) {
776
766
  uint64_t rax = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
777
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
767
+ napi_value value = NewString(call->env, (const char32_t *)rax);
778
768
  DISPOSE((void *)rax);
779
769
  return value;
780
770
  }
781
771
  OP(RunPointer) {
782
772
  uint64_t rax = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
783
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
773
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
784
774
  DISPOSE((void *)rax);
785
775
  return value;
786
776
  }
787
777
  OP(RunCallback) {
788
778
  uint64_t rax = WRAP(ForwardCallGG(call->native, base, &call->saved_sp).rax);
789
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
779
+ return WrapPointer(call->env, inst->type, (void *)rax);
790
780
  }
791
781
  OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
792
782
  OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
793
783
  OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
794
784
  OP(RunFloat32) {
795
785
  float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
796
- return Napi::Number::New(call->env, (double)f);
786
+ return NewFloat(call->env, f);
797
787
  }
798
788
  OP(RunFloat64) {
799
789
  double d = WRAP(ForwardCallDD(call->native, base, &call->saved_sp).xmm0);
800
- return Napi::Number::New(call->env, d);
790
+ return NewFloat(call->env, d);
801
791
  }
802
792
  OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
803
793
  OP(RunAggregateGG) {
@@ -846,42 +836,42 @@ namespace {
846
836
  OP(RunUInt64SX) { INTEGER_SWAP(GGX, uint64_t); }
847
837
  OP(RunStringX) {
848
838
  uint64_t rax = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
849
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
839
+ napi_value value = NewString(call->env, (const char *)rax);
850
840
  DISPOSE((void *)rax);
851
841
  return value;
852
842
  }
853
843
  OP(RunString16X) {
854
844
  uint64_t rax = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
855
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
845
+ napi_value value = NewString(call->env, (const char16_t *)rax);
856
846
  DISPOSE((void *)rax);
857
847
  return value;
858
848
  }
859
849
  OP(RunString32X) {
860
850
  uint64_t rax = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
861
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
851
+ napi_value value = NewString(call->env, (const char32_t *)rax);
862
852
  DISPOSE((void *)rax);
863
853
  return value;
864
854
  }
865
855
  OP(RunPointerX) {
866
856
  uint64_t rax = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
867
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
857
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
868
858
  DISPOSE((void *)rax);
869
859
  return value;
870
860
  }
871
861
  OP(RunCallbackX) {
872
862
  uint64_t rax = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp).rax);
873
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
863
+ return WrapPointer(call->env, inst->type, (void *)rax);
874
864
  }
875
865
  OP(RunRecordX) { K_UNREACHABLE(); return call->env.Null(); }
876
866
  OP(RunUnionX) { K_UNREACHABLE(); return call->env.Null(); }
877
867
  OP(RunArrayX) { K_UNREACHABLE(); return call->env.Null(); }
878
868
  OP(RunFloat32X) {
879
869
  float f = WRAP(ForwardCallFX(call->native, base, &call->saved_sp));
880
- return Napi::Number::New(call->env, (double)f);
870
+ return NewFloat(call->env, f);
881
871
  }
882
872
  OP(RunFloat64X) {
883
873
  double d = WRAP(ForwardCallDDX(call->native, base, &call->saved_sp).xmm0);
884
- return Napi::Number::New(call->env, d);
874
+ return NewFloat(call->env, d);
885
875
  }
886
876
  OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
887
877
  OP(RunAggregateGGX) {
@@ -920,7 +910,7 @@ namespace {
920
910
  do { \
921
911
  if (inst->type->dispose) { \
922
912
  void *ptr = *(void **)base; \
923
- inst->type->dispose(call->env, inst->type, ptr); \
913
+ inst->type->dispose(call->instance, inst->type, ptr); \
924
914
  } \
925
915
  } while (false)
926
916
  #define INTEGER(CType) \
@@ -983,42 +973,42 @@ namespace {
983
973
  OP(ReturnUInt64S) { INTEGER_SWAP(uint64_t); }
984
974
  OP(ReturnString) {
985
975
  uint64_t rax = *(uint64_t *)base;
986
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
976
+ napi_value value = NewString(call->env, (const char *)rax);
987
977
  DISPOSE();
988
978
  return value;
989
979
  }
990
980
  OP(ReturnString16) {
991
981
  uint64_t rax = *(uint64_t *)base;
992
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
982
+ napi_value value = NewString(call->env, (const char16_t *)rax);
993
983
  DISPOSE();
994
984
  return value;
995
985
  }
996
986
  OP(ReturnString32) {
997
987
  uint64_t rax = *(uint64_t *)base;
998
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
988
+ napi_value value = NewString(call->env, (const char32_t *)rax);
999
989
  DISPOSE();
1000
990
  return value;
1001
991
  }
1002
992
  OP(ReturnPointer) {
1003
993
  uint64_t rax = *(uint64_t *)base;
1004
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
994
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
1005
995
  DISPOSE();
1006
996
  return value;
1007
997
  }
1008
998
  OP(ReturnCallback) {
1009
999
  uint64_t rax = *(uint64_t *)base;
1010
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
1000
+ return WrapPointer(call->env, inst->type, (void *)rax);
1011
1001
  }
1012
1002
  OP(ReturnRecord) { K_UNREACHABLE(); return call->env.Null(); }
1013
1003
  OP(ReturnUnion) { K_UNREACHABLE(); return call->env.Null(); }
1014
1004
  OP(ReturnArray) { K_UNREACHABLE(); return call->env.Null(); }
1015
1005
  OP(ReturnFloat32) {
1016
1006
  float f = *(float *)base;
1017
- return Napi::Number::New(call->env, (double)f);
1007
+ return NewFloat(call->env, f);
1018
1008
  }
1019
1009
  OP(ReturnFloat64) {
1020
1010
  double d = *(double *)base;
1021
- return Napi::Number::New(call->env, d);
1011
+ return NewFloat(call->env, d);
1022
1012
  }
1023
1013
  OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
1024
1014
  OP(ReturnAggregateReg) { return DecodeObject(call->instance, base, inst->type); }
@@ -1188,30 +1178,30 @@ void CallData::Relay(Size idx, uint8_t *sp)
1188
1178
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1189
1179
  const char *str = *(const char **)src;
1190
1180
 
1191
- arguments[i] = str ? Napi::String::New(env, str) : env.Null();
1181
+ arguments[i] = NewString(env, str);
1192
1182
 
1193
1183
  if (param.type->dispose) {
1194
- param.type->dispose(env, param.type, str);
1184
+ param.type->dispose(instance, param.type, str);
1195
1185
  }
1196
1186
  } break;
1197
1187
  case PrimitiveKind::String16: {
1198
1188
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1199
1189
  const char16_t *str16 = *(const char16_t **)src;
1200
1190
 
1201
- arguments[i] = str16 ? Napi::String::New(env, str16) : env.Null();
1191
+ arguments[i] = NewString(env, str16);
1202
1192
 
1203
1193
  if (param.type->dispose) {
1204
- param.type->dispose(env, param.type, str16);
1194
+ param.type->dispose(instance, param.type, str16);
1205
1195
  }
1206
1196
  } break;
1207
1197
  case PrimitiveKind::String32: {
1208
1198
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1209
1199
  const char32_t *str32 = *(const char32_t **)src;
1210
1200
 
1211
- arguments[i] = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
1201
+ arguments[i] = NewString(env, str32);
1212
1202
 
1213
1203
  if (param.type->dispose) {
1214
- param.type->dispose(env, param.type, str32);
1204
+ param.type->dispose(instance, param.type, str32);
1215
1205
  }
1216
1206
  } break;
1217
1207
 
@@ -1219,10 +1209,10 @@ void CallData::Relay(Size idx, uint8_t *sp)
1219
1209
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1220
1210
  void *ptr2 = *(void **)src;
1221
1211
 
1222
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
1212
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
1223
1213
 
1224
1214
  if (param.type->dispose) {
1225
- param.type->dispose(env, param.type, ptr2);
1215
+ param.type->dispose(instance, param.type, ptr2);
1226
1216
  }
1227
1217
  } break;
1228
1218
 
@@ -1244,24 +1234,20 @@ void CallData::Relay(Size idx, uint8_t *sp)
1244
1234
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1245
1235
  float f = *(float *)src;
1246
1236
 
1247
- arguments[i] = Napi::Number::New(env, (double)f);
1237
+ arguments[i] = NewFloat(env, f);
1248
1238
  } break;
1249
1239
  case PrimitiveKind::Float64: {
1250
1240
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1251
1241
  double d = *(double *)src;
1252
1242
 
1253
- arguments[i] = Napi::Number::New(env, d);
1243
+ arguments[i] = NewFloat(env, d);
1254
1244
  } break;
1255
1245
 
1256
1246
  case PrimitiveKind::Callback: {
1257
1247
  const uint8_t *src = in_ptr + param.abi.offsets[0];
1258
1248
  void *ptr2 = *(void **)src;
1259
1249
 
1260
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
1261
-
1262
- if (param.type->dispose) {
1263
- param.type->dispose(env, param.type, ptr2);
1264
- }
1250
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
1265
1251
  } break;
1266
1252
 
1267
1253
  case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
@@ -1361,16 +1347,11 @@ void CallData::Relay(Size idx, uint8_t *sp)
1361
1347
 
1362
1348
  case PrimitiveKind::Record:
1363
1349
  case PrimitiveKind::Union: {
1364
- if (!IsObject(env, value)) [[unlikely]] {
1365
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
1366
- return;
1367
- }
1368
-
1369
1350
  if (proto->ret.abi.method == AbiMethod::Stack) {
1370
1351
  uint64_t *gpr_ptr = (uint64_t *)in_ptr;
1371
1352
  uint8_t *dest = (uint8_t *)gpr_ptr[0];
1372
1353
 
1373
- if (!PushObject(value, type, dest))
1354
+ if (!PushObject(value, type, dest)) [[unlikely]]
1374
1355
  return;
1375
1356
 
1376
1357
  out_reg->rax = (uint64_t)dest;
@@ -1378,7 +1359,7 @@ void CallData::Relay(Size idx, uint8_t *sp)
1378
1359
  K_ASSERT(type->size <= 16);
1379
1360
 
1380
1361
  uint8_t buf[16] = {};
1381
- if (!PushObject(value, type, buf))
1362
+ if (!PushObject(value, type, buf)) [[unlikely]]
1382
1363
  return;
1383
1364
 
1384
1365
  switch (proto->ret.abi.method) {