mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
selectors: Add a MatchingContext::nest function, make nesting_level private.
This commit is contained in:
parent
88d2982e23
commit
e4f08ee2bb
4 changed files with 52 additions and 33 deletions
|
@ -122,9 +122,9 @@ where
|
||||||
|
|
||||||
/// The current nesting level of selectors that we're matching.
|
/// 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.
|
/// immutable again.
|
||||||
pub nesting_level: usize,
|
nesting_level: usize,
|
||||||
|
|
||||||
/// An optional hook function for checking whether a pseudo-element
|
/// An optional hook function for checking whether a pseudo-element
|
||||||
/// should match when matching_mode is ForStatelessPseudoElement.
|
/// 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.
|
/// The quirks mode of the document.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn quirks_mode(&self) -> QuirksMode {
|
pub fn quirks_mode(&self) -> QuirksMode {
|
||||||
|
@ -192,4 +198,16 @@ where
|
||||||
pub fn classes_and_ids_case_sensitivity(&self) -> CaseSensitivity {
|
pub fn classes_and_ids_case_sensitivity(&self) -> CaseSensitivity {
|
||||||
self.classes_and_ids_case_sensitivity
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -289,7 +289,7 @@ where
|
||||||
// If this is the special pseudo-element mode, consume the ::pseudo-element
|
// If this is the special pseudo-element mode, consume the ::pseudo-element
|
||||||
// before proceeding, since the caller has already handled that part.
|
// before proceeding, since the caller has already handled that part.
|
||||||
if context.matching_mode == MatchingMode::ForStatelessPseudoElement &&
|
if context.matching_mode == MatchingMode::ForStatelessPseudoElement &&
|
||||||
context.nesting_level == 0 {
|
context.nesting_level() == 0 {
|
||||||
// Consume the pseudo.
|
// Consume the pseudo.
|
||||||
match *iter.next().unwrap() {
|
match *iter.next().unwrap() {
|
||||||
Component::PseudoElement(ref pseudo) => {
|
Component::PseudoElement(ref pseudo) => {
|
||||||
|
@ -347,7 +347,7 @@ fn matches_hover_and_active_quirk<Impl: SelectorImpl>(
|
||||||
return MatchesHoverAndActiveQuirk::No;
|
return MatchesHoverAndActiveQuirk::No;
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.nesting_level != 0 {
|
if context.nesting_level() != 0 {
|
||||||
return MatchesHoverAndActiveQuirk::No;
|
return MatchesHoverAndActiveQuirk::No;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,17 +639,15 @@ where
|
||||||
match *selector {
|
match *selector {
|
||||||
Component::Combinator(_) => unreachable!(),
|
Component::Combinator(_) => unreachable!(),
|
||||||
Component::Slotted(ref selector) => {
|
Component::Slotted(ref selector) => {
|
||||||
context.shared.nesting_level += 1;
|
context.shared.nest(|context| {
|
||||||
let result =
|
|
||||||
element.assigned_slot().is_some() &&
|
element.assigned_slot().is_some() &&
|
||||||
matches_complex_selector(
|
matches_complex_selector(
|
||||||
selector.iter(),
|
selector.iter(),
|
||||||
element,
|
element,
|
||||||
context.shared,
|
context,
|
||||||
flags_setter,
|
flags_setter,
|
||||||
);
|
)
|
||||||
context.shared.nesting_level -= 1;
|
})
|
||||||
result
|
|
||||||
}
|
}
|
||||||
Component::PseudoElement(ref pseudo) => {
|
Component::PseudoElement(ref pseudo) => {
|
||||||
element.match_pseudo_element(pseudo, context.shared)
|
element.match_pseudo_element(pseudo, context.shared)
|
||||||
|
@ -731,7 +729,7 @@ where
|
||||||
}
|
}
|
||||||
Component::NonTSPseudoClass(ref pc) => {
|
Component::NonTSPseudoClass(ref pc) => {
|
||||||
if context.matches_hover_and_active_quirk == MatchesHoverAndActiveQuirk::Yes &&
|
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) &&
|
E::Impl::is_active_or_hover(pc) &&
|
||||||
!element.is_link() {
|
!element.is_link() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -790,17 +788,22 @@ where
|
||||||
matches_generic_nth_child(element, context, 0, 1, true, true, flags_setter)
|
matches_generic_nth_child(element, context, 0, 1, true, true, flags_setter)
|
||||||
}
|
}
|
||||||
Component::Negation(ref negated) => {
|
Component::Negation(ref negated) => {
|
||||||
context.shared.nesting_level += 1;
|
let visited_handling = context.visited_handling;
|
||||||
let result = !negated.iter().all(|ss| {
|
context.shared.nest(|context| {
|
||||||
matches_simple_selector(
|
let mut local_context = LocalMatchingContext {
|
||||||
ss,
|
visited_handling,
|
||||||
element,
|
matches_hover_and_active_quirk: MatchesHoverAndActiveQuirk::No,
|
||||||
context,
|
shared: context,
|
||||||
flags_setter,
|
};
|
||||||
)
|
!negated.iter().all(|ss| {
|
||||||
});
|
matches_simple_selector(
|
||||||
context.shared.nesting_level -= 1;
|
ss,
|
||||||
result
|
element,
|
||||||
|
&mut local_context,
|
||||||
|
flags_setter,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2119,12 +2119,11 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
NonTSPseudoClass::MozPlaceholder => false,
|
NonTSPseudoClass::MozPlaceholder => false,
|
||||||
NonTSPseudoClass::MozAny(ref sels) => {
|
NonTSPseudoClass::MozAny(ref sels) => {
|
||||||
context.nesting_level += 1;
|
context.nest(|context| {
|
||||||
let result = sels.iter().any(|s| {
|
sels.iter().any(|s| {
|
||||||
matches_complex_selector(s.iter(), self, context, flags_setter)
|
matches_complex_selector(s.iter(), self, context, flags_setter)
|
||||||
});
|
})
|
||||||
context.nesting_level -= 1;
|
})
|
||||||
result
|
|
||||||
}
|
}
|
||||||
NonTSPseudoClass::Lang(ref lang_arg) => {
|
NonTSPseudoClass::Lang(ref lang_arg) => {
|
||||||
self.match_element_lang(None, lang_arg)
|
self.match_element_lang(None, lang_arg)
|
||||||
|
|
|
@ -162,12 +162,11 @@ impl<'a, E> Element for ElementWrapper<'a, E>
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
NonTSPseudoClass::MozAny(ref selectors) => {
|
NonTSPseudoClass::MozAny(ref selectors) => {
|
||||||
use selectors::matching::matches_complex_selector;
|
use selectors::matching::matches_complex_selector;
|
||||||
context.nesting_level += 1;
|
return context.nest(|context| {
|
||||||
let result = selectors.iter().any(|s| {
|
selectors.iter().any(|s| {
|
||||||
matches_complex_selector(s.iter(), self, context, _setter)
|
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
|
// :dir is implemented in terms of state flags, but which state flag
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue