diff --git a/servo/components/style/properties/shorthands/ui.mako.rs b/servo/components/style/properties/shorthands/ui.mako.rs index 1915c65a63ad..9765a10376a7 100644 --- a/servo/components/style/properties/shorthands/ui.mako.rs +++ b/servo/components/style/properties/shorthands/ui.mako.rs @@ -295,13 +295,6 @@ macro_rules! try_parse_one { impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: fmt::Write { - use crate::values::specified::easing::TimingFunction; - use crate::values::specified::{ - AnimationDirection, AnimationFillMode, AnimationPlayState, - }; - use crate::Zero; - use style_traits::values::SequenceWriter; - let len = self.animation_name.0.len(); // There should be at least one declared value if len == 0 { @@ -327,83 +320,28 @@ macro_rules! try_parse_one { dest.write_str(", ")?; } - // We follow the order of this syntax: - // = - // || - // || - // || - // || - // || - // || - // || - // [ none | ] || - // - // - // https://drafts.csswg.org/css-animations-2/#animation-shorthand - // - // FIXME: Bug 1804574. The initial value of duration should be auto, per - // css-animations-2. - let has_duration = !self.animation_duration.0[i].is_zero(); - let has_timing_function = !self.animation_timing_function.0[i].is_ease(); - let has_delay = !self.animation_delay.0[i].is_zero(); - let has_iteration_count = !self.animation_iteration_count.0[i].is_one(); - let has_direction = - !matches!(self.animation_direction.0[i], AnimationDirection::Normal); - let has_fill_mode = - !matches!(self.animation_fill_mode.0[i], AnimationFillMode::None); - let has_play_state = - !matches!(self.animation_play_state.0[i], AnimationPlayState::Running); - let animation_name = &self.animation_name.0[i]; - let has_name = !animation_name.is_none(); - let has_timeline = match self.animation_timeline { - Some(timeline) => !timeline.0[i].is_auto(), - _ => false, - }; - - let mut writer = SequenceWriter::new(dest, " "); - - // To avoid ambiguity, we have to serialize duration if both duration is initial - // but delay is not. (In other words, it's ambiguous if we serialize delay only.) - if has_duration || has_delay { - writer.item(&self.animation_duration.0[i])?; - } - - if has_timing_function || TimingFunction::match_keywords(animation_name) { - writer.item(&self.animation_timing_function.0[i])?; - } - - // For animation-delay and animation-iteration-count. - % for name in props[4:6]: - if has_${name} { - writer.item(&self.animation_${name}.0[i])?; - } - % endfor - - if has_direction || AnimationDirection::match_keywords(animation_name) { - writer.item(&self.animation_direction.0[i])?; - } - - if has_fill_mode || AnimationFillMode::match_keywords(animation_name) { - writer.item(&self.animation_fill_mode.0[i])?; - } - - if has_play_state || AnimationPlayState::match_keywords(animation_name) { - writer.item(&self.animation_play_state.0[i])?; - } - - // If all values are initial, we must serialize animation-name. - let has_any = { - has_timeline % for name in props[2:]: - || has_${name} + self.animation_${name}.0[i].to_css(dest)?; + dest.write_char(' ')?; % endfor - }; - if has_name || !has_any { - writer.item(animation_name)?; - } - if has_timeline { - writer.item(&self.animation_timeline.unwrap().0[i])?; + self.animation_name.0[i].to_css(dest)?; + + // Based on the spec, the default values of other properties must be output in at + // least the cases necessary to distinguish an animation-name. The serialization + // order of animation-timeline is always later than animation-name, so it's fine + // to not serialize it if it is the default value. It's still possible to + // distinguish them (because we always serialize animation-name). + // https://drafts.csswg.org/css-animations-1/#animation + // https://drafts.csswg.org/css-animations-2/#typedef-single-animation + // + // Note: it's also fine to always serialize this. However, it seems Blink + // doesn't serialize default animation-timeline now, so we follow the same rule. + if let Some(ref timeline) = self.animation_timeline { + if !timeline.0[i].is_auto() { + dest.write_char(' ')?; + timeline.0[i].to_css(dest)?; + } } } Ok(()) diff --git a/servo/components/style/values/specified/animation.rs b/servo/components/style/values/specified/animation.rs index 552521711c44..5a1f5003f3e3 100644 --- a/servo/components/style/values/specified/animation.rs +++ b/servo/components/style/values/specified/animation.rs @@ -165,12 +165,6 @@ impl AnimationIterationCount { pub fn one() -> Self { Self::Number(NonNegativeNumber::new(1.0)) } - - /// Returns true if it's `1.0`. - #[inline] - pub fn is_one(&self) -> bool { - *self == Self::one() - } } /// A value for the `animation-name` property. @@ -236,17 +230,6 @@ pub enum AnimationDirection { AlternateReverse, } -impl AnimationDirection { - /// Returns true if the name matches any animation-direction keyword. - #[inline] - pub fn match_keywords(name: &AnimationName) -> bool { - if let Some(name) = name.as_atom() { - return name.with_str(|n| Self::from_ident(n).is_ok()); - } - false - } -} - /// https://drafts.csswg.org/css-animations/#animation-play-state #[derive(Copy, Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)] #[repr(u8)] @@ -256,17 +239,6 @@ pub enum AnimationPlayState { Paused, } -impl AnimationPlayState { - /// Returns true if the name matches any animation-play-state keyword. - #[inline] - pub fn match_keywords(name: &AnimationName) -> bool { - if let Some(name) = name.as_atom() { - return name.with_str(|n| Self::from_ident(n).is_ok()); - } - false - } -} - /// https://drafts.csswg.org/css-animations/#propdef-animation-fill-mode #[derive(Copy, Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)] #[repr(u8)] @@ -278,18 +250,6 @@ pub enum AnimationFillMode { Both, } -impl AnimationFillMode { - /// Returns true if the name matches any animation-fill-mode keyword. - /// Note: animation-name:none is its initial value, so we don't have to match none here. - #[inline] - pub fn match_keywords(name: &AnimationName) -> bool { - if let Some(atom) = name.as_atom() { - return !name.is_none() && atom.with_str(|n| Self::from_ident(n).is_ok()); - } - false - } -} - /// https://drafts.csswg.org/css-animations-2/#animation-composition #[derive(Copy, Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss, ToResolvedValue, ToShmem)] #[repr(u8)] diff --git a/servo/components/style/values/specified/easing.rs b/servo/components/style/values/specified/easing.rs index 7697e6a5d77b..5e4d8ae1eaf5 100644 --- a/servo/components/style/values/specified/easing.rs +++ b/servo/components/style/values/specified/easing.rs @@ -9,7 +9,7 @@ use crate::values::computed::easing::TimingFunction as ComputedTimingFunction; use crate::values::computed::{Context, ToComputedValue}; use crate::values::generics::easing::TimingFunction as GenericTimingFunction; use crate::values::generics::easing::{StepPosition, TimingKeyword}; -use crate::values::specified::{AnimationName, Integer, Number, Percentage}; +use crate::values::specified::{Integer, Number, Percentage}; use cssparser::{Delimiter, Parser, Token}; use selectors::parser::SelectorParseErrorKind; use style_traits::{ParseError, StyleParseErrorKind}; @@ -140,15 +140,6 @@ impl TimingFunction { Ok(GenericTimingFunction::LinearFunction(builder.build())) } - - /// Returns true if the name matches any keyword. - #[inline] - pub fn match_keywords(name: &AnimationName) -> bool { - if let Some(name) = name.as_atom() { - return name.with_str(|n| TimingKeyword::from_ident(n).is_ok()); - } - false - } } // We need this for converting the specified TimingFunction into computed TimingFunction without diff --git a/testing/web-platform/meta/css/css-animations/computed-style-animation-parsing.html.ini b/testing/web-platform/meta/css/css-animations/computed-style-animation-parsing.html.ini new file mode 100644 index 000000000000..6592d5a38f29 --- /dev/null +++ b/testing/web-platform/meta/css/css-animations/computed-style-animation-parsing.html.ini @@ -0,0 +1,3 @@ +[computed-style-animation-parsing.html] + expected: + if (os == "android") and fission: [OK, TIMEOUT] diff --git a/testing/web-platform/meta/css/css-animations/parsing/animation-computed.html.ini b/testing/web-platform/meta/css/css-animations/parsing/animation-computed.html.ini new file mode 100644 index 000000000000..3f430114419a --- /dev/null +++ b/testing/web-platform/meta/css/css-animations/parsing/animation-computed.html.ini @@ -0,0 +1,44 @@ +[animation-computed.html] + expected: + if (os == "android") and fission: [OK, TIMEOUT] + [Default animation value] + expected: FAIL + + [Property animation value '1s'] + expected: FAIL + + [Property animation value 'cubic-bezier(0, -2, 1, 3)'] + expected: FAIL + + [Property animation value 'ease-in-out'] + expected: FAIL + + [Property animation value '1s -3s'] + expected: FAIL + + [Property animation value '4'] + expected: FAIL + + [Property animation value 'reverse'] + expected: FAIL + + [Property animation value 'both'] + expected: FAIL + + [Property animation value 'paused'] + expected: FAIL + + [Property animation value 'none'] + expected: FAIL + + [Property animation value 'anim'] + expected: FAIL + + [Property animation value 'anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)'] + expected: FAIL + + [Property animation value 'none, none'] + expected: FAIL + + [Animation with a delay but no duration] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-animations/parsing/animation-valid.html.ini b/testing/web-platform/meta/css/css-animations/parsing/animation-valid.html.ini new file mode 100644 index 000000000000..302a9486b43e --- /dev/null +++ b/testing/web-platform/meta/css/css-animations/parsing/animation-valid.html.ini @@ -0,0 +1,26 @@ +[animation-valid.html] + expected: + if (os == "android") and fission: [TIMEOUT, OK] + [e.style['animation'\] = "cubic-bezier(0, -2, 1, 3)" should set the property value] + expected: FAIL + + [e.style['animation'\] = "4" should set the property value] + expected: FAIL + + [e.style['animation'\] = "reverse" should set the property value] + expected: FAIL + + [e.style['animation'\] = "both" should set the property value] + expected: FAIL + + [e.style['animation'\] = "paused" should set the property value] + expected: FAIL + + [e.style['animation'\] = "none" should set the property value] + expected: FAIL + + [e.style['animation'\] = "anim" should set the property value] + expected: FAIL + + [e.style['animation'\] = "anim paused both reverse, 4 1s -3s cubic-bezier(0, -2, 1, 3)" should set the property value] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-animations/style-animation-parsing.html.ini b/testing/web-platform/meta/css/css-animations/style-animation-parsing.html.ini new file mode 100644 index 000000000000..bb7e13512fd3 --- /dev/null +++ b/testing/web-platform/meta/css/css-animations/style-animation-parsing.html.ini @@ -0,0 +1,3 @@ +[style-animation-parsing.html] + expected: + if (os == "android") and fission: [OK, TIMEOUT]