Browse Source

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.
Andreas Kling 1 year ago
parent
commit
24157e4d1b

+ 17 - 10
Userland/Libraries/LibWeb/DOM/Node.cpp

@@ -205,8 +205,10 @@ void Node::set_text_content(Optional<String> 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> node, JS::GCPtr<Node> 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<JS::NonnullGCPtr<Node>> 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();
 }

+ 4 - 3
Userland/Libraries/LibWeb/DOMParsing/InnerHTML.cpp

@@ -52,9 +52,10 @@ WebIDL::ExceptionOr<void> inner_html_setter(JS::NonnullGCPtr<DOM::Node> context_
     if (!is<HTML::HTMLTemplateElement>(*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 {};