LibWeb: Start implementing render-blocking mechanism from HTML spec

This change implements enough spec steps to block rendering until
execution of sync scripts inserted from HTML parser is complete.
This commit is contained in:
Aliaksandr Kalenik 2025-02-04 19:09:14 +01:00 committed by Andreas Kling
commit da579e11b0
Notes: github-actions[bot] 2025-02-05 17:29:43 +00:00
7 changed files with 99 additions and 3 deletions

View file

@ -270,7 +270,10 @@ void EventLoop::update_the_rendering()
if (!document.is_fully_active())
return false;
// FIXME: doc is render-blocked;
// doc is render-blocked;
if (document.is_render_blocked()) {
return false;
}
// doc's visibility state is "hidden";
if (document.hidden())

View file

@ -71,6 +71,37 @@ 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-dir
StringView HTMLElement::dir() const
{

View file

@ -151,6 +151,15 @@ 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; }
private:
virtual bool is_html_element() const final { return true; }

View file

@ -97,7 +97,8 @@ void HTMLScriptElement::execute_script()
return;
}
// FIXME: 3. Unblock rendering on el.
// 3. Unblock rendering on el.
unblock_rendering();
// 3. If el's result is null, then fire an event named error at el, and return.
if (m_result.has<ResultState::Null>()) {
@ -393,7 +394,10 @@ void HTMLScriptElement::prepare_script()
return;
}
// FIXME: 7. If el is potentially render-blocking, then block rendering on el.
// 7. If el is potentially render-blocking, then block rendering on el.
if (is_potentially_render_blocking()) {
block_rendering();
}
// 8. Set el's delaying the load event to true.
begin_delaying_document_load_event(*m_preparation_time_document);
@ -664,4 +668,11 @@ WebIDL::ExceptionOr<void> HTMLScriptElement::cloned(Node& copy, bool subtree) co
return {};
}
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#implicitly-potentially-render-blocking
bool HTMLScriptElement::is_implicitly_potentially_render_blocking() const
{
// A script element el is implicitly potentially render-blocking if el's type is "classic", el is parser-inserted, and el does not have an async or defer attribute.
return m_script_type == ScriptType::Classic && is_parser_inserted() && !has_attribute(AttributeNames::async) && !has_attribute(AttributeNames::defer);
}
}

View file

@ -65,6 +65,10 @@ public:
virtual WebIDL::ExceptionOr<void> cloned(Node&, bool) const override;
protected:
// https://html.spec.whatwg.org/multipage/urls-and-fetching.html#implicitly-potentially-render-blocking
virtual bool is_implicitly_potentially_render_blocking() const override;
private:
HTMLScriptElement(DOM::Document&, DOM::QualifiedName);