layout: Don't restart a transition if the end value for the new

transition is the same as the end value for a running transition per
CSS-TRANSITIONS § 3.

Besides being contrary to spec, the old behavior could cause a cascade
of CSS transitions incorrectly triggering themselves when calls to
`getComputedStyle()` were intermingled with them.

Improves performance of nytimes.com.
This commit is contained in:
Patrick Walton 2016-11-29 17:48:33 -08:00
parent f378f2807e
commit 89dff2d77f
3 changed files with 66 additions and 25 deletions

View file

@ -335,6 +335,11 @@ impl PropertyAnimation {
fn does_animate(&self) -> bool {
self.property.does_animate() && self.duration != Time(0.0)
}
#[inline]
pub fn has_the_same_end_value_as(&self, other: &PropertyAnimation) -> bool {
self.property.has_the_same_end_value_as(&other.property)
}
}
/// Inserts transitions into the queue of running animations as applicable for
@ -348,13 +353,24 @@ pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>
unsafe_node: UnsafeNode,
old_style: &ComputedValues,
new_style: &mut Arc<ComputedValues>,
timer: &Timer)
timer: &Timer,
possibly_expired_animations: &[PropertyAnimation])
-> bool {
let mut had_animations = false;
for i in 0..new_style.get_box().transition_property_count() {
// Create any property animations, if applicable.
let property_animations = PropertyAnimation::from_transition(i, old_style, Arc::make_mut(new_style));
for property_animation in property_animations {
// Per [1], don't trigger a new transition if the end state for that transition is
// the same as that of a transition that's already running on the same node.
//
// [1]: https://drafts.csswg.org/css-transitions/#starting
if possibly_expired_animations.iter().any(|animation| {
animation.has_the_same_end_value_as(&property_animation)
}) {
continue
}
// Set the property to the initial value.
// NB: get_mut is guaranteed to succeed since we called make_mut()
// above.