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");