LibWeb: Add loading event to style element

This commit is contained in:
Lorenz A
2025-10-15 05:52:11 +02:00
committed by Andreas Kling
parent ce2c4a3417
commit 7260159b8f
Notes: github-actions[bot] 2025-11-30 18:23:06 +00:00
7 changed files with 87 additions and 40 deletions

View File

@@ -4333,4 +4333,35 @@ GC::Ptr<Element const> Element::element_to_inherit_style_from(Optional<CSS::Pseu
return parent_or_shadow_host_element();
}
// https://html.spec.whatwg.org/multipage/dom.html#block-rendering
void Element::block_rendering()
{
// 1. Let document be el's node document.
auto& document = this->document();
// 2. If document allows adding render-blocking elements, then append el to document's render-blocking element set.
if (document.allows_adding_render_blocking_elements()) {
document.add_render_blocking_element(*this);
}
}
// https://html.spec.whatwg.org/multipage/dom.html#unblock-rendering
void Element::unblock_rendering()
{
// 1. Let document be el's node document.
auto& document = this->document();
// 2. Remove el from document's render-blocking element set.
document.remove_render_blocking_element(*this);
}
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#potentially-render-blocking
bool Element::is_potentially_render_blocking()
{
// An element is potentially render-blocking if
// FIXME: its blocking tokens set contains "render",
// or if it is implicitly potentially render-blocking, which will be defined at the individual elements.
return is_implicitly_potentially_render_blocking();
}
}

View File

@@ -511,6 +511,15 @@ public:
GC::Ref<CSS::StylePropertyMapReadOnly> computed_style_map();
// https://html.spec.whatwg.org/multipage/dom.html#block-rendering
void block_rendering();
// https://html.spec.whatwg.org/multipage/dom.html#unblock-rendering
void unblock_rendering();
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#potentially-render-blocking
bool is_potentially_render_blocking();
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#implicitly-potentially-render-blocking
virtual bool is_implicitly_potentially_render_blocking() const { return false; }
protected:
Element(Document&, DOM::QualifiedName);
virtual void initialize(JS::Realm&) override;

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2023, Preston Taylor <PrestonLeeTaylor@proton.me>
* Copyright (c) 2025, Lorenz Ackermann <me@lorenzackermann.xyz>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@@ -8,6 +9,7 @@
#include <LibWeb/CSS/StyleComputer.h>
#include <LibWeb/ContentSecurityPolicy/BlockingAlgorithms.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Event.h>
#include <LibWeb/DOM/ShadowRoot.h>
#include <LibWeb/DOM/StyleElementUtils.h>
#include <LibWeb/Infra/Strings.h>
@@ -97,6 +99,38 @@ void StyleElementUtils::update_a_style_block(DOM::Element& style_element)
style_element.document().script_blocking_style_sheet_set().set(style_element);
// FIXME: 8. If element's media attribute's value matches the environment and element is potentially render-blocking, then block rendering on element.
// https://html.spec.whatwg.org/multipage/semantics.html#the-style-element:critical-subresources
auto attempts_to_fetch_subresources_finished = [](GC::Ptr<CSS::CSSStyleSheet> style_sheet) {
// 1. Let element be the style element associated with the style sheet in question.
auto& element = *style_sheet->owner_node();
// 2. Let success be true.
auto success = true;
// FIXME: 3. If the attempts to obtain any of the style sheet's critical subresources failed for any reason
// (e.g., DNS error, HTTP 404 response, a connection being prematurely closed, unsupported Content-Type), set success to false.
// Note: that content-specific errors, e.g., CSS parse errors or PNG decoding errors, do not affect success.
// 4. Queue an element task on the networking task source given element and the following steps:
element.queue_an_element_task(HTML::Task::Source::UserInteraction, [&element, success] {
// 1. If success is true, fire an event named load at element.
// AD-HOC: these should call fire an event this is not implemented anywhere so we dispatch ourself
if (success)
element.dispatch_event(DOM::Event::create(element.realm(), HTML::EventNames::load));
// 2. Otherwise, fire an event named error at element.
else
element.dispatch_event(DOM::Event::create(element.realm(), HTML::EventNames::error));
// 3. If element contributes a script-blocking style sheet:
if (element.contributes_a_script_blocking_style_sheet()) {
// 1. Assert: element's node document's script-blocking style sheet set contains element.
VERIFY(element.document().script_blocking_style_sheet_set().contains(element));
// 2. Remove element from its node document's script-blocking style sheet set.
element.document().script_blocking_style_sheet_set().remove(element);
}
// 4. Unblock rendering on element.
element.unblock_rendering();
});
};
// FIXME: The element must delay the load event of the element's node document until all the attempts to obtain the style sheet's critical subresources, if any, are complete.
attempts_to_fetch_subresources_finished(m_associated_css_style_sheet);
}
void StyleElementUtils::visit_edges(JS::Cell::Visitor& visitor)

View File

@@ -77,37 +77,6 @@ void HTMLElement::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_popover_close_watcher);
}
// https://html.spec.whatwg.org/multipage/dom.html#block-rendering
void HTMLElement::block_rendering()
{
// 1. Let document be el's node document.
auto& document = this->document();
// 2. If document allows adding render-blocking elements, then append el to document's render-blocking element set.
if (document.allows_adding_render_blocking_elements()) {
document.add_render_blocking_element(*this);
}
}
// https://html.spec.whatwg.org/multipage/dom.html#unblock-rendering
void HTMLElement::unblock_rendering()
{
// 1. Let document be el's node document.
auto& document = this->document();
// 2. Remove el from document's render-blocking element set.
document.remove_render_blocking_element(*this);
}
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#potentially-render-blocking
bool HTMLElement::is_potentially_render_blocking()
{
// An element is potentially render-blocking if
// FIXME: its blocking tokens set contains "render",
// or if it is implicitly potentially render-blocking, which will be defined at the individual elements.
return is_implicitly_potentially_render_blocking();
}
// https://html.spec.whatwg.org/multipage/dom.html#dom-translate
bool HTMLElement::translate() const
{

View File

@@ -207,15 +207,6 @@ protected:
virtual void visit_edges(Cell::Visitor&) override;
// https://html.spec.whatwg.org/multipage/dom.html#block-rendering
void block_rendering();
// https://html.spec.whatwg.org/multipage/dom.html#unblock-rendering
void unblock_rendering();
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#potentially-render-blocking
bool is_potentially_render_blocking();
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#implicitly-potentially-render-blocking
virtual bool is_implicitly_potentially_render_blocking() const { return false; }
void set_inert(bool inert) { m_inert = inert; }
void set_subtree_inertness(bool is_inert);

View File

@@ -0,0 +1 @@
Onload event fired

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<script src="../include.js"></script>
<script>
asyncTest(done => {
const styleE = document.createElement('style');
styleE.onload = () => {
println("Onload event fired");
done();
}
document.head.append(styleE);
});
</script>