diff options
-rw-r--r-- | components/selectors/context.rs | 22 | ||||
-rw-r--r-- | components/selectors/matching.rs | 43 | ||||
-rw-r--r-- | components/style/gecko/wrapper.rs | 11 | ||||
-rw-r--r-- | components/style/invalidation/element/element_wrapper.rs | 9 |
4 files changed, 52 insertions, 33 deletions
diff --git a/components/selectors/context.rs b/components/selectors/context.rs index 856e18497d9..be18c29e1f9 100644 --- a/components/selectors/context.rs +++ b/components/selectors/context.rs @@ -122,9 +122,9 @@ where /// The current nesting level of selectors that we're matching. /// - /// FIXME(emilio): Move this somewhere else and make MatchingContext + /// FIXME(emilio): Consider putting the mutable stuff in a Cell. /// immutable again. - pub nesting_level: usize, + nesting_level: usize, /// An optional hook function for checking whether a pseudo-element /// should match when matching_mode is ForStatelessPseudoElement. @@ -181,6 +181,12 @@ where } } + /// How many times deep are we in a selector. + #[inline] + pub fn nesting_level(&self) -> usize { + self.nesting_level + } + /// The quirks mode of the document. #[inline] pub fn quirks_mode(&self) -> QuirksMode { @@ -192,4 +198,16 @@ where pub fn classes_and_ids_case_sensitivity(&self) -> CaseSensitivity { self.classes_and_ids_case_sensitivity } + + /// Runs F with a deeper nesting level. + #[inline] + pub fn nest<F, R>(&mut self, f: F) -> R + where + F: FnOnce(&mut Self) -> R, + { + self.nesting_level += 1; + let result = f(self); + self.nesting_level -= 1; + result + } } diff --git a/components/selectors/matching.rs b/components/selectors/matching.rs index 5b859b5e248..2b8e7123ac0 100644 --- a/components/selectors/matching.rs +++ b/components/selectors/matching.rs @@ -289,7 +289,7 @@ where // If this is the special pseudo-element mode, consume the ::pseudo-element // before proceeding, since the caller has already handled that part. if context.matching_mode == MatchingMode::ForStatelessPseudoElement && - context.nesting_level == 0 { + context.nesting_level() == 0 { // Consume the pseudo. match *iter.next().unwrap() { Component::PseudoElement(ref pseudo) => { @@ -347,7 +347,7 @@ fn matches_hover_and_active_quirk<Impl: SelectorImpl>( return MatchesHoverAndActiveQuirk::No; } - if context.nesting_level != 0 { + if context.nesting_level() != 0 { return MatchesHoverAndActiveQuirk::No; } @@ -639,17 +639,15 @@ where match *selector { Component::Combinator(_) => unreachable!(), Component::Slotted(ref selector) => { - context.shared.nesting_level += 1; - let result = + context.shared.nest(|context| { element.assigned_slot().is_some() && matches_complex_selector( selector.iter(), element, - context.shared, + context, flags_setter, - ); - context.shared.nesting_level -= 1; - result + ) + }) } Component::PseudoElement(ref pseudo) => { element.match_pseudo_element(pseudo, context.shared) @@ -731,7 +729,7 @@ where } Component::NonTSPseudoClass(ref pc) => { if context.matches_hover_and_active_quirk == MatchesHoverAndActiveQuirk::Yes && - context.shared.nesting_level == 0 && + context.shared.nesting_level() == 0 && E::Impl::is_active_or_hover(pc) && !element.is_link() { return false; @@ -790,17 +788,22 @@ where matches_generic_nth_child(element, context, 0, 1, true, true, flags_setter) } Component::Negation(ref negated) => { - context.shared.nesting_level += 1; - let result = !negated.iter().all(|ss| { - matches_simple_selector( - ss, - element, - context, - flags_setter, - ) - }); - context.shared.nesting_level -= 1; - result + let visited_handling = context.visited_handling; + context.shared.nest(|context| { + let mut local_context = LocalMatchingContext { + visited_handling, + matches_hover_and_active_quirk: MatchesHoverAndActiveQuirk::No, + shared: context, + }; + !negated.iter().all(|ss| { + matches_simple_selector( + ss, + element, + &mut local_context, + flags_setter, + ) + }) + }) } } } diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 0f8626eaa0e..12ff3517192 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -2119,12 +2119,11 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } NonTSPseudoClass::MozPlaceholder => false, NonTSPseudoClass::MozAny(ref sels) => { - context.nesting_level += 1; - let result = sels.iter().any(|s| { - matches_complex_selector(s.iter(), self, context, flags_setter) - }); - context.nesting_level -= 1; - result + context.nest(|context| { + sels.iter().any(|s| { + matches_complex_selector(s.iter(), self, context, flags_setter) + }) + }) } NonTSPseudoClass::Lang(ref lang_arg) => { self.match_element_lang(None, lang_arg) diff --git a/components/style/invalidation/element/element_wrapper.rs b/components/style/invalidation/element/element_wrapper.rs index 65f3ea89c19..e2ceedf912d 100644 --- a/components/style/invalidation/element/element_wrapper.rs +++ b/components/style/invalidation/element/element_wrapper.rs @@ -162,12 +162,11 @@ impl<'a, E> Element for ElementWrapper<'a, E> #[cfg(feature = "gecko")] NonTSPseudoClass::MozAny(ref selectors) => { use selectors::matching::matches_complex_selector; - context.nesting_level += 1; - let result = selectors.iter().any(|s| { - matches_complex_selector(s.iter(), self, context, _setter) + return context.nest(|context| { + selectors.iter().any(|s| { + matches_complex_selector(s.iter(), self, context, _setter) + }) }); - context.nesting_level -= 1; - return result } // :dir is implemented in terms of state flags, but which state flag |