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 {