LibJS+LibWeb: Parse modules off the main thread

Use the parse_off_thread() helper to submit
parse_program(ProgramType::Module) to the ThreadPool for parsing
on a worker thread. Bounce back to the main thread to compile and
deliver the result via deferred_invoke.

Falls back to synchronous parsing when the Rust pipeline is
unavailable (LIBJS_CPP=1 or LIBJS_COMPARE_PIPELINES=1).
This commit is contained in:
Andreas Kling
2026-02-27 23:44:53 +01:00
committed by Andreas Kling
parent 3f4d3d6108
commit 4c1e2aeb54
Notes: github-actions[bot] 2026-03-06 12:07:23 +00:00
3 changed files with 28 additions and 7 deletions

View File

@@ -775,8 +775,32 @@ void fetch_single_module_script(JS::Realm& realm,
// 7. If mimeType is a JavaScript MIME type and moduleType is "javascript", then set moduleScript to the result of creating a JavaScript module script given sourceText, moduleMapRealm, response's URL, and options.
// FIXME: Pass options.
if (mime_type.has_value() && mime_type->is_javascript() && module_type == "javascript")
if (mime_type.has_value() && mime_type->is_javascript() && module_type == "javascript") {
// If the Rust pipeline is available, parse off the main thread.
if (JS::RustIntegration::rust_pipeline_available()) {
auto on_complete_root = GC::make_root(on_complete);
auto realm_root = GC::make_root(&module_map_realm);
auto url_string = url.to_byte_string();
auto response_url = response->url().value_or({});
auto module_type_string = module_type.to_byte_string();
auto source_code = JS::SourceCode::create(
String::from_utf8(url_string.view()).release_value_but_fixme_should_propagate_errors(),
Utf16String::from_utf8(source_text));
parse_off_thread(move(source_code), JS::RustIntegration::ProgramType::Module, 0,
[url = move(url), url_string = move(url_string), response_url = move(response_url),
module_type_string = move(module_type_string),
on_complete_root = move(on_complete_root),
realm_root = move(realm_root)](auto* parsed, auto source_code) mutable {
auto module_script = JavaScriptModuleScript::create_from_pre_parsed(url_string, move(source_code), *realm_root, move(response_url), parsed).release_value_but_fixme_should_propagate_errors();
auto& mm = module_map_of_realm(*realm_root);
mm.set(url, module_type_string, { ModuleMap::EntryType::ModuleScript, module_script });
on_complete_root->function()(module_script);
});
return;
}
module_script = JavaScriptModuleScript::create(url.to_byte_string(), source_text, module_map_realm, response->url().value_or({})).release_value_but_fixme_should_propagate_errors();
}
// FIXME: 8. If the MIME type essence of mimeType is "text/css" and moduleType is "css", then set moduleScript to the result of creating a CSS module script given sourceText and settingsObject.
// FIXME: 9. If mimeType is a JSON MIME type and moduleType is "json", then set moduleScript to the result of creating a JSON module script given sourceText and settingsObject.

View File

@@ -71,17 +71,14 @@ WebIDL::ExceptionOr<GC::Ptr<JavaScriptModuleScript>> JavaScriptModuleScript::cre
return script;
}
WebIDL::ExceptionOr<GC::Ptr<JavaScriptModuleScript>> JavaScriptModuleScript::create_from_pre_parsed(ByteString const& filename, StringView source, JS::Realm& realm, URL::URL base_url, RustParsedProgram* parsed)
WebIDL::ExceptionOr<GC::Ptr<JavaScriptModuleScript>> JavaScriptModuleScript::create_from_pre_parsed(ByteString const& filename, NonnullRefPtr<JS::SourceCode const> source_code, JS::Realm& realm, URL::URL base_url, RustParsedProgram* parsed)
{
if (HTML::is_scripting_disabled(realm))
source = ""sv;
auto script = realm.create<JavaScriptModuleScript>(move(base_url), filename, realm);
script->set_parse_error(JS::js_null());
script->set_error_to_rethrow(JS::js_null());
auto result = JS::SourceTextModule::parse_from_pre_parsed(parsed, source, realm, filename.view(), script);
auto result = JS::SourceTextModule::parse_from_pre_parsed(parsed, move(source_code), realm, script);
if (result.is_error()) {
auto& parse_error = result.error().first();

View File

@@ -36,7 +36,7 @@ public:
virtual ~JavaScriptModuleScript() override;
static WebIDL::ExceptionOr<GC::Ptr<JavaScriptModuleScript>> create(ByteString const& filename, StringView source, JS::Realm&, URL::URL base_url);
static WebIDL::ExceptionOr<GC::Ptr<JavaScriptModuleScript>> create_from_pre_parsed(ByteString const& filename, StringView source, JS::Realm&, URL::URL base_url, RustParsedProgram* parsed);
static WebIDL::ExceptionOr<GC::Ptr<JavaScriptModuleScript>> create_from_pre_parsed(ByteString const& filename, NonnullRefPtr<JS::SourceCode const> source_code, JS::Realm&, URL::URL base_url, RustParsedProgram* parsed);
enum class PreventErrorReporting {
Yes,