diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs index edf51d848b9..b477a653188 100644 --- a/components/layout_thread/dom_wrapper.rs +++ b/components/layout_thread/dom_wrapper.rs @@ -464,6 +464,54 @@ impl<'le> TElement for ServoLayoutElement<'le> { } } + fn may_have_animations(&self) -> bool { + true + } + + fn animation_rule( + &self, + context: &SharedStyleContext, + ) -> Option>> { + let node = self.as_node(); + let document = node.owner_doc(); + context + .animation_states + .read() + .get(&node.opaque()) + .and_then(|set| { + set.get_value_map_for_active_animations(context.current_time_for_animations) + }) + .map(|map| { + Arc::new( + document + .style_shared_lock() + .wrap(PropertyDeclarationBlock::from_animation_value_map(&map)), + ) + }) + } + + fn transition_rule( + &self, + context: &SharedStyleContext, + ) -> Option>> { + let node = self.as_node(); + let document = node.owner_doc(); + context + .animation_states + .read() + .get(&node.opaque()) + .and_then(|set| { + set.get_value_map_for_active_transitions(context.current_time_for_animations) + }) + .map(|map| { + Arc::new( + document + .style_shared_lock() + .wrap(PropertyDeclarationBlock::from_animation_value_map(&map)), + ) + }) + } + fn state(&self) -> ElementState { self.element.get_state_for_layout() } @@ -581,11 +629,8 @@ impl<'le> TElement for ServoLayoutElement<'le> { self.element.has_selector_flags(flags) } - fn has_animations(&self) -> bool { - // We use this function not only for Gecko but also for Servo to know if this element has - // animations, so we maybe try to get the important rules of this element. This is used for - // off-main thread animations, but we don't support it on Servo, so return false directly. - false + fn has_animations(&self, context: &SharedStyleContext) -> bool { + return self.has_css_animations(context) || self.has_css_transitions(context); } fn has_css_animations(&self, context: &SharedStyleContext) -> bool { @@ -597,8 +642,13 @@ impl<'le> TElement for ServoLayoutElement<'le> { .unwrap_or(false) } - fn has_css_transitions(&self) -> bool { - unreachable!("this should be only called on gecko"); + fn has_css_transitions(&self, context: &SharedStyleContext) -> bool { + context + .animation_states + .read() + .get(&self.as_node().opaque()) + .map(|set| set.has_active_transition()) + .unwrap_or(false) } #[inline] diff --git a/components/layout_thread_2020/dom_wrapper.rs b/components/layout_thread_2020/dom_wrapper.rs index 926866b9e14..037b927539e 100644 --- a/components/layout_thread_2020/dom_wrapper.rs +++ b/components/layout_thread_2020/dom_wrapper.rs @@ -472,6 +472,54 @@ impl<'le> TElement for ServoLayoutElement<'le> { } } + fn may_have_animations(&self) -> bool { + true + } + + fn animation_rule( + &self, + context: &SharedStyleContext, + ) -> Option>> { + let node = self.as_node(); + let document = node.owner_doc(); + context + .animation_states + .read() + .get(&node.opaque()) + .and_then(|set| { + set.get_value_map_for_active_animations(context.current_time_for_animations) + }) + .map(|map| { + Arc::new( + document + .style_shared_lock() + .wrap(PropertyDeclarationBlock::from_animation_value_map(&map)), + ) + }) + } + + fn transition_rule( + &self, + context: &SharedStyleContext, + ) -> Option>> { + let node = self.as_node(); + let document = node.owner_doc(); + context + .animation_states + .read() + .get(&node.opaque()) + .and_then(|set| { + set.get_value_map_for_active_transitions(context.current_time_for_animations) + }) + .map(|map| { + Arc::new( + document + .style_shared_lock() + .wrap(PropertyDeclarationBlock::from_animation_value_map(&map)), + ) + }) + } + fn state(&self) -> ElementState { self.element.get_state_for_layout() } @@ -589,11 +637,8 @@ impl<'le> TElement for ServoLayoutElement<'le> { self.element.has_selector_flags(flags) } - fn has_animations(&self) -> bool { - // We use this function not only for Gecko but also for Servo to know if this element has - // animations, so we maybe try to get the important rules of this element. This is used for - // off-main thread animations, but we don't support it on Servo, so return false directly. - false + fn has_animations(&self, context: &SharedStyleContext) -> bool { + return self.has_css_animations(context) || self.has_css_transitions(context); } fn has_css_animations(&self, context: &SharedStyleContext) -> bool { @@ -605,8 +650,13 @@ impl<'le> TElement for ServoLayoutElement<'le> { .unwrap_or(false) } - fn has_css_transitions(&self) -> bool { - unreachable!("this should be only called on gecko"); + fn has_css_transitions(&self, context: &SharedStyleContext) -> bool { + context + .animation_states + .read() + .get(&self.as_node().opaque()) + .map(|set| set.has_active_transition()) + .unwrap_or(false) } #[inline] diff --git a/components/style/animation.rs b/components/style/animation.rs index d7601a8ed73..b107aaaf262 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -10,7 +10,7 @@ use crate::bezier::Bezier; use crate::context::{CascadeInputs, SharedStyleContext}; use crate::dom::{OpaqueNode, TDocument, TElement, TNode}; -use crate::properties::animated_properties::AnimationValue; +use crate::properties::animated_properties::{AnimationValue, AnimationValueMap}; use crate::properties::longhands::animation_direction::computed_value::single_value::T as AnimationDirection; use crate::properties::longhands::animation_fill_mode::computed_value::single_value::T as AnimationFillMode; use crate::properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState; @@ -127,13 +127,11 @@ impl PropertyAnimation { } /// Update the given animation at a given point of progress. - fn update(&self, style: &mut ComputedValues, progress: f64) { + fn calculate_value(&self, progress: f64) -> Result { let procedure = Procedure::Interpolate { progress: self.timing_function_output(progress), }; - if let Ok(new_value) = self.from.animate(&self.to, procedure) { - new_value.set_in_style_for_servo(style); - } + self.from.animate(&self.to, procedure) } } @@ -598,16 +596,14 @@ impl Animation { } } - /// Update the given style to reflect the values specified by this `Animation` - /// at the time provided by the given `SharedStyleContext`. - fn update_style(&self, context: &SharedStyleContext, style: &mut Arc) { + /// Fill in an `AnimationValueMap` with values calculated from this animation at + /// the given time value. + fn get_property_declaration_at_time(&self, now: f64, map: &mut AnimationValueMap) { let duration = self.duration; let started_at = self.started_at; let now = match self.state { - AnimationState::Running | AnimationState::Pending | AnimationState::Finished => { - context.current_time_for_animations - }, + AnimationState::Running | AnimationState::Pending | AnimationState::Finished => now, AnimationState::Paused(progress) => started_at + duration * progress, AnimationState::Canceled => return, }; @@ -666,7 +662,7 @@ impl Animation { } debug!( - "Animation::update_style: keyframe from {:?} to {:?}", + "Animation::get_property_declaration_at_time: keyframe from {:?} to {:?}", prev_keyframe_index, next_keyframe_index ); @@ -676,20 +672,19 @@ impl Animation { None => return, }; - let update_with_single_keyframe_style = |style, keyframe: &ComputedKeyframe| { - let mutable_style = Arc::make_mut(style); + let mut add_declarations_to_map = |keyframe: &ComputedKeyframe| { for value in keyframe.values.iter() { - value.set_in_style_for_servo(mutable_style); + map.insert(value.id(), value.clone()); } }; if total_progress <= 0.0 { - update_with_single_keyframe_style(style, &prev_keyframe); + add_declarations_to_map(&prev_keyframe); return; } if total_progress >= 1.0 { - update_with_single_keyframe_style(style, &next_keyframe); + add_declarations_to_map(&next_keyframe); return; } @@ -707,18 +702,18 @@ impl Animation { }; let relative_progress = (now - last_keyframe_ended_at) / relative_duration; - let mut new_style = (**style).clone(); for (from, to) in prev_keyframe.values.iter().zip(next_keyframe.values.iter()) { - PropertyAnimation { + let animation = PropertyAnimation { from: from.clone(), to: to.clone(), timing_function: prev_keyframe.timing_function, duration: relative_duration as f64, - } - .update(&mut new_style, relative_progress); - } + }; - *Arc::make_mut(style) = new_style; + if let Ok(value) = animation.calculate_value(relative_progress) { + map.insert(value.id(), value); + } + } } } @@ -799,7 +794,10 @@ impl Transition { // time of the style change event, times the reversing shortening // factor of the old transition // 2. 1 minus the reversing shortening factor of the old transition." - let transition_progress = replaced_transition.progress(now); + let transition_progress = ((now - replaced_transition.start_time) / + (replaced_transition.property_animation.duration)) + .min(1.0) + .max(0.0); let timing_function_output = replaced_animation.timing_function_output(transition_progress); let old_reversing_shortening_factor = replaced_transition.reversing_shortening_factor; self.reversing_shortening_factor = ((timing_function_output * @@ -845,25 +843,16 @@ impl Transition { time >= self.start_time + (self.property_animation.duration) } - /// Whether this animation has the same end value as another one. - #[inline] - fn progress(&self, now: f64) -> f64 { - let progress = (now - self.start_time) / (self.property_animation.duration); - progress.min(1.0) - } - - /// Update a style to the value specified by this `Transition` given a `SharedStyleContext`. - fn update_style(&self, context: &SharedStyleContext, style: &mut Arc) { - // Never apply canceled transitions to a style. - if self.state == AnimationState::Canceled { - return; + /// Update the given animation at a given point of progress. + pub fn calculate_value(&self, time: f64) -> Option { + let progress = (time - self.start_time) / (self.property_animation.duration); + if progress < 0.0 { + return None; } - let progress = self.progress(context.current_time_for_animations); - if progress >= 0.0 { - self.property_animation - .update(Arc::make_mut(style), progress); - } + self.property_animation + .calculate_value(progress.min(1.0)) + .ok() } } @@ -875,17 +864,30 @@ pub struct ElementAnimationSet { /// The transitions for this element. pub transitions: Vec, + + /// Whether or not this ElementAnimationSet has had animations or transitions + /// which have been added, removed, or had their state changed. + pub dirty: bool, } impl ElementAnimationSet { /// Cancel all animations in this `ElementAnimationSet`. This is typically called /// when the element has been removed from the DOM. pub fn cancel_all_animations(&mut self) { + self.dirty = !self.animations.is_empty(); for animation in self.animations.iter_mut() { animation.state = AnimationState::Canceled; } + self.cancel_active_transitions(); + } + + fn cancel_active_transitions(&mut self) { + self.dirty = !self.transitions.is_empty(); + for transition in self.transitions.iter_mut() { - transition.state = AnimationState::Canceled; + if transition.state != AnimationState::Finished { + transition.state = AnimationState::Canceled; + } } } @@ -894,12 +896,18 @@ impl ElementAnimationSet { context: &SharedStyleContext, style: &mut Arc, ) { - for animation in &self.animations { - animation.update_style(context, style); + let now = context.current_time_for_animations; + let mutable_style = Arc::make_mut(style); + if let Some(map) = self.get_value_map_for_active_animations(now) { + for value in map.values() { + value.set_in_style_for_servo(mutable_style); + } } - for transition in &self.transitions { - transition.update_style(context, style); + if let Some(map) = self.get_value_map_for_active_transitions(now) { + for value in map.values() { + value.set_in_style_for_servo(mutable_style); + } } } @@ -978,6 +986,7 @@ impl ElementAnimationSet { /// when appropriate. pub fn update_transitions_for_new_style( &mut self, + might_need_transitions_update: bool, context: &SharedStyleContext, opaque_node: OpaqueNode, old_style: Option<&Arc>, @@ -990,12 +999,18 @@ impl ElementAnimationSet { None => return, }; + // If the style of this element is display:none, then cancel all active transitions. + if after_change_style.get_box().clone_display().is_none() { + self.cancel_active_transitions(); + return; + } + + if !might_need_transitions_update { + return; + } + // We convert old values into `before-change-style` here. - // See https://drafts.csswg.org/css-transitions/#starting. We need to clone the - // style because this might still be a reference to the original `old_style` and - // we want to preserve that so that we can later properly calculate restyle damage. if self.has_active_transition() || self.has_active_animation() { - before_change_style = before_change_style.clone(); self.apply_active_animations(context, &mut before_change_style); } @@ -1016,6 +1031,7 @@ impl ElementAnimationSet { continue; } transition.state = AnimationState::Canceled; + self.dirty = true; } } @@ -1086,6 +1102,45 @@ impl ElementAnimationSet { } self.transitions.push(new_transition); + self.dirty = true; + } + + /// Generate a `AnimationValueMap` for this `ElementAnimationSet`'s + /// active transitions at the given time value. + pub fn get_value_map_for_active_transitions(&self, now: f64) -> Option { + if !self.has_active_transition() { + return None; + } + + let mut map = + AnimationValueMap::with_capacity_and_hasher(self.transitions.len(), Default::default()); + for transition in &self.transitions { + if transition.state == AnimationState::Canceled { + continue; + } + let value = match transition.calculate_value(now) { + Some(value) => value, + None => continue, + }; + map.insert(value.id(), value); + } + + Some(map) + } + + /// Generate a `AnimationValueMap` for this `ElementAnimationSet`'s + /// active animations at the given time value. + pub fn get_value_map_for_active_animations(&self, now: f64) -> Option { + if !self.has_active_animation() { + return None; + } + + let mut map = Default::default(); + for animation in &self.animations { + animation.get_property_declaration_at_time(now, &mut map); + } + + Some(map) } } @@ -1098,13 +1153,6 @@ pub fn start_transitions_if_applicable( new_style: &Arc, animation_state: &mut ElementAnimationSet, ) -> LonghandIdSet { - // If the style of this element is display:none, then we don't start any transitions - // and we cancel any currently running transitions by returning an empty LonghandIdSet. - let box_style = new_style.get_box(); - if box_style.clone_display().is_none() { - return LonghandIdSet::new(); - } - let mut properties_that_transition = LonghandIdSet::new(); for transition in new_style.transition_properties() { let physical_property = transition.longhand_id.to_physical(new_style.writing_mode); @@ -1214,6 +1262,8 @@ pub fn maybe_start_animations( is_new: true, }; + animation_state.dirty = true; + // If the animation was already present in the list for the node, just update its state. for existing_animation in animation_state.animations.iter_mut() { if existing_animation.state == AnimationState::Canceled { diff --git a/components/style/dom.rs b/components/style/dom.rs index 4e8d8ce9ca8..9b61cfbd3af 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -479,23 +479,25 @@ pub trait TElement: /// Get the combined animation and transition rules. /// /// FIXME(emilio): Is this really useful? - fn animation_rules(&self) -> AnimationRules { + fn animation_rules(&self, context: &SharedStyleContext) -> AnimationRules { if !self.may_have_animations() { return AnimationRules(None, None); } - AnimationRules(self.animation_rule(), self.transition_rule()) + AnimationRules(self.animation_rule(context), self.transition_rule(context)) } /// Get this element's animation rule. - fn animation_rule(&self) -> Option>> { - None - } + fn animation_rule( + &self, + _: &SharedStyleContext, + ) -> Option>>; /// Get this element's transition rule. - fn transition_rule(&self) -> Option>> { - None - } + fn transition_rule( + &self, + context: &SharedStyleContext, + ) -> Option>>; /// Get this element's state, for non-tree-structural pseudos. fn state(&self) -> ElementState; @@ -729,9 +731,7 @@ pub trait TElement: /// In Gecko, element has a flag that represents the element may have /// any type of animations or not to bail out animation stuff early. /// Whereas Servo doesn't have such flag. - fn may_have_animations(&self) -> bool { - false - } + fn may_have_animations(&self) -> bool; /// Creates a task to update various animation state on a given (pseudo-)element. #[cfg(feature = "gecko")] @@ -748,14 +748,14 @@ pub trait TElement: /// Returns true if the element has relevant animations. Relevant /// animations are those animations that are affecting the element's style /// or are scheduled to do so in the future. - fn has_animations(&self) -> bool; + fn has_animations(&self, context: &SharedStyleContext) -> bool; /// Returns true if the element has a CSS animation. fn has_css_animations(&self, context: &SharedStyleContext) -> bool; /// Returns true if the element has a CSS transition (including running transitions and /// completed transitions). - fn has_css_transitions(&self) -> bool; + fn has_css_transitions(&self, context: &SharedStyleContext) -> bool; /// Returns true if the element has animation restyle hints. fn has_animation_restyle_hints(&self) -> bool { diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index fd119d93c6c..4d680c3ff02 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -1524,32 +1524,10 @@ impl<'le> TElement for GeckoElement<'le> { self.may_have_animations() && unsafe { Gecko_ElementHasCSSAnimations(self.0) } } - fn has_css_transitions(&self) -> bool { + fn has_css_transitions(&self, _: &SharedStyleContext) -> bool { self.may_have_animations() && unsafe { Gecko_ElementHasCSSTransitions(self.0) } } - fn might_need_transitions_update( - &self, - old_style: Option<&ComputedValues>, - new_style: &ComputedValues, - ) -> bool { - let old_style = match old_style { - Some(v) => v, - None => return false, - }; - - let new_box_style = new_style.get_box(); - if !self.has_css_transitions() && !new_box_style.specifies_transitions() { - return false; - } - - if new_box_style.clone_display().is_none() || old_style.clone_display().is_none() { - return false; - } - - return true; - } - // Detect if there are any changes that require us to update transitions. // This is used as a more thoroughgoing check than the, cheaper // might_need_transitions_update check. diff --git a/components/style/matching.rs b/components/style/matching.rs index 3e0c00aaa88..fda77cc2685 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -8,7 +8,7 @@ #![deny(missing_docs)] use crate::computed_value_flags::ComputedValueFlags; -use crate::context::{ElementCascadeInputs, QuirksMode, SelectorFlagsMap}; +use crate::context::{CascadeInputs, ElementCascadeInputs, QuirksMode, SelectorFlagsMap}; use crate::context::{SharedStyleContext, StyleContext}; use crate::data::ElementData; use crate::dom::TElement; @@ -176,7 +176,9 @@ trait PrivateMatchMethods: TElement { if replacements.contains(RestyleHint::RESTYLE_CSS_TRANSITIONS) { replace_rule_node( CascadeLevel::Transitions, - self.transition_rule().as_ref().map(|a| a.borrow_arc()), + self.transition_rule(&context.shared) + .as_ref() + .map(|a| a.borrow_arc()), primary_rules, ); } @@ -184,7 +186,9 @@ trait PrivateMatchMethods: TElement { if replacements.contains(RestyleHint::RESTYLE_CSS_ANIMATIONS) { replace_rule_node( CascadeLevel::Animations, - self.animation_rule().as_ref().map(|a| a.borrow_arc()), + self.animation_rule(&context.shared) + .as_ref() + .map(|a| a.borrow_arc()), primary_rules, ); } @@ -194,14 +198,11 @@ trait PrivateMatchMethods: TElement { } /// If there is no transition rule in the ComputedValues, it returns None. - #[cfg(feature = "gecko")] fn after_change_style( &self, context: &mut StyleContext, primary_style: &Arc, ) -> Option> { - use crate::context::CascadeInputs; - let rule_node = primary_style.rules(); let without_transition_rules = context .shared @@ -314,6 +315,29 @@ trait PrivateMatchMethods: TElement { false } + fn might_need_transitions_update( + &self, + context: &StyleContext, + old_style: Option<&ComputedValues>, + new_style: &ComputedValues, + ) -> bool { + let old_style = match old_style { + Some(v) => v, + None => return false, + }; + + let new_box_style = new_style.get_box(); + if !self.has_css_transitions(context.shared) && !new_box_style.specifies_transitions() { + return false; + } + + if new_box_style.clone_display().is_none() || old_style.clone_display().is_none() { + return false; + } + + return true; + } + /// Create a SequentialTask for resolving descendants in a SMIL display /// property animation if the display property changed from none. #[cfg(feature = "gecko")] @@ -374,10 +398,12 @@ trait PrivateMatchMethods: TElement { tasks.insert(UpdateAnimationsTasks::CSS_ANIMATIONS); } - let before_change_style = if self - .might_need_transitions_update(old_values.as_ref().map(|s| &**s), new_values) - { - let after_change_style = if self.has_css_transitions() { + let before_change_style = if self.might_need_transitions_update( + context, + old_values.as_ref().map(|s| &**s), + new_values, + ) { + let after_change_style = if self.has_css_transitions(context.shared) { self.after_change_style(context, new_values) } else { None @@ -442,6 +468,16 @@ trait PrivateMatchMethods: TElement { // map because this call will do a RwLock::read(). let needs_animations_update = self.needs_animations_update(context, old_values.as_ref().map(|s| &**s), new_values); + let might_need_transitions_update = self.might_need_transitions_update( + context, + old_values.as_ref().map(|s| &**s), + new_values, + ); + + let mut after_change_style = None; + if might_need_transitions_update { + after_change_style = self.after_change_style(context, new_values); + } let this_opaque = self.as_node().opaque(); let shared_context = context.shared; @@ -471,28 +507,43 @@ trait PrivateMatchMethods: TElement { } animation_set.update_transitions_for_new_style( + might_need_transitions_update, &shared_context, this_opaque, old_values.as_ref(), - new_values, + after_change_style.as_ref().unwrap_or(new_values), ); - animation_set.apply_active_animations(shared_context, new_values); - // We clear away any finished transitions, but retain animations, because they - // might still be used for proper calculation of `animation-fill-mode`. + // might still be used for proper calculation of `animation-fill-mode`. This + // should change the computed values in the style, so we don't need to mark + // this set as dirty. animation_set .transitions .retain(|transition| transition.state != AnimationState::Finished); // If the ElementAnimationSet is empty, and don't store it in order to // save memory and to avoid extra processing later. + let changed_animations = animation_set.dirty; if !animation_set.is_empty() { + animation_set.dirty = false; shared_context .animation_states .write() .insert(this_opaque, animation_set); } + + // If we have modified animation or transitions, we recascade style for this node. + if changed_animations { + let mut resolver = StyleResolverForElement::new( + *self, + context, + RuleInclusion::All, + PseudoElementResolution::IfApplicable, + ); + let new_primary = resolver.resolve_style_with_default_parents(); + *new_values = new_primary.primary.style.0; + } } /// Computes and applies non-redundant damage. diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index a098534793f..619b5b2fc54 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -2828,11 +2828,12 @@ pub mod style_structs { /// Returns whether there are any transitions specified. #[cfg(feature = "servo")] pub fn specifies_transitions(&self) -> bool { - // TODO(mrobinson): This should check the combined duration and not just - // the duration. - self.transition_duration_iter() - .take(self.transition_property_count()) - .any(|t| t.seconds() > 0.) + (0..self.transition_property_count()).any(|index| { + let combined_duration = + self.transition_duration_mod(index).seconds().max(0.) + + self.transition_delay_mod(index).seconds(); + combined_duration > 0. + }) } /// Returns true if animation properties are equal between styles, but without diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs index 7f85104cb7c..fab21901bd9 100644 --- a/components/style/sharing/mod.rs +++ b/components/style/sharing/mod.rs @@ -587,6 +587,7 @@ impl StyleSharingCache { style: &PrimaryStyle, validation_data_holder: Option<&mut StyleSharingTarget>, dom_depth: usize, + shared_context: &SharedStyleContext, ) { let parent = match element.traversal_parent() { Some(element) => element, @@ -619,7 +620,7 @@ impl StyleSharingCache { // * Our computed style can still be affected by animations after we no // longer match any animation rules, since removing animations involves // a sequential task and an additional traversal. - if element.has_animations() { + if element.has_animations(shared_context) { debug!("Failing to insert to the cache: running animations"); return; } @@ -700,6 +701,7 @@ impl StyleSharingCache { bloom_filter, nth_index_cache, selector_flags_map, + shared_context, ) }) } @@ -711,6 +713,7 @@ impl StyleSharingCache { bloom: &StyleBloom, nth_index_cache: &mut NthIndexCache, selector_flags_map: &mut SelectorFlagsMap, + shared_context: &SharedStyleContext, ) -> Option { debug_assert!(!target.is_in_native_anonymous_subtree()); @@ -770,7 +773,7 @@ impl StyleSharingCache { return None; } - if target.element.has_animations() { + if target.element.has_animations(shared_context) { trace!("Miss: Has Animations"); return None; } diff --git a/components/style/style_resolver.rs b/components/style/style_resolver.rs index f3f2c6b41b7..bb4a1c8f77b 100644 --- a/components/style/style_resolver.rs +++ b/components/style/style_resolver.rs @@ -433,7 +433,7 @@ where implemented_pseudo.as_ref(), self.element.style_attribute(), self.element.smil_override(), - self.element.animation_rules(), + self.element.animation_rules(self.context.shared), self.rule_inclusion, &mut applicable_declarations, &mut matching_context, diff --git a/components/style/traversal.rs b/components/style/traversal.rs index 48e42656e86..a60faaa446e 100644 --- a/components/style/traversal.rs +++ b/components/style/traversal.rs @@ -613,6 +613,7 @@ where &new_styles.primary, Some(&mut target), traversal_data.current_dom_depth, + &context.shared, ); new_styles @@ -669,6 +670,7 @@ where &new_styles.primary, None, traversal_data.current_dom_depth, + &context.shared, ); } diff --git a/tests/wpt/metadata-layout-2020/css/css-animations/animation-base-response-003.html.ini b/tests/wpt/metadata-layout-2020/css/css-animations/animation-base-response-003.html.ini deleted file mode 100644 index 261190d6a21..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-animations/animation-base-response-003.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[animation-base-response-003.html] - [Identical elements are all responsive to font-size animation] - expected: FAIL - diff --git a/tests/wpt/metadata-layout-2020/css/css-color/animation/opacity-interpolation.html.ini b/tests/wpt/metadata-layout-2020/css/css-color/animation/opacity-interpolation.html.ini index 4b117661081..864bb88190e 100644 --- a/tests/wpt/metadata-layout-2020/css/css-color/animation/opacity-interpolation.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-color/animation/opacity-interpolation.html.ini @@ -89,66 +89,3 @@ [Web Animations: property from [initial\] to [0.2\] at (0.3) should be [0.76\]] expected: FAIL - [CSS Transitions with transition: all: property from [inherit\] to [0.2\] at (1.5) should be [0\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [initial\] to [0.2\] at (1.5) should be [0\]] - expected: FAIL - - [CSS Transitions: property from [inherit\] to [0.2\] at (1.5) should be [0\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [unset\] to [0.2\] at (1.5) should be [0\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [0\] to [1\] at (-0.3) should be [0\]] - expected: FAIL - - [CSS Animations: property from [inherit\] to [0.2\] at (1.5) should be [0\]] - expected: FAIL - - [CSS Transitions: property from [initial\] to [0.2\] at (1.5) should be [0\]] - expected: FAIL - - [CSS Animations: property from [unset\] to [0.2\] at (-0.3) should be [1\]] - expected: FAIL - - [CSS Transitions: property from [unset\] to [0.2\] at (1.5) should be [0\]] - expected: FAIL - - [CSS Animations: property from [0\] to [1\] at (1.5) should be [1\]] - expected: FAIL - - [CSS Animations: property from [initial\] to [0.2\] at (1.5) should be [0\]] - expected: FAIL - - [CSS Animations: property from [0\] to [1\] at (-0.3) should be [0\]] - expected: FAIL - - [CSS Transitions: property from [initial\] to [0.2\] at (-0.3) should be [1\]] - expected: FAIL - - [CSS Animations: property from [unset\] to [0.2\] at (1.5) should be [0\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [initial\] to [0.2\] at (-0.3) should be [1\]] - expected: FAIL - - [CSS Transitions: property from [0\] to [1\] at (-0.3) should be [0\]] - expected: FAIL - - [CSS Transitions: property from [unset\] to [0.2\] at (-0.3) should be [1\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [unset\] to [0.2\] at (-0.3) should be [1\]] - expected: FAIL - - [CSS Animations: property from [initial\] to [0.2\] at (-0.3) should be [1\]] - expected: FAIL - - [CSS Transitions: property from [0\] to [1\] at (1.5) should be [1\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [0\] to [1\] at (1.5) should be [1\]] - expected: FAIL - diff --git a/tests/wpt/metadata-layout-2020/css/css-transitions/non-rendered-element-001.html.ini b/tests/wpt/metadata-layout-2020/css/css-transitions/non-rendered-element-001.html.ini deleted file mode 100644 index 545eae021e5..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transitions/non-rendered-element-001.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[non-rendered-element-001.html] - [Transitions do not run for an element newly rendered] - expected: FAIL - diff --git a/tests/wpt/metadata-layout-2020/css/css-transitions/transition-base-response-003.html.ini b/tests/wpt/metadata-layout-2020/css/css-transitions/transition-base-response-003.html.ini deleted file mode 100644 index 28a4e5febe6..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transitions/transition-base-response-003.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[transition-base-response-003.html] - [Identical elements are all responsive to font-size transition] - expected: FAIL - diff --git a/tests/wpt/metadata/css/css-animations/animation-base-response-003.html.ini b/tests/wpt/metadata/css/css-animations/animation-base-response-003.html.ini deleted file mode 100644 index 261190d6a21..00000000000 --- a/tests/wpt/metadata/css/css-animations/animation-base-response-003.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[animation-base-response-003.html] - [Identical elements are all responsive to font-size animation] - expected: FAIL - diff --git a/tests/wpt/metadata/css/css-transitions/non-rendered-element-001.html.ini b/tests/wpt/metadata/css/css-transitions/non-rendered-element-001.html.ini deleted file mode 100644 index 545eae021e5..00000000000 --- a/tests/wpt/metadata/css/css-transitions/non-rendered-element-001.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[non-rendered-element-001.html] - [Transitions do not run for an element newly rendered] - expected: FAIL - diff --git a/tests/wpt/metadata/css/css-transitions/transition-base-response-003.html.ini b/tests/wpt/metadata/css/css-transitions/transition-base-response-003.html.ini deleted file mode 100644 index 28a4e5febe6..00000000000 --- a/tests/wpt/metadata/css/css-transitions/transition-base-response-003.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[transition-base-response-003.html] - [Identical elements are all responsive to font-size transition] - expected: FAIL -