From f91126ba861173dbf61c103332f27a9d1f5340c6 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Tue, 18 Jul 2017 19:13:48 +0900 Subject: [PATCH] Add has_current_styles_for_traversal(). In animation-only restyle, we just need to check the element has animation restyle hints or has recascade self which is a result of animation-only restyle for ancestors. has_current_styles() in Servo_ResolveStyle() is intentionally left there, it will be changed in a subsequent patch. --- components/style/dom.rs | 24 +++++++++++++++++++ .../invalidation/element/restyle_hints.rs | 7 ++++++ components/style/sharing/mod.rs | 2 +- components/style/traversal.rs | 11 ++++----- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/components/style/dom.rs b/components/style/dom.rs index f9173fa4f32..c14b59b763a 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -33,6 +33,7 @@ use std::ops::Deref; use stylearc::{Arc, ArcBorrow}; use stylist::Stylist; use thread_state; +use traversal::TraversalFlags; pub use style_traits::UnsafeNode; @@ -478,6 +479,29 @@ pub trait TElement : Eq + PartialEq + Debug + Hash + Sized + Copy + Clone + data.has_styles() && !data.has_invalidations() } + /// Returns whether the element's styles are up-to-date for |traversal_flags|. + fn has_current_styles_for_traversal(&self, + data: &ElementData, + traversal_flags: TraversalFlags) -> bool { + if traversal_flags.for_animation_only() { + // In animation-only restyle we never touch snapshots and don't + // care about them. But we can't assert '!self.handled_snapshot()' + // here since there are some cases that a second animation-only + // restyle which is a result of normal restyle (e.g. setting + // animation-name in normal restyle and creating a new CSS + // animation in a SequentialTask) is processed after the normal + // traversal in that we had elements that handled snapshot. + return data.has_styles() && + !data.restyle.hint.has_animation_hint_or_recascade(); + } + + if self.has_snapshot() && !self.handled_snapshot() { + return false; + } + + data.has_styles() && !data.has_invalidations() + } + /// Flags an element and its ancestors with a given `DescendantsBit`. /// /// TODO(emilio): We call this conservatively from restyle_element_internal diff --git a/components/style/invalidation/element/restyle_hints.rs b/components/style/invalidation/element/restyle_hints.rs index 4b968da031f..c9171d368cc 100644 --- a/components/style/invalidation/element/restyle_hints.rs +++ b/components/style/invalidation/element/restyle_hints.rs @@ -131,6 +131,13 @@ impl RestyleHint { self.intersects(Self::for_animations()) } + /// Returns whether the hint specifies that an animation cascade level must + /// be replaced. + #[inline] + pub fn has_animation_hint_or_recascade(&self) -> bool { + self.intersects(Self::for_animations() | RECASCADE_SELF) + } + /// Returns whether the hint specifies some restyle work other than an /// animation cascade level replacement. #[inline] diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs index f934d8cd5ab..462d0b16e1e 100644 --- a/components/style/sharing/mod.rs +++ b/components/style/sharing/mod.rs @@ -675,7 +675,7 @@ impl StyleSharingCandidateCache { } let data = candidate.element.borrow_data().unwrap(); - debug_assert!(target.has_current_styles(&data)); + debug_assert!(target.has_current_styles_for_traversal(&data, shared.traversal_flags)); debug!("Sharing style between {:?} and {:?}", target.element, candidate.element); diff --git a/components/style/traversal.rs b/components/style/traversal.rs index b9475ce7565..663ae72a433 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -328,8 +328,7 @@ pub trait DomTraversal : Sync { // animation-only restyle hint or recascade. if traversal_flags.for_animation_only() { return el.has_animation_only_dirty_descendants() || - data.restyle.hint.has_animation_hint() || - data.restyle.hint.has_recascade_self(); + data.restyle.hint.has_animation_hint_or_recascade(); } // If the dirty descendants bit is set, we need to traverse no matter @@ -341,7 +340,7 @@ pub trait DomTraversal : Sync { // If we have a restyle hint or need to recascade, we need to visit the // element. // - // Note that this is different than checking has_current_styles(), + // Note that this is different than checking has_current_styles_for_traversal(), // since that can return true even if we have a restyle hint indicating // that the element's descendants (but not necessarily the element) need // restyling. @@ -527,7 +526,8 @@ where debug_assert!(!element.has_snapshot() || element.handled_snapshot(), "Should've handled snapshots here already"); - let compute_self = !element.has_current_styles(data); + let compute_self = + !element.has_current_styles_for_traversal(data, context.shared.traversal_flags); let mut hint = RestyleHint::empty(); debug!("recalc_style_at: {:?} (compute_self={:?}, \ @@ -580,8 +580,7 @@ where propagated_hint, data.styles.is_display_none(), element.implemented_pseudo_element()); - debug_assert!(element.has_current_styles(data) || - context.shared.traversal_flags.for_animation_only(), + debug_assert!(element.has_current_styles_for_traversal(data, context.shared.traversal_flags), "Should have computed style or haven't yet valid computed \ style in case of animation-only restyle");