From 01e8a9bd350c87b190b30b6950a7f674f7dd1589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 7 Mar 2018 16:35:07 +0100 Subject: [PATCH] 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 --- components/selectors/matching.rs | 39 ++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/components/selectors/matching.rs b/components/selectors/matching.rs index 849edf74a09..6cb9acf59fe 100644 --- a/components/selectors/matching.rs +++ b/components/selectors/matching.rs @@ -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