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