summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibWeb/HTML/Parser
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-09-20 17:06:10 +0200
committerAndreas Kling <kling@serenityos.org>2021-09-20 17:22:25 +0200
commitc34da16089267bf3a22cf3e88a87347cdfc142ff (patch)
tree40723b22fb62c08e2a249f489f4a9acfce280d3c /Userland/Libraries/LibWeb/HTML/Parser
parente11ae33c664a3873ca3383ac4582f2ed9ccc5f1e (diff)
downloadserenity-c34da16089267bf3a22cf3e88a87347cdfc142ff.zip
LibWeb: Make <script src> loads partially async (by following the spec)
Instead of firing up a network request and synchronously blocking for it to finish via a nested event loop, we now start an asynchronous request when encountering <script src>. Once the script load finishes (or fails), it gets executed at one of the synchronization points in the HTML parser. This solves some long-standing issues with random unexpected events getting dispatched in the middle of parsing.
Diffstat (limited to 'Userland/Libraries/LibWeb/HTML/Parser')
-rw-r--r--Userland/Libraries/LibWeb/HTML/Parser/HTMLDocumentParser.cpp15
1 files changed, 8 insertions, 7 deletions
diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLDocumentParser.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLDocumentParser.cpp
index 88e4493257..6503eaaf49 100644
--- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLDocumentParser.cpp
+++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLDocumentParser.cpp
@@ -184,8 +184,11 @@ void HTMLDocumentParser::run(const AK::URL& url)
m_stack_of_open_elements.pop();
auto scripts_to_execute_when_parsing_has_finished = m_document->take_scripts_to_execute_when_parsing_has_finished({});
+
for (auto& script : scripts_to_execute_when_parsing_has_finished) {
- // FIXME: Spin the event loop until the script is ready to be parser executed and there's no style sheets blocking scripts.
+ main_thread_event_loop().spin_until([&] {
+ return script.is_ready_to_be_parser_executed() && !document().has_a_style_sheet_that_is_blocking_scripts();
+ });
script.execute_script();
}
@@ -193,12 +196,10 @@ void HTMLDocumentParser::run(const AK::URL& url)
content_loaded_event->set_bubbles(true);
m_document->dispatch_event(content_loaded_event);
- // FIXME: The document parser shouldn't execute these, it should just spin the event loop until the list becomes empty.
- // FIXME: Once the set has been added, also spin the event loop until the set becomes empty.
- auto scripts_to_execute_as_soon_as_possible = m_document->take_scripts_to_execute_as_soon_as_possible({});
- for (auto& script : scripts_to_execute_as_soon_as_possible) {
- script.execute_script();
- }
+ // 7. Spin the event loop until the set of scripts that will execute as soon as possible and the list of scripts that will execute in order as soon as possible are empty.
+ main_thread_event_loop().spin_until([&] {
+ return m_document->scripts_to_execute_as_soon_as_possible().is_empty();
+ });
// FIXME: Spin the event loop until there is nothing that delays the load event in the Document.