diff --git a/components/style/stylesheets/keyframes_rule.rs b/components/style/stylesheets/keyframes_rule.rs index 374f6f1d8ec..5172262014b 100644 --- a/components/style/stylesheets/keyframes_rule.rs +++ b/components/style/stylesheets/keyframes_rule.rs @@ -14,6 +14,7 @@ use crate::properties::{PropertyDeclarationId, SourcePropertyDeclaration}; use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, SharedRwLock, SharedRwLockReadGuard}; use crate::shared_lock::{Locked, ToCssWithGuard}; use crate::str::CssStringWriter; +use crate::stylesheets::layer_rule::LayerOrder; use crate::stylesheets::rule_parser::VendorPrefix; use crate::stylesheets::{CssRuleType, StylesheetContents}; use crate::values::{serialize_percentage, KeyframesName}; @@ -357,6 +358,8 @@ pub struct KeyframesAnimation { pub properties_changed: LonghandIdSet, /// Vendor prefix type the @keyframes has. pub vendor_prefix: Option, + /// The order of the cascade layer the keyframe rule was in. + pub layer_order: LayerOrder, } /// Get all the animated properties in a keyframes animation. @@ -409,12 +412,14 @@ impl KeyframesAnimation { pub fn from_keyframes( keyframes: &[Arc>], vendor_prefix: Option, + layer_order: LayerOrder, guard: &SharedRwLockReadGuard, ) -> Self { let mut result = KeyframesAnimation { steps: vec![], properties_changed: LonghandIdSet::new(), vendor_prefix, + layer_order, }; if keyframes.is_empty() { diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 6dc80e03ff5..489a9f5c6d4 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -2265,23 +2265,35 @@ impl CascadeData { self.rules_source_order += 1; }, CssRule::Keyframes(ref keyframes_rule) => { + use hashglobe::hash_map::Entry; + let keyframes_rule = keyframes_rule.read_with(guard); debug!("Found valid keyframes rule: {:?}", *keyframes_rule); - - // Don't let a prefixed keyframes animation override a non-prefixed one. - let needs_insertion = keyframes_rule.vendor_prefix.is_none() || - self.animations - .get(keyframes_rule.name.as_atom()) - .map_or(true, |rule| rule.vendor_prefix.is_some()); - if needs_insertion { - let animation = KeyframesAnimation::from_keyframes( - &keyframes_rule.keyframes, - keyframes_rule.vendor_prefix.clone(), - guard, - ); - debug!("Found valid keyframe animation: {:?}", animation); - self.animations - .try_insert(keyframes_rule.name.as_atom().clone(), animation)?; + match self.animations.try_entry(keyframes_rule.name.as_atom().clone())? { + Entry::Vacant(e) => { + e.insert(KeyframesAnimation::from_keyframes( + &keyframes_rule.keyframes, + keyframes_rule.vendor_prefix.clone(), + current_layer_order, + guard, + )); + }, + Entry::Occupied(mut e) => { + // Don't let a prefixed keyframes animation override + // a non-prefixed one on the same layer. + let needs_insert = + current_layer_order > e.get().layer_order || + (current_layer_order == e.get().layer_order && + (keyframes_rule.vendor_prefix.is_none() || e.get().vendor_prefix.is_some())); + if needs_insert { + e.insert(KeyframesAnimation::from_keyframes( + &keyframes_rule.keyframes, + keyframes_rule.vendor_prefix.clone(), + current_layer_order, + guard, + )); + } + }, } }, #[cfg(feature = "gecko")]