mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-13 03:29:49 +00:00
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:
parent
75168fa4d6
commit
da579e11b0
Notes:
github-actions[bot]
2025-02-05 17:29:43 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: da579e11b0
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3455
7 changed files with 99 additions and 3 deletions
|
@ -577,6 +577,7 @@ void Document::visit_edges(Cell::Visitor& visitor)
|
||||||
visitor.visit(m_editing_host_manager);
|
visitor.visit(m_editing_host_manager);
|
||||||
visitor.visit(m_local_storage_holder);
|
visitor.visit(m_local_storage_holder);
|
||||||
visitor.visit(m_session_storage_holder);
|
visitor.visit(m_session_storage_holder);
|
||||||
|
visitor.visit(m_render_blocking_elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://w3c.github.io/selection-api/#dom-document-getselection
|
// https://w3c.github.io/selection-api/#dom-document-getselection
|
||||||
|
@ -5971,6 +5972,32 @@ bool Document::allow_declarative_shadow_roots() const
|
||||||
return m_allow_declarative_shadow_roots;
|
return m_allow_declarative_shadow_roots;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/dom.html#render-blocked
|
||||||
|
bool Document::is_render_blocked() const
|
||||||
|
{
|
||||||
|
// A Document document is render-blocked if both of the following are true:
|
||||||
|
// - document's render-blocking element set is non-empty, or document allows adding render-blocking elements.
|
||||||
|
// - FIXME: The current high resolution time given document's relevant global object has not exceeded an implementation-defined timeout value.
|
||||||
|
return !m_render_blocking_elements.is_empty() || allows_adding_render_blocking_elements();
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/dom.html#allows-adding-render-blocking-elements
|
||||||
|
bool Document::allows_adding_render_blocking_elements() const
|
||||||
|
{
|
||||||
|
// A document allows adding render-blocking elements if document's content type is "text/html" and the body element of document is null.
|
||||||
|
return content_type() == "text/html" && !body();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Document::add_render_blocking_element(GC::Ref<Element> element)
|
||||||
|
{
|
||||||
|
m_render_blocking_elements.set(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Document::remove_render_blocking_element(GC::Ref<Element> element)
|
||||||
|
{
|
||||||
|
m_render_blocking_elements.remove(element);
|
||||||
|
}
|
||||||
|
|
||||||
// https://dom.spec.whatwg.org/#document-allow-declarative-shadow-roots
|
// https://dom.spec.whatwg.org/#document-allow-declarative-shadow-roots
|
||||||
void Document::set_allow_declarative_shadow_roots(bool allow)
|
void Document::set_allow_declarative_shadow_roots(bool allow)
|
||||||
{
|
{
|
||||||
|
|
|
@ -797,6 +797,14 @@ public:
|
||||||
GC::Ptr<HTML::Storage> local_storage_holder() { return m_local_storage_holder; }
|
GC::Ptr<HTML::Storage> local_storage_holder() { return m_local_storage_holder; }
|
||||||
void set_local_storage_holder(GC::Ptr<HTML::Storage> storage) { m_local_storage_holder = storage; }
|
void set_local_storage_holder(GC::Ptr<HTML::Storage> storage) { m_local_storage_holder = storage; }
|
||||||
|
|
||||||
|
// https:// html.spec.whatwg.org/multipage/dom.html#render-blocked
|
||||||
|
[[nodiscard]] bool is_render_blocked() const;
|
||||||
|
// https://html.spec.whatwg.org/multipage/dom.html#allows-adding-render-blocking-elements
|
||||||
|
[[nodiscard]] bool allows_adding_render_blocking_elements() const;
|
||||||
|
|
||||||
|
void add_render_blocking_element(GC::Ref<Element>);
|
||||||
|
void remove_render_blocking_element(GC::Ref<Element>);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void initialize(JS::Realm&) override;
|
virtual void initialize(JS::Realm&) override;
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
virtual void visit_edges(Cell::Visitor&) override;
|
||||||
|
@ -1131,6 +1139,9 @@ private:
|
||||||
// https://html.spec.whatwg.org/multipage/webstorage.html#local-storage-holder
|
// https://html.spec.whatwg.org/multipage/webstorage.html#local-storage-holder
|
||||||
// A Document object has an associated local storage holder, which is null or a Storage object. It is initially null.
|
// A Document object has an associated local storage holder, which is null or a Storage object. It is initially null.
|
||||||
GC::Ptr<HTML::Storage> m_local_storage_holder;
|
GC::Ptr<HTML::Storage> m_local_storage_holder;
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/dom.html#render-blocking-element-set
|
||||||
|
HashTable<GC::Ref<Element>> m_render_blocking_elements;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -270,7 +270,10 @@ void EventLoop::update_the_rendering()
|
||||||
if (!document.is_fully_active())
|
if (!document.is_fully_active())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// FIXME: doc is render-blocked;
|
// doc is render-blocked;
|
||||||
|
if (document.is_render_blocked()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// doc's visibility state is "hidden";
|
// doc's visibility state is "hidden";
|
||||||
if (document.hidden())
|
if (document.hidden())
|
||||||
|
|
|
@ -71,6 +71,37 @@ void HTMLElement::visit_edges(Cell::Visitor& visitor)
|
||||||
visitor.visit(m_popover_close_watcher);
|
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
|
// https://html.spec.whatwg.org/multipage/dom.html#dom-dir
|
||||||
StringView HTMLElement::dir() const
|
StringView HTMLElement::dir() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -151,6 +151,15 @@ protected:
|
||||||
|
|
||||||
virtual void visit_edges(Cell::Visitor&) override;
|
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:
|
private:
|
||||||
virtual bool is_html_element() const final { return true; }
|
virtual bool is_html_element() const final { return true; }
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,8 @@ void HTMLScriptElement::execute_script()
|
||||||
return;
|
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.
|
// 3. If el's result is null, then fire an event named error at el, and return.
|
||||||
if (m_result.has<ResultState::Null>()) {
|
if (m_result.has<ResultState::Null>()) {
|
||||||
|
@ -393,7 +394,10 @@ void HTMLScriptElement::prepare_script()
|
||||||
return;
|
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.
|
// 8. Set el's delaying the load event to true.
|
||||||
begin_delaying_document_load_event(*m_preparation_time_document);
|
begin_delaying_document_load_event(*m_preparation_time_document);
|
||||||
|
@ -664,4 +668,11 @@ WebIDL::ExceptionOr<void> HTMLScriptElement::cloned(Node& copy, bool subtree) co
|
||||||
return {};
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,10 @@ public:
|
||||||
|
|
||||||
virtual WebIDL::ExceptionOr<void> cloned(Node&, bool) const override;
|
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:
|
private:
|
||||||
HTMLScriptElement(DOM::Document&, DOM::QualifiedName);
|
HTMLScriptElement(DOM::Document&, DOM::QualifiedName);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue