@nocobase/plugin-workflow-javascript 2.1.0-beta.10 → 2.1.0-beta.12

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 (107) hide show
  1. package/dist/externalVersion.js +4 -4
  2. package/dist/node_modules/isolated-vm/.clang-tidy +13 -0
  3. package/dist/node_modules/isolated-vm/.dockerignore +9 -0
  4. package/dist/node_modules/isolated-vm/Dockerfile.alpine +9 -0
  5. package/dist/node_modules/isolated-vm/Dockerfile.debian +12 -0
  6. package/dist/node_modules/isolated-vm/LICENSE +13 -0
  7. package/dist/node_modules/isolated-vm/binding.gyp +120 -0
  8. package/dist/node_modules/isolated-vm/include.js +3 -0
  9. package/dist/node_modules/isolated-vm/inspector-example.js +59 -0
  10. package/dist/node_modules/isolated-vm/isolated-vm.d.ts +820 -0
  11. package/dist/node_modules/isolated-vm/isolated-vm.js +1 -0
  12. package/dist/node_modules/isolated-vm/native-example/binding.gyp +23 -0
  13. package/dist/node_modules/isolated-vm/native-example/example.cc +61 -0
  14. package/dist/node_modules/isolated-vm/native-example/package.json +13 -0
  15. package/dist/node_modules/isolated-vm/native-example/usage.js +35 -0
  16. package/dist/node_modules/isolated-vm/out/isolated_vm.node +0 -0
  17. package/dist/node_modules/isolated-vm/package.json +1 -0
  18. package/dist/node_modules/isolated-vm/src/external_copy/error.h +33 -0
  19. package/dist/node_modules/isolated-vm/src/external_copy/external_copy.cc +509 -0
  20. package/dist/node_modules/isolated-vm/src/external_copy/external_copy.h +117 -0
  21. package/dist/node_modules/isolated-vm/src/external_copy/serializer.cc +85 -0
  22. package/dist/node_modules/isolated-vm/src/external_copy/serializer.h +136 -0
  23. package/dist/node_modules/isolated-vm/src/external_copy/serializer_nortti.cc +73 -0
  24. package/dist/node_modules/isolated-vm/src/external_copy/string.cc +124 -0
  25. package/dist/node_modules/isolated-vm/src/external_copy/string.h +28 -0
  26. package/dist/node_modules/isolated-vm/src/isolate/allocator.h +32 -0
  27. package/dist/node_modules/isolated-vm/src/isolate/allocator_nortti.cc +142 -0
  28. package/dist/node_modules/isolated-vm/src/isolate/class_handle.h +334 -0
  29. package/dist/node_modules/isolated-vm/src/isolate/cpu_profile_manager.cc +220 -0
  30. package/dist/node_modules/isolated-vm/src/isolate/cpu_profile_manager.h +100 -0
  31. package/dist/node_modules/isolated-vm/src/isolate/environment.cc +626 -0
  32. package/dist/node_modules/isolated-vm/src/isolate/environment.h +381 -0
  33. package/dist/node_modules/isolated-vm/src/isolate/executor.cc +198 -0
  34. package/dist/node_modules/isolated-vm/src/isolate/executor.h +183 -0
  35. package/dist/node_modules/isolated-vm/src/isolate/external.h +64 -0
  36. package/dist/node_modules/isolated-vm/src/isolate/functor_runners.h +97 -0
  37. package/dist/node_modules/isolated-vm/src/isolate/generic/array.h +145 -0
  38. package/dist/node_modules/isolated-vm/src/isolate/generic/callbacks.h +272 -0
  39. package/dist/node_modules/isolated-vm/src/isolate/generic/error.h +140 -0
  40. package/dist/node_modules/isolated-vm/src/isolate/generic/extract_params.h +145 -0
  41. package/dist/node_modules/isolated-vm/src/isolate/generic/handle_cast.h +257 -0
  42. package/dist/node_modules/isolated-vm/src/isolate/generic/read_option.h +47 -0
  43. package/dist/node_modules/isolated-vm/src/isolate/holder.cc +88 -0
  44. package/dist/node_modules/isolated-vm/src/isolate/holder.h +63 -0
  45. package/dist/node_modules/isolated-vm/src/isolate/inspector.cc +200 -0
  46. package/dist/node_modules/isolated-vm/src/isolate/inspector.h +70 -0
  47. package/dist/node_modules/isolated-vm/src/isolate/node_wrapper.h +15 -0
  48. package/dist/node_modules/isolated-vm/src/isolate/platform_delegate.cc +22 -0
  49. package/dist/node_modules/isolated-vm/src/isolate/platform_delegate.h +46 -0
  50. package/dist/node_modules/isolated-vm/src/isolate/remote_handle.h +164 -0
  51. package/dist/node_modules/isolated-vm/src/isolate/run_with_timeout.h +171 -0
  52. package/dist/node_modules/isolated-vm/src/isolate/runnable.h +29 -0
  53. package/dist/node_modules/isolated-vm/src/isolate/scheduler.cc +191 -0
  54. package/dist/node_modules/isolated-vm/src/isolate/scheduler.h +165 -0
  55. package/dist/node_modules/isolated-vm/src/isolate/specific.h +35 -0
  56. package/dist/node_modules/isolated-vm/src/isolate/stack_trace.cc +219 -0
  57. package/dist/node_modules/isolated-vm/src/isolate/stack_trace.h +24 -0
  58. package/dist/node_modules/isolated-vm/src/isolate/strings.h +127 -0
  59. package/dist/node_modules/isolated-vm/src/isolate/three_phase_task.cc +385 -0
  60. package/dist/node_modules/isolated-vm/src/isolate/three_phase_task.h +136 -0
  61. package/dist/node_modules/isolated-vm/src/isolate/transferable.h +15 -0
  62. package/dist/node_modules/isolated-vm/src/isolate/util.h +45 -0
  63. package/dist/node_modules/isolated-vm/src/isolate/v8_inspector_wrapper.h +12 -0
  64. package/dist/node_modules/isolated-vm/src/isolate/v8_version.h +12 -0
  65. package/dist/node_modules/isolated-vm/src/isolated_vm.h +71 -0
  66. package/dist/node_modules/isolated-vm/src/lib/covariant.h +50 -0
  67. package/dist/node_modules/isolated-vm/src/lib/lockable.h +178 -0
  68. package/dist/node_modules/isolated-vm/src/lib/suspend.h +106 -0
  69. package/dist/node_modules/isolated-vm/src/lib/thread_pool.cc +98 -0
  70. package/dist/node_modules/isolated-vm/src/lib/thread_pool.h +45 -0
  71. package/dist/node_modules/isolated-vm/src/lib/timer.cc +233 -0
  72. package/dist/node_modules/isolated-vm/src/lib/timer.h +36 -0
  73. package/dist/node_modules/isolated-vm/src/module/callback.cc +151 -0
  74. package/dist/node_modules/isolated-vm/src/module/callback.h +64 -0
  75. package/dist/node_modules/isolated-vm/src/module/context_handle.cc +241 -0
  76. package/dist/node_modules/isolated-vm/src/module/context_handle.h +35 -0
  77. package/dist/node_modules/isolated-vm/src/module/evaluation.cc +109 -0
  78. package/dist/node_modules/isolated-vm/src/module/evaluation.h +99 -0
  79. package/dist/node_modules/isolated-vm/src/module/external_copy_handle.cc +119 -0
  80. package/dist/node_modules/isolated-vm/src/module/external_copy_handle.h +64 -0
  81. package/dist/node_modules/isolated-vm/src/module/isolate.cc +136 -0
  82. package/dist/node_modules/isolated-vm/src/module/isolate_handle.cc +611 -0
  83. package/dist/node_modules/isolated-vm/src/module/isolate_handle.h +47 -0
  84. package/dist/node_modules/isolated-vm/src/module/lib_handle.cc +77 -0
  85. package/dist/node_modules/isolated-vm/src/module/lib_handle.h +28 -0
  86. package/dist/node_modules/isolated-vm/src/module/module_handle.cc +475 -0
  87. package/dist/node_modules/isolated-vm/src/module/module_handle.h +68 -0
  88. package/dist/node_modules/isolated-vm/src/module/native_module_handle.cc +104 -0
  89. package/dist/node_modules/isolated-vm/src/module/native_module_handle.h +49 -0
  90. package/dist/node_modules/isolated-vm/src/module/reference_handle.cc +636 -0
  91. package/dist/node_modules/isolated-vm/src/module/reference_handle.h +106 -0
  92. package/dist/node_modules/isolated-vm/src/module/script_handle.cc +107 -0
  93. package/dist/node_modules/isolated-vm/src/module/script_handle.h +37 -0
  94. package/dist/node_modules/isolated-vm/src/module/session_handle.cc +173 -0
  95. package/dist/node_modules/isolated-vm/src/module/session_handle.h +31 -0
  96. package/dist/node_modules/isolated-vm/src/module/transferable.cc +268 -0
  97. package/dist/node_modules/isolated-vm/src/module/transferable.h +42 -0
  98. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v18.0.0.h +360 -0
  99. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v18.3.0.h +376 -0
  100. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v20.0.0.h +397 -0
  101. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v22.0.0.h +419 -0
  102. package/dist/node_modules/winston-transport/package.json +1 -1
  103. package/dist/server/IsolatedVm.js +75 -0
  104. package/dist/server/ScriptInstruction.d.ts +6 -0
  105. package/dist/server/ScriptInstruction.js +11 -1
  106. package/dist/server/Vm.js +42 -27
  107. package/package.json +3 -2
@@ -0,0 +1,233 @@
1
+ #include "timer.h"
2
+ #include <cassert>
3
+ #include <chrono>
4
+ #include <condition_variable>
5
+ #include <mutex>
6
+ #include <queue>
7
+ #include <thread>
8
+ #include <utility>
9
+ #include <unordered_set>
10
+
11
+ namespace ivm {
12
+
13
+ /**
14
+ * Contains data on a timer. This is shared between the timer_t handle and the thread responsible
15
+ * for the timer.
16
+ */
17
+ struct timer_data_t {
18
+ timer_data_t(
19
+ std::chrono::steady_clock::time_point timeout,
20
+ void** holder,
21
+ timer_t::callback_t callback,
22
+ const std::lock_guard<std::mutex>& /*lock*/
23
+ ) : callback{std::move(callback)}, holder{holder}, timeout{timeout} {
24
+ if (holder != nullptr) {
25
+ last_holder_value = std::exchange(*holder, static_cast<void*>(this));
26
+ }
27
+ }
28
+
29
+ auto adjust() -> bool {
30
+ if (paused_duration == std::chrono::steady_clock::duration{}) {
31
+ return false;
32
+ } else {
33
+ timeout += paused_duration;
34
+ paused_duration = {};
35
+ return true;
36
+ }
37
+ }
38
+
39
+ auto is_paused() const -> bool {
40
+ return paused_at != std::chrono::steady_clock::time_point{};
41
+ }
42
+
43
+ void pause() {
44
+ paused_at = std::chrono::steady_clock::now();
45
+ }
46
+
47
+ void resume() {
48
+ paused_duration += std::chrono::steady_clock::now() - paused_at;
49
+ paused_at = {};
50
+ }
51
+
52
+ struct cmp {
53
+ auto operator()(const std::shared_ptr<timer_data_t>& left, const std::shared_ptr<timer_data_t>& right) const {
54
+ return left->timeout > right->timeout;
55
+ }
56
+ };
57
+
58
+ timer_t::callback_t callback;
59
+ void** holder = nullptr;
60
+ void* last_holder_value;
61
+ std::chrono::steady_clock::time_point timeout;
62
+ std::chrono::steady_clock::time_point paused_at{};
63
+ std::chrono::steady_clock::duration paused_duration{};
64
+ std::shared_ptr<timer_data_t> threadless_self;
65
+ bool is_alive = true;
66
+ bool is_running = false;
67
+ bool is_dtor_waiting = false;
68
+ };
69
+
70
+ namespace {
71
+
72
+ /**
73
+ * Stash these here in case statics are destroyed while the module is unloading but timers are still
74
+ * active
75
+ */
76
+ struct shared_state_t {
77
+ std::unordered_set<struct timer_thread_t*> threads;
78
+ std::condition_variable cv;
79
+ std::mutex mutex;
80
+ };
81
+ auto global_shared_state = std::make_shared<shared_state_t>();
82
+
83
+ /**
84
+ * Manager for a thread which handles 1 or many timers.
85
+ */
86
+ struct timer_thread_t {
87
+ explicit timer_thread_t(std::shared_ptr<timer_data_t> first_timer) :
88
+ next_timeout{first_timer->timeout}, shared_state{global_shared_state} {
89
+ queue.emplace(std::move(first_timer));
90
+ std::thread thread{[this] { entry(); }};
91
+ thread.detach();
92
+ }
93
+
94
+ void entry() {
95
+ std::unique_lock<std::mutex> lock{shared_state->mutex, std::defer_lock};
96
+ while (true) {
97
+ std::this_thread::sleep_until(next_timeout);
98
+ lock.lock();
99
+ next_timeout = std::chrono::steady_clock::now();
100
+ run_next(lock);
101
+ if (queue.empty()) {
102
+ auto ii = shared_state->threads.find(this);
103
+ assert(ii != shared_state->threads.end());
104
+ shared_state->threads.erase(ii);
105
+ lock.unlock();
106
+ delete this;
107
+ return;
108
+ }
109
+ next_timeout = queue.top()->timeout;
110
+ lock.unlock();
111
+ }
112
+ }
113
+
114
+ void maybe_run_next(std::unique_lock<std::mutex>& lock) {
115
+ if (!queue.empty() && queue.top()->timeout <= next_timeout) {
116
+ run_next(lock);
117
+ }
118
+ }
119
+
120
+ void run_next(std::unique_lock<std::mutex>& lock) {
121
+ auto data = queue.top();
122
+ queue.pop();
123
+ {
124
+ if (data->is_alive) {
125
+ if (data->is_paused()) {
126
+ data->threadless_self = std::move(data);
127
+ } else if (data->adjust()) {
128
+ start_or_join_timer(std::move(data), lock);
129
+ } else {
130
+ data->is_running = true;
131
+ lock.unlock();
132
+ data->callback(reinterpret_cast<void*>(this));
133
+ lock.lock();
134
+ data->is_running = false;
135
+ if (data->is_dtor_waiting) {
136
+ shared_state->cv.notify_all();
137
+ }
138
+ return;
139
+ }
140
+ } else {
141
+ data.reset();
142
+ }
143
+ }
144
+ maybe_run_next(lock);
145
+ }
146
+
147
+ // Requires lock
148
+ template <template<class> class Lock>
149
+ static void start_or_join_timer(std::shared_ptr<timer_data_t> data, const Lock<std::mutex>& /*lock*/) {
150
+ // Try to find a thread to put this timer into
151
+ for (const auto& thread : global_shared_state->threads) {
152
+ if (thread->next_timeout < data->timeout) {
153
+ thread->queue.push(std::move(data));
154
+ return;
155
+ }
156
+ }
157
+
158
+ // Time to spawn a new thread
159
+ global_shared_state->threads.insert(new timer_thread_t(std::move(data)));
160
+ }
161
+
162
+ std::priority_queue<
163
+ std::shared_ptr<timer_data_t>,
164
+ std::deque<std::shared_ptr<timer_data_t>>,
165
+ timer_data_t::cmp
166
+ > queue;
167
+ std::chrono::steady_clock::time_point next_timeout;
168
+ std::shared_ptr<shared_state_t> shared_state;
169
+ };
170
+
171
+ } // anonymous namespace
172
+
173
+ /**
174
+ * timer_t implementation
175
+ */
176
+ timer_t::timer_t(uint32_t ms, void** holder, const callback_t& callback) {
177
+ std::lock_guard<std::mutex> lock{global_shared_state->mutex};
178
+ data = std::make_shared<timer_data_t>(
179
+ std::chrono::steady_clock::now() + std::chrono::milliseconds{ms},
180
+ holder, callback,
181
+ lock
182
+ );
183
+ timer_thread_t::start_or_join_timer(data, lock);
184
+ }
185
+
186
+ timer_t::~timer_t() {
187
+ std::unique_lock<std::mutex> lock{global_shared_state->mutex};
188
+ if (data->is_running) {
189
+ data->is_dtor_waiting = true;
190
+ do {
191
+ global_shared_state->cv.wait(lock);
192
+ } while (data->is_running);
193
+ }
194
+ data->is_alive = false;
195
+ if (data->holder != nullptr) {
196
+ *data->holder = data->last_holder_value;
197
+ }
198
+ }
199
+
200
+ void timer_t::chain(void* ptr) {
201
+ auto& thread = *reinterpret_cast<timer_thread_t*>(ptr);
202
+ std::unique_lock<std::mutex> lock{global_shared_state->mutex};
203
+ thread.maybe_run_next(lock);
204
+ }
205
+
206
+ void timer_t::pause(void*& holder) {
207
+ std::unique_lock<std::mutex> lock{global_shared_state->mutex};
208
+ if (holder != nullptr) {
209
+ auto& data = *static_cast<timer_data_t*>(holder);
210
+ data.pause();
211
+ }
212
+ }
213
+
214
+ void timer_t::resume(void*& holder) {
215
+ std::unique_lock<std::mutex> lock{global_shared_state->mutex};
216
+ if (holder != nullptr) {
217
+ auto& data = *static_cast<timer_data_t*>(holder);
218
+ data.resume();
219
+ if (data.threadless_self) {
220
+ timer_thread_t::start_or_join_timer(std::move(data.threadless_self), lock);
221
+ }
222
+ }
223
+ }
224
+
225
+ void timer_t::wait_detached(uint32_t ms, const callback_t& callback) {
226
+ std::lock_guard<std::mutex> lock{global_shared_state->mutex};
227
+ timer_thread_t::start_or_join_timer(std::make_shared<timer_data_t>(
228
+ std::chrono::steady_clock::now() + std::chrono::milliseconds{ms},
229
+ nullptr, callback, lock
230
+ ), lock);
231
+ }
232
+
233
+ } // namespace ivm
@@ -0,0 +1,36 @@
1
+ #pragma once
2
+ #include <memory>
3
+ #include <functional>
4
+
5
+ namespace ivm {
6
+
7
+ /**
8
+ * isolated-vm could start timers from different threads which libuv isn't really cut out for, so
9
+ * I'm rolling my own here. The goal of the library is to have atomic timers without spawning a new
10
+ * thread for each timer.
11
+ */
12
+ struct timer_data_t;
13
+ class timer_t {
14
+ public:
15
+ using callback_t = std::function<void(void*)>;
16
+
17
+ // Runs a callback unless the `timer_t` destructor is called.
18
+ timer_t(uint32_t ms, void** holder, const callback_t& callback);
19
+ timer_t(uint32_t ms, const callback_t& callback) : timer_t{ms, nullptr, callback} {}
20
+ timer_t(const timer_t&) = delete;
21
+ ~timer_t();
22
+ auto operator= (const timer_t&) = delete;
23
+
24
+ // Runs a callback in `ms` with no `timer_t` object.
25
+ static void wait_detached(uint32_t ms, const callback_t& callback);
26
+ // Invoked from callbacks when they are done scheduling and may need to wait
27
+ static void chain(void* ptr);
28
+ // Pause/unpause timer callbacks
29
+ static void pause(void*& holder);
30
+ static void resume(void*& holder);
31
+
32
+ private:
33
+ std::shared_ptr<timer_data_t> data;
34
+ };
35
+
36
+ } // namespace ivm
@@ -0,0 +1,151 @@
1
+ #include "callback.h"
2
+
3
+ #include <utility>
4
+ #include "external_copy/serializer.h"
5
+ #include "isolate/external.h"
6
+ #include "isolate/three_phase_task.h"
7
+
8
+ using namespace v8;
9
+
10
+ namespace ivm {
11
+
12
+ /**
13
+ * CallbackHandle implementation
14
+ */
15
+ auto CallbackHandle::Definition() -> Local<FunctionTemplate> {
16
+ return Inherit<TransferableHandle>(MakeClass(
17
+ "Callback", ConstructorFunction<decltype(&New), &New>{}
18
+ ));
19
+ }
20
+
21
+ auto CallbackHandle::New(Local<Function> fn, MaybeLocal<Object> options) -> std::unique_ptr<CallbackHandle> {
22
+ auto context = Isolate::GetCurrent()->GetCurrentContext();
23
+
24
+ // Get function parameter count
25
+ auto maybe_length = Unmaybe(fn->Get(context, StringTable::Get().length))->Int32Value(context);
26
+ int length;
27
+ if (!maybe_length.To(&length)) {
28
+ length = 0;
29
+ }
30
+
31
+ // Read options
32
+ auto apply = CallbackHandle::InvokeData::Apply::Sync;
33
+ if (ReadOption(options, StringTable::Get().async, false)) {
34
+ apply = CallbackHandle::InvokeData::Apply::Async;
35
+ } else if (ReadOption(options, StringTable::Get().ignored, false)) {
36
+ apply = CallbackHandle::InvokeData::Apply::Ignored;
37
+ }
38
+
39
+ // Return handle instance
40
+ return std::make_unique<CallbackHandle>(CallbackHandle::Data{
41
+ HandleCast<std::string>(fn->GetDebugName()),
42
+ length,
43
+ RemoteHandle<Function>{fn},
44
+ RemoteHandle<Context>{context},
45
+ apply});
46
+ }
47
+
48
+ auto CallbackHandle::TransferOut() -> std::unique_ptr<Transferable> {
49
+ return std::make_unique<CallbackTransferable>(data);
50
+ }
51
+
52
+ /**
53
+ * Runner for invocation of functions created by `Callback`
54
+ */
55
+ class InvokeRunner : public ThreePhaseTask {
56
+ public:
57
+ InvokeRunner(CallbackHandle::Data data, const FunctionCallbackInfo<Value>& info) : data{std::move(data)} {
58
+ // Transfer arguments out
59
+ argv = std::make_unique<SerializedVector>(info);
60
+ }
61
+
62
+ void Phase2() final {
63
+ // Setup context
64
+ auto* isolate = Isolate::GetCurrent();
65
+ auto& env = IsolateEnvironment::GetCurrent();
66
+ auto context = Deref(data.context);
67
+ Context::Scope context_scope{context};
68
+ auto fn = Deref(data.callback);
69
+ // Copy arguments into isolate
70
+ auto argv_inner = argv->CopyIntoAsVector();
71
+ // Run function and transfer out
72
+ auto maybe_value = fn->Call(context, Undefined(isolate), argv_inner.size(), argv_inner.empty() ? nullptr : &argv_inner[0]);
73
+ if (env.DidHitMemoryLimit()) {
74
+ throw FatalRuntimeError("Isolate was disposed during execution due to memory limit");
75
+ } else if (env.terminated) {
76
+ throw FatalRuntimeError("Isolate was disposed during execution");
77
+ }
78
+ auto value = Unmaybe(maybe_value);
79
+ if (data.apply != CallbackHandle::Data::Apply::Ignored) {
80
+ result = TransferOut(value, TransferOptions{TransferOptions::Type::Copy});
81
+ }
82
+ }
83
+
84
+ auto Phase3() -> Local<Value> final {
85
+ if (result) {
86
+ return result->TransferIn();
87
+ } else {
88
+ return Undefined(Isolate::GetCurrent());
89
+ }
90
+ }
91
+
92
+ private:
93
+ CallbackHandle::InvokeData data;
94
+ std::unique_ptr<SerializedVector> argv;
95
+ std::unique_ptr<Transferable> result;
96
+ };
97
+
98
+ /**
99
+ * CallbackHandleTransferable implementation
100
+ */
101
+ CallbackTransferable::CallbackTransferable(CallbackHandle::Data& data) : data{data} {}
102
+
103
+ CallbackTransferable::CallbackTransferable(Local<Function> data) :
104
+ CallbackTransferable{data, Isolate::GetCurrent()->GetCurrentContext()} {}
105
+
106
+ CallbackTransferable::CallbackTransferable(Local<Function> fn, Local<Context> context) : data{
107
+ [&]() {
108
+ const auto name = fn->GetDebugName();
109
+ if (name->IsString()) {
110
+ return std::optional{HandleCast<std::string>(name)};
111
+ } else {
112
+ return std::optional<std::string>{};
113
+ }
114
+ }(),
115
+ HandleCast<int>(Unmaybe(fn->Get(context, StringTable::Get().length))),
116
+ RemoteHandle<Function>{fn},
117
+ RemoteHandle<Context>{context},
118
+ CallbackHandle::InvokeData::Apply::Sync
119
+ } {}
120
+
121
+ auto CallbackTransferable::TransferIn() -> Local<Value> {
122
+
123
+ // Instantiate function in isolate
124
+ auto* isolate = Isolate::GetCurrent();
125
+ auto context = isolate->GetCurrentContext();
126
+ auto external = MakeExternal<CallbackHandle::Data>(data);
127
+ auto fn = Unmaybe(Function::New(context, Invoke, external, data.length, ConstructorBehavior::kThrow));
128
+ if (data.name) {
129
+ fn->SetName(HandleCast<Local<String>>(*data.name));
130
+ }
131
+ return fn;
132
+ }
133
+
134
+ void CallbackTransferable::Invoke(const FunctionCallbackInfo<Value>& info) {
135
+ FunctorRunners::RunCallback(info, [&]() {
136
+ auto& data = *static_cast<CallbackHandle::Data*>(info.Data().As<External>()->Value());
137
+ auto& isolate = *data.context.GetIsolateHolder();
138
+ switch (data.apply) {
139
+ case CallbackHandle::Data::Apply::Sync:
140
+ return ThreePhaseTask::Run<0, InvokeRunner>(isolate, data, info);
141
+ case CallbackHandle::Data::Apply::Async:
142
+ return ThreePhaseTask::Run<1, InvokeRunner>(isolate, data, info);
143
+ case CallbackHandle::Data::Apply::Ignored:
144
+ return ThreePhaseTask::Run<2, InvokeRunner>(isolate, data, info);
145
+ default:
146
+ throw std::logic_error{"Unknown callback flag"};
147
+ }
148
+ });
149
+ }
150
+
151
+ } // namespace ivm
@@ -0,0 +1,64 @@
1
+ #pragma once
2
+ #include "transferable.h"
3
+ #include <optional>
4
+ #include <v8.h>
5
+ #include <tuple>
6
+ #include <utility>
7
+
8
+ namespace ivm {
9
+
10
+ /**
11
+ * Holds a reference to a function in an arbitrary isolate
12
+ */
13
+ class CallbackHandle : public TransferableHandle {
14
+ public:
15
+ template <class ...Args>
16
+ explicit CallbackHandle(Args&&... args) : data{std::forward<Args>(args)...} {}
17
+
18
+ static auto Definition() -> v8::Local<v8::FunctionTemplate>;
19
+ static auto New(v8::Local<v8::Function> fn, v8::MaybeLocal<v8::Object> maybe_options) ->
20
+ std::unique_ptr<CallbackHandle>;
21
+ auto TransferOut() -> std::unique_ptr<Transferable> final;
22
+
23
+ void Release();
24
+
25
+ struct InvokeData {
26
+ enum class Apply { Async, Ignored, Sync };
27
+ RemoteHandle<v8::Function> callback;
28
+ RemoteHandle<v8::Context> context;
29
+ Apply apply{};
30
+ };
31
+
32
+ struct Data : public InvokeData {
33
+ Data() = default;
34
+
35
+ template <class ...Args>
36
+ Data(std::optional<std::string> name, int length, Args&&... args) :
37
+ InvokeData{std::forward<Args>(args)...},
38
+ name{std::move(name)}, length{length} {}
39
+
40
+ std::optional<std::string> name;
41
+ int length = 0;
42
+ };
43
+
44
+ private:
45
+ Data data;
46
+ };
47
+
48
+ /**
49
+ * Internal transferable handle for callback
50
+ */
51
+ class CallbackTransferable : public Transferable {
52
+ public:
53
+ explicit CallbackTransferable(CallbackHandle::Data& data);
54
+ explicit CallbackTransferable(v8::Local<v8::Function> data);
55
+ CallbackTransferable(v8::Local<v8::Function> fn, v8::Local<v8::Context> context);
56
+
57
+ auto TransferIn() -> v8::Local<v8::Value> final;
58
+
59
+ private:
60
+ static void Invoke(const v8::FunctionCallbackInfo<v8::Value>& info);
61
+ CallbackHandle::Data data;
62
+ };
63
+
64
+ } // namespace ivm