@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,257 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <v8.h>
|
|
3
|
+
#include "error.h"
|
|
4
|
+
#include "../v8_version.h"
|
|
5
|
+
|
|
6
|
+
namespace ivm {
|
|
7
|
+
|
|
8
|
+
// Internal handle conversion error. All these `HandleCastImpl` functions are templated and inlined and
|
|
9
|
+
// throwing generates verbose asm so this is implementated as a static function to clean up the
|
|
10
|
+
// typical case
|
|
11
|
+
struct ParamIncorrect : std::exception {
|
|
12
|
+
explicit ParamIncorrect(const char* type) : type{type} {}
|
|
13
|
+
[[noreturn]] static void Throw(const char* type) { throw ParamIncorrect{type}; }
|
|
14
|
+
const char* type;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Common arguments for casting functions
|
|
18
|
+
class HandleCastArguments {
|
|
19
|
+
private:
|
|
20
|
+
// Most of the time we won't need the context (and it is never needed in "strict" casting mode).
|
|
21
|
+
// This little holder will only call GetCurrentContext() when needed because the optimizer can't
|
|
22
|
+
// elide the call in any circumstances
|
|
23
|
+
class ContextHolder {
|
|
24
|
+
public:
|
|
25
|
+
explicit ContextHolder(v8::Isolate* isolate) : isolate{isolate} {}
|
|
26
|
+
inline operator v8::Local<v8::Context>() const { // NOLINT(hicpp-explicit-conversions)
|
|
27
|
+
if (context.IsEmpty()) {
|
|
28
|
+
context = isolate->GetCurrentContext();
|
|
29
|
+
}
|
|
30
|
+
return context;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private:
|
|
34
|
+
v8::Isolate* const isolate;
|
|
35
|
+
mutable v8::Local<v8::Context> context{};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
public:
|
|
39
|
+
HandleCastArguments() : HandleCastArguments{true, v8::Isolate::GetCurrent()} {}
|
|
40
|
+
|
|
41
|
+
HandleCastArguments(bool strict, v8::Isolate* isolate) :
|
|
42
|
+
isolate{isolate}, context{isolate}, strict{strict} {}
|
|
43
|
+
|
|
44
|
+
HandleCastArguments(const v8::FunctionCallbackInfo<v8::Value>& info) : // NOLINT(hicpp-explicit-conversions)
|
|
45
|
+
HandleCastArguments{true, info.GetIsolate()} {}
|
|
46
|
+
|
|
47
|
+
HandleCastArguments(const v8::PropertyCallbackInfo<v8::Value>& info) : // NOLINT(hicpp-explicit-conversions)
|
|
48
|
+
HandleCastArguments{true, info.GetIsolate()} {}
|
|
49
|
+
|
|
50
|
+
HandleCastArguments(const v8::PropertyCallbackInfo<void>& info) : // NOLINT(hicpp-explicit-conversions)
|
|
51
|
+
HandleCastArguments{true, info.GetIsolate()} {}
|
|
52
|
+
|
|
53
|
+
v8::Isolate* const isolate;
|
|
54
|
+
const ContextHolder context;
|
|
55
|
+
const bool strict;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Helper
|
|
59
|
+
template <class Type>
|
|
60
|
+
struct HandleCastTag {};
|
|
61
|
+
|
|
62
|
+
// Explicit casts: printf("%d\n", HandleCastImpl<int>(value));
|
|
63
|
+
template <class Type, class Value>
|
|
64
|
+
auto HandleCast(Value&& value, HandleCastArguments arguments = {}) -> Type {
|
|
65
|
+
return HandleCastImpl(std::forward<Value>(value), arguments, HandleCastTag<Type>{});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Identity cast
|
|
69
|
+
template <class Type>
|
|
70
|
+
inline auto HandleCastImpl(Type value, const HandleCastArguments& /*arguments*/, HandleCastTag<Type> /*tag*/) {
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Local<Value> -> Local<...> conversions
|
|
75
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& /*arguments*/, HandleCastTag<v8::Local<v8::Array>> /*tag*/) {
|
|
76
|
+
if (value->IsArray()) {
|
|
77
|
+
return value.As<v8::Array>();
|
|
78
|
+
}
|
|
79
|
+
ParamIncorrect::Throw("an array");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& arguments, HandleCastTag<v8::Local<v8::Boolean>> /*tag*/) {
|
|
83
|
+
if (value->IsBoolean()) {
|
|
84
|
+
return value.As<v8::Boolean>();
|
|
85
|
+
} else if (!arguments.strict) {
|
|
86
|
+
return value->ToBoolean(arguments.isolate);
|
|
87
|
+
}
|
|
88
|
+
ParamIncorrect::Throw("a boolean");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& /*arguments*/, HandleCastTag<v8::Local<v8::Function>> /*tag*/) {
|
|
92
|
+
if (value->IsFunction()) {
|
|
93
|
+
return value.As<v8::Function>();
|
|
94
|
+
}
|
|
95
|
+
ParamIncorrect::Throw("a function");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& /*arguments*/, HandleCastTag<v8::Local<v8::Int32>> /*tag*/) {
|
|
99
|
+
if (value->IsInt32()) {
|
|
100
|
+
return value.As<v8::Int32>();
|
|
101
|
+
}
|
|
102
|
+
ParamIncorrect::Throw("a 32-bit number");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& /*arguments*/, HandleCastTag<v8::Local<v8::Uint32>> /*tag*/) {
|
|
106
|
+
if (value->IsUint32()) {
|
|
107
|
+
return value.As<v8::Uint32>();
|
|
108
|
+
}
|
|
109
|
+
ParamIncorrect::Throw("a 32-bit number");
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& /*arguments*/, HandleCastTag<v8::Local<v8::Number>> /*tag*/) {
|
|
113
|
+
if (value->IsNumber()) {
|
|
114
|
+
return value.As<v8::Number>();
|
|
115
|
+
}
|
|
116
|
+
ParamIncorrect::Throw("a number");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& /*arguments*/, HandleCastTag<v8::Local<v8::Object>> /*tag*/) {
|
|
120
|
+
if (value->IsObject()) {
|
|
121
|
+
return value.As<v8::Object>();
|
|
122
|
+
}
|
|
123
|
+
ParamIncorrect::Throw("an object");
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& arguments, HandleCastTag<v8::Local<v8::String>> /*tag*/) {
|
|
127
|
+
if (value->IsString()) {
|
|
128
|
+
return value.As<v8::String>();
|
|
129
|
+
} else if (!arguments.strict) {
|
|
130
|
+
return Unmaybe(value->ToString(arguments.context));
|
|
131
|
+
}
|
|
132
|
+
ParamIncorrect::Throw("a string");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Local<Value> -> MaybeLocal<...> conversions
|
|
136
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& /*arguments*/, HandleCastTag<v8::MaybeLocal<v8::Array>> /*tag*/)
|
|
137
|
+
-> v8::MaybeLocal<v8::Array> {
|
|
138
|
+
if (value->IsNullOrUndefined()) {
|
|
139
|
+
return {};
|
|
140
|
+
} else if (value->IsArray()) {
|
|
141
|
+
return {value.As<v8::Array>()};
|
|
142
|
+
}
|
|
143
|
+
ParamIncorrect::Throw("an array");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& /*arguments*/, HandleCastTag<v8::MaybeLocal<v8::Function>> /*tag*/)
|
|
147
|
+
-> v8::MaybeLocal<v8::Function> {
|
|
148
|
+
if (value->IsNullOrUndefined()) {
|
|
149
|
+
return {};
|
|
150
|
+
} else if (value->IsFunction()) {
|
|
151
|
+
return {value.As<v8::Function>()};
|
|
152
|
+
}
|
|
153
|
+
ParamIncorrect::Throw("a function");
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& /*arguments*/, HandleCastTag<v8::MaybeLocal<v8::Object>> /*tag*/)
|
|
157
|
+
-> v8::MaybeLocal<v8::Object> {
|
|
158
|
+
if (value->IsNullOrUndefined()) {
|
|
159
|
+
return {};
|
|
160
|
+
} else if (value->IsObject()) {
|
|
161
|
+
return {value.As<v8::Object>()};
|
|
162
|
+
}
|
|
163
|
+
ParamIncorrect::Throw("an object");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& arguments, HandleCastTag<v8::MaybeLocal<v8::String>> /*tag*/)
|
|
167
|
+
-> v8::MaybeLocal<v8::String> {
|
|
168
|
+
if (value->IsNullOrUndefined()) {
|
|
169
|
+
return {};
|
|
170
|
+
} else if (value->IsString()) {
|
|
171
|
+
return {value.As<v8::String>()};
|
|
172
|
+
} else if (!arguments.strict) {
|
|
173
|
+
return {Unmaybe(value->ToString(arguments.context))};
|
|
174
|
+
}
|
|
175
|
+
ParamIncorrect::Throw("a string");
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& /*arguments*/, HandleCastTag<v8::MaybeLocal<v8::Value>> /*tag*/) {
|
|
179
|
+
return v8::MaybeLocal<v8::Value>{value};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Local<...> -> native C++ conversions
|
|
183
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& arguments, HandleCastTag<bool> /*tag*/) {
|
|
184
|
+
return HandleCast<bool>(HandleCast<v8::Local<v8::Boolean>>(value, arguments), arguments);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
inline auto HandleCastImpl(v8::Local<v8::Boolean> value, const HandleCastArguments& /*arguments*/, HandleCastTag<bool> /*tag*/) {
|
|
188
|
+
return value->Value();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& arguments, HandleCastTag<double> /*tag*/) {
|
|
192
|
+
return HandleCast<double>(HandleCast<v8::Local<v8::Number>>(value, arguments), arguments);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
inline auto HandleCastImpl(v8::Local<v8::Number> value, const HandleCastArguments& /*arguments*/, HandleCastTag<double> /*tag*/) {
|
|
196
|
+
return value->Value();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& arguments, HandleCastTag<int32_t> /*tag*/) {
|
|
200
|
+
return HandleCast<int32_t>(HandleCast<v8::Local<v8::Int32>>(value, arguments), arguments);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
inline auto HandleCastImpl(v8::Local<v8::Int32> value, const HandleCastArguments& /*arguments*/, HandleCastTag<int32_t> /*tag*/) {
|
|
204
|
+
return value->Value();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& arguments, HandleCastTag<uint32_t> /*tag*/) {
|
|
208
|
+
return HandleCast<uint32_t>(HandleCast<v8::Local<v8::Uint32>>(value, arguments), arguments);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
inline auto HandleCastImpl(v8::Local<v8::Uint32> value, const HandleCastArguments& /*arguments*/, HandleCastTag<uint32_t> /*tag*/) {
|
|
212
|
+
return value->Value();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
inline auto HandleCastImpl(v8::Local<v8::Value> value, const HandleCastArguments& arguments, HandleCastTag<std::string> /*tag*/) {
|
|
216
|
+
return HandleCast<std::string>(HandleCast<v8::Local<v8::String>>(value, arguments), arguments);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
inline auto HandleCastImpl(v8::Local<v8::String> value, const HandleCastArguments& arguments, HandleCastTag<std::string> /*tag*/) {
|
|
220
|
+
v8::String::Utf8Value utf8_value{arguments.isolate, value};
|
|
221
|
+
return std::string{*utf8_value, static_cast<size_t>(utf8_value.length())};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// native C++ -> Local<Value> conversions
|
|
225
|
+
inline auto HandleCastImpl(bool value, const HandleCastArguments& arguments, HandleCastTag<v8::Local<v8::Boolean>> /*tag*/) {
|
|
226
|
+
return v8::Boolean::New(arguments.isolate, value);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
inline auto HandleCastImpl(int32_t value, const HandleCastArguments& arguments, HandleCastTag<v8::Local<v8::Integer>> /*tag*/) {
|
|
230
|
+
return v8::Integer::New(arguments.isolate, value);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
inline auto HandleCastImpl(uint32_t value, const HandleCastArguments& arguments, HandleCastTag<v8::Local<v8::Integer>> /*tag*/) {
|
|
234
|
+
return v8::Integer::NewFromUnsigned(arguments.isolate, value);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
inline auto HandleCastImpl(int64_t value, const HandleCastArguments& arguments, HandleCastTag<v8::Local<v8::BigInt>> /*tag*/) {
|
|
238
|
+
return v8::BigInt::New(arguments.isolate, value);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
inline auto HandleCastImpl(uint64_t value, const HandleCastArguments& arguments, HandleCastTag<v8::Local<v8::BigInt>> /*tag*/) {
|
|
242
|
+
return v8::BigInt::NewFromUnsigned(arguments.isolate, value);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
inline auto HandleCastImpl(double value, const HandleCastArguments& arguments, HandleCastTag<v8::Local<v8::Number>> /*tag*/) {
|
|
246
|
+
return v8::Number::New(arguments.isolate, value);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
inline auto HandleCastImpl(const char* value, const HandleCastArguments& arguments, HandleCastTag<v8::Local<v8::String>> /*tag*/) {
|
|
250
|
+
return Unmaybe(v8::String::NewFromUtf8(arguments.isolate, value, v8::NewStringType::kNormal));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
inline auto HandleCastImpl(const std::string& value, const HandleCastArguments& arguments, HandleCastTag<v8::Local<v8::String>> /*tag*/) {
|
|
254
|
+
return Unmaybe(v8::String::NewFromUtf8(arguments.isolate, value.c_str(), v8::NewStringType::kNormal, value.size()));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
} // namespace ivm
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <v8.h>
|
|
3
|
+
#include "handle_cast.h"
|
|
4
|
+
|
|
5
|
+
namespace ivm {
|
|
6
|
+
namespace detail {
|
|
7
|
+
|
|
8
|
+
struct ParamRequired : std::exception {};
|
|
9
|
+
|
|
10
|
+
template <class Type, class Property, class Default>
|
|
11
|
+
inline auto ReadOptionImpl(v8::MaybeLocal<v8::Object> maybe_options, Property&& property, Default default_fn) {
|
|
12
|
+
HandleCastArguments arguments;
|
|
13
|
+
auto property_handle = HandleCast<v8::Local<v8::String>>(std::forward<Property>(property), arguments);
|
|
14
|
+
try {
|
|
15
|
+
v8::Local<v8::Object> options;
|
|
16
|
+
if (maybe_options.ToLocal(&options)) {
|
|
17
|
+
v8::Local<v8::Value> value = Unmaybe(options->Get(arguments.context, property_handle));
|
|
18
|
+
if (value->IsNullOrUndefined()) {
|
|
19
|
+
return default_fn();
|
|
20
|
+
}
|
|
21
|
+
return HandleCast<Type>(value, arguments);
|
|
22
|
+
} else {
|
|
23
|
+
return default_fn();
|
|
24
|
+
}
|
|
25
|
+
} catch (const ParamIncorrect& ex) {
|
|
26
|
+
throw RuntimeTypeError{
|
|
27
|
+
std::string{"`"}+ *v8::String::Utf8Value{arguments.isolate, property_handle}+ "` must be "+ ex.type
|
|
28
|
+
};
|
|
29
|
+
} catch (const ParamRequired&) {
|
|
30
|
+
throw RuntimeTypeError(
|
|
31
|
+
std::string{"`"}+ *v8::String::Utf8Value{arguments.isolate, property_handle}+ "` is required");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
} // namespace detail
|
|
36
|
+
|
|
37
|
+
template <class Type, class Options, class Property>
|
|
38
|
+
auto ReadOption(Options options, Property&& property) {
|
|
39
|
+
return detail::ReadOptionImpl<Type>(options, std::forward<Property>(property), []() { throw detail::ParamRequired(); });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
template <class Type, class Options, class Property>
|
|
43
|
+
auto ReadOption(Options options, Property&& property, Type default_value) {
|
|
44
|
+
return detail::ReadOptionImpl<Type>(options, std::forward<Property>(property), [&]() { return std::move(default_value); });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#include "holder.h"
|
|
2
|
+
#include "environment.h"
|
|
3
|
+
#include "scheduler.h"
|
|
4
|
+
#include "util.h"
|
|
5
|
+
#include "lib/timer.h"
|
|
6
|
+
#include <utility>
|
|
7
|
+
|
|
8
|
+
namespace ivm {
|
|
9
|
+
|
|
10
|
+
void IsolateDisposeWait::IsolateDidDispose() {
|
|
11
|
+
*is_disposed.write() = true;
|
|
12
|
+
is_disposed.notify_all();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
void IsolateDisposeWait::Join() {
|
|
16
|
+
auto lock = is_disposed.read<true>();
|
|
17
|
+
while (!*lock) {
|
|
18
|
+
lock.wait();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
auto IsolateHolder::GetCurrent() -> std::shared_ptr<IsolateHolder> {
|
|
23
|
+
return IsolateEnvironment::GetCurrentHolder();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
auto IsolateHolder::Dispose() -> bool {
|
|
27
|
+
auto ref = std::exchange(*isolate.write(), {});
|
|
28
|
+
if (ref) {
|
|
29
|
+
ref->Terminate();
|
|
30
|
+
ref.reset();
|
|
31
|
+
return true;
|
|
32
|
+
} else {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
void IsolateHolder::Release() {
|
|
38
|
+
auto ref = std::exchange(*isolate.write(), {});
|
|
39
|
+
ref.reset();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
auto IsolateHolder::GetIsolate() -> std::shared_ptr<IsolateEnvironment> {
|
|
43
|
+
return *isolate.read();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
void IsolateHolder::ScheduleTask(std::unique_ptr<Runnable> task, bool run_inline, bool wake_isolate, bool handle_task) {
|
|
47
|
+
auto ref = *isolate.read();
|
|
48
|
+
if (ref) {
|
|
49
|
+
if (run_inline && Executor::MayRunInlineTasks(*ref)) {
|
|
50
|
+
task->Run();
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
auto lock = ref->scheduler->Lock();
|
|
54
|
+
if (handle_task) {
|
|
55
|
+
lock->handle_tasks.push(std::move(task));
|
|
56
|
+
} else {
|
|
57
|
+
lock->tasks.push(std::move(task));
|
|
58
|
+
}
|
|
59
|
+
if (wake_isolate) {
|
|
60
|
+
lock->WakeIsolate(std::move(ref));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Methods for v8::TaskRunner
|
|
66
|
+
void IsolateTaskRunner::PostTask(std::unique_ptr<v8::Task> task) {
|
|
67
|
+
auto env = weak_env.lock();
|
|
68
|
+
if (env) {
|
|
69
|
+
env->GetScheduler().Lock()->tasks.push(std::move(task));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
void IsolateTaskRunner::PostDelayedTask(std::unique_ptr<v8::Task> task, double delay_in_seconds) {
|
|
74
|
+
// wait_detached erases the type of the lambda into a std::function which must be
|
|
75
|
+
// copyable. The unique_ptr is stored in a shared pointer so ownership can be handled correctly.
|
|
76
|
+
auto shared_task = std::make_shared<std::unique_ptr<v8::Task>>(std::move(task));
|
|
77
|
+
auto weak_env = this->weak_env;
|
|
78
|
+
timer_t::wait_detached(static_cast<uint32_t>(delay_in_seconds * 1000), [shared_task, weak_env](void* next) {
|
|
79
|
+
auto env = weak_env.lock();
|
|
80
|
+
if (env) {
|
|
81
|
+
// Don't wake the isolate, this will just run the next time the isolate is doing something
|
|
82
|
+
env->GetScheduler().Lock()->tasks.push(std::move(*shared_task));
|
|
83
|
+
}
|
|
84
|
+
timer_t::chain(next);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
} // namespace ivm
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include "platform_delegate.h"
|
|
3
|
+
#include "runnable.h"
|
|
4
|
+
#include "v8_version.h"
|
|
5
|
+
#include "lib/lockable.h"
|
|
6
|
+
#include <v8-platform.h>
|
|
7
|
+
#include <condition_variable>
|
|
8
|
+
#include <mutex>
|
|
9
|
+
#include <memory>
|
|
10
|
+
|
|
11
|
+
namespace ivm {
|
|
12
|
+
|
|
13
|
+
class IsolateEnvironment;
|
|
14
|
+
|
|
15
|
+
class IsolateDisposeWait {
|
|
16
|
+
public:
|
|
17
|
+
void IsolateDidDispose();
|
|
18
|
+
void Join();
|
|
19
|
+
|
|
20
|
+
private:
|
|
21
|
+
lockable_t<bool, false, true> is_disposed{false};
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
class IsolateHolder {
|
|
25
|
+
friend IsolateEnvironment;
|
|
26
|
+
|
|
27
|
+
public:
|
|
28
|
+
explicit IsolateHolder(std::shared_ptr<IsolateEnvironment> isolate) :
|
|
29
|
+
isolate{std::move(isolate)} {}
|
|
30
|
+
IsolateHolder(const IsolateHolder&) = delete;
|
|
31
|
+
~IsolateHolder() = default;
|
|
32
|
+
auto operator=(const IsolateHolder&) = delete;
|
|
33
|
+
|
|
34
|
+
static auto GetCurrent() -> std::shared_ptr<IsolateHolder>;
|
|
35
|
+
|
|
36
|
+
auto Dispose() -> bool;
|
|
37
|
+
void Release();
|
|
38
|
+
auto GetIsolate() -> std::shared_ptr<IsolateEnvironment>;
|
|
39
|
+
void ScheduleTask(std::unique_ptr<Runnable> task, bool run_inline, bool wake_isolate, bool handle_task = false);
|
|
40
|
+
|
|
41
|
+
private:
|
|
42
|
+
lockable_t<std::shared_ptr<IsolateEnvironment>> isolate;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// This needs to be separate from IsolateHolder because v8 holds references to this indefinitely and
|
|
46
|
+
// we don't want it keeping the isolate alive.
|
|
47
|
+
class IsolateTaskRunner final : public TaskRunner {
|
|
48
|
+
public:
|
|
49
|
+
explicit IsolateTaskRunner(const std::shared_ptr<IsolateEnvironment>& isolate) : weak_env{isolate} {}
|
|
50
|
+
IsolateTaskRunner(const IsolateTaskRunner&) = delete;
|
|
51
|
+
~IsolateTaskRunner() final = default;
|
|
52
|
+
auto operator=(const IsolateTaskRunner&) = delete;
|
|
53
|
+
|
|
54
|
+
// Methods for v8::TaskRunner
|
|
55
|
+
void PostTask(std::unique_ptr<v8::Task> task) final;
|
|
56
|
+
void PostDelayedTask(std::unique_ptr<v8::Task> task, double delay_in_seconds) final;
|
|
57
|
+
void PostNonNestableTask(std::unique_ptr<v8::Task> task) final { PostTask(std::move(task)); }
|
|
58
|
+
|
|
59
|
+
private:
|
|
60
|
+
std::weak_ptr<IsolateEnvironment> weak_env;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
} // namespace ivm
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#include "inspector.h"
|
|
2
|
+
#include "environment.h"
|
|
3
|
+
#include "runnable.h"
|
|
4
|
+
#include "util.h"
|
|
5
|
+
#include "lib/timer.h"
|
|
6
|
+
#include <string>
|
|
7
|
+
|
|
8
|
+
using namespace ivm;
|
|
9
|
+
using namespace v8;
|
|
10
|
+
using namespace v8_inspector;
|
|
11
|
+
using std::shared_ptr;
|
|
12
|
+
using std::unique_ptr;
|
|
13
|
+
|
|
14
|
+
namespace ivm {
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* This constructor will be called from a non-locked thread.
|
|
18
|
+
*/
|
|
19
|
+
InspectorAgent::InspectorAgent(IsolateEnvironment& isolate) : isolate(isolate), inspector(V8Inspector::create(isolate, this)) {
|
|
20
|
+
struct AddDefaultContext : public Runnable {
|
|
21
|
+
InspectorAgent& that;
|
|
22
|
+
explicit AddDefaultContext(InspectorAgent& agent) : that(agent) {}
|
|
23
|
+
void Run() final {
|
|
24
|
+
// We can assume that agent is still alive because otherwise this won't get called
|
|
25
|
+
that.ContextCreated(that.isolate.DefaultContext(), "default");
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
SendInterrupt(std::make_unique<AddDefaultContext>(*this));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Called right before the isolate is disposed.
|
|
33
|
+
*/
|
|
34
|
+
InspectorAgent::~InspectorAgent() {
|
|
35
|
+
auto sessions_lock = active_sessions.write();
|
|
36
|
+
for (auto ii = sessions_lock->begin(); ii != sessions_lock->end(); ) {
|
|
37
|
+
InspectorSession* session = *ii;
|
|
38
|
+
++ii;
|
|
39
|
+
session->Disconnect();
|
|
40
|
+
}
|
|
41
|
+
assert(sessions_lock->empty());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* When debugging running JS code this function is called and is expected to block and process
|
|
46
|
+
* inspector messages until the inspector is done. This happens in the isolate's currently running
|
|
47
|
+
* thread so we know that an Executor::Lock is up.
|
|
48
|
+
*/
|
|
49
|
+
void InspectorAgent::runMessageLoopOnPause(int /*context_group_id*/) {
|
|
50
|
+
if (terminated) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
Executor::PauseScope pause_cpu_timer{isolate.executor.cpu_timer};
|
|
54
|
+
std::unique_lock<std::mutex> lock{mutex};
|
|
55
|
+
running = true;
|
|
56
|
+
do {
|
|
57
|
+
cv.wait(lock);
|
|
58
|
+
lock.unlock();
|
|
59
|
+
{
|
|
60
|
+
Executor::UnpauseScope unpause_cpu_timer{pause_cpu_timer};
|
|
61
|
+
isolate.InterruptEntryAsync();
|
|
62
|
+
}
|
|
63
|
+
lock.lock();
|
|
64
|
+
} while (running && !terminated);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* This is the notificaiton to exit from the currently running `runMessageLoopOnPause` from another
|
|
69
|
+
* thread.
|
|
70
|
+
*/
|
|
71
|
+
void InspectorAgent::quitMessageLoopOnPause() {
|
|
72
|
+
// This is called from within runMessageLoopOnPause, therefore lock is already acquired
|
|
73
|
+
running = false;
|
|
74
|
+
cv.notify_all();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Connects a V8Inspector::Channel to a V8Inspector which returns an instance of V8InspectorSession.
|
|
79
|
+
*/
|
|
80
|
+
auto InspectorAgent::ConnectSession(InspectorSession& session) -> unique_ptr<V8InspectorSession> {
|
|
81
|
+
active_sessions.write()->insert(&session);
|
|
82
|
+
#if V8_AT_LEAST(10, 3, 118)
|
|
83
|
+
return inspector->connect(1, &session, StringView(), v8_inspector::V8Inspector::ClientTrustLevel::kFullyTrusted);
|
|
84
|
+
#else
|
|
85
|
+
return inspector->connect(1, &session, StringView());
|
|
86
|
+
#endif
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Called from the session when it disconnects.
|
|
91
|
+
*/
|
|
92
|
+
void InspectorAgent::SessionDisconnected(InspectorSession& session) {
|
|
93
|
+
assert(active_sessions.write()->erase(&session) == 1);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Request to send an interrupt to the inspected isolate
|
|
98
|
+
*/
|
|
99
|
+
void InspectorAgent::SendInterrupt(unique_ptr<Runnable> task) {
|
|
100
|
+
// If this isolate is already locked just run the task. This happens at least when the isolate is disposing
|
|
101
|
+
// and `holder` no longer has a valid shared_ptr
|
|
102
|
+
if (Executor::GetCurrentEnvironment() == &isolate) {
|
|
103
|
+
task->Run();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// Grab pointer because it's needed for WakeIsolate
|
|
107
|
+
auto holder = isolate.holder.lock();
|
|
108
|
+
assert(holder);
|
|
109
|
+
auto ptr = holder->GetIsolate();
|
|
110
|
+
assert(ptr);
|
|
111
|
+
// Push interrupt onto queue
|
|
112
|
+
auto scheduler_lock = isolate.scheduler->Lock();
|
|
113
|
+
scheduler_lock->interrupts.push(std::move(task));
|
|
114
|
+
// Wake up the isolate
|
|
115
|
+
if (!scheduler_lock->WakeIsolate(ptr)) { // `true` if isolate is inactive
|
|
116
|
+
// Isolate is currently running
|
|
117
|
+
std::lock_guard<std::mutex> lock{mutex};
|
|
118
|
+
if (running) {
|
|
119
|
+
// Isolate is being debugged and is in `runMessageLoopOnPause`
|
|
120
|
+
cv.notify_all();
|
|
121
|
+
} else {
|
|
122
|
+
// Isolate is busy running JS code
|
|
123
|
+
scheduler_lock->InterruptIsolate();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Hook to add context to agent.
|
|
130
|
+
*/
|
|
131
|
+
void InspectorAgent::ContextCreated(Local<Context> context, const std::string& name) {
|
|
132
|
+
inspector->contextCreated(V8ContextInfo(context, 1, StringView(reinterpret_cast<const uint8_t*>(name.c_str()), name.length())));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Hook to remove context from agent.
|
|
137
|
+
*/
|
|
138
|
+
void InspectorAgent::ContextDestroyed(Local<Context> context) {
|
|
139
|
+
inspector->contextDestroyed(context);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Called when this isolate needs to dispose, disables all inspector activity
|
|
144
|
+
*/
|
|
145
|
+
void InspectorAgent::Terminate() {
|
|
146
|
+
std::lock_guard<std::mutex> lock(mutex);
|
|
147
|
+
terminated = true;
|
|
148
|
+
cv.notify_all();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Creates a new session and connects it to a given agent.
|
|
153
|
+
*/
|
|
154
|
+
InspectorSession::InspectorSession(IsolateEnvironment& isolate) : agent(*isolate.GetInspectorAgent()), session(agent.ConnectSession(*this)) {}
|
|
155
|
+
|
|
156
|
+
InspectorSession::~InspectorSession() {
|
|
157
|
+
Disconnect();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Disconnects this session from the v8 inspector. Allows inspector to deallocate gracefully.
|
|
162
|
+
*/
|
|
163
|
+
void InspectorSession::Disconnect() {
|
|
164
|
+
std::lock_guard<std::mutex> lock(mutex);
|
|
165
|
+
if (session) {
|
|
166
|
+
agent.SessionDisconnected(*this);
|
|
167
|
+
struct DeleteSession : public Runnable {
|
|
168
|
+
shared_ptr<V8InspectorSession> session;
|
|
169
|
+
explicit DeleteSession(shared_ptr<V8InspectorSession> session) : session(std::move(session)) {}
|
|
170
|
+
// Nothing is needed since the dtor will (should) delete the session in the right context
|
|
171
|
+
void Run() final {}
|
|
172
|
+
};
|
|
173
|
+
agent.SendInterrupt(std::make_unique<DeleteSession>(std::move(session)));
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Send a message from this session to the backend.
|
|
179
|
+
*/
|
|
180
|
+
void InspectorSession::DispatchBackendProtocolMessage(std::vector<uint16_t> message) {
|
|
181
|
+
std::lock_guard<std::mutex> lock(mutex);
|
|
182
|
+
if (session) {
|
|
183
|
+
struct DispatchMessage : public Runnable {
|
|
184
|
+
std::vector<uint16_t> message;
|
|
185
|
+
std::weak_ptr<V8InspectorSession> weak_session;
|
|
186
|
+
explicit DispatchMessage(std::vector<uint16_t> message, shared_ptr<V8InspectorSession>& session) : message(std::move(message)), weak_session(session) {}
|
|
187
|
+
void Run() final {
|
|
188
|
+
auto session = weak_session.lock();
|
|
189
|
+
if (session) {
|
|
190
|
+
session->dispatchProtocolMessage(StringView(&message[0], message.size()));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
agent.SendInterrupt(std::make_unique<DispatchMessage>(std::move(message), session));
|
|
195
|
+
} else {
|
|
196
|
+
throw RuntimeGenericError("Session is dead");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
} // namespace ivm
|