mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
selectors: Avoid looking at MatchingMode if the selector isn't the topmost.
Also, switch the hover quirk to the same mechanism. Bug: 1379696 Reviewed-By: bholley MozReview-Commit-ID: KrmNqNyASf6
This commit is contained in:
parent
2475039e40
commit
1f2b79bc30
2 changed files with 31 additions and 21 deletions
|
@ -53,24 +53,25 @@ impl ElementSelectorFlags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds per-element data alongside a pointer to MatchingContext.
|
/// Holds per-selector data alongside a pointer to MatchingContext.
|
||||||
pub struct LocalMatchingContext<'a, 'b: 'a, Impl: SelectorImpl> {
|
pub struct LocalMatchingContext<'a, 'b: 'a, Impl: SelectorImpl> {
|
||||||
/// Shared `MatchingContext`.
|
/// Shared `MatchingContext`.
|
||||||
pub shared: &'a mut MatchingContext<'b>,
|
pub shared: &'a mut MatchingContext<'b>,
|
||||||
/// A reference to the base selector we're matching against.
|
/// A reference to the base selector we're matching against.
|
||||||
pub selector: &'a Selector<Impl>,
|
pub selector: &'a Selector<Impl>,
|
||||||
/// The offset of the current compound selector being matched, kept up to date by
|
/// The offset of the current compound selector being matched, kept up to
|
||||||
/// the callees when the iterator is advanced. This, in conjunction with the selector
|
/// date by the callees when the iterator is advanced. This, in conjunction
|
||||||
/// reference above, allows callees to synthesize an iterator for the current compound
|
/// with the selector reference above, allows callees to synthesize an
|
||||||
/// selector on-demand. This is necessary because the primary iterator may already have
|
/// iterator for the current compound selector on-demand. This is necessary
|
||||||
/// been advanced partway through the current compound selector, and the callee may need
|
/// because the primary iterator may already have been advanced partway
|
||||||
/// the whole thing.
|
/// through the current compound selector, and the callee may need the whole
|
||||||
|
/// thing.
|
||||||
offset: usize,
|
offset: usize,
|
||||||
|
/// The level of nesting for the selector being matched.
|
||||||
|
pub nesting_level: usize,
|
||||||
/// Holds a bool flag to see whether :active and :hover quirk should try to
|
/// Holds a bool flag to see whether :active and :hover quirk should try to
|
||||||
/// match or not. This flag can only be true in these two cases:
|
/// match or not. This flag can only be true in the case PseudoElements are
|
||||||
/// - LocalMatchingContext is currently within a functional pseudo class
|
/// encountered when matching mode is ForStatelessPseudoElement.
|
||||||
/// like `:-moz-any` or `:not`.
|
|
||||||
/// - PseudoElements are encountered when matching mode is ForStatelessPseudoElement.
|
|
||||||
pub hover_active_quirk_disabled: bool,
|
pub hover_active_quirk_disabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +85,7 @@ impl<'a, 'b, Impl> LocalMatchingContext<'a, 'b, Impl>
|
||||||
shared: shared,
|
shared: shared,
|
||||||
selector: selector,
|
selector: selector,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
|
nesting_level: 0,
|
||||||
// We flip this off once third sequence is reached.
|
// We flip this off once third sequence is reached.
|
||||||
hover_active_quirk_disabled: selector.has_pseudo_element(),
|
hover_active_quirk_disabled: selector.has_pseudo_element(),
|
||||||
}
|
}
|
||||||
|
@ -107,8 +109,16 @@ impl<'a, 'b, Impl> LocalMatchingContext<'a, 'b, Impl>
|
||||||
/// Returns true if current compound selector matches :active and :hover quirk.
|
/// Returns true if current compound selector matches :active and :hover quirk.
|
||||||
/// https://quirks.spec.whatwg.org/#the-active-and-hover-quirk
|
/// https://quirks.spec.whatwg.org/#the-active-and-hover-quirk
|
||||||
pub fn active_hover_quirk_matches(&mut self) -> bool {
|
pub fn active_hover_quirk_matches(&mut self) -> bool {
|
||||||
if self.shared.quirks_mode() != QuirksMode::Quirks ||
|
if self.shared.quirks_mode() != QuirksMode::Quirks {
|
||||||
self.hover_active_quirk_disabled {
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't allow it in recursive selectors such as :not and :-moz-any.
|
||||||
|
if self.nesting_level != 0 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.hover_active_quirk_disabled {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,7 +463,8 @@ pub fn matches_complex_selector<E, F>(mut iter: SelectorIter<E::Impl>,
|
||||||
F: FnMut(&E, ElementSelectorFlags),
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
if context.shared.matching_mode == MatchingMode::ForStatelessPseudoElement {
|
if context.nesting_level == 0 &&
|
||||||
|
context.shared.matching_mode == MatchingMode::ForStatelessPseudoElement {
|
||||||
assert!(iter.clone().any(|c| {
|
assert!(iter.clone().any(|c| {
|
||||||
matches!(*c, Component::PseudoElement(..))
|
matches!(*c, Component::PseudoElement(..))
|
||||||
}));
|
}));
|
||||||
|
@ -462,7 +473,8 @@ pub fn matches_complex_selector<E, F>(mut iter: SelectorIter<E::Impl>,
|
||||||
|
|
||||||
// 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.shared.matching_mode == MatchingMode::ForStatelessPseudoElement {
|
if context.nesting_level == 0 &&
|
||||||
|
context.shared.matching_mode == MatchingMode::ForStatelessPseudoElement {
|
||||||
// Consume the pseudo.
|
// Consume the pseudo.
|
||||||
let pseudo = iter.next().unwrap();
|
let pseudo = iter.next().unwrap();
|
||||||
debug_assert!(matches!(*pseudo, Component::PseudoElement(..)),
|
debug_assert!(matches!(*pseudo, Component::PseudoElement(..)),
|
||||||
|
@ -733,13 +745,12 @@ fn matches_simple_selector<E, F>(
|
||||||
matches_generic_nth_child(element, 0, 1, true, true, flags_setter)
|
matches_generic_nth_child(element, 0, 1, true, true, flags_setter)
|
||||||
}
|
}
|
||||||
Component::Negation(ref negated) => {
|
Component::Negation(ref negated) => {
|
||||||
let old_value = context.hover_active_quirk_disabled;
|
context.nesting_level += 1;
|
||||||
context.hover_active_quirk_disabled = true;
|
|
||||||
let result = !negated.iter().all(|ss| {
|
let result = !negated.iter().all(|ss| {
|
||||||
matches_simple_selector(ss, element, context,
|
matches_simple_selector(ss, element, context,
|
||||||
relevant_link, flags_setter)
|
relevant_link, flags_setter)
|
||||||
});
|
});
|
||||||
context.hover_active_quirk_disabled = old_value;
|
context.nesting_level -= 1;
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1777,12 +1777,11 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
|
||||||
}
|
}
|
||||||
NonTSPseudoClass::MozPlaceholder => false,
|
NonTSPseudoClass::MozPlaceholder => false,
|
||||||
NonTSPseudoClass::MozAny(ref sels) => {
|
NonTSPseudoClass::MozAny(ref sels) => {
|
||||||
let old_value = context.hover_active_quirk_disabled;
|
context.nesting_level += 1;
|
||||||
context.hover_active_quirk_disabled = true;
|
|
||||||
let result = sels.iter().any(|s| {
|
let result = sels.iter().any(|s| {
|
||||||
matches_complex_selector(s.iter(), self, context, flags_setter)
|
matches_complex_selector(s.iter(), self, context, flags_setter)
|
||||||
});
|
});
|
||||||
context.hover_active_quirk_disabled = old_value;
|
context.nesting_level -= 1;
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
NonTSPseudoClass::Lang(ref lang_arg) => {
|
NonTSPseudoClass::Lang(ref lang_arg) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue