koffi 3.0.1 → 3.0.2

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.
@@ -4,6 +4,7 @@
4
4
  #include "lib/native/base/base.hh"
5
5
  #include "call.hh"
6
6
  #include "ffi.hh"
7
+ #include "type.hh"
7
8
  #include "util.hh"
8
9
  #if defined(_WIN32)
9
10
  #include "win32.hh"
@@ -71,15 +72,6 @@ void CallData::Finalize()
71
72
  DecodeElements(instance, value, out.ptr, out.type, len);
72
73
  } break;
73
74
 
74
- case OutArgument::Kind::Buffer: {
75
- Span<uint8_t> buffer;
76
-
77
- bool success = TryBuffer(env, value, &buffer);
78
- K_ASSERT(success);
79
-
80
- DecodeBuffer(buffer, out.ptr, out.type);
81
- } break;
82
-
83
75
  case OutArgument::Kind::String: {
84
76
  K_ASSERT(IsArray(env, value));
85
77
  K_ASSERT(GetArrayLength(env, value) == 1);
@@ -113,7 +105,7 @@ void CallData::Finalize()
113
105
  case OutArgument::Kind::Object: {
114
106
  if (CheckValueTag(env, value, &UnionValueMarker)) {
115
107
  UnionValue *u = nullptr;
116
- napi_unwrap(env, value, (void **)&u);
108
+ NAPI_OK(napi_unwrap(env, value, (void **)&u));
117
109
 
118
110
  u->SetRaw(out.ptr);
119
111
  } else {
@@ -183,7 +175,7 @@ void CallData::RelayAsync(Size idx, uint8_t *sp)
183
175
  .sp = sp
184
176
  };
185
177
 
186
- napi_call_threadsafe_function(instance->broker, &ctx, napi_tsfn_blocking);
178
+ NAPI_OK(napi_call_threadsafe_function(instance->broker, &ctx, napi_tsfn_blocking));
187
179
 
188
180
  // Wait until it executes
189
181
  std::unique_lock<std::mutex> lock(ctx.mutex);
@@ -198,8 +190,8 @@ napi_value CallData::CallCallback(const TrampolineInfo *trampoline, const napi_v
198
190
  napi_value func;
199
191
  napi_value value;
200
192
 
201
- napi_get_undefined(env, &recv);
202
- napi_get_reference_value(env, trampoline->func, &func);
193
+ NAPI_OK(napi_get_undefined(env, &recv));
194
+ NAPI_OK(napi_get_reference_value(env, trampoline->func, &func));
203
195
 
204
196
  napi_status status = napi_call_function(env, recv, func, (size_t)count, args, &value);
205
197
  if (status == napi_pending_exception) [[unlikely]]
@@ -257,7 +249,6 @@ bool CallData::PushString32(napi_value value, int directions, const char32_t **o
257
249
  Size CallData::PushStringValue(napi_value value, const char **out_str)
258
250
  {
259
251
  size_t len;
260
- napi_status status;
261
252
 
262
253
  size_t available = (size_t)(mem->heap.end - mem->heap.ptr);
263
254
  char *ptr = (char *)mem->heap.ptr;
@@ -266,7 +257,7 @@ Size CallData::PushStringValue(napi_value value, const char **out_str)
266
257
  if (available >= 4096) [[likely]] {
267
258
  char *ptr = (char *)mem->heap.ptr;
268
259
 
269
- status = napi_get_value_string_utf8(env, value, ptr, 4096, &len);
260
+ napi_status status = napi_get_value_string_utf8(env, value, ptr, 4096, &len);
270
261
  if (status == napi_string_expected)
271
262
  return -1;
272
263
  K_ASSERT(status == napi_ok);
@@ -285,14 +276,12 @@ Size CallData::PushStringValue(napi_value value, const char **out_str)
285
276
  }
286
277
  }
287
278
 
288
- status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
289
- K_ASSERT(status == napi_ok);
279
+ NAPI_OK(napi_get_value_string_utf8(env, value, nullptr, 0, &len));
290
280
 
291
281
  len++;
292
282
 
293
283
  if (len <= available) {
294
- status = napi_get_value_string_utf8(env, value, ptr, len, nullptr);
295
- K_ASSERT(status == napi_ok);
284
+ NAPI_OK(napi_get_value_string_utf8(env, value, ptr, len, nullptr));
296
285
 
297
286
  mem->heap.ptr += (Size)AlignLen(len, 16);
298
287
 
@@ -302,8 +291,7 @@ Size CallData::PushStringValue(napi_value value, const char **out_str)
302
291
  Span<char> buf = AllocateSpan<char>(&mem->allocator, (Size)len);
303
292
  release_alloc |= (prev_stack == mem->stack.end);
304
293
 
305
- status = napi_get_value_string_utf8(env, value, buf.ptr, len, nullptr);
306
- K_ASSERT(status == napi_ok);
294
+ NAPI_OK(napi_get_value_string_utf8(env, value, buf.ptr, len, nullptr));
307
295
 
308
296
  *out_str = buf.ptr;
309
297
  return (Size)len;
@@ -314,9 +302,8 @@ Size CallData::PushString16Value(napi_value value, const char16_t **out_str16)
314
302
  {
315
303
  size_t len = 0;
316
304
  Span<char16_t> buf;
317
- napi_status status;
318
305
 
319
- status = napi_get_value_string_utf16(env, value, nullptr, 0, &len);
306
+ napi_status status = napi_get_value_string_utf16(env, value, nullptr, 0, &len);
320
307
  if (status == napi_string_expected)
321
308
  return -1;
322
309
  K_ASSERT(status == napi_ok);
@@ -327,16 +314,14 @@ Size CallData::PushString16Value(napi_value value, const char16_t **out_str16)
327
314
  buf.len = (mem->heap.end - mem->heap.ptr) / 2;
328
315
 
329
316
  if (len <= (size_t)buf.len) {
330
- status = napi_get_value_string_utf16(env, value, buf.ptr, len, nullptr);
331
- K_ASSERT(status == napi_ok);
317
+ NAPI_OK(napi_get_value_string_utf16(env, value, buf.ptr, len, nullptr));
332
318
 
333
319
  mem->heap.ptr += (Size)AlignLen(len * 2, 16);
334
320
  } else {
335
321
  buf = AllocateSpan<char16_t>(&mem->allocator, (Size)len);
336
322
  release_alloc |= (prev_stack == mem->stack.end);
337
323
 
338
- status = napi_get_value_string_utf16(env, value, buf.ptr, len, nullptr);
339
- K_ASSERT(status == napi_ok);
324
+ NAPI_OK(napi_get_value_string_utf16(env, value, buf.ptr, len, nullptr));
340
325
  }
341
326
 
342
327
  *out_str16 = buf.ptr;
@@ -652,7 +637,7 @@ bool CallData::PushNormalArray(Napi::Array array, const TypeInfo *type, Size siz
652
637
  #define PUSH_ARRAY(SetCode) \
653
638
  do { \
654
639
  for (Size i = 0; i < len; i++) { \
655
- Napi::Value value = array[(uint32_t)i]; \
640
+ napi_value value = array[(uint32_t)i].AsValue(); \
656
641
  \
657
642
  uint8_t *dest = origin + offset; \
658
643
  SetCode \
@@ -744,11 +729,6 @@ bool CallData::PushNormalArray(Napi::Array array, const TypeInfo *type, Size siz
744
729
  } break;
745
730
  case PrimitiveKind::Pointer: {
746
731
  PUSH_ARRAY({
747
- if (!IsObject(env, value)) [[unlikely]] {
748
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
749
- return false;
750
- }
751
-
752
732
  void *ptr;
753
733
  if (!PushPointer(value, ref, 1, &ptr)) [[unlikely]]
754
734
  return false;
@@ -770,17 +750,17 @@ bool CallData::PushNormalArray(Napi::Array array, const TypeInfo *type, Size siz
770
750
  } break;
771
751
  case PrimitiveKind::Array: {
772
752
  for (Size i = 0; i < len; i++) {
773
- Napi::Value value = array[(uint32_t)i];
753
+ napi_value value = array[(uint32_t)i].AsValue();
774
754
 
775
755
  uint8_t *dest = origin + offset;
776
756
 
777
- if (value.IsArray()) {
778
- Napi::Array array2 = value.As<Napi::Array>();
779
- if (!PushNormalArray(array2, ref, (Size)ref->size, dest))
757
+ if (IsArray(env, value)) {
758
+ Napi::Array array = Napi::Array(env, value);
759
+ if (!PushNormalArray(array, ref, (Size)ref->size, dest))
780
760
  return false;
781
761
  } else if (Span<uint8_t> buffer = {}; TryBuffer(env, value, &buffer)) {
782
762
  PushBuffer(buffer, ref, dest);
783
- } else if (value.IsString()) {
763
+ } else if (GetKindOf(env, value) == napi_string) {
784
764
  if (!PushStringArray(value, ref, dest))
785
765
  return false;
786
766
  } else {
@@ -814,19 +794,13 @@ bool CallData::PushNormalArray(Napi::Array array, const TypeInfo *type, Size siz
814
794
  });
815
795
  } break;
816
796
  case PrimitiveKind::Callback: {
817
- for (Size i = 0; i < len; i++) {
818
- Napi::Value value = array[(uint32_t)i];
819
-
820
- uint8_t *dest = origin + offset;
821
-
797
+ PUSH_ARRAY({
822
798
  void *ptr;
823
799
  if (!PushCallback(value, ref, &ptr))
824
800
  return false;
825
801
 
826
- *(void **)dest = ptr;
827
-
828
- offset += stride;
829
- }
802
+ *(const void **)dest = ptr;
803
+ });
830
804
  } break;
831
805
 
832
806
  case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
@@ -893,14 +867,9 @@ bool CallData::PushStringArray(napi_value value, const TypeInfo *type, uint8_t *
893
867
  size_t encoded = 0;
894
868
 
895
869
  switch (type->ref.type->primitive) {
896
- case PrimitiveKind::Int8: {
897
- napi_status status = napi_get_value_string_utf8(env, value, (char *)origin, type->size, &encoded);
898
- K_ASSERT(status == napi_ok);
899
- } break;
870
+ case PrimitiveKind::Int8: { NAPI_OK(napi_get_value_string_utf8(env, value, (char *)origin, type->size, &encoded)); } break;
900
871
  case PrimitiveKind::Int16: {
901
- napi_status status = napi_get_value_string_utf16(env, value, (char16_t *)origin, type->size / 2, &encoded);
902
- K_ASSERT(status == napi_ok);
903
-
872
+ NAPI_OK(napi_get_value_string_utf16(env, value, (char16_t *)origin, type->size / 2, &encoded));
904
873
  encoded *= 2;
905
874
  } break;
906
875
 
@@ -933,7 +902,7 @@ restart:
933
902
  Napi::External<ValueCast> external = Napi::External<ValueCast>(env, value);
934
903
  ValueCast *cast = external.Data();
935
904
 
936
- napi_get_reference_value(env, cast->ref, &value);
905
+ NAPI_OK(napi_get_reference_value(env, cast->ref, &value));
937
906
  type = cast->type;
938
907
 
939
908
  goto restart;
@@ -1029,8 +998,7 @@ bool CallData::PushPointerSlow(napi_value value, napi_valuetype kind, const Type
1029
998
  if (directions & 2) {
1030
999
  OutArgument *out = out_arguments.AppendDefault();
1031
1000
 
1032
- napi_status status = napi_create_reference(env, value, 1, &out->ref);
1033
- K_ASSERT(status == napi_ok);
1001
+ NAPI_OK(napi_create_reference(env, value, 1, &out->ref));
1034
1002
 
1035
1003
  out->kind = out_kind;
1036
1004
  out->ptr = (const uint8_t *)ptr;
@@ -1062,8 +1030,7 @@ bool CallData::PushPointerSlow(napi_value value, napi_valuetype kind, const Type
1062
1030
  if (directions & 2) {
1063
1031
  OutArgument *out = out_arguments.AppendDefault();
1064
1032
 
1065
- napi_status status = napi_create_reference(env, value, 1, &out->ref);
1066
- K_ASSERT(status == napi_ok);
1033
+ NAPI_OK(napi_create_reference(env, value, 1, &out->ref));
1067
1034
 
1068
1035
  out->kind = OutArgument::Kind::Object;
1069
1036
  out->ptr = (const uint8_t *)ptr;
@@ -1107,7 +1074,7 @@ restart:
1107
1074
  Napi::External<ValueCast> external = Napi::External<ValueCast>(env, value);
1108
1075
  ValueCast *cast = external.Data();
1109
1076
 
1110
- napi_get_reference_value(env, cast->ref, &value);
1077
+ NAPI_OK(napi_get_reference_value(env, cast->ref, &value));
1111
1078
  type = cast->type;
1112
1079
 
1113
1080
  goto restart;
@@ -1132,7 +1099,7 @@ restart:
1132
1099
  Napi::External<ValueCast> external = Napi::External<ValueCast>(env, value);
1133
1100
  ValueCast *cast = external.Data();
1134
1101
 
1135
- napi_get_reference_value(env, cast->ref, &value);
1102
+ NAPI_OK(napi_get_reference_value(env, cast->ref, &value));
1136
1103
  type = cast->type;
1137
1104
 
1138
1105
  goto restart;
@@ -1148,7 +1115,7 @@ Size CallData::PushIndirectString(Napi::Array array, const TypeInfo *ref, void *
1148
1115
  if (array.Length() != 1)
1149
1116
  return -1;
1150
1117
 
1151
- Napi::Value value = array[0u];
1118
+ napi_value value = array[0u].AsValue();
1152
1119
 
1153
1120
  if (ref == instance->void_type) {
1154
1121
  return PushStringValue(value, (const char **)out_ptr);
@@ -1192,7 +1159,7 @@ void *CallData::ReserveTrampoline(const FunctionInfo *proto, Napi::Function func
1192
1159
  trampoline->instance = instance;
1193
1160
  trampoline->stack0 = instance->memories[0]->stack0;
1194
1161
  trampoline->proto = proto;
1195
- napi_create_reference(env, func, 1, &trampoline->func);
1162
+ NAPI_OK(napi_create_reference(env, func, 1, &trampoline->func));
1196
1163
 
1197
1164
  void *ptr = GetTrampoline(idx);
1198
1165
 
@@ -1305,13 +1272,12 @@ void InitTranslateZeroCall(Napi::Env env)
1305
1272
 
1306
1273
  Napi::Object self = Napi::Object::New(env);
1307
1274
 
1308
- napi_status status;
1309
1275
  napi_value func;
1310
1276
  napi_value ret;
1311
1277
 
1312
- status = napi_create_function(env, nullptr, 0, [](napi_env env, napi_callback_info info) {
1278
+ auto cb = [](napi_env env, napi_callback_info info) {
1313
1279
  napi_value self;
1314
- napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr);
1280
+ NAPI_OK(napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr));
1315
1281
 
1316
1282
  napi_value *ptr = (napi_value *)info;
1317
1283
 
@@ -1322,11 +1288,10 @@ void InitTranslateZeroCall(Napi::Env env)
1322
1288
  }
1323
1289
 
1324
1290
  return self;
1325
- }, nullptr, &func);
1326
- K_ASSERT(status == napi_ok);
1291
+ };
1327
1292
 
1328
- status = napi_call_function(env, self, func, 0, nullptr, &ret);
1329
- K_ASSERT(status == napi_ok);
1293
+ NAPI_OK(napi_create_function(env, nullptr, 0, cb, nullptr, &func));
1294
+ NAPI_OK(napi_call_function(env, self, func, 0, nullptr, &ret));
1330
1295
  }
1331
1296
 
1332
1297
  bool InitAsyncBroker(Napi::Env env, InstanceData *instance)
@@ -1339,7 +1304,8 @@ bool InitAsyncBroker(Napi::Env env, InstanceData *instance)
1339
1304
  LogError("Failed to create async callback broker");
1340
1305
  return false;
1341
1306
  }
1342
- napi_unref_threadsafe_function(env, instance->broker);
1307
+
1308
+ NAPI_OK(napi_unref_threadsafe_function(env, instance->broker));
1343
1309
  }
1344
1310
 
1345
1311
  return true;
@@ -1376,8 +1342,7 @@ napi_value TranslateFastCall(napi_env env, napi_callback_info info)
1376
1342
  size_t count = 6;
1377
1343
  FunctionInfo *func;
1378
1344
 
1379
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func);
1380
- K_ASSERT(status == napi_ok);
1345
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func));
1381
1346
 
1382
1347
  if (count < (size_t)func->required_parameters) [[unlikely]] {
1383
1348
  ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, count);
@@ -1429,13 +1394,10 @@ napi_value TranslateNormalCall(napi_env env, napi_callback_info info)
1429
1394
  size_t count = 8;
1430
1395
  FunctionInfo *func;
1431
1396
 
1432
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func);
1433
- K_ASSERT(status == napi_ok);
1397
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func));
1434
1398
 
1435
1399
  if (count > 8) {
1436
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, nullptr);
1437
- K_ASSERT(status == napi_ok);
1438
-
1400
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
1439
1401
  count = std::min(count, (size_t)MaxParameters);
1440
1402
  }
1441
1403
 
@@ -1482,13 +1444,10 @@ napi_value TranslateNormalCallDebugAsync(napi_env env, napi_callback_info info)
1482
1444
  size_t count = 8;
1483
1445
  FunctionInfo *func;
1484
1446
 
1485
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func);
1486
- K_ASSERT(status == napi_ok);
1447
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func));
1487
1448
 
1488
1449
  if (count > 8) {
1489
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, nullptr);
1490
- K_ASSERT(status == napi_ok);
1491
-
1450
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
1492
1451
  count = std::min(count, (size_t)MaxParameters);
1493
1452
  }
1494
1453
 
@@ -1517,7 +1476,7 @@ static napi_value TranslateVariadicCall(napi_env env, const FunctionInfo *func,
1517
1476
 
1518
1477
  for (Size i = prev->required_parameters, j = prev->required_parameters; i < (Size)count; i += 2, j++) {
1519
1478
  int directions;
1520
- const TypeInfo *type = ResolveType(Napi::Value(env, args[i]), &directions);
1479
+ const TypeInfo *type = ResolveType(instance, args[i], &directions);
1521
1480
 
1522
1481
  if (type != prev->parameters[j].type || directions != prev->parameters[j].directions) [[unlikely]] {
1523
1482
  match = false;
@@ -1558,7 +1517,7 @@ static napi_value TranslateVariadicCall(napi_env env, const FunctionInfo *func,
1558
1517
  for (Size i = variadic->required_parameters; i < count; i += 2) {
1559
1518
  ParameterInfo param = {};
1560
1519
 
1561
- param.type = ResolveType(Napi::Value(env, args[i]), &param.directions);
1520
+ param.type = ResolveType(instance, args[i], &param.directions);
1562
1521
 
1563
1522
  if (!param.type) [[unlikely]]
1564
1523
  return Napi::Env(env).Null();
@@ -1607,13 +1566,10 @@ napi_value TranslateVariadicCall(napi_env env, napi_callback_info info)
1607
1566
  size_t count = 8;
1608
1567
  FunctionInfo *func;
1609
1568
 
1610
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func);
1611
- K_ASSERT(status == napi_ok);
1569
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func));
1612
1570
 
1613
1571
  if (count > 8) {
1614
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, nullptr);
1615
- K_ASSERT(status == napi_ok);
1616
-
1572
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
1617
1573
  count = std::min(count, (size_t)MaxParameters);
1618
1574
  }
1619
1575
 
@@ -1703,13 +1659,10 @@ napi_value TranslateAsyncCall(napi_env env, napi_callback_info info)
1703
1659
  size_t count = 6;
1704
1660
  FunctionInfo *func;
1705
1661
 
1706
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func);
1707
- K_ASSERT(status == napi_ok);
1662
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, (void **)&func));
1708
1663
 
1709
1664
  if (count > 6) {
1710
- napi_status status = napi_get_cb_info(env, info, &count, args, nullptr, nullptr);
1711
- K_ASSERT(status == napi_ok);
1712
-
1665
+ NAPI_OK(napi_get_cb_info(env, info, &count, args, nullptr, nullptr));
1713
1666
  count = std::min(count, (size_t)MaxParameters);
1714
1667
  }
1715
1668
 
@@ -1800,7 +1753,7 @@ extern "C" void RelayCallback(Size idx, uint8_t *sp)
1800
1753
  K_DEFER { call.Finalize(); };
1801
1754
 
1802
1755
  napi_handle_scope scope;
1803
- napi_open_handle_scope(env, &scope);
1756
+ NAPI_OK(napi_open_handle_scope(env, &scope));
1804
1757
  K_DEFER { napi_close_handle_scope(env, scope); };
1805
1758
 
1806
1759
  call.Relay(idx, sp);
@@ -1839,7 +1792,7 @@ extern "C" void RelayDirect(CallData *call, Size idx, uint8_t *sp)
1839
1792
  // Relay the call
1840
1793
  {
1841
1794
  napi_handle_scope scope;
1842
- napi_open_handle_scope(call->env, &scope);
1795
+ NAPI_OK(napi_open_handle_scope(call->env, &scope));
1843
1796
  K_DEFER { napi_close_handle_scope(call->env, scope); };
1844
1797
 
1845
1798
  call->Relay(idx, sp);
@@ -1874,4 +1827,162 @@ void *GetTrampoline(int idx)
1874
1827
  return (void *)(TrampolineStart + TrampolineSize * idx);
1875
1828
  }
1876
1829
 
1830
+ bool Encode(InstanceData *instance, uint8_t *origin, napi_value value, const TypeInfo *type)
1831
+ {
1832
+ Napi::Env env = instance->env;
1833
+
1834
+ InstanceMemory mem = {};
1835
+ CallData call(env, instance, &mem, nullptr);
1836
+
1837
+ #define PUSH_INTEGER(CType) \
1838
+ do { \
1839
+ CType v; \
1840
+ if (!TryNumber(env, value, &v)) [[unlikely]] { \
1841
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
1842
+ return false; \
1843
+ } \
1844
+ \
1845
+ *(CType *)origin = v; \
1846
+ } while (false)
1847
+ #define PUSH_INTEGER_SWAP(CType) \
1848
+ do { \
1849
+ CType v; \
1850
+ if (!TryNumber(env, value, &v)) [[unlikely]] { \
1851
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
1852
+ return false; \
1853
+ } \
1854
+ \
1855
+ *(CType *)origin = ReverseBytes(v); \
1856
+ } while (false)
1857
+
1858
+ switch (type->primitive) {
1859
+ case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
1860
+
1861
+ case PrimitiveKind::Bool: {
1862
+ bool b;
1863
+ napi_status status = napi_get_value_bool(env, value, &b);
1864
+
1865
+ if (status != napi_ok) [[unlikely]] {
1866
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
1867
+ return false;
1868
+ }
1869
+
1870
+ *(bool *)origin = b;
1871
+ } break;
1872
+ case PrimitiveKind::Int8: { PUSH_INTEGER(int8_t); } break;
1873
+ case PrimitiveKind::UInt8: { PUSH_INTEGER(uint8_t); } break;
1874
+ case PrimitiveKind::Int16: { PUSH_INTEGER(int16_t); } break;
1875
+ case PrimitiveKind::Int16S: { PUSH_INTEGER_SWAP(int16_t); } break;
1876
+ case PrimitiveKind::UInt16: { PUSH_INTEGER(uint16_t); } break;
1877
+ case PrimitiveKind::UInt16S: { PUSH_INTEGER_SWAP(uint16_t); } break;
1878
+ case PrimitiveKind::Int32: { PUSH_INTEGER(int32_t); } break;
1879
+ case PrimitiveKind::Int32S: { PUSH_INTEGER_SWAP(int32_t); } break;
1880
+ case PrimitiveKind::UInt32: { PUSH_INTEGER(uint32_t); } break;
1881
+ case PrimitiveKind::UInt32S: { PUSH_INTEGER_SWAP(uint32_t); } break;
1882
+ case PrimitiveKind::Int64: { PUSH_INTEGER(int64_t); } break;
1883
+ case PrimitiveKind::Int64S: { PUSH_INTEGER_SWAP(int64_t); } break;
1884
+ case PrimitiveKind::UInt64: { PUSH_INTEGER(uint64_t); } break;
1885
+ case PrimitiveKind::UInt64S: { PUSH_INTEGER_SWAP(uint64_t); } break;
1886
+ case PrimitiveKind::String: {
1887
+ const char *str;
1888
+ if (!call.PushString(value, 1, &str)) [[unlikely]]
1889
+ return false;
1890
+ *(const char **)origin = str;
1891
+ } break;
1892
+ case PrimitiveKind::String16: {
1893
+ const char16_t *str16;
1894
+ if (!call.PushString16(value, 1, &str16)) [[unlikely]]
1895
+ return false;
1896
+ *(const char16_t **)origin = str16;
1897
+ } break;
1898
+ case PrimitiveKind::String32: {
1899
+ const char32_t *str32;
1900
+ if (!call.PushString32(value, 1, &str32)) [[unlikely]]
1901
+ return false;
1902
+ *(const char32_t **)origin = str32;
1903
+ } break;
1904
+ case PrimitiveKind::Pointer: {
1905
+ void *ptr;
1906
+ if (!call.PushPointer(value, type, 1, &ptr)) [[unlikely]]
1907
+ return false;
1908
+ *(void **)origin = ptr;
1909
+ } break;
1910
+ case PrimitiveKind::Record:
1911
+ case PrimitiveKind::Union: {
1912
+ if (!IsObject(env, value)) [[unlikely]] {
1913
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
1914
+ return false;
1915
+ }
1916
+
1917
+ if (!call.PushObject(value, type, origin))
1918
+ return false;
1919
+ } break;
1920
+ case PrimitiveKind::Array: {
1921
+ if (IsArray(env, value)) {
1922
+ Napi::Array array = Napi::Array(env, value);
1923
+ if (!call.PushNormalArray(array, type, type->size, origin))
1924
+ return false;
1925
+ } else if (Span<uint8_t> buffer = {}; TryBuffer(env, value, &buffer)) {
1926
+ call.PushBuffer(buffer, type, origin);
1927
+ } else if (GetKindOf(env, value) == napi_string) {
1928
+ if (!call.PushStringArray(value, type, origin))
1929
+ return false;
1930
+ } else {
1931
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected array", GetValueType(instance, value));
1932
+ return false;
1933
+ }
1934
+ } break;
1935
+ case PrimitiveKind::Float32: {
1936
+ float f;
1937
+ if (!TryNumber(env, value, &f)) [[unlikely]] {
1938
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
1939
+ return false;
1940
+ }
1941
+
1942
+ memcpy(origin, &f, 4);
1943
+ } break;
1944
+ case PrimitiveKind::Float64: {
1945
+ double d;
1946
+ if (!TryNumber(env, value, &d)) [[unlikely]] {
1947
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
1948
+ return false;
1949
+ }
1950
+
1951
+ memcpy(origin, &d, 8);
1952
+ } break;
1953
+ case PrimitiveKind::Callback: {
1954
+ void *ptr;
1955
+ if (!TryPointer(env, value, &ptr)) [[unlikely]] {
1956
+ if (GetKindOf(env, value) == napi_function) {
1957
+ ThrowError<Napi::Error>(env, "Cannot encode non-registered callback");
1958
+ } else {
1959
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
1960
+ }
1961
+ return false;
1962
+ }
1963
+
1964
+ *(void **)origin = ptr;
1965
+ } break;
1966
+
1967
+ case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
1968
+ }
1969
+
1970
+ #undef PUSH_INTEGER_SWAP
1971
+ #undef PUSH_INTEGER
1972
+
1973
+ // Keep memory around if any was allocated
1974
+ if (mem.allocator.IsUsed()) {
1975
+ LinkedAllocator *copy = instance->encode_map.FindValue(origin, nullptr);
1976
+
1977
+ if (!copy) {
1978
+ copy = instance->encode_allocators.AppendDefault();
1979
+ instance->encode_map.Set(origin, copy);
1980
+ }
1981
+
1982
+ std::swap(mem.allocator, *copy);
1983
+ }
1984
+
1985
+ return true;
1986
+ }
1987
+
1877
1988
  }
@@ -21,7 +21,6 @@ struct alignas(8) CallData {
21
21
  struct OutArgument {
22
22
  enum class Kind {
23
23
  Array,
24
- Buffer,
25
24
  String,
26
25
  String16,
27
26
  String32,
@@ -180,4 +179,6 @@ void PerformAsyncRelay(napi_env env, napi_value callback, void *ctx, void *udata
180
179
 
181
180
  void *GetTrampoline(int idx);
182
181
 
182
+ bool Encode(InstanceData *instance, uint8_t *ptr, napi_value value, const TypeInfo *type);
183
+
183
184
  }