1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 20:07:34 +00:00

LibWeb: Limit style update tree traversal to dirty subtrees

This patch adds a second style dirty bit that tracks whether a DOM node
has one or more children with dirty style. This allows the style update
to skip over entire subtrees where all nodes are clean.
This commit is contained in:
Andreas Kling 2020-12-14 12:04:30 +01:00
parent d1479aef56
commit 6809be436b
3 changed files with 32 additions and 7 deletions

View file

@ -400,13 +400,25 @@ void Document::update_layout()
}
}
void Document::update_style()
static void update_style_recursively(DOM::Node& node)
{
for_each_in_subtree_of_type<Element>([&](auto& element) {
if (element.needs_style_update())
element.recompute_style();
node.for_each_child([&](auto& child) {
if (child.needs_style_update()) {
if (is<Element>(child))
downcast<Element>(child).recompute_style();
child.set_needs_style_update(false);
}
if (child.child_needs_style_update()) {
update_style_recursively(child);
child.set_child_needs_style_update(false);
}
return IterationDecision::Continue;
});
}
void Document::update_style()
{
update_style_recursively(*this);
update_layout();
}

View file

@ -254,8 +254,17 @@ void Node::set_needs_style_update(bool value)
if (m_needs_style_update == value)
return;
m_needs_style_update = value;
if (m_needs_style_update)
if (m_needs_style_update) {
for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent())
ancestor->m_child_needs_style_update = true;
document().schedule_style_update();
}
}
void Node::inserted_into(Node&)
{
set_needs_style_update(true);
}
}

View file

@ -126,7 +126,7 @@ public:
Element* parent_element();
const Element* parent_element() const;
virtual void inserted_into(Node&) { }
virtual void inserted_into(Node&);
virtual void removed_from(Node&) { }
virtual void children_changed() { }
@ -140,6 +140,9 @@ public:
bool needs_style_update() const { return m_needs_style_update; }
void set_needs_style_update(bool);
bool child_needs_style_update() const { return m_child_needs_style_update; }
void set_child_needs_style_update(bool b) { m_child_needs_style_update = b; }
void invalidate_style();
bool is_link() const;
@ -157,7 +160,8 @@ protected:
Document* m_document { nullptr };
mutable WeakPtr<Layout::Node> m_layout_node;
NodeType m_type { NodeType::INVALID };
bool m_needs_style_update { true };
bool m_needs_style_update { false };
bool m_child_needs_style_update { false };
};
}