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
@@ -74,16 +74,16 @@ inline void *Code2Op(AbiOpcode code)
74
74
 
75
75
  bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
76
76
  {
77
- func->ret.regular = IsRegularSize(func->ret.type->size, 8);
77
+ func->ret.abi.regular = IsRegularSize(func->ret.type->size, 8);
78
78
 
79
79
  for (Size i = 0; i < func->parameters.len; i++) {
80
- int16_t arg = (int16_t)(!func->ret.regular + i);
80
+ int16_t arg = (int16_t)(!func->ret.abi.regular + i);
81
81
  ParameterInfo &param = func->parameters[i];
82
82
 
83
- param.regular = IsRegularSize(param.type->size, 8);
83
+ param.abi.regular = IsRegularSize(param.type->size, 8);
84
84
 
85
85
  if (param.type->primitive == PrimitiveKind::Record || param.type->primitive == PrimitiveKind::Union) {
86
- AbiOpcode code = param.regular ? AbiOpcode::PushAggregateReg : AbiOpcode::PushAggregateMem;
86
+ AbiOpcode code = param.abi.regular ? AbiOpcode::PushAggregateReg : AbiOpcode::PushAggregateMem;
87
87
 
88
88
  func->sync.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(arg * 8), .b2 = (int16_t)param.directions, .type = param.type });
89
89
  func->async.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(arg * 8), .b2 = (int16_t)param.directions, .type = param.type });
@@ -100,7 +100,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
100
100
 
101
101
  // At least 4 parameter registers
102
102
  {
103
- Size count = std::max((Size)4, func->parameters.len + !func->ret.regular);
103
+ Size count = std::max((Size)4, func->parameters.len + !func->ret.abi.regular);
104
104
  func->stk_size = AlignLen(8 * count, 16);
105
105
  }
106
106
 
@@ -168,7 +168,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
168
168
 
169
169
  case PrimitiveKind::Record:
170
170
  case PrimitiveKind::Union: {
171
- if (func->ret.regular) {
171
+ if (func->ret.abi.regular) {
172
172
  AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateRegX : AbiOpcode::RunAggregateReg;
173
173
  AbiOpcode call = func->forward_fp ? AbiOpcode::CallGX : AbiOpcode::CallG;
174
174
 
@@ -370,14 +370,9 @@ namespace {
370
370
  OP(PushAggregateReg) {
371
371
  napi_value arg = args[inst->a];
372
372
 
373
- if (!IsObject(call->env, arg)) [[unlikely]] {
374
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
375
- return call->env.Null();
376
- }
377
-
378
373
  uint8_t *ptr = (uint8_t *)(base + inst->b1);
379
374
 
380
- if (!call->PushObject(arg, inst->type, ptr))
375
+ if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
381
376
  return call->env.Null();
382
377
 
383
378
  NEXT();
@@ -385,15 +380,10 @@ namespace {
385
380
  OP(PushAggregateMem) {
386
381
  napi_value arg = args[inst->a];
387
382
 
388
- if (!IsObject(call->env, arg)) [[unlikely]] {
389
- ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
390
- return call->env.Null();
391
- }
392
-
393
383
  uint8_t *ptr = call->AllocHeap(inst->type->size);
394
384
  *(uint8_t **)(base + inst->b1) = ptr;
395
385
 
396
- if (!call->PushObject(arg, inst->type, ptr))
386
+ if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
397
387
  return call->env.Null();
398
388
 
399
389
  NEXT();
@@ -415,7 +405,7 @@ namespace {
415
405
  #define DISPOSE(Ptr) \
416
406
  do { \
417
407
  if (inst->type->dispose) { \
418
- inst->type->dispose(call->env, inst->type, (Ptr)); \
408
+ inst->type->dispose(call->instance, inst->type, (Ptr)); \
419
409
  } \
420
410
  } while (false)
421
411
 
@@ -443,42 +433,42 @@ namespace {
443
433
  OP(RunUInt64S) { INTEGER_SWAP(G, uint64_t); }
444
434
  OP(RunString) {
445
435
  uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
446
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
436
+ napi_value value = NewString(call->env, (const char *)rax);
447
437
  DISPOSE((void *)rax);
448
438
  return value;
449
439
  }
450
440
  OP(RunString16) {
451
441
  uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
452
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
442
+ napi_value value = NewString(call->env, (const char16_t *)rax);
453
443
  DISPOSE((void *)rax);
454
444
  return value;
455
445
  }
456
446
  OP(RunString32) {
457
447
  uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
458
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
448
+ napi_value value = NewString(call->env, (const char32_t *)rax);
459
449
  DISPOSE((void *)rax);
460
450
  return value;
461
451
  }
462
452
  OP(RunPointer) {
463
453
  uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
464
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
454
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
465
455
  DISPOSE((void *)rax);
466
456
  return value;
467
457
  }
468
458
  OP(RunCallback) {
469
459
  uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
470
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
460
+ return WrapPointer(call->env, inst->type, (void *)rax);
471
461
  }
472
462
  OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
473
463
  OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
474
464
  OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
475
465
  OP(RunFloat32) {
476
466
  float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
477
- return Napi::Number::New(call->env, (double)f);
467
+ return NewFloat(call->env, f);
478
468
  }
479
469
  OP(RunFloat64) {
480
470
  double d = WRAP(ForwardCallD(call->native, base, &call->saved_sp));
481
- return Napi::Number::New(call->env, d);
471
+ return NewFloat(call->env, d);
482
472
  }
483
473
  OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
484
474
  OP(RunAggregateReg) {
@@ -514,42 +504,42 @@ namespace {
514
504
  OP(RunUInt64SX) { INTEGER_SWAP(GX, uint64_t); }
515
505
  OP(RunStringX) {
516
506
  uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
517
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
507
+ napi_value value = NewString(call->env, (const char *)rax);
518
508
  DISPOSE((void *)rax);
519
509
  return value;
520
510
  }
521
511
  OP(RunString16X) {
522
512
  uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
523
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
513
+ napi_value value = NewString(call->env, (const char16_t *)rax);
524
514
  DISPOSE((void *)rax);
525
515
  return value;
526
516
  }
527
517
  OP(RunString32X) {
528
518
  uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
529
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
519
+ napi_value value = NewString(call->env, (const char32_t *)rax);
530
520
  DISPOSE((void *)rax);
531
521
  return value;
532
522
  }
533
523
  OP(RunPointerX) {
534
524
  uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
535
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
525
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
536
526
  DISPOSE((void *)rax);
537
527
  return value;
538
528
  }
539
529
  OP(RunCallbackX) {
540
530
  uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
541
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
531
+ return WrapPointer(call->env, inst->type, (void *)rax);
542
532
  }
543
533
  OP(RunRecordX) { K_UNREACHABLE(); return call->env.Null(); }
544
534
  OP(RunUnionX) { K_UNREACHABLE(); return call->env.Null(); }
545
535
  OP(RunArrayX) { K_UNREACHABLE(); return call->env.Null(); }
546
536
  OP(RunFloat32X) {
547
537
  float f = WRAP(ForwardCallFX(call->native, base, &call->saved_sp));
548
- return Napi::Number::New(call->env, (double)f);
538
+ return NewFloat(call->env, f);
549
539
  }
550
540
  OP(RunFloat64X) {
551
541
  double d = WRAP(ForwardCallDX(call->native, base, &call->saved_sp));
552
- return Napi::Number::New(call->env, d);
542
+ return NewFloat(call->env, d);
553
543
  }
554
544
  OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
555
545
  OP(RunAggregateRegX) {
@@ -575,7 +565,7 @@ namespace {
575
565
  do { \
576
566
  if (inst->type->dispose) { \
577
567
  void *ptr = *(void **)base; \
578
- inst->type->dispose(call->env, inst->type, ptr); \
568
+ inst->type->dispose(call->instance, inst->type, ptr); \
579
569
  } \
580
570
  } while (false)
581
571
  #define INTEGER(CType) \
@@ -632,42 +622,42 @@ namespace {
632
622
  OP(ReturnUInt64S) { INTEGER_SWAP(uint64_t); }
633
623
  OP(ReturnString) {
634
624
  uint64_t rax = *(uint64_t *)base;
635
- napi_value value = rax ? Napi::String::New(call->env, (const char *)rax) : call->env.Null();
625
+ napi_value value = NewString(call->env, (const char *)rax);
636
626
  DISPOSE();
637
627
  return value;
638
628
  }
639
629
  OP(ReturnString16) {
640
630
  uint64_t rax = *(uint64_t *)base;
641
- napi_value value = rax ? Napi::String::New(call->env, (const char16_t *)rax) : call->env.Null();
631
+ napi_value value = NewString(call->env, (const char16_t *)rax);
642
632
  DISPOSE();
643
633
  return value;
644
634
  }
645
635
  OP(ReturnString32) {
646
636
  uint64_t rax = *(uint64_t *)base;
647
- napi_value value = rax ? MakeStringFromUTF32(call->env, (const char32_t *)rax) : call->env.Null();
637
+ napi_value value = NewString(call->env, (const char32_t *)rax);
648
638
  DISPOSE();
649
639
  return value;
650
640
  }
651
641
  OP(ReturnPointer) {
652
642
  uint64_t rax = *(uint64_t *)base;
653
- napi_value value = rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
643
+ napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
654
644
  DISPOSE();
655
645
  return value;
656
646
  }
657
647
  OP(ReturnCallback) {
658
648
  uint64_t rax = *(uint64_t *)base;
659
- return rax ? WrapPointer(call->env, inst->type, (void *)rax) : call->env.Null();
649
+ return WrapPointer(call->env, inst->type, (void *)rax);
660
650
  }
661
651
  OP(ReturnRecord) { K_UNREACHABLE(); return call->env.Null(); }
662
652
  OP(ReturnUnion) { K_UNREACHABLE(); return call->env.Null(); }
663
653
  OP(ReturnArray) { K_UNREACHABLE(); return call->env.Null(); }
664
654
  OP(ReturnFloat32) {
665
655
  float f = *(float *)base;
666
- return Napi::Number::New(call->env, (double)f);
656
+ return NewFloat(call->env, f);
667
657
  }
668
658
  OP(ReturnFloat64) {
669
659
  double d = *(double *)base;
670
- return Napi::Number::New(call->env, d);
660
+ return NewFloat(call->env, d);
671
661
  }
672
662
  OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
673
663
  OP(ReturnAggregateReg) { return DecodeObject(call->instance, base, inst->type); }
@@ -778,7 +768,7 @@ void CallData::Relay(Size idx, uint8_t *sp)
778
768
  uint64_t *xmm_ptr = gpr_ptr + 4;
779
769
  uint64_t *stk_ptr = (uint64_t *)caller_sp;
780
770
 
781
- uint8_t *return_ptr = !proto->ret.regular ? (uint8_t *)gpr_ptr[0] : nullptr;
771
+ uint8_t *return_ptr = !proto->ret.abi.regular ? (uint8_t *)gpr_ptr[0] : nullptr;
782
772
 
783
773
  K_DEFER_N(err_guard) {
784
774
  trampoline->state = -1;
@@ -889,56 +879,52 @@ void CallData::Relay(Size idx, uint8_t *sp)
889
879
  const char *str = *(const char **)(j < 4 ? gpr_ptr + j : stk_ptr);
890
880
  stk_ptr += (j >= 4);
891
881
 
892
- arguments[i] = str ? Napi::String::New(env, str) : env.Null();
882
+ arguments[i] = NewString(env, str);
893
883
 
894
884
  if (param.type->dispose) {
895
- param.type->dispose(env, param.type, str);
885
+ param.type->dispose(instance, param.type, str);
896
886
  }
897
887
  } break;
898
888
  case PrimitiveKind::String16: {
899
889
  const char16_t *str16 = *(const char16_t **)(j < 4 ? gpr_ptr + j : stk_ptr);
900
890
  stk_ptr += (j >= 4);
901
891
 
902
- arguments[i] = str16 ? Napi::String::New(env, str16) : env.Null();
892
+ arguments[i] = NewString(env, str16);
903
893
 
904
894
  if (param.type->dispose) {
905
- param.type->dispose(env, param.type, str16);
895
+ param.type->dispose(instance, param.type, str16);
906
896
  }
907
897
  } break;
908
898
  case PrimitiveKind::String32: {
909
899
  const char32_t *str32 = *(const char32_t **)(j < 4 ? gpr_ptr + j : stk_ptr);
910
900
  stk_ptr += (j >= 4);
911
901
 
912
- arguments[i] = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
902
+ arguments[i] = NewString(env, str32);
913
903
 
914
904
  if (param.type->dispose) {
915
- param.type->dispose(env, param.type, str32);
905
+ param.type->dispose(instance, param.type, str32);
916
906
  }
917
907
  } break;
918
908
  case PrimitiveKind::Pointer: {
919
909
  void *ptr2 = *(void **)(j < 4 ? gpr_ptr + j : stk_ptr);
920
910
  stk_ptr += (j >= 4);
921
911
 
922
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
912
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
923
913
 
924
914
  if (param.type->dispose) {
925
- param.type->dispose(env, param.type, ptr2);
915
+ param.type->dispose(instance, param.type, ptr2);
926
916
  }
927
917
  } break;
928
918
  case PrimitiveKind::Callback: {
929
919
  void *ptr2 = *(void **)(j < 4 ? gpr_ptr + j : stk_ptr);
930
920
  stk_ptr += (j >= 4);
931
921
 
932
- arguments[i] = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
933
-
934
- if (param.type->dispose) {
935
- param.type->dispose(env, param.type, ptr2);
936
- }
922
+ arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
937
923
  } break;
938
924
  case PrimitiveKind::Record:
939
925
  case PrimitiveKind::Union: {
940
926
  uint8_t *ptr;
941
- if (param.regular) {
927
+ if (param.abi.regular) {
942
928
  ptr = (uint8_t *)(j < 4 ? gpr_ptr + j : stk_ptr);
943
929
  } else {
944
930
  ptr = *(uint8_t **)(j < 4 ? gpr_ptr + j : stk_ptr);
@@ -952,13 +938,13 @@ void CallData::Relay(Size idx, uint8_t *sp)
952
938
  float f = *(float *)(j < 4 ? xmm_ptr + j : stk_ptr);
953
939
  stk_ptr += (j >= 4);
954
940
 
955
- arguments[i] = Napi::Number::New(env, (double)f);
941
+ arguments[i] = NewFloat(env, f);
956
942
  } break;
957
943
  case PrimitiveKind::Float64: {
958
944
  double d = *(double *)(j < 4 ? xmm_ptr + j : stk_ptr);
959
945
  stk_ptr += (j >= 4);
960
946
 
961
- arguments[i] = Napi::Number::New(env, d);
947
+ arguments[i] = NewFloat(env, d);
962
948
  } break;
963
949
 
964
950
  case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
@@ -1049,17 +1035,13 @@ void CallData::Relay(Size idx, uint8_t *sp)
1049
1035
  } break;
1050
1036
  case PrimitiveKind::Record:
1051
1037
  case PrimitiveKind::Union: {
1052
- if (!IsObject(env, value)) [[unlikely]] {
1053
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
1054
- return;
1055
- }
1056
-
1057
1038
  if (return_ptr) {
1058
- if (!PushObject(value, type, return_ptr))
1039
+ if (!PushObject(value, type, return_ptr)) [[unlikely]]
1059
1040
  return;
1060
1041
  out_reg->rax = (uint64_t)return_ptr;
1061
1042
  } else {
1062
- PushObject(value, type, (uint8_t *)&out_reg->rax);
1043
+ if (!PushObject(value, type, (uint8_t *)&out_reg->rax)) [[unlikely]]
1044
+ return;
1063
1045
  }
1064
1046
  } break;
1065
1047
  case PrimitiveKind::Array: { K_UNREACHABLE(); } break;