@auto_js/v8 0.0.9 → 0.0.11
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/_module.cc +1 -0
- package/evaluation/module.cc +23 -20
- package/evaluation/module.h.cc +16 -17
- package/evaluation/script.cc +7 -7
- package/evaluation/script.h.cc +5 -8
- package/isolated/agent.h.cc +4 -1
- package/isolated/cluster.h.cc +1 -1
- package/isolated/memory_policy.cc +2 -2
- package/package.json +3 -3
- package/platform/delegate.cc +1 -1
- package/platform/delegate.h.cc +1 -1
- package/platform/foreground_runner.cc +2 -2
- package/platform/scheduler.cc +2 -2
- package/platform/task.cc +1 -1
- package/support/callback.cc +3 -3
- package/support/callback_storage.cc +2 -2
- package/support/error.h.cc +1 -1
- package/transfer/accept.cc +2 -2
- package/transfer/accept.h.cc +84 -40
- package/transfer/visit.cc +17 -6
- package/value/function.cc +4 -2
package/_module.cc
CHANGED
|
@@ -24,6 +24,7 @@ export import :evaluation.script;
|
|
|
24
24
|
export import :isolated.agent;
|
|
25
25
|
export import :isolated.clock;
|
|
26
26
|
export import :isolated.cluster;
|
|
27
|
+
export import :isolated.executor;
|
|
27
28
|
export import :isolated.memory_policy;
|
|
28
29
|
export import :isolated.platform;
|
|
29
30
|
export import :platform.delegate;
|
package/evaluation/module.cc
CHANGED
|
@@ -11,8 +11,8 @@ import v8;
|
|
|
11
11
|
|
|
12
12
|
namespace js::iv8 {
|
|
13
13
|
|
|
14
|
-
auto module_record::requests(context_lock_witness lock
|
|
15
|
-
auto requests_array = fixed_array{lock.context(),
|
|
14
|
+
auto module_record::requests(context_lock_witness lock) -> std::vector<module_request> {
|
|
15
|
+
auto requests_array = fixed_array{lock.context(), GetModuleRequests()};
|
|
16
16
|
auto requests_view =
|
|
17
17
|
requests_array |
|
|
18
18
|
std::views::transform([ & ](v8::Local<v8::Data> value) -> module_request {
|
|
@@ -38,7 +38,7 @@ auto module_record::requests(context_lock_witness lock, v8::Local<v8::Module> mo
|
|
|
38
38
|
return {std::from_range, std::move(requests_view)};
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
auto module_record::compile(context_lock_witness lock, v8::Local<v8::String> source_text, iv8::source_origin origin) ->
|
|
41
|
+
auto module_record::compile(context_lock_witness lock, v8::Local<v8::String> source_text, iv8::source_origin origin) -> v8::MaybeLocal<module_record> {
|
|
42
42
|
auto location = origin.location.value_or(source_location{});
|
|
43
43
|
auto maybe_resource_name = js::transfer_in_strict<v8::MaybeLocal<v8::String>>(std::move(origin).name, lock);
|
|
44
44
|
v8::Local<v8::String> resource_name{};
|
|
@@ -56,9 +56,7 @@ auto module_record::compile(context_lock_witness lock, v8::Local<v8::String> sou
|
|
|
56
56
|
true,
|
|
57
57
|
};
|
|
58
58
|
v8::ScriptCompiler::Source source{source_text, script_origin};
|
|
59
|
-
return
|
|
60
|
-
return v8::ScriptCompiler::CompileModule(lock.isolate(), &source);
|
|
61
|
-
});
|
|
59
|
+
return v8::ScriptCompiler::CompileModule(lock.isolate(), &source).As<module_record>();
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
auto module_record::create_synthetic(
|
|
@@ -66,12 +64,12 @@ auto module_record::create_synthetic(
|
|
|
66
64
|
v8::Local<v8::String> module_name,
|
|
67
65
|
std::span<const v8::Local<v8::String>> export_names,
|
|
68
66
|
std::span<const v8::Local<v8::Data>> export_values
|
|
69
|
-
) -> v8::Local<
|
|
67
|
+
) -> v8::Local<module_record> {
|
|
70
68
|
thread_local std::span<const v8::Local<v8::String>>* tl_export_names;
|
|
71
69
|
thread_local std::span<const v8::Local<v8::Data>>* tl_export_values;
|
|
72
70
|
tl_export_names = &export_names;
|
|
73
71
|
tl_export_values = &export_values;
|
|
74
|
-
auto scope_exit = util::scope_exit{[ & ]
|
|
72
|
+
auto scope_exit = util::scope_exit{[ & ] {
|
|
75
73
|
tl_export_names = nullptr;
|
|
76
74
|
tl_export_values = nullptr;
|
|
77
75
|
}};
|
|
@@ -79,7 +77,7 @@ auto module_record::create_synthetic(
|
|
|
79
77
|
// Make `v8::Module` record with immediate evaluation steps
|
|
80
78
|
v8::Module::SyntheticModuleEvaluationSteps evaluation_steps =
|
|
81
79
|
[](v8::Local<v8::Context> context, v8::Local<v8::Module> module) -> v8::MaybeLocal<v8::Value> {
|
|
82
|
-
auto lock = [ & ]
|
|
80
|
+
auto lock = [ & ] -> context_lock_witness {
|
|
83
81
|
auto isolate_witness = isolate_lock_witness::make_witness(v8::Isolate::GetCurrent());
|
|
84
82
|
return context_lock_witness::make_witness(isolate_witness, context);
|
|
85
83
|
}();
|
|
@@ -102,19 +100,19 @@ auto module_record::create_synthetic(
|
|
|
102
100
|
return resolver->GetPromise();
|
|
103
101
|
};
|
|
104
102
|
auto v8_export_names = v8::MemorySpan<const v8::Local<v8::String>>{export_names.begin(), export_names.end()};
|
|
105
|
-
auto
|
|
103
|
+
auto synthetic_module = v8::Module::CreateSyntheticModule(lock.isolate(), module_name, v8_export_names, evaluation_steps);
|
|
106
104
|
|
|
107
105
|
// "Link" the module, which is a no-op
|
|
108
106
|
// auto null_callback = v8::Module::ResolveModuleByIndexCallback{nullptr};
|
|
109
107
|
auto null_callback = v8::Module::ResolveModuleCallback{nullptr};
|
|
110
|
-
unmaybe(
|
|
108
|
+
unmaybe(synthetic_module->InstantiateModule(lock.context(), null_callback));
|
|
111
109
|
|
|
112
110
|
// `Evaluate` invokes `evaluation_steps` above
|
|
113
|
-
unmaybe(
|
|
114
|
-
return module_record;
|
|
111
|
+
unmaybe(synthetic_module->Evaluate(lock.context()));
|
|
112
|
+
return synthetic_module.As<module_record>();
|
|
115
113
|
}
|
|
116
114
|
|
|
117
|
-
auto module_record::link(context_lock_witness lock,
|
|
115
|
+
auto module_record::link(context_lock_witness lock, module_link_record link_record) -> void {
|
|
118
116
|
// Initialize link state
|
|
119
117
|
auto module_specifier_map = std::unordered_map<v8::Local<v8::Module>, unsigned, address_hash>{};
|
|
120
118
|
auto module_id = 0U;
|
|
@@ -146,11 +144,13 @@ auto module_record::link(context_lock_witness lock, v8::Local<v8::Module> module
|
|
|
146
144
|
return (*linker_ptr)(referrer, module_request_index);
|
|
147
145
|
}
|
|
148
146
|
};
|
|
149
|
-
|
|
147
|
+
// nb: It is strange that we need js here.
|
|
148
|
+
auto allow_js = v8::Isolate::AllowJavascriptExecutionScope{lock.isolate()};
|
|
149
|
+
unmaybe(InstantiateModule(lock.context(), v8_callback));
|
|
150
150
|
linker_ptr = nullptr;
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
auto module_record::link(context_lock_witness lock
|
|
153
|
+
auto module_record::link(context_lock_witness lock) -> void {
|
|
154
154
|
// Probably a synthetic module
|
|
155
155
|
auto v8_callback = v8::Module::ResolveModuleByIndexCallback{
|
|
156
156
|
[](
|
|
@@ -161,12 +161,15 @@ auto module_record::link(context_lock_witness lock, v8::Local<v8::Module> module
|
|
|
161
161
|
std::terminate();
|
|
162
162
|
}
|
|
163
163
|
};
|
|
164
|
-
unmaybe(
|
|
164
|
+
unmaybe(InstantiateModule(lock.context(), v8_callback));
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
auto module_record::evaluate(context_lock_witness lock
|
|
168
|
-
auto promise =
|
|
169
|
-
|
|
167
|
+
auto module_record::evaluate(context_lock_witness lock) -> expected_value_type {
|
|
168
|
+
auto promise = [ & ] -> auto {
|
|
169
|
+
auto allow_js = v8::Isolate::AllowJavascriptExecutionScope{lock.isolate()};
|
|
170
|
+
return unmaybe(Evaluate(lock.context())).As<v8::Promise>();
|
|
171
|
+
}();
|
|
172
|
+
if (IsGraphAsync()) {
|
|
170
173
|
throw std::runtime_error{"Module is async"};
|
|
171
174
|
}
|
|
172
175
|
if (promise->State() == v8::Promise::kRejected) {
|
package/evaluation/module.h.cc
CHANGED
|
@@ -45,53 +45,52 @@ export struct module_link_record {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
// `v8::Module` utilities
|
|
48
|
-
export class module_record {
|
|
48
|
+
export class module_record : public v8::Module {
|
|
49
49
|
public:
|
|
50
|
-
using expected_module_type = std::expected<v8::Local<v8::Module>, js::error_value>;
|
|
51
50
|
using expected_value_type = std::expected<std::monostate, js::error_value>;
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
auto evaluate(context_lock_witness lock) -> expected_value_type;
|
|
53
|
+
auto link(context_lock_witness lock, module_link_record link_record) -> void;
|
|
54
|
+
auto link(context_lock_witness lock) -> void;
|
|
55
|
+
auto requests(context_lock_witness lock) -> std::vector<module_request>;
|
|
57
56
|
|
|
58
|
-
static auto compile(context_lock_witness lock, auto source_text, iv8::source_origin origin) ->
|
|
57
|
+
static auto compile(context_lock_witness lock, auto source_text, iv8::source_origin origin) -> v8::MaybeLocal<module_record>;
|
|
59
58
|
|
|
60
59
|
template <class... Types>
|
|
61
|
-
static auto create_synthetic(context_lock_witness lock, auto origin, std::tuple<std::in_place_t, Types...> module_interface) -> v8::Local<
|
|
60
|
+
static auto create_synthetic(context_lock_witness lock, auto origin, std::tuple<std::in_place_t, Types...> module_interface) -> v8::Local<module_record>;
|
|
62
61
|
|
|
63
62
|
template <class... Types>
|
|
64
|
-
static auto create_synthetic(context_lock_witness lock, auto origin, std::tuple<Types...> module_interface) -> v8::Local<
|
|
63
|
+
static auto create_synthetic(context_lock_witness lock, auto origin, std::tuple<Types...> module_interface) -> v8::Local<module_record>;
|
|
65
64
|
|
|
66
65
|
template <class Type>
|
|
67
|
-
static auto create_synthetic(context_lock_witness lock, auto origin, std::vector<Type> module_interface) -> v8::Local<
|
|
66
|
+
static auto create_synthetic(context_lock_witness lock, auto origin, std::vector<Type> module_interface) -> v8::Local<module_record>;
|
|
68
67
|
|
|
69
68
|
static auto create_synthetic(
|
|
70
69
|
context_lock_witness lock,
|
|
71
70
|
v8::Local<v8::String> module_name,
|
|
72
71
|
std::span<const v8::Local<v8::String>> export_names,
|
|
73
72
|
std::span<const v8::Local<v8::Data>> export_values
|
|
74
|
-
) -> v8::Local<
|
|
73
|
+
) -> v8::Local<module_record>;
|
|
75
74
|
|
|
76
75
|
private:
|
|
77
|
-
static auto compile(context_lock_witness lock, v8::Local<v8::String> source_text, iv8::source_origin origin) ->
|
|
76
|
+
static auto compile(context_lock_witness lock, v8::Local<v8::String> source_text, iv8::source_origin origin) -> v8::MaybeLocal<module_record>;
|
|
78
77
|
};
|
|
79
78
|
|
|
80
79
|
// ---
|
|
81
80
|
|
|
82
|
-
auto module_record::compile(context_lock_witness lock, auto source_text, iv8::source_origin origin) ->
|
|
81
|
+
auto module_record::compile(context_lock_witness lock, auto source_text, iv8::source_origin origin) -> v8::MaybeLocal<module_record> {
|
|
83
82
|
auto local_source_text = js::transfer_in_strict<v8::Local<v8::String>>(std::move(source_text), lock);
|
|
84
83
|
return compile(lock, local_source_text, std::move(origin));
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
template <class... Types>
|
|
88
|
-
auto module_record::create_synthetic(context_lock_witness lock, auto origin, std::tuple<std::in_place_t, Types...> module_interface) -> v8::Local<
|
|
89
|
-
auto [... ii ] = util::sequence<sizeof...(Types)>;
|
|
87
|
+
auto module_record::create_synthetic(context_lock_witness lock, auto origin, std::tuple<std::in_place_t, Types...> module_interface) -> v8::Local<module_record> {
|
|
88
|
+
constexpr auto [... ii ] = util::sequence<sizeof...(Types)>;
|
|
90
89
|
return create_synthetic(lock, origin, std::tuple{std::get<ii + 1>(module_interface)...});
|
|
91
90
|
}
|
|
92
91
|
|
|
93
92
|
template <class... Types>
|
|
94
|
-
auto module_record::create_synthetic(context_lock_witness lock, auto origin, std::tuple<Types...> module_interface) -> v8::Local<
|
|
93
|
+
auto module_record::create_synthetic(context_lock_witness lock, auto origin, std::tuple<Types...> module_interface) -> v8::Local<module_record> {
|
|
95
94
|
const auto& [... entries ] = module_interface;
|
|
96
95
|
auto origin_local = js::transfer_in_strict<v8::Local<v8::String>>(std::move(origin), lock);
|
|
97
96
|
auto names = js::transfer_in_strict<std::array<v8::Local<v8::String>, sizeof...(Types)>>(std::tuple{std::get<0>(entries)...}, lock);
|
|
@@ -100,7 +99,7 @@ auto module_record::create_synthetic(context_lock_witness lock, auto origin, std
|
|
|
100
99
|
}
|
|
101
100
|
|
|
102
101
|
template <class Type>
|
|
103
|
-
auto module_record::create_synthetic(context_lock_witness lock, auto origin, std::vector<Type> module_interface) -> v8::Local<
|
|
102
|
+
auto module_record::create_synthetic(context_lock_witness lock, auto origin, std::vector<Type> module_interface) -> v8::Local<module_record> {
|
|
104
103
|
auto origin_local = js::transfer_in_strict<v8::Local<v8::String>>(std::move(origin), lock);
|
|
105
104
|
auto name_locals = std::vector<v8::Local<v8::String>>{};
|
|
106
105
|
name_locals.reserve(module_interface.size());
|
package/evaluation/script.cc
CHANGED
|
@@ -7,7 +7,7 @@ import v8;
|
|
|
7
7
|
|
|
8
8
|
namespace js::iv8 {
|
|
9
9
|
|
|
10
|
-
auto script::compile(context_lock_witness lock, v8::Local<v8::String> code_string, source_origin source_origin) ->
|
|
10
|
+
auto script::compile(context_lock_witness lock, v8::Local<v8::String> code_string, source_origin source_origin) -> v8::MaybeLocal<script> {
|
|
11
11
|
auto location = source_origin.location.value_or(source_location{});
|
|
12
12
|
auto maybe_resource_name = js::transfer_in_strict<v8::MaybeLocal<v8::String>>(std::move(source_origin).name, lock);
|
|
13
13
|
v8::Local<v8::String> resource_name{};
|
|
@@ -15,14 +15,14 @@ auto script::compile(context_lock_witness lock, v8::Local<v8::String> code_strin
|
|
|
15
15
|
std::ignore = maybe_resource_name.ToLocal(&resource_name);
|
|
16
16
|
v8::ScriptOrigin origin{resource_name, location.line, location.column};
|
|
17
17
|
v8::ScriptCompiler::Source source{code_string, origin};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
auto unbound_script = v8::ScriptCompiler::CompileUnboundScript(lock.isolate(), &source);
|
|
19
|
+
// nb: `As<script>()` doesn't work because `v8::UnboundScript` doesn't provide a `Cast` function
|
|
20
|
+
return std::bit_cast<v8::MaybeLocal<script>>(unbound_script);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
auto script::run(context_lock_witness lock
|
|
24
|
-
auto
|
|
25
|
-
return unmaybe(
|
|
23
|
+
auto script::run(context_lock_witness lock) -> v8::Local<v8::Value> {
|
|
24
|
+
auto allow_js = v8::Isolate::AllowJavascriptExecutionScope{lock.isolate()};
|
|
25
|
+
return unmaybe(BindToCurrentContext()->Run(lock.context()));
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
} // namespace js::iv8
|
package/evaluation/script.h.cc
CHANGED
|
@@ -7,23 +7,20 @@ import v8;
|
|
|
7
7
|
|
|
8
8
|
namespace js::iv8 {
|
|
9
9
|
|
|
10
|
-
export
|
|
10
|
+
export class script : public v8::UnboundScript {
|
|
11
11
|
public:
|
|
12
|
-
using expected_script_type = std::expected<v8::Local<v8::UnboundScript>, js::error_value>;
|
|
13
|
-
using expected_value_type = std::optional<std::expected<js::value_t, js::error_value>>;
|
|
14
|
-
|
|
15
12
|
// nb: It is undocumented (and even mentions "context independent"), but the script compiler
|
|
16
13
|
// actually needs a context because it can throw an error and *that* would need a context.
|
|
17
|
-
static auto compile(context_lock_witness lock, auto code_string, source_origin source_origin) ->
|
|
18
|
-
|
|
14
|
+
static auto compile(context_lock_witness lock, auto code_string, source_origin source_origin) -> v8::MaybeLocal<script>;
|
|
15
|
+
auto run(context_lock_witness lock) -> v8::Local<v8::Value>;
|
|
19
16
|
|
|
20
17
|
private:
|
|
21
|
-
static auto compile(context_lock_witness lock, v8::Local<v8::String> code_string, source_origin source_origin) ->
|
|
18
|
+
static auto compile(context_lock_witness lock, v8::Local<v8::String> code_string, source_origin source_origin) -> v8::MaybeLocal<script>;
|
|
22
19
|
};
|
|
23
20
|
|
|
24
21
|
// ---
|
|
25
22
|
|
|
26
|
-
auto script::compile(context_lock_witness lock, auto code_string, source_origin source_origin) ->
|
|
23
|
+
auto script::compile(context_lock_witness lock, auto code_string, source_origin source_origin) -> v8::MaybeLocal<script> {
|
|
27
24
|
auto local_code_string = js::transfer_in_strict<v8::Local<v8::String>>(std::move(code_string), lock);
|
|
28
25
|
return compile(lock, local_code_string, std::move(source_origin));
|
|
29
26
|
}
|
package/isolated/agent.h.cc
CHANGED
|
@@ -19,7 +19,7 @@ class agent_host_of;
|
|
|
19
19
|
|
|
20
20
|
// `agent_host` behavior parameters
|
|
21
21
|
export struct behavior_params {
|
|
22
|
-
memory_policy::covariant memory_policy;
|
|
22
|
+
isolated::memory_policy::covariant memory_policy;
|
|
23
23
|
clock::any_clock clock;
|
|
24
24
|
std::optional<double> random_seed;
|
|
25
25
|
};
|
|
@@ -201,6 +201,9 @@ auto agent_handle_of<Type>::schedule(Task task, Args... args) const -> void {
|
|
|
201
201
|
[](std::stop_token /*stop_token*/, const auto& host, const auto& task, auto&&... args) -> void {
|
|
202
202
|
auto isolate_lock = isolate_execution_lock{host->executor().isolate()};
|
|
203
203
|
std::visit([](auto& clock) -> void { clock.begin_tick(); }, host->clock());
|
|
204
|
+
// By default we disallow code execution except when explicitly annotated
|
|
205
|
+
auto disallow_js =
|
|
206
|
+
v8::Isolate::DisallowJavascriptExecutionScope{isolate_lock.isolate(), v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE};
|
|
204
207
|
task(lock{isolate_lock, static_cast<agent_host_of<Type>&>(*host)}, std::forward<decltype(args)>(args)...);
|
|
205
208
|
},
|
|
206
209
|
std::move(host),
|
package/isolated/cluster.h.cc
CHANGED
|
@@ -42,7 +42,7 @@ auto cluster::make_agent(auto make_environment, behavior_params params, auto cal
|
|
|
42
42
|
) -> auto {
|
|
43
43
|
auto host = std::make_shared<agent_host_of<environment_type>>(std::move(storage), params);
|
|
44
44
|
auto isolate_lock = isolate_execution_lock{host->executor().isolate()};
|
|
45
|
-
host->emplace_environment(util::elide{[ & ]
|
|
45
|
+
host->emplace_environment(util::elide{[ & ] -> environment_type {
|
|
46
46
|
return make_environment(agent_lock{isolate_lock, *host});
|
|
47
47
|
}});
|
|
48
48
|
auto lock = agent_lock_of{isolate_lock, *host};
|
|
@@ -42,8 +42,8 @@ auto memory_policy::limited::near_heap_limit_callback(std::size_t current_heap_l
|
|
|
42
42
|
auto& executor = agent_host::get_current(isolate).executor();
|
|
43
43
|
executor.terminate();
|
|
44
44
|
}
|
|
45
|
-
// Increase heap limit
|
|
46
|
-
return current_heap_limit + (
|
|
45
|
+
// Increase heap limit 80mb at a time. Experimentally derived.
|
|
46
|
+
return current_heap_limit + (80 << 20);
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
} // namespace js::iv8::isolated
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@auto_js/v8",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"author": "https://github.com/laverdet/",
|
|
5
5
|
"homepage": "https://github.com/laverdet/isolated-vm/tree/experimental/packages/auto_js/v8",
|
|
6
6
|
"license": "ISC",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@auto_js/js": "^0.0.
|
|
9
|
-
"@auto_js/v8_exports": "^0.0.
|
|
8
|
+
"@auto_js/js": "^0.0.11",
|
|
9
|
+
"@auto_js/v8_exports": "^0.0.8"
|
|
10
10
|
},
|
|
11
11
|
"repository": {
|
|
12
12
|
"type": "git",
|
package/platform/delegate.cc
CHANGED
|
@@ -15,7 +15,7 @@ struct platform_instance_handle {
|
|
|
15
15
|
util::lockable<platform_instance_handle> shared_platform;
|
|
16
16
|
|
|
17
17
|
platform_handle::platform_handle(const std::type_info& type, make_type* make) :
|
|
18
|
-
platform_{util::elide{[ & ]
|
|
18
|
+
platform_{util::elide{[ & ] -> std::shared_ptr<v8::Platform> {
|
|
19
19
|
auto lock = shared_platform.write();
|
|
20
20
|
auto acquired_platform = lock->platform.lock();
|
|
21
21
|
if (acquired_platform) {
|
package/platform/delegate.h.cc
CHANGED
|
@@ -83,7 +83,7 @@ export class instrumentation_delegate : virtual public v8::Platform {
|
|
|
83
83
|
|
|
84
84
|
template <class Delegate>
|
|
85
85
|
auto platform_handle::acquire() -> platform_handle {
|
|
86
|
-
constexpr auto make = []
|
|
86
|
+
constexpr auto make = [] -> std::shared_ptr<v8::Platform> {
|
|
87
87
|
return std::make_shared<Delegate>();
|
|
88
88
|
};
|
|
89
89
|
return platform_handle{typeid(Delegate), make};
|
|
@@ -35,13 +35,13 @@ auto foreground_runner::terminate() -> void {
|
|
|
35
35
|
auto foreground_runner::get_for_priority(std::shared_ptr<foreground_runner> self, v8::TaskPriority priority) -> std::shared_ptr<v8::TaskRunner> {
|
|
36
36
|
return util::template_switch(
|
|
37
37
|
priority_numeric_from(priority),
|
|
38
|
-
util::
|
|
38
|
+
util::sequence_cw<priority_count>,
|
|
39
39
|
util::overloaded{
|
|
40
40
|
[ & ](auto priority) -> std::shared_ptr<v8::TaskRunner> {
|
|
41
41
|
using priority_runner_of = foreground_runner_of_priority<priority_enum_from(priority)>;
|
|
42
42
|
return std::static_pointer_cast<priority_runner_of>(std::move(self));
|
|
43
43
|
},
|
|
44
|
-
[]
|
|
44
|
+
[] -> std::shared_ptr<v8::TaskRunner> {
|
|
45
45
|
throw std::logic_error{"Invalid 'foreground_runner' priority"};
|
|
46
46
|
},
|
|
47
47
|
}
|
package/platform/scheduler.cc
CHANGED
|
@@ -138,7 +138,7 @@ auto scheduler_foreground_thread::controller::run(
|
|
|
138
138
|
});
|
|
139
139
|
const auto any_stop_token = util::composite_stop_token{std::move(stop_token), termination_stop_token};
|
|
140
140
|
while (!any_stop_token.stop_requested()) {
|
|
141
|
-
auto [... timeout ] = [ & ]
|
|
141
|
+
auto [... timeout ] = [ & ] -> auto {
|
|
142
142
|
if constexpr (requires { typename queue_type::clock_type; }) {
|
|
143
143
|
return std::tuple{lock->queue.flush(queue_type::clock_type::now())};
|
|
144
144
|
} else {
|
|
@@ -192,7 +192,7 @@ auto scheduler_background_threads::controller::run(
|
|
|
192
192
|
});
|
|
193
193
|
const auto any_stop_token = util::composite_stop_token{std::move(stop_token), termination_stop_token};
|
|
194
194
|
while (!any_stop_token.stop_requested()) {
|
|
195
|
-
auto [... timeout ] = [ & ]
|
|
195
|
+
auto [... timeout ] = [ & ] -> auto {
|
|
196
196
|
if constexpr (requires { typename queue_type::clock_type; }) {
|
|
197
197
|
return std::tuple{lock->queue.flush(queue_type::clock_type::now())};
|
|
198
198
|
} else {
|
package/platform/task.cc
CHANGED
|
@@ -43,7 +43,7 @@ class task_of final : public v8::Task {
|
|
|
43
43
|
|
|
44
44
|
template <class... Args>
|
|
45
45
|
auto make_task_of(std::invocable<std::stop_token, Args...> auto callback, Args&&... args) -> std::unique_ptr<v8::Task> {
|
|
46
|
-
auto task = [ & ]
|
|
46
|
+
auto task = [ & ] -> auto {
|
|
47
47
|
if constexpr (sizeof...(Args) == 0) {
|
|
48
48
|
return std::move(callback);
|
|
49
49
|
} else {
|
package/support/callback.cc
CHANGED
|
@@ -29,8 +29,8 @@ constexpr auto make_free_function_with_try_catch =
|
|
|
29
29
|
auto bound_function = util::bind{
|
|
30
30
|
[](callback_type& callback, Lock lock, const v8::FunctionCallbackInfo<v8::Value>& info) noexcept(Nx) -> void {
|
|
31
31
|
// NOLINTNEXTLINE(cppcoreguidelines-slicing)
|
|
32
|
-
auto result = invoke_internal_error_scope(lock, [ & ]
|
|
33
|
-
auto run = util::regular_return{[ & ]
|
|
32
|
+
auto result = invoke_internal_error_scope(lock, [ & ] -> auto {
|
|
33
|
+
auto run = util::regular_return{[ & ] -> decltype(auto) {
|
|
34
34
|
return std::apply(
|
|
35
35
|
callback,
|
|
36
36
|
std::tuple_cat(
|
|
@@ -61,7 +61,7 @@ constexpr auto make_free_function_noexcept =
|
|
|
61
61
|
using callback_type = decltype(callback);
|
|
62
62
|
auto bound_function = util::bind{
|
|
63
63
|
[](callback_type& callback, Lock lock, const v8::FunctionCallbackInfo<v8::Value>& /*info*/) noexcept -> void {
|
|
64
|
-
auto run = util::regular_return{[ & ]
|
|
64
|
+
auto run = util::regular_return{[ & ] -> decltype(auto) {
|
|
65
65
|
return callback(lock);
|
|
66
66
|
}};
|
|
67
67
|
return js::transfer_in_strict<v8::Local<v8::Value>>(run().value_or(std::monostate{}), lock);
|
|
@@ -81,7 +81,7 @@ auto make_callback_storage(const auto& lock, auto function) {
|
|
|
81
81
|
return std::tuple{callback, data};
|
|
82
82
|
} else if constexpr (sizeof(bound_type) == sizeof(void*)) {
|
|
83
83
|
// Trivial function of pointer type. Data() is the function data.
|
|
84
|
-
auto data = [ & ]
|
|
84
|
+
auto data = [ & ] -> auto {
|
|
85
85
|
#if V8_HAS_TAGGED_EXTERNAL
|
|
86
86
|
return v8::External::New(lock.isolate(), std::bit_cast<void*>(bound), 0);
|
|
87
87
|
#else
|
|
@@ -89,7 +89,7 @@ auto make_callback_storage(const auto& lock, auto function) {
|
|
|
89
89
|
#endif
|
|
90
90
|
}();
|
|
91
91
|
const auto callback = v8::FunctionCallback{[](const v8::FunctionCallbackInfo<v8::Value>& info) -> void {
|
|
92
|
-
auto invoke = [ & ]
|
|
92
|
+
auto invoke = [ & ] -> auto {
|
|
93
93
|
#if V8_HAS_TAGGED_EXTERNAL
|
|
94
94
|
// TODO: Use this feature
|
|
95
95
|
return std::bit_cast<bound_type>(info.Data().As<v8::External>()->Value(0));
|
package/support/error.h.cc
CHANGED
|
@@ -17,7 +17,7 @@ auto externalize_caught_error(context_lock_witness lock, v8::Local<v8::Value> va
|
|
|
17
17
|
// Catch `iv8::pending_error` or `js::error`, converting to thrown v8 runtime error.
|
|
18
18
|
[[nodiscard]] auto invoke_internal_error_scope(context_lock_witness lock, auto operation) {
|
|
19
19
|
using result_type = std::invoke_result_t<decltype(operation)>;
|
|
20
|
-
using value_type = type_t<[]
|
|
20
|
+
using value_type = type_t<[] {
|
|
21
21
|
if constexpr (type<result_type> == type<void>) {
|
|
22
22
|
return type<bool>;
|
|
23
23
|
} else {
|
package/transfer/accept.cc
CHANGED
|
@@ -89,7 +89,7 @@ auto accept_v8_value::operator()(date_tag /*tag*/, visit_holder /*visit*/, js_cl
|
|
|
89
89
|
auto accept_v8_value::operator()(error_tag /*tag*/, visit_holder /*visit*/, const js::error_value& subject) const
|
|
90
90
|
-> js::referenceable_value<v8::Local<v8::Object>> {
|
|
91
91
|
auto message = js::transfer_in<v8::Local<v8::String>>(subject.message(), witness());
|
|
92
|
-
auto error = v8::Local<v8::Value>{[ & ]
|
|
92
|
+
auto error = v8::Local<v8::Value>{[ & ] -> v8::Local<v8::Value> {
|
|
93
93
|
switch (subject.name()) {
|
|
94
94
|
// These functions don't need an isolate somehow?
|
|
95
95
|
default:
|
|
@@ -131,7 +131,7 @@ auto accept_v8_value::operator()(array_buffer_tag /*tag*/, visit_holder /*visit*
|
|
|
131
131
|
auto accept_v8_value::operator()(shared_array_buffer_tag /*tag*/, visit_holder /*visit*/, js::shared_array_buffer&& subject) const
|
|
132
132
|
-> js::referenceable_value<v8::Local<v8::SharedArrayBuffer>> {
|
|
133
133
|
auto byte_length = subject.byte_length();
|
|
134
|
-
auto backing_store = [ & ]
|
|
134
|
+
auto backing_store = [ & ] -> auto {
|
|
135
135
|
if (byte_length == 0) {
|
|
136
136
|
// v8 does not call the deleter if `byte_length` is zero. So the heap-allocated shared_ptr
|
|
137
137
|
// trick does not work in that case.
|
package/transfer/accept.h.cc
CHANGED
|
@@ -16,10 +16,10 @@ constexpr auto make_free_function(auto function);
|
|
|
16
16
|
|
|
17
17
|
// Reference acceptor
|
|
18
18
|
struct reaccept_v8_value {
|
|
19
|
-
using reference_type = v8::Local<v8::
|
|
19
|
+
using reference_type = v8::Local<v8::Data>;
|
|
20
20
|
|
|
21
21
|
template <class Type>
|
|
22
|
-
constexpr auto operator()(std::type_identity<v8::Local<Type>> /*type*/, v8::Local<v8::
|
|
22
|
+
constexpr auto operator()(std::type_identity<v8::Local<Type>> /*type*/, v8::Local<v8::Data> subject) const -> v8::Local<Type> {
|
|
23
23
|
return subject.As<Type>();
|
|
24
24
|
}
|
|
25
25
|
};
|
|
@@ -63,6 +63,12 @@ struct accept_v8_primitive {
|
|
|
63
63
|
return (*this)(number_tag_of<double>{}, visit, double{std::forward<decltype(subject)>(subject)});
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
template <class Type>
|
|
67
|
+
auto operator()(number_tag_of<Type> tag, visit_holder visit, Type subject) const -> v8::Local<tag_to_v8<number_tag_of<Type>>> {
|
|
68
|
+
auto value = (*this)(tag, visit, std::int32_t{std::forward<decltype(subject)>(subject)});
|
|
69
|
+
return v8::Local<v8::Int32>{value}.As<tag_to_v8<number_tag_of<Type>>>();
|
|
70
|
+
}
|
|
71
|
+
|
|
66
72
|
template <class Type>
|
|
67
73
|
auto operator()(number_tag_of<Type> tag, visit_holder visit, auto&& subject) const -> v8::Local<tag_to_v8<number_tag_of<Type>>> {
|
|
68
74
|
return (*this)(tag, visit, Type{std::forward<decltype(subject)>(subject)});
|
|
@@ -167,12 +173,10 @@ struct accept_v8_value : accept_v8_primitive {
|
|
|
167
173
|
[](v8::Local<v8::Array> array, auto& self, auto& visit, auto /*&&*/ subject) -> void {
|
|
168
174
|
auto&& range = util::into_range(std::forward<decltype(subject)>(subject));
|
|
169
175
|
for (auto&& [ key, value ] : util::forward_range(std::forward<decltype(range)>(range))) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
);
|
|
175
|
-
unmaybe(result);
|
|
176
|
+
// nb: 'first' must run before 'second'
|
|
177
|
+
auto name = visit.first(std::forward<decltype(key)>(key), self);
|
|
178
|
+
auto item = visit.second(std::forward<decltype(value)>(value), self);
|
|
179
|
+
unmaybe(array->Set(self.context_, name, item));
|
|
176
180
|
}
|
|
177
181
|
},
|
|
178
182
|
};
|
|
@@ -203,8 +207,8 @@ struct accept_v8_value : accept_v8_primitive {
|
|
|
203
207
|
v8::Array::New(self.isolate(), Size),
|
|
204
208
|
std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
|
|
205
209
|
[](v8::Local<v8::Array> array, auto& self, auto& visit, auto /*&&*/ tuple) -> void {
|
|
206
|
-
|
|
207
|
-
(..., [ & ]
|
|
210
|
+
constexpr auto [... indices ] = util::sequence<Size>;
|
|
211
|
+
(..., [ & ] -> void {
|
|
208
212
|
auto element = visit(indices, std::forward<decltype(tuple)>(tuple), self);
|
|
209
213
|
unmaybe(array->Set(self.context_, indices, element));
|
|
210
214
|
}());
|
|
@@ -221,12 +225,10 @@ struct accept_v8_value : accept_v8_primitive {
|
|
|
221
225
|
[](v8::Local<v8::Object> object, auto& self, auto& visit, auto /*&&*/ subject) -> void {
|
|
222
226
|
auto&& range = util::into_range(std::forward<decltype(subject)>(subject));
|
|
223
227
|
for (auto&& [ key, value ] : util::forward_range(std::forward<decltype(range)>(range))) {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
);
|
|
229
|
-
unmaybe(result);
|
|
228
|
+
// nb: 'first' must run before 'second'
|
|
229
|
+
auto name = visit.first(std::forward<decltype(key)>(key), self);
|
|
230
|
+
auto item = visit.second(std::forward<decltype(value)>(value), self);
|
|
231
|
+
unmaybe(object->Set(self.context_, name, item));
|
|
230
232
|
}
|
|
231
233
|
},
|
|
232
234
|
};
|
|
@@ -281,8 +283,8 @@ struct accept_v8_value : accept_v8_primitive {
|
|
|
281
283
|
|
|
282
284
|
template <std::size_t Size>
|
|
283
285
|
auto accept_entry_pair_struct(this const auto& self, auto& visit, v8::Local<v8::Object> target, auto&& subject) -> void {
|
|
284
|
-
|
|
285
|
-
(..., [ & ]
|
|
286
|
+
constexpr auto [... indices ] = util::sequence<Size>;
|
|
287
|
+
(..., [ & ] -> void {
|
|
286
288
|
auto accept_entry = accept_entry_pair<decltype(self), decltype(self)>{self};
|
|
287
289
|
auto entry = visit(std::integral_constant<std::size_t, indices>{}, std::forward<decltype(subject)>(subject), accept_entry);
|
|
288
290
|
unmaybe(target->Set(self.context_, entry.first, entry.second));
|
|
@@ -293,44 +295,56 @@ struct accept_v8_value : accept_v8_primitive {
|
|
|
293
295
|
v8::Local<v8::Context> context_;
|
|
294
296
|
};
|
|
295
297
|
|
|
296
|
-
//
|
|
298
|
+
// Lock delegate for `accept_v8_value_with`. In the `context_lock_witness` case, `accept_v8_value`
|
|
299
|
+
// holds that lock by type. If the lock is more specialized we need to hold another reference.
|
|
297
300
|
template <class Lock>
|
|
298
|
-
struct
|
|
301
|
+
struct accept_v8_value_lock_delegate;
|
|
299
302
|
|
|
300
303
|
template <>
|
|
301
|
-
struct
|
|
304
|
+
struct accept_v8_value_lock_delegate<context_lock_witness> : accept_v8_value {
|
|
302
305
|
using accept_v8_value::accept_v8_value;
|
|
303
|
-
using accept_v8_value::operator();
|
|
304
|
-
using accept_v8_value::witness;
|
|
305
|
-
|
|
306
|
-
// function instantiation
|
|
307
|
-
auto operator()(function_prototype_tag /*tag*/, visit_holder /*visit*/, auto subject) const -> v8::Local<iv8::Function> {
|
|
308
|
-
auto [ function, length ] = make_free_function<context_lock_witness>(std::move(subject).callback);
|
|
309
|
-
auto [ callback, data ] = make_callback_storage(witness(), std::move(function));
|
|
310
|
-
return unmaybe(v8::Function::New(witness().context(), callback, data, length, v8::ConstructorBehavior::kThrow).template As<iv8::Function>());
|
|
311
|
-
}
|
|
312
306
|
};
|
|
313
307
|
|
|
314
308
|
template <class Lock>
|
|
315
|
-
struct
|
|
309
|
+
struct accept_v8_value_lock_delegate : accept_v8_value {
|
|
316
310
|
public:
|
|
317
|
-
|
|
311
|
+
accept_v8_value_lock_delegate(auto* transfer, const Lock& lock) :
|
|
318
312
|
accept_v8_value{transfer, lock},
|
|
319
313
|
lock_{lock} {}
|
|
320
314
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
// function instantiation
|
|
324
|
-
auto operator()(function_prototype_tag /*tag*/, visit_holder /*visit*/, auto subject) const -> v8::Local<iv8::Function> {
|
|
325
|
-
auto [ function, length ] = make_free_function<Lock>(std::move(subject).callback);
|
|
326
|
-
auto [ callback, data ] = make_callback_storage(lock_.get(), std::move(function));
|
|
327
|
-
return v8::Function::New(lock_.get().context(), callback, data, length, v8::ConstructorBehavior::kThrow);
|
|
328
|
-
}
|
|
315
|
+
[[nodiscard]] auto witness() const -> const Lock& { return lock_; }
|
|
329
316
|
|
|
330
317
|
private:
|
|
331
318
|
std::reference_wrapper<const Lock> lock_;
|
|
332
319
|
};
|
|
333
320
|
|
|
321
|
+
// `accept_v8_value` subclass, implementing specialized acceptor with lock type.
|
|
322
|
+
template <class Lock>
|
|
323
|
+
struct accept_v8_value_with : accept_v8_value_lock_delegate<Lock> {
|
|
324
|
+
using accept_v8_value_lock_delegate<Lock>::accept_v8_value_lock_delegate;
|
|
325
|
+
using accept_v8_value_lock_delegate<Lock>::operator();
|
|
326
|
+
using accept_v8_value_lock_delegate<Lock>::witness;
|
|
327
|
+
|
|
328
|
+
// object template instantiation
|
|
329
|
+
auto operator()(object_prototype_tag /*tag*/, visit_holder /*visit*/, v8::Local<v8::ObjectTemplate> subject) const -> v8::Local<v8::Object> {
|
|
330
|
+
return unmaybe(subject->NewInstance(witness().context()));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// function instantiation (from template)
|
|
334
|
+
auto operator()(function_prototype_tag /*tag*/, visit_holder /*visit*/, v8::Local<v8::FunctionTemplate> subject) const -> v8::Local<iv8::Function> {
|
|
335
|
+
auto fn = unmaybe(subject->GetFunction(witness().context()));
|
|
336
|
+
return v8::Local<v8::Function>{fn}.As<iv8::Function>();
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// function instantiation (from native type)
|
|
340
|
+
auto operator()(function_prototype_tag /*tag*/, visit_holder /*visit*/, auto subject) const -> v8::Local<iv8::Function> {
|
|
341
|
+
auto [ function, length ] = make_free_function<context_lock_witness>(std::move(subject).callback);
|
|
342
|
+
auto [ callback, data ] = make_callback_storage(witness(), std::move(function));
|
|
343
|
+
auto fn = unmaybe(v8::Function::New(witness().context(), callback, data, length, v8::ConstructorBehavior::kThrow));
|
|
344
|
+
return v8::Local<v8::Function>{fn}.As<iv8::Function>();
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
|
|
334
348
|
// Acceptor with template environment
|
|
335
349
|
template <class Meta, class Lock>
|
|
336
350
|
struct accept_v8_template : accept_v8_primitive {
|
|
@@ -339,6 +353,36 @@ struct accept_v8_template : accept_v8_primitive {
|
|
|
339
353
|
accept_v8_primitive{transfer, lock},
|
|
340
354
|
lock_{lock} {}
|
|
341
355
|
|
|
356
|
+
// cast primitive to prototype
|
|
357
|
+
template <std::convertible_to<primitive_tag> Tag>
|
|
358
|
+
auto operator()(Tag tag, auto& visit, auto&& subject) const -> v8::Local<v8::Template>
|
|
359
|
+
// refuse on bigint, which requires a context for some reason.
|
|
360
|
+
requires(!std::convertible_to<Tag, bigint_tag>) {
|
|
361
|
+
const accept_v8_primitive& accept = *this;
|
|
362
|
+
auto result = accept(tag, visit, std::forward<decltype(subject)>(subject));
|
|
363
|
+
auto value = v8::Local<v8::Value>{dispatch_referenceable(result)};
|
|
364
|
+
// nb: We are smuggling a `v8::Primitive` as a `v8::Template`
|
|
365
|
+
return std::bit_cast<v8::Local<v8::Template>>(value);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// object
|
|
369
|
+
auto operator()(this const auto& self, dictionary_tag /*tag*/, auto& visit, auto&& subject)
|
|
370
|
+
-> js::deferred_receiver<v8::Local<v8::ObjectTemplate>, decltype(self), decltype(visit), decltype(subject)> {
|
|
371
|
+
return {
|
|
372
|
+
v8::ObjectTemplate::New(self.isolate()),
|
|
373
|
+
std::forward_as_tuple(self, visit, std::forward<decltype(subject)>(subject)),
|
|
374
|
+
[](v8::Local<v8::ObjectTemplate> object, auto& self, auto& visit, auto /*&&*/ subject) -> void {
|
|
375
|
+
auto&& range = util::into_range(std::forward<decltype(subject)>(subject));
|
|
376
|
+
for (auto&& [ key, value ] : util::forward_range(std::forward<decltype(range)>(range))) {
|
|
377
|
+
// nb: 'first' must run before 'second'
|
|
378
|
+
auto name = v8::Local<v8::Template>{visit.first(std::forward<decltype(key)>(key), self)};
|
|
379
|
+
auto item = visit.second(std::forward<decltype(value)>(value), self);
|
|
380
|
+
object->Set(name.As<v8::Name>(), item);
|
|
381
|
+
}
|
|
382
|
+
},
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
|
|
342
386
|
// function template
|
|
343
387
|
auto operator()(function_prototype_tag /*tag*/, visit_holder /*visit*/, auto subject) const -> v8::Local<v8::FunctionTemplate> {
|
|
344
388
|
auto [ function, length ] = make_free_function<Lock>(std::move(subject).callback);
|
package/transfer/visit.cc
CHANGED
|
@@ -25,7 +25,7 @@ struct visit_property_name {
|
|
|
25
25
|
|
|
26
26
|
template <class Accept>
|
|
27
27
|
auto operator()(v8::Local<v8::Primitive> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
28
|
-
return visit_.get().lookup_or_visit(subject, [ & ]
|
|
28
|
+
return visit_.get().lookup_or_visit(subject, [ & ] -> accept_target_t<Accept> {
|
|
29
29
|
auto accept_as = [ & ]<class Tag>(Tag tag) -> auto {
|
|
30
30
|
auto value = value_of{witness(), subject.As<tag_to_v8<Tag>>()};
|
|
31
31
|
return accept(tag, *this, value);
|
|
@@ -80,7 +80,7 @@ struct visit_cached_immediate : Visit {
|
|
|
80
80
|
auto operator()(auto subject, const Accept& accept) -> accept_target_t<Accept>
|
|
81
81
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124954
|
|
82
82
|
requires requires { this->immediate(subject, accept); } {
|
|
83
|
-
return lookup_or_visit(subject, [ & ]
|
|
83
|
+
return lookup_or_visit(subject, [ & ] -> accept_target_t<Accept> {
|
|
84
84
|
return immediate(subject, accept);
|
|
85
85
|
});
|
|
86
86
|
}
|
|
@@ -276,7 +276,7 @@ struct visit_value : visit_flat_value<Target> {
|
|
|
276
276
|
auto operator()(v8::Local<v8::Value> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
277
277
|
|
|
278
278
|
// Check the reference map, and check type
|
|
279
|
-
return lookup_or_visit(subject, [ & ]
|
|
279
|
+
return lookup_or_visit(subject, [ & ] -> accept_target_t<Accept> {
|
|
280
280
|
return util::template_traverse(
|
|
281
281
|
accept_tags_of_v<Accept>,
|
|
282
282
|
util::overloaded{
|
|
@@ -313,7 +313,7 @@ struct visit_value : visit_flat_value<Target> {
|
|
|
313
313
|
[](auto /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
314
314
|
|
|
315
315
|
// Slow path
|
|
316
|
-
[ & ]
|
|
316
|
+
[ & ] -> accept_target_t<Accept> {
|
|
317
317
|
if (subject->IsObject()) {
|
|
318
318
|
return immediate(subject.As<v8::Object>(), accept);
|
|
319
319
|
} else {
|
|
@@ -327,7 +327,7 @@ struct visit_value : visit_flat_value<Target> {
|
|
|
327
327
|
|
|
328
328
|
template <class Accept>
|
|
329
329
|
auto operator()(v8::Local<iv8::DataBlock> subject, const Accept& accept) -> accept_target_t<Accept> {
|
|
330
|
-
return lookup_or_visit(subject, [ & ]
|
|
330
|
+
return lookup_or_visit(subject, [ & ] -> accept_target_t<Accept> {
|
|
331
331
|
return util::template_traverse(
|
|
332
332
|
accept_tags_of_v<Accept>,
|
|
333
333
|
util::overloaded{
|
|
@@ -337,7 +337,7 @@ struct visit_value : visit_flat_value<Target> {
|
|
|
337
337
|
[ & ](shared_array_buffer_tag /*tag*/, auto next) -> accept_target_t<Accept> { return next(); },
|
|
338
338
|
|
|
339
339
|
// Slow path
|
|
340
|
-
[ & ]
|
|
340
|
+
[ & ] -> accept_target_t<Accept> {
|
|
341
341
|
return immediate(subject, accept);
|
|
342
342
|
}
|
|
343
343
|
}
|
|
@@ -471,6 +471,17 @@ struct visit_v8_value_of {
|
|
|
471
471
|
struct visit_template {
|
|
472
472
|
explicit visit_template(auto* /*transfer*/) {}
|
|
473
473
|
|
|
474
|
+
template <class Accept>
|
|
475
|
+
auto operator()(v8::Local<v8::Template> subject, const Accept& accept) const -> accept_target_t<Accept> {
|
|
476
|
+
if (subject->IsFunctionTemplate()) {
|
|
477
|
+
return (*this)(subject.As<v8::FunctionTemplate>(), accept);
|
|
478
|
+
} else if (subject->IsObjectTemplate()) {
|
|
479
|
+
return (*this)(subject.As<v8::ObjectTemplate>(), accept);
|
|
480
|
+
} else {
|
|
481
|
+
return accept_target_t<Accept>{subject};
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
|
|
474
485
|
template <class Accept>
|
|
475
486
|
auto operator()(v8::Local<v8::FunctionTemplate> subject, const Accept& accept) const -> accept_target_t<Accept> {
|
|
476
487
|
return accept(function_prototype_tag{}, *this, subject);
|
package/value/function.cc
CHANGED
|
@@ -10,11 +10,12 @@ namespace js::iv8 {
|
|
|
10
10
|
|
|
11
11
|
template <class Result>
|
|
12
12
|
auto Function::apply(context_lock_witness lock, auto&& args) -> Result {
|
|
13
|
-
auto result = [ & ]
|
|
13
|
+
auto result = [ & ] {
|
|
14
14
|
using args_type = std::vector<v8::Local<v8::Value>>;
|
|
15
15
|
auto handle_scope = v8::EscapableHandleScope{lock.isolate()};
|
|
16
16
|
auto undefined = js::transfer_in_strict<v8::Local<v8::Value>>(std::monostate{}, lock);
|
|
17
17
|
auto argv = js::transfer_in_strict<args_type>(std::forward<decltype(args)>(args), lock);
|
|
18
|
+
auto allow_js = v8::Isolate::AllowJavascriptExecutionScope{lock.isolate()};
|
|
18
19
|
auto result = unmaybe(v8::Function::Call(lock.context(), undefined, argv.size(), argv.data()));
|
|
19
20
|
return handle_scope.Escape(result);
|
|
20
21
|
}();
|
|
@@ -23,7 +24,7 @@ auto Function::apply(context_lock_witness lock, auto&& args) -> Result {
|
|
|
23
24
|
|
|
24
25
|
template <class Result>
|
|
25
26
|
auto Function::call(context_lock_witness lock, auto&&... args) -> Result {
|
|
26
|
-
auto result = [ & ]
|
|
27
|
+
auto result = [ & ] {
|
|
27
28
|
using args_type = std::array<v8::Local<v8::Value>, sizeof...(args) + 1>;
|
|
28
29
|
auto handle_scope = v8::EscapableHandleScope{lock.isolate()};
|
|
29
30
|
auto argv = js::transfer_in_strict<args_type>(
|
|
@@ -33,6 +34,7 @@ auto Function::call(context_lock_witness lock, auto&&... args) -> Result {
|
|
|
33
34
|
),
|
|
34
35
|
lock
|
|
35
36
|
);
|
|
37
|
+
auto allow_js = v8::Isolate::AllowJavascriptExecutionScope{lock.isolate()};
|
|
36
38
|
return handle_scope.Escape(unmaybe(v8::Function::Call(lock.context(), argv[ 0 ], argv.size() - 1, argv.data() + 1)));
|
|
37
39
|
}();
|
|
38
40
|
return js::transfer_out<Result>(result, lock);
|