koffi 3.0.0 → 3.0.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.
@@ -36,19 +36,19 @@ extern "C" double ForwardCallDR(const void *func, uint8_t *sp, uint8_t **out_sav
36
36
  enum class AbiOpcode {
37
37
  #define PRIMITIVE(Name) Push ## Name,
38
38
  #include "../primitives.inc"
39
- PushAggregate,
39
+ PushAggregateStack,
40
40
  #define PRIMITIVE(Name) Run ## Name,
41
41
  #include "../primitives.inc"
42
42
  RunAggregateG,
43
43
  RunAggregateF,
44
44
  RunAggregateD,
45
- RunAggregateStack,
45
+ RunAggregateMem,
46
46
  #define PRIMITIVE(Name) Run ## Name ## R,
47
47
  #include "../primitives.inc"
48
48
  RunAggregateGR,
49
49
  RunAggregateFR,
50
50
  RunAggregateDR,
51
- RunAggregateStackR,
51
+ RunAggregateMemR,
52
52
  Yield,
53
53
  CallG,
54
54
  CallF,
@@ -61,7 +61,7 @@ enum class AbiOpcode {
61
61
  #define PRIMITIVE(Name) Return ## Name,
62
62
  #include "../primitives.inc"
63
63
  ReturnAggregateReg,
64
- ReturnAggregateStack
64
+ ReturnAggregateMem
65
65
  };
66
66
 
67
67
  static inline void *Code2Op(AbiOpcode code)
@@ -119,14 +119,14 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
119
119
  }
120
120
 
121
121
  if (param.type->primitive == PrimitiveKind::Record || param.type->primitive == PrimitiveKind::Union) {
122
- func->sync.Append({ .op = Code2Op(AbiOpcode::PushAggregate), .a = param.offset, .b1 = offset, .b2 = (int16_t)param.directions, .type = param.type });
123
- func->async.Append({ .op = Code2Op(AbiOpcode::PushAggregate), .a = param.offset, .b1 = offset, .b2 = (int16_t)param.directions, .type = param.type });
122
+ func->sync.Append({ .op = Code2Op(AbiOpcode::PushAggregateStack), .a = param.offset, .b1 = (int16_t)(offset * 4), .b2 = (int16_t)param.directions, .type = param.type });
123
+ func->async.Append({ .op = Code2Op(AbiOpcode::PushAggregateStack), .a = param.offset, .b1 = (int16_t)(offset * 4), .b2 = (int16_t)param.directions, .type = param.type });
124
124
  } else {
125
125
  int delta = (int)AbiOpcode::PushVoid - (int)PrimitiveKind::Void;
126
126
  AbiOpcode code = (AbiOpcode)((int)param.type->primitive + delta);
127
127
 
128
- func->sync.Append({ .op = Code2Op(code), .a = param.offset, .b1 = offset, .b2 = (int16_t)param.directions, .type = param.type });
129
- func->async.Append({ .op = Code2Op(code), .a = param.offset, .b1 = offset, .b2 = (int16_t)param.directions, .type = param.type });
128
+ func->sync.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(offset * 4), .b2 = (int16_t)param.directions, .type = param.type });
129
+ func->async.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(offset * 4), .b2 = (int16_t)param.directions, .type = param.type });
130
130
  }
131
131
  }
132
132
 
@@ -232,12 +232,12 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
232
232
  func->async.Append({ .op = Code2Op(call) });
233
233
  func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
234
234
  } else {
235
- AbiOpcode run = fast ? AbiOpcode::RunAggregateStackR : AbiOpcode::RunAggregateStack;
235
+ AbiOpcode run = fast ? AbiOpcode::RunAggregateMemR : AbiOpcode::RunAggregateMem;
236
236
  AbiOpcode call = fast ? AbiOpcode::CallStackR : AbiOpcode::CallStack;
237
237
 
238
238
  func->sync.Append({ .op = Code2Op(run), .a = (int32_t)func->ret.type->size, .type = func->ret.type });
239
239
  func->async.Append({ .op = Code2Op(call), .a = (int32_t)func->ret.type->size });
240
- func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateStack), .type = func->ret.type });
240
+ func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateMem), .type = func->ret.type });
241
241
  }
242
242
  } break;
243
243
  case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
@@ -298,7 +298,7 @@ namespace {
298
298
  #define NEXT() \
299
299
  break
300
300
 
301
- napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiInstruction *inst)
301
+ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiInstruction *inst)
302
302
  {
303
303
  for (;; ++inst) {
304
304
  switch ((intptr_t)inst->op) {
@@ -328,7 +328,7 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
328
328
  return call->env.Null(); \
329
329
  } \
330
330
  \
331
- *(base + inst->b1) = (uint32_t)v; \
331
+ *(uint32_t *)(base + inst->b1) = (uint32_t)v; \
332
332
  } while (false)
333
333
  #define INTEGER32_SWAP(CType) \
334
334
  do { \
@@ -338,7 +338,7 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
338
338
  return call->env.Null(); \
339
339
  } \
340
340
  \
341
- *(base + inst->b1) = (uint32_t)ReverseBytes(v); \
341
+ *(uint32_t *)(base + inst->b1) = (uint32_t)ReverseBytes(v); \
342
342
  } while (false)
343
343
  #define INTEGER64(CType) \
344
344
  do { \
@@ -459,7 +459,7 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
459
459
  NEXT();
460
460
  }
461
461
  OP(PushPrototype) { K_UNREACHABLE(); return call->env.Null(); }
462
- OP(PushAggregate) {
462
+ OP(PushAggregateStack) {
463
463
  napi_value arg = args[inst->a];
464
464
 
465
465
  if (!IsObject(call->env, arg)) [[unlikely]] {
@@ -482,22 +482,22 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
482
482
 
483
483
  #define INTEGER32(Suffix, CType) \
484
484
  do { \
485
- uint32_t eax = (uint32_t)WRAP(ForwardCall ## Suffix(call->native, (uint8_t *)base, &call->saved_sp)); \
485
+ uint32_t eax = (uint32_t)WRAP(ForwardCall ## Suffix(call->native, base, &call->saved_sp)); \
486
486
  return NewInt(call->env, (CType)eax); \
487
487
  } while (false)
488
488
  #define INTEGER32_SWAP(Suffix, CType) \
489
489
  do { \
490
- uint32_t eax = (uint32_t)WRAP(ForwardCall ## Suffix(call->native, (uint8_t *)base, &call->saved_sp)); \
490
+ uint32_t eax = (uint32_t)WRAP(ForwardCall ## Suffix(call->native, base, &call->saved_sp)); \
491
491
  return NewInt(call->env, ReverseBytes((CType)eax)); \
492
492
  } while (false)
493
493
  #define INTEGER64(Suffix, CType) \
494
494
  do { \
495
- uint64_t ret = WRAP(ForwardCall ## Suffix(call->native, (uint8_t *)base, &call->saved_sp)); \
495
+ uint64_t ret = WRAP(ForwardCall ## Suffix(call->native, base, &call->saved_sp)); \
496
496
  return NewInt(call->env, (CType)ret); \
497
497
  } while (false)
498
498
  #define INTEGER64_SWAP(Suffix, CType) \
499
499
  do { \
500
- uint64_t ret = WRAP(ForwardCall ## Suffix(call->native, (uint8_t *)base, &call->saved_sp)); \
500
+ uint64_t ret = WRAP(ForwardCall ## Suffix(call->native, base, &call->saved_sp)); \
501
501
  return NewInt(call->env, ReverseBytes((CType)ret)); \
502
502
  } while (false)
503
503
  #define DISPOSE(Ptr) \
@@ -508,11 +508,11 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
508
508
  } while (false)
509
509
 
510
510
  OP(RunVoid) {
511
- WRAP(ForwardCallG(call->native, (uint8_t *)base, &call->saved_sp));
511
+ WRAP(ForwardCallG(call->native, base, &call->saved_sp));
512
512
  return nullptr;
513
513
  }
514
514
  OP(RunBool) {
515
- uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, (uint8_t *)base, &call->saved_sp));
515
+ uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
516
516
  return Napi::Boolean::New(call->env, eax & 0x1);
517
517
  }
518
518
  OP(RunInt8) { INTEGER32(G, int8_t); }
@@ -530,68 +530,68 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
530
530
  OP(RunUInt64) { INTEGER64(G, uint64_t); }
531
531
  OP(RunUInt64S) { INTEGER64_SWAP(G, uint64_t); }
532
532
  OP(RunString) {
533
- uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, (uint8_t *)base, &call->saved_sp));
533
+ uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
534
534
  napi_value value = eax ? Napi::String::New(call->env, (const char *)eax) : call->env.Null();
535
535
  DISPOSE((void *)eax);
536
536
  return value;
537
537
  }
538
538
  OP(RunString16) {
539
- uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, (uint8_t *)base, &call->saved_sp));
539
+ uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
540
540
  napi_value value = eax ? Napi::String::New(call->env, (const char16_t *)eax) : call->env.Null();
541
541
  DISPOSE((void *)eax);
542
542
  return value;
543
543
  }
544
544
  OP(RunString32) {
545
- uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, (uint8_t *)base, &call->saved_sp));
545
+ uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
546
546
  napi_value value = eax ? MakeStringFromUTF32(call->env, (const char32_t *)eax) : call->env.Null();
547
547
  DISPOSE((void *)eax);
548
548
  return value;
549
549
  }
550
550
  OP(RunPointer) {
551
- uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, (uint8_t *)base, &call->saved_sp));
551
+ uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
552
552
  napi_value value = eax ? WrapPointer(call->env, inst->type, (void *)eax) : call->env.Null();
553
553
  DISPOSE((void *)eax);
554
554
  return value;
555
555
  }
556
556
  OP(RunCallback) {
557
- uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, (uint8_t *)base, &call->saved_sp));
557
+ uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
558
558
  return eax ? WrapPointer(call->env, inst->type, (void *)eax) : call->env.Null();
559
559
  }
560
560
  OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
561
561
  OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
562
562
  OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
563
563
  OP(RunFloat32) {
564
- float f = WRAP(ForwardCallF(call->native, (uint8_t *)base, &call->saved_sp));
564
+ float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
565
565
  return Napi::Number::New(call->env, (double)f);
566
566
  }
567
567
  OP(RunFloat64) {
568
- double d = WRAP(ForwardCallD(call->native, (uint8_t *)base, &call->saved_sp));
568
+ double d = WRAP(ForwardCallD(call->native, base, &call->saved_sp));
569
569
  return Napi::Number::New(call->env, d);
570
570
  }
571
571
  OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
572
572
  OP(RunAggregateG) {
573
- auto ret = WRAP(ForwardCallG(call->native, (uint8_t *)base, &call->saved_sp));
574
- return DecodeObject(call->env, (const uint8_t *)&ret, inst->type);
573
+ auto ret = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
574
+ return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
575
575
  }
576
576
  OP(RunAggregateF) {
577
- auto ret = WRAP(ForwardCallF(call->native, (uint8_t *)base, &call->saved_sp));
578
- return DecodeObject(call->env, (const uint8_t *)&ret, inst->type);
577
+ auto ret = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
578
+ return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
579
579
  }
580
580
  OP(RunAggregateD) {
581
- auto ret = WRAP(ForwardCallD(call->native, (uint8_t *)base, &call->saved_sp));
582
- return DecodeObject(call->env, (const uint8_t *)&ret, inst->type);
581
+ auto ret = WRAP(ForwardCallD(call->native, base, &call->saved_sp));
582
+ return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
583
583
  }
584
- OP(RunAggregateStack) {
584
+ OP(RunAggregateMem) {
585
585
  *(uint8_t **)base = call->AllocHeap(inst->a);
586
- uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, (uint8_t *)base, &call->saved_sp));
587
- return DecodeObject(call->env, (const uint8_t *)eax, inst->type);
586
+ uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
587
+ return DecodeObject(call->instance, (const uint8_t *)eax, inst->type);
588
588
  }
589
589
  OP(RunVoidR) {
590
- WRAP(ForwardCallGR(call->native, (uint8_t *)base, &call->saved_sp));
590
+ WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
591
591
  return nullptr;
592
592
  }
593
593
  OP(RunBoolR) {
594
- uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, (uint8_t *)base, &call->saved_sp));
594
+ uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
595
595
  return Napi::Boolean::New(call->env, eax & 0x1);
596
596
  }
597
597
  OP(RunInt8R) { INTEGER32(GR, int8_t); }
@@ -609,65 +609,65 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
609
609
  OP(RunUInt64R) { INTEGER64(GR, uint64_t); }
610
610
  OP(RunUInt64SR) { INTEGER64_SWAP(GR, uint64_t); }
611
611
  OP(RunStringR) {
612
- uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, (uint8_t *)base, &call->saved_sp));
612
+ uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
613
613
  napi_value value = eax ? Napi::String::New(call->env, (const char *)eax) : call->env.Null();
614
614
  DISPOSE((void *)eax);
615
615
  return value;
616
616
  }
617
617
  OP(RunString16R) {
618
- uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, (uint8_t *)base, &call->saved_sp));
618
+ uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
619
619
  napi_value value = eax ? Napi::String::New(call->env, (const char16_t *)eax) : call->env.Null();
620
620
  DISPOSE((void *)eax);
621
621
  return value;
622
622
  }
623
623
  OP(RunString32R) {
624
- uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, (uint8_t *)base, &call->saved_sp));
624
+ uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
625
625
  napi_value value = eax ? MakeStringFromUTF32(call->env, (const char32_t *)eax) : call->env.Null();
626
626
  DISPOSE((void *)eax);
627
627
  return value;
628
628
  }
629
629
  OP(RunPointerR) {
630
- uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, (uint8_t *)base, &call->saved_sp));
630
+ uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
631
631
  napi_value value = eax ? WrapPointer(call->env, inst->type, (void *)eax) : call->env.Null();
632
632
  DISPOSE((void *)eax);
633
633
  return value;
634
634
  }
635
635
  OP(RunCallbackR) {
636
- uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, (uint8_t *)base, &call->saved_sp));
636
+ uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
637
637
  return eax ? WrapPointer(call->env, inst->type, (void *)eax) : call->env.Null();
638
638
  }
639
639
  OP(RunRecordR) { K_UNREACHABLE(); return call->env.Null(); }
640
640
  OP(RunUnionR) { K_UNREACHABLE(); return call->env.Null(); }
641
641
  OP(RunArrayR) { K_UNREACHABLE(); return call->env.Null(); }
642
642
  OP(RunFloat32R) {
643
- float f = WRAP(ForwardCallFR(call->native, (uint8_t *)base, &call->saved_sp));
643
+ float f = WRAP(ForwardCallFR(call->native, base, &call->saved_sp));
644
644
  return Napi::Number::New(call->env, (double)f);
645
645
  }
646
646
  OP(RunFloat64R) {
647
- double d = WRAP(ForwardCallDR(call->native, (uint8_t *)base, &call->saved_sp));
647
+ double d = WRAP(ForwardCallDR(call->native, base, &call->saved_sp));
648
648
  return Napi::Number::New(call->env, d);
649
649
  }
650
650
  OP(RunPrototypeR) { K_UNREACHABLE(); return call->env.Null(); }
651
651
  OP(RunAggregateGR) {
652
- auto ret = WRAP(ForwardCallGR(call->native, (uint8_t *)base, &call->saved_sp));
653
- return DecodeObject(call->env, (const uint8_t *)&ret, inst->type);
652
+ auto ret = WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
653
+ return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
654
654
  }
655
655
  OP(RunAggregateFR) {
656
- auto ret = WRAP(ForwardCallFR(call->native, (uint8_t *)base, &call->saved_sp));
657
- return DecodeObject(call->env, (const uint8_t *)&ret, inst->type);
656
+ auto ret = WRAP(ForwardCallFR(call->native, base, &call->saved_sp));
657
+ return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
658
658
  }
659
659
  OP(RunAggregateDR) {
660
- auto ret = WRAP(ForwardCallDR(call->native, (uint8_t *)base, &call->saved_sp));
661
- return DecodeObject(call->env, (const uint8_t *)&ret, inst->type);
660
+ auto ret = WRAP(ForwardCallDR(call->native, base, &call->saved_sp));
661
+ return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
662
662
  }
663
- OP(RunAggregateStackR) {
663
+ OP(RunAggregateMemR) {
664
664
  #if defined(_WIN32)
665
- *(uint8_t **)(base + 4) = call->AllocHeap(inst->a);
665
+ *(uint8_t **)(base + 16) = call->AllocHeap(inst->a);
666
666
  #else
667
667
  *(uint8_t **)base = call->AllocHeap(inst->a);
668
668
  #endif
669
- uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, (uint8_t *)base, &call->saved_sp));
670
- return DecodeObject(call->env, (const uint8_t *)eax, inst->type);
669
+ uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
670
+ return DecodeObject(call->instance, (const uint8_t *)eax, inst->type);
671
671
  }
672
672
 
673
673
  #undef DISPOSE
@@ -678,7 +678,7 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
678
678
 
679
679
  #define CALL(Suffix) \
680
680
  do { \
681
- auto ret = WRAP(ForwardCall ## Suffix(call->native, (uint8_t *)base, &call->saved_sp)); \
681
+ auto ret = WRAP(ForwardCall ## Suffix(call->native, base, &call->saved_sp)); \
682
682
  memcpy(base, &ret, K_SIZE(ret)); \
683
683
  } while (false)
684
684
  #define DISPOSE() \
@@ -711,6 +711,7 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
711
711
 
712
712
  OP(Yield) {
713
713
  call->async_ip = inst + 1;
714
+ call->async_base = base;
714
715
  return nullptr;
715
716
  }
716
717
 
@@ -727,7 +728,7 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
727
728
  OP(CallDR) { CALL(DR); return nullptr; }
728
729
  OP(CallStackR) {
729
730
  #if defined(_WIN32)
730
- *(uint8_t **)(base + 4) = call->AllocHeap(inst->a);
731
+ *(uint8_t **)(base + 16) = call->AllocHeap(inst->a);
731
732
  #else
732
733
  *(uint8_t **)base = call->AllocHeap(inst->a);
733
734
  #endif
@@ -794,10 +795,10 @@ napi_value RunLoop(CallData *call, napi_value *args, uint32_t *base, const AbiIn
794
795
  return Napi::Number::New(call->env, d);
795
796
  }
796
797
  OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
797
- OP(ReturnAggregateReg) { return DecodeObject(call->env, (const uint8_t *)base, inst->type); }
798
- OP(ReturnAggregateStack) {
798
+ OP(ReturnAggregateReg) { return DecodeObject(call->instance, (const uint8_t *)base, inst->type); }
799
+ OP(ReturnAggregateMem) {
799
800
  uint32_t eax = *(uint32_t *)base;
800
- return DecodeObject(call->env, (const uint8_t *)eax, inst->type);
801
+ return DecodeObject(call->instance, (const uint8_t *)eax, inst->type);
801
802
  }
802
803
 
803
804
  #undef DISPOSE
@@ -821,7 +822,7 @@ napi_value CallData::Run(const FunctionInfo *func, napi_value *args)
821
822
  return env.Null();
822
823
 
823
824
  const AbiInstruction *first = func->sync.ptr;
824
- return RunLoop(this, args, (uint32_t *)base, first);
825
+ return RunLoop(this, args, base, first);
825
826
  }
826
827
 
827
828
  bool CallData::PrepareAsync(const FunctionInfo *func, napi_value *args)
@@ -832,19 +833,19 @@ bool CallData::PrepareAsync(const FunctionInfo *func, napi_value *args)
832
833
  async_base = base;
833
834
 
834
835
  const AbiInstruction *first = func->async.ptr;
835
- return !RunLoop(this, args, (uint32_t *)base, first); // Yield returns nullptr
836
+ return !RunLoop(this, args, base, first); // Yield returns nullptr
836
837
  }
837
838
 
838
839
  void CallData::ExecuteAsync()
839
840
  {
840
841
  const AbiInstruction *next = async_ip++;
841
- RunLoop(this, nullptr, (uint32_t *)async_base, next);
842
+ RunLoop(this, nullptr, async_base, next);
842
843
  }
843
844
 
844
845
  napi_value CallData::EndAsync()
845
846
  {
846
847
  const AbiInstruction *next = async_ip++;
847
- return RunLoop(this, nullptr, (uint32_t *)async_base, next);
848
+ return RunLoop(this, nullptr, async_base, next);
848
849
  }
849
850
 
850
851
  void CallData::Relay(Size idx, uint8_t *sp)
@@ -1000,7 +1001,7 @@ void CallData::Relay(Size idx, uint8_t *sp)
1000
1001
  case PrimitiveKind::Record:
1001
1002
  case PrimitiveKind::Union: {
1002
1003
  uint8_t *ptr = (uint8_t *)args_ptr;
1003
- arguments[i] = DecodeObject(env, ptr, param.type);
1004
+ arguments[i] = DecodeObject(instance, ptr, param.type);
1004
1005
 
1005
1006
  args_ptr = (uint32_t *)AlignUp(ptr + param.type->size, 4);
1006
1007
  } break;
@@ -68,7 +68,7 @@ void CallData::Finalize()
68
68
  K_ASSERT(IsArray(env, value));
69
69
 
70
70
  uint32_t len = GetArrayLength(env, value);
71
- DecodeElements(env, value, out.ptr, out.type, len);
71
+ DecodeElements(instance, value, out.ptr, out.type, len);
72
72
  } break;
73
73
 
74
74
  case OutArgument::Kind::Buffer: {
@@ -117,7 +117,7 @@ void CallData::Finalize()
117
117
 
118
118
  u->SetRaw(out.ptr);
119
119
  } else {
120
- DecodeObject(env, value, out.ptr, out.type->ref.type);
120
+ DecodeObject(instance, value, out.ptr, out.type->ref.type);
121
121
  }
122
122
  } break;
123
123
  }
@@ -37,10 +37,12 @@ namespace K {
37
37
 
38
38
  SharedData shared;
39
39
 
40
- // Some N-API functions are loaded dynamically to work around bugs or because they are recent
40
+ // Some Node-API functions are loaded dynamically to work around bugs or because they are recent
41
41
  napi_status (NAPI_CDECL *node_api_get_buffer_info)(napi_env env, napi_value value, void **data, size_t *length);
42
42
  napi_status (NAPI_CDECL *node_api_create_property_key_utf8)(napi_env env, const char* str, size_t length, napi_value* result);
43
43
  napi_status (NAPI_CDECL *node_api_post_finalizer)(node_api_basic_env env, napi_finalize finalize_cb, void* finalize_data, void* finalize_hint);
44
+ napi_status (NAPI_CDECL *node_api_create_object_with_properties)(napi_env env, napi_value prototype_or_null, const napi_value *property_names,
45
+ const napi_value *property_values, size_t property_count, napi_value *result);
44
46
  napi_value (*translate_zero_call)(napi_env env, napi_callback_info info);
45
47
 
46
48
  static bool ChangeSize(const char *name, Napi::Value value, Size min_size, Size max_size, Size *out_size)
@@ -254,7 +256,11 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
254
256
 
255
257
  bool skip = (info.Length() > 1);
256
258
  bool named = skip && !IsNullOrUndefined(env, info[0]);
259
+ #if defined(EXTERNAL_TYPES)
260
+ bool redefine = named && info[0].IsExternal() && CheckValueTag(env, info[0], &TypeObjectMarker);
261
+ #else
257
262
  bool redefine = named && info[0].IsObject() && CheckValueTag(env, info[0], &TypeObjectMarker);
263
+ #endif
258
264
 
259
265
  if (named && !info[0].IsString() && !redefine) {
260
266
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, info[0]));
@@ -288,10 +294,16 @@ static Napi::Value CreateStructType(const Napi::CallbackInfo &info, bool pad)
288
294
  TypeInfo *replace = nullptr;
289
295
 
290
296
  if (redefine) {
297
+ #if defined(EXTERNAL_TYPES)
298
+ Napi::External<TypeInfo> external = name.As<Napi::External<TypeInfo>>();
299
+ replace = external.Data();
300
+ #else
291
301
  TypeObject *defn = nullptr;
292
302
  napi_unwrap(env, name, (void **)&defn);
293
303
 
294
304
  replace = (TypeInfo *)defn->GetType();
305
+ #endif
306
+
295
307
  type->name = replace->name;
296
308
 
297
309
  if (replace->primitive != PrimitiveKind::Void || replace == instance->void_type) {
@@ -442,7 +454,11 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
442
454
 
443
455
  bool skip = (info.Length() > 1);
444
456
  bool named = skip && !IsNullOrUndefined(env, info[0]);
457
+ #if defined(EXTERNAL_TYPES)
458
+ bool redefine = named && info[0].IsExternal() && CheckValueTag(env, info[0], &TypeObjectMarker);
459
+ #else
445
460
  bool redefine = named && info[0].IsObject() && CheckValueTag(env, info[0], &TypeObjectMarker);
461
+ #endif
446
462
 
447
463
  if (named && !info[0].IsString() && !redefine) {
448
464
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for name, expected string", GetValueType(instance, info[0]));
@@ -476,10 +492,16 @@ static Napi::Value CreateUnionType(const Napi::CallbackInfo &info)
476
492
  TypeInfo *replace = nullptr;
477
493
 
478
494
  if (redefine) {
495
+ #if defined(EXTERNAL_TYPES)
496
+ Napi::External<TypeInfo> external = name.As<Napi::External<TypeInfo>>();
497
+ replace = external.Data();
498
+ #else
479
499
  TypeObject *defn = nullptr;
480
500
  napi_unwrap(env, name, (void **)&defn);
481
501
 
482
502
  replace = (TypeInfo *)defn->GetType();
503
+ #endif
504
+
483
505
  type->name = replace->name;
484
506
 
485
507
  if (replace->primitive != PrimitiveKind::Void || replace == instance->void_type) {
@@ -1338,12 +1360,13 @@ static Napi::Value CreateEnumType(const Napi::CallbackInfo &info)
1338
1360
  return env.Null();
1339
1361
  err_guard.Disable();
1340
1362
 
1341
- Napi::Object defn = WrapType(env, type, false);
1363
+ Napi::Value wrapper = WrapType(env, type, false);
1364
+ Napi::Object defn = type->defn.Value();
1342
1365
 
1343
1366
  defn.Set("values", values);
1344
1367
  defn.Freeze();
1345
1368
 
1346
- return defn;
1369
+ return wrapper;
1347
1370
  }
1348
1371
 
1349
1372
  static Napi::Value CreateTypeAlias(const Napi::CallbackInfo &info)
@@ -1390,6 +1413,29 @@ static Napi::Value GetResolvedType(const Napi::CallbackInfo &info)
1390
1413
  return WrapType(env, type);
1391
1414
  }
1392
1415
 
1416
+ #if defined(EXTERNAL_TYPES)
1417
+
1418
+ static Napi::Value GetTypeDefinition(const Napi::CallbackInfo &info)
1419
+ {
1420
+ Napi::Env env = info.Env();
1421
+
1422
+ if (info.Length() < 1) {
1423
+ ThrowError<Napi::TypeError>(env, "Expected 1 argument, got %1", info.Length());
1424
+ return env.Null();
1425
+ }
1426
+
1427
+ const TypeInfo *type = ResolveType(info[0]);
1428
+ if (!type)
1429
+ return env.Null();
1430
+
1431
+ // Make sure definition is available
1432
+ WrapType(env, type);
1433
+
1434
+ return type->defn.Value();
1435
+ }
1436
+
1437
+ #endif
1438
+
1393
1439
  InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, Size heap_size)
1394
1440
  {
1395
1441
  std::lock_guard<std::mutex> lock(instance->mem_mutex);
@@ -1878,11 +1924,11 @@ static Napi::Value DecodeValue(const Napi::CallbackInfo &info)
1878
1924
  if (has_len) {
1879
1925
  Size len = info[2 + has_offset].As<Napi::Number>();
1880
1926
 
1881
- Napi::Value ret = Decode(value, (Size)offset, type, &len);
1882
- return ret;
1927
+ napi_value ret = Decode(value, (Size)offset, type, &len);
1928
+ return Napi::Value(env, ret);
1883
1929
  } else {
1884
- Napi::Value ret = Decode(value, (Size)offset, type);
1885
- return ret;
1930
+ napi_value ret = Decode(value, (Size)offset, type);
1931
+ return Napi::Value(env, ret);
1886
1932
  }
1887
1933
  }
1888
1934
 
@@ -2417,7 +2463,7 @@ static napi_value CreateFunction(napi_env env, napi_callback native, const char
2417
2463
 
2418
2464
  static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2419
2465
  {
2420
- // Load recent N-API functions (version >= 9) functions dynamically
2466
+ // Load recent Node-API functions (version >= 9) functions dynamically
2421
2467
  {
2422
2468
  static std::once_flag flag;
2423
2469
 
@@ -2464,6 +2510,8 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2464
2510
  node_api_post_finalizer = SYMBOL(node_api_post_finalizer);
2465
2511
  }
2466
2512
 
2513
+ node_api_create_object_with_properties = SYMBOL(node_api_create_object_with_properties);
2514
+
2467
2515
  #undef SYMBOL
2468
2516
  });
2469
2517
  }
@@ -2495,6 +2543,9 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2495
2543
  exports.Set("enumeration", Napi::Function::New(env, CreateEnumType, "enumeration"));
2496
2544
 
2497
2545
  exports.Set("type", Napi::Function::New(env, GetResolvedType, "type"));
2546
+ #if defined(EXTERNAL_TYPES)
2547
+ exports.Set("introspect", Napi::Function::New(env, GetTypeDefinition, "introspect"));
2548
+ #endif
2498
2549
 
2499
2550
  exports.Set("load", Napi::Function::New(env, LoadSharedLibrary, "load"));
2500
2551
 
@@ -2573,13 +2624,18 @@ static Napi::Object InitModule(Napi::Env env, Napi::Object exports)
2573
2624
 
2574
2625
  // Init object classes and symbols
2575
2626
  {
2627
+ instance->object_constructor = Napi::Persistent(env.RunScript("Object.prototype").As<Napi::Object>());
2576
2628
  instance->construct_lib = Napi::Persistent(LibraryHandle::InitClass(env));
2629
+ #if !defined(EXTERNAL_TYPES)
2577
2630
  instance->construct_type = Napi::Persistent(TypeObject::InitClass(env));
2631
+ #endif
2578
2632
  instance->construct_poll = Napi::Persistent(PollHandle::InitClass(env));
2579
2633
  instance->active_symbol = Napi::Persistent(Napi::Symbol::New(env, "active"));
2580
2634
 
2581
2635
  exports.Set("LibraryHandle", instance->construct_lib.Value());
2636
+ #if !defined(EXTERNAL_TYPES)
2582
2637
  exports.Set("TypeObject", instance->construct_type.Value());
2638
+ #endif
2583
2639
  }
2584
2640
 
2585
2641
  // Init base types
@@ -9,6 +9,9 @@
9
9
 
10
10
  namespace K {
11
11
 
12
+ // #define EXTERNAL_POINTERS
13
+ // #define EXTERNAL_TYPES
14
+
12
15
  static const Size DefaultSyncStackSize = Mebibytes(1);
13
16
  static const Size DefaultSyncHeapSize = Mebibytes(2);
14
17
  static const Size DefaultAsyncStackSize = Kibibytes(128);
@@ -66,11 +69,6 @@ struct RecordMember {
66
69
  struct TypeInfo {
67
70
  const char *name;
68
71
 
69
- // Make sure primitive ends up as the upper N-API tag value when we cast TypeInfo pointers to
70
- // napi_type_tag pointers. Yes, I want to do this. We don't do strict aliasing here.
71
- // N.B. Some node versions don't like when one of the two tag values is 0, so make sure
72
- // this does not happen! It would happen if primitive is 0 and size is 0. To avoid this
73
- // situation, PrimitiveKind::Void (the only type with size 0) is explictly not 0.
74
72
  alignas(8) PrimitiveKind primitive;
75
73
  int32_t size;
76
74
  int16_t align;
@@ -309,8 +307,11 @@ struct InstanceData {
309
307
  const TypeInfo *str16_type;
310
308
  const TypeInfo *str32_type;
311
309
 
310
+ Napi::ObjectReference object_constructor;
312
311
  Napi::FunctionReference construct_lib;
312
+ #if !defined(EXTERNAL_TYPES)
313
313
  Napi::FunctionReference construct_type;
314
+ #endif
314
315
  Napi::FunctionReference construct_poll;
315
316
  Napi::Reference<Napi::Symbol> active_symbol;
316
317
 
@@ -390,10 +391,12 @@ static_assert(MaxTrampolines <= INT16_MAX);
390
391
 
391
392
  extern SharedData shared;
392
393
 
393
- // Some N-API functions are loaded dynamically to work around bugs or because they are recent
394
+ // Some Node-API functions are loaded dynamically to work around bugs or because they are recent
394
395
  extern napi_status (NAPI_CDECL *node_api_get_buffer_info)(napi_env env, napi_value value, void **data, size_t *length);
395
396
  extern napi_status (NAPI_CDECL *node_api_create_property_key_utf8)(napi_env env, const char* str, size_t length, napi_value* result);
396
397
  extern napi_status (NAPI_CDECL *node_api_post_finalizer)(node_api_basic_env env, napi_finalize finalize_cb, void* finalize_data, void* finalize_hint);
398
+ extern napi_status (NAPI_CDECL *node_api_create_object_with_properties)(napi_env env, napi_value prototype_or_null, const napi_value *property_names,
399
+ const napi_value *property_values, size_t property_count, napi_value *result);
397
400
  extern napi_value (*translate_zero_call)(napi_env env, napi_callback_info info);
398
401
 
399
402
  InstanceMemory *AllocateMemory(InstanceData *instance, Size stack_size, Size heap_size);
@@ -5,11 +5,8 @@
5
5
  #error Please define PRIMITIVE() before including primitives.inc
6
6
  #endif
7
7
 
8
- // Void is explictly not first so that it is not 0, for reasons related to N-API type tags.
9
- // Look at TypeInfo definition for more information!
10
-
11
- PRIMITIVE(Bool)
12
8
  PRIMITIVE(Void)
9
+ PRIMITIVE(Bool)
13
10
  PRIMITIVE(Int8)
14
11
  PRIMITIVE(UInt8)
15
12
  PRIMITIVE(Int16)