diff --git a/components/style/matching.rs b/components/style/matching.rs index 4680bed1bdf5..129b4884cbec 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -398,9 +398,7 @@ impl StyleSharingCandidateCache { return; } - let animation_count = box_style.animation_name_count(); - debug_assert!(animation_count > 0); - if animation_count > 1 || box_style.animation_name_at(0).0 != atom!("") { + if box_style.animation_name_count() > 0 { debug!("Failing to insert to the cache: animations"); return; } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 240a0926799c..1c26c4a8f5a9 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1324,7 +1324,7 @@ fn static_assert() { <%def name="impl_animation_time_value(ident, gecko_ffi_name)"> #[allow(non_snake_case)] pub fn set_animation_${ident}(&mut self, v: longhands::animation_${ident}::computed_value::T) { - debug_assert!(!v.0.is_empty()); + assert!(v.0.len() > 0); unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) }; self.gecko.mAnimation${gecko_ffi_name}Count = v.0.len() as u32; @@ -1348,7 +1348,7 @@ fn static_assert() { use properties::longhands::animation_${ident}::single_value::computed_value::T as Keyword; use gecko_bindings::structs; - debug_assert!(!v.0.is_empty()); + assert!(v.0.len() > 0); unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) }; self.gecko.mAnimation${gecko_ffi_name}Count = v.0.len() as u32; @@ -1727,14 +1727,15 @@ fn static_assert() { pub fn set_animation_name(&mut self, v: longhands::animation_name::computed_value::T) { use nsstring::nsCString; - - debug_assert!(!v.0.is_empty()); unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) }; - self.gecko.mAnimationNameCount = v.0.len() as u32; - for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) { - // TODO This is inefficient. We should fix this in bug 1329169. - gecko.mName.assign_utf8(&nsCString::from(servo.0.to_string())); + if v.0.len() > 0 { + self.gecko.mAnimationNameCount = v.0.len() as u32; + for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) { + gecko.mName.assign_utf8(&nsCString::from(servo.0.to_string())); + } + } else { + unsafe { self.gecko.mAnimations[0].mName.truncate(); } } } pub fn animation_name_at(&self, index: usize) @@ -1772,7 +1773,7 @@ fn static_assert() { use std::f32; use properties::longhands::animation_iteration_count::single_value::SpecifiedValue as AnimationIterationCount; - debug_assert!(!v.0.is_empty()); + assert!(v.0.len() > 0); unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) }; self.gecko.mAnimationIterationCountCount = v.0.len() as u32; @@ -1798,7 +1799,7 @@ fn static_assert() { ${impl_copy_animation_value('iteration_count', 'IterationCount')} pub fn set_animation_timing_function(&mut self, v: longhands::animation_timing_function::computed_value::T) { - debug_assert!(!v.0.is_empty()); + assert!(v.0.len() > 0); unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) }; self.gecko.mAnimationTimingFunctionCount = v.0.len() as u32; diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index ae749fcde168..696d90383534 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -460,11 +460,6 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", Time(0.0) } - #[inline] - pub fn get_initial_specified_value() -> SpecifiedValue { - SpecifiedValue(0.0) - } - pub fn parse(context: &ParserContext, input: &mut Parser) -> Result { Time::parse(context, input) } @@ -732,7 +727,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", #[inline] pub fn get_initial_specified_value() -> SpecifiedValue { - SpecifiedValue::Keyword(FunctionKeyword::Ease) + ToComputedValue::from_computed_value(&ease()) } pub fn parse(context: &ParserContext, input: &mut Parser) -> Result { @@ -781,6 +776,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", <%helpers:vector_longhand name="animation-name" + allow_empty="True" need_index="True" animatable="False", extra_prefixes="moz webkit" @@ -801,16 +797,6 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", #[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub struct SpecifiedValue(pub Atom); - #[inline] - pub fn get_initial_value() -> computed_value::T { - get_initial_specified_value() - } - - #[inline] - pub fn get_initial_specified_value() -> SpecifiedValue { - SpecifiedValue(atom!("")) - } - impl fmt::Display for SpecifiedValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) @@ -819,11 +805,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", impl ToCss for SpecifiedValue { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - if self.0 == atom!("") { - dest.write_str("none") - } else { - dest.write_str(&*self.0.to_string()) - } + dest.write_str(&*self.0.to_string()) } } @@ -831,11 +813,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", fn parse(_context: &ParserContext, input: &mut ::cssparser::Parser) -> Result { use cssparser::Token; Ok(match input.next() { - Ok(Token::Ident(ref value)) => SpecifiedValue(if value == "none" { - atom!("") - } else { - Atom::from(&**value) - }), + Ok(Token::Ident(ref value)) if value != "none" => SpecifiedValue(Atom::from(&**value)), Ok(Token::QuotedString(value)) => SpecifiedValue(Atom::from(&*value)), _ => return Err(()), }) @@ -857,7 +835,6 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", spec="https://drafts.csswg.org/css-animations/#propdef-animation-duration", allowed_in_keyframe_block="False"> pub use properties::longhands::transition_duration::single_value::computed_value; - pub use properties::longhands::transition_duration::single_value::get_initial_specified_value; pub use properties::longhands::transition_duration::single_value::{get_initial_value, parse}; pub use properties::longhands::transition_duration::single_value::SpecifiedValue; @@ -926,12 +903,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto", #[inline] pub fn get_initial_value() -> computed_value::T { - get_initial_specified_value() - } - - #[inline] - pub fn get_initial_specified_value() -> SpecifiedValue { - SpecifiedValue::Number(1.0) + computed_value::T::Number(1.0) } #[inline] @@ -983,7 +955,6 @@ ${helpers.single_keyword("animation-fill-mode", spec="https://drafts.csswg.org/css-animations/#propdef-animation-delay", allowed_in_keyframe_block="False"> pub use properties::longhands::transition_duration::single_value::computed_value; - pub use properties::longhands::transition_duration::single_value::get_initial_specified_value; pub use properties::longhands::transition_duration::single_value::{get_initial_value, parse}; pub use properties::longhands::transition_duration::single_value::SpecifiedValue; diff --git a/components/style/properties/shorthand/box.mako.rs b/components/style/properties/shorthand/box.mako.rs index c951c3833ad8..3bb821fe737e 100644 --- a/components/style/properties/shorthand/box.mako.rs +++ b/components/style/properties/shorthand/box.mako.rs @@ -153,26 +153,32 @@ macro_rules! try_parse_one { animation-fill-mode animation-play-state" allowed_in_keyframe_block="False" spec="https://drafts.csswg.org/css-animations/#propdef-animation"> - <% - props = "name duration timing_function delay iteration_count \ - direction fill_mode play_state".split() - %> use parser::Parse; - % for prop in props: - use properties::longhands::animation_${prop}; - % endfor + use properties::longhands::{animation_name, animation_duration, animation_timing_function}; + use properties::longhands::{animation_delay, animation_iteration_count, animation_direction}; + use properties::longhands::{animation_fill_mode, animation_play_state}; pub fn parse_value(context: &ParserContext, input: &mut Parser) -> Result { struct SingleAnimation { - % for prop in props: - animation_${prop}: animation_${prop}::SingleSpecifiedValue, - % endfor + animation_name: animation_name::SingleSpecifiedValue, + animation_duration: animation_duration::SingleSpecifiedValue, + animation_timing_function: animation_timing_function::SingleSpecifiedValue, + animation_delay: animation_delay::SingleSpecifiedValue, + animation_iteration_count: animation_iteration_count::SingleSpecifiedValue, + animation_direction: animation_direction::SingleSpecifiedValue, + animation_fill_mode: animation_fill_mode::SingleSpecifiedValue, + animation_play_state: animation_play_state::SingleSpecifiedValue, } fn parse_one_animation(context: &ParserContext, input: &mut Parser) -> Result { - % for prop in props: - let mut ${prop} = None; - % endfor + let mut duration = None; + let mut timing_function = None; + let mut delay = None; + let mut iteration_count = None; + let mut direction = None; + let mut fill_mode = None; + let mut play_state = None; + let mut name = None; // NB: Name must be the last one here so that keywords valid for other // longhands are not interpreted as names. @@ -192,29 +198,62 @@ macro_rules! try_parse_one { break } - Ok(SingleAnimation { - % for prop in props: - animation_${prop}: ${prop}.unwrap_or_else(animation_${prop}::single_value - ::get_initial_specified_value), - % endfor - }) + if let Some(name) = name { + Ok(SingleAnimation { + animation_name: name, + animation_duration: + duration.unwrap_or_else(animation_duration::single_value::get_initial_value), + animation_timing_function: + timing_function.unwrap_or_else(animation_timing_function::single_value + ::get_initial_specified_value), + animation_delay: + delay.unwrap_or_else(animation_delay::single_value::get_initial_value), + animation_iteration_count: + iteration_count.unwrap_or_else(animation_iteration_count::single_value::get_initial_value), + animation_direction: + direction.unwrap_or_else(animation_direction::single_value::get_initial_value), + animation_fill_mode: + fill_mode.unwrap_or_else(animation_fill_mode::single_value::get_initial_value), + animation_play_state: + play_state.unwrap_or_else(animation_play_state::single_value::get_initial_value), + }) + } else { + Err(()) + } } - % for prop in props: - let mut ${prop}s = vec![]; - % endfor + let mut names = vec![]; + let mut durations = vec![]; + let mut timing_functions = vec![]; + let mut delays = vec![]; + let mut iteration_counts = vec![]; + let mut directions = vec![]; + let mut fill_modes = vec![]; + let mut play_states = vec![]; - let results = try!(input.parse_comma_separated(|i| parse_one_animation(context, i))); - for result in results.into_iter() { - % for prop in props: - ${prop}s.push(result.animation_${prop}); - % endfor + if input.try(|input| input.expect_ident_matching("none")).is_err() { + let results = try!(input.parse_comma_separated(|i| parse_one_animation(context, i))); + for result in results.into_iter() { + names.push(result.animation_name); + durations.push(result.animation_duration); + timing_functions.push(result.animation_timing_function); + delays.push(result.animation_delay); + iteration_counts.push(result.animation_iteration_count); + directions.push(result.animation_direction); + fill_modes.push(result.animation_fill_mode); + play_states.push(result.animation_play_state); + } } Ok(Longhands { - % for prop in props: - animation_${prop}: animation_${prop}::SpecifiedValue(${prop}s), - % endfor + animation_name: animation_name::SpecifiedValue(names), + animation_duration: animation_duration::SpecifiedValue(durations), + animation_timing_function: animation_timing_function::SpecifiedValue(timing_functions), + animation_delay: animation_delay::SpecifiedValue(delays), + animation_iteration_count: animation_iteration_count::SpecifiedValue(iteration_counts), + animation_direction: animation_direction::SpecifiedValue(directions), + animation_fill_mode: animation_fill_mode::SpecifiedValue(fill_modes), + animation_play_state: animation_play_state::SpecifiedValue(play_states), }) } @@ -226,9 +265,14 @@ macro_rules! try_parse_one { return Ok(()); } + <% + subproperties = "duration timing_function delay direction \ + fill_mode iteration_count play_state".split() + %> + // If any value list length is differs then we don't do a shorthand serialization // either. - % for name in props[1:]: + % for name in subproperties: if len != self.animation_${name}.0.len() { return Ok(()) } @@ -239,7 +283,7 @@ macro_rules! try_parse_one { try!(write!(dest, ", ")); } - % for name in props[1:]: + % for name in subproperties: self.animation_${name}.0[i].to_css(dest)?; dest.write_str(" ")?; % endfor diff --git a/tests/unit/style/lib.rs b/tests/unit/style/lib.rs index bb88a538a733..184ff4e15792 100644 --- a/tests/unit/style/lib.rs +++ b/tests/unit/style/lib.rs @@ -14,7 +14,7 @@ extern crate parking_lot; extern crate rayon; extern crate rustc_serialize; extern crate selectors; -#[macro_use] extern crate servo_atoms; +extern crate servo_atoms; extern crate servo_config; extern crate servo_url; extern crate style; diff --git a/tests/unit/style/parsing/animation.rs b/tests/unit/style/parsing/animation.rs index bf9f3b3e2eea..ed7467909209 100644 --- a/tests/unit/style/parsing/animation.rs +++ b/tests/unit/style/parsing/animation.rs @@ -5,27 +5,11 @@ use cssparser::Parser; use media_queries::CSSErrorReporterTest; use parsing::parse; -use servo_atoms::Atom; use style::parser::{Parse, ParserContext}; use style::properties::longhands::animation_iteration_count::single_value::computed_value::T as AnimationIterationCount; -use style::properties::longhands::animation_name; use style::stylesheets::Origin; use style_traits::ToCss; -#[test] -fn test_animation_name() { - use self::animation_name::single_value::SpecifiedValue as SingleValue; - let other_name = Atom::from("other-name"); - assert_eq!(parse_longhand!(animation_name, "none"), - animation_name::SpecifiedValue(vec![SingleValue(atom!(""))])); - assert_eq!(parse_longhand!(animation_name, "other-name, none, 'other-name', \"other-name\""), - animation_name::SpecifiedValue( - vec![SingleValue(other_name.clone()), - SingleValue(atom!("")), - SingleValue(other_name.clone()), - SingleValue(other_name.clone())])); -} - #[test] fn test_animation_iteration() { assert_roundtrip_with_context!(AnimationIterationCount::parse, "0", "0"); diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs index 9433d97ed3d6..9e99169c54de 100644 --- a/tests/unit/style/properties/serialization.rs +++ b/tests/unit/style/properties/serialization.rs @@ -983,7 +983,7 @@ mod shorthand_serialization { let serialization = block.to_css_string(); - assert_eq!(serialization, "animation: 1s ease-in 0s infinite normal forwards paused bounce;") + assert_eq!(serialization, "animation: 1s ease-in 0s normal forwards infinite paused bounce;") } #[test] @@ -1001,8 +1001,8 @@ mod shorthand_serialization { let serialization = block.to_css_string(); assert_eq!(serialization, - "animation: 1s ease-in 0s infinite normal forwards paused bounce, \ - 0.2s linear 1s 2 reverse backwards running roll;"); + "animation: 1s ease-in 0s normal forwards infinite paused bounce, \ + 0.2s linear 1s reverse backwards 2 running roll;"); } #[test]