style: Introduce CustomPropertiesBuilder.

I'm about to introduce more state here to implement optimizations for custom
property cascading, so this abstraction is useful to encapsulate that state.
This commit is contained in:
Emilio Cobos Álvarez 2017-10-08 14:58:14 +02:00
parent 47efcd5e52
commit d0f080d5dd
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
4 changed files with 73 additions and 63 deletions

View file

@ -457,9 +457,59 @@ fn parse_var_function<'i, 't>(
Ok(()) 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 /// Add one custom property declaration to a map, unless another with the same
/// name was already there. /// name was already there.
pub fn cascade<'a>( fn cascade<'a>(
custom_properties: &mut Option<OrderedMap<&'a Name, BorrowedSpecifiedValue<'a>>>, custom_properties: &mut Option<OrderedMap<&'a Name, BorrowedSpecifiedValue<'a>>>,
inherited: Option<&'a Arc<CustomPropertiesMap>>, inherited: Option<&'a Arc<CustomPropertiesMap>>,
seen: &mut PrecomputedHashSet<&'a Name>, 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 /// https://drafts.csswg.org/css-variables/#cycles
/// ///
/// The initial value of a custom property is represented by this property not /// The initial value of a custom property is represented by this property not

View file

@ -9,6 +9,7 @@
use context::QuirksMode; use context::QuirksMode;
use cssparser::{DeclarationListParser, parse_important, ParserInput, CowRcStr}; use cssparser::{DeclarationListParser, parse_important, ParserInput, CowRcStr};
use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter, ParseError as CssParseError}; use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter, ParseError as CssParseError};
use custom_properties::CustomPropertiesBuilder;
use error_reporting::{ParseErrorReporter, ContextualParseError}; use error_reporting::{ParseErrorReporter, ContextualParseError};
use parser::{ParserContext, ParserErrorContext}; use parser::{ParserContext, ParserErrorContext};
use properties::animated_properties::AnimationValue; use properties::animated_properties::AnimationValue;
@ -691,24 +692,15 @@ impl PropertyDeclarationBlock {
&self, &self,
inherited_custom_properties: Option<&Arc<::custom_properties::CustomPropertiesMap>>, inherited_custom_properties: Option<&Arc<::custom_properties::CustomPropertiesMap>>,
) -> Option<Arc<::custom_properties::CustomPropertiesMap>> { ) -> Option<Arc<::custom_properties::CustomPropertiesMap>> {
let mut custom_properties = None; let mut builder = CustomPropertiesBuilder::new(inherited_custom_properties);
let mut seen_custom = PrecomputedHashSet::default();
for declaration in self.normal_declaration_iter() { for declaration in self.normal_declaration_iter() {
if let PropertyDeclaration::Custom(ref name, ref value) = *declaration { if let PropertyDeclaration::Custom(ref name, ref value) = *declaration {
::custom_properties::cascade( builder.cascade(name, value.borrow());
&mut custom_properties,
inherited_custom_properties,
&mut seen_custom,
name,
value.borrow(),
);
} }
} }
::custom_properties::finish_cascade(
custom_properties, builder.build()
inherited_custom_properties,
)
} }
} }

View file

@ -12,6 +12,7 @@
#[cfg(feature = "servo")] #[cfg(feature = "servo")]
use app_units::Au; use app_units::Au;
use custom_properties::CustomPropertiesBuilder;
use servo_arc::{Arc, UniqueArc}; use servo_arc::{Arc, UniqueArc};
use smallbitvec::SmallBitVec; use smallbitvec::SmallBitVec;
use std::borrow::Cow; use std::borrow::Cow;
@ -33,7 +34,6 @@ use media_queries::Device;
use parser::ParserContext; use parser::ParserContext;
#[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont; #[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont;
use rule_cache::{RuleCache, RuleCacheConditions}; use rule_cache::{RuleCache, RuleCacheConditions};
use selector_map::PrecomputedHashSet;
use selector_parser::PseudoElement; use selector_parser::PseudoElement;
use selectors::parser::SelectorParseError; use selectors::parser::SelectorParseError;
#[cfg(feature = "servo")] use servo_config::prefs::PREFS; #[cfg(feature = "servo")] use servo_config::prefs::PREFS;
@ -3228,26 +3228,18 @@ where
} }
}; };
let inherited_custom_properties = inherited_style.custom_properties(); let custom_properties = {
let mut custom_properties = None; let mut builder =
let mut seen_custom = PrecomputedHashSet::default(); CustomPropertiesBuilder::new(inherited_style.custom_properties());
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 = for (declaration, _cascade_level) in iter_declarations() {
::custom_properties::finish_cascade( if let PropertyDeclaration::Custom(ref name, ref value) = *declaration {
custom_properties, builder.cascade(name, value.borrow());
inherited_custom_properties, }
); }
builder.build()
};
let mut context = computed::Context { let mut context = computed::Context {
is_root_element: flags.contains(IS_ROOT_ELEMENT), is_root_element: flags.contains(IS_ROOT_ELEMENT),

View file

@ -4,7 +4,7 @@
use cssparser::{Parser, ParserInput}; use cssparser::{Parser, ParserInput};
use servo_arc::Arc; 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 style::properties::DeclaredValue;
use test::{self, Bencher}; use test::{self, Bencher};
@ -18,19 +18,13 @@ fn cascade(
(Name::from(name), SpecifiedValue::parse(&mut parser).unwrap()) (Name::from(name), SpecifiedValue::parse(&mut parser).unwrap())
}).collect::<Vec<_>>(); }).collect::<Vec<_>>();
let mut custom_properties = None; let mut builder = CustomPropertiesBuilder::new(inherited);
let mut seen = Default::default();
for &(ref name, ref val) in &values { for &(ref name, ref val) in &values {
custom_properties::cascade( builder.cascade(name, DeclaredValue::Value(val));
&mut custom_properties,
inherited,
&mut seen,
name,
DeclaredValue::Value(val)
)
} }
custom_properties::finish_cascade(custom_properties, inherited) builder.build()
} }
#[bench] #[bench]