style: Propagate changes in custom properties' computed values to descendants.

If ComputedValues.custom_properties differs between the old and new
ComputedValues, indicate that we have to propogate changes to
descendants by setting child_cascade_requirement to
MustCascadeDescendants in cascade_primary.

style::matching::TElement::cascade_primary already calls
accumulate_damage, which eventually calls
ServoRestyleDamage::compute_style_difference in order to check if other
properties' computed values changed. If any of those change, we signal
that we need to propogate changes for inherited properties.

With Properties & Values, some custom properties will not be inherited,
and we will need to revisit this.
This commit is contained in:
Jonathan Chan 2017-06-12 15:03:25 -07:00
parent c1ea54d3c4
commit 32f62a5ac6
5 changed files with 57 additions and 2 deletions

View file

@ -66,7 +66,7 @@ pub struct BorrowedSpecifiedValue<'a> {
/// A computed value is just a set of tokens as well, until we resolve variables
/// properly.
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct ComputedValue {
css: String,

View file

@ -1894,6 +1894,13 @@ impl ComputedValues {
self.visited_style.clone()
}
// Aah! The << in the return type below is not valid syntax, but we must
// escape < that way for Mako.
/// Gets a reference to the custom properties map (if one exists).
pub fn get_custom_properties(&self) -> Option<<&::custom_properties::ComputedValuesMap> {
self.custom_properties.as_ref().map(|x| &**x)
}
/// Get the custom properties map if necessary.
///
/// Cloning the Arc here is fine because it only happens in the case where

View file

@ -64,7 +64,16 @@ impl ServoRestyleDamage {
new: &ServoComputedValues)
-> StyleDifference {
let damage = compute_damage(old, new);
let change = if damage.is_empty() { StyleChange::Unchanged } else { StyleChange::Changed };
// If computed values for custom properties changed, we should cascade these changes to
// children (custom properties are all inherited).
// https://www.w3.org/TR/css-variables/#defining-variables
// (With Properties & Values, not all custom properties will be inherited!)
let variable_values_changed = old.get_custom_properties() != new.get_custom_properties();
let change = if damage.is_empty() && !variable_values_changed {
StyleChange::Unchanged
} else {
StyleChange::Changed
};
StyleDifference::new(damage, change)
}

View file

@ -19992,6 +19992,12 @@
{}
]
],
"mozilla/upstream/css_variables_setProperty_recompute.html": [
[
"/_mozilla/mozilla/upstream/css_variables_setProperty_recompute.html",
{}
]
],
"mozilla/variadic-interface.html": [
[
"/_mozilla/mozilla/variadic-interface.html",
@ -31665,6 +31671,10 @@
"dfb31d3f9c4f24913055924c375f08b990b63e49",
"testharness"
],
"mozilla/upstream/css_variables_setProperty_recompute.html": [
"2e9326948f5115b3b63564fd26bae326bc8e2187",
"testharness"
],
"mozilla/variadic-interface.html": [
"9edd5150d36fabae42077a034655a8457eb75bff",
"testharness"

View file

@ -0,0 +1,29 @@
<!doctype html>
<meta charset="utf-8">
<title>Calling setProperty on a custom property should recompute its value inherited by children</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#parent {
--foo: bar;
}
</style>
<div id="parent">
<div id="child">
</div>
</div>
<script>
test(function () {
let parent = document.getElementById("parent");
let child = document.getElementById("child");
parent.style.setProperty("--foo", "old");
assert_equals(window.getComputedStyle(child).getPropertyValue("--foo"), "old");
parent.style.setProperty("--foo", "new");
assert_equals(window.getComputedStyle(child).getPropertyValue("--foo"), "new");
}, "Calling setProperty on a custom property should recompute its value inherited by children");
</script>