Bug 1343168 - Drop assertions and set initial values when setting animation property with empty vector. r? draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Wed, 01 Mar 2017 11:39:04 +0900
changeset 490652 0f2597225e96ee1e2815a9ebf9659c2597fb5e45
parent 490433 1bc2ad020aee2830e0a7941f10958dbec108c254
child 547335 bf1daaffa9ff2fda23ddcf8a2b200c8361d77657
push id47181
push userhikezoe@mozilla.com
push dateWed, 01 Mar 2017 02:39:37 +0000
bugs1343168
milestone54.0a1
Bug 1343168 - Drop assertions and set initial values when setting animation property with empty vector. r? MozReview-Commit-ID: Bsohywv5hIN
layout/style/test/stylo-failures.md
servo/components/style/properties/data.py
servo/components/style/properties/gecko.mako.rs
--- a/layout/style/test/stylo-failures.md
+++ b/layout/style/test/stylo-failures.md
@@ -55,17 +55,17 @@ Any line which doesn't follow the format
     * test_animations_event_handler_attribute.html [10]
     * test_animations_event_order.html [12]
   * SMIL Animation
     * test_restyles_in_smil_animation.html [2]
   * Property parsing and computation:
     * test_inherit_computation.html `animation` [6]
     * test_initial_computation.html `animation` [12]
     * test_property_syntax_errors.html `animation` [404]
-    * test_value_storage.html `animation` [1063]
+    * test_value_storage.html `animation` [1087]
 * test_any_dynamic.html: -moz-any pseudo class [2]
 * CSSOM support:
   * @namespace ##easy##
     * test_at_rule_parse_serialize.html [1]
     * test_bug765590.html [1]
     * test_font_face_parser.html `@namespace` [1]
   * @import
     * test_bug221428.html [1]
@@ -437,27 +437,25 @@ Any line which doesn't follow the format
     * ... `-moz-outline-radius:` [76]
     * test_shorthand_property_getters.html `should condense to shortest possible` [6]
   * transform property servo/servo#15194
     * test_value_storage.html `'transform` [104]
     * ... `"transform` [66]
     * ... `-webkit-transform` [109]
     * test_specified_value_serialization.html [27]
     * test_units_angle.html [3]
-  * test_value_storage.html `columns:`: servo/servo#15190 [32]
+  * test_value_storage.html `columns:`: servo/servo#15190 [20]
   * {background,mask}-position lacks comma for serialization servo/servo#15200
     * test_value_storage.html `background-position` [81]
     * ... `for 'mask-position` [18]
     * ... `for '-webkit-mask-position` [36]
     * ... `for '-webkit-mask` [3]
     * test_shorthand_property_getters.html `background-position` [3]
   * box-shadow wrong order of &lt;length&gt; values servo/servo#15203
     * test_value_storage.html `box-shadow` [44]
-  * outline shorthand generates "initial" as part servo/servo#15206
-    * test_value_storage.html `'outline:` [4]
   * border shorthand serializes when not Serializes servo/servo#15395
     * test_shorthand_property_getters.html `should not be able to serialize border` [7]
   * color value not canonicalized servo/servo#15397
     * test_shorthand_property_getters.html `should condense to canonical case` [2]
   * background-position invalid 3-value form **issue to be filed**
     * test_shorthand_property_getters.html `should serialize to 4-value` [2]
   * test_variables.html `--weird`: name of custom property is not escaped properly servo/servo#15399 [1]
   * ... `got "--`: CSS-wide keywords in custom properties servo/servo#15401 [3]
--- a/servo/components/style/properties/data.py
+++ b/servo/components/style/properties/data.py
@@ -78,16 +78,19 @@ class Keyword(object):
             return self.gecko_constant_prefix + "_" + suffix.upper()
 
     def needs_cast(self):
         return self.gecko_enum_prefix is None
 
     def maybe_cast(self, type_str):
         return "as " + type_str if self.needs_cast() else ""
 
+    def gecko_type_name(self, type_str):
+        return type_str if self.needs_cast() else self.gecko_enum_prefix
+
 
 def arg_to_bool(arg):
     if isinstance(arg, bool):
         return arg
     assert arg in ["True", "False"]
     return arg == "True"
 
 
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -1319,53 +1319,66 @@ fn static_assert() {
     pub fn animation_${ident}_count(&self) -> usize {
         self.gecko.mAnimation${gecko_ffi_name}Count as usize
     }
 </%def>
 
 <%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) {
-        assert!(v.0.len() > 0);
+        use properties::longhands::animation_${ident}::single_value::get_initial_value as get_initial_value;
+
         unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
 
         self.gecko.mAnimation${gecko_ffi_name}Count = v.0.len() as u32;
-        for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
-            gecko.m${gecko_ffi_name} = servo.seconds() * 1000.;
+        if v.0.len() > 0 {
+            for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
+                gecko.m${gecko_ffi_name} = servo.seconds() * 1000.;
+            }
+        } else {
+            self.gecko.mAnimation${gecko_ffi_name}Count = 1;
+            self.gecko.mAnimations[0].m${gecko_ffi_name} = get_initial_value().seconds() * 1000.;
         }
     }
     #[allow(non_snake_case)]
     pub fn animation_${ident}_at(&self, index: usize)
         -> longhands::animation_${ident}::computed_value::SingleComputedValue {
         use values::specified::Time;
         Time(self.gecko.mAnimations[index].m${gecko_ffi_name} / 1000.)
     }
     ${impl_animation_count(ident, gecko_ffi_name)}
     ${impl_copy_animation_value(ident, gecko_ffi_name)}
 </%def>
 
 <%def name="impl_animation_keyword(ident, gecko_ffi_name, keyword, cast_type='u8')">
     #[allow(non_snake_case)]
     pub fn set_animation_${ident}(&mut self, v: longhands::animation_${ident}::computed_value::T) {
         use properties::longhands::animation_${ident}::single_value::computed_value::T as Keyword;
-        use gecko_bindings::structs;
-
-        assert!(v.0.len() > 0);
+        use properties::longhands::animation_${ident}::single_value::get_initial_value as get_initial_value;
+        use gecko_bindings::structs::*;
+
         unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
 
-        self.gecko.mAnimation${gecko_ffi_name}Count = v.0.len() as u32;
-
-        for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
-            let result = match servo {
+        fn servo_keyword_to_gecko_value(servo: Keyword) -> ${keyword.gecko_type_name(cast_type)} {
+            match servo {
                 % for value in keyword.gecko_values():
                     Keyword::${to_rust_ident(value)} =>
-                        structs::${keyword.gecko_constant(value)} ${keyword.maybe_cast(cast_type)},
+                        ${keyword.gecko_constant(value)} ${keyword.maybe_cast(cast_type)},
                 % endfor
-            };
-            gecko.m${gecko_ffi_name} = result;
+            }
+        }
+        if v.0.len() > 0 {
+            self.gecko.mAnimation${gecko_ffi_name}Count = v.0.len() as u32;
+
+            for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
+                gecko.m${gecko_ffi_name} = servo_keyword_to_gecko_value(servo);
+            }
+        } else {
+            self.gecko.mAnimation${gecko_ffi_name}Count = 1;
+            self.gecko.mAnimations[0].m${gecko_ffi_name} = servo_keyword_to_gecko_value(get_initial_value());
         }
     }
     #[allow(non_snake_case)]
     pub fn animation_${ident}_at(&self, index: usize)
         -> longhands::animation_${ident}::computed_value::SingleComputedValue {
         use properties::longhands::animation_${ident}::single_value::computed_value::T as Keyword;
         match self.gecko.mAnimations[index].m${gecko_ffi_name} ${keyword.maybe_cast("u32")} {
             % for value in keyword.gecko_values():
@@ -1767,49 +1780,64 @@ fn static_assert() {
     ${impl_animation_keyword('fill_mode', 'FillMode',
                              data.longhands_by_name["animation-fill-mode"].keyword)}
     ${impl_animation_keyword('play_state', 'PlayState',
                              data.longhands_by_name["animation-play-state"].keyword)}
 
     pub fn set_animation_iteration_count(&mut self, v: longhands::animation_iteration_count::computed_value::T) {
         use std::f32;
         use properties::longhands::animation_iteration_count::single_value::SpecifiedValue as AnimationIterationCount;
-
-        assert!(v.0.len() > 0);
+        use properties::longhands::animation_iteration_count::single_value::get_initial_value as get_initial_value;
+
         unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
 
-        self.gecko.mAnimationIterationCountCount = v.0.len() as u32;
-        for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
+        fn servo_value_to_f32(servo: AnimationIterationCount) -> f32 {
             match servo {
-                AnimationIterationCount::Number(n) => gecko.mIterationCount = n,
-                AnimationIterationCount::Infinite => gecko.mIterationCount = f32::INFINITY,
+                AnimationIterationCount::Number(n) => n,
+                AnimationIterationCount::Infinite => f32::INFINITY,
             }
         }
+
+        if v.0.len() > 0 {
+            self.gecko.mAnimationIterationCountCount = v.0.len() as u32;
+            for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
+                gecko.mIterationCount = servo_value_to_f32(servo);
+            }
+        } else {
+            self.gecko.mAnimationIterationCountCount = 1;
+            self.gecko.mAnimations[0].mIterationCount = servo_value_to_f32(get_initial_value());
+        }
     }
     pub fn animation_iteration_count_at(&self, index: usize)
         -> longhands::animation_iteration_count::computed_value::SingleComputedValue {
         use properties::longhands::animation_iteration_count::single_value::computed_value::T
             as AnimationIterationCount;
 
         if self.gecko.mAnimations[index].mIterationCount.is_infinite() {
             AnimationIterationCount::Infinite
         } else {
             AnimationIterationCount::Number(self.gecko.mAnimations[index].mIterationCount)
         }
     }
     ${impl_animation_count('iteration_count', 'IterationCount')}
     ${impl_copy_animation_value('iteration_count', 'IterationCount')}
 
     pub fn set_animation_timing_function(&mut self, v: longhands::animation_timing_function::computed_value::T) {
-        assert!(v.0.len() > 0);
+        use properties::longhands::animation_timing_function::single_value::get_initial_value as get_initial_value;
+
         unsafe { self.gecko.mAnimations.ensure_len(v.0.len()) };
 
-        self.gecko.mAnimationTimingFunctionCount = v.0.len() as u32;
-        for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
-            gecko.mTimingFunction = servo.into();
+        if v.0.len() > 0 {
+            self.gecko.mAnimationTimingFunctionCount = v.0.len() as u32;
+            for (servo, gecko) in v.0.into_iter().zip(self.gecko.mAnimations.iter_mut()) {
+                gecko.mTimingFunction = servo.into();
+            }
+        } else {
+            self.gecko.mAnimationTimingFunctionCount = 1;
+            self.gecko.mAnimations[0].mTimingFunction = get_initial_value().into();
         }
     }
     ${impl_animation_count('timing_function', 'TimingFunction')}
     ${impl_copy_animation_value('timing_function', 'TimingFunction')}
     pub fn animation_timing_function_at(&self, index: usize)
         -> longhands::animation_timing_function::computed_value::SingleComputedValue {
         self.gecko.mAnimations[index].mTimingFunction.into()
     }