@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,636 @@
1
+ #include "reference_handle.h"
2
+ #include "external_copy/external_copy.h"
3
+ #include "isolate/run_with_timeout.h"
4
+ #include "isolate/three_phase_task.h"
5
+ #include "transferable.h"
6
+ #include <array>
7
+
8
+ using namespace v8;
9
+ using std::shared_ptr;
10
+ using std::unique_ptr;
11
+
12
+ namespace ivm {
13
+ namespace {
14
+
15
+ using TypeOf = detail::ReferenceData::TypeOf;
16
+ auto InferTypeOf(Local<Value> value) -> TypeOf {
17
+ if (value->IsNull()) {
18
+ return TypeOf::Null;
19
+ } else if (value->IsUndefined()) {
20
+ return TypeOf::Undefined;
21
+ } else if (value->IsNumber()) {
22
+ return TypeOf::Number;
23
+ } else if (value->IsString()) {
24
+ return TypeOf::String;
25
+ } else if (value->IsBoolean()) {
26
+ return TypeOf::Boolean;
27
+ } else if (value->IsFunction()) {
28
+ return TypeOf::Function;
29
+ } else {
30
+ return TypeOf::Object;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * The return value for .derefInto()
36
+ */
37
+ class DereferenceHandleTransferable : public Transferable {
38
+ public:
39
+ DereferenceHandleTransferable(shared_ptr<IsolateHolder> isolate, RemoteHandle<v8::Value> reference) :
40
+ isolate{std::move(isolate)}, reference{std::move(reference)} {}
41
+
42
+ auto TransferIn() -> v8::Local<v8::Value> final {
43
+ if (isolate == IsolateEnvironment::GetCurrentHolder()) {
44
+ return Deref(reference);
45
+ } else {
46
+ throw RuntimeTypeError("Cannot dereference this into target isolate");
47
+ }
48
+ }
49
+
50
+ private:
51
+ shared_ptr<IsolateHolder> isolate;
52
+ RemoteHandle<v8::Value> reference;
53
+ };
54
+
55
+ class DereferenceHandle : public TransferableHandle {
56
+ public:
57
+ DereferenceHandle(shared_ptr<IsolateHolder> isolate, RemoteHandle<v8::Value> reference) :
58
+ isolate{std::move(isolate)}, reference{std::move(reference)} {}
59
+
60
+ static auto Definition() -> v8::Local<v8::FunctionTemplate> {
61
+ return Inherit<TransferableHandle>(MakeClass("Dereference", nullptr));
62
+ }
63
+
64
+ auto TransferOut() -> std::unique_ptr<Transferable> final {
65
+ if (!reference) {
66
+ throw RuntimeGenericError("The return value of `derefInto()` should only be used once");
67
+ }
68
+ return std::make_unique<DereferenceHandleTransferable>(std::move(isolate), std::move(reference));
69
+ }
70
+
71
+ private:
72
+ shared_ptr<IsolateHolder> isolate;
73
+ RemoteHandle<v8::Value> reference;
74
+ };
75
+
76
+ } // anonymous namespace
77
+
78
+ namespace detail {
79
+
80
+ ReferenceData::ReferenceData(Local<Value> value, bool inherit) : ReferenceData{
81
+ IsolateEnvironment::GetCurrentHolder(),
82
+ RemoteHandle<Value>(value),
83
+ RemoteHandle<Context>(Isolate::GetCurrent()->GetCurrentContext()),
84
+ InferTypeOf(value),
85
+ false,
86
+ inherit} {}
87
+
88
+ ReferenceData::ReferenceData(
89
+ shared_ptr<IsolateHolder> isolate,
90
+ RemoteHandle<Value> reference,
91
+ RemoteHandle<Context> context,
92
+ TypeOf type_of,
93
+ bool accessors,
94
+ bool inherit
95
+ ) :
96
+ isolate{std::move(isolate)},
97
+ reference{std::move(reference)},
98
+ context{std::move(context)},
99
+ type_of{type_of},
100
+ accessors{accessors},
101
+ inherit{inherit} {}
102
+
103
+ } // namespace detail
104
+
105
+ /**
106
+ * ReferenceHandle implementation
107
+ */
108
+ auto ReferenceHandle::Definition() -> Local<FunctionTemplate> {
109
+ return Inherit<TransferableHandle>(MakeClass(
110
+ "Reference", ConstructorFunction<decltype(&New), &New>{},
111
+ "deref", MemberFunction<decltype(&ReferenceHandle::Deref), &ReferenceHandle::Deref>{},
112
+ "derefInto", MemberFunction<decltype(&ReferenceHandle::DerefInto), &ReferenceHandle::DerefInto>{},
113
+ "release", MemberFunction<decltype(&ReferenceHandle::Release), &ReferenceHandle::Release>{},
114
+ "copy", MemberFunction<decltype(&ReferenceHandle::Copy<1>), &ReferenceHandle::Copy<1>>{},
115
+ "copySync", MemberFunction<decltype(&ReferenceHandle::Copy<0>), &ReferenceHandle::Copy<0>>{},
116
+ "delete", MemberFunction<decltype(&ReferenceHandle::Delete<1>), &ReferenceHandle::Delete<1>>{},
117
+ "deleteIgnored", MemberFunction<decltype(&ReferenceHandle::Delete<2>), &ReferenceHandle::Delete<2>>{},
118
+ "deleteSync", MemberFunction<decltype(&ReferenceHandle::Delete<0>), &ReferenceHandle::Delete<0>>{},
119
+ "get", MemberFunction<decltype(&ReferenceHandle::Get<1>), &ReferenceHandle::Get<1>>{},
120
+ "getSync", MemberFunction<decltype(&ReferenceHandle::Get<0>), &ReferenceHandle::Get<0>>{},
121
+ "set", MemberFunction<decltype(&ReferenceHandle::Set<1>), &ReferenceHandle::Set<1>>{},
122
+ "setIgnored", MemberFunction<decltype(&ReferenceHandle::Set<2>), &ReferenceHandle::Set<2>>{},
123
+ "setSync", MemberFunction<decltype(&ReferenceHandle::Set<0>), &ReferenceHandle::Set<0>>{},
124
+ "apply", MemberFunction<decltype(&ReferenceHandle::Apply<1>), &ReferenceHandle::Apply<1>>{},
125
+ "applyIgnored", MemberFunction<decltype(&ReferenceHandle::Apply<2>), &ReferenceHandle::Apply<2>>{},
126
+ "applySync", MemberFunction<decltype(&ReferenceHandle::Apply<0>), &ReferenceHandle::Apply<0>>{},
127
+ "applySyncPromise", MemberFunction<decltype(&ReferenceHandle::Apply<4>), &ReferenceHandle::Apply<4>>{},
128
+ "typeof", MemberAccessor<decltype(&ReferenceHandle::TypeOfGetter), &ReferenceHandle::TypeOfGetter>{}
129
+ ));
130
+ }
131
+
132
+ auto ReferenceHandle::New(Local<Value> value, MaybeLocal<Object> options) -> unique_ptr<ReferenceHandle> {
133
+ auto inherit = ReadOption<bool>(options, StringTable::Get().unsafeInherit, false);
134
+ return std::make_unique<ReferenceHandle>(value, inherit);
135
+ }
136
+
137
+ auto ReferenceHandle::TransferOut() -> unique_ptr<Transferable> {
138
+ return std::make_unique<ReferenceHandleTransferable>(*this);
139
+ }
140
+
141
+ /**
142
+ * Getter for typeof property.
143
+ */
144
+ auto ReferenceHandle::TypeOfGetter() -> Local<Value> {
145
+ CheckDisposed();
146
+ switch (type_of) {
147
+ case TypeOf::Null:
148
+ return StringTable::Get().null;
149
+ case TypeOf::Undefined:
150
+ return StringTable::Get().undefined;
151
+ case TypeOf::Number:
152
+ return StringTable::Get().number;
153
+ case TypeOf::String:
154
+ return StringTable::Get().string;
155
+ case TypeOf::Boolean:
156
+ return StringTable::Get().boolean;
157
+ case TypeOf::Object:
158
+ return StringTable::Get().object;
159
+ case TypeOf::Function:
160
+ return StringTable::Get().function;
161
+ }
162
+ std::terminate();
163
+ }
164
+
165
+ /**
166
+ * Attempt to return this handle to the current context.
167
+ */
168
+ auto ReferenceHandle::Deref(MaybeLocal<Object> maybe_options) -> Local<Value> {
169
+ CheckDisposed();
170
+ if (isolate.get() != IsolateEnvironment::GetCurrentHolder().get()) {
171
+ throw RuntimeTypeError("Cannot dereference this from current isolate");
172
+ }
173
+ bool release = ReadOption<bool>(maybe_options, StringTable::Get().release, false);
174
+ Local<Value> ret = ivm::Deref(reference);
175
+ if (release) {
176
+ Release();
177
+ }
178
+ return ret;
179
+ }
180
+
181
+ /**
182
+ * Return a handle which will dereference itself when passing into another isolate.
183
+ */
184
+ auto ReferenceHandle::DerefInto(MaybeLocal<Object> maybe_options) -> Local<Value> {
185
+ CheckDisposed();
186
+ bool release = ReadOption<bool>(maybe_options, StringTable::Get().release, false);
187
+ Local<Value> ret = ClassHandle::NewInstance<DereferenceHandle>(isolate, reference);
188
+ if (release) {
189
+ Release();
190
+ }
191
+ return ret;
192
+ }
193
+
194
+ /**
195
+ * Release this reference.
196
+ */
197
+ auto ReferenceHandle::Release() -> Local<Value> {
198
+ CheckDisposed();
199
+ isolate.reset();
200
+ reference = {};
201
+ context = {};
202
+ return Undefined(Isolate::GetCurrent());
203
+ }
204
+
205
+ /**
206
+ * Call a function, like Function.prototype.apply
207
+ */
208
+ class ApplyRunner : public ThreePhaseTask {
209
+ public:
210
+ ApplyRunner(
211
+ ReferenceHandle& that,
212
+ MaybeLocal<Value> recv_handle,
213
+ Maybe<ArrayRange> maybe_arguments,
214
+ MaybeLocal<Object> maybe_options
215
+ ) : context{that.context}, reference{that.reference}
216
+ {
217
+ that.CheckDisposed();
218
+
219
+ // Get receiver, holder, this, whatever
220
+ Local<Value> recv_local;
221
+ if (recv_handle.ToLocal(&recv_local)) {
222
+ recv = TransferOut(recv_local);
223
+ }
224
+
225
+ // Get run options
226
+ TransferOptions arguments_transfer_options;
227
+ Local<Object> options;
228
+ if (maybe_options.ToLocal(&options)) {
229
+ timeout = ReadOption<int32_t>(options, StringTable::Get().timeout, 0);
230
+ arguments_transfer_options = TransferOptions{
231
+ ReadOption<MaybeLocal<Object>>(options, StringTable::Get().arguments, {})};
232
+ return_transfer_options = TransferOptions{
233
+ ReadOption<MaybeLocal<Object>>(options, StringTable::Get().result, {}),
234
+ TransferOptions::Type::Reference};
235
+ }
236
+
237
+ // Externalize all arguments
238
+ ArrayRange arguments;
239
+ if (maybe_arguments.To(&arguments)) {
240
+ argv.reserve(std::distance(arguments.begin(), arguments.end()));
241
+ for (auto argument : arguments) {
242
+ argv.push_back(TransferOut(argument, arguments_transfer_options));
243
+ }
244
+ }
245
+ }
246
+
247
+ ApplyRunner(const ApplyRunner&) = delete;
248
+ auto operator=(const ApplyRunner&) = delete;
249
+
250
+ ~ApplyRunner() final {
251
+ if (did_finish) {
252
+ *did_finish = 1;
253
+ }
254
+ }
255
+
256
+ void Phase2() final {
257
+ // Invoke in the isolate
258
+ Local<Context> context_handle = Deref(context);
259
+ Context::Scope context_scope{context_handle};
260
+ Local<Value> fn = Deref(reference);
261
+ if (!fn->IsFunction()) {
262
+ throw RuntimeTypeError("Reference is not a function");
263
+ }
264
+ std::vector<Local<Value>> argv_inner = TransferArguments();
265
+ Local<Value> recv_inner = recv->TransferIn();
266
+ Local<Value> result = RunWithTimeout(timeout,
267
+ [&fn, &context_handle, &recv_inner, &argv_inner]() {
268
+ return fn.As<Function>()->Call(context_handle, recv_inner, argv_inner.size(), argv_inner.empty() ? nullptr : &argv_inner[0]);
269
+ }
270
+ );
271
+ ret = TransferOut(result, return_transfer_options);
272
+ }
273
+
274
+ auto Phase2Async(Scheduler::AsyncWait& wait) -> bool final {
275
+ // Same as regular `Phase2()` but if it returns a promise we will wait on it
276
+ if (!(return_transfer_options == TransferOptions{TransferOptions::Type::Reference})) {
277
+ throw RuntimeTypeError("`result` options are not available for `applySyncPromise`");
278
+ }
279
+ Local<Context> context_handle = Deref(context);
280
+ Context::Scope context_scope{context_handle};
281
+ Local<Value> fn = Deref(reference);
282
+ if (!fn->IsFunction()) {
283
+ throw RuntimeTypeError("Reference is not a function");
284
+ }
285
+ Local<Value> recv_inner = recv->TransferIn();
286
+ std::vector<Local<Value>> argv_inner = TransferArguments();
287
+ Local<Value> value = RunWithTimeout(
288
+ timeout,
289
+ [&fn, &context_handle, &recv_inner, &argv_inner]() {
290
+ return fn.As<Function>()->Call(context_handle, recv_inner, argv_inner.size(), argv_inner.empty() ? nullptr : &argv_inner[0]);
291
+ }
292
+ );
293
+ if (value->IsPromise()) {
294
+ Isolate* isolate = Isolate::GetCurrent();
295
+ // This is only called from the default isolate, so we don't need an IsolateSpecific
296
+ static Persistent<Function> callback_persistent{isolate, CompileAsyncWrapper()};
297
+ Local<Function> callback_fn = Deref(callback_persistent);
298
+ did_finish = std::make_shared<char>(0);
299
+ std::array<Local<Value>, 3> argv;
300
+ argv[0] = External::New(isolate, reinterpret_cast<void*>(this));
301
+ argv[1] = External::New(isolate, new shared_ptr<char>(did_finish));
302
+ argv[2] = value;
303
+ async_wait = &wait;
304
+ Unmaybe(callback_fn->Call(context_handle, callback_fn, 3, &argv.front()));
305
+ return true;
306
+ } else {
307
+ ret = TransferOut(value, return_transfer_options);
308
+ return false;
309
+ }
310
+ }
311
+
312
+ auto Phase3() -> Local<Value> final {
313
+ if (did_finish && *did_finish == 0) {
314
+ *did_finish = 1;
315
+ throw RuntimeGenericError("Script execution timed out.");
316
+ } else if (async_error) {
317
+ Isolate::GetCurrent()->ThrowException(async_error->CopyInto());
318
+ throw RuntimeError();
319
+ } else {
320
+ return ret->TransferIn();
321
+ }
322
+ }
323
+
324
+ private:
325
+ /**
326
+ * This is an internal callback that will be called after a Promise returned from
327
+ * `applySyncPromise` has resolved
328
+ */
329
+ static void AsyncCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
330
+ // It's possible the invocation timed out, in which case the ApplyRunner will be dead. The
331
+ // shared_ptr<bool> here will be marked as true and we can exit early.
332
+ auto* did_finish_ptr = reinterpret_cast<shared_ptr<char>*>(info[1].As<External>()->Value());
333
+ auto did_finish = std::move(*did_finish_ptr);
334
+ delete did_finish_ptr;
335
+ if (*did_finish == 1) {
336
+ return;
337
+ }
338
+ ApplyRunner& self = *reinterpret_cast<ApplyRunner*>(info[0].As<External>()->Value());
339
+ if (info.Length() == 3) {
340
+ // Resolved
341
+ FunctorRunners::RunCatchExternal(IsolateEnvironment::GetCurrent().DefaultContext(), [&self, &info]() {
342
+ self.ret = TransferOut(info[2]);
343
+ }, [&self](unique_ptr<ExternalCopy> error) {
344
+ self.async_error = std::move(error);
345
+ });
346
+ } else {
347
+ // Rejected
348
+ self.async_error = ExternalCopy::CopyThrownValue(info[3]);
349
+ }
350
+ *self.did_finish = 1;
351
+ self.async_wait->Done();
352
+ }
353
+
354
+ /**
355
+ * The C++ promise interface is a little clumsy so this does some work in JS for us. This function
356
+ * is called once and returns a JS function that will be reused.
357
+ */
358
+ static auto CompileAsyncWrapper() -> Local<Function> {
359
+ Isolate* isolate = Isolate::GetCurrent();
360
+ Local<Context> context = IsolateEnvironment::GetCurrent().DefaultContext();
361
+ Local<Script> script = Unmaybe(Script::Compile(context, v8_string(
362
+ "'use strict';"
363
+ "(function(AsyncCallback) {"
364
+ "return function(ptr, did_finish, promise) {"
365
+ "promise.then(function(val) {"
366
+ "AsyncCallback(ptr, did_finish, val);"
367
+ "}, function(err) {"
368
+ "AsyncCallback(ptr, did_finish, null, err);"
369
+ "});"
370
+ "};"
371
+ "})"
372
+ )));
373
+ Local<Value> outer_fn = Unmaybe(script->Run(context));
374
+ assert(outer_fn->IsFunction());
375
+ Local<Value> callback_fn = Unmaybe(FunctionTemplate::New(isolate, AsyncCallback)->GetFunction(context));
376
+ Local<Value> inner_fn = Unmaybe(outer_fn.As<Function>()->Call(context, Undefined(isolate), 1, &callback_fn));
377
+ assert(inner_fn->IsFunction());
378
+ return inner_fn.As<Function>();
379
+ }
380
+
381
+ auto TransferArguments() -> std::vector<Local<Value>> {
382
+ std::vector<Local<Value>> argv_inner;
383
+ size_t argc = argv.size();
384
+ argv_inner.reserve(argc);
385
+ for (size_t ii = 0; ii < argc; ++ii) {
386
+ argv_inner.emplace_back(argv[ii]->TransferIn());
387
+ }
388
+ return argv_inner;
389
+ }
390
+
391
+ std::vector<unique_ptr<Transferable>> argv;
392
+ RemoteHandle<Context> context;
393
+ RemoteHandle<Value> reference;
394
+ unique_ptr<Transferable> recv;
395
+ unique_ptr<Transferable> ret;
396
+ uint32_t timeout = 0;
397
+ // Only used in the AsyncPhase2 case
398
+ shared_ptr<char> did_finish; // GCC 5.4.0 `std::make_shared<bool>(...)` is broken(?)
399
+ TransferOptions return_transfer_options{TransferOptions::Type::Reference};
400
+ unique_ptr<ExternalCopy> async_error;
401
+ Scheduler::AsyncWait* async_wait = nullptr;
402
+ };
403
+ template <int async>
404
+ auto ReferenceHandle::Apply(MaybeLocal<Value> recv_handle, Maybe<ArrayRange> maybe_arguments, MaybeLocal<Object> maybe_options) -> Local<Value> {
405
+ return ThreePhaseTask::Run<async, ApplyRunner>(*isolate, *this, recv_handle, maybe_arguments, maybe_options);
406
+ }
407
+
408
+ /**
409
+ * Copy this reference's value into this isolate
410
+ */
411
+ class CopyRunner : public ThreePhaseTask {
412
+ public:
413
+ CopyRunner(
414
+ const ReferenceHandle& that,
415
+ RemoteHandle<Context> context,
416
+ RemoteHandle<Value> reference
417
+ ) : context{std::move(context)}, reference{std::move(reference)} {
418
+ that.CheckDisposed();
419
+ }
420
+
421
+ void Phase2() final {
422
+ Context::Scope context_scope{Deref(context)};
423
+ Local<Value> value = Deref(reference);
424
+ copy = ExternalCopy::Copy(value);
425
+ }
426
+
427
+ auto Phase3() -> Local<Value> final {
428
+ return copy->TransferIn();
429
+ }
430
+
431
+ private:
432
+ RemoteHandle<Context> context;
433
+ RemoteHandle<Value> reference;
434
+ unique_ptr<Transferable> copy;
435
+ };
436
+
437
+ template <int async>
438
+ auto ReferenceHandle::Copy() -> Local<Value> {
439
+ return ThreePhaseTask::Run<async, CopyRunner>(*isolate, *this, context, reference);
440
+ }
441
+
442
+ /**
443
+ * Base class for get, set, and delete runners
444
+ */
445
+ class AccessorRunner : public ThreePhaseTask {
446
+ public:
447
+ AccessorRunner(ReferenceHandle& target, Local<Value> key_handle) :
448
+ context{target.context},
449
+ target{target.reference},
450
+ key{ExternalCopy::CopyIfPrimitive(key_handle)} {
451
+ target.CheckDisposed();
452
+ if (!key || (!key_handle->IsName() && !key_handle->IsUint32())) {
453
+ throw RuntimeTypeError("Invalid `key`");
454
+ } else if (target.type_of != decltype(target.type_of)::Object) {
455
+ throw RuntimeTypeError("Reference is not an object");
456
+ }
457
+ }
458
+
459
+ protected:
460
+ auto GetTargetAndAlsoCheckForProxy() -> Local<Object> {
461
+ auto object = Local<Object>::Cast(Deref(target));
462
+ if (HasProxy(object)) {
463
+ throw RuntimeTypeError("Object is or has proxy");
464
+ }
465
+ return object;
466
+ }
467
+
468
+ auto GetKey(Local<Context> context) -> Local<Name> {
469
+ auto key_inner = key->CopyInto();
470
+ return (key_inner->IsString() || key_inner->IsSymbol()) ?
471
+ key_inner.As<Name>() : Unmaybe(key_inner->ToString(context)).As<Name>();
472
+ }
473
+
474
+ RemoteHandle<Context> context;
475
+
476
+ private:
477
+ static auto HasProxy(Local<Object> object) -> bool {
478
+ if (object->IsProxy()) {
479
+ return true;
480
+ } else {
481
+ auto proto = object->GetPrototype();
482
+ if (proto->IsNullOrUndefined()) {
483
+ return false;
484
+ } else {
485
+ return HasProxy(proto.As<Object>());
486
+ }
487
+ }
488
+ }
489
+
490
+ RemoteHandle<Value> target;
491
+ unique_ptr<ExternalCopy> key;
492
+ };
493
+
494
+ /**
495
+ * Get a property from this reference, returned as another reference
496
+ */
497
+ class GetRunner final : public AccessorRunner {
498
+ public:
499
+ GetRunner(ReferenceHandle& target, Local<Value> key_handle, MaybeLocal<Object> maybe_options) :
500
+ AccessorRunner{target, key_handle},
501
+ options{maybe_options, target.inherit ?
502
+ TransferOptions::Type::DeepReference : TransferOptions::Type::Reference},
503
+ accessors{target.accessors || ReadOption(maybe_options, StringTable::Get().accessors, false)},
504
+ inherit{target.inherit} {}
505
+
506
+ void Phase2() final {
507
+ // Setup
508
+ auto* isolate = Isolate::GetCurrent();
509
+ auto context = Deref(this->context);
510
+ Context::Scope context_scope{context};
511
+ auto name = GetKey(context);
512
+ auto object = GetTargetAndAlsoCheckForProxy();
513
+
514
+ // Get property
515
+ ret = TransferOut([&]() {
516
+ if (inherit) {
517
+ // To avoid accessors I guess we have to walk the prototype chain ourselves
518
+ auto target = object;
519
+ if (!accessors) {
520
+ do {
521
+ if (Unmaybe(target->HasOwnProperty(context, name))) {
522
+ if (Unmaybe(target->HasRealNamedCallbackProperty(context, name))) {
523
+ throw RuntimeTypeError("Property is getter");
524
+ }
525
+ return Unmaybe(target->GetRealNamedProperty(context, name));
526
+ }
527
+ auto next = target->GetPrototype();
528
+ if (next->IsNullOrUndefined()) {
529
+ return Undefined(isolate).As<Value>();
530
+ }
531
+ target = next.As<Object>();
532
+ } while (true);
533
+ }
534
+ } else if (!Unmaybe(object->HasOwnProperty(context, name))) {
535
+ return Undefined(isolate).As<Value>();
536
+ } else if (!accessors && Unmaybe(object->HasRealNamedCallbackProperty(context, name))) {
537
+ throw RuntimeTypeError("Property is getter");
538
+ }
539
+ return Unmaybe(object->Get(context, name));
540
+ }(), options);
541
+ }
542
+
543
+ auto Phase3() -> Local<Value> final {
544
+ return ret->TransferIn();
545
+ }
546
+
547
+ private:
548
+ unique_ptr<Transferable> ret;
549
+ TransferOptions options;
550
+ bool accessors;
551
+ bool inherit;
552
+ };
553
+ template <int async>
554
+ auto ReferenceHandle::Get(Local<Value> key_handle, MaybeLocal<Object> maybe_options) -> Local<Value> {
555
+ return ThreePhaseTask::Run<async, GetRunner>(*isolate, *this, key_handle, maybe_options);
556
+ }
557
+
558
+ /**
559
+ * Delete a property on this reference
560
+ */
561
+ class DeleteRunner final : public AccessorRunner {
562
+ public:
563
+ DeleteRunner(ReferenceHandle& that, Local<Value> key_handle) :
564
+ AccessorRunner{that, key_handle} {}
565
+
566
+ void Phase2() final {
567
+ auto context = Deref(this->context);
568
+ Context::Scope context_scope{context};
569
+ auto object = GetTargetAndAlsoCheckForProxy();
570
+ if (!Unmaybe(object->Delete(context, GetKey(context)))) {
571
+ throw RuntimeTypeError("Delete failed");
572
+ }
573
+ }
574
+
575
+ auto Phase3() -> Local<Value> final {
576
+ return Undefined(Isolate::GetCurrent());
577
+ }
578
+ };
579
+ template <int async>
580
+ auto ReferenceHandle::Delete(Local<Value> key_handle) -> Local<Value> {
581
+ return ThreePhaseTask::Run<async, DeleteRunner>(*isolate, *this, key_handle);
582
+ }
583
+
584
+ /**
585
+ * Attempt to set a property on this reference
586
+ */
587
+ class SetRunner final : public AccessorRunner {
588
+ public:
589
+ SetRunner(
590
+ ReferenceHandle& that,
591
+ Local<Value> key_handle,
592
+ Local<Value> val_handle,
593
+ MaybeLocal<Object> maybe_options
594
+ ) :
595
+ AccessorRunner{that, key_handle},
596
+ val{TransferOut(val_handle, TransferOptions{maybe_options})} {}
597
+
598
+ void Phase2() final {
599
+ auto context = Deref(this->context);
600
+ Context::Scope context_scope{context};
601
+ auto name = GetKey(context);
602
+ auto object = GetTargetAndAlsoCheckForProxy();
603
+ // Delete key before transferring in, potentially freeing up some v8 heap
604
+ Unmaybe(object->Delete(context, name));
605
+ auto val_inner = val->TransferIn();
606
+ if (!Unmaybe(object->CreateDataProperty(context, GetKey(context), val_inner))) {
607
+ throw RuntimeTypeError("Set failed");
608
+ }
609
+ }
610
+
611
+ auto Phase3() -> Local<Value> final {
612
+ return Undefined(Isolate::GetCurrent());
613
+ }
614
+
615
+ private:
616
+ unique_ptr<Transferable> val;
617
+ };
618
+ template <int async>
619
+ auto ReferenceHandle::Set(Local<Value> key_handle, Local<Value> val_handle, MaybeLocal<Object> maybe_options) -> Local<Value> {
620
+ return ThreePhaseTask::Run<async, SetRunner>(*isolate, *this, key_handle, val_handle, maybe_options);
621
+ }
622
+
623
+ void ReferenceHandle::CheckDisposed() const {
624
+ if (!reference) {
625
+ throw RuntimeGenericError("Reference has been released");
626
+ }
627
+ }
628
+
629
+ /**
630
+ * ReferenceHandleTransferable implementation
631
+ */
632
+ auto ReferenceHandleTransferable::TransferIn() -> Local<Value> {
633
+ return ClassHandle::NewInstance<ReferenceHandle>(std::move(*this));
634
+ }
635
+
636
+ } // namespace ivm