@nocobase/plugin-workflow-javascript 2.1.0-beta.11 → 2.1.0-beta.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/externalVersion.js +4 -4
- package/dist/node_modules/isolated-vm/.clang-tidy +13 -0
- package/dist/node_modules/isolated-vm/.dockerignore +9 -0
- package/dist/node_modules/isolated-vm/Dockerfile.alpine +9 -0
- package/dist/node_modules/isolated-vm/Dockerfile.debian +12 -0
- package/dist/node_modules/isolated-vm/LICENSE +13 -0
- package/dist/node_modules/isolated-vm/binding.gyp +120 -0
- package/dist/node_modules/isolated-vm/include.js +3 -0
- package/dist/node_modules/isolated-vm/inspector-example.js +59 -0
- package/dist/node_modules/isolated-vm/isolated-vm.d.ts +820 -0
- package/dist/node_modules/isolated-vm/isolated-vm.js +1 -0
- package/dist/node_modules/isolated-vm/native-example/binding.gyp +23 -0
- package/dist/node_modules/isolated-vm/native-example/example.cc +61 -0
- package/dist/node_modules/isolated-vm/native-example/package.json +13 -0
- package/dist/node_modules/isolated-vm/native-example/usage.js +35 -0
- package/dist/node_modules/isolated-vm/out/isolated_vm.node +0 -0
- package/dist/node_modules/isolated-vm/package.json +1 -0
- package/dist/node_modules/isolated-vm/src/external_copy/error.h +33 -0
- package/dist/node_modules/isolated-vm/src/external_copy/external_copy.cc +509 -0
- package/dist/node_modules/isolated-vm/src/external_copy/external_copy.h +117 -0
- package/dist/node_modules/isolated-vm/src/external_copy/serializer.cc +85 -0
- package/dist/node_modules/isolated-vm/src/external_copy/serializer.h +136 -0
- package/dist/node_modules/isolated-vm/src/external_copy/serializer_nortti.cc +73 -0
- package/dist/node_modules/isolated-vm/src/external_copy/string.cc +124 -0
- package/dist/node_modules/isolated-vm/src/external_copy/string.h +28 -0
- package/dist/node_modules/isolated-vm/src/isolate/allocator.h +32 -0
- package/dist/node_modules/isolated-vm/src/isolate/allocator_nortti.cc +142 -0
- package/dist/node_modules/isolated-vm/src/isolate/class_handle.h +334 -0
- package/dist/node_modules/isolated-vm/src/isolate/cpu_profile_manager.cc +220 -0
- package/dist/node_modules/isolated-vm/src/isolate/cpu_profile_manager.h +100 -0
- package/dist/node_modules/isolated-vm/src/isolate/environment.cc +626 -0
- package/dist/node_modules/isolated-vm/src/isolate/environment.h +381 -0
- package/dist/node_modules/isolated-vm/src/isolate/executor.cc +198 -0
- package/dist/node_modules/isolated-vm/src/isolate/executor.h +183 -0
- package/dist/node_modules/isolated-vm/src/isolate/external.h +64 -0
- package/dist/node_modules/isolated-vm/src/isolate/functor_runners.h +97 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/array.h +145 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/callbacks.h +272 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/error.h +140 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/extract_params.h +145 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/handle_cast.h +257 -0
- package/dist/node_modules/isolated-vm/src/isolate/generic/read_option.h +47 -0
- package/dist/node_modules/isolated-vm/src/isolate/holder.cc +88 -0
- package/dist/node_modules/isolated-vm/src/isolate/holder.h +63 -0
- package/dist/node_modules/isolated-vm/src/isolate/inspector.cc +200 -0
- package/dist/node_modules/isolated-vm/src/isolate/inspector.h +70 -0
- package/dist/node_modules/isolated-vm/src/isolate/node_wrapper.h +15 -0
- package/dist/node_modules/isolated-vm/src/isolate/platform_delegate.cc +22 -0
- package/dist/node_modules/isolated-vm/src/isolate/platform_delegate.h +46 -0
- package/dist/node_modules/isolated-vm/src/isolate/remote_handle.h +164 -0
- package/dist/node_modules/isolated-vm/src/isolate/run_with_timeout.h +171 -0
- package/dist/node_modules/isolated-vm/src/isolate/runnable.h +29 -0
- package/dist/node_modules/isolated-vm/src/isolate/scheduler.cc +191 -0
- package/dist/node_modules/isolated-vm/src/isolate/scheduler.h +165 -0
- package/dist/node_modules/isolated-vm/src/isolate/specific.h +35 -0
- package/dist/node_modules/isolated-vm/src/isolate/stack_trace.cc +219 -0
- package/dist/node_modules/isolated-vm/src/isolate/stack_trace.h +24 -0
- package/dist/node_modules/isolated-vm/src/isolate/strings.h +127 -0
- package/dist/node_modules/isolated-vm/src/isolate/three_phase_task.cc +385 -0
- package/dist/node_modules/isolated-vm/src/isolate/three_phase_task.h +136 -0
- package/dist/node_modules/isolated-vm/src/isolate/transferable.h +15 -0
- package/dist/node_modules/isolated-vm/src/isolate/util.h +45 -0
- package/dist/node_modules/isolated-vm/src/isolate/v8_inspector_wrapper.h +12 -0
- package/dist/node_modules/isolated-vm/src/isolate/v8_version.h +12 -0
- package/dist/node_modules/isolated-vm/src/isolated_vm.h +71 -0
- package/dist/node_modules/isolated-vm/src/lib/covariant.h +50 -0
- package/dist/node_modules/isolated-vm/src/lib/lockable.h +178 -0
- package/dist/node_modules/isolated-vm/src/lib/suspend.h +106 -0
- package/dist/node_modules/isolated-vm/src/lib/thread_pool.cc +98 -0
- package/dist/node_modules/isolated-vm/src/lib/thread_pool.h +45 -0
- package/dist/node_modules/isolated-vm/src/lib/timer.cc +233 -0
- package/dist/node_modules/isolated-vm/src/lib/timer.h +36 -0
- package/dist/node_modules/isolated-vm/src/module/callback.cc +151 -0
- package/dist/node_modules/isolated-vm/src/module/callback.h +64 -0
- package/dist/node_modules/isolated-vm/src/module/context_handle.cc +241 -0
- package/dist/node_modules/isolated-vm/src/module/context_handle.h +35 -0
- package/dist/node_modules/isolated-vm/src/module/evaluation.cc +109 -0
- package/dist/node_modules/isolated-vm/src/module/evaluation.h +99 -0
- package/dist/node_modules/isolated-vm/src/module/external_copy_handle.cc +119 -0
- package/dist/node_modules/isolated-vm/src/module/external_copy_handle.h +64 -0
- package/dist/node_modules/isolated-vm/src/module/isolate.cc +136 -0
- package/dist/node_modules/isolated-vm/src/module/isolate_handle.cc +611 -0
- package/dist/node_modules/isolated-vm/src/module/isolate_handle.h +47 -0
- package/dist/node_modules/isolated-vm/src/module/lib_handle.cc +77 -0
- package/dist/node_modules/isolated-vm/src/module/lib_handle.h +28 -0
- package/dist/node_modules/isolated-vm/src/module/module_handle.cc +475 -0
- package/dist/node_modules/isolated-vm/src/module/module_handle.h +68 -0
- package/dist/node_modules/isolated-vm/src/module/native_module_handle.cc +104 -0
- package/dist/node_modules/isolated-vm/src/module/native_module_handle.h +49 -0
- package/dist/node_modules/isolated-vm/src/module/reference_handle.cc +636 -0
- package/dist/node_modules/isolated-vm/src/module/reference_handle.h +106 -0
- package/dist/node_modules/isolated-vm/src/module/script_handle.cc +107 -0
- package/dist/node_modules/isolated-vm/src/module/script_handle.h +37 -0
- package/dist/node_modules/isolated-vm/src/module/session_handle.cc +173 -0
- package/dist/node_modules/isolated-vm/src/module/session_handle.h +31 -0
- package/dist/node_modules/isolated-vm/src/module/transferable.cc +268 -0
- package/dist/node_modules/isolated-vm/src/module/transferable.h +42 -0
- package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v18.0.0.h +360 -0
- package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v18.3.0.h +376 -0
- package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v20.0.0.h +397 -0
- package/dist/node_modules/isolated-vm/vendor/v8_inspector/nodejs_v22.0.0.h +419 -0
- package/dist/node_modules/winston-transport/package.json +1 -1
- package/dist/server/IsolatedVm.js +75 -0
- package/dist/server/ScriptInstruction.d.ts +6 -0
- package/dist/server/ScriptInstruction.js +11 -1
- package/dist/server/Vm.js +42 -27
- package/package.json +3 -2
|
@@ -0,0 +1,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
|