diff options
-rw-r--r-- | components/layout_thread/dom_wrapper.rs | 6 | ||||
-rw-r--r-- | components/script/dom/element.rs | 4 | ||||
-rw-r--r-- | components/selectors/context.rs | 4 | ||||
-rw-r--r-- | components/selectors/matching.rs | 391 | ||||
-rw-r--r-- | components/selectors/tree.rs | 17 | ||||
-rw-r--r-- | components/style/gecko/wrapper.rs | 18 | ||||
-rw-r--r-- | components/style/invalidation/element/element_wrapper.rs | 59 | ||||
-rw-r--r-- | components/style/stylist.rs | 12 |
8 files changed, 256 insertions, 255 deletions
diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs index 2a95324ccb7..2863d840ce5 100644 --- a/components/layout_thread/dom_wrapper.rs +++ b/components/layout_thread/dom_wrapper.rs @@ -51,7 +51,7 @@ use script_layout_interface::{OpaqueStyleAndLayoutData, StyleData}; use script_layout_interface::wrapper_traits::{DangerousThreadSafeLayoutNode, GetLayoutData, LayoutNode}; use script_layout_interface::wrapper_traits::{PseudoElementType, ThreadSafeLayoutElement, ThreadSafeLayoutNode}; use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity}; -use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, RelevantLinkStatus}; +use selectors::matching::{ElementSelectorFlags, MatchingContext, RelevantLinkStatus}; use selectors::matching::VisitedHandlingMode; use selectors::sink::Push; use servo_arc::{Arc, ArcBorrow}; @@ -720,7 +720,7 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> { fn match_non_ts_pseudo_class<F>(&self, pseudo_class: &NonTSPseudoClass, - _: &mut LocalMatchingContext<Self::Impl>, + _: &mut MatchingContext, _: &RelevantLinkStatus, _: &mut F) -> bool @@ -1240,7 +1240,7 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> { fn match_non_ts_pseudo_class<F>(&self, _: &NonTSPseudoClass, - _: &mut LocalMatchingContext<Self::Impl>, + _: &mut MatchingContext, _: &RelevantLinkStatus, _: &mut F) -> bool diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index f6e5357df10..91179ee1b34 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -89,7 +89,7 @@ use script_layout_interface::message::ReflowGoal; use script_thread::ScriptThread; use selectors::Element as SelectorsElement; use selectors::attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity}; -use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, RelevantLinkStatus}; +use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode, RelevantLinkStatus}; use selectors::matching::{HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS}; use selectors::sink::Push; use servo_arc::Arc; @@ -2583,7 +2583,7 @@ impl<'a> SelectorsElement for DomRoot<Element> { fn match_non_ts_pseudo_class<F>(&self, pseudo_class: &NonTSPseudoClass, - _: &mut LocalMatchingContext<Self::Impl>, + _: &mut MatchingContext, _: &RelevantLinkStatus, _: &mut F) -> bool diff --git a/components/selectors/context.rs b/components/selectors/context.rs index 894cc31b15d..22c886315fb 100644 --- a/components/selectors/context.rs +++ b/components/selectors/context.rs @@ -102,6 +102,9 @@ pub struct MatchingContext<'a> { /// See https://drafts.csswg.org/selectors-4/#scope-pseudo pub scope_element: Option<OpaqueElement>, + /// The current nesting level of selectors that we're matching. + pub nesting_level: usize, + quirks_mode: QuirksMode, classes_and_ids_case_sensitivity: CaseSensitivity, } @@ -140,6 +143,7 @@ impl<'a> MatchingContext<'a> { relevant_link_found: false, classes_and_ids_case_sensitivity: quirks_mode.classes_and_ids_case_sensitivity(), scope_element: None, + nesting_level: 0, } } diff --git a/components/selectors/matching.rs b/components/selectors/matching.rs index 875ac2862e6..711bec885d4 100644 --- a/components/selectors/matching.rs +++ b/components/selectors/matching.rs @@ -54,116 +54,19 @@ impl ElementSelectorFlags { } } -/// Holds per-selector data alongside a pointer to MatchingContext. -pub struct LocalMatchingContext<'a, 'b: 'a, Impl: SelectorImpl> { - /// Shared `MatchingContext`. - pub shared: &'a mut MatchingContext<'b>, - /// A reference to the base selector we're matching against. - pub selector: &'a Selector<Impl>, - /// The offset of the current compound selector being matched, kept up to - /// date by the callees when the iterator is advanced. This, in conjunction - /// with the selector reference above, allows callees to synthesize an - /// iterator for the current compound selector on-demand. This is necessary - /// because the primary iterator may already have been advanced partway - /// through the current compound selector, and the callee may need the whole - /// thing. - 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 - /// match or not. This flag can only be true in the case PseudoElements are - /// encountered when matching mode is ForStatelessPseudoElement. - pub hover_active_quirk_disabled: bool, -} - -impl<'a, 'b, Impl> LocalMatchingContext<'a, 'b, Impl> - where Impl: SelectorImpl -{ - /// Constructs a new `LocalMatchingContext`. - pub fn new(shared: &'a mut MatchingContext<'b>, - selector: &'a Selector<Impl>) -> Self { - Self { - shared: shared, - selector: selector, - offset: 0, - nesting_level: 0, - // We flip this off once third sequence is reached. - hover_active_quirk_disabled: selector.has_pseudo_element(), - } - } - - /// Updates offset of Selector to show new compound selector. - /// To be able to correctly re-synthesize main SelectorIter. - fn note_position(&mut self, selector_iter: &SelectorIter<Impl>) { - if let QuirksMode::Quirks = self.shared.quirks_mode() { - if self.selector.has_pseudo_element() && self.offset != 0 { - // This is the _second_ call to note_position, - // which means we've moved past the compound - // selector adjacent to the pseudo-element. - self.hover_active_quirk_disabled = false; - } - - self.offset = self.selector.len() - selector_iter.selector_length(); - } - } - - /// Returns true if current compound selector matches :active and :hover quirk. - /// https://quirks.spec.whatwg.org/#the-active-and-hover-quirk - pub fn active_hover_quirk_matches(&self) -> bool { - if self.shared.quirks_mode() != QuirksMode::Quirks { - 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; - } - - let mut iter = if self.offset == 0 { - self.selector.iter() - } else { - self.selector.iter_from(self.offset) - }; - - return iter.all(|simple| { - match *simple { - Component::LocalName(_) | - Component::AttributeInNoNamespaceExists { .. } | - Component::AttributeInNoNamespace { .. } | - Component::AttributeOther(_) | - Component::ID(_) | - Component::Class(_) | - Component::PseudoElement(_) | - Component::Negation(_) | - Component::FirstChild | - Component::LastChild | - Component::OnlyChild | - Component::Empty | - Component::NthChild(_, _) | - Component::NthLastChild(_, _) | - Component::NthOfType(_, _) | - Component::NthLastOfType(_, _) | - Component::FirstOfType | - Component::LastOfType | - Component::OnlyOfType => false, - Component::NonTSPseudoClass(ref pseudo_class) => { - Impl::is_active_or_hover(pseudo_class) - }, - _ => true, - } - }); - } +/// Holds per-compound-selector data. +struct LocalMatchingContext<'a, 'b: 'a> { + shared: &'a mut MatchingContext<'b>, + matches_hover_and_active_quirk: bool, } -pub fn matches_selector_list<E>(selector_list: &SelectorList<E::Impl>, - element: &E, - context: &mut MatchingContext) - -> bool - where E: Element +pub fn matches_selector_list<E>( + selector_list: &SelectorList<E::Impl>, + element: &E, + context: &mut MatchingContext, +) -> bool +where + E: Element { selector_list.0.iter().any(|selector| { matches_selector(selector, @@ -176,10 +79,9 @@ pub fn matches_selector_list<E>(selector_list: &SelectorList<E::Impl>, } #[inline(always)] -fn may_match<E>(hashes: &AncestorHashes, - bf: &BloomFilter) - -> bool - where E: Element, +fn may_match<E>(hashes: &AncestorHashes, bf: &BloomFilter) -> bool +where + E: Element, { // Check the first three hashes. Note that we can check for zero before // masking off the high bits, since if any of the first three hashes is @@ -370,15 +272,17 @@ enum SelectorMatchingResult { /// unncessary cache miss for cases when we can fast-reject with AncestorHashes /// (which the caller can store inline with the selector pointer). #[inline(always)] -pub fn matches_selector<E, F>(selector: &Selector<E::Impl>, - offset: usize, - hashes: Option<&AncestorHashes>, - element: &E, - context: &mut MatchingContext, - flags_setter: &mut F) - -> bool - where E: Element, - F: FnMut(&E, ElementSelectorFlags), +pub fn matches_selector<E, F>( + selector: &Selector<E::Impl>, + offset: usize, + hashes: Option<&AncestorHashes>, + element: &E, + context: &mut MatchingContext, + flags_setter: &mut F, +) -> bool +where + E: Element, + F: FnMut(&E, ElementSelectorFlags), { // Use the bloom filter to fast-reject. if let Some(hashes) = hashes { @@ -389,13 +293,7 @@ pub fn matches_selector<E, F>(selector: &Selector<E::Impl>, } } - let mut local_context = LocalMatchingContext::new(context, selector); - let iter = if offset == 0 { - selector.iter() - } else { - selector.iter_from(offset) - }; - matches_complex_selector(iter, element, &mut local_context, flags_setter) + matches_complex_selector(selector.iter_from(offset), element, context, flags_setter) } /// Whether a compound selector matched, and whether it was the rightmost @@ -431,7 +329,11 @@ where selector.combinator_at(from_offset); // This asserts. } - let mut local_context = LocalMatchingContext::new(context, selector); + let mut local_context = LocalMatchingContext { + shared: context, + matches_hover_and_active_quirk: false, + }; + for component in selector.iter_raw_parse_order_from(from_offset - 1) { if matches!(*component, Component::Combinator(..)) { return CompoundSelectorMatchingResult::Matched { @@ -457,27 +359,20 @@ where } /// Matches a complex selector. -pub fn matches_complex_selector<E, F>(mut iter: SelectorIter<E::Impl>, - element: &E, - context: &mut LocalMatchingContext<E::Impl>, - flags_setter: &mut F) - -> bool - where E: Element, - F: FnMut(&E, ElementSelectorFlags), +pub fn matches_complex_selector<E, F>( + mut iter: SelectorIter<E::Impl>, + element: &E, + context: &mut MatchingContext, + flags_setter: &mut F, +) -> bool +where + E: Element, + F: FnMut(&E, ElementSelectorFlags), { - if cfg!(debug_assertions) { - if context.nesting_level == 0 && - context.shared.matching_mode == MatchingMode::ForStatelessPseudoElement { - assert!(iter.clone().any(|c| { - matches!(*c, Component::PseudoElement(..)) - })); - } - } - // If this is the special pseudo-element mode, consume the ::pseudo-element // before proceeding, since the caller has already handled that part. if context.nesting_level == 0 && - context.shared.matching_mode == MatchingMode::ForStatelessPseudoElement { + context.matching_mode == MatchingMode::ForStatelessPseudoElement { // Consume the pseudo. let pseudo = iter.next().unwrap(); debug_assert!(matches!(*pseudo, Component::PseudoElement(..)), @@ -491,41 +386,119 @@ pub fn matches_complex_selector<E, F>(mut iter: SelectorIter<E::Impl>, return false; } - // Advance to the non-pseudo-element part of the selector, and inform - // the context. + // Advance to the non-pseudo-element part of the selector, but let the + // context note that . if iter.next_sequence().is_none() { return true; } - context.note_position(&iter); } - match matches_complex_selector_internal(iter, - element, - context, - &mut RelevantLinkStatus::Looking, - flags_setter) { + let result = matches_complex_selector_internal( + iter, + element, + context, + &mut RelevantLinkStatus::Looking, + flags_setter, + Rightmost::Yes, + ); + + match result { SelectorMatchingResult::Matched => true, _ => false } } -fn matches_complex_selector_internal<E, F>(mut selector_iter: SelectorIter<E::Impl>, - element: &E, - context: &mut LocalMatchingContext<E::Impl>, - relevant_link: &mut RelevantLinkStatus, - flags_setter: &mut F) - -> SelectorMatchingResult - where E: Element, - F: FnMut(&E, ElementSelectorFlags), +#[inline] +fn matches_hover_and_active_quirk<Impl: SelectorImpl>( + selector_iter: &SelectorIter<Impl>, + context: &MatchingContext, + rightmost: Rightmost, +) -> bool { + if context.quirks_mode() != QuirksMode::Quirks { + return false; + } + + if context.nesting_level != 0 { + return false; + } + + // This compound selector had a pseudo-element to the right that we + // intentionally skipped. + if matches!(rightmost, Rightmost::Yes) && + context.matching_mode == MatchingMode::ForStatelessPseudoElement { + return false; + } + + selector_iter.clone().all(|simple| { + match *simple { + Component::LocalName(_) | + Component::AttributeInNoNamespaceExists { .. } | + Component::AttributeInNoNamespace { .. } | + Component::AttributeOther(_) | + Component::ID(_) | + Component::Class(_) | + Component::PseudoElement(_) | + Component::Negation(_) | + Component::FirstChild | + Component::LastChild | + Component::OnlyChild | + Component::Empty | + Component::NthChild(_, _) | + Component::NthLastChild(_, _) | + Component::NthOfType(_, _) | + Component::NthLastOfType(_, _) | + Component::FirstOfType | + Component::LastOfType | + Component::OnlyOfType => false, + Component::NonTSPseudoClass(ref pseudo_class) => { + Impl::is_active_or_hover(pseudo_class) + }, + _ => true, + } + }) +} + +enum Rightmost { + Yes, + No, +} + +fn matches_complex_selector_internal<E, F>( + mut selector_iter: SelectorIter<E::Impl>, + element: &E, + context: &mut MatchingContext, + relevant_link: &mut RelevantLinkStatus, + flags_setter: &mut F, + rightmost: Rightmost, +) -> SelectorMatchingResult +where + E: Element, + F: FnMut(&E, ElementSelectorFlags), { - *relevant_link = relevant_link.examine_potential_link(element, &mut context.shared); + *relevant_link = relevant_link.examine_potential_link(element, context); debug!("Matching complex selector {:?} for {:?}, relevant link {:?}", selector_iter, element, relevant_link); - let matches_all_simple_selectors = selector_iter.all(|simple| { - matches_simple_selector(simple, element, context, &relevant_link, flags_setter) - }); + + let matches_all_simple_selectors = { + let matches_hover_and_active_quirk = + matches_hover_and_active_quirk(&selector_iter, context, rightmost); + let mut local_context = + LocalMatchingContext { + shared: context, + matches_hover_and_active_quirk, + }; + selector_iter.all(|simple| { + matches_simple_selector( + simple, + element, + &mut local_context, + &relevant_link, + flags_setter, + ) + }) + }; let combinator = selector_iter.next_sequence(); let siblings = combinator.map_or(false, |c| c.is_sibling()); @@ -567,13 +540,14 @@ fn matches_complex_selector_internal<E, F>(mut selector_iter: SelectorIter<E::Im None => return candidate_not_found, Some(next_element) => next_element, }; - // Note in which compound selector are we currently. - context.note_position(&selector_iter); - let result = matches_complex_selector_internal(selector_iter.clone(), - &element, - context, - relevant_link, - flags_setter); + let result = matches_complex_selector_internal( + selector_iter.clone(), + &element, + context, + relevant_link, + flags_setter, + Rightmost::No, + ); match (result, c) { // Return the status immediately. (SelectorMatchingResult::Matched, _) => return result, @@ -614,14 +588,15 @@ fn matches_complex_selector_internal<E, F>(mut selector_iter: SelectorIter<E::Im /// Determines whether the given element matches the given single selector. #[inline] fn matches_simple_selector<E, F>( - selector: &Component<E::Impl>, - element: &E, - context: &mut LocalMatchingContext<E::Impl>, - relevant_link: &RelevantLinkStatus, - flags_setter: &mut F) - -> bool - where E: Element, - F: FnMut(&E, ElementSelectorFlags), + selector: &Component<E::Impl>, + element: &E, + context: &mut LocalMatchingContext, + relevant_link: &RelevantLinkStatus, + flags_setter: &mut F, +) -> bool +where + E: Element, + F: FnMut(&E, ElementSelectorFlags), { match *selector { Component::Combinator(_) => unreachable!(), @@ -705,7 +680,14 @@ fn matches_simple_selector<E, F>( ) } Component::NonTSPseudoClass(ref pc) => { - element.match_non_ts_pseudo_class(pc, context, relevant_link, flags_setter) + if context.matches_hover_and_active_quirk && + context.shared.nesting_level == 0 && + E::Impl::is_active_or_hover(pc) && + !element.is_link() { + return false; + } + + element.match_non_ts_pseudo_class(pc, &mut context.shared, relevant_link, flags_setter) } Component::FirstChild => { matches_first_child(element, flags_setter) @@ -753,12 +735,17 @@ fn matches_simple_selector<E, F>( matches_generic_nth_child(element, context, 0, 1, true, true, flags_setter) } Component::Negation(ref negated) => { - context.nesting_level += 1; + context.shared.nesting_level += 1; let result = !negated.iter().all(|ss| { - matches_simple_selector(ss, element, context, - relevant_link, flags_setter) + matches_simple_selector( + ss, + element, + context, + relevant_link, + flags_setter, + ) }); - context.nesting_level -= 1; + context.shared.nesting_level -= 1; result } } @@ -773,16 +760,18 @@ fn select_name<'a, T>(is_html: bool, local_name: &'a T, local_name_lower: &'a T) } #[inline] -fn matches_generic_nth_child<E, F>(element: &E, - context: &mut LocalMatchingContext<E::Impl>, - a: i32, - b: i32, - is_of_type: bool, - is_from_end: bool, - flags_setter: &mut F) - -> bool - where E: Element, - F: FnMut(&E, ElementSelectorFlags), +fn matches_generic_nth_child<E, F>( + element: &E, + context: &mut LocalMatchingContext, + a: i32, + b: i32, + is_of_type: bool, + is_from_end: bool, + flags_setter: &mut F, +) -> bool +where + E: Element, + F: FnMut(&E, ElementSelectorFlags), { if element.ignores_nth_child_selectors() { return false; @@ -880,8 +869,9 @@ where #[inline] fn matches_first_child<E, F>(element: &E, flags_setter: &mut F) -> bool - where E: Element, - F: FnMut(&E, ElementSelectorFlags), +where + E: Element, + F: FnMut(&E, ElementSelectorFlags), { flags_setter(element, HAS_EDGE_CHILD_SELECTOR); element.prev_sibling_element().is_none() @@ -889,8 +879,9 @@ fn matches_first_child<E, F>(element: &E, flags_setter: &mut F) -> bool #[inline] fn matches_last_child<E, F>(element: &E, flags_setter: &mut F) -> bool - where E: Element, - F: FnMut(&E, ElementSelectorFlags), +where + E: Element, + F: FnMut(&E, ElementSelectorFlags), { flags_setter(element, HAS_EDGE_CHILD_SELECTOR); element.next_sibling_element().is_none() diff --git a/components/selectors/tree.rs b/components/selectors/tree.rs index 958311ad0d8..d99804c8675 100644 --- a/components/selectors/tree.rs +++ b/components/selectors/tree.rs @@ -6,7 +6,7 @@ //! between layout and style. use attr::{AttrSelectorOperation, NamespaceConstraint, CaseSensitivity}; -use matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext, RelevantLinkStatus}; +use matching::{ElementSelectorFlags, MatchingContext, RelevantLinkStatus}; use parser::SelectorImpl; use servo_arc::NonZeroPtrMut; use std::fmt::Debug; @@ -64,12 +64,15 @@ pub trait Element: Sized + Clone + Debug { operation: &AttrSelectorOperation<&<Self::Impl as SelectorImpl>::AttrValue>) -> bool; - fn match_non_ts_pseudo_class<F>(&self, - pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass, - context: &mut LocalMatchingContext<Self::Impl>, - relevant_link: &RelevantLinkStatus, - flags_setter: &mut F) -> bool - where F: FnMut(&Self, ElementSelectorFlags); + fn match_non_ts_pseudo_class<F>( + &self, + pc: &<Self::Impl as SelectorImpl>::NonTSPseudoClass, + context: &mut MatchingContext, + relevant_link: &RelevantLinkStatus, + flags_setter: &mut F, + ) -> bool + where + F: FnMut(&Self, ElementSelectorFlags); fn match_pseudo_element(&self, pe: &<Self::Impl as SelectorImpl>::PseudoElement, diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 66f53fc2e77..052fb627f9e 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -78,7 +78,7 @@ use rule_tree::CascadeLevel as ServoCascadeLevel; use selector_parser::{AttrValue, ElementExt, PseudoClassStringArg}; use selectors::{Element, OpaqueElement}; use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator, CaseSensitivity, NamespaceConstraint}; -use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext}; +use selectors::matching::{ElementSelectorFlags, MatchingContext}; use selectors::matching::{RelevantLinkStatus, VisitedHandlingMode}; use selectors::sink::Push; use servo_arc::{Arc, ArcBorrow, RawOffsetArc}; @@ -1844,7 +1844,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { fn match_non_ts_pseudo_class<F>( &self, pseudo_class: &NonTSPseudoClass, - context: &mut LocalMatchingContext<Self::Impl>, + context: &mut MatchingContext, relevant_link: &RelevantLinkStatus, flags_setter: &mut F, ) -> bool @@ -1899,20 +1899,14 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { NonTSPseudoClass::MozDirAttrRTL | NonTSPseudoClass::MozDirAttrLikeAuto | NonTSPseudoClass::MozAutofill | + NonTSPseudoClass::Active | + NonTSPseudoClass::Hover | NonTSPseudoClass::MozAutofillPreview => { self.get_state().intersects(pseudo_class.state_flag()) }, NonTSPseudoClass::AnyLink => self.is_link(), - NonTSPseudoClass::Link => relevant_link.is_unvisited(self, context.shared), - NonTSPseudoClass::Visited => relevant_link.is_visited(self, context.shared), - NonTSPseudoClass::Active | - NonTSPseudoClass::Hover => { - if context.active_hover_quirk_matches() && !self.is_link() { - false - } else { - self.get_state().contains(pseudo_class.state_flag()) - } - }, + NonTSPseudoClass::Link => relevant_link.is_unvisited(self, context), + NonTSPseudoClass::Visited => relevant_link.is_visited(self, context), NonTSPseudoClass::MozFirstNode => { flags_setter(self, HAS_EDGE_CHILD_SELECTOR); let mut elem = self.as_node(); diff --git a/components/style/invalidation/element/element_wrapper.rs b/components/style/invalidation/element/element_wrapper.rs index 705da44840c..294f878cd20 100644 --- a/components/style/invalidation/element/element_wrapper.rs +++ b/components/style/invalidation/element/element_wrapper.rs @@ -11,7 +11,7 @@ use element_state::ElementState; use selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl, Snapshot, SnapshotMap, AttrValue}; use selectors::{Element, OpaqueElement}; use selectors::attr::{AttrSelectorOperation, CaseSensitivity, NamespaceConstraint}; -use selectors::matching::{ElementSelectorFlags, LocalMatchingContext, MatchingContext}; +use selectors::matching::{ElementSelectorFlags, MatchingContext}; use selectors::matching::RelevantLinkStatus; use std::cell::Cell; use std::fmt; @@ -149,13 +149,15 @@ impl<'a, E> Element for ElementWrapper<'a, E> { type Impl = SelectorImpl; - fn match_non_ts_pseudo_class<F>(&self, - pseudo_class: &NonTSPseudoClass, - context: &mut LocalMatchingContext<Self::Impl>, - relevant_link: &RelevantLinkStatus, - _setter: &mut F) - -> bool - where F: FnMut(&Self, ElementSelectorFlags), + fn match_non_ts_pseudo_class<F>( + &self, + pseudo_class: &NonTSPseudoClass, + context: &mut MatchingContext, + relevant_link: &RelevantLinkStatus, + _setter: &mut F, + ) -> bool + where + F: FnMut(&Self, ElementSelectorFlags), { // Some pseudo-classes need special handling to evaluate them against // the snapshot. @@ -163,9 +165,12 @@ impl<'a, E> Element for ElementWrapper<'a, E> #[cfg(feature = "gecko")] NonTSPseudoClass::MozAny(ref selectors) => { use selectors::matching::matches_complex_selector; - return selectors.iter().any(|s| { + context.nesting_level += 1; + let result = 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 @@ -195,10 +200,10 @@ impl<'a, E> Element for ElementWrapper<'a, E> // state directly. Instead, we use the `relevant_link` to determine if // they match. NonTSPseudoClass::Link => { - return relevant_link.is_unvisited(self, context.shared); + return relevant_link.is_unvisited(self, context); } NonTSPseudoClass::Visited => { - return relevant_link.is_visited(self, context.shared); + return relevant_link.is_visited(self, context); } #[cfg(feature = "gecko")] @@ -230,27 +235,31 @@ impl<'a, E> Element for ElementWrapper<'a, E> let flag = pseudo_class.state_flag(); if flag.is_empty() { - return self.element.match_non_ts_pseudo_class(pseudo_class, - context, - relevant_link, - &mut |_, _| {}) + return self.element.match_non_ts_pseudo_class( + pseudo_class, + context, + relevant_link, + &mut |_, _| {}, + ) } match self.snapshot().and_then(|s| s.state()) { Some(snapshot_state) => snapshot_state.intersects(flag), None => { - self.element.match_non_ts_pseudo_class(pseudo_class, - context, - relevant_link, - &mut |_, _| {}) + self.element.match_non_ts_pseudo_class( + pseudo_class, + context, + relevant_link, + &mut |_, _| {}, + ) } } } - fn match_pseudo_element(&self, - pseudo_element: &PseudoElement, - context: &mut MatchingContext) - -> bool - { + fn match_pseudo_element( + &self, + pseudo_element: &PseudoElement, + context: &mut MatchingContext, + ) -> bool { self.element.match_pseudo_element(pseudo_element, context) } diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 710f0cb56a0..324bf2301af 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -2309,12 +2309,12 @@ impl Rule { } /// Creates a new Rule. - pub fn new(selector: Selector<SelectorImpl>, - hashes: AncestorHashes, - style_rule: Arc<Locked<StyleRule>>, - source_order: u32) - -> Self - { + pub fn new( + selector: Selector<SelectorImpl>, + hashes: AncestorHashes, + style_rule: Arc<Locked<StyleRule>>, + source_order: u32, + ) -> Self { Rule { selector: selector, hashes: hashes, |