From 1e27f2883b92e717bd44bb05fd012df8d4f532c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 11 Jan 2018 12:07:24 +0100 Subject: [PATCH 1/8] selectors: Allow defining an implementation-dependent field in the matching context. --- components/selectors/context.rs | 4 ++++ components/selectors/parser.rs | 2 ++ components/selectors/size_of_tests.rs | 1 + components/style/gecko/selector_parser.rs | 1 + components/style/lib.rs | 2 ++ components/style/servo/selector_parser.rs | 1 + 6 files changed, 11 insertions(+) diff --git a/components/selectors/context.rs b/components/selectors/context.rs index ca7a2bfcb60..79e0b69b4e8 100644 --- a/components/selectors/context.rs +++ b/components/selectors/context.rs @@ -130,6 +130,9 @@ where /// should match when matching_mode is ForStatelessPseudoElement. pub pseudo_element_matching_fn: Option<&'a Fn(&Impl::PseudoElement) -> bool>, + /// Extra implementation-dependent matching data. + pub extra_data: Option, + quirks_mode: QuirksMode, classes_and_ids_case_sensitivity: CaseSensitivity, _impl: ::std::marker::PhantomData, @@ -173,6 +176,7 @@ where scope_element: None, nesting_level: 0, pseudo_element_matching_fn: None, + extra_data: None, _impl: ::std::marker::PhantomData, } } diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index a6902d105c7..dead7875d0f 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -84,6 +84,7 @@ macro_rules! with_all_bounds { /// are parameterized on SelectorImpl. See /// pub trait SelectorImpl: Clone + Sized + 'static { + type ExtraMatchingData: Sized + 'static; type AttrValue: $($InSelector)*; type Identifier: $($InSelector)* + PrecomputedHash; type ClassName: $($InSelector)* + PrecomputedHash; @@ -2027,6 +2028,7 @@ pub mod tests { } impl SelectorImpl for DummySelectorImpl { + type ExtraMatchingData = (); type AttrValue = DummyAtom; type Identifier = DummyAtom; type ClassName = DummyAtom; diff --git a/components/selectors/size_of_tests.rs b/components/selectors/size_of_tests.rs index 46b966ec5f3..8f0d6da94ef 100644 --- a/components/selectors/size_of_tests.rs +++ b/components/selectors/size_of_tests.rs @@ -24,6 +24,7 @@ impl parser::PseudoElement for gecko_like_types::PseudoElement { // Boilerplate impl SelectorImpl for Impl { + type ExtraMatchingData = u64; type AttrValue = Atom; type Identifier = Atom; type ClassName = Atom; diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index b70054fe84a..417e5caec99 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -278,6 +278,7 @@ impl NonTSPseudoClass { pub struct SelectorImpl; impl ::selectors::SelectorImpl for SelectorImpl { + type ExtraMatchingData = (); type AttrValue = Atom; type Identifier = Atom; type ClassName = Atom; diff --git a/components/style/lib.rs b/components/style/lib.rs index d4d3855a481..01e9cb7f191 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -26,6 +26,8 @@ #![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 a06de17734e..b9b3a5a3b20 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -377,6 +377,7 @@ impl ::selectors::SelectorImpl for SelectorImpl { type PseudoElement = PseudoElement; type NonTSPseudoClass = NonTSPseudoClass; + type ExtraMatchingData = !; type AttrValue = String; type Identifier = Atom; type ClassName = Atom; From cb1a951477165f147ceff4eed35ea1b2ea664779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 11 Jan 2018 12:37:47 +0100 Subject: [PATCH 2/8] style: Allow storing a DocumentState for invalidation. --- components/style/gecko/selector_parser.rs | 9 ++++++++- components/style/gecko/wrapper.rs | 23 ++++++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index 417e5caec99..d4656f0c7fb 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -277,8 +277,15 @@ 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 = (); + type ExtraMatchingData = InvalidationMatchingData; type AttrValue = Atom; type Identifier = Atom; type ClassName = Atom; diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 56ad17e6009..4de36a327d4 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -2110,8 +2110,14 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { self.get_document_theme() == DocumentTheme::Doc_Theme_Dark } NonTSPseudoClass::MozWindowInactive => { - self.document_state() - .contains(DocumentState::NS_DOCUMENT_STATE_WINDOW_INACTIVE) + let state_bit = DocumentState::NS_DOCUMENT_STATE_WINDOW_INACTIVE; + if let Some(ref invalidation_data) = context.extra_data { + if invalidation_data.document_state.intersects(state_bit) { + return true; + } + } + + self.document_state().contains(state_bit) } NonTSPseudoClass::MozPlaceholder => false, NonTSPseudoClass::MozAny(ref sels) => { @@ -2126,9 +2132,16 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { self.match_element_lang(None, lang_arg) } NonTSPseudoClass::MozLocaleDir(ref dir) => { - let doc_is_rtl = - self.document_state() - .contains(DocumentState::NS_DOCUMENT_STATE_RTL_LOCALE); + let state_bit = DocumentState::NS_DOCUMENT_STATE_RTL_LOCALE; + if let Some(ref invalidation_data) = context.extra_data { + // NOTE(emilio): We could still return false for + // Direction::Other(..), but we don't bother. + if invalidation_data.document_state.intersects(state_bit) { + return true; + } + } + + let doc_is_rtl = self.document_state().contains(state_bit); match **dir { Direction::Ltr => !doc_is_rtl, From 14661e470f041d6b38862203135912c77a1f4b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 11 Jan 2018 15:40:02 +0100 Subject: [PATCH 3/8] style: Add a couple FIXMEs I've noticed while working on this. ::slotted is hard. --- components/style/data.rs | 2 ++ components/style/invalidation/element/invalidator.rs | 3 +++ 2 files changed, 5 insertions(+) diff --git a/components/style/data.rs b/components/style/data.rs index 56f2de5beb6..56efedc41f0 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -262,6 +262,8 @@ impl ElementData { } let mut xbl_stylists = SmallVec::<[_; 3]>::new(); + // FIXME(emilio): This is wrong, needs to account for ::slotted rules + // that may apply to elements down the tree. let cut_off_inheritance = element.each_applicable_non_document_style_rule_data(|data, quirks_mode| { xbl_stylists.push((data, quirks_mode)) diff --git a/components/style/invalidation/element/invalidator.rs b/components/style/invalidation/element/invalidator.rs index 14aa084a1b0..3e2866ddca8 100644 --- a/components/style/invalidation/element/invalidator.rs +++ b/components/style/invalidation/element/invalidator.rs @@ -505,6 +505,9 @@ where DescendantInvalidationKind::Slotted, ); + // FIXME(emilio): Need to handle nested slotted nodes if `element` + // is itself a . + debug_assert!( sibling_invalidations.is_empty(), "::slotted() shouldn't have sibling combinators to the right, \ From 2c1d72ad1a2e788daf8db0014602ee9640fa4d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 11 Jan 2018 15:40:37 +0100 Subject: [PATCH 4/8] style: Track document state dependencies in the invalidation maps. --- .../invalidation/element/invalidation_map.rs | 43 +++++++++++++++++-- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/components/style/invalidation/element/invalidation_map.rs b/components/style/invalidation/element/invalidation_map.rs index 809d3eb4a78..9cbfcb77e8b 100644 --- a/components/style/invalidation/element/invalidation_map.rs +++ b/components/style/invalidation/element/invalidation_map.rs @@ -6,7 +6,7 @@ use {Atom, LocalName, Namespace}; use context::QuirksMode; -use element_state::ElementState; +use element_state::{DocumentState, ElementState}; use fallible::FallibleVec; use hashglobe::FailedAllocationError; use selector_map::{MaybeCaseInsensitiveHashMap, SelectorMap, SelectorMapEntry}; @@ -133,6 +133,19 @@ impl SelectorMapEntry for StateDependency { } } +/// The same, but for document state selectors. +#[derive(Clone, Debug, MallocSizeOf)] +pub struct DocumentStateDependency { + /// The selector that is affected. We don't need to track an offset, since + /// when it changes it changes for the whole document anyway. + #[cfg_attr(feature = "gecko", + ignore_malloc_size_of = "CssRules have primary refs, we measure there")] + #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")] + pub selector: Selector, + /// The state this dependency is affected by. + pub state: DocumentState, +} + /// A map where we store invalidations. /// /// This is slightly different to a SelectorMap, in the sense of that the same @@ -151,6 +164,8 @@ pub struct InvalidationMap { pub id_to_selector: MaybeCaseInsensitiveHashMap>, /// A map of all the state dependencies. pub state_affecting_selectors: SelectorMap, + /// A list of document state dependencies in the rules we represent. + pub document_state_selectors: Vec, /// A map of other attribute affecting selectors. pub other_attribute_affecting_selectors: SelectorMap, /// Whether there are attribute rules of the form `[class~="foo"]` that may @@ -172,6 +187,7 @@ impl InvalidationMap { class_to_selector: MaybeCaseInsensitiveHashMap::new(), id_to_selector: MaybeCaseInsensitiveHashMap::new(), state_affecting_selectors: SelectorMap::new(), + document_state_selectors: Vec::new(), other_attribute_affecting_selectors: SelectorMap::new(), has_class_attribute_selectors: false, has_id_attribute_selectors: false, @@ -181,6 +197,7 @@ impl InvalidationMap { /// Returns the number of dependencies stored in the invalidation map. pub fn len(&self) -> usize { self.state_affecting_selectors.len() + + self.document_state_selectors.len() + self.other_attribute_affecting_selectors.len() + self.id_to_selector.iter().fold(0, |accum, (_, ref v)| { accum + v.len() @@ -195,7 +212,7 @@ impl InvalidationMap { pub fn note_selector( &mut self, selector: &Selector, - quirks_mode: QuirksMode + quirks_mode: QuirksMode, ) -> Result<(), FailedAllocationError> { self.collect_invalidations_for(selector, quirks_mode) } @@ -205,6 +222,7 @@ impl InvalidationMap { self.class_to_selector.clear(); self.id_to_selector.clear(); self.state_affecting_selectors.clear(); + self.document_state_selectors.clear(); self.other_attribute_affecting_selectors.clear(); self.has_id_attribute_selectors = false; self.has_class_attribute_selectors = false; @@ -222,6 +240,8 @@ impl InvalidationMap { let mut combinator; let mut index = 0; + let mut document_state = DocumentState::empty(); + loop { let sequence_start = index; @@ -229,6 +249,7 @@ impl InvalidationMap { classes: SmallVec::new(), ids: SmallVec::new(), state: ElementState::empty(), + document_state: &mut document_state, other_attributes: false, has_id_attribute_selectors: false, has_class_attribute_selectors: false, @@ -297,15 +318,28 @@ impl InvalidationMap { index += 1; // Account for the combinator. } + if !document_state.is_empty() { + self.document_state_selectors.try_push(DocumentStateDependency { + state: document_state, + selector: selector.clone(), + })?; + } + Ok(()) } } /// A struct that collects invalidations for a given compound selector. -struct CompoundSelectorDependencyCollector { +struct CompoundSelectorDependencyCollector<'a> { /// The state this compound selector is affected by. state: ElementState, + /// The document this _complex_ selector is affected by. + /// + /// We don't need to track state per compound selector, since it's global + /// state and it changes for everything. + document_state: &'a mut DocumentState, + /// The classes this compound selector is affected by. /// /// NB: This will be often a single class, but could be multiple in @@ -330,7 +364,7 @@ struct CompoundSelectorDependencyCollector { has_class_attribute_selectors: bool, } -impl SelectorVisitor for CompoundSelectorDependencyCollector { +impl<'a> SelectorVisitor for CompoundSelectorDependencyCollector<'a> { type Impl = SelectorImpl; fn visit_simple_selector(&mut self, s: &Component) -> bool { @@ -353,6 +387,7 @@ impl SelectorVisitor for CompoundSelectorDependencyCollector { } _ => pc.state_flag(), }; + *self.document_state |= pc.document_state_flag(); } _ => {} } From 5b7d9eb94aa7e84498fcd654b346c9f5e0d972ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 11 Jan 2018 15:53:36 +0100 Subject: [PATCH 5/8] style: Add a document state invalidator. --- components/style/gecko/selector_parser.rs | 8 +- .../invalidation/element/document_state.rs | 98 +++++++++++++++++++ components/style/invalidation/element/mod.rs | 1 + components/style/lib.rs | 2 - components/style/servo/selector_parser.rs | 3 +- 5 files changed, 102 insertions(+), 10 deletions(-) create mode 100644 components/style/invalidation/element/document_state.rs 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; From a69d2296156e16d5a766237c8cb16357c87cd47e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 12 Jan 2018 10:32:50 +0100 Subject: [PATCH 6/8] style: Use a more compact form for should_process_descendants. --- components/style/invalidation/element/document_state.rs | 9 ++++----- .../style/invalidation/element/state_and_attributes.rs | 8 +++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/components/style/invalidation/element/document_state.rs b/components/style/invalidation/element/document_state.rs index 8262f249d6f..253b9b4cc43 100644 --- a/components/style/invalidation/element/document_state.rs +++ b/components/style/invalidation/element/document_state.rs @@ -81,11 +81,10 @@ impl<'a, E: TElement> InvalidationProcessor<'a, E> for DocumentStateInvalidation } 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) + match element.borrow_data() { + Some(d) => state_and_attributes::should_process_descendants(&d), + None => false, + } } fn invalidated_descendants(&mut self, element: E, child: E) { diff --git a/components/style/invalidation/element/state_and_attributes.rs b/components/style/invalidation/element/state_and_attributes.rs index 37d6fc675b2..fd93062eadd 100644 --- a/components/style/invalidation/element/state_and_attributes.rs +++ b/components/style/invalidation/element/state_and_attributes.rs @@ -298,12 +298,10 @@ where return should_process_descendants(&self.data) } - let data = match element.borrow_data() { - Some(d) => d, + match element.borrow_data() { + Some(d) => should_process_descendants(&d), None => return false, - }; - - should_process_descendants(&data) + } } fn recursion_limit_exceeded(&mut self, element: E) { From 9a1f20f1e8376e3876c1d74aaa9d8e14ed9bccb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 12 Jan 2018 10:38:09 +0100 Subject: [PATCH 7/8] style: Add a comment about figuring out what the best way to deal with XBL is. --- components/style/invalidation/element/document_state.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/style/invalidation/element/document_state.rs b/components/style/invalidation/element/document_state.rs index 253b9b4cc43..f7a8926b8c3 100644 --- a/components/style/invalidation/element/document_state.rs +++ b/components/style/invalidation/element/document_state.rs @@ -22,6 +22,9 @@ pub struct InvalidationMatchingData { /// An invalidation processor for style changes due to state and attribute /// changes. pub struct DocumentStateInvalidationProcessor<'a, E: TElement> { + // TODO(emilio): We might want to just run everything for every possible + // binding along with the document data, or just apply the XBL stuff to the + // bound subtrees. rules: &'a StyleRuleCascadeData, matching_context: MatchingContext<'a, E::Impl>, document_states_changed: DocumentState, From 335ca47361dc6837f8ef72fb3f738b1c1005499b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 12 Jan 2018 11:04:24 +0100 Subject: [PATCH 8/8] style: Use Default for ExtraStyleData instead of Option. --- components/selectors/context.rs | 4 ++-- components/selectors/parser.rs | 2 +- components/style/gecko/wrapper.rs | 12 ++++-------- .../style/invalidation/element/document_state.rs | 13 +++++++++++-- 4 files changed, 18 insertions(+), 13 deletions(-) diff --git a/components/selectors/context.rs b/components/selectors/context.rs index 79e0b69b4e8..856e18497d9 100644 --- a/components/selectors/context.rs +++ b/components/selectors/context.rs @@ -131,7 +131,7 @@ where pub pseudo_element_matching_fn: Option<&'a Fn(&Impl::PseudoElement) -> bool>, /// Extra implementation-dependent matching data. - pub extra_data: Option, + pub extra_data: Impl::ExtraMatchingData, quirks_mode: QuirksMode, classes_and_ids_case_sensitivity: CaseSensitivity, @@ -176,7 +176,7 @@ where scope_element: None, nesting_level: 0, pseudo_element_matching_fn: None, - extra_data: None, + extra_data: Default::default(), _impl: ::std::marker::PhantomData, } } diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index dead7875d0f..99b73353abf 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -84,7 +84,7 @@ macro_rules! with_all_bounds { /// are parameterized on SelectorImpl. See /// pub trait SelectorImpl: Clone + Sized + 'static { - type ExtraMatchingData: Sized + 'static; + type ExtraMatchingData: Sized + Default + 'static; type AttrValue: $($InSelector)*; type Identifier: $($InSelector)* + PrecomputedHash; type ClassName: $($InSelector)* + PrecomputedHash; diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 4de36a327d4..a2f75c4b4bb 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -2111,10 +2111,8 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } NonTSPseudoClass::MozWindowInactive => { let state_bit = DocumentState::NS_DOCUMENT_STATE_WINDOW_INACTIVE; - if let Some(ref invalidation_data) = context.extra_data { - if invalidation_data.document_state.intersects(state_bit) { - return true; - } + if context.extra_data.document_state.intersects(state_bit) { + return true; } self.document_state().contains(state_bit) @@ -2133,12 +2131,10 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } NonTSPseudoClass::MozLocaleDir(ref dir) => { let state_bit = DocumentState::NS_DOCUMENT_STATE_RTL_LOCALE; - if let Some(ref invalidation_data) = context.extra_data { + if context.extra_data.document_state.intersects(state_bit) { // NOTE(emilio): We could still return false for // Direction::Other(..), but we don't bother. - if invalidation_data.document_state.intersects(state_bit) { - return true; - } + return true; } let doc_is_rtl = self.document_state().contains(state_bit); diff --git a/components/style/invalidation/element/document_state.rs b/components/style/invalidation/element/document_state.rs index f7a8926b8c3..cf7a164ebdb 100644 --- a/components/style/invalidation/element/document_state.rs +++ b/components/style/invalidation/element/document_state.rs @@ -19,6 +19,15 @@ pub struct InvalidationMatchingData { pub document_state: DocumentState, } +impl Default for InvalidationMatchingData { + #[inline(always)] + fn default() -> Self { + Self { + document_state: DocumentState::empty(), + } + } +} + /// An invalidation processor for style changes due to state and attribute /// changes. pub struct DocumentStateInvalidationProcessor<'a, E: TElement> { @@ -46,9 +55,9 @@ impl<'a, E: TElement> DocumentStateInvalidationProcessor<'a, E> { quirks_mode, ); - matching_context.extra_data = Some(InvalidationMatchingData { + matching_context.extra_data = InvalidationMatchingData { document_state: document_states_changed, - }); + }; Self { rules, document_states_changed, matching_context } }