diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index d4656f0c7fb..c87c2682aaa 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -9,6 +9,7 @@ use element_state::{DocumentState, ElementState}; use gecko_bindings::structs::{self, CSSPseudoClassType}; use gecko_bindings::structs::RawServoSelectorList; use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI}; +use invalidation::element::document_state::InvalidationMatchingData; use selector_parser::{Direction, SelectorParser}; use selectors::SelectorList; use selectors::parser::{self as selector_parser, Selector, SelectorMethods, SelectorParseErrorKind}; @@ -277,13 +278,6 @@ impl NonTSPseudoClass { #[derive(Clone, Debug, Eq, PartialEq)] pub struct SelectorImpl; -/// A struct holding the members necessary to invalidate document state -/// selectors. -pub struct InvalidationMatchingData { - /// The document state that has changed, which makes it always match. - pub document_state: DocumentState, -} - impl ::selectors::SelectorImpl for SelectorImpl { type ExtraMatchingData = InvalidationMatchingData; type AttrValue = Atom; diff --git a/components/style/invalidation/element/document_state.rs b/components/style/invalidation/element/document_state.rs new file mode 100644 index 00000000000..8262f249d6f --- /dev/null +++ b/components/style/invalidation/element/document_state.rs @@ -0,0 +1,98 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! An invalidation processor for style changes due to document state changes. + +use dom::TElement; +use element_state::DocumentState; +use invalidation::element::invalidator::{DescendantInvalidationLists, InvalidationVector}; +use invalidation::element::invalidator::{Invalidation, InvalidationProcessor}; +use invalidation::element::state_and_attributes; +use selectors::matching::{MatchingContext, MatchingMode, QuirksMode, VisitedHandlingMode}; +use stylist::StyleRuleCascadeData; + +/// A struct holding the members necessary to invalidate document state +/// selectors. +pub struct InvalidationMatchingData { + /// The document state that has changed, which makes it always match. + pub document_state: DocumentState, +} + +/// An invalidation processor for style changes due to state and attribute +/// changes. +pub struct DocumentStateInvalidationProcessor<'a, E: TElement> { + rules: &'a StyleRuleCascadeData, + matching_context: MatchingContext<'a, E::Impl>, + document_states_changed: DocumentState, +} + +impl<'a, E: TElement> DocumentStateInvalidationProcessor<'a, E> { + /// Creates a new DocumentStateInvalidationProcessor. + #[inline] + pub fn new( + rules: &'a StyleRuleCascadeData, + document_states_changed: DocumentState, + quirks_mode: QuirksMode, + ) -> Self { + let mut matching_context = MatchingContext::new_for_visited( + MatchingMode::Normal, + None, + None, + VisitedHandlingMode::AllLinksVisitedAndUnvisited, + quirks_mode, + ); + + matching_context.extra_data = Some(InvalidationMatchingData { + document_state: document_states_changed, + }); + + Self { rules, document_states_changed, matching_context } + } +} + +impl<'a, E: TElement> InvalidationProcessor<'a, E> for DocumentStateInvalidationProcessor<'a, E> { + fn collect_invalidations( + &mut self, + _element: E, + self_invalidations: &mut InvalidationVector<'a>, + _descendant_invalidations: &mut DescendantInvalidationLists<'a>, + _sibling_invalidations: &mut InvalidationVector<'a>, + ) -> bool { + let map = self.rules.invalidation_map(); + + for dependency in &map.document_state_selectors { + if !dependency.state.intersects(self.document_states_changed) { + continue; + } + + self_invalidations.push(Invalidation::new(&dependency.selector, 0)); + } + + false + } + + fn matching_context(&mut self) -> &mut MatchingContext<'a, E::Impl> { + &mut self.matching_context + } + + fn recursion_limit_exceeded(&mut self, _: E) { + unreachable!("We don't run document state invalidation with stack limits") + } + + fn should_process_descendants(&mut self, element: E) -> bool { + let data = match element.borrow_data() { + Some(d) => d, + None => return false, + }; + state_and_attributes::should_process_descendants(&data) + } + + fn invalidated_descendants(&mut self, element: E, child: E) { + state_and_attributes::invalidated_descendants(element, child) + } + + fn invalidated_self(&mut self, element: E) { + state_and_attributes::invalidated_self(element); + } +} diff --git a/components/style/invalidation/element/mod.rs b/components/style/invalidation/element/mod.rs index 52e4bd38844..f80d9af65a7 100644 --- a/components/style/invalidation/element/mod.rs +++ b/components/style/invalidation/element/mod.rs @@ -4,6 +4,7 @@ //! Invalidation of element styles due to attribute or style changes. +pub mod document_state; pub mod element_wrapper; pub mod invalidation_map; pub mod invalidator; diff --git a/components/style/lib.rs b/components/style/lib.rs index 01e9cb7f191..d4d3855a481 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -26,8 +26,6 @@ #![deny(warnings)] #![deny(missing_docs)] -#![cfg_attr(feature = "servo", feature(never_type))] - #![recursion_limit = "500"] // For define_css_keyword_enum! in -moz-appearance extern crate app_units; diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index b9b3a5a3b20..dbedda39590 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -12,6 +12,7 @@ use cssparser::{Parser as CssParser, ToCss, serialize_identifier, CowRcStr, Sour use dom::{OpaqueNode, TElement, TNode}; use element_state::{DocumentState, ElementState}; use fnv::FnvHashMap; +use invalidation::element::document_state::InvalidationMatchingData; use invalidation::element::element_wrapper::ElementSnapshot; use properties::ComputedValues; use properties::PropertyFlags; @@ -377,7 +378,7 @@ impl ::selectors::SelectorImpl for SelectorImpl { type PseudoElement = PseudoElement; type NonTSPseudoClass = NonTSPseudoClass; - type ExtraMatchingData = !; + type ExtraMatchingData = InvalidationMatchingData; type AttrValue = String; type Identifier = Atom; type ClassName = Atom;