diff options
author | Andreas Kling <kling@serenityos.org> | 2022-03-19 18:10:59 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-03-19 22:04:43 +0100 |
commit | 0b861e0c9da13443e78e8a88a34fbc28d15fbbee (patch) | |
tree | db59cf9461fdaa67b1f605b6dfd19c66014e76e8 | |
parent | f87edd4c14b0b72575d0915b3255f2870e99d7ea (diff) | |
download | serenity-0b861e0c9da13443e78e8a88a34fbc28d15fbbee.zip |
LibWeb: Make document-level style invalidation fast
Add a flag to DOM::Document that means the whole document needs a style
update. This saves us the trouble of traversing the entire DOM to mark
all nodes as needing a style update.
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.cpp | 10 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Document.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Node.cpp | 7 |
3 files changed, 18 insertions, 4 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index a07554a552..12016473da 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -595,6 +595,7 @@ void Document::update_layout() [[nodiscard]] static bool update_style_recursively(DOM::Node& node) { + bool const needs_full_style_update = node.document().needs_full_style_update(); bool needs_relayout = false; if (is<Element>(node)) { @@ -602,15 +603,15 @@ void Document::update_layout() } node.set_needs_style_update(false); - if (node.child_needs_style_update()) { + if (needs_full_style_update || node.child_needs_style_update()) { if (node.is_element()) { if (auto* shadow_root = static_cast<DOM::Element&>(node).shadow_root()) { - if (shadow_root->needs_style_update() || shadow_root->child_needs_style_update()) + if (needs_full_style_update || shadow_root->needs_style_update() || shadow_root->child_needs_style_update()) needs_relayout |= update_style_recursively(*shadow_root); } } node.for_each_child([&](auto& child) { - if (child.needs_style_update() || child.child_needs_style_update()) + if (needs_full_style_update || child.needs_style_update() || child.child_needs_style_update()) needs_relayout |= update_style_recursively(child); return IterationDecision::Continue; }); @@ -624,10 +625,11 @@ void Document::update_style() { if (!browsing_context()) return; - if (!needs_style_update() && !child_needs_style_update()) + if (!needs_full_style_update() && !needs_style_update() && !child_needs_style_update()) return; if (update_style_recursively(*this)) invalidate_layout(); + m_needs_full_style_update = false; m_style_update_timer->stop(); } diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index ec080dde64..94ce18bcd5 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -334,6 +334,9 @@ public: callback(*node_iterator); } + bool needs_full_style_update() const { return m_needs_full_style_update; } + void set_needs_full_style_update(bool b) { m_needs_full_style_update = b; } + private: explicit Document(const AK::URL&); @@ -438,6 +441,8 @@ private: bool m_needs_layout { false }; + bool m_needs_full_style_update { false }; + HashTable<NodeIterator*> m_node_iterators; }; diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index ee91ec5e25..364c4ea69c 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -176,6 +176,13 @@ void Node::set_node_value(const String& value) void Node::invalidate_style() { + if (is_document()) { + auto& document = static_cast<DOM::Document&>(*this); + document.set_needs_full_style_update(true); + document.schedule_style_update(); + return; + } + for_each_in_inclusive_subtree([&](Node& node) { node.m_needs_style_update = true; if (node.has_children()) |