@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,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