1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 14:37:46 +00:00

LibWeb: Add a simple StyleInvalidator class

This patch adds a simple, naive & inefficient class for document-wide
style invalidation, e.g. after element attribute updates. During
construction it collects a HashMap of a document's elements and their
matching rules, during destruction it does the same and then compares
the results; dirtying all elements that have a different number or order
of matching rules afterwards.

Much room for improvement, but it solves the problem of stale element
styling after attribute updates for now :^)

Fixes #4404.
This commit is contained in:
Linus Groh 2020-12-14 21:31:10 +00:00 committed by Andreas Kling
parent 9a9d655abe
commit 5e7945e26f
6 changed files with 142 additions and 16 deletions

View file

@ -103,6 +103,22 @@ Vector<MatchingRule> StyleResolver::collect_matching_rules(const DOM::Element& e
return matching_rules;
}
void StyleResolver::sort_matching_rules(Vector<MatchingRule>& matching_rules) const
{
quick_sort(matching_rules, [&](MatchingRule& a, MatchingRule& b) {
auto& a_selector = a.rule->selectors()[a.selector_index];
auto& b_selector = b.rule->selectors()[b.selector_index];
auto a_specificity = a_selector.specificity();
auto b_specificity = b_selector.specificity();
if (a_selector.specificity() == b_selector.specificity()) {
if (a.style_sheet_index == b.style_sheet_index)
return a.rule_index < b.rule_index;
return a.style_sheet_index < b.style_sheet_index;
}
return a_specificity < b_specificity;
});
}
bool StyleResolver::is_inherited_property(CSS::PropertyID property_id)
{
static HashTable<CSS::PropertyID> inherited_properties;
@ -547,19 +563,7 @@ NonnullRefPtr<StyleProperties> StyleResolver::resolve_style(const DOM::Element&
element.apply_presentational_hints(*style);
auto matching_rules = collect_matching_rules(element);
quick_sort(matching_rules, [&](MatchingRule& a, MatchingRule& b) {
auto& a_selector = a.rule->selectors()[a.selector_index];
auto& b_selector = b.rule->selectors()[b.selector_index];
auto a_specificity = a_selector.specificity();
auto b_specificity = b_selector.specificity();
if (a_selector.specificity() == b_selector.specificity()) {
if (a.style_sheet_index == b.style_sheet_index)
return a.rule_index < b.rule_index;
return a.style_sheet_index < b.style_sheet_index;
}
return a_specificity < b_specificity;
});
sort_matching_rules(matching_rules);
for (auto& match : matching_rules) {
for (auto& property : match.rule->declaration().properties()) {