@nocobase/plugin-workflow-javascript 2.1.0-beta.11 → 2.1.0-beta.13
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,272 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <v8.h>
|
|
3
|
+
#include "error.h"
|
|
4
|
+
#include "extract_params.h"
|
|
5
|
+
|
|
6
|
+
namespace ivm {
|
|
7
|
+
namespace detail {
|
|
8
|
+
|
|
9
|
+
// Helper to extract arguments out of function
|
|
10
|
+
template <class Function>
|
|
11
|
+
struct extract_arguments;
|
|
12
|
+
|
|
13
|
+
template <class Function>
|
|
14
|
+
struct extract_arguments<Function*> : extract_arguments<Function> {};
|
|
15
|
+
|
|
16
|
+
template <class Return, class ...Args>
|
|
17
|
+
struct extract_arguments<Return(Args...)> {
|
|
18
|
+
using arguments = std::tuple<Args...>;
|
|
19
|
+
static constexpr auto index_sequence = std::make_index_sequence<sizeof...(Args)>{};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
template<class Class, class Return, class ...Args>
|
|
23
|
+
struct extract_arguments<Return(Class::*)(Args...)> : extract_arguments<Return(Args...)> {};
|
|
24
|
+
|
|
25
|
+
// Helper to turn Return(Class:*)(...) into Return(*)(Class&, ...)
|
|
26
|
+
template <class Signature>
|
|
27
|
+
struct unbind_member_function;
|
|
28
|
+
|
|
29
|
+
template <>
|
|
30
|
+
struct unbind_member_function<std::nullptr_t> {
|
|
31
|
+
using type = std::nullptr_t;
|
|
32
|
+
template <std::nullptr_t>
|
|
33
|
+
static constexpr auto invoke = nullptr;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
template <class Return, class ...Args>
|
|
37
|
+
struct unbind_member_function<Return(Args...)> {};
|
|
38
|
+
|
|
39
|
+
template<class Class, class Return, class ...Args>
|
|
40
|
+
struct unbind_member_function<Return(Class::*)(Args...)> {
|
|
41
|
+
using type = Return(*)(Class&, Args...);
|
|
42
|
+
template <Return(Class::*Function)(Args...)>
|
|
43
|
+
static inline auto invoke(Class& instance, Args... args) -> Return {
|
|
44
|
+
return (instance.*Function)(args...);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Callbacks that return `void` will return this instead which lets us pass it as an argument
|
|
49
|
+
struct VoidReturn {};
|
|
50
|
+
inline auto HandleCastImpl(VoidReturn /*value*/, HandleCastArguments arguments, HandleCastTag<v8::Local<v8::Value>> /*tag*/) {
|
|
51
|
+
return v8::Undefined(arguments.isolate);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Returns a `VoidReturn{}` from void functions, which is later converted to `undefined`. This
|
|
55
|
+
// is needed because the return value from any function needs to be used as a parameter to
|
|
56
|
+
// another function.
|
|
57
|
+
template <class Function>
|
|
58
|
+
inline auto InvokeWithoutVoid(
|
|
59
|
+
Function function,
|
|
60
|
+
typename std::enable_if<std::is_same<void, decltype(function())>::value>::type* /*conditional*/ = nullptr
|
|
61
|
+
) {
|
|
62
|
+
function();
|
|
63
|
+
return VoidReturn{};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
template <class Function>
|
|
67
|
+
inline decltype(auto) InvokeWithoutVoid(
|
|
68
|
+
Function function,
|
|
69
|
+
typename std::enable_if<!std::is_same<void, decltype(function())>::value>::type* /*conditional*/ = nullptr
|
|
70
|
+
) {
|
|
71
|
+
return function();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// The return value of C++ callbacks are run through this to forward the value to v8
|
|
75
|
+
template <class Type>
|
|
76
|
+
inline void Returner(Type return_value, const v8::FunctionCallbackInfo<v8::Value>& info) {
|
|
77
|
+
info.GetReturnValue().Set(HandleCast<v8::Local<v8::Value>>(return_value, info));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
template <class Type>
|
|
81
|
+
inline void Returner(Type return_value, v8::Local<v8::Name> /*name*/, const v8::PropertyCallbackInfo<v8::Value>& info) {
|
|
82
|
+
info.GetReturnValue().Set(HandleCast<v8::Local<v8::Value>>(return_value, info));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
inline void Returner(
|
|
86
|
+
VoidReturn /*return_value*/,
|
|
87
|
+
v8::Local<v8::Name> /*name*/,
|
|
88
|
+
v8::Local<v8::Value> /*value*/,
|
|
89
|
+
const v8::PropertyCallbackInfo<void>& /*info*/
|
|
90
|
+
) {}
|
|
91
|
+
|
|
92
|
+
// This the main entry point for all parameterized v8 callbacks
|
|
93
|
+
template <class Signature, Signature Function, int Offset, class ...Args>
|
|
94
|
+
struct CallbackMaker {
|
|
95
|
+
// This is responsible for unpacking the arguments from the C++ function, invoking the param
|
|
96
|
+
// extracter on the v8 info descriptors, and passing the results to the C++ function
|
|
97
|
+
template <size_t ...Indices>
|
|
98
|
+
static inline void Spread(Args... args, std::index_sequence<Indices...> /*indices*/) {
|
|
99
|
+
using FnArgs = typename extract_arguments<Signature>::arguments;
|
|
100
|
+
return Returner(InvokeWithoutVoid([&]() {
|
|
101
|
+
// ParamExtractor is implemented as a struct which holds the arguments because earlier
|
|
102
|
+
// versions of gcc segfault on nested template packs
|
|
103
|
+
ParamExtractor<Offset, Args...> extractor{args...};
|
|
104
|
+
// try/catch is here instead of in ParamExtractor to avoid having to set up / tear down stack
|
|
105
|
+
// guard once per parameter
|
|
106
|
+
try {
|
|
107
|
+
extractor.CheckLength(static_cast<FnArgs*>(nullptr));
|
|
108
|
+
return Function(extractor.template Invoke<Indices, std::tuple_element_t<Indices, FnArgs>>()...);
|
|
109
|
+
} catch (const ParamIncorrect& ex) {
|
|
110
|
+
extractor.Caught(ex);
|
|
111
|
+
}
|
|
112
|
+
}), args...);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Passed directly to v8
|
|
116
|
+
static void Callback(Args... args) {
|
|
117
|
+
RunBarrier([&]() {
|
|
118
|
+
Spread(args..., extract_arguments<Signature>::index_sequence);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
template <int Offset, class ...Args>
|
|
124
|
+
struct CallbackMaker<std::nullptr_t, nullptr, Offset, Args...> {
|
|
125
|
+
static constexpr std::nullptr_t Callback = nullptr;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Base type for all native callback pointers
|
|
129
|
+
template <class Type, class... Args>
|
|
130
|
+
struct GenericCallback {
|
|
131
|
+
constexpr explicit GenericCallback(Type callback) : callback{callback} {}
|
|
132
|
+
const Type callback;
|
|
133
|
+
|
|
134
|
+
template <int Offset, class Signature, Signature Function>
|
|
135
|
+
static constexpr auto ToCallback() -> Type {
|
|
136
|
+
return CallbackMaker<Signature, Function, Offset, Args...>::Callback;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Any callbacks in the form of `void callback(const v8::FunctionCallbackInfo<v8::Value>&)`
|
|
141
|
+
struct FunctionCallbackImpl : GenericCallback<v8::FunctionCallback,
|
|
142
|
+
const v8::FunctionCallbackInfo<v8::Value>&> {
|
|
143
|
+
constexpr FunctionCallbackImpl(std::nullptr_t /*nullptr*/) : GenericCallback{nullptr}, length{0} {} // NOLINT(hicpp-explicit-conversions)
|
|
144
|
+
constexpr FunctionCallbackImpl(v8::FunctionCallback callback, int length) :
|
|
145
|
+
GenericCallback{callback}, length{length} {}
|
|
146
|
+
const int length;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Functions meant to be called without a `this` parameter
|
|
150
|
+
struct FreeFunctionHolder : FunctionCallbackImpl {
|
|
151
|
+
using FunctionCallbackImpl::FunctionCallbackImpl;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
// Functions where `this` is castable into a native pointer
|
|
155
|
+
struct MemberFunctionHolder : FunctionCallbackImpl {
|
|
156
|
+
using FunctionCallbackImpl::FunctionCallbackImpl;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// Member getters and setters
|
|
160
|
+
struct MemberGetterHolder : GenericCallback<v8::AccessorNameGetterCallback,
|
|
161
|
+
v8::Local<v8::Name>, const v8::PropertyCallbackInfo<v8::Value>&> {
|
|
162
|
+
using GenericCallback::GenericCallback;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
struct MemberSetterHolder : GenericCallback<v8::AccessorNameSetterCallback,
|
|
166
|
+
v8::Local<v8::Name>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<void>&> {
|
|
167
|
+
using GenericCallback::GenericCallback;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
struct MemberAccessorHolder {
|
|
171
|
+
constexpr MemberAccessorHolder(MemberGetterHolder getter, MemberSetterHolder setter) : getter{getter}, setter{setter} {}
|
|
172
|
+
const MemberGetterHolder getter;
|
|
173
|
+
const MemberSetterHolder setter;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
// Static getters and setters
|
|
177
|
+
struct StaticGetterHolder : FreeFunctionHolder {
|
|
178
|
+
using FreeFunctionHolder::FreeFunctionHolder;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
struct StaticSetterHolder : FreeFunctionHolder {
|
|
182
|
+
using FreeFunctionHolder::FreeFunctionHolder;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
struct StaticAccessorHolder {
|
|
186
|
+
constexpr StaticAccessorHolder(StaticGetterHolder getter, StaticSetterHolder setter) : getter{getter}, setter{setter} {}
|
|
187
|
+
const StaticGetterHolder getter;
|
|
188
|
+
const StaticSetterHolder setter;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
} // namespace detail
|
|
192
|
+
|
|
193
|
+
// Public interfaces for implementation classes are kept separate to ensure there is a common
|
|
194
|
+
// interface for all instances of this template. For example it's easier to accept
|
|
195
|
+
// `detail::FreeFunctionHolder` as parameter vs `FreeFunction<..., ...>`.
|
|
196
|
+
template <class Signature, Signature Function>
|
|
197
|
+
struct FreeFunction : detail::FreeFunctionHolder {
|
|
198
|
+
using FreeFunctionHolder::FreeFunctionHolder;
|
|
199
|
+
constexpr FreeFunction() : FreeFunctionHolder{
|
|
200
|
+
ToCallback<0, Signature, Function>(),
|
|
201
|
+
std::tuple_size<typename detail::extract_arguments<Signature>::arguments>::value
|
|
202
|
+
} {}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
template <class Signature, Signature Function>
|
|
206
|
+
struct MemberFunction : detail::MemberFunctionHolder {
|
|
207
|
+
using MemberFunctionHolder::MemberFunctionHolder;
|
|
208
|
+
constexpr MemberFunction() : MemberFunctionHolder{
|
|
209
|
+
ToCallback<-1, typename Unbound::type, Unbound::template invoke<Function>>(),
|
|
210
|
+
std::tuple_size<typename detail::extract_arguments<Signature>::arguments>::value
|
|
211
|
+
} {}
|
|
212
|
+
|
|
213
|
+
private:
|
|
214
|
+
using Unbound = detail::unbind_member_function<Signature>;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
template <class Signature, Signature Function>
|
|
218
|
+
struct FreeFunctionWithData : detail::FreeFunctionHolder {
|
|
219
|
+
using FreeFunctionHolder::FreeFunctionHolder;
|
|
220
|
+
constexpr FreeFunctionWithData() : FreeFunctionHolder{
|
|
221
|
+
ToCallback<-2, Signature, Function>(),
|
|
222
|
+
std::tuple_size<typename detail::extract_arguments<Signature>::arguments>::value
|
|
223
|
+
} {}
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
template <
|
|
227
|
+
class GetterSignature, GetterSignature Getter,
|
|
228
|
+
class SetterSignature = std::nullptr_t, SetterSignature Setter = nullptr
|
|
229
|
+
>
|
|
230
|
+
struct MemberAccessor : detail::MemberAccessorHolder {
|
|
231
|
+
constexpr MemberAccessor() : MemberAccessorHolder{
|
|
232
|
+
detail::MemberGetterHolder{detail::MemberGetterHolder::ToCallback<
|
|
233
|
+
0, typename UnboundGetter::type, UnboundGetter::template invoke<Getter>
|
|
234
|
+
>()},
|
|
235
|
+
detail::MemberSetterHolder{detail::MemberSetterHolder::ToCallback<
|
|
236
|
+
0, typename UnboundSetter::type, UnboundSetter::template invoke<Setter>
|
|
237
|
+
>()}
|
|
238
|
+
} {}
|
|
239
|
+
|
|
240
|
+
private:
|
|
241
|
+
using UnboundGetter = detail::unbind_member_function<GetterSignature>;
|
|
242
|
+
using UnboundSetter = detail::unbind_member_function<SetterSignature>;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
// gcc seems to have trouble explicitly substituting std::nullptr_t into these templates so this one
|
|
246
|
+
// is partially specialized. Theoretically you could just remove this whole definition but I
|
|
247
|
+
// wouldn't try it.
|
|
248
|
+
template <class GetterSignature, GetterSignature Getter>
|
|
249
|
+
struct MemberAccessor<GetterSignature, Getter, std::nullptr_t, nullptr> : detail::MemberAccessorHolder {
|
|
250
|
+
constexpr MemberAccessor() : MemberAccessorHolder{
|
|
251
|
+
detail::MemberGetterHolder{detail::MemberGetterHolder::ToCallback<
|
|
252
|
+
0, typename UnboundGetter::type, UnboundGetter::template invoke<Getter>
|
|
253
|
+
>()},
|
|
254
|
+
detail::MemberSetterHolder{nullptr}
|
|
255
|
+
} {}
|
|
256
|
+
|
|
257
|
+
private:
|
|
258
|
+
using UnboundGetter = detail::unbind_member_function<GetterSignature>;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
template <
|
|
262
|
+
class GetterSignature, GetterSignature Getter,
|
|
263
|
+
class SetterSignature = std::nullptr_t, SetterSignature Setter = nullptr
|
|
264
|
+
>
|
|
265
|
+
struct StaticAccessor : detail::StaticAccessorHolder {
|
|
266
|
+
constexpr StaticAccessor() : StaticAccessorHolder{
|
|
267
|
+
detail::StaticGetterHolder{detail::StaticGetterHolder::ToCallback<0, GetterSignature, Getter>(), 0},
|
|
268
|
+
detail::StaticSetterHolder{detail::StaticSetterHolder::ToCallback<0, SetterSignature, Setter>(), 1}
|
|
269
|
+
} {}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
} // namespace ivm
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <stdexcept>
|
|
3
|
+
#include <string>
|
|
4
|
+
#include <v8.h>
|
|
5
|
+
#include "isolate/v8_version.h"
|
|
6
|
+
|
|
7
|
+
namespace ivm {
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* JS + C++ exceptions, use with care
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// `RuntimeError` can be thrown when v8 already has an exception on deck
|
|
14
|
+
class RuntimeError : public std::exception {};
|
|
15
|
+
|
|
16
|
+
namespace detail {
|
|
17
|
+
|
|
18
|
+
// `RuntimeErrorWithMessage` is a general error that has an error message with it
|
|
19
|
+
class RuntimeErrorWithMessage : public RuntimeError {
|
|
20
|
+
public:
|
|
21
|
+
explicit RuntimeErrorWithMessage(std::string message) : message{std::move(message)} {}
|
|
22
|
+
|
|
23
|
+
auto GetMessage() const {
|
|
24
|
+
return message;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
private:
|
|
28
|
+
std::string message;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// `RuntimeErrorConstructible` is a abstract error that can be imported back into v8
|
|
32
|
+
class RuntimeErrorConstructible : public RuntimeErrorWithMessage {
|
|
33
|
+
using RuntimeErrorWithMessage::RuntimeErrorWithMessage;
|
|
34
|
+
public:
|
|
35
|
+
virtual auto ConstructError() const -> v8::Local<v8::Value> = 0;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// `RuntimeErrorWithConstructor` can be used to construct any of the `v8::Exception` errors
|
|
39
|
+
#if V8_AT_LEAST(11, 9, 154)
|
|
40
|
+
template <v8::Local<v8::Value> (*Error)(v8::Local<v8::String>, v8::Local<v8::Value>)>
|
|
41
|
+
#else
|
|
42
|
+
template <v8::Local<v8::Value> (*Error)(v8::Local<v8::String>)>
|
|
43
|
+
#endif
|
|
44
|
+
class RuntimeErrorWithConstructor : public RuntimeErrorConstructible {
|
|
45
|
+
using RuntimeErrorConstructible::RuntimeErrorConstructible;
|
|
46
|
+
public:
|
|
47
|
+
RuntimeErrorWithConstructor(const std::string& message, std::string stack_trace) :
|
|
48
|
+
RuntimeErrorConstructible{message}, stack_trace{std::move(stack_trace)} {}
|
|
49
|
+
|
|
50
|
+
auto ConstructError() const -> v8::Local<v8::Value> final {
|
|
51
|
+
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
|
52
|
+
v8::MaybeLocal<v8::String> maybe_message = v8::String::NewFromUtf8(isolate, GetMessage().c_str(), v8::NewStringType::kNormal);
|
|
53
|
+
v8::Local<v8::String> message_handle;
|
|
54
|
+
if (maybe_message.ToLocal(&message_handle)) {
|
|
55
|
+
v8::Local<v8::Object> error =
|
|
56
|
+
#if V8_AT_LEAST(11, 9, 154)
|
|
57
|
+
Error(message_handle, {}).As<v8::Object>();
|
|
58
|
+
#else
|
|
59
|
+
Error(message_handle).As<v8::Object>();
|
|
60
|
+
#endif
|
|
61
|
+
if (!stack_trace.empty() && isolate->InContext()) {
|
|
62
|
+
std::string stack_str = std::string(GetMessage()) + stack_trace;
|
|
63
|
+
v8::MaybeLocal<v8::String> maybe_stack = v8::String::NewFromUtf8(isolate, stack_str.c_str(), v8::NewStringType::kNormal);
|
|
64
|
+
v8::MaybeLocal<v8::String> maybe_stack_symbol = v8::String::NewFromUtf8(isolate, "stack", v8::NewStringType::kNormal);
|
|
65
|
+
v8::Local<v8::String> stack;
|
|
66
|
+
v8::Local<v8::String> stack_symbol;
|
|
67
|
+
if (maybe_stack.ToLocal(&stack) && maybe_stack_symbol.ToLocal(&stack_symbol)) {
|
|
68
|
+
error->Set(isolate->GetCurrentContext(), stack_symbol, stack).IsJust();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return error;
|
|
72
|
+
}
|
|
73
|
+
// If the MaybeLocal is empty then I think v8 will have an exception on deck. I don't know if
|
|
74
|
+
// there's any way to assert() this though.
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
auto GetStackTrace() const -> std::string {
|
|
79
|
+
return stack_trace;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private:
|
|
83
|
+
std::string stack_trace;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// `FatalRuntimeError` is for very bad situations when the isolate is now in an unknown state
|
|
89
|
+
class FatalRuntimeError : public detail::RuntimeErrorWithMessage {
|
|
90
|
+
using RuntimeErrorWithMessage::RuntimeErrorWithMessage;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// These correspond to the given JS error types
|
|
94
|
+
using RuntimeGenericError = detail::RuntimeErrorWithConstructor<v8::Exception::Error>;
|
|
95
|
+
using RuntimeTypeError = detail::RuntimeErrorWithConstructor<v8::Exception::TypeError>;
|
|
96
|
+
using RuntimeRangeError = detail::RuntimeErrorWithConstructor<v8::Exception::RangeError>;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Convert a MaybeLocal<T> to Local<T> and throw an error if it's empty. Someone else should throw
|
|
100
|
+
* the v8 exception.
|
|
101
|
+
*/
|
|
102
|
+
template <class Type>
|
|
103
|
+
auto Unmaybe(v8::Maybe<Type> handle) -> Type {
|
|
104
|
+
Type just;
|
|
105
|
+
if (handle.To(&just)) {
|
|
106
|
+
return just;
|
|
107
|
+
} else {
|
|
108
|
+
throw RuntimeError();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
template <class Type>
|
|
113
|
+
auto Unmaybe(v8::MaybeLocal<Type> handle) -> v8::Local<Type> {
|
|
114
|
+
v8::Local<Type> local;
|
|
115
|
+
if (handle.ToLocal(&local)) {
|
|
116
|
+
return local;
|
|
117
|
+
} else {
|
|
118
|
+
throw RuntimeError();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
namespace detail {
|
|
123
|
+
|
|
124
|
+
template <class Functor>
|
|
125
|
+
inline void RunBarrier(Functor fn) {
|
|
126
|
+
// Runs a function and converts C++ errors to immediate v8 errors. Pretty much the same as
|
|
127
|
+
// `RunCallback` but with no return value.
|
|
128
|
+
try {
|
|
129
|
+
fn();
|
|
130
|
+
} catch (const FatalRuntimeError& cc_error) {
|
|
131
|
+
// Execution is terminating
|
|
132
|
+
} catch (const detail::RuntimeErrorConstructible& cc_error) {
|
|
133
|
+
v8::Isolate::GetCurrent()->ThrowException(cc_error.ConstructError());
|
|
134
|
+
} catch (const RuntimeError& cc_error) {
|
|
135
|
+
// A JS error is waiting in the isolate
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
} // namespace detail
|
|
140
|
+
} // namespace ivm
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
#include <string>
|
|
3
|
+
#include <v8.h>
|
|
4
|
+
#include "error.h"
|
|
5
|
+
#include "handle_cast.h"
|
|
6
|
+
|
|
7
|
+
namespace ivm {
|
|
8
|
+
namespace detail {
|
|
9
|
+
|
|
10
|
+
// Returns the name of the current function being called, used for error messages
|
|
11
|
+
inline auto CalleeName(const v8::FunctionCallbackInfo<v8::Value>& info) -> std::string {
|
|
12
|
+
v8::Isolate* isolate = info.GetIsolate();
|
|
13
|
+
return std::string("`")+ *v8::String::Utf8Value{isolate, Unmaybe(info.Data()->ToString(isolate->GetCurrentContext()))}+ "`";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
inline auto CalleeName(const v8::PropertyCallbackInfo<v8::Value>& info) -> std::string {
|
|
17
|
+
v8::Isolate* isolate = info.GetIsolate();
|
|
18
|
+
return std::string("`")+ *v8::String::Utf8Value{isolate, Unmaybe(info.Data()->ToString(isolate->GetCurrentContext()))}+ "`";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
inline auto CalleeName(const v8::PropertyCallbackInfo<void>& info) -> std::string {
|
|
22
|
+
v8::Isolate* isolate = info.GetIsolate();
|
|
23
|
+
return std::string("`")+ *v8::String::Utf8Value{isolate, Unmaybe(info.Data()->ToString(isolate->GetCurrentContext()))}+ "`";
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Specifies the types which may be default constructed when missing from arguments
|
|
27
|
+
template <class Type>
|
|
28
|
+
struct IsEmptyHandleAllowed : std::false_type {};
|
|
29
|
+
|
|
30
|
+
template <class Type>
|
|
31
|
+
struct IsEmptyHandleAllowed<Type*> : std::true_type {};
|
|
32
|
+
|
|
33
|
+
template <class Type>
|
|
34
|
+
struct IsEmptyHandleAllowed<v8::Maybe<Type>> : std::true_type {};
|
|
35
|
+
|
|
36
|
+
template <class Type>
|
|
37
|
+
struct IsEmptyHandleAllowed<v8::MaybeLocal<Type>> : std::true_type {};
|
|
38
|
+
|
|
39
|
+
// Statically counts the required arguments in a given callback function
|
|
40
|
+
template <size_t Index, class ...Args>
|
|
41
|
+
struct RequiredArguments;
|
|
42
|
+
|
|
43
|
+
template <size_t Index, class Type, class ...Rest>
|
|
44
|
+
struct RequiredArguments<Index, Type, Rest...> {
|
|
45
|
+
constexpr static size_t value = std::max(
|
|
46
|
+
IsEmptyHandleAllowed<Type>::value ? 0 : Index + 1,
|
|
47
|
+
RequiredArguments<Index + 1, Rest...>::value
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
template <size_t Index>
|
|
52
|
+
struct RequiredArguments<Index> {
|
|
53
|
+
constexpr static size_t value = 0;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Extracts parameters from various v8 call signatures
|
|
57
|
+
template <int Index>
|
|
58
|
+
inline auto ExtractParamImpl(const v8::FunctionCallbackInfo<v8::Value>& info) -> v8::Local<v8::Value> {
|
|
59
|
+
if (Index == -2) {
|
|
60
|
+
return info.Data();
|
|
61
|
+
} else if (Index == -1) {
|
|
62
|
+
return info.This();
|
|
63
|
+
} else {
|
|
64
|
+
return info[Index];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
template <int Index>
|
|
69
|
+
inline auto ExtractParamImpl(v8::Local<v8::Name> /*name*/, const v8::PropertyCallbackInfo<v8::Value>& info) -> v8::Local<v8::Value> {
|
|
70
|
+
static_assert(Index == 0, "Getter callback should have no parameters");
|
|
71
|
+
return info.This();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
template <int Index>
|
|
75
|
+
inline auto ExtractParamImpl(v8::Local<v8::Name> /*name*/, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -> v8::Local<v8::Value> {
|
|
76
|
+
static_assert(Index < 2, "Setter callback should have exactly 1 parameter");
|
|
77
|
+
if (Index == 0) {
|
|
78
|
+
return info.This();
|
|
79
|
+
} else if (Index == 1) {
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Generic unpacker with empty checking
|
|
85
|
+
template <int Offset, class ...Args>
|
|
86
|
+
class ParamExtractor {
|
|
87
|
+
public:
|
|
88
|
+
explicit ParamExtractor(Args... args) : args{args...} {}
|
|
89
|
+
|
|
90
|
+
template <class ...Types>
|
|
91
|
+
inline void CheckLength(std::tuple<Types...>* /*tuple*/) {
|
|
92
|
+
size_t length = CalculateLength(std::get<sizeof...(Args) - 1>(args));
|
|
93
|
+
constexpr size_t required = RequiredArguments<0, Types...>::value;
|
|
94
|
+
if (length < required) {
|
|
95
|
+
// `this` counts as a parameter so adjust this count for the error message
|
|
96
|
+
constexpr int adjusted = static_cast<int>(required) + std::max(Offset, -1);
|
|
97
|
+
throw RuntimeTypeError{CalleeName()+ " requires at least "+ std::to_string(adjusted)+ (adjusted == 1 ? " parameter" : " parameters")};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
template <int Index, class Type>
|
|
102
|
+
inline decltype(auto) Invoke() {
|
|
103
|
+
constexpr int AdjustedIndex = Index == 0 ? Offset : (std::max(-1, Offset) + Index);
|
|
104
|
+
ii = AdjustedIndex;
|
|
105
|
+
v8::Local<v8::Value> value = Extract<AdjustedIndex>(seq);
|
|
106
|
+
return HandleCast<Type>(value, std::get<sizeof...(Args) - 1>(args));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
[[noreturn]] void Caught(const ParamIncorrect& ex) {
|
|
110
|
+
if (ii == -1) {
|
|
111
|
+
throw RuntimeTypeError{CalleeName()+ " requires `this` to be "+ ex.type};
|
|
112
|
+
} else {
|
|
113
|
+
throw RuntimeTypeError{CalleeName()+ " requires parameter "+ std::to_string(ii + 1)+ " to be "+ ex.type};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
private:
|
|
118
|
+
auto CalleeName() {
|
|
119
|
+
return detail::CalleeName(std::get<sizeof...(Args) - 1>(args));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
template <int Index, size_t ...Indices>
|
|
123
|
+
inline auto Extract(std::index_sequence<Indices...> /*indices*/) {
|
|
124
|
+
return ExtractParamImpl<Index>(std::get<Indices>(args)...);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static inline auto CalculateLength(const v8::FunctionCallbackInfo<v8::Value>& info) -> size_t {
|
|
128
|
+
return info.Length() + (Offset == 0 ? 0 : 1);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
static inline auto CalculateLength(const v8::PropertyCallbackInfo<v8::Value>& /*info*/) -> size_t {
|
|
132
|
+
return 1; // `this`
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
static inline auto CalculateLength(const v8::PropertyCallbackInfo<void>& /*info*/) -> size_t {
|
|
136
|
+
return 2; // `this`, `value`
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
std::tuple<Args...> args;
|
|
140
|
+
int ii = 0;
|
|
141
|
+
static constexpr auto seq = std::make_index_sequence<sizeof...(Args)>{};
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
} // namespace detail
|
|
145
|
+
} // namespace ivm
|