diff options
-rw-r--r-- | components/style/custom_properties.rs | 70 | ||||
-rw-r--r-- | components/style/properties/declaration_block.rs | 18 | ||||
-rw-r--r-- | components/style/properties/properties.mako.rs | 30 | ||||
-rw-r--r-- | tests/unit/style/custom_properties.rs | 16 |
4 files changed, 72 insertions, 62 deletions
diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index 7fd74f83c1b..ca6e820335b 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -457,9 +457,59 @@ fn parse_var_function<'i, 't>( Ok(()) } +/// A struct that takes care of encapsulating the cascade process for custom +/// properties. +pub struct CustomPropertiesBuilder<'a> { + seen: PrecomputedHashSet<&'a Name>, + custom_properties: Option<OrderedMap<&'a Name, BorrowedSpecifiedValue<'a>>>, + inherited: Option<&'a Arc<CustomPropertiesMap>>, +} + +impl<'a> CustomPropertiesBuilder<'a> { + /// Create a new builder, inheriting from a given custom properties map. + pub fn new(inherited: Option<&'a Arc<CustomPropertiesMap>>) -> Self { + Self { + seen: PrecomputedHashSet::default(), + custom_properties: None, + inherited, + } + } + + /// Cascade a given custom property declaration. + pub fn cascade( + &mut self, + name: &'a Name, + specified_value: DeclaredValue<'a, Box<SpecifiedValue>>, + ) { + cascade( + &mut self.custom_properties, + self.inherited, + &mut self.seen, + name, + specified_value, + ) + } + + /// Returns the final map of applicable custom properties. + /// + /// If there was any specified property, we've created a new map and now we need + /// to remove any potential cycles, and wrap it in an arc. + /// + /// Otherwise, just use the inherited custom properties map. + pub fn build(mut self) -> Option<Arc<CustomPropertiesMap>> { + let mut map = match self.custom_properties.take() { + Some(map) => map, + None => return self.inherited.cloned(), + }; + + remove_cycles(&mut map); + Some(Arc::new(substitute_all(map))) + } +} + /// Add one custom property declaration to a map, unless another with the same /// name was already there. -pub fn cascade<'a>( +fn cascade<'a>( custom_properties: &mut Option<OrderedMap<&'a Name, BorrowedSpecifiedValue<'a>>>, inherited: Option<&'a Arc<CustomPropertiesMap>>, seen: &mut PrecomputedHashSet<&'a Name>, @@ -509,24 +559,6 @@ pub fn cascade<'a>( } } -/// Returns the final map of applicable custom properties. -/// -/// If there was any specified property, we've created a new map and now we need -/// to remove any potential cycles, and wrap it in an arc. -/// -/// Otherwise, just use the inherited custom properties map. -pub fn finish_cascade( - specified_values_map: Option<OrderedMap<&Name, BorrowedSpecifiedValue>>, - inherited: Option<&Arc<CustomPropertiesMap>>, -) -> Option<Arc<CustomPropertiesMap>> { - if let Some(mut map) = specified_values_map { - remove_cycles(&mut map); - Some(Arc::new(substitute_all(map))) - } else { - inherited.cloned() - } -} - /// https://drafts.csswg.org/css-variables/#cycles /// /// The initial value of a custom property is represented by this property not diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index b1c7d547bbb..df4840f0dda 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -9,6 +9,7 @@ use context::QuirksMode; use cssparser::{DeclarationListParser, parse_important, ParserInput, CowRcStr}; use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter, ParseError as CssParseError}; +use custom_properties::CustomPropertiesBuilder; use error_reporting::{ParseErrorReporter, ContextualParseError}; use parser::{ParserContext, ParserErrorContext}; use properties::animated_properties::AnimationValue; @@ -691,24 +692,15 @@ impl PropertyDeclarationBlock { &self, inherited_custom_properties: Option<&Arc<::custom_properties::CustomPropertiesMap>>, ) -> Option<Arc<::custom_properties::CustomPropertiesMap>> { - let mut custom_properties = None; - let mut seen_custom = PrecomputedHashSet::default(); + let mut builder = CustomPropertiesBuilder::new(inherited_custom_properties); for declaration in self.normal_declaration_iter() { if let PropertyDeclaration::Custom(ref name, ref value) = *declaration { - ::custom_properties::cascade( - &mut custom_properties, - inherited_custom_properties, - &mut seen_custom, - name, - value.borrow(), - ); + builder.cascade(name, value.borrow()); } } - ::custom_properties::finish_cascade( - custom_properties, - inherited_custom_properties, - ) + + builder.build() } } diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 031bd1e580b..d18bacbb631 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -12,6 +12,7 @@ #[cfg(feature = "servo")] use app_units::Au; +use custom_properties::CustomPropertiesBuilder; use servo_arc::{Arc, UniqueArc}; use smallbitvec::SmallBitVec; use std::borrow::Cow; @@ -33,7 +34,6 @@ use media_queries::Device; use parser::ParserContext; #[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont; use rule_cache::{RuleCache, RuleCacheConditions}; -use selector_map::PrecomputedHashSet; use selector_parser::PseudoElement; use selectors::parser::SelectorParseError; #[cfg(feature = "servo")] use servo_config::prefs::PREFS; @@ -3228,26 +3228,18 @@ where } }; - let inherited_custom_properties = inherited_style.custom_properties(); - let mut custom_properties = None; - let mut seen_custom = PrecomputedHashSet::default(); - for (declaration, _cascade_level) in iter_declarations() { - if let PropertyDeclaration::Custom(ref name, ref value) = *declaration { - ::custom_properties::cascade( - &mut custom_properties, - inherited_custom_properties, - &mut seen_custom, - name, - value.borrow(), - ); + let custom_properties = { + let mut builder = + CustomPropertiesBuilder::new(inherited_style.custom_properties()); + + for (declaration, _cascade_level) in iter_declarations() { + if let PropertyDeclaration::Custom(ref name, ref value) = *declaration { + builder.cascade(name, value.borrow()); + } } - } - let custom_properties = - ::custom_properties::finish_cascade( - custom_properties, - inherited_custom_properties, - ); + builder.build() + }; let mut context = computed::Context { is_root_element: flags.contains(IS_ROOT_ELEMENT), diff --git a/tests/unit/style/custom_properties.rs b/tests/unit/style/custom_properties.rs index 135583e9d62..7a2741633c8 100644 --- a/tests/unit/style/custom_properties.rs +++ b/tests/unit/style/custom_properties.rs @@ -4,7 +4,7 @@ use cssparser::{Parser, ParserInput}; use servo_arc::Arc; -use style::custom_properties::{self, Name, SpecifiedValue, CustomPropertiesMap}; +use style::custom_properties::{Name, SpecifiedValue, CustomPropertiesMap, CustomPropertiesBuilder}; use style::properties::DeclaredValue; use test::{self, Bencher}; @@ -18,19 +18,13 @@ fn cascade( (Name::from(name), SpecifiedValue::parse(&mut parser).unwrap()) }).collect::<Vec<_>>(); - let mut custom_properties = None; - let mut seen = Default::default(); + let mut builder = CustomPropertiesBuilder::new(inherited); + for &(ref name, ref val) in &values { - custom_properties::cascade( - &mut custom_properties, - inherited, - &mut seen, - name, - DeclaredValue::Value(val) - ) + builder.cascade(name, DeclaredValue::Value(val)); } - custom_properties::finish_cascade(custom_properties, inherited) + builder.build() } #[bench] |