From dbba0a520fa16e7b2e9ad7742bf0dc7e24a9c241 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 26 Sep 2021 01:03:42 +0200 Subject: [PATCH] LibWeb: Allow HTML parser to delay delivery of the document "load" event We will now spin in "the end" until there are no more "things delaying the load event". Of course, nothing actually uses this yet, and there are a lot of things that need to. --- Userland/Libraries/LibWeb/CMakeLists.txt | 1 + Userland/Libraries/LibWeb/DOM/Document.h | 10 +++++++ .../LibWeb/DOM/DocumentLoadEventDelayer.cpp | 23 ++++++++++++++++ .../LibWeb/DOM/DocumentLoadEventDelayer.h | 27 +++++++++++++++++++ Userland/Libraries/LibWeb/Forward.h | 1 + .../LibWeb/HTML/Parser/HTMLParser.cpp | 6 ++++- 6 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.cpp create mode 100644 Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.h diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index fe96024545..f60e97d754 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -48,6 +48,7 @@ set(SOURCES DOM/DOMImplementation.cpp DOM/Document.cpp DOM/DocumentFragment.cpp + DOM/DocumentLoadEventDelayer.cpp DOM/DocumentType.cpp DOM/Element.cpp DOM/ElementFactory.cpp diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 4b9573c569..83977757d8 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -285,6 +285,14 @@ public: Bindings::LocationObject* location(); + size_t number_of_things_delaying_the_load_event() { return m_number_of_things_delaying_the_load_event; } + void increment_number_of_things_delaying_the_load_event(Badge) { ++m_number_of_things_delaying_the_load_event; } + void decrement_number_of_things_delaying_the_load_event(Badge) + { + VERIFY(m_number_of_things_delaying_the_load_event); + --m_number_of_things_delaying_the_load_event; + } + private: explicit Document(const AK::URL&); @@ -367,6 +375,8 @@ private: u32 m_script_blocking_style_sheet_counter { 0 }; NonnullRefPtr m_history; + + size_t m_number_of_things_delaying_the_load_event { 0 }; }; } diff --git a/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.cpp b/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.cpp new file mode 100644 index 0000000000..60043ea00c --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace Web::DOM { + +DocumentLoadEventDelayer::DocumentLoadEventDelayer(Document& document) + : m_document(document) +{ + m_document->increment_number_of_things_delaying_the_load_event({}); +} + +DocumentLoadEventDelayer::~DocumentLoadEventDelayer() +{ + m_document->decrement_number_of_things_delaying_the_load_event({}); +} + +} diff --git a/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.h b/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.h new file mode 100644 index 0000000000..ac8a17294f --- /dev/null +++ b/Userland/Libraries/LibWeb/DOM/DocumentLoadEventDelayer.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace Web::DOM { + +class DocumentLoadEventDelayer { + AK_MAKE_NONMOVABLE(DocumentLoadEventDelayer); + AK_MAKE_NONCOPYABLE(DocumentLoadEventDelayer); + +public: + explicit DocumentLoadEventDelayer(Document&); + ~DocumentLoadEventDelayer(); + +private: + NonnullRefPtr m_document; +}; + +} diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index f8c3a2d750..bae3610e66 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -64,6 +64,7 @@ class CharacterData; class Comment; class Document; class DocumentFragment; +class DocumentLoadEventDelayer; class DocumentType; class DOMException; class DOMImplementation; diff --git a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp index c3d222d851..74508b327a 100644 --- a/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp +++ b/Userland/Libraries/LibWeb/HTML/Parser/HTMLParser.cpp @@ -231,7 +231,11 @@ void HTMLParser::the_end() return m_document->scripts_to_execute_as_soon_as_possible().is_empty(); }); - // FIXME: 8. Spin the event loop until there is nothing that delays the load event in the Document. + // 8. Spin the event loop until there is nothing that delays the load event in the Document. + // FIXME: Track down all the things that are supposed to delay the load event. + main_thread_event_loop().spin_until([&] { + return m_document->number_of_things_delaying_the_load_event() == 0; + }); // 9. Queue a global task on the DOM manipulation task source given the Document's relevant global object to run the following steps: queue_global_task(HTML::Task::Source::DOMManipulation, *m_document, [document = m_document]() mutable {