From 0a563f394e6ce2fa33aac651fd50d027b647a390 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 14 Apr 2024 10:24:44 +0200 Subject: [PATCH] LibWeb: Only invalidate style/layout on mutation for connected DOM nodes If a DOM node isn't connected, there's no need to invalidate, since it's not going to be visible anyway. The node will be automatically inserted if/when it becomes connected in the future. --- Userland/Libraries/LibWeb/DOM/Node.cpp | 27 ++++++++++++------- .../Libraries/LibWeb/DOMParsing/InnerHTML.cpp | 7 ++--- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index e0da6612b78ab4..470be4a01703eb 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -205,8 +205,10 @@ void Node::set_text_content(Optional const& maybe_content) // Otherwise, do nothing. - document().invalidate_style(); - document().invalidate_layout(); + if (is_connected()) { + document().invalidate_style(); + document().invalidate_layout(); + } document().bump_dom_tree_version(); } @@ -510,10 +512,11 @@ void Node::insert_before(JS::NonnullGCPtr node, JS::GCPtr child, boo // 9. Run the children changed steps for parent. children_changed(); - // FIXME: This will need to become smarter when we implement the :has() selector. - invalidate_style(); - - document().invalidate_layout(); + if (is_connected()) { + // FIXME: This will need to become smarter when we implement the :has() selector. + invalidate_style(); + document().invalidate_layout(); + } document().bump_dom_tree_version(); } @@ -569,6 +572,8 @@ WebIDL::ExceptionOr> Node::append_child(JS::NonnullGCPtr< // https://dom.spec.whatwg.org/#concept-node-remove void Node::remove(bool suppress_observers) { + bool was_connected = is_connected(); + // 1. Let parent be node’s parent auto* parent = this->parent(); @@ -705,10 +710,12 @@ void Node::remove(bool suppress_observers) // 21. Run the children changed steps for parent. parent->children_changed(); - // Since the tree structure has changed, we need to invalidate both style and layout. - // In the future, we should find a way to only invalidate the parts that actually need it. - document().invalidate_style(); - document().invalidate_layout(); + if (was_connected) { + // Since the tree structure has changed, we need to invalidate both style and layout. + // In the future, we should find a way to only invalidate the parts that actually need it. + document().invalidate_style(); + document().invalidate_layout(); + } document().bump_dom_tree_version(); } diff --git a/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp b/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp index 0d0855205ab47e..e35a759074b778 100644 --- a/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp +++ b/Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp @@ -52,9 +52,10 @@ WebIDL::ExceptionOr inner_html_setter(JS::NonnullGCPtr context_ if (!is(*context_object)) { context_object->set_needs_style_update(true); - // NOTE: Since the DOM has changed, we have to rebuild the layout tree. - context_object->document().invalidate_layout(); - context_object->document().set_needs_layout(); + if (context_object->is_connected()) { + // NOTE: Since the DOM has changed, we have to rebuild the layout tree. + context_object->document().invalidate_layout(); + } } return {};