mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Make custom property substitution do less work.
When var() is substituted, record that result rather than re-compute it later.
This commit is contained in:
parent
1c1a9379a3
commit
4bf28417b4
1 changed files with 63 additions and 25 deletions
|
@ -210,37 +210,67 @@ fn remove_cycles(map: &mut HashMap<&Atom, BorrowedValue>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn substitute_all(custom_properties: HashMap<&Atom, BorrowedValue>) -> HashMap<Atom, String> {
|
fn substitute_all(custom_properties: HashMap<&Atom, BorrowedValue>) -> HashMap<Atom, String> {
|
||||||
custom_properties.iter().filter_map(|(&name, value)| {
|
let mut substituted_map = HashMap::new();
|
||||||
let mut substituted = String::new();
|
let mut invalid = HashSet::new();
|
||||||
if substitute_one(value, &mut substituted, &custom_properties).is_ok() {
|
for (&name, value) in &custom_properties {
|
||||||
Some((name.clone(), substituted))
|
// If this value is invalid at computed time it won’t be inserted in substituted_map.
|
||||||
} else {
|
// Nothing else to do.
|
||||||
None
|
let _ = substitute_one(
|
||||||
}
|
name, value, &custom_properties, None, &mut substituted_map, &mut invalid);
|
||||||
}).collect()
|
}
|
||||||
|
substituted_map
|
||||||
}
|
}
|
||||||
|
|
||||||
fn substitute_one(value: &BorrowedValue,
|
fn substitute_one(name: &Atom,
|
||||||
substituted: &mut String,
|
value: &BorrowedValue,
|
||||||
custom_properties: &HashMap<&Atom, BorrowedValue>)
|
custom_properties: &HashMap<&Atom, BorrowedValue>,
|
||||||
|
substituted: Option<&mut String>,
|
||||||
|
substituted_map: &mut HashMap<Atom, String>,
|
||||||
|
invalid: &mut HashSet<Atom>)
|
||||||
-> Result<(), ()> {
|
-> Result<(), ()> {
|
||||||
if let Some(references) = value.references {
|
if let Some(value) = substituted_map.get(name) {
|
||||||
|
if let Some(substituted) = substituted {
|
||||||
|
substituted.push_str(value)
|
||||||
|
}
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
if invalid.contains(name) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
let value = if let Some(references) = value.references {
|
||||||
if !references.is_empty() {
|
if !references.is_empty() {
|
||||||
|
let mut substituted = String::new();
|
||||||
let mut input = Parser::new(&value.value);
|
let mut input = Parser::new(&value.value);
|
||||||
let mut start = input.position();
|
let mut start = input.position();
|
||||||
try!(substitute_block(&mut input, &mut start, substituted, &custom_properties));
|
if substitute_block(
|
||||||
|
custom_properties, &mut input, &mut start, &mut substituted,
|
||||||
|
substituted_map, invalid,
|
||||||
|
).is_err() {
|
||||||
|
invalid.insert(name.clone());
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
substituted.push_str(input.slice_from(start));
|
substituted.push_str(input.slice_from(start));
|
||||||
return Ok(())
|
substituted
|
||||||
|
} else {
|
||||||
|
value.value.to_owned()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
value.value.to_owned()
|
||||||
|
};
|
||||||
|
if let Some(substituted) = substituted {
|
||||||
|
substituted.push_str(&value)
|
||||||
}
|
}
|
||||||
substituted.push_str(value.value);
|
substituted_map.insert(name.clone(), value);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn substitute_block(input: &mut Parser,
|
fn substitute_block(custom_properties: &HashMap<&Atom, BorrowedValue>,
|
||||||
|
input: &mut Parser,
|
||||||
start: &mut SourcePosition,
|
start: &mut SourcePosition,
|
||||||
substituted: &mut String,
|
substituted: &mut String,
|
||||||
custom_properties: &HashMap<&Atom, BorrowedValue>)
|
substituted_map: &mut HashMap<Atom, String>,
|
||||||
|
invalid: &mut HashSet<Atom>)
|
||||||
-> Result<(), ()> {
|
-> Result<(), ()> {
|
||||||
while let Ok(token) = input.next() {
|
while let Ok(token) = input.next() {
|
||||||
match token {
|
match token {
|
||||||
|
@ -252,12 +282,21 @@ fn substitute_block(input: &mut Parser,
|
||||||
let name = Atom::from_slice(&name[2..]);
|
let name = Atom::from_slice(&name[2..]);
|
||||||
|
|
||||||
if let Some(value) = custom_properties.get(&name) {
|
if let Some(value) = custom_properties.get(&name) {
|
||||||
return substitute_one(value, substituted, custom_properties)
|
try!(substitute_one(
|
||||||
|
&name, value, custom_properties,
|
||||||
|
Some(substituted), substituted_map, invalid));
|
||||||
|
// Skip over the fallback, as `parse_nested_block` would return `Err`
|
||||||
|
// if we don’t consume all of `input`.
|
||||||
|
// FIXME: Add a specialized method to cssparser to do this with less work.
|
||||||
|
while let Ok(_) = input.next() {}
|
||||||
|
} else {
|
||||||
|
try!(input.expect_comma());
|
||||||
|
let mut start = input.position();
|
||||||
|
try!(substitute_block(
|
||||||
|
custom_properties, input, &mut start, substituted,
|
||||||
|
substituted_map, invalid));
|
||||||
|
substituted.push_str(input.slice_from(start));
|
||||||
}
|
}
|
||||||
try!(input.expect_comma());
|
|
||||||
let mut start = input.position();
|
|
||||||
try!(substitute_block(input, &mut start, substituted, custom_properties));
|
|
||||||
substituted.push_str(input.slice_from(start));
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}));
|
}));
|
||||||
*start = input.position();
|
*start = input.position();
|
||||||
|
@ -267,9 +306,8 @@ fn substitute_block(input: &mut Parser,
|
||||||
Token::ParenthesisBlock |
|
Token::ParenthesisBlock |
|
||||||
Token::CurlyBracketBlock |
|
Token::CurlyBracketBlock |
|
||||||
Token::SquareBracketBlock => {
|
Token::SquareBracketBlock => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| substitute_block(
|
||||||
substitute_block(input, start, substituted, custom_properties)
|
custom_properties, input, start, substituted, substituted_map, invalid)));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue