koffi 2.1.5 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/ChangeLog.md +21 -1
  2. package/doc/Makefile +1 -1
  3. package/doc/callbacks.md +175 -0
  4. package/doc/changes.md +2 -3
  5. package/doc/conf.py +29 -6
  6. package/doc/functions.md +39 -124
  7. package/doc/index.rst +1 -0
  8. package/doc/make.bat +1 -1
  9. package/doc/types.md +36 -9
  10. package/package.json +2 -2
  11. package/src/core/libcc/libcc.cc +89 -27
  12. package/src/core/libcc/libcc.hh +74 -39
  13. package/src/koffi/build/2.2.1/koffi_darwin_arm64.tar.gz +0 -0
  14. package/src/koffi/build/2.2.1/koffi_darwin_x64.tar.gz +0 -0
  15. package/src/koffi/build/2.2.1/koffi_freebsd_arm64.tar.gz +0 -0
  16. package/src/koffi/build/2.2.1/koffi_freebsd_ia32.tar.gz +0 -0
  17. package/src/koffi/build/2.2.1/koffi_freebsd_x64.tar.gz +0 -0
  18. package/src/koffi/build/2.2.1/koffi_linux_arm32hf.tar.gz +0 -0
  19. package/src/koffi/build/2.2.1/koffi_linux_arm64.tar.gz +0 -0
  20. package/src/koffi/build/2.2.1/koffi_linux_ia32.tar.gz +0 -0
  21. package/src/koffi/build/2.2.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  22. package/src/koffi/build/2.2.1/koffi_linux_x64.tar.gz +0 -0
  23. package/src/koffi/build/2.2.1/koffi_openbsd_ia32.tar.gz +0 -0
  24. package/src/koffi/build/2.2.1/koffi_openbsd_x64.tar.gz +0 -0
  25. package/src/koffi/build/2.2.1/koffi_win32_arm64.tar.gz +0 -0
  26. package/src/koffi/build/2.2.1/koffi_win32_ia32.tar.gz +0 -0
  27. package/src/koffi/build/2.2.1/koffi_win32_x64.tar.gz +0 -0
  28. package/src/koffi/qemu/qemu.js +3 -1
  29. package/src/koffi/src/abi_arm32.cc +26 -23
  30. package/src/koffi/src/abi_arm64.cc +25 -22
  31. package/src/koffi/src/abi_riscv64.cc +21 -18
  32. package/src/koffi/src/abi_x64_sysv.cc +20 -17
  33. package/src/koffi/src/abi_x64_win.cc +19 -16
  34. package/src/koffi/src/abi_x86.cc +23 -20
  35. package/src/koffi/src/call.cc +222 -607
  36. package/src/koffi/src/call.hh +7 -11
  37. package/src/koffi/src/ffi.cc +229 -29
  38. package/src/koffi/src/ffi.hh +6 -2
  39. package/src/koffi/src/parser.cc +3 -9
  40. package/src/koffi/src/util.cc +546 -8
  41. package/src/koffi/src/util.hh +8 -2
  42. package/src/koffi/test/CMakeLists.txt +3 -3
  43. package/src/koffi/test/callbacks.js +89 -0
  44. package/src/koffi/test/misc.c +78 -0
  45. package/src/koffi/test/raylib.js +2 -2
  46. package/src/koffi/test/sqlite.js +1 -1
  47. package/src/koffi/test/sync.js +28 -6
  48. package/vendor/brotli/c/common/platform.h +2 -0
  49. package/vendor/sqlite3mc/sqlite3.c +243532 -0
  50. package/vendor/sqlite3mc/sqlite3.h +12887 -0
  51. package/src/koffi/build/2.1.5/koffi_darwin_arm64.tar.gz +0 -0
  52. package/src/koffi/build/2.1.5/koffi_darwin_x64.tar.gz +0 -0
  53. package/src/koffi/build/2.1.5/koffi_freebsd_arm64.tar.gz +0 -0
  54. package/src/koffi/build/2.1.5/koffi_freebsd_ia32.tar.gz +0 -0
  55. package/src/koffi/build/2.1.5/koffi_freebsd_x64.tar.gz +0 -0
  56. package/src/koffi/build/2.1.5/koffi_linux_arm32hf.tar.gz +0 -0
  57. package/src/koffi/build/2.1.5/koffi_linux_arm64.tar.gz +0 -0
  58. package/src/koffi/build/2.1.5/koffi_linux_ia32.tar.gz +0 -0
  59. package/src/koffi/build/2.1.5/koffi_linux_riscv64hf64.tar.gz +0 -0
  60. package/src/koffi/build/2.1.5/koffi_linux_x64.tar.gz +0 -0
  61. package/src/koffi/build/2.1.5/koffi_openbsd_ia32.tar.gz +0 -0
  62. package/src/koffi/build/2.1.5/koffi_openbsd_x64.tar.gz +0 -0
  63. package/src/koffi/build/2.1.5/koffi_win32_arm64.tar.gz +0 -0
  64. package/src/koffi/build/2.1.5/koffi_win32_ia32.tar.gz +0 -0
  65. package/src/koffi/build/2.1.5/koffi_win32_x64.tar.gz +0 -0
@@ -46,40 +46,71 @@ CallData::~CallData()
46
46
  if (!--mem->depth && mem->temporary) {
47
47
  delete mem;
48
48
  }
49
+
50
+ instance = nullptr;
49
51
  }
50
52
 
51
- bool CallData::PushString(Napi::Value value, const char **out_str)
53
+ bool CallData::PushString(Napi::Value value, int directions, const char **out_str)
52
54
  {
53
55
  if (value.IsString()) {
54
- Span<char> buf;
55
- size_t len = 0;
56
- napi_status status;
56
+ if (RG_UNLIKELY(directions & 2)) {
57
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
58
+ return false;
59
+ }
57
60
 
58
- buf.ptr = (char *)mem->heap.ptr;
59
- buf.len = std::max((Size)0, mem->heap.len - Kibibytes(32));
61
+ PushStringValue(value, out_str);
62
+ return true;
63
+ } else if (IsNullOrUndefined(value)) {
64
+ *out_str = nullptr;
65
+ return true;
66
+ } else if (value.IsArray()) {
67
+ Napi::Array array = value.As<Napi::Array>();
60
68
 
61
- status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
62
- RG_ASSERT(status == napi_ok);
69
+ if (RG_UNLIKELY(!(directions & 2))) {
70
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
71
+ return false;
72
+ }
73
+ if (RG_UNLIKELY(array.Length() != 1)) {
74
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, value));
75
+ return false;
76
+ }
63
77
 
64
- len++;
78
+ value = array[0u];
65
79
 
66
- if (RG_LIKELY(len < (size_t)buf.len)) {
67
- mem->heap.ptr += (Size)len;
68
- mem->heap.len -= (Size)len;
69
- } else {
70
- status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
71
- RG_ASSERT(status == napi_ok);
80
+ if (RG_UNLIKELY(!value.IsString())) {
81
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, array[0u]));
82
+ return false;
83
+ }
84
+
85
+ Size len = PushStringValue(value, out_str);
86
+ if (RG_UNLIKELY(len < 0))
87
+ return false;
88
+
89
+ // Create array type
90
+ TypeInfo *type;
91
+ {
92
+ type = AllocateOne<TypeInfo>(&call_alloc, (int)AllocFlag::Zero);
93
+
94
+ type->name = "<temporary>";
72
95
 
73
- buf = AllocateSpan<char>(&call_alloc, (Size)len + 1);
96
+ type->primitive = PrimitiveKind::Array;
97
+ type->align = 1;
98
+ type->size = (int32_t)len;
99
+ type->ref.type = instance->char_type;
100
+ type->hint = TypeInfo::ArrayHint::String;
101
+ }
102
+
103
+ // Prepare output argument
104
+ {
105
+ OutArgument *out = out_arguments.AppendDefault();
74
106
 
75
- status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
107
+ napi_status status = napi_create_reference(env, array, 1, &out->ref);
76
108
  RG_ASSERT(status == napi_ok);
109
+
110
+ out->ptr = (const uint8_t *)*out_str;
111
+ out->type = type;
77
112
  }
78
113
 
79
- *out_str = buf.ptr;
80
- return true;
81
- } else if (IsNullOrUndefined(value)) {
82
- *out_str = nullptr;
83
114
  return true;
84
115
  } else {
85
116
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
@@ -87,38 +118,100 @@ bool CallData::PushString(Napi::Value value, const char **out_str)
87
118
  }
88
119
  }
89
120
 
90
- bool CallData::PushString16(Napi::Value value, const char16_t **out_str16)
121
+ Size CallData::PushStringValue(Napi::Value value, const char **out_str)
91
122
  {
92
- if (value.IsString()) {
93
- Span<char16_t> buf;
94
- size_t len = 0;
95
- napi_status status;
123
+ Span<char> buf;
124
+ size_t len = 0;
125
+ napi_status status;
96
126
 
97
- buf.ptr = (char16_t *)mem->heap.ptr;
98
- buf.len = std::max((Size)0, mem->heap.len - Kibibytes(32)) / 2;
127
+ buf.ptr = (char *)mem->heap.ptr;
128
+ buf.len = std::max((Size)0, mem->heap.len - Kibibytes(32));
99
129
 
100
- status = napi_get_value_string_utf16(env, value, buf.ptr, (size_t)buf.len, &len);
130
+ status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
131
+ RG_ASSERT(status == napi_ok);
132
+
133
+ len++;
134
+
135
+ if (RG_LIKELY(len < (size_t)buf.len)) {
136
+ mem->heap.ptr += (Size)len;
137
+ mem->heap.len -= (Size)len;
138
+ } else {
139
+ status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
101
140
  RG_ASSERT(status == napi_ok);
102
141
 
103
- len++;
142
+ buf = AllocateSpan<char>(&call_alloc, (Size)len + 1);
104
143
 
105
- if (RG_LIKELY(len < (size_t)buf.len)) {
106
- mem->heap.ptr += (Size)len * 2;
107
- mem->heap.len -= (Size)len * 2;
108
- } else {
109
- status = napi_get_value_string_utf16(env, value, nullptr, 0, &len);
110
- RG_ASSERT(status == napi_ok);
144
+ status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
145
+ RG_ASSERT(status == napi_ok);
111
146
 
112
- buf = AllocateSpan<char16_t>(&call_alloc, ((Size)len + 1) * 2);
147
+ len++;
148
+ }
113
149
 
114
- status = napi_get_value_string_utf16(env, value, buf.ptr, (size_t)buf.len, &len);
115
- RG_ASSERT(status == napi_ok);
150
+ *out_str = buf.ptr;
151
+ return (Size)len;
152
+ }
153
+
154
+ bool CallData::PushString16(Napi::Value value, int directions, const char16_t **out_str16)
155
+ {
156
+ if (value.IsString()) {
157
+ if (RG_UNLIKELY(directions & 2)) {
158
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
159
+ return false;
116
160
  }
117
161
 
118
- *out_str16 = buf.ptr;
162
+ PushString16Value(value, out_str16);
119
163
  return true;
120
164
  } else if (IsNullOrUndefined(value)) {
121
165
  *out_str16 = nullptr;
166
+ return true;
167
+ } else if (value.IsArray()) {
168
+ Napi::Array array = value.As<Napi::Array>();
169
+
170
+ if (RG_UNLIKELY(!(directions & 2))) {
171
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
172
+ return false;
173
+ }
174
+ if (RG_UNLIKELY(array.Length() != 1)) {
175
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, value));
176
+ return false;
177
+ }
178
+
179
+ value = array[0u];
180
+
181
+ if (RG_UNLIKELY(!value.IsString())) {
182
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected [string]", GetValueType(instance, array[0u]));
183
+ return false;
184
+ }
185
+
186
+ Size len = PushString16Value(value, out_str16);
187
+ if (RG_UNLIKELY(len < 0))
188
+ return false;
189
+
190
+ // Create array type
191
+ TypeInfo *type;
192
+ {
193
+ type = AllocateOne<TypeInfo>(&call_alloc, (int)AllocFlag::Zero);
194
+
195
+ type->name = "<temporary>";
196
+
197
+ type->primitive = PrimitiveKind::Array;
198
+ type->align = 1;
199
+ type->size = (int32_t)(len * 2);
200
+ type->ref.type = instance->char16_type;
201
+ type->hint = TypeInfo::ArrayHint::String;
202
+ }
203
+
204
+ // Prepare output argument
205
+ {
206
+ OutArgument *out = out_arguments.AppendDefault();
207
+
208
+ napi_status status = napi_create_reference(env, array, 1, &out->ref);
209
+ RG_ASSERT(status == napi_ok);
210
+
211
+ out->ptr = (const uint8_t *)*out_str16;
212
+ out->type = type;
213
+ }
214
+
122
215
  return true;
123
216
  } else {
124
217
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected string", GetValueType(instance, value));
@@ -126,6 +219,39 @@ bool CallData::PushString16(Napi::Value value, const char16_t **out_str16)
126
219
  }
127
220
  }
128
221
 
222
+ Size CallData::PushString16Value(Napi::Value value, const char16_t **out_str16)
223
+ {
224
+ Span<char16_t> buf;
225
+ size_t len = 0;
226
+ napi_status status;
227
+
228
+ buf.ptr = (char16_t *)mem->heap.ptr;
229
+ buf.len = std::max((Size)0, mem->heap.len - Kibibytes(32)) / 2;
230
+
231
+ status = napi_get_value_string_utf16(env, value, buf.ptr, (size_t)buf.len, &len);
232
+ RG_ASSERT(status == napi_ok);
233
+
234
+ len++;
235
+
236
+ if (RG_LIKELY(len < (size_t)buf.len)) {
237
+ mem->heap.ptr += (Size)len * 2;
238
+ mem->heap.len -= (Size)len * 2;
239
+ } else {
240
+ status = napi_get_value_string_utf16(env, value, nullptr, 0, &len);
241
+ RG_ASSERT(status == napi_ok);
242
+
243
+ buf = AllocateSpan<char16_t>(&call_alloc, ((Size)len + 1) * 2);
244
+
245
+ status = napi_get_value_string_utf16(env, value, buf.ptr, (size_t)buf.len, &len);
246
+ RG_ASSERT(status == napi_ok);
247
+
248
+ len++;
249
+ }
250
+
251
+ *out_str16 = buf.ptr;
252
+ return (Size)len;
253
+ }
254
+
129
255
  bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origin, int16_t realign)
130
256
  {
131
257
  RG_ASSERT(IsObject(obj));
@@ -161,7 +287,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
161
287
  return false;
162
288
  }
163
289
 
164
- int8_t v = CopyNumber<int8_t>(value);
290
+ int8_t v = GetNumber<int8_t>(value);
165
291
  *(int8_t *)dest = v;
166
292
  } break;
167
293
  case PrimitiveKind::UInt8: {
@@ -170,7 +296,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
170
296
  return false;
171
297
  }
172
298
 
173
- uint8_t v = CopyNumber<uint8_t>(value);
299
+ uint8_t v = GetNumber<uint8_t>(value);
174
300
  *(uint8_t *)dest = v;
175
301
  } break;
176
302
  case PrimitiveKind::Int16: {
@@ -179,7 +305,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
179
305
  return false;
180
306
  }
181
307
 
182
- int16_t v = CopyNumber<int16_t>(value);
308
+ int16_t v = GetNumber<int16_t>(value);
183
309
  *(int16_t *)dest = v;
184
310
  } break;
185
311
  case PrimitiveKind::Int16S: {
@@ -188,7 +314,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
188
314
  return false;
189
315
  }
190
316
 
191
- int16_t v = CopyNumber<int16_t>(value);
317
+ int16_t v = GetNumber<int16_t>(value);
192
318
  *(int16_t *)dest = ReverseBytes(v);
193
319
  } break;
194
320
  case PrimitiveKind::UInt16: {
@@ -197,7 +323,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
197
323
  return false;
198
324
  }
199
325
 
200
- uint16_t v = CopyNumber<uint16_t>(value);
326
+ uint16_t v = GetNumber<uint16_t>(value);
201
327
  *(uint16_t *)dest = v;
202
328
  } break;
203
329
  case PrimitiveKind::UInt16S: {
@@ -206,7 +332,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
206
332
  return false;
207
333
  }
208
334
 
209
- uint16_t v = CopyNumber<uint16_t>(value);
335
+ uint16_t v = GetNumber<uint16_t>(value);
210
336
  *(uint16_t *)dest = ReverseBytes(v);
211
337
  } break;
212
338
  case PrimitiveKind::Int32: {
@@ -215,7 +341,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
215
341
  return false;
216
342
  }
217
343
 
218
- int32_t v = CopyNumber<int32_t>(value);
344
+ int32_t v = GetNumber<int32_t>(value);
219
345
  *(int32_t *)dest = v;
220
346
  } break;
221
347
  case PrimitiveKind::Int32S: {
@@ -224,7 +350,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
224
350
  return false;
225
351
  }
226
352
 
227
- int32_t v = CopyNumber<int32_t>(value);
353
+ int32_t v = GetNumber<int32_t>(value);
228
354
  *(int32_t *)dest = ReverseBytes(v);
229
355
  } break;
230
356
  case PrimitiveKind::UInt32: {
@@ -233,7 +359,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
233
359
  return false;
234
360
  }
235
361
 
236
- uint32_t v = CopyNumber<uint32_t>(value);
362
+ uint32_t v = GetNumber<uint32_t>(value);
237
363
  *(uint32_t *)dest = v;
238
364
  } break;
239
365
  case PrimitiveKind::UInt32S: {
@@ -242,7 +368,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
242
368
  return false;
243
369
  }
244
370
 
245
- uint32_t v = CopyNumber<uint32_t>(value);
371
+ uint32_t v = GetNumber<uint32_t>(value);
246
372
  *(uint32_t *)dest = ReverseBytes(v);
247
373
  } break;
248
374
  case PrimitiveKind::Int64: {
@@ -251,7 +377,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
251
377
  return false;
252
378
  }
253
379
 
254
- int64_t v = CopyNumber<int64_t>(value);
380
+ int64_t v = GetNumber<int64_t>(value);
255
381
  *(int64_t *)dest = v;
256
382
  } break;
257
383
  case PrimitiveKind::Int64S: {
@@ -260,7 +386,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
260
386
  return false;
261
387
  }
262
388
 
263
- int64_t v = CopyNumber<int64_t>(value);
389
+ int64_t v = GetNumber<int64_t>(value);
264
390
  *(int64_t *)dest = ReverseBytes(v);
265
391
  } break;
266
392
  case PrimitiveKind::UInt64: {
@@ -269,7 +395,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
269
395
  return false;
270
396
  }
271
397
 
272
- uint64_t v = CopyNumber<uint64_t>(value);
398
+ uint64_t v = GetNumber<uint64_t>(value);
273
399
  *(uint64_t *)dest = v;
274
400
  } break;
275
401
  case PrimitiveKind::UInt64S: {
@@ -278,19 +404,19 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
278
404
  return false;
279
405
  }
280
406
 
281
- uint64_t v = CopyNumber<uint64_t>(value);
407
+ uint64_t v = GetNumber<uint64_t>(value);
282
408
  *(uint64_t *)dest = ReverseBytes(v);
283
409
  } break;
284
410
  case PrimitiveKind::String: {
285
411
  const char *str;
286
- if (RG_UNLIKELY(!PushString(value, &str)))
412
+ if (RG_UNLIKELY(!PushString(value, 1, &str)))
287
413
  return false;
288
414
 
289
415
  *(const char **)dest = str;
290
416
  } break;
291
417
  case PrimitiveKind::String16: {
292
418
  const char16_t *str16;
293
- if (RG_UNLIKELY(!PushString16(value, &str16)))
419
+ if (RG_UNLIKELY(!PushString16(value, 1, &str16)))
294
420
  return false;
295
421
 
296
422
  *(const char16_t **)dest = str16;
@@ -317,13 +443,13 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
317
443
  Napi::Array array = value.As<Napi::Array>();
318
444
  Size len = (Size)member.type->size / member.type->ref.type->size;
319
445
 
320
- if (!PushNormalArray(array, len, member.type->ref.type, dest, realign))
446
+ if (!PushNormalArray(array, len, member.type, dest, realign))
321
447
  return false;
322
448
  } else if (value.IsTypedArray()) {
323
449
  Napi::TypedArray array = value.As<Napi::TypedArray>();
324
450
  Size len = (Size)member.type->size / member.type->ref.type->size;
325
451
 
326
- if (!PushTypedArray(array, len, member.type->ref.type, dest, realign))
452
+ if (!PushTypedArray(array, len, member.type, dest, realign))
327
453
  return false;
328
454
  } else if (value.IsString() && !realign) {
329
455
  if (!PushStringArray(value, member.type, dest))
@@ -339,7 +465,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
339
465
  return false;
340
466
  }
341
467
 
342
- float f = CopyNumber<float>(value);
468
+ float f = GetNumber<float>(value);
343
469
  *(float *)dest = f;
344
470
  } break;
345
471
  case PrimitiveKind::Float64: {
@@ -348,7 +474,7 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
348
474
  return false;
349
475
  }
350
476
 
351
- double d = CopyNumber<double>(value);
477
+ double d = GetNumber<double>(value);
352
478
  *(double *)dest = d;
353
479
  } break;
354
480
  case PrimitiveKind::Callback: {
@@ -380,10 +506,12 @@ bool CallData::PushObject(Napi::Object obj, const TypeInfo *type, uint8_t *origi
380
506
  return true;
381
507
  }
382
508
 
383
- bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref, uint8_t *origin, int16_t realign)
509
+ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *type, uint8_t *origin, int16_t realign)
384
510
  {
385
511
  RG_ASSERT(array.IsArray());
386
512
 
513
+ const TypeInfo *ref = type->ref.type;
514
+
387
515
  if (RG_UNLIKELY(array.Length() != (size_t)len)) {
388
516
  ThrowError<Napi::Error>(env, "Expected array of length %1, got %2", len, array.Length());
389
517
  return false;
@@ -413,7 +541,10 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref,
413
541
  } while (false)
414
542
 
415
543
  switch (ref->primitive) {
416
- case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
544
+ case PrimitiveKind::Void: {
545
+ ThrowError<Napi::TypeError>(env, "Ambigous parameter type %1, use koffi.as(value, type)", type->name); \
546
+ return false;
547
+ } break;
417
548
 
418
549
  case PrimitiveKind::Bool: {
419
550
  PUSH_ARRAY(value.IsBoolean(), "boolean", {
@@ -423,92 +554,92 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref,
423
554
  } break;
424
555
  case PrimitiveKind::Int8: {
425
556
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
426
- int8_t v = CopyNumber<int8_t>(value);
557
+ int8_t v = GetNumber<int8_t>(value);
427
558
  *(int8_t *)dest = v;
428
559
  });
429
560
  } break;
430
561
  case PrimitiveKind::UInt8: {
431
562
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
432
- uint8_t v = CopyNumber<uint8_t>(value);
563
+ uint8_t v = GetNumber<uint8_t>(value);
433
564
  *(uint8_t *)dest = v;
434
565
  });
435
566
  } break;
436
567
  case PrimitiveKind::Int16: {
437
568
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
438
- int16_t v = CopyNumber<int16_t>(value);
569
+ int16_t v = GetNumber<int16_t>(value);
439
570
  *(int16_t *)dest = v;
440
571
  });
441
572
  } break;
442
573
  case PrimitiveKind::Int16S: {
443
574
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
444
- int16_t v = CopyNumber<int16_t>(value);
575
+ int16_t v = GetNumber<int16_t>(value);
445
576
  *(int16_t *)dest = ReverseBytes(v);
446
577
  });
447
578
  } break;
448
579
  case PrimitiveKind::UInt16: {
449
580
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
450
- uint16_t v = CopyNumber<uint16_t>(value);
581
+ uint16_t v = GetNumber<uint16_t>(value);
451
582
  *(uint16_t *)dest = v;
452
583
  });
453
584
  } break;
454
585
  case PrimitiveKind::UInt16S: {
455
586
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
456
- uint16_t v = CopyNumber<uint16_t>(value);
587
+ uint16_t v = GetNumber<uint16_t>(value);
457
588
  *(uint16_t *)dest = ReverseBytes(v);
458
589
  });
459
590
  } break;
460
591
  case PrimitiveKind::Int32: {
461
592
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
462
- int32_t v = CopyNumber<int32_t>(value);
593
+ int32_t v = GetNumber<int32_t>(value);
463
594
  *(int32_t *)dest = v;
464
595
  });
465
596
  } break;
466
597
  case PrimitiveKind::Int32S: {
467
598
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
468
- int32_t v = CopyNumber<int32_t>(value);
599
+ int32_t v = GetNumber<int32_t>(value);
469
600
  *(int32_t *)dest = ReverseBytes(v);
470
601
  });
471
602
  } break;
472
603
  case PrimitiveKind::UInt32: {
473
604
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
474
- uint32_t v = CopyNumber<uint32_t>(value);
605
+ uint32_t v = GetNumber<uint32_t>(value);
475
606
  *(uint32_t *)dest = v;
476
607
  });
477
608
  } break;
478
609
  case PrimitiveKind::UInt32S: {
479
610
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
480
- uint32_t v = CopyNumber<uint32_t>(value);
611
+ uint32_t v = GetNumber<uint32_t>(value);
481
612
  *(uint32_t *)dest = ReverseBytes(v);
482
613
  });
483
614
  } break;
484
615
  case PrimitiveKind::Int64: {
485
616
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
486
- int64_t v = CopyNumber<int64_t>(value);
617
+ int64_t v = GetNumber<int64_t>(value);
487
618
  *(int64_t *)dest = v;
488
619
  });
489
620
  } break;
490
621
  case PrimitiveKind::Int64S: {
491
622
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
492
- int64_t v = CopyNumber<int64_t>(value);
623
+ int64_t v = GetNumber<int64_t>(value);
493
624
  *(int64_t *)dest = ReverseBytes(v);
494
625
  });
495
626
  } break;
496
627
  case PrimitiveKind::UInt64: {
497
628
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
498
- uint64_t v = CopyNumber<uint64_t>(value);
629
+ uint64_t v = GetNumber<uint64_t>(value);
499
630
  *(uint64_t *)dest = v;
500
631
  });
501
632
  } break;
502
633
  case PrimitiveKind::UInt64S: {
503
634
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
504
- uint64_t v = CopyNumber<uint64_t>(value);
635
+ uint64_t v = GetNumber<uint64_t>(value);
505
636
  *(uint64_t *)dest = ReverseBytes(v);
506
637
  });
507
638
  } break;
508
639
  case PrimitiveKind::String: {
509
640
  PUSH_ARRAY(true, "string", {
510
641
  const char *str;
511
- if (RG_UNLIKELY(!PushString(value, &str)))
642
+ if (RG_UNLIKELY(!PushString(value, 1, &str)))
512
643
  return false;
513
644
 
514
645
  *(const char **)dest = str;
@@ -517,7 +648,7 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref,
517
648
  case PrimitiveKind::String16: {
518
649
  PUSH_ARRAY(true, "string", {
519
650
  const char16_t *str16;
520
- if (RG_UNLIKELY(!PushString16(value, &str16)))
651
+ if (RG_UNLIKELY(!PushString16(value, 1, &str16)))
521
652
  return false;
522
653
 
523
654
  *(const char16_t **)dest = str16;
@@ -552,13 +683,13 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref,
552
683
  Napi::Array array2 = value.As<Napi::Array>();
553
684
  Size len2 = (Size)ref->size / ref->ref.type->size;
554
685
 
555
- if (!PushNormalArray(array2, len2, ref->ref.type, dest, realign))
686
+ if (!PushNormalArray(array2, len2, ref, dest, realign))
556
687
  return false;
557
688
  } else if (value.IsTypedArray()) {
558
689
  Napi::TypedArray array2 = value.As<Napi::TypedArray>();
559
690
  Size len2 = (Size)ref->size / ref->ref.type->size;
560
691
 
561
- if (!PushTypedArray(array2, len2, ref->ref.type, dest, realign))
692
+ if (!PushTypedArray(array2, len2, ref, dest, realign))
562
693
  return false;
563
694
  } else if (value.IsString() && !realign) {
564
695
  if (!PushStringArray(value, ref, dest))
@@ -573,13 +704,13 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref,
573
704
  } break;
574
705
  case PrimitiveKind::Float32: {
575
706
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
576
- float f = CopyNumber<float>(value);
707
+ float f = GetNumber<float>(value);
577
708
  *(float *)dest = f;
578
709
  });
579
710
  } break;
580
711
  case PrimitiveKind::Float64: {
581
712
  PUSH_ARRAY(value.IsNumber() || value.IsBigInt(), "number", {
582
- double d = CopyNumber<double>(value);
713
+ double d = GetNumber<double>(value);
583
714
  *(double *)dest = d;
584
715
  });
585
716
  } break;
@@ -624,10 +755,12 @@ bool CallData::PushNormalArray(Napi::Array array, Size len, const TypeInfo *ref,
624
755
  return true;
625
756
  }
626
757
 
627
- bool CallData::PushTypedArray(Napi::TypedArray array, Size len, const TypeInfo *ref, uint8_t *origin, int16_t realign)
758
+ bool CallData::PushTypedArray(Napi::TypedArray array, Size len, const TypeInfo *type, uint8_t *origin, int16_t realign)
628
759
  {
629
760
  RG_ASSERT(array.IsTypedArray());
630
761
 
762
+ const TypeInfo *ref = type->ref.type;
763
+
631
764
  if (RG_UNLIKELY(array.ElementLength() != (size_t)len)) {
632
765
  ThrowError<Napi::Error>(env, "Expected array of length %1, got %2", len, array.ElementLength());
633
766
  return false;
@@ -732,7 +865,7 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
732
865
  ptr = AllocHeap(size, 16);
733
866
 
734
867
  if (directions & 1) {
735
- if (!PushNormalArray(array, len, type->ref.type, ptr))
868
+ if (!PushNormalArray(array, len, type, ptr))
736
869
  return false;
737
870
  } else {
738
871
  memset(ptr, 0, size);
@@ -746,7 +879,7 @@ bool CallData::PushPointer(Napi::Value value, const TypeInfo *type, int directio
746
879
  ptr = AllocHeap(size, 16);
747
880
 
748
881
  if (directions & 1) {
749
- if (!PushTypedArray(array, len, type->ref.type, ptr))
882
+ if (!PushTypedArray(array, len, type, ptr))
750
883
  return false;
751
884
  } else {
752
885
  if (RG_UNLIKELY(array.TypedArrayType() != GetTypedArrayType(type->ref.type) &&
@@ -813,13 +946,13 @@ void CallData::PopOutArguments()
813
946
 
814
947
  if (value.IsArray()) {
815
948
  Napi::Array array(env, value);
816
- PopNormalArray(array, out.ptr, out.type);
949
+ DecodeNormalArray(array, out.ptr, out.type);
817
950
  } else if (value.IsTypedArray()) {
818
951
  Napi::TypedArray array(env, value);
819
- PopTypedArray(array, out.ptr, out.type);
952
+ DecodeTypedArray(array, out.ptr, out.type);
820
953
  } else {
821
954
  Napi::Object obj(env, value);
822
- PopObject(obj, out.ptr, out.type);
955
+ DecodeObject(obj, out.ptr, out.type);
823
956
  }
824
957
 
825
958
  if (out.type->dispose) {
@@ -845,531 +978,13 @@ void *CallData::ReserveTrampoline(const FunctionInfo *proto, Napi::Function func
845
978
 
846
979
  trampoline->proto = proto;
847
980
  trampoline->func.Reset(func, 1);
981
+ trampoline->recv.Reset();
848
982
  trampoline->generation = (int32_t)mem->generation;
849
983
 
850
984
  void *ptr = GetTrampoline(idx, proto);
851
985
  return ptr;
852
986
  }
853
987
 
854
- void CallData::PopObject(Napi::Object obj, const uint8_t *origin, const TypeInfo *type, int16_t realign)
855
- {
856
- Napi::Env env = obj.Env();
857
- InstanceData *instance = env.GetInstanceData<InstanceData>();
858
-
859
- RG_ASSERT(type->primitive == PrimitiveKind::Record);
860
-
861
- for (Size i = 0; i < type->members.len; i++) {
862
- const RecordMember &member = type->members[i];
863
-
864
- Size offset = realign ? (i * realign) : member.offset;
865
- const uint8_t *src = origin + offset;
866
-
867
- switch (member.type->primitive) {
868
- case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
869
-
870
- case PrimitiveKind::Bool: {
871
- bool b = *(bool *)src;
872
- obj.Set(member.name, Napi::Boolean::New(env, b));
873
- } break;
874
- case PrimitiveKind::Int8: {
875
- double d = (double)*(int8_t *)src;
876
- obj.Set(member.name, Napi::Number::New(env, d));
877
- } break;
878
- case PrimitiveKind::UInt8: {
879
- double d = (double)*(uint8_t *)src;
880
- obj.Set(member.name, Napi::Number::New(env, d));
881
- } break;
882
- case PrimitiveKind::Int16: {
883
- double d = (double)*(int16_t *)src;
884
- obj.Set(member.name, Napi::Number::New(env, d));
885
- } break;
886
- case PrimitiveKind::Int16S: {
887
- int16_t v = *(int16_t *)src;
888
- double d = (double)ReverseBytes(v);
889
-
890
- obj.Set(member.name, Napi::Number::New(env, d));
891
- } break;
892
- case PrimitiveKind::UInt16: {
893
- double d = (double)*(uint16_t *)src;
894
- obj.Set(member.name, Napi::Number::New(env, d));
895
- } break;
896
- case PrimitiveKind::UInt16S: {
897
- uint16_t v = *(uint16_t *)src;
898
- double d = (double)ReverseBytes(v);
899
-
900
- obj.Set(member.name, Napi::Number::New(env, d));
901
- } break;
902
- case PrimitiveKind::Int32: {
903
- double d = (double)*(int32_t *)src;
904
- obj.Set(member.name, Napi::Number::New(env, d));
905
- } break;
906
- case PrimitiveKind::Int32S: {
907
- int32_t v = *(int32_t *)src;
908
- double d = (double)ReverseBytes(v);
909
-
910
- obj.Set(member.name, Napi::Number::New(env, d));
911
- } break;
912
- case PrimitiveKind::UInt32: {
913
- double d = (double)*(uint32_t *)src;
914
- obj.Set(member.name, Napi::Number::New(env, d));
915
- } break;
916
- case PrimitiveKind::UInt32S: {
917
- uint32_t v = *(uint32_t *)src;
918
- double d = (double)ReverseBytes(v);
919
-
920
- obj.Set(member.name, Napi::Number::New(env, d));
921
- } break;
922
- case PrimitiveKind::Int64: {
923
- int64_t v = *(int64_t *)src;
924
- obj.Set(member.name, NewBigInt(env, v));
925
- } break;
926
- case PrimitiveKind::Int64S: {
927
- int64_t v = ReverseBytes(*(int64_t *)src);
928
- obj.Set(member.name, NewBigInt(env, v));
929
- } break;
930
- case PrimitiveKind::UInt64: {
931
- uint64_t v = *(uint64_t *)src;
932
- obj.Set(member.name, NewBigInt(env, v));
933
- } break;
934
- case PrimitiveKind::UInt64S: {
935
- uint64_t v = ReverseBytes(*(uint64_t *)src);
936
- obj.Set(member.name, NewBigInt(env, v));
937
- } break;
938
- case PrimitiveKind::String: {
939
- const char *str = *(const char **)src;
940
- obj.Set(member.name, str ? Napi::String::New(env, str) : env.Null());
941
-
942
- if (member.type->dispose) {
943
- member.type->dispose(env, member.type, str);
944
- }
945
- } break;
946
- case PrimitiveKind::String16: {
947
- const char16_t *str16 = *(const char16_t **)src;
948
- obj.Set(member.name, str16 ? Napi::String::New(env, str16) : env.Null());
949
-
950
- if (member.type->dispose) {
951
- member.type->dispose(env, member.type, str16);
952
- }
953
- } break;
954
- case PrimitiveKind::Pointer:
955
- case PrimitiveKind::Callback: {
956
- void *ptr2 = *(void **)src;
957
-
958
- if (ptr2) {
959
- Napi::External<void> external = Napi::External<void>::New(env, ptr2);
960
- SetValueTag(instance, external, member.type->ref.marker);
961
-
962
- obj.Set(member.name, external);
963
- } else {
964
- obj.Set(member.name, env.Null());
965
- }
966
-
967
- if (member.type->dispose) {
968
- member.type->dispose(env, member.type, ptr2);
969
- }
970
- } break;
971
- case PrimitiveKind::Record: {
972
- Napi::Object obj2 = PopObject(src, member.type, realign);
973
- obj.Set(member.name, obj2);
974
- } break;
975
- case PrimitiveKind::Array: {
976
- Napi::Value value = PopArray(src, member.type, realign);
977
- obj.Set(member.name, value);
978
- } break;
979
- case PrimitiveKind::Float32: {
980
- float f = *(float *)src;
981
- obj.Set(member.name, Napi::Number::New(env, (double)f));
982
- } break;
983
- case PrimitiveKind::Float64: {
984
- double d = *(double *)src;
985
- obj.Set(member.name, Napi::Number::New(env, d));
986
- } break;
987
-
988
- case PrimitiveKind::Prototype: { RG_UNREACHABLE(); } break;
989
- }
990
- }
991
- }
992
-
993
- Napi::Object CallData::PopObject(const uint8_t *origin, const TypeInfo *type, int16_t realign)
994
- {
995
- Napi::Object obj = Napi::Object::New(env);
996
- PopObject(obj, origin, type, realign);
997
- return obj;
998
- }
999
-
1000
- static Size WideStringLength(const char16_t *str16, Size max)
1001
- {
1002
- Size len = 0;
1003
-
1004
- while (len < max && str16[len]) {
1005
- len++;
1006
- }
1007
-
1008
- return len;
1009
- }
1010
-
1011
- void CallData::PopNormalArray(Napi::Array array, const uint8_t *origin, const TypeInfo *ref, int16_t realign)
1012
- {
1013
- RG_ASSERT(array.IsArray());
1014
-
1015
- Size offset = 0;
1016
- uint32_t len = array.Length();
1017
-
1018
- #define POP_ARRAY(SetCode) \
1019
- do { \
1020
- for (uint32_t i = 0; i < len; i++) { \
1021
- int16_t align = std::max(realign, ref->align); \
1022
- offset = AlignLen(offset, align); \
1023
- \
1024
- const uint8_t *src = origin + offset; \
1025
- \
1026
- SetCode \
1027
- \
1028
- offset += ref->size; \
1029
- } \
1030
- } while (false)
1031
- #define POP_NUMBER_ARRAY(CType) \
1032
- do { \
1033
- POP_ARRAY({ \
1034
- double d = (double)*(CType *)src; \
1035
- array.Set(i, Napi::Number::New(env, d)); \
1036
- }); \
1037
- } while (false)
1038
- #define POP_NUMBER_ARRAY_SWAP(CType) \
1039
- do { \
1040
- POP_ARRAY({ \
1041
- CType v = *(CType *)src; \
1042
- double d = (double)ReverseBytes(v); \
1043
- array.Set(i, Napi::Number::New(env, d)); \
1044
- }); \
1045
- } while (false)
1046
-
1047
- switch (ref->primitive) {
1048
- case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
1049
-
1050
- case PrimitiveKind::Bool: {
1051
- POP_ARRAY({
1052
- bool b = *(bool *)src;
1053
- array.Set(i, Napi::Boolean::New(env, b));
1054
- });
1055
- } break;
1056
- case PrimitiveKind::Int8: { POP_NUMBER_ARRAY(int8_t); } break;
1057
- case PrimitiveKind::UInt8: { POP_NUMBER_ARRAY(uint8_t); } break;
1058
- case PrimitiveKind::Int16: { POP_NUMBER_ARRAY(int16_t); } break;
1059
- case PrimitiveKind::Int16S: { POP_NUMBER_ARRAY_SWAP(int16_t); } break;
1060
- case PrimitiveKind::UInt16: { POP_NUMBER_ARRAY(uint16_t); } break;
1061
- case PrimitiveKind::UInt16S: { POP_NUMBER_ARRAY_SWAP(uint16_t); } break;
1062
- case PrimitiveKind::Int32: { POP_NUMBER_ARRAY(int32_t); } break;
1063
- case PrimitiveKind::Int32S: { POP_NUMBER_ARRAY_SWAP(int32_t); } break;
1064
- case PrimitiveKind::UInt32: { POP_NUMBER_ARRAY(uint32_t); } break;
1065
- case PrimitiveKind::UInt32S: { POP_NUMBER_ARRAY_SWAP(uint32_t); } break;
1066
- case PrimitiveKind::Int64: {
1067
- POP_ARRAY({
1068
- int64_t v = *(int64_t *)src;
1069
- array.Set(i, NewBigInt(env, v));
1070
- });
1071
- } break;
1072
- case PrimitiveKind::Int64S: {
1073
- POP_ARRAY({
1074
- int64_t v = ReverseBytes(*(int64_t *)src);
1075
- array.Set(i, NewBigInt(env, v));
1076
- });
1077
- } break;
1078
- case PrimitiveKind::UInt64: {
1079
- POP_ARRAY({
1080
- uint64_t v = *(uint64_t *)src;
1081
- array.Set(i, NewBigInt(env, v));
1082
- });
1083
- } break;
1084
- case PrimitiveKind::UInt64S: {
1085
- POP_ARRAY({
1086
- uint64_t v = ReverseBytes(*(uint64_t *)src);
1087
- array.Set(i, NewBigInt(env, v));
1088
- });
1089
- } break;
1090
- case PrimitiveKind::String: {
1091
- POP_ARRAY({
1092
- const char *str = *(const char **)src;
1093
- array.Set(i, str ? Napi::String::New(env, str) : env.Null());
1094
-
1095
- if (ref->dispose) {
1096
- ref->dispose(env, ref, str);
1097
- }
1098
- });
1099
- } break;
1100
- case PrimitiveKind::String16: {
1101
- POP_ARRAY({
1102
- const char16_t *str16 = *(const char16_t **)src;
1103
- array.Set(i, str16 ? Napi::String::New(env, str16) : env.Null());
1104
-
1105
- if (ref->dispose) {
1106
- ref->dispose(env, ref, str16);
1107
- }
1108
- });
1109
- } break;
1110
- case PrimitiveKind::Pointer:
1111
- case PrimitiveKind::Callback: {
1112
- POP_ARRAY({
1113
- void *ptr2 = *(void **)src;
1114
-
1115
- if (ptr2) {
1116
- Napi::External<void> external = Napi::External<void>::New(env, ptr2);
1117
- SetValueTag(instance, external, ref->ref.marker);
1118
-
1119
- array.Set(i, external);
1120
- } else {
1121
- array.Set(i, env.Null());
1122
- }
1123
-
1124
- if (ref->dispose) {
1125
- ref->dispose(env, ref, ptr2);
1126
- }
1127
- });
1128
- } break;
1129
- case PrimitiveKind::Record: {
1130
- POP_ARRAY({
1131
- Napi::Object obj = PopObject(src, ref, realign);
1132
- array.Set(i, obj);
1133
- });
1134
- } break;
1135
- case PrimitiveKind::Array: {
1136
- POP_ARRAY({
1137
- Napi::Value value = PopArray(src, ref, realign);
1138
- array.Set(i, value);
1139
- });
1140
- } break;
1141
- case PrimitiveKind::Float32: { POP_NUMBER_ARRAY(float); } break;
1142
- case PrimitiveKind::Float64: { POP_NUMBER_ARRAY(double); } break;
1143
-
1144
- case PrimitiveKind::Prototype: { RG_UNREACHABLE(); } break;
1145
- }
1146
-
1147
- #undef POP_NUMBER_ARRAY_SWAP
1148
- #undef POP_NUMBER_ARRAY
1149
- #undef POP_ARRAY
1150
- }
1151
-
1152
- void CallData::PopTypedArray(Napi::TypedArray array, const uint8_t *origin, const TypeInfo *ref, int16_t realign)
1153
- {
1154
- RG_ASSERT(array.IsTypedArray());
1155
- RG_ASSERT(GetTypedArrayType(ref) == array.TypedArrayType() ||
1156
- ref == instance->void_type);
1157
-
1158
- uint8_t *buf = (uint8_t *)array.ArrayBuffer().Data();
1159
-
1160
- if (realign) {
1161
- Size offset = 0;
1162
- Size len = (Size)array.ElementLength();
1163
- Size size = (Size)array.ElementSize();
1164
-
1165
- for (Size i = 0; i < len; i++) {
1166
- offset = AlignLen(offset, realign);
1167
-
1168
- uint8_t *dest = buf + i * size;
1169
- const uint8_t *src = origin + offset;
1170
-
1171
- memcpy(dest, src, size);
1172
-
1173
- offset += size;
1174
- }
1175
- } else {
1176
- memcpy_safe(buf, origin, (size_t)array.ByteLength());
1177
- }
1178
-
1179
- #define SWAP(CType) \
1180
- do { \
1181
- CType *data = (CType *)buf; \
1182
- Size len = (Size)array.ElementLength(); \
1183
- \
1184
- for (Size i = 0; i < len; i++) { \
1185
- data[i] = ReverseBytes(data[i]); \
1186
- } \
1187
- } while (false)
1188
-
1189
- if (ref->primitive == PrimitiveKind::Int16S || ref->primitive == PrimitiveKind::UInt16S) {
1190
- SWAP(uint16_t);
1191
- } else if (ref->primitive == PrimitiveKind::Int32S || ref->primitive == PrimitiveKind::UInt32S) {
1192
- SWAP(uint32_t);
1193
- } else if (ref->primitive == PrimitiveKind::Int64S || ref->primitive == PrimitiveKind::UInt64S) {
1194
- SWAP(uint64_t);
1195
- }
1196
-
1197
- #undef SWAP
1198
- }
1199
-
1200
- Napi::Value CallData::PopArray(const uint8_t *origin, const TypeInfo *type, int16_t realign)
1201
- {
1202
- RG_ASSERT(type->primitive == PrimitiveKind::Array);
1203
-
1204
- uint32_t len = type->size / type->ref.type->size;
1205
- Size offset = 0;
1206
-
1207
- #define POP_ARRAY(SetCode) \
1208
- do { \
1209
- Napi::Array array = Napi::Array::New(env); \
1210
- \
1211
- for (uint32_t i = 0; i < len; i++) { \
1212
- int16_t align = std::max(realign, type->ref.type->align); \
1213
- offset = AlignLen(offset, align); \
1214
- \
1215
- const uint8_t *src = origin + offset; \
1216
- \
1217
- SetCode \
1218
- \
1219
- offset += type->ref.type->size; \
1220
- } \
1221
- \
1222
- return array; \
1223
- } while (false)
1224
- #define POP_NUMBER_ARRAY(TypedArrayType, CType) \
1225
- do { \
1226
- if (type->hint == TypeInfo::ArrayHint::Array) { \
1227
- POP_ARRAY({ \
1228
- double d = (double)*(CType *)src; \
1229
- array.Set(i, Napi::Number::New(env, d)); \
1230
- }); \
1231
- } else { \
1232
- Napi::TypedArrayType array = Napi::TypedArrayType::New(env, len); \
1233
- PopTypedArray(array, origin, type->ref.type, realign); \
1234
- \
1235
- return array; \
1236
- } \
1237
- } while (false)
1238
- #define POP_NUMBER_ARRAY_SWAP(TypedArrayType, CType) \
1239
- do { \
1240
- if (type->hint == TypeInfo::ArrayHint::Array) { \
1241
- POP_ARRAY({ \
1242
- CType v = *(CType *)src; \
1243
- double d = (double)ReverseBytes(v); \
1244
- array.Set(i, Napi::Number::New(env, d)); \
1245
- }); \
1246
- } else { \
1247
- Napi::TypedArrayType array = Napi::TypedArrayType::New(env, len); \
1248
- PopTypedArray(array, origin, type->ref.type, realign); \
1249
- \
1250
- return array; \
1251
- } \
1252
- } while (false)
1253
-
1254
- switch (type->ref.type->primitive) {
1255
- case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
1256
-
1257
- case PrimitiveKind::Bool: {
1258
- POP_ARRAY({
1259
- bool b = *(bool *)src;
1260
- array.Set(i, Napi::Boolean::New(env, b));
1261
- });
1262
- } break;
1263
- case PrimitiveKind::Int8: {
1264
- if (type->hint == TypeInfo::ArrayHint::String) {
1265
- RG_ASSERT(!realign);
1266
-
1267
- const char *ptr = (const char *)origin;
1268
- size_t count = strnlen(ptr, (size_t)len);
1269
-
1270
- Napi::String str = Napi::String::New(env, ptr, count);
1271
- return str;
1272
- }
1273
-
1274
- POP_NUMBER_ARRAY(Int8Array, int8_t);
1275
- } break;
1276
- case PrimitiveKind::UInt8: { POP_NUMBER_ARRAY(Uint8Array, uint8_t); } break;
1277
- case PrimitiveKind::Int16: {
1278
- if (type->hint == TypeInfo::ArrayHint::String) {
1279
- RG_ASSERT(!realign);
1280
-
1281
- const char16_t *ptr = (const char16_t *)origin;
1282
- Size count = WideStringLength(ptr, len);
1283
-
1284
- Napi::String str = Napi::String::New(env, ptr, count);
1285
- return str;
1286
- }
1287
-
1288
- POP_NUMBER_ARRAY(Int16Array, int16_t);
1289
- } break;
1290
- case PrimitiveKind::Int16S: { POP_NUMBER_ARRAY_SWAP(Int16Array, int16_t); } break;
1291
- case PrimitiveKind::UInt16: { POP_NUMBER_ARRAY(Uint16Array, uint16_t); } break;
1292
- case PrimitiveKind::UInt16S: { POP_NUMBER_ARRAY_SWAP(Uint16Array, uint16_t); } break;
1293
- case PrimitiveKind::Int32: { POP_NUMBER_ARRAY(Int32Array, int32_t); } break;
1294
- case PrimitiveKind::Int32S: { POP_NUMBER_ARRAY_SWAP(Int32Array, int32_t); } break;
1295
- case PrimitiveKind::UInt32: { POP_NUMBER_ARRAY(Uint32Array, uint32_t); } break;
1296
- case PrimitiveKind::UInt32S: { POP_NUMBER_ARRAY_SWAP(Uint32Array, uint32_t); } break;
1297
- case PrimitiveKind::Int64: {
1298
- POP_ARRAY({
1299
- int64_t v = *(int64_t *)src;
1300
- array.Set(i, NewBigInt(env, v));
1301
- });
1302
- } break;
1303
- case PrimitiveKind::Int64S: {
1304
- POP_ARRAY({
1305
- int64_t v = ReverseBytes(*(int64_t *)src);
1306
- array.Set(i, NewBigInt(env, v));
1307
- });
1308
- } break;
1309
- case PrimitiveKind::UInt64: {
1310
- POP_ARRAY({
1311
- uint64_t v = *(uint64_t *)src;
1312
- array.Set(i, NewBigInt(env, v));
1313
- });
1314
- } break;
1315
- case PrimitiveKind::UInt64S: {
1316
- POP_ARRAY({
1317
- uint64_t v = ReverseBytes(*(uint64_t *)src);
1318
- array.Set(i, NewBigInt(env, v));
1319
- });
1320
- } break;
1321
- case PrimitiveKind::String: {
1322
- POP_ARRAY({
1323
- const char *str = *(const char **)src;
1324
- array.Set(i, str ? Napi::String::New(env, str) : env.Null());
1325
- });
1326
- } break;
1327
- case PrimitiveKind::String16: {
1328
- POP_ARRAY({
1329
- const char16_t *str16 = *(const char16_t **)src;
1330
- array.Set(i, str16 ? Napi::String::New(env, str16) : env.Null());
1331
- });
1332
- } break;
1333
- case PrimitiveKind::Pointer:
1334
- case PrimitiveKind::Callback: {
1335
- POP_ARRAY({
1336
- void *ptr2 = *(void **)src;
1337
-
1338
- if (ptr2) {
1339
- Napi::External<void> external = Napi::External<void>::New(env, ptr2);
1340
- SetValueTag(instance, external, type->ref.type->ref.marker);
1341
-
1342
- array.Set(i, external);
1343
- } else {
1344
- array.Set(i, env.Null());
1345
- }
1346
- });
1347
- } break;
1348
- case PrimitiveKind::Record: {
1349
- POP_ARRAY({
1350
- Napi::Object obj = PopObject(src, type->ref.type, realign);
1351
- array.Set(i, obj);
1352
- });
1353
- } break;
1354
- case PrimitiveKind::Array: {
1355
- POP_ARRAY({
1356
- Napi::Value value = PopArray(src, type->ref.type, realign);
1357
- array.Set(i, value);
1358
- });
1359
- } break;
1360
- case PrimitiveKind::Float32: { POP_NUMBER_ARRAY(Float32Array, float); } break;
1361
- case PrimitiveKind::Float64: { POP_NUMBER_ARRAY(Float64Array, double); } break;
1362
-
1363
- case PrimitiveKind::Prototype: { RG_UNREACHABLE(); } break;
1364
- }
1365
-
1366
- #undef POP_NUMBER_ARRAY_SWAP
1367
- #undef POP_NUMBER_ARRAY
1368
- #undef POP_ARRAY
1369
-
1370
- RG_UNREACHABLE();
1371
- }
1372
-
1373
988
  void CallData::DumpForward() const
1374
989
  {
1375
990
  PrintLn(stderr, "%!..+---- %1 (%2) ----%!0", func->name, CallConventionNames[(int)func->convention]);