koffi 2.2.0 → 2.2.2-beta.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 (76) hide show
  1. package/ChangeLog.md +6 -0
  2. package/package.json +2 -2
  3. package/src/koffi/build/2.2.2-beta.1/koffi_darwin_arm64.tar.gz +0 -0
  4. package/src/koffi/build/2.2.2-beta.1/koffi_darwin_x64.tar.gz +0 -0
  5. package/src/koffi/build/2.2.2-beta.1/koffi_freebsd_arm64.tar.gz +0 -0
  6. package/src/koffi/build/2.2.2-beta.1/koffi_freebsd_ia32.tar.gz +0 -0
  7. package/src/koffi/build/2.2.2-beta.1/koffi_freebsd_x64.tar.gz +0 -0
  8. package/src/koffi/build/2.2.2-beta.1/koffi_linux_arm32hf.tar.gz +0 -0
  9. package/src/koffi/build/2.2.2-beta.1/koffi_linux_arm64.tar.gz +0 -0
  10. package/src/koffi/build/2.2.2-beta.1/koffi_linux_ia32.tar.gz +0 -0
  11. package/src/koffi/build/2.2.2-beta.1/koffi_linux_riscv64hf64.tar.gz +0 -0
  12. package/src/koffi/build/2.2.2-beta.1/koffi_linux_x64.tar.gz +0 -0
  13. package/src/koffi/build/2.2.2-beta.1/koffi_openbsd_ia32.tar.gz +0 -0
  14. package/src/koffi/build/2.2.2-beta.1/koffi_openbsd_x64.tar.gz +0 -0
  15. package/src/koffi/build/2.2.2-beta.1/koffi_win32_arm64.tar.gz +0 -0
  16. package/src/koffi/build/2.2.2-beta.1/koffi_win32_ia32.tar.gz +0 -0
  17. package/src/koffi/build/2.2.2-beta.1/koffi_win32_x64.tar.gz +0 -0
  18. package/src/koffi/qemu/qemu.js +12 -10
  19. package/src/koffi/src/abi_arm32.cc +7 -11
  20. package/src/koffi/src/abi_arm64.cc +7 -11
  21. package/src/koffi/src/abi_riscv64.cc +7 -11
  22. package/src/koffi/src/abi_x64_sysv.cc +7 -11
  23. package/src/koffi/src/abi_x64_win.cc +7 -11
  24. package/src/koffi/src/abi_x86.cc +7 -11
  25. package/src/koffi/src/call.cc +53 -2
  26. package/src/koffi/src/call.hh +6 -1
  27. package/src/koffi/src/ffi.cc +66 -12
  28. package/src/koffi/src/ffi.hh +2 -0
  29. package/src/koffi/src/index.js +6 -2
  30. package/src/koffi/test/CMakeLists.txt +1 -1
  31. package/src/koffi/test/async.js +3 -0
  32. package/src/koffi/test/callbacks.js +30 -0
  33. package/src/koffi/test/misc.c +11 -0
  34. package/vendor/{sqlite3mc → sqlite3}/sqlite3.c +139 -43
  35. package/vendor/{sqlite3mc → sqlite3}/sqlite3.h +10 -3
  36. package/vendor/{sqlite3mc → sqlite3}/sqlite3ext.h +0 -0
  37. package/vendor/{sqlite3mc → sqlite3}/sqlite3mc.c +156 -53
  38. package/vendor/{sqlite3mc → sqlite3}/sqlite3mc.def +0 -0
  39. package/vendor/{sqlite3mc → sqlite3}/sqlite3mc.h +12 -5
  40. package/vendor/sqlite3/wasm/README.txt +23 -0
  41. package/vendor/sqlite3/wasm/common/SqliteTestUtil.js +236 -0
  42. package/vendor/sqlite3/wasm/common/emscripten.css +24 -0
  43. package/vendor/sqlite3/wasm/common/testing.css +63 -0
  44. package/vendor/sqlite3/wasm/demo-123-worker.html +44 -0
  45. package/vendor/sqlite3/wasm/demo-123.html +24 -0
  46. package/vendor/sqlite3/wasm/demo-123.js +289 -0
  47. package/vendor/sqlite3/wasm/demo-jsstorage.html +49 -0
  48. package/vendor/sqlite3/wasm/demo-jsstorage.js +114 -0
  49. package/vendor/sqlite3/wasm/demo-worker1-promiser.html +34 -0
  50. package/vendor/sqlite3/wasm/demo-worker1-promiser.js +270 -0
  51. package/vendor/sqlite3/wasm/demo-worker1.html +34 -0
  52. package/vendor/sqlite3/wasm/demo-worker1.js +345 -0
  53. package/vendor/sqlite3/wasm/index.html +90 -0
  54. package/vendor/sqlite3/wasm/jswasm/sqlite3-opfs-async-proxy.js +830 -0
  55. package/vendor/sqlite3/wasm/jswasm/sqlite3-worker1-promiser.js +259 -0
  56. package/vendor/sqlite3/wasm/jswasm/sqlite3-worker1.js +49 -0
  57. package/vendor/sqlite3/wasm/jswasm/sqlite3.js +10119 -0
  58. package/vendor/sqlite3/wasm/jswasm/sqlite3.wasm +0 -0
  59. package/vendor/sqlite3/wasm/tester1-worker.html +63 -0
  60. package/vendor/sqlite3/wasm/tester1.html +28 -0
  61. package/vendor/sqlite3/wasm/tester1.js +1864 -0
  62. package/src/koffi/build/2.2.0/koffi_darwin_arm64.tar.gz +0 -0
  63. package/src/koffi/build/2.2.0/koffi_darwin_x64.tar.gz +0 -0
  64. package/src/koffi/build/2.2.0/koffi_freebsd_arm64.tar.gz +0 -0
  65. package/src/koffi/build/2.2.0/koffi_freebsd_ia32.tar.gz +0 -0
  66. package/src/koffi/build/2.2.0/koffi_freebsd_x64.tar.gz +0 -0
  67. package/src/koffi/build/2.2.0/koffi_linux_arm32hf.tar.gz +0 -0
  68. package/src/koffi/build/2.2.0/koffi_linux_arm64.tar.gz +0 -0
  69. package/src/koffi/build/2.2.0/koffi_linux_ia32.tar.gz +0 -0
  70. package/src/koffi/build/2.2.0/koffi_linux_riscv64hf64.tar.gz +0 -0
  71. package/src/koffi/build/2.2.0/koffi_linux_x64.tar.gz +0 -0
  72. package/src/koffi/build/2.2.0/koffi_openbsd_ia32.tar.gz +0 -0
  73. package/src/koffi/build/2.2.0/koffi_openbsd_x64.tar.gz +0 -0
  74. package/src/koffi/build/2.2.0/koffi_win32_arm64.tar.gz +0 -0
  75. package/src/koffi/build/2.2.0/koffi_win32_ia32.tar.gz +0 -0
  76. package/src/koffi/build/2.2.0/koffi_win32_x64.tar.gz +0 -0
package/ChangeLog.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## History
4
4
 
5
+ ### Koffi 2.2.1
6
+
7
+ **Main fixes:**
8
+
9
+ - Fix crash when [calling callback again after FFI call inside previous callback](https://github.com/Koromix/rygel/issues/15)
10
+
5
11
  ### Koffi 2.2.0
6
12
 
7
13
  **New features:**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "2.2.0",
4
- "stable": "2.2.0",
3
+ "version": "2.2.2-beta.1",
4
+ "stable": "2.2.1",
5
5
  "description": "Fast and simple C FFI (foreign function interface) for Node.js",
6
6
  "keywords": [
7
7
  "foreign",
@@ -63,6 +63,7 @@ async function main() {
63
63
  switch (process.argv[2]) {
64
64
  case 'pack': { command = pack; } break;
65
65
  case 'publish': { command = publish; } break;
66
+ case 'prepare': { command = prepare; } break;
66
67
  case 'test': { command = test; } break;
67
68
  case 'start': { command = start; } break;
68
69
  case 'stop': { command = stop; } break;
@@ -190,7 +191,7 @@ async function main() {
190
191
  console.log();
191
192
 
192
193
  try {
193
- let success = await command();
194
+ let success = !!(await command());
194
195
  process.exit(!success);
195
196
  } catch (err) {
196
197
  console.error(err);
@@ -205,6 +206,7 @@ Commands:
205
206
  test Run the machines and perform the tests (default)
206
207
  pack Create NPM package with prebuilt Koffi binaries
207
208
  publish Publish NPM package with prebuilt Koffi binaries
209
+ prepare Prepare distribution-ready NPM package directory
208
210
 
209
211
  start Start the machines but don't run anythingh
210
212
  stop Stop running machines
@@ -290,10 +292,9 @@ async function start(detach = true) {
290
292
 
291
293
  async function pack() {
292
294
  let pack_dir = script_dir + '/../build';
293
- let dist_dir = script_dir + '/../build/dist';
295
+ let dist_dir = await prepare(dist_dir);
294
296
 
295
- let success = await prepare(dist_dir);
296
- if (!success)
297
+ if (dist_dir == null)
297
298
  return false;
298
299
 
299
300
  let npm = (process.platform == 'win32') ? 'npm.cmd' : 'npm';
@@ -305,10 +306,9 @@ async function pack() {
305
306
  }
306
307
 
307
308
  async function publish() {
308
- let dist_dir = script_dir + '/../build/dist';
309
+ let dist_dir = await prepare();
309
310
 
310
- let success = await prepare(dist_dir);
311
- if (!success)
311
+ if (dist_dir == null)
312
312
  return false;
313
313
 
314
314
  let npm = (process.platform == 'win32') ? 'npm.cmd' : 'npm';
@@ -319,7 +319,8 @@ async function publish() {
319
319
  });
320
320
  }
321
321
 
322
- async function prepare(dist_dir) {
322
+ async function prepare() {
323
+ let dist_dir = script_dir + '/../build/dist';
323
324
  let snapshot_dir = snapshot();
324
325
 
325
326
  let json = fs.readFileSync(root_dir + '/src/koffi/package.json', { encoding: 'utf-8' });
@@ -457,7 +458,7 @@ async function prepare(dist_dir) {
457
458
  if (!success) {
458
459
  console.log('');
459
460
  console.log('>> Status: ' + chalk.bold.red('FAILED'));
460
- return false;
461
+ return null;
461
462
  }
462
463
  }
463
464
 
@@ -495,7 +496,7 @@ async function prepare(dist_dir) {
495
496
  fs.renameSync(dist_dir + '/web/koffi.dev', dist_dir + '/doc');
496
497
  }
497
498
 
498
- return true;
499
+ return dist_dir;
499
500
  }
500
501
 
501
502
  function snapshot() {
@@ -519,6 +520,7 @@ function snapshot() {
519
520
  parts[1] == 'miniz' ||
520
521
  parts[1] == 'node-addon-api' ||
521
522
  parts[1] == 'raylib' ||
523
+ parts[1] == 'sqlite3' ||
522
524
  parts[1] == 'sqlite3mc';
523
525
  } else if (parts[0] == 'web') {
524
526
  return parts[1] == null || parts[1] == 'koffi.dev';
@@ -121,8 +121,6 @@ static void *const Trampolines[][2] = {
121
121
  };
122
122
  RG_STATIC_ASSERT(RG_LEN(Trampolines) == MaxTrampolines * 2);
123
123
 
124
- static RG_THREAD_LOCAL CallData *exec_call;
125
-
126
124
  static inline int IsHFA(const TypeInfo *type)
127
125
  {
128
126
  #ifdef __ARM_PCS_VFP
@@ -495,8 +493,6 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
495
493
 
496
494
  void CallData::Execute()
497
495
  {
498
- exec_call = this;
499
-
500
496
  #define PERFORM_CALL(Suffix) \
501
497
  ([&]() { \
502
498
  auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, new_sp, &old_sp) \
@@ -862,8 +858,13 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
862
858
  const TypeInfo *type = proto->ret.type;
863
859
 
864
860
  // Make the call
865
- napi_value ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
866
- [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
861
+ napi_value ret;
862
+ if (async) {
863
+ ret = (napi_value)func.Call(arguments[0], arguments.len - 1, arguments.data + 1);
864
+ } else {
865
+ ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
866
+ [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
867
+ }
867
868
  Napi::Value value(env, ret);
868
869
 
869
870
  if (RG_UNLIKELY(env.IsExceptionPending()))
@@ -1058,11 +1059,6 @@ void *GetTrampoline(Size idx, const FunctionInfo *proto)
1058
1059
  return Trampolines[idx][vec];
1059
1060
  }
1060
1061
 
1061
- extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
1062
- {
1063
- exec_call->Relay(idx, own_sp, caller_sp, out_reg);
1064
- }
1065
-
1066
1062
  }
1067
1063
 
1068
1064
  #endif
@@ -123,8 +123,6 @@ static void *const Trampolines[][2] = {
123
123
  };
124
124
  RG_STATIC_ASSERT(RG_LEN(Trampolines) == MaxTrampolines * 2);
125
125
 
126
- static RG_THREAD_LOCAL CallData *exec_call;
127
-
128
126
  static inline int IsHFA(const TypeInfo *type)
129
127
  {
130
128
  return IsHFA(type, 1, 4);
@@ -563,8 +561,6 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
563
561
 
564
562
  void CallData::Execute()
565
563
  {
566
- exec_call = this;
567
-
568
564
  #define PERFORM_CALL(Suffix) \
569
565
  ([&]() { \
570
566
  auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, new_sp, &old_sp) \
@@ -1087,8 +1083,13 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
1087
1083
  const TypeInfo *type = proto->ret.type;
1088
1084
 
1089
1085
  // Make the call
1090
- napi_value ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
1091
- [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
1086
+ napi_value ret;
1087
+ if (async) {
1088
+ ret = (napi_value)func.Call(arguments[0], arguments.len - 1, arguments.data + 1);
1089
+ } else {
1090
+ ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
1091
+ [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
1092
+ }
1092
1093
  Napi::Value value(env, ret);
1093
1094
 
1094
1095
  if (RG_UNLIKELY(env.IsExceptionPending()))
@@ -1251,11 +1252,6 @@ void *GetTrampoline(Size idx, const FunctionInfo *proto)
1251
1252
  return Trampolines[idx][vec];
1252
1253
  }
1253
1254
 
1254
- extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
1255
- {
1256
- exec_call->Relay(idx, own_sp, caller_sp, out_reg);
1257
- }
1258
-
1259
1255
  }
1260
1256
 
1261
1257
  #endif
@@ -131,8 +131,6 @@ static void *const Trampolines[][2] = {
131
131
  };
132
132
  RG_STATIC_ASSERT(RG_LEN(Trampolines) == MaxTrampolines * 2);
133
133
 
134
- static RG_THREAD_LOCAL CallData *exec_call;
135
-
136
134
  static void AnalyseParameter(ParameterInfo *param, int gpr_avail, int vec_avail)
137
135
  {
138
136
  gpr_avail = std::min(2, gpr_avail);
@@ -410,8 +408,6 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
410
408
 
411
409
  void CallData::Execute()
412
410
  {
413
- exec_call = this;
414
-
415
411
  #define PERFORM_CALL(Suffix) \
416
412
  ([&]() { \
417
413
  auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, new_sp, &old_sp) \
@@ -761,8 +757,13 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
761
757
  const TypeInfo *type = proto->ret.type;
762
758
 
763
759
  // Make the call
764
- napi_value ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
765
- [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
760
+ napi_value ret;
761
+ if (async) {
762
+ ret = (napi_value)func.Call(arguments[0], arguments.len - 1, arguments.data + 1);
763
+ } else {
764
+ ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
765
+ [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
766
+ }
766
767
  Napi::Value value(env, ret);
767
768
 
768
769
  if (RG_UNLIKELY(env.IsExceptionPending()))
@@ -924,11 +925,6 @@ void *GetTrampoline(Size idx, const FunctionInfo *proto)
924
925
  return Trampolines[idx][fp];
925
926
  }
926
927
 
927
- extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
928
- {
929
- exec_call->Relay(idx, own_sp, caller_sp, out_reg);
930
- }
931
-
932
928
  }
933
929
 
934
930
  #endif
@@ -138,8 +138,6 @@ static void *const Trampolines[][2] = {
138
138
  };
139
139
  RG_STATIC_ASSERT(RG_LEN(Trampolines) == MaxTrampolines * 2);
140
140
 
141
- static RG_THREAD_LOCAL CallData *exec_call;
142
-
143
141
  static inline RegisterClass MergeClasses(RegisterClass cls1, RegisterClass cls2)
144
142
  {
145
143
  if (cls1 == cls2)
@@ -474,8 +472,6 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
474
472
 
475
473
  void CallData::Execute()
476
474
  {
477
- exec_call = this;
478
-
479
475
  #define PERFORM_CALL(Suffix) \
480
476
  ([&]() { \
481
477
  auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, new_sp, &old_sp) \
@@ -809,8 +805,13 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
809
805
  const TypeInfo *type = proto->ret.type;
810
806
 
811
807
  // Make the call
812
- napi_value ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
813
- [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
808
+ napi_value ret;
809
+ if (async) {
810
+ ret = (napi_value)func.Call(arguments[0], arguments.len - 1, arguments.data + 1);
811
+ } else {
812
+ ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
813
+ [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
814
+ }
814
815
  Napi::Value value(env, ret);
815
816
 
816
817
  if (RG_UNLIKELY(env.IsExceptionPending()))
@@ -989,11 +990,6 @@ void *GetTrampoline(Size idx, const FunctionInfo *proto)
989
990
  return Trampolines[idx][xmm];
990
991
  }
991
992
 
992
- extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
993
- {
994
- exec_call->Relay(idx, own_sp, caller_sp, out_reg);
995
- }
996
-
997
993
  }
998
994
 
999
995
  #endif
@@ -107,8 +107,6 @@ static void *const Trampolines[][2] = {
107
107
  };
108
108
  RG_STATIC_ASSERT(RG_LEN(Trampolines) == MaxTrampolines * 2);
109
109
 
110
- static RG_THREAD_LOCAL CallData *exec_call;
111
-
112
110
  bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
113
111
  {
114
112
  func->ret.regular = IsRegularSize(func->ret.type->size, 8);
@@ -285,8 +283,6 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
285
283
 
286
284
  void CallData::Execute()
287
285
  {
288
- exec_call = this;
289
-
290
286
  #define PERFORM_CALL(Suffix) \
291
287
  ([&]() { \
292
288
  auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, new_sp, &old_sp) \
@@ -602,8 +598,13 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
602
598
  const TypeInfo *type = proto->ret.type;
603
599
 
604
600
  // Make the call
605
- napi_value ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
606
- [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
601
+ napi_value ret;
602
+ if (async) {
603
+ ret = (napi_value)func.Call(arguments[0], arguments.len - 1, arguments.data + 1);
604
+ } else {
605
+ ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
606
+ [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
607
+ }
607
608
  Napi::Value value(env, ret);
608
609
 
609
610
  if (RG_UNLIKELY(env.IsExceptionPending()))
@@ -763,11 +764,6 @@ void *GetTrampoline(Size idx, const FunctionInfo *proto)
763
764
  return Trampolines[idx][xmm];
764
765
  }
765
766
 
766
- extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
767
- {
768
- exec_call->Relay(idx, own_sp, caller_sp, out_reg);
769
- }
770
-
771
767
  }
772
768
 
773
769
  #endif
@@ -113,8 +113,6 @@ static void *const Trampolines[][2] = {
113
113
  };
114
114
  RG_STATIC_ASSERT(RG_LEN(Trampolines) == MaxTrampolines * 2);
115
115
 
116
- static RG_THREAD_LOCAL CallData *exec_call;
117
-
118
116
  bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
119
117
  {
120
118
  if (!func->lib && func->convention != CallConvention::Cdecl &&
@@ -366,8 +364,6 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
366
364
 
367
365
  void CallData::Execute()
368
366
  {
369
- exec_call = this;
370
-
371
367
  #define PERFORM_CALL(Suffix) \
372
368
  ([&]() { \
373
369
  auto ret = (func->fast ? ForwardCallR ## Suffix(func->func, new_sp, &old_sp) \
@@ -681,8 +677,13 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegister
681
677
  const TypeInfo *type = proto->ret.type;
682
678
 
683
679
  // Make the call
684
- napi_value ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
685
- [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
680
+ napi_value ret;
681
+ if (async) {
682
+ ret = (napi_value)func.Call(arguments[0], arguments.len - 1, arguments.data + 1);
683
+ } else {
684
+ ret = CallSwitchStack(&func, (size_t)arguments.len, arguments.data, old_sp, &mem->stack,
685
+ [](Napi::Function *func, size_t argc, napi_value *argv) { return (napi_value)func->Call(argv[0], argc - 1, argv + 1); });
686
+ }
686
687
  Napi::Value value(env, ret);
687
688
 
688
689
  if (RG_UNLIKELY(env.IsExceptionPending()))
@@ -866,11 +867,6 @@ void *GetTrampoline(Size idx, const FunctionInfo *proto)
866
867
  return Trampolines[idx][x87];
867
868
  }
868
869
 
869
- extern "C" void RelayCallback(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
870
- {
871
- exec_call->Relay(idx, own_sp, caller_sp, out_reg);
872
- }
873
-
874
870
  }
875
871
 
876
872
  #endif
@@ -20,9 +20,23 @@
20
20
 
21
21
  namespace RG {
22
22
 
23
- CallData::CallData(Napi::Env env, InstanceData *instance, const FunctionInfo *func, InstanceMemory *mem)
23
+ struct RelayContext {
24
+ CallData *call;
25
+
26
+ Size idx;
27
+ uint8_t *own_sp;
28
+ uint8_t *caller_sp;
29
+ BackRegisters *out_reg;
30
+
31
+ std::mutex mutex;
32
+ std::condition_variable cv;
33
+ bool done = false;
34
+ };
35
+
36
+ CallData::CallData(Napi::Env env, InstanceData *instance,
37
+ const FunctionInfo *func, InstanceMemory *mem, bool async)
24
38
  : env(env), instance(instance), func(func),
25
- mem(mem), old_stack_mem(mem->stack), old_heap_mem(mem->heap)
39
+ mem(mem), old_stack_mem(mem->stack), old_heap_mem(mem->heap), async(async)
26
40
  {
27
41
  mem->generation += !mem->depth;
28
42
  mem->depth++;
@@ -46,6 +60,43 @@ CallData::~CallData()
46
60
  if (!--mem->depth && mem->temporary) {
47
61
  delete mem;
48
62
  }
63
+
64
+ instance = nullptr;
65
+ }
66
+
67
+ void CallData::RelaySafe(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg)
68
+ {
69
+ if (async) {
70
+ RelayContext ctx;
71
+
72
+ ctx.call = this;
73
+ ctx.idx = idx;
74
+ ctx.own_sp = own_sp;
75
+ ctx.caller_sp = caller_sp;
76
+ ctx.out_reg = out_reg;
77
+
78
+ napi_call_threadsafe_function(instance->broker, &ctx, napi_tsfn_blocking);
79
+
80
+ // Wait until it executes
81
+ std::unique_lock<std::mutex> lock(ctx.mutex);
82
+ while (!ctx.done) {
83
+ ctx.cv.wait(lock);
84
+ }
85
+ } else {
86
+ Relay(idx, own_sp, caller_sp, out_reg);
87
+ }
88
+ }
89
+
90
+ void CallData::RelayAsync(napi_env, napi_value, void *, void *udata)
91
+ {
92
+ RelayContext *ctx = (RelayContext *)udata;
93
+
94
+ ctx->call->Relay(ctx->idx, ctx->own_sp, ctx->caller_sp, ctx->out_reg);
95
+
96
+ // We're done!
97
+ std::lock_guard<std::mutex> lock(ctx->mutex);
98
+ ctx->done = true;
99
+ ctx->cv.notify_one();
49
100
  }
50
101
 
51
102
  bool CallData::PushString(Napi::Value value, int directions, const char **out_str)
@@ -42,6 +42,8 @@ class alignas(8) CallData {
42
42
  Span<uint8_t> old_stack_mem;
43
43
  Span<uint8_t> old_heap_mem;
44
44
 
45
+ bool async;
46
+
45
47
  int16_t used_trampolines = 0;
46
48
 
47
49
  LocalArray<OutArgument, MaxOutParameters> out_arguments;
@@ -68,7 +70,8 @@ class alignas(8) CallData {
68
70
  BlockAllocator call_alloc;
69
71
 
70
72
  public:
71
- CallData(Napi::Env env, InstanceData *instance, const FunctionInfo *func, InstanceMemory *mem);
73
+ CallData(Napi::Env env, InstanceData *instance,
74
+ const FunctionInfo *func, InstanceMemory *mem, bool async);
72
75
  ~CallData();
73
76
 
74
77
  #ifdef UNITY_BUILD
@@ -88,6 +91,8 @@ public:
88
91
  #undef INLINE_IF_UNITY
89
92
 
90
93
  void Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg);
94
+ void RelaySafe(Size idx, uint8_t *own_sp, uint8_t *caller_sp, BackRegisters *out_reg);
95
+ static void RelayAsync(napi_env, napi_value, void *, void *udata);
91
96
 
92
97
  void DumpForward() const;
93
98