mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-23 09:46:04 -05:00
LibWeb: Filter rules to run before allocating vector of matches
By filtering first, we end up allocating much less vector space most of the time. This is mostly helpful in pathological cases where there's a huge number of rules present, but most of them get rejected early.
This commit is contained in:
parent
ee352e59db
commit
c8f22f65d9
Notes:
github-actions[bot]
2024-09-09 18:13:24 +00:00
Author: https://github.com/awesomekling Commit: https://github.com/LadybirdBrowser/ladybird/commit/c8f22f65d96 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1345
2 changed files with 27 additions and 7 deletions
|
@ -395,9 +395,9 @@ Vector<MatchingRule> StyleComputer::collect_matching_rules(DOM::Element const& e
|
|||
|
||||
add_rules_to_run(rule_cache.other_rules);
|
||||
|
||||
Vector<MatchingRule> matching_rules;
|
||||
matching_rules.ensure_capacity(rules_to_run.size());
|
||||
for (auto const& rule_to_run : rules_to_run) {
|
||||
size_t maximum_match_count = 0;
|
||||
|
||||
for (auto& rule_to_run : rules_to_run) {
|
||||
// FIXME: This needs to be revised when adding support for the ::shadow selector, as it needs to cross shadow boundaries.
|
||||
auto rule_root = rule_to_run.shadow_root;
|
||||
auto from_user_agent_or_user_stylesheet = rule_to_run.cascade_origin == CascadeOrigin::UserAgent || rule_to_run.cascade_origin == CascadeOrigin::User;
|
||||
|
@ -412,21 +412,40 @@ Vector<MatchingRule> StyleComputer::collect_matching_rules(DOM::Element const& e
|
|||
|| (element.is_shadow_host() && rule_root == element.shadow_root())
|
||||
|| from_user_agent_or_user_stylesheet;
|
||||
|
||||
if (!rule_is_relevant_for_current_scope)
|
||||
if (!rule_is_relevant_for_current_scope) {
|
||||
rule_to_run.skip = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto const& selector = rule_to_run.rule->selectors()[rule_to_run.selector_index];
|
||||
if (should_reject_with_ancestor_filter(*selector)) {
|
||||
rule_to_run.skip = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
++maximum_match_count;
|
||||
}
|
||||
|
||||
if (maximum_match_count == 0)
|
||||
return {};
|
||||
|
||||
Vector<MatchingRule> matching_rules;
|
||||
matching_rules.ensure_capacity(maximum_match_count);
|
||||
|
||||
for (auto const& rule_to_run : rules_to_run) {
|
||||
if (rule_to_run.skip)
|
||||
continue;
|
||||
|
||||
// NOTE: When matching an element against a rule from outside the shadow root's style scope,
|
||||
// we have to pass in null for the shadow host, otherwise combinator traversal will
|
||||
// be confined to the element itself (since it refuses to cross the shadow boundary).
|
||||
auto rule_root = rule_to_run.shadow_root;
|
||||
auto shadow_host_to_use = shadow_host;
|
||||
if (element.is_shadow_host() && rule_root != element.shadow_root())
|
||||
shadow_host_to_use = nullptr;
|
||||
|
||||
auto const& selector = rule_to_run.rule->selectors()[rule_to_run.selector_index];
|
||||
|
||||
if (should_reject_with_ancestor_filter(*selector))
|
||||
continue;
|
||||
|
||||
if (rule_to_run.can_use_fast_matches) {
|
||||
if (!SelectorEngine::fast_matches(selector, *rule_to_run.sheet, element, shadow_host_to_use))
|
||||
continue;
|
||||
|
|
|
@ -93,6 +93,7 @@ struct MatchingRule {
|
|||
bool contains_pseudo_element { false };
|
||||
bool contains_root_pseudo_class { false };
|
||||
bool can_use_fast_matches { false };
|
||||
bool skip { false };
|
||||
};
|
||||
|
||||
struct FontFaceKey {
|
||||
|
|
Loading…
Add table
Reference in a new issue