@nocobase/plugin-workflow-javascript 2.1.0-beta.11 → 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.
- package/dist/externalVersion.js +4 -4
- package/dist/node_modules/isolated-vm/.clang-tidy +13 -0
- package/dist/node_modules/isolated-vm/.dockerignore +9 -0
- package/dist/node_modules/isolated-vm/Dockerfile.alpine +9 -0
- package/dist/node_modules/isolated-vm/Dockerfile.debian +12 -0
- package/dist/node_modules/isolated-vm/LICENSE +13 -0
- package/dist/node_modules/isolated-vm/binding.gyp +120 -0
- package/dist/node_modules/isolated-vm/include.js +3 -0
- package/dist/node_modules/isolated-vm/inspector-example.js +59 -0
- package/dist/node_modules/isolated-vm/isolated-vm.d.ts +820 -0
- package/dist/node_modules/isolated-vm/isolated-vm.js +1 -0
- package/dist/node_modules/isolated-vm/native-example/binding.gyp +23 -0
- package/dist/node_modules/isolated-vm/native-example/example.cc +61 -0
- package/dist/node_modules/isolated-vm/native-example/package.json +13 -0
- package/dist/node_modules/isolated-vm/native-example/usage.js +35 -0
- package/dist/node_modules/isolated-vm/out/isolated_vm.node +0 -0
- package/dist/node_modules/isolated-vm/package.json +1 -0
- package/dist/node_modules/isolated-vm/src/external_copy/error.h +33 -0
- package/dist/node_modules/isolated-vm/src/external_copy/external_copy.cc +509 -0
- package/dist/node_modules/isolated-vm/src/external_copy/external_copy.h +117 -0
- package/dist/node_modules/isolated-vm/src/external_copy/serializer.cc +85 -0
- package/dist/node_modules/isolated-vm/src/external_copy/serializer.h +136 -0
- package/dist/node_modules/isolated-vm/src/external_copy/serializer_nortti.cc +73 -0
- package/dist/node_modules/isolated-vm/src/external_copy/string.cc +124 -0
- package/dist/node_modules/isolated-vm/src/external_copy/string.h +28 -0
- package/dist/node_modules/isolated-vm/src/isolate/allocator.h +32 -0
- package/dist/node_modules/isolated-vm/src/isolate/allocator_nortti.cc +142 -0
- package/dist/node_modules/isolated-vm/src/isolate/class_handle.h +334 -0
- package/dist/node_modules/isolated-vm/src/isolate/cpu_profile_manager.cc +220 -0
- package/dist/node_modules/isolated-vm/src/isolate/cpu_profile_manager.h +100 -0
- package/dist/node_modules/isolated-vm/src/isolate/environment.cc +626 -0
- package/dist/node_modules/isolated-vm/src/isolate/environment.h +381 -0
- package/dist/node_modules/isolated-vm/src/isolate/executor.cc +198 -0
- package/dist/node_modules/isolated-vm/src/isolate/executor.h +183 -0
- package/dist/node_modules/isolated-vm/src/isolate/external.h +64 -0
- package/dist/node_modules/isolated-vm/src/isolate/functor_runners.h +97 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/array.h +145 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/callbacks.h +272 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/error.h +140 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/extract_params.h +145 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/handle_cast.h +257 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/read_option.h +47 -0
- package/dist/node_modules/isolated-vm/src/isolate/holder.cc +88 -0
- package/dist/node_modules/isolated-vm/src/isolate/holder.h +63 -0
- package/dist/node_modules/isolated-vm/src/isolate/inspector.cc +200 -0
- package/dist/node_modules/isolated-vm/src/isolate/inspector.h +70 -0
- package/dist/node_modules/isolated-vm/src/isolate/node_wrapper.h +15 -0
- package/dist/node_modules/isolated-vm/src/isolate/platform_delegate.cc +22 -0
- package/dist/node_modules/isolated-vm/src/isolate/platform_delegate.h +46 -0
- package/dist/node_modules/isolated-vm/src/isolate/remote_handle.h +164 -0
- package/dist/node_modules/isolated-vm/src/isolate/run_with_timeout.h +171 -0
- package/dist/node_modules/isolated-vm/src/isolate/runnable.h +29 -0
- package/dist/node_modules/isolated-vm/src/isolate/scheduler.cc +191 -0
- package/dist/node_modules/isolated-vm/src/isolate/scheduler.h +165 -0
- package/dist/node_modules/isolated-vm/src/isolate/specific.h +35 -0
- package/dist/node_modules/isolated-vm/src/isolate/stack_trace.cc +219 -0
- package/dist/node_modules/isolated-vm/src/isolate/stack_trace.h +24 -0
- package/dist/node_modules/isolated-vm/src/isolate/strings.h +127 -0
- package/dist/node_modules/isolated-vm/src/isolate/three_phase_task.cc +385 -0
- package/dist/node_modules/isolated-vm/src/isolate/three_phase_task.h +136 -0
- package/dist/node_modules/isolated-vm/src/isolate/transferable.h +15 -0
- package/dist/node_modules/isolated-vm/src/isolate/util.h +45 -0
- package/dist/node_modules/isolated-vm/src/isolate/v8_inspector_wrapper.h +12 -0
- package/dist/node_modules/isolated-vm/src/isolate/v8_version.h +12 -0
- package/dist/node_modules/isolated-vm/src/isolated_vm.h +71 -0
- package/dist/node_modules/isolated-vm/src/lib/covariant.h +50 -0
- package/dist/node_modules/isolated-vm/src/lib/lockable.h +178 -0
- package/dist/node_modules/isolated-vm/src/lib/suspend.h +106 -0
- package/dist/node_modules/isolated-vm/src/lib/thread_pool.cc +98 -0
- package/dist/node_modules/isolated-vm/src/lib/thread_pool.h +45 -0
- package/dist/node_modules/isolated-vm/src/lib/timer.cc +233 -0
- package/dist/node_modules/isolated-vm/src/lib/timer.h +36 -0
- package/dist/node_modules/isolated-vm/src/module/callback.cc +151 -0
- package/dist/node_modules/isolated-vm/src/module/callback.h +64 -0
- package/dist/node_modules/isolated-vm/src/module/context_handle.cc +241 -0
- package/dist/node_modules/isolated-vm/src/module/context_handle.h +35 -0
- package/dist/node_modules/isolated-vm/src/module/evaluation.cc +109 -0
- package/dist/node_modules/isolated-vm/src/module/evaluation.h +99 -0
- package/dist/node_modules/isolated-vm/src/module/external_copy_handle.cc +119 -0
- package/dist/node_modules/isolated-vm/src/module/external_copy_handle.h +64 -0
- package/dist/node_modules/isolated-vm/src/module/isolate.cc +136 -0
- package/dist/node_modules/isolated-vm/src/module/isolate_handle.cc +611 -0
- package/dist/node_modules/isolated-vm/src/module/isolate_handle.h +47 -0
- package/dist/node_modules/isolated-vm/src/module/lib_handle.cc +77 -0
- package/dist/node_modules/isolated-vm/src/module/lib_handle.h +28 -0
- package/dist/node_modules/isolated-vm/src/module/module_handle.cc +475 -0
- package/dist/node_modules/isolated-vm/src/module/module_handle.h +68 -0
- package/dist/node_modules/isolated-vm/src/module/native_module_handle.cc +104 -0
- package/dist/node_modules/isolated-vm/src/module/native_module_handle.h +49 -0
- package/dist/node_modules/isolated-vm/src/module/reference_handle.cc +636 -0
- package/dist/node_modules/isolated-vm/src/module/reference_handle.h +106 -0
- package/dist/node_modules/isolated-vm/src/module/script_handle.cc +107 -0
- package/dist/node_modules/isolated-vm/src/module/script_handle.h +37 -0
- package/dist/node_modules/isolated-vm/src/module/session_handle.cc +173 -0
- package/dist/node_modules/isolated-vm/src/module/session_handle.h +31 -0
- package/dist/node_modules/isolated-vm/src/module/transferable.cc +268 -0
- package/dist/node_modules/isolated-vm/src/module/transferable.h +42 -0
- package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v18.0.0.h +360 -0
- package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v18.3.0.h +376 -0
- package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v20.0.0.h +397 -0
- package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v22.0.0.h +419 -0
- package/dist/node_modules/winston-transport/package.json +1 -1
- package/dist/server/IsolatedVm.js +75 -0
- package/dist/server/ScriptInstruction.d.ts +6 -0
- package/dist/server/ScriptInstruction.js +11 -1
- package/dist/server/Vm.js +42 -27
- 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
|