@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,77 @@
1
+ #include "lib_handle.h"
2
+ #include <uv.h>
3
+
4
+ using namespace v8;
5
+ using std::unique_ptr;
6
+
7
+ namespace ivm {
8
+
9
+ /**
10
+ * Stateless transferable interface
11
+ */
12
+ auto LibHandle::LibTransferable::TransferIn() -> Local<Value> {
13
+ return ClassHandle::NewInstance<LibHandle>();
14
+ }
15
+
16
+ /**
17
+ * ivm.lib API container
18
+ */
19
+ auto LibHandle::Definition() -> Local<FunctionTemplate> {
20
+ return Inherit<TransferableHandle>(MakeClass(
21
+ "Lib", nullptr,
22
+ "hrtime", MemberFunction<decltype(&LibHandle::Hrtime), &LibHandle::Hrtime>{},
23
+ "privateSymbol", MemberFunction<decltype(&LibHandle::PrivateSymbol), &LibHandle::PrivateSymbol>{},
24
+ "testHang", MemberFunction<decltype(&LibHandle::TestHang), &LibHandle::TestHang>{},
25
+ "testOOM", MemberFunction<decltype(&LibHandle::TestOOM), &LibHandle::TestOOM>{}
26
+ ));
27
+ }
28
+
29
+ auto LibHandle::TransferOut() -> unique_ptr<Transferable> {
30
+ return std::make_unique<LibTransferable>();
31
+ }
32
+
33
+ // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
34
+ auto LibHandle::Hrtime(MaybeLocal<Array> maybe_diff) -> Local<Value> {
35
+ Isolate* isolate = Isolate::GetCurrent();
36
+ Local<Context> context = isolate->GetCurrentContext();
37
+ uint64_t time = uv_hrtime();
38
+ constexpr auto kNanos = (uint64_t)1e9;
39
+ Local<Array> diff;
40
+ if (maybe_diff.ToLocal(&diff)) {
41
+ if (diff->Length() != 2) {
42
+ throw RuntimeTypeError("hrtime diff must be 2-length array");
43
+ }
44
+ uint64_t time_diff = Unmaybe(diff->Get(context, 0)).As<Uint32>()->Value() * kNanos + Unmaybe(diff->Get(context, 1)).As<Uint32>()->Value();
45
+ time -= time_diff;
46
+ }
47
+ Local<Array> ret = Array::New(isolate, 2);
48
+ Unmaybe(ret->Set(context, 0, Uint32::New(isolate, (uint32_t)(time / kNanos))));
49
+ Unmaybe(ret->Set(context, 1, Uint32::New(isolate, (uint32_t)(time - (time / kNanos) * kNanos))));
50
+ return ret;
51
+ }
52
+
53
+ // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
54
+ auto LibHandle::PrivateSymbol(MaybeLocal<String> maybe_name) -> Local<Value> {
55
+ Local<String> name{};
56
+ if (maybe_name.ToLocal(&name)) { /* nothing */ }
57
+ auto symbol = Private::New(Isolate::GetCurrent(), name);
58
+ return *reinterpret_cast<Local<Value>*>(&symbol);
59
+ }
60
+
61
+ // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
62
+ auto LibHandle::TestHang() -> Local<Value> {
63
+ auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(60);
64
+ while (std::chrono::steady_clock::now() < deadline) {}
65
+ return Undefined(Isolate::GetCurrent());
66
+ }
67
+
68
+ // NOLINTNEXTLINE(readability-convert-member-functions-to-static)
69
+ auto LibHandle::TestOOM() -> Local<Value> {
70
+ Isolate* isolate = Isolate::GetCurrent();
71
+ for (;;) {
72
+ Array::New(isolate, 128);
73
+ }
74
+ return {};
75
+ }
76
+
77
+ } // namespace ivm
@@ -0,0 +1,28 @@
1
+ #pragma once
2
+ #include <v8.h>
3
+
4
+ #include <memory>
5
+
6
+ #include "transferable.h"
7
+ #include "transferable.h"
8
+
9
+ namespace ivm {
10
+
11
+ class LibHandle : public TransferableHandle {
12
+ private:
13
+ class LibTransferable : public Transferable {
14
+ public:
15
+ auto TransferIn() -> v8::Local<v8::Value> final;
16
+ };
17
+
18
+ auto Hrtime(v8::MaybeLocal<v8::Array> maybe_diff) -> v8::Local<v8::Value>;
19
+ auto PrivateSymbol(v8::MaybeLocal<v8::String> maybe_name) -> v8::Local<v8::Value>;
20
+ auto TestHang() -> v8::Local<v8::Value>;
21
+ auto TestOOM() -> v8::Local<v8::Value>;
22
+
23
+ public:
24
+ static auto Definition() -> v8::Local<v8::FunctionTemplate>;
25
+ auto TransferOut() -> std::unique_ptr<Transferable> final;
26
+ };
27
+
28
+ } // namespace ivm
@@ -0,0 +1,475 @@
1
+ #include "module_handle.h"
2
+ #include "context_handle.h"
3
+ #include "reference_handle.h"
4
+ #include "transferable.h"
5
+ #include "isolate/class_handle.h"
6
+ #include "isolate/run_with_timeout.h"
7
+ #include "isolate/three_phase_task.h"
8
+
9
+ #include <algorithm>
10
+
11
+ using namespace v8;
12
+ using std::shared_ptr;
13
+
14
+ namespace ivm {
15
+
16
+
17
+ namespace {
18
+
19
+ auto LookupModuleInfo(Local<Module> module) {
20
+ auto& module_map = IsolateEnvironment::GetCurrent().module_handles;
21
+ auto range = module_map.equal_range(module->GetIdentityHash());
22
+ auto it = std::find_if(range.first, range.second, [&](decltype(*module_map.begin()) data) {
23
+ return data.second->handle.Deref() == module;
24
+ });
25
+ return it == range.second ? nullptr : it->second;
26
+ }
27
+
28
+ } // anonymous namespace
29
+
30
+ ModuleInfo::ModuleInfo(Local<Module> handle) : identity_hash{handle->GetIdentityHash()}, handle{handle} {
31
+ // Add to isolate's list of modules
32
+ IsolateEnvironment::GetCurrent().module_handles.emplace(identity_hash, this);
33
+ // Grab all dependency specifiers
34
+ Isolate* isolate = Isolate::GetCurrent();
35
+ auto context = isolate->GetCurrentContext();
36
+ auto& requests = **handle->GetModuleRequests();
37
+ dependency_specifiers.reserve(requests.Length());
38
+ for (int ii = 0; ii < requests.Length(); ii++) {
39
+ auto request = requests.Get(context, ii).As<ModuleRequest>();
40
+ dependency_specifiers.emplace_back(*String::Utf8Value{isolate, request->GetSpecifier()});
41
+ }
42
+ }
43
+
44
+ ModuleInfo::~ModuleInfo() {
45
+ // Remove from isolate's list of modules
46
+ auto environment = handle.GetIsolateHolder()->GetIsolate();
47
+ if (environment) {
48
+ auto& module_map = environment->module_handles;
49
+ auto range = module_map.equal_range(identity_hash);
50
+ auto it = std::find_if(range.first, range.second, [&](decltype(*module_map.begin()) data) {
51
+ return this == data.second;
52
+ });
53
+ assert(it != range.second);
54
+ module_map.erase(it);
55
+ }
56
+ }
57
+
58
+ ModuleHandle::ModuleHandleTransferable::ModuleHandleTransferable(shared_ptr<ModuleInfo> info) : info(std::move(info)) {}
59
+
60
+ auto ModuleHandle::ModuleHandleTransferable::TransferIn() -> Local<Value> {
61
+ return ClassHandle::NewInstance<ModuleHandle>(info);
62
+ };
63
+
64
+ ModuleHandle::ModuleHandle(shared_ptr<ModuleInfo> info) : info(std::move(info)) {}
65
+
66
+ auto ModuleHandle::Definition() -> Local<FunctionTemplate> {
67
+ return Inherit<TransferableHandle>(MakeClass(
68
+ "Module", nullptr,
69
+ "dependencySpecifiers", MemberAccessor<decltype(&ModuleHandle::GetDependencySpecifiers), &ModuleHandle::GetDependencySpecifiers>{},
70
+ "instantiate", MemberFunction<decltype(&ModuleHandle::Instantiate), &ModuleHandle::Instantiate>{},
71
+ "instantiateSync", MemberFunction<decltype(&ModuleHandle::InstantiateSync), &ModuleHandle::InstantiateSync>{},
72
+ "evaluate", MemberFunction<decltype(&ModuleHandle::Evaluate<1>), &ModuleHandle::Evaluate<1>>{},
73
+ "evaluateSync", MemberFunction<decltype(&ModuleHandle::Evaluate<0>), &ModuleHandle::Evaluate<0>>{},
74
+ "namespace", MemberAccessor<decltype(&ModuleHandle::GetNamespace), &ModuleHandle::GetNamespace>{},
75
+ "release", MemberFunction<decltype(&ModuleHandle::Release), &ModuleHandle::Release>{}
76
+ ));
77
+ }
78
+
79
+ auto ModuleHandle::TransferOut() -> std::unique_ptr<Transferable> {
80
+ return std::make_unique<ModuleHandleTransferable>(info);
81
+ }
82
+
83
+ auto ModuleHandle::GetDependencySpecifiers() -> Local<Value> {
84
+ Isolate* isolate = Isolate::GetCurrent();
85
+ size_t length = info->dependency_specifiers.size();
86
+ Local<Array> deps = Array::New(isolate, length);
87
+ for (size_t ii = 0; ii < length; ++ii) {
88
+ Unmaybe(deps->Set(isolate->GetCurrentContext(), ii, v8_string(info->dependency_specifiers[ii].c_str())));
89
+ }
90
+ return deps;
91
+ }
92
+
93
+ auto ModuleHandle::GetInfo() const -> std::shared_ptr<ModuleInfo> {
94
+ if (!info) {
95
+ throw RuntimeGenericError("Module has been released");
96
+ }
97
+ return info;
98
+ }
99
+
100
+ auto ModuleHandle::Release() -> Local<Value> {
101
+ info.reset();
102
+ return Undefined(Isolate::GetCurrent());
103
+ }
104
+
105
+ void ModuleHandle::InitializeImportMeta(Local<Context> context, Local<Module> module, Local<Object> meta) {
106
+ ModuleInfo* found = LookupModuleInfo(module);
107
+ if (found != nullptr) {
108
+ if (found->meta_callback) {
109
+ detail::RunBarrier([&]() {
110
+ Local<Value> argv[1];
111
+ argv[0] = meta;
112
+ Unmaybe(found->meta_callback.Deref()->Call(context, Undefined(context->GetIsolate()), 1, argv));
113
+ });
114
+ }
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Implements the module linking logic used by `instantiate`. This is implemented as a class handle
120
+ * so v8 can manage the lifetime of the linker. If a promise fails to resolve then v8 will be
121
+ * responsible for calling the destructor.
122
+ */
123
+ class ModuleLinker : public ClassHandle {
124
+ public:
125
+ /**
126
+ * These methods are split out from the main class so I don't have to recreate the class
127
+ * inheritance in v8
128
+ */
129
+ struct Implementation {
130
+ RemoteHandle<Object> linker;
131
+ explicit Implementation(Local<Object> linker) : linker(linker) {}
132
+ virtual ~Implementation() = default;
133
+ virtual void HandleCallbackReturn(ModuleHandle* module, size_t ii, Local<Value> value) = 0;
134
+ virtual auto Begin(ModuleHandle& module, RemoteHandle<Context> context) -> Local<Value> = 0;
135
+ auto GetLinker() const -> ModuleLinker& {
136
+ auto* ptr = ClassHandle::Unwrap<ModuleLinker>(linker.Deref());
137
+ assert(ptr);
138
+ return *ptr;
139
+ }
140
+ };
141
+
142
+ private:
143
+ RemoteHandle<Function> callback;
144
+ std::unique_ptr<Implementation> impl;
145
+ std::vector<std::shared_ptr<ModuleInfo>> modules;
146
+
147
+ public:
148
+ static auto Definition() -> v8::Local<v8::FunctionTemplate> {
149
+ return MakeClass("Linker", nullptr);
150
+ }
151
+
152
+ explicit ModuleLinker(Local<Function> callback) : callback(callback) {}
153
+
154
+ ModuleLinker(const ModuleLinker&) = delete;
155
+ auto operator=(const ModuleLinker&) = delete;
156
+
157
+ ~ModuleLinker() override {
158
+ Reset();
159
+ }
160
+
161
+ template <typename T>
162
+ void SetImplementation() {
163
+ impl = std::make_unique<T>(This());
164
+ }
165
+
166
+ template <typename T>
167
+ auto GetImplementation() -> T* {
168
+ return dynamic_cast<T*>(impl.get());
169
+ }
170
+
171
+ auto Begin(ModuleHandle& module, RemoteHandle<Context> context) -> Local<Value> {
172
+ return impl->Begin(module, std::move(context));
173
+ }
174
+
175
+ void ResolveDependency(size_t ii, ModuleInfo& module, ModuleHandle* dependency) {
176
+ {
177
+ // I don't think the lock is actually needed here because this linker has already claimed
178
+ // the whole module, and this code will only be running in a single thread.. but putting
179
+ // up the lock is probably good practice or something.
180
+ std::lock_guard<std::mutex> lock(module.mutex);
181
+ module.resolutions[module.dependency_specifiers[ii]] = dependency->GetInfo();
182
+ }
183
+ Link(dependency);
184
+ }
185
+
186
+ void Link(ModuleHandle* module) {
187
+ // Check current link status
188
+ auto info = module->GetInfo();
189
+ {
190
+ std::lock_guard<std::mutex> lock(info->mutex);
191
+ switch (info->link_status) {
192
+ case ModuleInfo::LinkStatus::None:
193
+ info->link_status = ModuleInfo::LinkStatus::Linking;
194
+ info->linker = this;
195
+ break;
196
+ case ModuleInfo::LinkStatus::Linking:
197
+ if (info->linker != this) {
198
+ throw RuntimeGenericError("Module is currently being linked by another linker");
199
+ }
200
+ return;
201
+ case ModuleInfo::LinkStatus::Linked:
202
+ return;
203
+ }
204
+ }
205
+ // Recursively link
206
+ modules.emplace_back(info);
207
+ Isolate* isolate = Isolate::GetCurrent();
208
+ Local<Context> context = isolate->GetCurrentContext();
209
+ Local<Value> recv = Undefined(isolate);
210
+ Local<Value> argv[2];
211
+ argv[1] = module->This();
212
+ Local<Function> fn = callback.Deref();
213
+ for (size_t ii = 0; ii < info->dependency_specifiers.size(); ++ii) {
214
+ argv[0] = v8_string(info->dependency_specifiers[ii].c_str());
215
+ impl->HandleCallbackReturn(module, ii, Unmaybe(fn->Call(context, recv, 2, argv)));
216
+ }
217
+ }
218
+
219
+ void Reset(ModuleInfo::LinkStatus status = ModuleInfo::LinkStatus::None) {
220
+ // Clears out dependency info. If the module wasn't instantiated this resets them back to
221
+ // their original state. If it was instantiated then we don't need the dependencies anymore
222
+ // anyway.
223
+ for (auto& module : modules) {
224
+ std::lock_guard<std::mutex> lock(module->mutex);
225
+ module->linker = nullptr;
226
+ module->link_status = status;
227
+ module->resolutions.clear();
228
+ }
229
+ modules.clear();
230
+ impl.reset();
231
+ }
232
+ };
233
+
234
+ /**
235
+ * Runner for `instantiate`. By the time this is invoked the module will already have all its
236
+ * dependencies resolved by the linker.
237
+ */
238
+ struct InstantiateRunner : public ThreePhaseTask {
239
+ RemoteHandle<Context> context;
240
+ shared_ptr<ModuleInfo> info;
241
+ RemoteHandle<Object> linker;
242
+
243
+ static auto ResolveCallback(Local<Context> /*context*/, Local<String> specifier, Local<FixedArray> /*import_assertions*/, Local<Module> referrer) -> MaybeLocal<Module> {
244
+ MaybeLocal<Module> ret;
245
+ detail::RunBarrier([&]() {
246
+ // Lookup ModuleInfo* instance from `referrer`
247
+ ModuleInfo* found = LookupModuleInfo(referrer);
248
+ if (found != nullptr) {
249
+ // nb: lock is already acquired in `Instantiate`
250
+ auto& resolutions = found->resolutions;
251
+ auto it = resolutions.find(*String::Utf8Value{Isolate::GetCurrent(), specifier});
252
+ if (it != resolutions.end()) {
253
+ ret = it->second->handle.Deref();
254
+ return;
255
+ }
256
+ }
257
+ throw RuntimeGenericError("Dependency was left unresolved. Please report this error on github.");
258
+ });
259
+ return ret;
260
+ }
261
+
262
+ InstantiateRunner(
263
+ RemoteHandle<Context> context,
264
+ shared_ptr<ModuleInfo> info,
265
+ Local<Object> linker
266
+ ) :
267
+ context(std::move(context)),
268
+ info(std::move(info)),
269
+ linker(linker) {
270
+ // Sanity check
271
+ if (this->info->handle.GetIsolateHolder() != this->context.GetIsolateHolder()) {
272
+ throw RuntimeGenericError("Invalid context");
273
+ }
274
+ }
275
+
276
+ void Phase2() final {
277
+ Local<Module> mod = info->handle.Deref();
278
+ Local<Context> context_local = context.Deref();
279
+ info->context_handle = std::move(context);
280
+ std::lock_guard<std::mutex> lock{info->mutex};
281
+ TryCatch try_catch{Isolate::GetCurrent()};
282
+ try {
283
+ Unmaybe(mod->InstantiateModule(context_local, ResolveCallback));
284
+ } catch (...) {
285
+ try_catch.ReThrow();
286
+ throw;
287
+ }
288
+ // `InstantiateModule` will return Maybe<bool>{true} even when there are exceptions pending.
289
+ // This condition is checked here and a C++ is thrown which will propagate out as a JS
290
+ // exception.
291
+ if (try_catch.HasCaught()) {
292
+ try_catch.ReThrow();
293
+ throw RuntimeError();
294
+ }
295
+ }
296
+
297
+ auto Phase3() -> Local<Value> final {
298
+ ClassHandle::Unwrap<ModuleLinker>(linker.Deref())->Reset(ModuleInfo::LinkStatus::Linked);
299
+ return Undefined(Isolate::GetCurrent());
300
+ }
301
+ };
302
+
303
+ /**
304
+ * Async / sync implementations of the linker
305
+ */
306
+ class ModuleLinkerSync : public ModuleLinker::Implementation {
307
+ private:
308
+ void HandleCallbackReturn(ModuleHandle* module, size_t ii, Local<Value> value) final {
309
+ ModuleHandle* resolved = value->IsObject() ? ClassHandle::Unwrap<ModuleHandle>(value.As<Object>()) : nullptr;
310
+ if (resolved == nullptr) {
311
+ throw RuntimeTypeError("Resolved dependency was not `Module`");
312
+ }
313
+ GetLinker().ResolveDependency(ii, *module->GetInfo(), resolved);
314
+ }
315
+
316
+ public:
317
+ using ModuleLinker::Implementation::Implementation;
318
+ auto Begin(ModuleHandle& module, RemoteHandle<Context> context) -> Local<Value> final {
319
+ try {
320
+ GetLinker().Link(&module);
321
+ } catch (const RuntimeError& err) {
322
+ GetLinker().Reset();
323
+ throw;
324
+ }
325
+ auto info = module.GetInfo();
326
+ return ThreePhaseTask::Run<0, InstantiateRunner>(*info->handle.GetIsolateHolder(), context, info, linker.Deref());
327
+ }
328
+ };
329
+
330
+ class ModuleLinkerAsync : public ModuleLinker::Implementation {
331
+ private:
332
+ RemoteTuple<Promise::Resolver, Function> async_handles;
333
+ RemoteHandle<Context> context;
334
+ shared_ptr<ModuleInfo> info;
335
+ uint32_t pending = 0;
336
+
337
+ static auto ModuleResolved(Local<Array> holder, Local<Value> value) -> Local<Value> {
338
+ detail::RunBarrier([&]() {
339
+ ModuleHandle* resolved = value->IsObject() ? ClassHandle::Unwrap<ModuleHandle>(value.As<Object>()) : nullptr;
340
+ if (resolved == nullptr) {
341
+ throw RuntimeTypeError("Resolved dependency was not `Module`");
342
+ }
343
+ Local<Context> context = Isolate::GetCurrent()->GetCurrentContext();
344
+ auto* linker = ClassHandle::Unwrap<ModuleLinker>(Unmaybe(holder->Get(context, 0)).As<Object>());
345
+ auto* impl = linker->GetImplementation<ModuleLinkerAsync>();
346
+ if (impl == nullptr) {
347
+ return;
348
+ }
349
+ auto* module = ClassHandle::Unwrap<ModuleHandle>(Unmaybe(holder->Get(context, 1)).As<Object>());
350
+ auto ii = Unmaybe(holder->Get(context, 2)).As<Uint32>()->Value();
351
+ linker->ResolveDependency(ii, *module->GetInfo(), resolved);
352
+ if (--impl->pending == 0) {
353
+ impl->Instantiate();
354
+ }
355
+ });
356
+ return Undefined(Isolate::GetCurrent());
357
+ }
358
+
359
+ static auto ModuleRejected(ModuleLinker& linker, Local<Value> error) -> Local<Value> {
360
+ detail::RunBarrier([&]() {
361
+ auto* impl = linker.GetImplementation<ModuleLinkerAsync>();
362
+ if (impl != nullptr) {
363
+ Unmaybe(impl->async_handles.Deref<0>()->Reject(Isolate::GetCurrent()->GetCurrentContext(), error));
364
+ linker.Reset();
365
+ }
366
+ });
367
+ return Undefined(Isolate::GetCurrent());
368
+ }
369
+
370
+ void HandleCallbackReturn(ModuleHandle* module, size_t ii, Local<Value> value) final {
371
+ // Resolve via Promise.resolve() so thenables will work
372
+ ++pending;
373
+ Isolate* isolate = Isolate::GetCurrent();
374
+ Local<Context> context = isolate->GetCurrentContext();
375
+ Local<Promise::Resolver> resolver = Unmaybe(Promise::Resolver::New(context));
376
+ Local<Promise> promise = resolver->GetPromise();
377
+ Local<Array> holder = Array::New(isolate, 3);
378
+ Unmaybe(holder->Set(context, 0, linker.Deref()));
379
+ Unmaybe(holder->Set(context, 1, module->This()));
380
+ Unmaybe(holder->Set(context, 2, Uint32::New(isolate, ii)));
381
+ promise = Unmaybe(promise->Then(context, Unmaybe(
382
+ Function::New(context, FreeFunctionWithData<decltype(&ModuleResolved), &ModuleResolved>{}.callback, holder)
383
+ )));
384
+ Unmaybe(promise->Catch(context, async_handles.Deref<1>()));
385
+ Unmaybe(resolver->Resolve(context, value));
386
+ }
387
+
388
+ void Instantiate() {
389
+ Unmaybe(async_handles.Deref<0>()->Resolve(
390
+ Isolate::GetCurrent()->GetCurrentContext(),
391
+ ThreePhaseTask::Run<1, InstantiateRunner>(*info->handle.GetIsolateHolder(), context, info, linker.Deref())
392
+ ));
393
+ }
394
+
395
+ public:
396
+ explicit ModuleLinkerAsync(Local<Object> linker) : Implementation(linker), async_handles(
397
+ Unmaybe(Promise::Resolver::New(Isolate::GetCurrent()->GetCurrentContext())),
398
+ Unmaybe(Function::New(
399
+ Isolate::GetCurrent()->GetCurrentContext(),
400
+ FreeFunctionWithData<decltype(&ModuleRejected), &ModuleRejected>{}.callback, linker)
401
+ )
402
+ ) {}
403
+
404
+ using ModuleLinker::Implementation::Implementation;
405
+ auto Begin(ModuleHandle& module, RemoteHandle<Context> context) -> Local<Value> final {
406
+ GetLinker().Link(&module);
407
+ info = module.GetInfo();
408
+ this->context = std::move(context);
409
+ if (pending == 0) {
410
+ Instantiate();
411
+ }
412
+ return async_handles.Deref<0>()->GetPromise();
413
+ }
414
+ };
415
+
416
+ auto ModuleHandle::Instantiate(ContextHandle& context_handle, Local<Function> callback) -> Local<Value> {
417
+ auto context = context_handle.GetContext();
418
+ Local<Object> linker_handle = ClassHandle::NewInstance<ModuleLinker>(callback);
419
+ auto* linker = ClassHandle::Unwrap<ModuleLinker>(linker_handle);
420
+ linker->SetImplementation<ModuleLinkerAsync>();
421
+ return linker->Begin(*this, context);
422
+ }
423
+
424
+ auto ModuleHandle::InstantiateSync(ContextHandle& context_handle, Local<Function> callback) -> Local<Value> {
425
+ auto context = context_handle.GetContext();
426
+ Local<Object> linker_handle = ClassHandle::NewInstance<ModuleLinker>(callback);
427
+ auto* linker = ClassHandle::Unwrap<ModuleLinker>(linker_handle);
428
+ linker->SetImplementation<ModuleLinkerSync>();
429
+ return linker->Begin(*this, context);
430
+ }
431
+
432
+ struct EvaluateRunner : public ThreePhaseTask {
433
+ shared_ptr<ModuleInfo> info;
434
+ std::unique_ptr<Transferable> result;
435
+ uint32_t timeout;
436
+
437
+ EvaluateRunner(shared_ptr<ModuleInfo> info, uint32_t ms) : info(std::move(info)), timeout(ms) {}
438
+
439
+ void Phase2() final {
440
+ Local<Module> mod = info->handle.Deref();
441
+ if (mod->GetStatus() == Module::Status::kUninstantiated) {
442
+ throw RuntimeGenericError("Module is uninstantiated");
443
+ }
444
+ Local<Context> context_local = Deref(info->context_handle);
445
+ Context::Scope context_scope(context_local);
446
+ result = OptionalTransferOut(RunWithTimeout(timeout, [&]() { return mod->Evaluate(context_local); }));
447
+ std::lock_guard<std::mutex> lock(info->mutex);
448
+ info->global_namespace = RemoteHandle<Value>(mod->GetModuleNamespace());
449
+ }
450
+
451
+ auto Phase3() -> Local<Value> final {
452
+ if (result) {
453
+ return result->TransferIn();
454
+ } else {
455
+ return Undefined(Isolate::GetCurrent()).As<Value>();
456
+ }
457
+ }
458
+ };
459
+
460
+ template <int async>
461
+ auto ModuleHandle::Evaluate(MaybeLocal<Object> maybe_options) -> Local<Value> {
462
+ auto info = GetInfo();
463
+ int32_t timeout_ms = ReadOption<int32_t>(maybe_options, StringTable::Get().timeout, 0);
464
+ return ThreePhaseTask::Run<async, EvaluateRunner>(*info->handle.GetIsolateHolder(), info, timeout_ms);
465
+ }
466
+
467
+ auto ModuleHandle::GetNamespace() -> Local<Value> {
468
+ std::lock_guard<std::mutex> lock(info->mutex);
469
+ if (!info->global_namespace) {
470
+ throw RuntimeGenericError("Module has not been instantiated.");
471
+ }
472
+ return ClassHandle::NewInstance<ReferenceHandle>(info->handle.GetSharedIsolateHolder(), info->global_namespace, info->context_handle, ReferenceHandle::TypeOf::Object, true, false);
473
+ }
474
+
475
+ } // namespace ivm
@@ -0,0 +1,68 @@
1
+ #pragma once
2
+ #include <v8.h>
3
+ #include <memory>
4
+ #include <mutex>
5
+ #include "isolate/holder.h"
6
+ #include "isolate/remote_handle.h"
7
+ #include "transferable.h"
8
+
9
+ namespace ivm {
10
+
11
+ struct ModuleInfo {
12
+ // Underlying data on the module. Some information is stored outside of v8 so there is a separate
13
+ // struct to hold this data, which is then referenced by any number of handles.
14
+ friend struct InstantiateRunner;
15
+ friend class ModuleHandle;
16
+ enum class LinkStatus { None, Linking, Linked };
17
+ std::mutex mutex;
18
+ class ModuleLinker* linker = nullptr;
19
+ LinkStatus link_status = LinkStatus::None;
20
+ int identity_hash;
21
+ std::vector<std::string> dependency_specifiers;
22
+ std::unordered_map<std::string, std::shared_ptr<ModuleInfo>> resolutions;
23
+ RemoteHandle<v8::Module> handle;
24
+ RemoteHandle<v8::Context> context_handle;
25
+ RemoteHandle<v8::Value> global_namespace;
26
+ RemoteHandle<v8::Function> meta_callback;
27
+ explicit ModuleInfo(v8::Local<v8::Module> handle);
28
+ ModuleInfo(const ModuleInfo&) = delete;
29
+ auto operator=(const ModuleInfo&) = delete;
30
+ ~ModuleInfo();
31
+ };
32
+
33
+ class ModuleHandle : public TransferableHandle {
34
+ private:
35
+ class ModuleHandleTransferable : public Transferable {
36
+ private:
37
+ std::shared_ptr<ModuleInfo> info;
38
+ public:
39
+ explicit ModuleHandleTransferable(std::shared_ptr<ModuleInfo> info);
40
+ auto TransferIn() -> v8::Local<v8::Value> final;
41
+ };
42
+
43
+ std::shared_ptr<ModuleInfo> info;
44
+
45
+ public:
46
+ using DontFreezeInstance = void;
47
+
48
+ explicit ModuleHandle(std::shared_ptr<ModuleInfo> info);
49
+
50
+ static auto Definition() -> v8::Local<v8::FunctionTemplate>;
51
+ auto TransferOut() -> std::unique_ptr<Transferable> final;
52
+
53
+ auto GetDependencySpecifiers() -> v8::Local<v8::Value>;
54
+ auto GetInfo() const -> std::shared_ptr<ModuleInfo>;
55
+ auto Release() -> v8::Local<v8::Value>;
56
+
57
+ auto Instantiate(class ContextHandle& context_handle, v8::Local<v8::Function> callback) -> v8::Local<v8::Value>;
58
+ auto InstantiateSync(class ContextHandle& context_handle, v8::Local<v8::Function> callback) -> v8::Local<v8::Value>;
59
+
60
+ template <int async>
61
+ auto Evaluate(v8::MaybeLocal<v8::Object> maybe_options) -> v8::Local<v8::Value>;
62
+
63
+ auto GetNamespace() -> v8::Local<v8::Value>;
64
+
65
+ static void InitializeImportMeta(v8::Local<v8::Context> context, v8::Local<v8::Module> module, v8::Local<v8::Object> meta);
66
+ };
67
+
68
+ } // namespace ivm