summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-03-19 18:10:59 +0100
committerAndreas Kling <kling@serenityos.org>2022-03-19 22:04:43 +0100
commit0b861e0c9da13443e78e8a88a34fbc28d15fbbee (patch)
treedb59cf9461fdaa67b1f605b6dfd19c66014e76e8
parentf87edd4c14b0b72575d0915b3255f2870e99d7ea (diff)
downloadserenity-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.cpp10
-rw-r--r--Userland/Libraries/LibWeb/DOM/Document.h5
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.cpp7
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())