@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.
Files changed (107) hide show
  1. package/dist/externalVersion.js +4 -4
  2. package/dist/node_modules/isolated-vm/.clang-tidy +13 -0
  3. package/dist/node_modules/isolated-vm/.dockerignore +9 -0
  4. package/dist/node_modules/isolated-vm/Dockerfile.alpine +9 -0
  5. package/dist/node_modules/isolated-vm/Dockerfile.debian +12 -0
  6. package/dist/node_modules/isolated-vm/LICENSE +13 -0
  7. package/dist/node_modules/isolated-vm/binding.gyp +120 -0
  8. package/dist/node_modules/isolated-vm/include.js +3 -0
  9. package/dist/node_modules/isolated-vm/inspector-example.js +59 -0
  10. package/dist/node_modules/isolated-vm/isolated-vm.d.ts +820 -0
  11. package/dist/node_modules/isolated-vm/isolated-vm.js +1 -0
  12. package/dist/node_modules/isolated-vm/native-example/binding.gyp +23 -0
  13. package/dist/node_modules/isolated-vm/native-example/example.cc +61 -0
  14. package/dist/node_modules/isolated-vm/native-example/package.json +13 -0
  15. package/dist/node_modules/isolated-vm/native-example/usage.js +35 -0
  16. package/dist/node_modules/isolated-vm/out/isolated_vm.node +0 -0
  17. package/dist/node_modules/isolated-vm/package.json +1 -0
  18. package/dist/node_modules/isolated-vm/src/external_copy/error.h +33 -0
  19. package/dist/node_modules/isolated-vm/src/external_copy/external_copy.cc +509 -0
  20. package/dist/node_modules/isolated-vm/src/external_copy/external_copy.h +117 -0
  21. package/dist/node_modules/isolated-vm/src/external_copy/serializer.cc +85 -0
  22. package/dist/node_modules/isolated-vm/src/external_copy/serializer.h +136 -0
  23. package/dist/node_modules/isolated-vm/src/external_copy/serializer_nortti.cc +73 -0
  24. package/dist/node_modules/isolated-vm/src/external_copy/string.cc +124 -0
  25. package/dist/node_modules/isolated-vm/src/external_copy/string.h +28 -0
  26. package/dist/node_modules/isolated-vm/src/isolate/allocator.h +32 -0
  27. package/dist/node_modules/isolated-vm/src/isolate/allocator_nortti.cc +142 -0
  28. package/dist/node_modules/isolated-vm/src/isolate/class_handle.h +334 -0
  29. package/dist/node_modules/isolated-vm/src/isolate/cpu_profile_manager.cc +220 -0
  30. package/dist/node_modules/isolated-vm/src/isolate/cpu_profile_manager.h +100 -0
  31. package/dist/node_modules/isolated-vm/src/isolate/environment.cc +626 -0
  32. package/dist/node_modules/isolated-vm/src/isolate/environment.h +381 -0
  33. package/dist/node_modules/isolated-vm/src/isolate/executor.cc +198 -0
  34. package/dist/node_modules/isolated-vm/src/isolate/executor.h +183 -0
  35. package/dist/node_modules/isolated-vm/src/isolate/external.h +64 -0
  36. package/dist/node_modules/isolated-vm/src/isolate/functor_runners.h +97 -0
  37. package/dist/node_modules/isolated-vm/src/isolate/generic/array.h +145 -0
  38. package/dist/node_modules/isolated-vm/src/isolate/generic/callbacks.h +272 -0
  39. package/dist/node_modules/isolated-vm/src/isolate/generic/error.h +140 -0
  40. package/dist/node_modules/isolated-vm/src/isolate/generic/extract_params.h +145 -0
  41. package/dist/node_modules/isolated-vm/src/isolate/generic/handle_cast.h +257 -0
  42. package/dist/node_modules/isolated-vm/src/isolate/generic/read_option.h +47 -0
  43. package/dist/node_modules/isolated-vm/src/isolate/holder.cc +88 -0
  44. package/dist/node_modules/isolated-vm/src/isolate/holder.h +63 -0
  45. package/dist/node_modules/isolated-vm/src/isolate/inspector.cc +200 -0
  46. package/dist/node_modules/isolated-vm/src/isolate/inspector.h +70 -0
  47. package/dist/node_modules/isolated-vm/src/isolate/node_wrapper.h +15 -0
  48. package/dist/node_modules/isolated-vm/src/isolate/platform_delegate.cc +22 -0
  49. package/dist/node_modules/isolated-vm/src/isolate/platform_delegate.h +46 -0
  50. package/dist/node_modules/isolated-vm/src/isolate/remote_handle.h +164 -0
  51. package/dist/node_modules/isolated-vm/src/isolate/run_with_timeout.h +171 -0
  52. package/dist/node_modules/isolated-vm/src/isolate/runnable.h +29 -0
  53. package/dist/node_modules/isolated-vm/src/isolate/scheduler.cc +191 -0
  54. package/dist/node_modules/isolated-vm/src/isolate/scheduler.h +165 -0
  55. package/dist/node_modules/isolated-vm/src/isolate/specific.h +35 -0
  56. package/dist/node_modules/isolated-vm/src/isolate/stack_trace.cc +219 -0
  57. package/dist/node_modules/isolated-vm/src/isolate/stack_trace.h +24 -0
  58. package/dist/node_modules/isolated-vm/src/isolate/strings.h +127 -0
  59. package/dist/node_modules/isolated-vm/src/isolate/three_phase_task.cc +385 -0
  60. package/dist/node_modules/isolated-vm/src/isolate/three_phase_task.h +136 -0
  61. package/dist/node_modules/isolated-vm/src/isolate/transferable.h +15 -0
  62. package/dist/node_modules/isolated-vm/src/isolate/util.h +45 -0
  63. package/dist/node_modules/isolated-vm/src/isolate/v8_inspector_wrapper.h +12 -0
  64. package/dist/node_modules/isolated-vm/src/isolate/v8_version.h +12 -0
  65. package/dist/node_modules/isolated-vm/src/isolated_vm.h +71 -0
  66. package/dist/node_modules/isolated-vm/src/lib/covariant.h +50 -0
  67. package/dist/node_modules/isolated-vm/src/lib/lockable.h +178 -0
  68. package/dist/node_modules/isolated-vm/src/lib/suspend.h +106 -0
  69. package/dist/node_modules/isolated-vm/src/lib/thread_pool.cc +98 -0
  70. package/dist/node_modules/isolated-vm/src/lib/thread_pool.h +45 -0
  71. package/dist/node_modules/isolated-vm/src/lib/timer.cc +233 -0
  72. package/dist/node_modules/isolated-vm/src/lib/timer.h +36 -0
  73. package/dist/node_modules/isolated-vm/src/module/callback.cc +151 -0
  74. package/dist/node_modules/isolated-vm/src/module/callback.h +64 -0
  75. package/dist/node_modules/isolated-vm/src/module/context_handle.cc +241 -0
  76. package/dist/node_modules/isolated-vm/src/module/context_handle.h +35 -0
  77. package/dist/node_modules/isolated-vm/src/module/evaluation.cc +109 -0
  78. package/dist/node_modules/isolated-vm/src/module/evaluation.h +99 -0
  79. package/dist/node_modules/isolated-vm/src/module/external_copy_handle.cc +119 -0
  80. package/dist/node_modules/isolated-vm/src/module/external_copy_handle.h +64 -0
  81. package/dist/node_modules/isolated-vm/src/module/isolate.cc +136 -0
  82. package/dist/node_modules/isolated-vm/src/module/isolate_handle.cc +611 -0
  83. package/dist/node_modules/isolated-vm/src/module/isolate_handle.h +47 -0
  84. package/dist/node_modules/isolated-vm/src/module/lib_handle.cc +77 -0
  85. package/dist/node_modules/isolated-vm/src/module/lib_handle.h +28 -0
  86. package/dist/node_modules/isolated-vm/src/module/module_handle.cc +475 -0
  87. package/dist/node_modules/isolated-vm/src/module/module_handle.h +68 -0
  88. package/dist/node_modules/isolated-vm/src/module/native_module_handle.cc +104 -0
  89. package/dist/node_modules/isolated-vm/src/module/native_module_handle.h +49 -0
  90. package/dist/node_modules/isolated-vm/src/module/reference_handle.cc +636 -0
  91. package/dist/node_modules/isolated-vm/src/module/reference_handle.h +106 -0
  92. package/dist/node_modules/isolated-vm/src/module/script_handle.cc +107 -0
  93. package/dist/node_modules/isolated-vm/src/module/script_handle.h +37 -0
  94. package/dist/node_modules/isolated-vm/src/module/session_handle.cc +173 -0
  95. package/dist/node_modules/isolated-vm/src/module/session_handle.h +31 -0
  96. package/dist/node_modules/isolated-vm/src/module/transferable.cc +268 -0
  97. package/dist/node_modules/isolated-vm/src/module/transferable.h +42 -0
  98. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v18.0.0.h +360 -0
  99. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v18.3.0.h +376 -0
  100. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v20.0.0.h +397 -0
  101. package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v22.0.0.h +419 -0
  102. package/dist/node_modules/winston-transport/package.json +1 -1
  103. package/dist/server/IsolatedVm.js +75 -0
  104. package/dist/server/ScriptInstruction.d.ts +6 -0
  105. package/dist/server/ScriptInstruction.js +11 -1
  106. package/dist/server/Vm.js +42 -27
  107. package/package.json +3 -2
@@ -0,0 +1,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