@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.
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,611 @@
1
+ #include "isolate_handle.h"
2
+ #include "context_handle.h"
3
+ #include "external_copy_handle.h"
4
+ #include "isolate/holder.h"
5
+ #include "script_handle.h"
6
+ #include "module_handle.h"
7
+ #include "session_handle.h"
8
+ #include "external_copy/external_copy.h"
9
+ #include "lib/lockable.h"
10
+ #include "isolate/allocator.h"
11
+ #include "isolate/functor_runners.h"
12
+ #include "isolate/platform_delegate.h"
13
+ #include "isolate/remote_handle.h"
14
+ #include "isolate/three_phase_task.h"
15
+ #include "isolate/v8_version.h"
16
+ #include "module/evaluation.h"
17
+ #include "v8-platform.h"
18
+ #include "v8-profiler.h"
19
+ #include <cstring>
20
+ #include <deque>
21
+ #include <memory>
22
+ #include <iostream>
23
+
24
+ using namespace v8;
25
+ using v8::CpuProfile;
26
+ using std::shared_ptr;
27
+ using std::unique_ptr;
28
+
29
+ namespace ivm {
30
+
31
+ /**
32
+ * IsolateHandle implementation
33
+ */
34
+ IsolateHandle::IsolateHandleTransferable::IsolateHandleTransferable(shared_ptr<IsolateHolder> isolate) : isolate(std::move(isolate)) {}
35
+
36
+ auto IsolateHandle::IsolateHandleTransferable::TransferIn() -> Local<Value> {
37
+ return ClassHandle::NewInstance<IsolateHandle>(isolate);
38
+ }
39
+
40
+ IsolateHandle::IsolateHandle(shared_ptr<IsolateHolder> isolate) : isolate(std::move(isolate)) {}
41
+
42
+ auto IsolateHandle::Definition() -> Local<FunctionTemplate> {
43
+ return Inherit<TransferableHandle>(MakeClass(
44
+ "Isolate", ConstructorFunction<decltype(&New), &New>{},
45
+ "createSnapshot", FreeFunction<decltype(&CreateSnapshot), &CreateSnapshot>{},
46
+ "compileScript", MemberFunction<decltype(&IsolateHandle::CompileScript<1>), &IsolateHandle::CompileScript<1>>{},
47
+ "compileScriptSync", MemberFunction<decltype(&IsolateHandle::CompileScript<0>), &IsolateHandle::CompileScript<0>>{},
48
+ "compileModule", MemberFunction<decltype(&IsolateHandle::CompileModule<1>), &IsolateHandle::CompileModule<1>>{},
49
+ "compileModuleSync", MemberFunction<decltype(&IsolateHandle::CompileModule<0>), &IsolateHandle::CompileModule<0>>{},
50
+ "cpuTime", MemberAccessor<decltype(&IsolateHandle::GetCpuTime), &IsolateHandle::GetCpuTime>{},
51
+ "createContext", MemberFunction<decltype(&IsolateHandle::CreateContext<1>), &IsolateHandle::CreateContext<1>>{},
52
+ "createContextSync", MemberFunction<decltype(&IsolateHandle::CreateContext<0>), &IsolateHandle::CreateContext<0>>{},
53
+ "createInspectorSession", MemberFunction<decltype(&IsolateHandle::CreateInspectorSession), &IsolateHandle::CreateInspectorSession>{},
54
+ "dispose", MemberFunction<decltype(&IsolateHandle::Dispose), &IsolateHandle::Dispose>{},
55
+ "getHeapStatistics", MemberFunction<decltype(&IsolateHandle::GetHeapStatistics<1>), &IsolateHandle::GetHeapStatistics<1>>{},
56
+ "getHeapStatisticsSync", MemberFunction<decltype(&IsolateHandle::GetHeapStatistics<0>), &IsolateHandle::GetHeapStatistics<0>>{},
57
+ "isDisposed", MemberAccessor<decltype(&IsolateHandle::IsDisposedGetter), &IsolateHandle::IsDisposedGetter>{},
58
+ "referenceCount", MemberAccessor<decltype(&IsolateHandle::GetReferenceCount), &IsolateHandle::GetReferenceCount>{},
59
+ "wallTime", MemberAccessor<decltype(&IsolateHandle::GetWallTime), &IsolateHandle::GetWallTime>{},
60
+ "startCpuProfiler", MemberFunction<decltype(&IsolateHandle::StartCpuProfiler), &IsolateHandle::StartCpuProfiler>{},
61
+ "stopCpuProfiler", MemberFunction<decltype(&IsolateHandle::StopCpuProfiler<1>), &IsolateHandle::StopCpuProfiler<1>>{}
62
+ ));
63
+ }
64
+
65
+ /**
66
+ * Create a new Isolate. It all starts here!
67
+ */
68
+ auto IsolateHandle::New(MaybeLocal<Object> maybe_options) -> unique_ptr<ClassHandle> {
69
+ shared_ptr<v8::BackingStore> snapshot_blob;
70
+ RemoteHandle<Function> error_handler;
71
+ size_t snapshot_blob_length = 0;
72
+ size_t memory_limit = 128;
73
+ bool inspector = false;
74
+
75
+ // Parse options
76
+ Local<Object> options;
77
+ if (maybe_options.ToLocal(&options)) {
78
+
79
+ // Check memory limits
80
+ memory_limit = ReadOption<double>(options, "memoryLimit", 128);
81
+ if (memory_limit < 8) {
82
+ throw RuntimeGenericError("`memoryLimit` must be at least 8");
83
+ }
84
+
85
+ // Set snapshot
86
+ auto maybe_snapshot = ReadOption<MaybeLocal<Object>>(options, StringTable::Get().snapshot, {});
87
+ Local<Object> snapshot_handle;
88
+ if (maybe_snapshot.ToLocal(&snapshot_handle)) {
89
+ auto* copy_handle = ClassHandle::Unwrap<ExternalCopyHandle>(snapshot_handle.As<Object>());
90
+ if (copy_handle != nullptr) {
91
+ ExternalCopyArrayBuffer* copy_ptr = dynamic_cast<ExternalCopyArrayBuffer*>(copy_handle->GetValue().get());
92
+ if (copy_ptr != nullptr) {
93
+ snapshot_blob = copy_ptr->Acquire();
94
+ snapshot_blob_length = snapshot_blob->ByteLength();
95
+ }
96
+ }
97
+ if (!snapshot_blob) {
98
+ throw RuntimeTypeError("`snapshot` must be an ExternalCopy to ArrayBuffer");
99
+ }
100
+ }
101
+
102
+ // Check inspector flag
103
+ inspector = ReadOption<bool>(options, StringTable::Get().inspector, false);
104
+
105
+ auto maybe_handler = ReadOption<MaybeLocal<Function>>(options, StringTable::Get().onCatastrophicError, {});
106
+ Local<Function> error_handler_local;
107
+ if (maybe_handler.ToLocal(&error_handler_local)) {
108
+ error_handler = RemoteHandle<Function>{error_handler_local};
109
+ }
110
+ }
111
+
112
+ // Return isolate handle
113
+ auto holder = IsolateEnvironment::New(memory_limit, std::move(snapshot_blob), snapshot_blob_length);
114
+ auto env = holder->GetIsolate();
115
+ env->GetIsolate()->SetHostInitializeImportMetaObjectCallback(ModuleHandle::InitializeImportMeta);
116
+ env->error_handler = error_handler;
117
+ if (inspector) {
118
+ env->EnableInspectorAgent();
119
+ }
120
+ return std::make_unique<IsolateHandle>(holder);
121
+ }
122
+
123
+ auto IsolateHandle::TransferOut() -> unique_ptr<Transferable> {
124
+ return std::make_unique<IsolateHandleTransferable>(isolate);
125
+ }
126
+
127
+ /**
128
+ * Create a new v8::Context in this isolate and returns a ContextHandle
129
+ */
130
+ struct CreateContextRunner : public ThreePhaseTask {
131
+ bool enable_inspector = false;
132
+ RemoteHandle<Context> context;
133
+ RemoteHandle<Value> global;
134
+
135
+ explicit CreateContextRunner(MaybeLocal<Object>& maybe_options) {
136
+ enable_inspector = ReadOption<bool>(maybe_options, StringTable::Get().inspector, false);
137
+ }
138
+
139
+ void Phase2() final {
140
+ // Use custom deleter on the shared_ptr which will notify the isolate when we're probably done with this context
141
+ struct ContextDeleter {
142
+ void operator() (Persistent<Context>& context) const {
143
+ auto& env = IsolateEnvironment::GetCurrent();
144
+ context.Reset();
145
+ env.GetIsolate()->ContextDisposedNotification();
146
+ }
147
+ };
148
+
149
+ auto& env = IsolateEnvironment::GetCurrent();
150
+
151
+ // Sanity check before we build the context
152
+ if (enable_inspector && env.GetInspectorAgent() == nullptr) {
153
+ Context::Scope context_scope{env.DefaultContext()}; // TODO: This is needed to throw, but is stupid and sloppy
154
+ throw RuntimeGenericError("Inspector is not enabled for this isolate");
155
+ }
156
+
157
+ // Make a new context and setup shared pointers
158
+ IsolateEnvironment::HeapCheck heap_check{env, true};
159
+ Local<Context> context_handle = env.NewContext();
160
+ if (enable_inspector) {
161
+ env.GetInspectorAgent()->ContextCreated(context_handle, "<isolated-vm>");
162
+ }
163
+ context = RemoteHandle<Context>{context_handle, ContextDeleter{}};
164
+ global = RemoteHandle<Value>{context_handle->Global()};
165
+ heap_check.Epilogue();
166
+ }
167
+
168
+ auto Phase3() -> Local<Value> final {
169
+ // Make a new Context{} JS class
170
+ return ClassHandle::NewInstance<ContextHandle>(std::move(context), std::move(global));
171
+ }
172
+ };
173
+ template <int async>
174
+ auto IsolateHandle::CreateContext(MaybeLocal<Object> maybe_options) -> Local<Value> {
175
+ return ThreePhaseTask::Run<async, CreateContextRunner>(*isolate, maybe_options);
176
+ }
177
+
178
+ /**
179
+ * Compiles a script in this isolate and returns a ScriptHandle
180
+ */
181
+ struct CompileScriptRunner : public CodeCompilerHolder, public ThreePhaseTask {
182
+ RemoteHandle<UnboundScript> script;
183
+
184
+ CompileScriptRunner(const Local<String>& code_handle, const MaybeLocal<Object>& maybe_options) :
185
+ CodeCompilerHolder{code_handle, maybe_options, false} {}
186
+
187
+ void Phase2() final {
188
+ // Compile in second isolate and return UnboundScript persistent
189
+ auto& isolate = IsolateEnvironment::GetCurrent();
190
+ Context::Scope context_scope(isolate.DefaultContext());
191
+ IsolateEnvironment::HeapCheck heap_check{isolate, true};
192
+ auto source = GetSource();
193
+ ScriptCompiler::CompileOptions compile_options = ScriptCompiler::kNoCompileOptions;
194
+ if (DidSupplyCachedData()) {
195
+ compile_options = ScriptCompiler::kConsumeCodeCache;
196
+ }
197
+ script = RemoteHandle<UnboundScript>{RunWithAnnotatedErrors(
198
+ [&isolate, &source, compile_options]() { return Unmaybe(ScriptCompiler::CompileUnboundScript(isolate, source.get(), compile_options)); }
199
+ )};
200
+
201
+ // Check cached data flags
202
+ if (DidSupplyCachedData()) {
203
+ SetCachedDataRejected(source->GetCachedData()->rejected);
204
+ }
205
+ if (ShouldProduceCachedData()) {
206
+ ScriptCompiler::CachedData* cached_data = ScriptCompiler::CreateCodeCache(script.Deref());
207
+ assert(cached_data != nullptr);
208
+ SaveCachedData(cached_data);
209
+ }
210
+ ResetSource();
211
+ heap_check.Epilogue();
212
+ }
213
+
214
+ auto Phase3() -> Local<Value> final {
215
+ // Wrap UnboundScript in JS Script{} class
216
+ Local<Object> value = ClassHandle::NewInstance<ScriptHandle>(std::move(script));
217
+ WriteCompileResults(value);
218
+ return value;
219
+ }
220
+ };
221
+
222
+ struct StopCpuProfileRunner: public ThreePhaseTask {
223
+ const char* title_;
224
+ std::vector<IVMCpuProfile> profiles;
225
+
226
+ explicit StopCpuProfileRunner(const char* title): title_(title) {}
227
+
228
+ void Phase2() final {
229
+ auto& isolate = IsolateEnvironment::GetCurrent();
230
+ profiles = isolate.GetCpuProfileManager()->StopProfiling(title_);
231
+ }
232
+
233
+ auto Phase3() -> Local<Value> final {
234
+ auto* isolate = Isolate::GetCurrent();
235
+ auto ctx = isolate->GetCurrentContext();
236
+
237
+ const int arr_size = static_cast<int>(profiles.size());
238
+ auto arr = Array::New(isolate, arr_size);
239
+
240
+ for (int i = 0; i < arr_size; i++) {
241
+ IVMCpuProfile profile = profiles.at(i);
242
+ Unmaybe(arr->Set(ctx, i, profile.ToJSObject(isolate)));
243
+ }
244
+
245
+ return arr;
246
+ }
247
+ };
248
+
249
+ template <int async>
250
+ auto IsolateHandle::CompileScript(Local<String> code_handle, MaybeLocal<Object> maybe_options) -> Local<Value> {
251
+ return ThreePhaseTask::Run<async, CompileScriptRunner>(*this->isolate, code_handle, maybe_options);
252
+ }
253
+
254
+ /**
255
+ * Compiles a module in this isolate and returns a ModuleHandle
256
+ */
257
+ struct CompileModuleRunner : public CodeCompilerHolder, public ThreePhaseTask {
258
+ shared_ptr<ModuleInfo> module_info;
259
+ RemoteHandle<Function> meta_callback;
260
+
261
+ CompileModuleRunner(const Local<String>& code_handle, const MaybeLocal<Object>& maybe_options) :
262
+ CodeCompilerHolder{code_handle, maybe_options, true} {
263
+
264
+ auto maybe_meta_callback = ReadOption<MaybeLocal<Function>>(maybe_options, StringTable::Get().meta, {});
265
+ Local<Function> meta_callback;
266
+ if (maybe_meta_callback.ToLocal(&meta_callback)) {
267
+ this->meta_callback = RemoteHandle<Function>{meta_callback};
268
+ }
269
+ }
270
+
271
+ void Phase2() final {
272
+ auto& isolate = IsolateEnvironment::GetCurrent();
273
+ Context::Scope context_scope(isolate.DefaultContext());
274
+ IsolateEnvironment::HeapCheck heap_check{isolate, true};
275
+ auto source = GetSource();
276
+ auto module_handle = RunWithAnnotatedErrors(
277
+ [&]() { return Unmaybe(ScriptCompiler::CompileModule(isolate, source.get())); }
278
+ );
279
+
280
+ if (DidSupplyCachedData()) {
281
+ SetCachedDataRejected(source->GetCachedData()->rejected);
282
+ }
283
+ if (ShouldProduceCachedData()) {
284
+ ScriptCompiler::CachedData* cached_data = ScriptCompiler::CreateCodeCache(module_handle->GetUnboundModuleScript());
285
+ assert(cached_data != nullptr);
286
+ SaveCachedData(cached_data);
287
+ }
288
+
289
+ ResetSource();
290
+ module_info = std::make_shared<ModuleInfo>(module_handle);
291
+ if (meta_callback) {
292
+ if (meta_callback.GetSharedIsolateHolder() != IsolateEnvironment::GetCurrentHolder()) {
293
+ throw RuntimeGenericError("`meta` callback must belong to entered isolate");
294
+ }
295
+ module_info->meta_callback = meta_callback;
296
+ }
297
+ heap_check.Epilogue();
298
+ }
299
+
300
+ auto Phase3() -> Local<Value> final {
301
+ Local<Object> value = ClassHandle::NewInstance<ModuleHandle>(std::move(module_info));
302
+ WriteCompileResults(value);
303
+ return value;
304
+ }
305
+ };
306
+
307
+ template <int async>
308
+ auto IsolateHandle::CompileModule(Local<String> code_handle, MaybeLocal<Object> maybe_options) -> Local<Value> {
309
+ return ThreePhaseTask::Run<async, CompileModuleRunner>(*this->isolate, code_handle, maybe_options);
310
+ }
311
+
312
+ /**
313
+ * Create a new channel for debugging on the inspector
314
+ */
315
+ auto IsolateHandle::CreateInspectorSession() -> Local<Value> {
316
+ if (IsolateEnvironment::GetCurrentHolder() == isolate) {
317
+ throw RuntimeGenericError("An isolate is not debuggable from within itself");
318
+ }
319
+ shared_ptr<IsolateEnvironment> env = isolate->GetIsolate();
320
+ if (!env) {
321
+ throw RuntimeGenericError("Isolate is diposed");
322
+ }
323
+ if (env->GetInspectorAgent() == nullptr) {
324
+ throw RuntimeGenericError("Inspector is not enabled for this isolate");
325
+ }
326
+ return ClassHandle::NewInstance<SessionHandle>(*env);
327
+ }
328
+
329
+ /**
330
+ * Dispose an isolate
331
+ */
332
+ auto IsolateHandle::Dispose() -> Local<Value> {
333
+ if (!isolate->Dispose()) {
334
+ throw RuntimeGenericError("Isolate is already disposed");
335
+ }
336
+ return Undefined(Isolate::GetCurrent());
337
+ }
338
+
339
+ /**
340
+ * Get heap statistics from v8
341
+ */
342
+ struct HeapStatRunner : public ThreePhaseTask {
343
+ HeapStatistics heap;
344
+ size_t externally_allocated_size = 0;
345
+ size_t adjustment = 0;
346
+
347
+ // Dummy constructor to workaround gcc bug
348
+ explicit HeapStatRunner(int /*unused*/) {}
349
+
350
+ void Phase2() final {
351
+ IsolateEnvironment& isolate = IsolateEnvironment::GetCurrent();
352
+ isolate->GetHeapStatistics(&heap);
353
+ adjustment = heap.heap_size_limit() - isolate.GetInitialHeapSizeLimit();
354
+ externally_allocated_size = isolate.GetExtraAllocatedMemory();
355
+ }
356
+
357
+ auto Phase3() -> Local<Value> final {
358
+ Isolate* isolate = Isolate::GetCurrent();
359
+ Local<Context> context = isolate->GetCurrentContext();
360
+ Local<Object> ret = Object::New(isolate);
361
+ auto& strings = StringTable::Get();
362
+ Unmaybe(ret->Set(context, strings.total_heap_size, Number::New(isolate, heap.total_heap_size())));
363
+ Unmaybe(ret->Set(context, strings.total_heap_size_executable, Number::New(isolate, heap.total_heap_size_executable())));
364
+ Unmaybe(ret->Set(context, strings.total_physical_size, Number::New(isolate, heap.total_physical_size())));
365
+ Unmaybe(ret->Set(context, strings.total_available_size, Number::New(isolate, static_cast<double>(heap.total_available_size()) - adjustment)));
366
+ Unmaybe(ret->Set(context, strings.used_heap_size, Number::New(isolate, heap.used_heap_size())));
367
+ Unmaybe(ret->Set(context, strings.heap_size_limit, Number::New(isolate, static_cast<double>(heap.heap_size_limit()) - adjustment)));
368
+ Unmaybe(ret->Set(context, strings.malloced_memory, Number::New(isolate, heap.malloced_memory())));
369
+ Unmaybe(ret->Set(context, strings.peak_malloced_memory, Number::New(isolate, heap.peak_malloced_memory())));
370
+ Unmaybe(ret->Set(context, strings.does_zap_garbage, Number::New(isolate, heap.does_zap_garbage())));
371
+ Unmaybe(ret->Set(context, strings.externally_allocated_size, Number::New(isolate, externally_allocated_size)));
372
+ return ret;
373
+ }
374
+ };
375
+ template <int async>
376
+ auto IsolateHandle::GetHeapStatistics() -> Local<Value> {
377
+ return ThreePhaseTask::Run<async, HeapStatRunner>(*isolate, 0);
378
+ }
379
+
380
+ /**
381
+ * Timers
382
+ */
383
+ auto IsolateHandle::GetCpuTime() -> Local<Value> {
384
+ auto env = this->isolate->GetIsolate();
385
+ if (!env) {
386
+ throw RuntimeGenericError("Isolate is disposed");
387
+ }
388
+ uint64_t time = env->GetCpuTime().count();
389
+ return HandleCast<Local<BigInt>>(time);
390
+ }
391
+
392
+ auto IsolateHandle::GetWallTime() -> Local<Value> {
393
+ auto env = this->isolate->GetIsolate();
394
+ if (!env) {
395
+ throw RuntimeGenericError("Isolate is disposed");
396
+ }
397
+ uint64_t time = env->GetWallTime().count();
398
+ return HandleCast<Local<BigInt>>(time);
399
+ }
400
+
401
+ auto IsolateHandle::StartCpuProfiler(v8::Local<v8::String> title) -> Local<Value> {
402
+ auto env = this->isolate->GetIsolate();
403
+
404
+ if (!env) {
405
+ throw RuntimeGenericError("Isolate is disposed");
406
+ }
407
+
408
+ Isolate* iso = Isolate::GetCurrent();
409
+ v8::String::Utf8Value str(iso, title);
410
+ const char* title_ = *str;
411
+
412
+ env->GetCpuProfileManager()->StartProfiling(title_);
413
+
414
+ return HandleCast<Local<Boolean>>(true);
415
+ }
416
+
417
+ template <int async>
418
+ auto IsolateHandle::StopCpuProfiler(v8::Local<v8::String> title) -> Local<Value> {
419
+ auto env = this->isolate->GetIsolate();
420
+
421
+ if (!env) {
422
+ throw RuntimeGenericError("Isolate is disposed");
423
+ }
424
+
425
+ Isolate* iso = Isolate::GetCurrent();
426
+ v8::String::Utf8Value str(iso, title);
427
+ const size_t len = strlen(*str);
428
+
429
+ char* dest = (char*)std::malloc(len + 1);
430
+
431
+ strcpy(dest, *str);
432
+
433
+ return ThreePhaseTask::Run<async, StopCpuProfileRunner>(*isolate, dest);
434
+ }
435
+
436
+ /**
437
+ * Reference count
438
+ */
439
+ auto IsolateHandle::GetReferenceCount() -> Local<Value> {
440
+ auto env = this->isolate->GetIsolate();
441
+ if (!env) {
442
+ throw RuntimeGenericError("Isolate is disposed");
443
+ }
444
+ return Number::New(Isolate::GetCurrent(), env->GetRemotesCount());
445
+ }
446
+
447
+ /**
448
+ * Simple disposal checker
449
+ */
450
+ auto IsolateHandle::IsDisposedGetter() -> Local<Value> {
451
+ return Boolean::New(Isolate::GetCurrent(), !isolate->GetIsolate());
452
+ }
453
+
454
+ /**
455
+ * Create a snapshot from some code and return it as an external ArrayBuffer
456
+ */
457
+ static auto SerializeInternalFieldsCallback(Local<Object> /*holder*/, int /*index*/, void* /*data*/) -> StartupData {
458
+ return {nullptr, 0};
459
+ }
460
+
461
+ auto IsolateHandle::CreateSnapshot(ArrayRange script_handles, MaybeLocal<String> warmup_handle) -> Local<Value> {
462
+
463
+ // Simple platform delegate and task queue
464
+ using TaskDeque = lockable_t<std::deque<std::unique_ptr<v8::Task>>>;
465
+ class SnapshotPlatformDelegate :
466
+ public node::IsolatePlatformDelegate, public TaskRunner,
467
+ public std::enable_shared_from_this<SnapshotPlatformDelegate> {
468
+
469
+ public:
470
+ explicit SnapshotPlatformDelegate(TaskDeque& tasks) : tasks{tasks} {}
471
+
472
+ // v8 will continually post delayed tasks so we cut it off when work is done
473
+ void DoneWithWork() {
474
+ done = true;
475
+ }
476
+
477
+ // Methods for IsolatePlatformDelegate
478
+ auto GetForegroundTaskRunner() -> std::shared_ptr<v8::TaskRunner> final {
479
+ return shared_from_this();
480
+ }
481
+ auto IdleTasksEnabled() -> bool final {
482
+ return false;
483
+ }
484
+
485
+ // Methods for v8::TaskRunner
486
+ void PostTask(std::unique_ptr<v8::Task> task) final {
487
+ tasks.write()->push_back(std::move(task));
488
+ }
489
+ void PostDelayedTask(std::unique_ptr<v8::Task> task, double /*delay_in_seconds*/) final {
490
+ if (!done) {
491
+ PostTask(std::move(task));
492
+ }
493
+ }
494
+ void PostNonNestableTask(std::unique_ptr<v8::Task> task) final {
495
+ PostTask(std::move(task));
496
+ }
497
+
498
+ private:
499
+ lockable_t<std::deque<std::unique_ptr<v8::Task>>>& tasks;
500
+ bool done = false;
501
+ };
502
+
503
+ TaskDeque tasks;
504
+ auto delegate = std::make_shared<SnapshotPlatformDelegate>(tasks);
505
+
506
+ // Copy embed scripts and warmup script from outer isolate
507
+ std::vector<std::pair<ExternalCopyString, ScriptOriginHolder>> scripts;
508
+ Isolate* isolate = Isolate::GetCurrent();
509
+ Local<Context> context = isolate->GetCurrentContext();
510
+ scripts.reserve(std::distance(script_handles.begin(), script_handles.end()));
511
+ for (auto value : script_handles) {
512
+ auto script_handle = HandleCast<Local<Object>>(value);
513
+ Local<Value> script = Unmaybe(script_handle.As<Object>()->Get(context, StringTable::Get().code));
514
+ if (!script->IsString()) {
515
+ throw RuntimeTypeError("`code` property is required");
516
+ }
517
+ scripts.emplace_back(ExternalCopyString{script.As<String>()}, ScriptOriginHolder{script_handle});
518
+ }
519
+ ExternalCopyString warmup_script;
520
+ if (!warmup_handle.IsEmpty()) {
521
+ warmup_script = ExternalCopyString{warmup_handle.ToLocalChecked().As<String>()};
522
+ }
523
+
524
+ // Create the snapshot
525
+ StartupData snapshot {};
526
+ unique_ptr<const char[]> snapshot_data_ptr;
527
+ shared_ptr<ExternalCopy> error;
528
+ {
529
+ Isolate* isolate;
530
+ isolate = Isolate::Allocate();
531
+ PlatformDelegate::RegisterIsolate(isolate, delegate.get());
532
+ SnapshotCreator snapshot_creator{isolate};
533
+ {
534
+ Locker locker(isolate);
535
+ Isolate::Scope isolate_scope(isolate);
536
+ HandleScope handle_scope(isolate);
537
+ Local<Context> context = Context::New(isolate);
538
+ snapshot_creator.SetDefaultContext(context, {&SerializeInternalFieldsCallback, nullptr});
539
+ FunctorRunners::RunCatchExternal(context, [&]() {
540
+ HandleScope handle_scope(isolate);
541
+ Local<Context> context_dirty = Context::New(isolate);
542
+ for (auto& script : scripts) {
543
+ Local<String> code = script.first.CopyInto().As<String>();
544
+ ScriptOrigin script_origin = ScriptOrigin{script.second};
545
+ ScriptCompiler::Source source{code, script_origin};
546
+ Local<UnboundScript> unbound_script;
547
+ {
548
+ Context::Scope context_scope{context};
549
+ Local<Script> compiled_script = RunWithAnnotatedErrors(
550
+ [&context, &source]() { return Unmaybe(ScriptCompiler::Compile(context, &source, ScriptCompiler::kNoCompileOptions)); }
551
+ );
552
+ Unmaybe(compiled_script->Run(context));
553
+ unbound_script = compiled_script->GetUnboundScript();
554
+ }
555
+ if (warmup_script) {
556
+ Context::Scope context_scope{context_dirty};
557
+ Unmaybe(unbound_script->BindToCurrentContext()->Run(context_dirty));
558
+ }
559
+ }
560
+ if (warmup_script) {
561
+ Context::Scope context_scope{context_dirty};
562
+ MaybeLocal<Object> tmp;
563
+ ScriptOriginHolder script_origin{tmp};
564
+ ScriptCompiler::Source source{warmup_script.CopyInto().As<String>(), ScriptOrigin{script_origin}};
565
+ RunWithAnnotatedErrors([&context_dirty, &source]() {
566
+ Unmaybe(Unmaybe(ScriptCompiler::Compile(context_dirty, &source, ScriptCompiler::kNoCompileOptions))->Run(context_dirty));
567
+ });
568
+ }
569
+ }, [ &error ](unique_ptr<ExternalCopy> error_inner) {
570
+ error = std::move(error_inner);
571
+ });
572
+ isolate->ContextDisposedNotification(false);
573
+
574
+ // Run all queued tasks
575
+ delegate->DoneWithWork();
576
+ while (true) {
577
+ auto task = [&]() -> std::unique_ptr<v8::Task> {
578
+ auto lock = tasks.write();
579
+ if (lock->empty()) {
580
+ return nullptr;
581
+ }
582
+ auto task = std::move(lock->front());
583
+ lock->pop_front();
584
+ return task;
585
+ }();
586
+ if (task) {
587
+ task->Run();
588
+ } else {
589
+ break;
590
+ }
591
+ }
592
+ }
593
+ // nb: Snapshot must be created even in the error case, because `~SnapshotCreator` will crash if
594
+ // you don't
595
+ snapshot = snapshot_creator.CreateBlob(SnapshotCreator::FunctionCodeHandling::kKeep);
596
+ snapshot_data_ptr.reset(snapshot.data);
597
+ PlatformDelegate::UnregisterIsolate(isolate);
598
+ }
599
+
600
+ // Export to outer scope
601
+ if (error) {
602
+ Isolate::GetCurrent()->ThrowException(error->CopyInto());
603
+ return Undefined(Isolate::GetCurrent());
604
+ } else if (snapshot.raw_size == 0) {
605
+ throw RuntimeGenericError("Failure creating snapshot");
606
+ }
607
+ auto buffer = std::make_shared<ExternalCopyArrayBuffer>((void*)snapshot.data, snapshot.raw_size);
608
+ return ClassHandle::NewInstance<ExternalCopyHandle>(buffer);
609
+ }
610
+
611
+ } // namespace ivm
@@ -0,0 +1,47 @@
1
+ #pragma once
2
+ #include "isolate/generic/array.h"
3
+ #include "transferable.h"
4
+ #include <v8.h>
5
+ #include <memory>
6
+
7
+ namespace ivm {
8
+
9
+ /**
10
+ * Reference to a v8 isolate
11
+ */
12
+ class IsolateHandle : public TransferableHandle {
13
+ private:
14
+ std::shared_ptr<IsolateHolder> isolate;
15
+
16
+ class IsolateHandleTransferable : public Transferable {
17
+ private:
18
+ std::shared_ptr<IsolateHolder> isolate;
19
+ public:
20
+ explicit IsolateHandleTransferable(std::shared_ptr<IsolateHolder> isolate);
21
+ auto TransferIn() -> v8::Local<v8::Value> final;
22
+ };
23
+
24
+ public:
25
+ explicit IsolateHandle(std::shared_ptr<IsolateHolder> isolate);
26
+ static auto Definition() -> v8::Local<v8::FunctionTemplate>;
27
+ static auto New(v8::MaybeLocal<v8::Object> maybe_options) -> std::unique_ptr<ClassHandle>;
28
+ auto TransferOut() -> std::unique_ptr<Transferable> final;
29
+
30
+ template <int async> auto CreateContext(v8::MaybeLocal<v8::Object> maybe_options) -> v8::Local<v8::Value>;
31
+ template <int async> auto CompileScript(v8::Local<v8::String> code_handle, v8::MaybeLocal<v8::Object> maybe_options) -> v8::Local<v8::Value>;
32
+ template <int async> auto CompileModule(v8::Local<v8::String> code_handle, v8::MaybeLocal<v8::Object> maybe_options) -> v8::Local<v8::Value>;
33
+
34
+ auto CreateInspectorSession() -> v8::Local<v8::Value>;
35
+ auto Dispose() -> v8::Local<v8::Value>;
36
+ template <int async> auto GetHeapStatistics() -> v8::Local<v8::Value>;
37
+ auto GetCpuTime() -> v8::Local<v8::Value>;
38
+ auto GetWallTime() -> v8::Local<v8::Value>;
39
+ auto StartCpuProfiler(v8::Local<v8::String> title) -> v8::Local<v8::Value>;
40
+ template <int async> auto StopCpuProfiler(v8::Local<v8::String> title) -> v8::Local<v8::Value>;
41
+
42
+ auto GetReferenceCount() -> v8::Local<v8::Value>;
43
+ auto IsDisposedGetter() -> v8::Local<v8::Value>;
44
+ static auto CreateSnapshot(ArrayRange script_handles, v8::MaybeLocal<v8::String> warmup_handle) -> v8::Local<v8::Value>;
45
+ };
46
+
47
+ } // namespace ivm