aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/selectors/context.rs22
-rw-r--r--components/selectors/matching.rs43
-rw-r--r--components/style/gecko/wrapper.rs11
-rw-r--r--components/style/invalidation/element/element_wrapper.rs9
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