mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
style: Refactor the custom properties map to have less temporary hashmap entries.
This commit is contained in:
parent
1ecd942384
commit
c354f224ff
1 changed files with 64 additions and 62 deletions
|
@ -57,7 +57,7 @@ pub struct BorrowedSpecifiedValue<'a> {
|
||||||
css: &'a str,
|
css: &'a str,
|
||||||
first_token_type: TokenSerializationType,
|
first_token_type: TokenSerializationType,
|
||||||
last_token_type: TokenSerializationType,
|
last_token_type: TokenSerializationType,
|
||||||
references: Option<&'a PrecomputedHashSet<Name>>,
|
references: &'a PrecomputedHashSet<Name>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A computed value is just a set of tokens as well, until we resolve variables
|
/// A computed value is just a set of tokens as well, until we resolve variables
|
||||||
|
@ -155,6 +155,11 @@ where
|
||||||
self.values.len()
|
self.values.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether this map is empty.
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
/// Remove an item given its key.
|
/// Remove an item given its key.
|
||||||
fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
|
fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
|
||||||
where
|
where
|
||||||
|
@ -461,7 +466,7 @@ fn parse_var_function<'i, 't>(
|
||||||
/// properties.
|
/// properties.
|
||||||
pub struct CustomPropertiesBuilder<'a> {
|
pub struct CustomPropertiesBuilder<'a> {
|
||||||
seen: PrecomputedHashSet<&'a Name>,
|
seen: PrecomputedHashSet<&'a Name>,
|
||||||
specified_custom_properties: Option<OrderedMap<&'a Name, BorrowedSpecifiedValue<'a>>>,
|
specified_custom_properties: OrderedMap<&'a Name, Option<BorrowedSpecifiedValue<'a>>>,
|
||||||
inherited: Option<&'a Arc<CustomPropertiesMap>>,
|
inherited: Option<&'a Arc<CustomPropertiesMap>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +475,7 @@ impl<'a> CustomPropertiesBuilder<'a> {
|
||||||
pub fn new(inherited: Option<&'a Arc<CustomPropertiesMap>>) -> Self {
|
pub fn new(inherited: Option<&'a Arc<CustomPropertiesMap>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
seen: PrecomputedHashSet::default(),
|
seen: PrecomputedHashSet::default(),
|
||||||
specified_custom_properties: None,
|
specified_custom_properties: OrderedMap::new(),
|
||||||
inherited,
|
inherited,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -486,38 +491,19 @@ impl<'a> CustomPropertiesBuilder<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let map = match self.specified_custom_properties {
|
|
||||||
Some(ref mut map) => map,
|
|
||||||
None => {
|
|
||||||
let mut map = OrderedMap::new();
|
|
||||||
if let Some(inherited) = self.inherited {
|
|
||||||
for (name, inherited_value) in inherited.iter() {
|
|
||||||
map.insert(name, BorrowedSpecifiedValue {
|
|
||||||
css: &inherited_value.css,
|
|
||||||
first_token_type: inherited_value.first_token_type,
|
|
||||||
last_token_type: inherited_value.last_token_type,
|
|
||||||
references: None
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.specified_custom_properties = Some(map);
|
|
||||||
self.specified_custom_properties.as_mut().unwrap()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
match specified_value {
|
match specified_value {
|
||||||
DeclaredValue::Value(ref specified_value) => {
|
DeclaredValue::Value(ref specified_value) => {
|
||||||
map.insert(name, BorrowedSpecifiedValue {
|
self.specified_custom_properties.insert(name, Some(BorrowedSpecifiedValue {
|
||||||
css: &specified_value.css,
|
css: &specified_value.css,
|
||||||
first_token_type: specified_value.first_token_type,
|
first_token_type: specified_value.first_token_type,
|
||||||
last_token_type: specified_value.last_token_type,
|
last_token_type: specified_value.last_token_type,
|
||||||
references: Some(&specified_value.references),
|
references: &specified_value.references,
|
||||||
});
|
}));
|
||||||
},
|
},
|
||||||
DeclaredValue::WithVariables(_) => unreachable!(),
|
DeclaredValue::WithVariables(_) => unreachable!(),
|
||||||
DeclaredValue::CSSWideKeyword(keyword) => match keyword {
|
DeclaredValue::CSSWideKeyword(keyword) => match keyword {
|
||||||
CSSWideKeyword::Initial => {
|
CSSWideKeyword::Initial => {
|
||||||
map.remove(&name);
|
self.specified_custom_properties.insert(name, None);
|
||||||
}
|
}
|
||||||
CSSWideKeyword::Unset | // Custom properties are inherited by default.
|
CSSWideKeyword::Unset | // Custom properties are inherited by default.
|
||||||
CSSWideKeyword::Inherit => {} // The inherited value is what we already have.
|
CSSWideKeyword::Inherit => {} // The inherited value is what we already have.
|
||||||
|
@ -532,13 +518,12 @@ impl<'a> CustomPropertiesBuilder<'a> {
|
||||||
///
|
///
|
||||||
/// Otherwise, just use the inherited custom properties map.
|
/// Otherwise, just use the inherited custom properties map.
|
||||||
pub fn build(mut self) -> Option<Arc<CustomPropertiesMap>> {
|
pub fn build(mut self) -> Option<Arc<CustomPropertiesMap>> {
|
||||||
let mut map = match self.specified_custom_properties.take() {
|
if self.specified_custom_properties.is_empty() {
|
||||||
Some(map) => map,
|
return self.inherited.cloned();
|
||||||
None => return self.inherited.cloned(),
|
}
|
||||||
};
|
|
||||||
|
|
||||||
remove_cycles(&mut map);
|
remove_cycles(&mut self.specified_custom_properties);
|
||||||
Some(Arc::new(substitute_all(map)))
|
Some(Arc::new(substitute_all(self.specified_custom_properties, self.inherited)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -546,7 +531,7 @@ impl<'a> CustomPropertiesBuilder<'a> {
|
||||||
///
|
///
|
||||||
/// 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
|
||||||
/// being in the map.
|
/// being in the map.
|
||||||
fn remove_cycles(map: &mut OrderedMap<&Name, BorrowedSpecifiedValue>) {
|
fn remove_cycles(map: &mut OrderedMap<&Name, Option<BorrowedSpecifiedValue>>) {
|
||||||
let mut to_remove = PrecomputedHashSet::default();
|
let mut to_remove = PrecomputedHashSet::default();
|
||||||
{
|
{
|
||||||
let mut visited = PrecomputedHashSet::default();
|
let mut visited = PrecomputedHashSet::default();
|
||||||
|
@ -555,7 +540,7 @@ fn remove_cycles(map: &mut OrderedMap<&Name, BorrowedSpecifiedValue>) {
|
||||||
walk(map, name, &mut stack, &mut visited, &mut to_remove);
|
walk(map, name, &mut stack, &mut visited, &mut to_remove);
|
||||||
|
|
||||||
fn walk<'a>(
|
fn walk<'a>(
|
||||||
map: &OrderedMap<&'a Name, BorrowedSpecifiedValue<'a>>,
|
map: &OrderedMap<&'a Name, Option<BorrowedSpecifiedValue<'a>>>,
|
||||||
name: &'a Name,
|
name: &'a Name,
|
||||||
stack: &mut Vec<&'a Name>,
|
stack: &mut Vec<&'a Name>,
|
||||||
visited: &mut PrecomputedHashSet<&'a Name>,
|
visited: &mut PrecomputedHashSet<&'a Name>,
|
||||||
|
@ -565,10 +550,10 @@ fn remove_cycles(map: &mut OrderedMap<&Name, BorrowedSpecifiedValue>) {
|
||||||
if already_visited_before {
|
if already_visited_before {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let Some(value) = map.get(&name) {
|
if let Some(&Some(ref value)) = map.get(&name) {
|
||||||
if let Some(references) = value.references {
|
if !value.references.is_empty() {
|
||||||
stack.push(name);
|
stack.push(name);
|
||||||
for next in references {
|
for next in value.references {
|
||||||
if let Some(position) = stack.iter().position(|&x| x == next) {
|
if let Some(position) = stack.iter().position(|&x| x == next) {
|
||||||
// Found a cycle
|
// Found a cycle
|
||||||
for &in_cycle in &stack[position..] {
|
for &in_cycle in &stack[position..] {
|
||||||
|
@ -591,16 +576,33 @@ fn remove_cycles(map: &mut OrderedMap<&Name, BorrowedSpecifiedValue>) {
|
||||||
|
|
||||||
/// Replace `var()` functions for all custom properties.
|
/// Replace `var()` functions for all custom properties.
|
||||||
fn substitute_all(
|
fn substitute_all(
|
||||||
specified_values_map: OrderedMap<&Name, BorrowedSpecifiedValue>
|
specified_values_map: OrderedMap<&Name, Option<BorrowedSpecifiedValue>>,
|
||||||
|
inherited: Option<&Arc<CustomPropertiesMap>>,
|
||||||
) -> CustomPropertiesMap {
|
) -> CustomPropertiesMap {
|
||||||
let mut custom_properties_map = CustomPropertiesMap::new();
|
let mut custom_properties_map = match inherited {
|
||||||
|
None => CustomPropertiesMap::new(),
|
||||||
|
Some(inherited) => (**inherited).clone(),
|
||||||
|
};
|
||||||
|
|
||||||
let mut invalid = PrecomputedHashSet::default();
|
let mut invalid = PrecomputedHashSet::default();
|
||||||
|
|
||||||
for (name, value) in specified_values_map.iter() {
|
for (name, value) in specified_values_map.iter() {
|
||||||
// If this value is invalid at computed-time it won’t be inserted in computed_values_map.
|
let value = match *value {
|
||||||
// Nothing else to do.
|
Some(ref v) => v,
|
||||||
|
None => {
|
||||||
|
custom_properties_map.remove(*name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let _ = substitute_one(
|
let _ = substitute_one(
|
||||||
name, value, &specified_values_map, None,
|
name,
|
||||||
&mut custom_properties_map, &mut invalid);
|
value,
|
||||||
|
&specified_values_map,
|
||||||
|
None,
|
||||||
|
&mut custom_properties_map,
|
||||||
|
&mut invalid,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
custom_properties_map
|
custom_properties_map
|
||||||
|
@ -613,22 +615,23 @@ fn substitute_all(
|
||||||
fn substitute_one(
|
fn substitute_one(
|
||||||
name: &Name,
|
name: &Name,
|
||||||
specified_value: &BorrowedSpecifiedValue,
|
specified_value: &BorrowedSpecifiedValue,
|
||||||
specified_values_map: &OrderedMap<&Name, BorrowedSpecifiedValue>,
|
specified_values_map: &OrderedMap<&Name, Option<BorrowedSpecifiedValue>>,
|
||||||
partial_computed_value: Option<&mut ComputedValue>,
|
partial_computed_value: Option<&mut ComputedValue>,
|
||||||
custom_properties_map: &mut CustomPropertiesMap,
|
custom_properties_map: &mut CustomPropertiesMap,
|
||||||
invalid: &mut PrecomputedHashSet<Name>,
|
invalid: &mut PrecomputedHashSet<Name>,
|
||||||
) -> Result<TokenSerializationType, ()> {
|
) -> Result<TokenSerializationType, ()> {
|
||||||
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)
|
|
||||||
}
|
|
||||||
return Ok(computed_value.last_token_type)
|
|
||||||
}
|
|
||||||
|
|
||||||
if invalid.contains(name) {
|
if invalid.contains(name) {
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
let computed_value = if specified_value.references.map_or(false, |set| !set.is_empty()) {
|
|
||||||
|
let computed_value = if specified_value.references.is_empty() {
|
||||||
|
// The specified value contains no var() reference
|
||||||
|
ComputedValue {
|
||||||
|
css: specified_value.css.to_owned(),
|
||||||
|
first_token_type: specified_value.first_token_type,
|
||||||
|
last_token_type: specified_value.last_token_type,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
let mut partial_computed_value = ComputedValue::empty();
|
let mut partial_computed_value = ComputedValue::empty();
|
||||||
let mut input = ParserInput::new(&specified_value.css);
|
let mut input = ParserInput::new(&specified_value.css);
|
||||||
let mut input = Parser::new(&mut input);
|
let mut input = Parser::new(&mut input);
|
||||||
|
@ -636,9 +639,15 @@ fn substitute_one(
|
||||||
let result = substitute_block(
|
let result = substitute_block(
|
||||||
&mut input, &mut position, &mut partial_computed_value,
|
&mut input, &mut position, &mut partial_computed_value,
|
||||||
&mut |name, partial_computed_value| {
|
&mut |name, partial_computed_value| {
|
||||||
if let Some(other_specified_value) = specified_values_map.get(&name) {
|
if let Some(other_specified_value) = specified_values_map.get(&name).and_then(|v| v.as_ref()) {
|
||||||
substitute_one(name, other_specified_value, specified_values_map,
|
substitute_one(
|
||||||
Some(partial_computed_value), custom_properties_map, invalid)
|
name,
|
||||||
|
other_specified_value,
|
||||||
|
specified_values_map,
|
||||||
|
Some(partial_computed_value),
|
||||||
|
custom_properties_map,
|
||||||
|
invalid,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
@ -651,13 +660,6 @@ fn substitute_one(
|
||||||
invalid.insert(name.clone());
|
invalid.insert(name.clone());
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// The specified value contains no var() reference
|
|
||||||
ComputedValue {
|
|
||||||
css: specified_value.css.to_owned(),
|
|
||||||
first_token_type: specified_value.first_token_type,
|
|
||||||
last_token_type: specified_value.last_token_type,
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if let Some(partial_computed_value) = partial_computed_value {
|
if let Some(partial_computed_value) = partial_computed_value {
|
||||||
partial_computed_value.push_variable(&computed_value)
|
partial_computed_value.push_variable(&computed_value)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue