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:
parent
9a9d655abe
commit
5e7945e26f
6 changed files with 142 additions and 16 deletions
|
@ -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()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue