diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index fe6e45751f2..1993bb64339 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -8,9 +8,10 @@ use Atom; use cssparser::{Delimiter, Parser, ParserInput, SourcePosition, Token, TokenSerializationType}; -use hash::{HashMap, HashSet}; use parser::ParserContext; +use precomputed_hash::PrecomputedHash; use properties::{CSSWideKeyword, DeclaredValue}; +use selector_map::{PrecomputedHashSet, PrecomputedHashMap}; use selectors::parser::SelectorParseError; use servo_arc::Arc; use std::ascii::AsciiExt; @@ -49,7 +50,7 @@ pub struct SpecifiedValue { last_token_type: TokenSerializationType, /// Custom property names in var() functions. - references: HashSet, + references: PrecomputedHashSet, } /// This struct is a cheap borrowed version of a `SpecifiedValue`. @@ -57,7 +58,7 @@ pub struct BorrowedSpecifiedValue<'a> { css: &'a str, first_token_type: TokenSerializationType, last_token_type: TokenSerializationType, - references: Option<&'a HashSet>, + references: Option<&'a PrecomputedHashSet>, } /// A computed value is just a set of tokens as well, until we resolve variables @@ -99,23 +100,23 @@ pub type CustomPropertiesMap = OrderedMap; #[derive(Clone, Debug, Eq, PartialEq)] pub struct OrderedMap where - K: Eq + Hash + Clone, + K: PrecomputedHash + Hash + Eq + Clone, { /// Key index. index: Vec, /// Key-value map. - values: HashMap, + values: PrecomputedHashMap, } impl OrderedMap where - K: Eq + Hash + Clone, + K: Eq + PrecomputedHash + Hash + Clone, { /// Creates a new ordered map. pub fn new() -> Self { OrderedMap { index: Vec::new(), - values: HashMap::new(), + values: PrecomputedHashMap::default(), } } @@ -157,7 +158,7 @@ where fn remove(&mut self, key: &Q) -> Option where K: Borrow, - Q: Hash + Eq, + Q: PrecomputedHash + Hash + Eq, { let index = match self.index.iter().position(|k| k.borrow() == key) { Some(p) => p, @@ -174,7 +175,7 @@ where /// added to the key-value map. pub struct OrderedMapIterator<'a, K, V> where - K: 'a + Eq + Hash + Clone, V: 'a, + K: 'a + Eq + PrecomputedHash + Hash + Clone, V: 'a, { /// The OrderedMap itself. inner: &'a OrderedMap, @@ -184,7 +185,7 @@ where impl<'a, K, V> Iterator for OrderedMapIterator<'a, K, V> where - K: Eq + Hash + Clone, + K: Eq + PrecomputedHash + Hash + Clone, { type Item = (&'a K, &'a V); @@ -239,9 +240,11 @@ impl ComputedValue { impl SpecifiedValue { /// Parse a custom property SpecifiedValue. - pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result, ParseError<'i>> { - let mut references = Some(HashSet::new()); + pub fn parse<'i, 't>( + _context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result, ParseError<'i>> { + let mut references = Some(PrecomputedHashSet::default()); let (first, css, last) = parse_self_contained_declaration_value(input, &mut references)?; Ok(Box::new(SpecifiedValue { css: css.into_owned(), @@ -260,14 +263,14 @@ pub fn parse_non_custom_with_var<'i, 't> Ok((first_token_type, css)) } -fn parse_self_contained_declaration_value<'i, 't> - (input: &mut Parser<'i, 't>, - references: &mut Option>) - -> Result<( - TokenSerializationType, - Cow<'i, str>, - TokenSerializationType - ), ParseError<'i>> { +fn parse_self_contained_declaration_value<'i, 't>( + input: &mut Parser<'i, 't>, + references: &mut Option> +) -> Result< + (TokenSerializationType, Cow<'i, str>, TokenSerializationType), + ParseError<'i> +> +{ let start_position = input.position(); let mut missing_closing_characters = String::new(); let (first, last) = parse_declaration_value(input, references, &mut missing_closing_characters)?; @@ -283,11 +286,11 @@ fn parse_self_contained_declaration_value<'i, 't> } /// https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value -fn parse_declaration_value<'i, 't> - (input: &mut Parser<'i, 't>, - references: &mut Option>, - missing_closing_characters: &mut String) - -> Result<(TokenSerializationType, TokenSerializationType), ParseError<'i>> { +fn parse_declaration_value<'i, 't>( + input: &mut Parser<'i, 't>, + references: &mut Option>, + missing_closing_characters: &mut String +) -> Result<(TokenSerializationType, TokenSerializationType), ParseError<'i>> { input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| { // Need at least one token let start = input.state(); @@ -300,12 +303,11 @@ fn parse_declaration_value<'i, 't> /// Like parse_declaration_value, but accept `!` and `;` since they are only /// invalid at the top level -fn parse_declaration_value_block<'i, 't> - (input: &mut Parser<'i, 't>, - references: &mut Option>, - missing_closing_characters: &mut String) - -> Result<(TokenSerializationType, TokenSerializationType), - ParseError<'i>> { +fn parse_declaration_value_block<'i, 't>( + input: &mut Parser<'i, 't>, + references: &mut Option>, + missing_closing_characters: &mut String +) -> Result<(TokenSerializationType, TokenSerializationType), ParseError<'i>> { let mut token_start = input.position(); let mut token = match input.next_including_whitespace_and_comments() { // FIXME: remove clone() when borrows are non-lexical @@ -416,9 +418,10 @@ fn parse_declaration_value_block<'i, 't> } // If the var function is valid, return Ok((custom_property_name, fallback)) -fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>, - references: &mut Option>) - -> Result<(), ParseError<'i>> { +fn parse_var_function<'i, 't>( + input: &mut Parser<'i, 't>, + references: &mut Option> +) -> Result<(), ParseError<'i>> { let name = input.expect_ident_cloned()?; let name: Result<_, ParseError> = parse_name(&name) @@ -443,11 +446,13 @@ fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>, /// Add one custom property declaration to a map, unless another with the same /// name was already there. -pub fn cascade<'a>(custom_properties: &mut Option>>, - inherited: &'a Option>, - seen: &mut HashSet<&'a Name>, - name: &'a Name, - specified_value: DeclaredValue<'a, Box>) { +pub fn cascade<'a>( + custom_properties: &mut Option>>, + inherited: &'a Option>, + seen: &mut PrecomputedHashSet<&'a Name>, + name: &'a Name, + specified_value: DeclaredValue<'a, Box> +) { let was_already_present = !seen.insert(name); if was_already_present { return; @@ -514,18 +519,20 @@ pub fn finish_cascade(specified_values_map: Option) { - let mut to_remove = HashSet::new(); + let mut to_remove = PrecomputedHashSet::default(); { - let mut visited = HashSet::new(); + let mut visited = PrecomputedHashSet::default(); let mut stack = Vec::new(); for name in &map.index { walk(map, name, &mut stack, &mut visited, &mut to_remove); - fn walk<'a>(map: &OrderedMap<&'a Name, BorrowedSpecifiedValue<'a>>, - name: &'a Name, - stack: &mut Vec<&'a Name>, - visited: &mut HashSet<&'a Name>, - to_remove: &mut HashSet) { + fn walk<'a>( + map: &OrderedMap<&'a Name, BorrowedSpecifiedValue<'a>>, + name: &'a Name, + stack: &mut Vec<&'a Name>, + visited: &mut PrecomputedHashSet<&'a Name>, + to_remove: &mut PrecomputedHashSet, + ) { let already_visited_before = !visited.insert(name); if already_visited_before { return @@ -555,10 +562,11 @@ fn remove_cycles(map: &mut OrderedMap<&Name, BorrowedSpecifiedValue>) { } /// Replace `var()` functions for all custom properties. -fn substitute_all(specified_values_map: OrderedMap<&Name, BorrowedSpecifiedValue>) - -> CustomPropertiesMap { +fn substitute_all( + specified_values_map: OrderedMap<&Name, BorrowedSpecifiedValue> +) -> CustomPropertiesMap { let mut custom_properties_map = CustomPropertiesMap::new(); - let mut invalid = HashSet::new(); + let mut invalid = PrecomputedHashSet::default(); for name in &specified_values_map.index { let value = specified_values_map.get(name).unwrap(); @@ -576,13 +584,14 @@ fn substitute_all(specified_values_map: OrderedMap<&Name, BorrowedSpecifiedValue /// Also recursively record results for other custom properties referenced by `var()` functions. /// Return `Err(())` for invalid at computed time. /// or `Ok(last_token_type that was pushed to partial_computed_value)` otherwise. -fn substitute_one(name: &Name, - specified_value: &BorrowedSpecifiedValue, - specified_values_map: &OrderedMap<&Name, BorrowedSpecifiedValue>, - partial_computed_value: Option<&mut ComputedValue>, - custom_properties_map: &mut CustomPropertiesMap, - invalid: &mut HashSet) - -> Result { +fn substitute_one( + name: &Name, + specified_value: &BorrowedSpecifiedValue, + specified_values_map: &OrderedMap<&Name, BorrowedSpecifiedValue>, + partial_computed_value: Option<&mut ComputedValue>, + custom_properties_map: &mut CustomPropertiesMap, + invalid: &mut PrecomputedHashSet, +) -> Result { if let Some(computed_value) = custom_properties_map.get(&name) { if let Some(partial_computed_value) = partial_computed_value { partial_computed_value.push_variable(computed_value) diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 2adcce9fc2f..a2093aabd8e 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -693,8 +693,7 @@ impl PropertyDeclarationBlock { inherited_custom_properties: Option>, ) -> Option> { let mut custom_properties = None; - // FIXME: Use PrecomputedHasher instead. - let mut seen_custom = HashSet::new(); + let mut seen_custom = PrecomputedHashSet::default(); for declaration in self.normal_declaration_iter() { if let PropertyDeclaration::Custom(ref name, ref value) = *declaration { diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 09664f7dbee..b8ec62171df 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -15,7 +15,6 @@ use app_units::Au; use servo_arc::{Arc, UniqueArc}; use smallbitvec::SmallBitVec; use std::borrow::Cow; -use hash::HashSet; use std::{fmt, mem, ops}; use std::cell::RefCell; #[cfg(feature = "gecko")] use std::ptr; @@ -35,6 +34,7 @@ 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; @@ -3272,7 +3272,7 @@ where let inherited_custom_properties = inherited_style.custom_properties(); let mut custom_properties = None; - let mut seen_custom = HashSet::new(); + 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(