mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Remove custom property declarations in dependency cycles.
This commit is contained in:
parent
09e60beb78
commit
65d4ecaa39
3 changed files with 59 additions and 5 deletions
|
@ -12,7 +12,7 @@ pub struct Value {
|
||||||
/// In CSS syntax
|
/// In CSS syntax
|
||||||
pub value: String,
|
pub value: String,
|
||||||
|
|
||||||
/// Custom property names in var() functions
|
/// Custom property names in var() functions. Do not include the `--` prefix.
|
||||||
pub references: HashSet<Atom>,
|
pub references: HashSet<Atom>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +109,8 @@ fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>, references: &mut HashS
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add one custom property declaration to a map,
|
||||||
|
/// unless another with the same name was already there.
|
||||||
pub fn cascade(custom_properties: &mut Option<Map>, inherited_custom_properties: &Option<Arc<Map>>,
|
pub fn cascade(custom_properties: &mut Option<Map>, inherited_custom_properties: &Option<Arc<Map>>,
|
||||||
name: &Atom, value: &Value) {
|
name: &Atom, value: &Value) {
|
||||||
let map = match *custom_properties {
|
let map = match *custom_properties {
|
||||||
|
@ -123,3 +125,54 @@ pub fn cascade(custom_properties: &mut Option<Map>, inherited_custom_properties:
|
||||||
};
|
};
|
||||||
map.entry(name.clone()).or_insert(value.clone());
|
map.entry(name.clone()).or_insert(value.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If any custom property declarations where found for this element (`custom_properties.is_some()`)
|
||||||
|
/// remove cycles and move the map into an `Arc`.
|
||||||
|
/// Otherwise, default to the inherited map.
|
||||||
|
pub fn finish_cascade(custom_properties: Option<Map>,
|
||||||
|
inherited_custom_properties: &Option<Arc<Map>>)
|
||||||
|
-> Option<Arc<Map>> {
|
||||||
|
if let Some(mut map) = custom_properties {
|
||||||
|
remove_cycles(&mut map);
|
||||||
|
Some(Arc::new(map))
|
||||||
|
} else {
|
||||||
|
inherited_custom_properties.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://drafts.csswg.org/css-variables/#cycles
|
||||||
|
fn remove_cycles(map: &mut Map) {
|
||||||
|
let mut to_remove = HashSet::new();
|
||||||
|
{
|
||||||
|
let mut visited = HashSet::new();
|
||||||
|
let mut stack = Vec::new();
|
||||||
|
for name in map.keys() {
|
||||||
|
walk(map, name, &mut stack, &mut visited, &mut to_remove);
|
||||||
|
|
||||||
|
fn walk<'a>(map: &'a Map, name: &'a Atom, stack: &mut Vec<&'a Atom>,
|
||||||
|
visited: &mut HashSet<&'a Atom>, to_remove: &mut HashSet<Atom>) {
|
||||||
|
let was_not_already_present = visited.insert(name);
|
||||||
|
if !was_not_already_present {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let Some(value) = map.get(name) {
|
||||||
|
stack.push(name);
|
||||||
|
for next in &value.references {
|
||||||
|
if let Some(position) = stack.position_elem(&next) {
|
||||||
|
// Found a cycle
|
||||||
|
for in_cycle in &stack[position..] {
|
||||||
|
to_remove.insert((**in_cycle).clone());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
walk(map, next, stack, visited, to_remove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for name in &to_remove {
|
||||||
|
map.remove(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#![feature(custom_attribute)]
|
#![feature(custom_attribute)]
|
||||||
#![feature(custom_derive)]
|
#![feature(custom_derive)]
|
||||||
#![feature(plugin)]
|
#![feature(plugin)]
|
||||||
|
#![feature(slice_position_elem)]
|
||||||
#![feature(vec_push_all)]
|
#![feature(vec_push_all)]
|
||||||
|
|
||||||
#![plugin(serde_macros)]
|
#![plugin(serde_macros)]
|
||||||
|
|
|
@ -6174,8 +6174,8 @@ fn cascade_with_cached_declarations(
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
${style_struct.ident}: style_${style_struct.ident},
|
${style_struct.ident}: style_${style_struct.ident},
|
||||||
% endfor
|
% endfor
|
||||||
custom_properties: custom_properties
|
custom_properties: ::custom_properties::finish_cascade(
|
||||||
.map(Arc::new).or_else(|| parent_style.custom_properties.clone()),
|
custom_properties, &parent_style.custom_properties),
|
||||||
shareable: shareable,
|
shareable: shareable,
|
||||||
root_font_size: parent_style.root_font_size,
|
root_font_size: parent_style.root_font_size,
|
||||||
}
|
}
|
||||||
|
@ -6451,8 +6451,8 @@ pub fn cascade(viewport_size: Size2D<Au>,
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
${style_struct.ident}: style.${style_struct.ident},
|
${style_struct.ident}: style.${style_struct.ident},
|
||||||
% endfor
|
% endfor
|
||||||
custom_properties: custom_properties
|
custom_properties: ::custom_properties::finish_cascade(
|
||||||
.map(Arc::new).or_else(|| inherited_style.custom_properties.clone()),
|
custom_properties, &inherited_style.custom_properties),
|
||||||
shareable: shareable,
|
shareable: shareable,
|
||||||
root_font_size: context.root_font_size,
|
root_font_size: context.root_font_size,
|
||||||
}, cacheable)
|
}, cacheable)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue