Skip to content

Commit

Permalink
Auto merge of #20248 - emilio:invalidation-selectors-faster, r=bholley
Browse files Browse the repository at this point in the history
style: Change the order we match selectors on invalidation to match normal order.

This changes the order to match the normal selector-matching order, which is
usually faster.

That is, when matching div:nth-child(2), for example, before this patch we'd
first try to match :nth-child(2), and only then div.

This patch makes us walk until the end or the next combinator, and only then
match backwards, matching first div, then :nth-child.

Bug: 1443814
Reviewed-by: bholley

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/20248)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Mar 8, 2018
2 parents 6a2ec87 + 01e8a9b commit 8e52f8a
Showing 1 changed file with 34 additions and 5 deletions.
39 changes: 34 additions & 5 deletions components/selectors/matching.rs
Expand Up @@ -249,23 +249,52 @@ where
matches_hover_and_active_quirk: MatchesHoverAndActiveQuirk::No,
};

// Find the end of the selector or the next combinator, then match
// backwards, so that we match in the same order as
// matches_complex_selector, which is usually faster.
let start_offset = from_offset;
for component in selector.iter_raw_parse_order_from(from_offset) {
if matches!(*component, Component::Combinator(..)) {
debug_assert_ne!(from_offset, 0, "Selector started with a combinator?");
return CompoundSelectorMatchingResult::Matched {
next_combinator_offset: from_offset,
}
break;
}

from_offset += 1;
}

debug_assert!(from_offset >= 1);
debug_assert!(from_offset <= selector.len());

let iter = selector.iter_from(selector.len() - from_offset);
debug_assert!(
iter.clone().next().is_some() || (
from_offset != selector.len() && matches!(
selector.combinator_at_parse_order(from_offset),
Combinator::SlotAssignment | Combinator::PseudoElement
)
),
"Got the math wrong: {:?} | {:?} | {} {}",
selector,
selector.iter_raw_match_order().as_slice(),
from_offset,
start_offset
);

for component in iter {
if !matches_simple_selector(
component,
element,
&mut local_context,
&mut |_, _| {}) {
&mut |_, _| {}
) {
return CompoundSelectorMatchingResult::NotMatched;
}
}

from_offset += 1;
if from_offset != selector.len() {
return CompoundSelectorMatchingResult::Matched {
next_combinator_offset: from_offset,
}
}

CompoundSelectorMatchingResult::FullyMatched
Expand Down

0 comments on commit 8e52f8a

Please sign in to comment.