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
@@ -81,10 +81,10 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
81
81
  if (func->ret.type->primitive != PrimitiveKind::Record &&
82
82
  func->ret.type->primitive != PrimitiveKind::Union) {
83
83
  K_ASSERT(IsRegularSize(func->ret.type->size, 8));
84
- func->ret.trivial = true;
84
+ func->ret.abi.regular = true;
85
85
  #if defined(_WIN32) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
86
86
  } else {
87
- func->ret.trivial = IsRegularSize(func->ret.type->size, 8);
87
+ func->ret.abi.regular = IsRegularSize(func->ret.type->size, 8);
88
88
  #endif
89
89
  }
90
90
 
@@ -95,7 +95,7 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
95
95
  Size fast_offset = 0;
96
96
  Size stk_offset = fast ? 4 : 0;
97
97
 
98
- if (!func->ret.trivial) {
98
+ if (!func->ret.abi.regular) {
99
99
  #if defined(_WIN32)
100
100
  stk_offset++;
101
101
  #else
@@ -225,7 +225,7 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
225
225
  }
226
226
  #endif
227
227
 
228
- if (func->ret.trivial) {
228
+ if (func->ret.abi.regular) {
229
229
  AbiOpcode run = fast ? AbiOpcode::RunAggregateGR : AbiOpcode::RunAggregateG;
230
230
  AbiOpcode call = fast ? AbiOpcode::CallGR : AbiOpcode::CallG;
231
231
 
@@ -270,13 +270,13 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
270
270
  case CallConvention::Stdcall: {
271
271
  K_ASSERT(!func->variadic);
272
272
 
273
- Size suffix = (stk_offset - !func->ret.trivial) * 4;
273
+ Size suffix = (stk_offset - !func->ret.abi.regular) * 4;
274
274
  func->decorated_name = Fmt(&instance->str_alloc, "_%1@%2", func->name, suffix).ptr;
275
275
  } break;
276
276
  case CallConvention::Fastcall: {
277
277
  K_ASSERT(!func->variadic);
278
278
 
279
- Size suffix = (fast_offset + stk_offset - 4 - !func->ret.trivial) * 4;
279
+ Size suffix = (fast_offset + stk_offset - 4 - !func->ret.abi.regular) * 4;
280
280
  func->decorated_name = Fmt(&instance->str_alloc, "@%1@%2", func->name, suffix).ptr;
281
281
  } break;
282
282
  case CallConvention::Thiscall: {
@@ -463,14 +463,9 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
463
463
  OP(PushAggregateStack) {
464
464
  napi_value arg = args[inst->a];
465
465
 
466
- if (!IsObject(call->env, arg)) [[unlikely]] {
467
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
468
- return call->env.Null();
469
- }
470
-
471
466
  uint8_t *ptr = (uint8_t *)(base + inst->b1);
472
467
 
473
- if (!call->PushObject(arg, inst->type, ptr))
468
+ if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
474
469
  return call->env.Null();
475
470
 
476
471
  NEXT();
@@ -504,7 +499,7 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
504
499
  #define DISPOSE(Ptr) \
505
500
  do { \
506
501
  if (inst->type->dispose) { \
507
- inst->type->dispose(call->env, inst->type, (Ptr)); \
502
+ inst->type->dispose(call->instance, inst->type, (Ptr)); \
508
503
  } \
509
504
  } while (false)
510
505
 
@@ -532,42 +527,42 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
532
527
  OP(RunUInt64S) { INTEGER64_SWAP(G, uint64_t); }
533
528
  OP(RunString) {
534
529
  uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
535
- napi_value value = eax ? Napi::String::New(call->env, (const char *)eax) : call->env.Null();
530
+ napi_value value = NewString(call->env, (const char *)eax);
536
531
  DISPOSE((void *)eax);
537
532
  return value;
538
533
  }
539
534
  OP(RunString16) {
540
535
  uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
541
- napi_value value = eax ? Napi::String::New(call->env, (const char16_t *)eax) : call->env.Null();
536
+ napi_value value = NewString(call->env, (const char16_t *)eax);
542
537
  DISPOSE((void *)eax);
543
538
  return value;
544
539
  }
545
540
  OP(RunString32) {
546
541
  uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
547
- napi_value value = eax ? MakeStringFromUTF32(call->env, (const char32_t *)eax) : call->env.Null();
542
+ napi_value value = NewString(call->env, (const char32_t *)eax);
548
543
  DISPOSE((void *)eax);
549
544
  return value;
550
545
  }
551
546
  OP(RunPointer) {
552
547
  uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
553
- napi_value value = eax ? WrapPointer(call->env, inst->type, (void *)eax) : call->env.Null();
548
+ napi_value value = WrapPointer(call->env, inst->type, (void *)eax);
554
549
  DISPOSE((void *)eax);
555
550
  return value;
556
551
  }
557
552
  OP(RunCallback) {
558
553
  uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
559
- return eax ? WrapPointer(call->env, inst->type, (void *)eax) : call->env.Null();
554
+ return WrapPointer(call->env, inst->type, (void *)eax);
560
555
  }
561
556
  OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
562
557
  OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
563
558
  OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
564
559
  OP(RunFloat32) {
565
560
  float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
566
- return Napi::Number::New(call->env, (double)f);
561
+ return NewFloat(call->env, f);
567
562
  }
568
563
  OP(RunFloat64) {
569
564
  double d = WRAP(ForwardCallD(call->native, base, &call->saved_sp));
570
- return Napi::Number::New(call->env, d);
565
+ return NewFloat(call->env, d);
571
566
  }
572
567
  OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
573
568
  OP(RunAggregateG) {
@@ -611,42 +606,42 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
611
606
  OP(RunUInt64SR) { INTEGER64_SWAP(GR, uint64_t); }
612
607
  OP(RunStringR) {
613
608
  uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
614
- napi_value value = eax ? Napi::String::New(call->env, (const char *)eax) : call->env.Null();
609
+ napi_value value = NewString(call->env, (const char *)eax);
615
610
  DISPOSE((void *)eax);
616
611
  return value;
617
612
  }
618
613
  OP(RunString16R) {
619
614
  uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
620
- napi_value value = eax ? Napi::String::New(call->env, (const char16_t *)eax) : call->env.Null();
615
+ napi_value value = NewString(call->env, (const char16_t *)eax);
621
616
  DISPOSE((void *)eax);
622
617
  return value;
623
618
  }
624
619
  OP(RunString32R) {
625
620
  uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
626
- napi_value value = eax ? MakeStringFromUTF32(call->env, (const char32_t *)eax) : call->env.Null();
621
+ napi_value value = NewString(call->env, (const char32_t *)eax);
627
622
  DISPOSE((void *)eax);
628
623
  return value;
629
624
  }
630
625
  OP(RunPointerR) {
631
626
  uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
632
- napi_value value = eax ? WrapPointer(call->env, inst->type, (void *)eax) : call->env.Null();
627
+ napi_value value = WrapPointer(call->env, inst->type, (void *)eax);
633
628
  DISPOSE((void *)eax);
634
629
  return value;
635
630
  }
636
631
  OP(RunCallbackR) {
637
632
  uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
638
- return eax ? WrapPointer(call->env, inst->type, (void *)eax) : call->env.Null();
633
+ return WrapPointer(call->env, inst->type, (void *)eax);
639
634
  }
640
635
  OP(RunRecordR) { K_UNREACHABLE(); return call->env.Null(); }
641
636
  OP(RunUnionR) { K_UNREACHABLE(); return call->env.Null(); }
642
637
  OP(RunArrayR) { K_UNREACHABLE(); return call->env.Null(); }
643
638
  OP(RunFloat32R) {
644
639
  float f = WRAP(ForwardCallFR(call->native, base, &call->saved_sp));
645
- return Napi::Number::New(call->env, (double)f);
640
+ return NewFloat(call->env, f);
646
641
  }
647
642
  OP(RunFloat64R) {
648
643
  double d = WRAP(ForwardCallDR(call->native, base, &call->saved_sp));
649
- return Napi::Number::New(call->env, d);
644
+ return NewFloat(call->env, d);
650
645
  }
651
646
  OP(RunPrototypeR) { K_UNREACHABLE(); return call->env.Null(); }
652
647
  OP(RunAggregateGR) {
@@ -686,7 +681,7 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
686
681
  do { \
687
682
  if (inst->type->dispose) { \
688
683
  void *ptr = *(void **)base; \
689
- inst->type->dispose(call->env, inst->type, ptr); \
684
+ inst->type->dispose(call->instance, inst->type, ptr); \
690
685
  } \
691
686
  } while (false)
692
687
  #define INTEGER32(CType) \
@@ -758,42 +753,42 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
758
753
  OP(ReturnUInt64S) { INTEGER64_SWAP(uint64_t); }
759
754
  OP(ReturnString) {
760
755
  uint32_t eax = *(uint32_t *)base;
761
- napi_value value = eax ? Napi::String::New(call->env, (const char *)eax) : call->env.Null();
756
+ napi_value value = NewString(call->env, (const char *)eax);
762
757
  DISPOSE();
763
758
  return value;
764
759
  }
765
760
  OP(ReturnString16) {
766
761
  uint32_t eax = *(uint32_t *)base;
767
- napi_value value = eax ? Napi::String::New(call->env, (const char16_t *)eax) : call->env.Null();
762
+ napi_value value = NewString(call->env, (const char16_t *)eax);
768
763
  DISPOSE();
769
764
  return value;
770
765
  }
771
766
  OP(ReturnString32) {
772
767
  uint32_t eax = *(uint32_t *)base;
773
- napi_value value = eax ? MakeStringFromUTF32(call->env, (const char32_t *)eax) : call->env.Null();
768
+ napi_value value = NewString(call->env, (const char32_t *)eax);
774
769
  DISPOSE();
775
770
  return value;
776
771
  }
777
772
  OP(ReturnPointer) {
778
773
  uint32_t eax = *(uint32_t *)base;
779
- napi_value value = eax ? WrapPointer(call->env, inst->type, (void *)eax) : call->env.Null();
774
+ napi_value value = WrapPointer(call->env, inst->type, (void *)eax);
780
775
  DISPOSE();
781
776
  return value;
782
777
  }
783
778
  OP(ReturnCallback) {
784
779
  uint32_t eax = *(uint32_t *)base;
785
- return eax ? WrapPointer(call->env, inst->type, (void *)eax) : call->env.Null();
780
+ return WrapPointer(call->env, inst->type, (void *)eax);
786
781
  }
787
782
  OP(ReturnRecord) { K_UNREACHABLE(); return call->env.Null(); }
788
783
  OP(ReturnUnion) { K_UNREACHABLE(); return call->env.Null(); }
789
784
  OP(ReturnArray) { K_UNREACHABLE(); return call->env.Null(); }
790
785
  OP(ReturnFloat32) {
791
786
  float f = *(float *)base;
792
- return Napi::Number::New(call->env, (double)f);
787
+ return NewFloat(call->env, f);
793
788
  }
794
789
  OP(ReturnFloat64) {
795
790
  double d = *(double *)base;
796
- return Napi::Number::New(call->env, d);
791
+ return NewFloat(call->env, d);
797
792
  }
798
793
  OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
799
794
  OP(ReturnAggregateReg) { return DecodeObject(call->instance, (const uint8_t *)base, inst->type); }
@@ -859,8 +854,8 @@ void CallData::Relay(Size idx, uint8_t *sp)
859
854
 
860
855
  uint32_t *args_ptr = (uint32_t *)caller_sp;
861
856
 
862
- uint8_t *return_ptr = !proto->ret.trivial ? (uint8_t *)args_ptr[0] : nullptr;
863
- args_ptr += !proto->ret.trivial;
857
+ uint8_t *return_ptr = !proto->ret.abi.regular ? (uint8_t *)args_ptr[0] : nullptr;
858
+ args_ptr += !proto->ret.abi.regular;
864
859
 
865
860
  if (proto->convention == CallConvention::Stdcall) {
866
861
  out_reg->ret_pop = (int)proto->ret_pop;
@@ -961,43 +956,39 @@ void CallData::Relay(Size idx, uint8_t *sp)
961
956
  } break;
962
957
  case PrimitiveKind::String: {
963
958
  const char *str = *(const char **)(args_ptr++);
964
- arguments[i] = str ? Napi::String::New(env, str) : env.Null();
959
+ arguments[i] = NewString(env, str);
965
960
 
966
961
  if (param.type->dispose) {
967
- param.type->dispose(env, param.type, str);
962
+ param.type->dispose(instance, param.type, str);
968
963
  }
969
964
  } break;
970
965
  case PrimitiveKind::String16: {
971
966
  const char16_t *str16 = *(const char16_t **)(args_ptr++);
972
- arguments[i] = str16 ? Napi::String::New(env, str16) : env.Null();
967
+ arguments[i] = NewString(env, str16);
973
968
 
974
969
  if (param.type->dispose) {
975
- param.type->dispose(env, param.type, str16);
970
+ param.type->dispose(instance, param.type, str16);
976
971
  }
977
972
  } break;
978
973
  case PrimitiveKind::String32: {
979
974
  const char32_t *str32 = *(const char32_t **)(args_ptr++);
980
- arguments[i] = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
975
+ arguments[i] = NewString(env, str32);
981
976
 
982
977
  if (param.type->dispose) {
983
- param.type->dispose(env, param.type, str32);
978
+ param.type->dispose(instance, param.type, str32);
984
979
  }
985
980
  } break;
986
981
  case PrimitiveKind::Pointer: {
987
982
  void *ptr2 = *(void **)(args_ptr++);
988
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
983
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
989
984
 
990
985
  if (param.type->dispose) {
991
- param.type->dispose(env, param.type, ptr2);
986
+ param.type->dispose(instance, param.type, ptr2);
992
987
  }
993
988
  } break;
994
989
  case PrimitiveKind::Callback: {
995
990
  void *ptr2 = *(void **)(args_ptr++);
996
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
997
-
998
- if (param.type->dispose) {
999
- param.type->dispose(env, param.type, ptr2);
1000
- }
991
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
1001
992
  } break;
1002
993
  case PrimitiveKind::Record:
1003
994
  case PrimitiveKind::Union: {
@@ -1009,13 +1000,13 @@ void CallData::Relay(Size idx, uint8_t *sp)
1009
1000
  case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
1010
1001
  case PrimitiveKind::Float32: {
1011
1002
  float f = *(float *)(args_ptr++);
1012
- arguments[i] = Napi::Number::New(env, (double)f);
1003
+ arguments[i] = NewFloat(env, f);
1013
1004
  } break;
1014
1005
  case PrimitiveKind::Float64: {
1015
1006
  double d = *(double *)args_ptr;
1016
1007
  args_ptr += 2;
1017
1008
 
1018
- arguments[i] = Napi::Number::New(env, d);
1009
+ arguments[i] = NewFloat(env, d);
1019
1010
  } break;
1020
1011
 
1021
1012
  case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
@@ -1137,17 +1128,13 @@ void CallData::Relay(Size idx, uint8_t *sp)
1137
1128
  } break;
1138
1129
  case PrimitiveKind::Record:
1139
1130
  case PrimitiveKind::Union: {
1140
- if (!IsObject(env, value)) [[unlikely]] {
1141
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
1142
- return;
1143
- }
1144
-
1145
1131
  if (return_ptr) {
1146
- if (!PushObject(value, type, return_ptr))
1132
+ if (!PushObject(value, type, return_ptr)) [[unlikely]]
1147
1133
  return;
1148
1134
  out_reg->eax = (uint32_t)return_ptr;
1149
1135
  } else {
1150
- PushObject(value, type, (uint8_t *)&out_reg->eax);
1136
+ if (!PushObject(value, type, (uint8_t *)&out_reg->eax))
1137
+ return;
1151
1138
  }
1152
1139
 
1153
1140
  out_reg->ret_type = 0;