Backed out 4 changesets (bug 1458814) for failres in builds/worker/workspace/build/tests/reftest/tests/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-pct-pct.svg on a CLOSED TREE
authorNoemi Erli <nerli@mozilla.com>
Fri, 04 May 2018 08:39:52 +0300
changeset 472993 5630f78d35cf0e4f7410ba08588ed055bdcc60bb
parent 472992 b917e7e80a51f27410b9fde249c72ae49803a163
child 472994 8994f35fe5fc89f4e8f4e09579a6962f8a4a3e65
child 473037 04d34700272c7d4372a71f8f97a30d13ced2580d
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1458814
milestone61.0a1
backs outd0990dff4fc4eabd59b09cf6f9ff5c0e0f64fe9c
c61d211a9f1d365936d40f50844b5ca389a5c070
e7f7ea7ab4af8fe7a9ded72d994845915be0af73
9ac18a3eeaa566385ddf34fd04f13d02a71445fe
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1458814) for failres in builds/worker/workspace/build/tests/reftest/tests/layout/reftests/svg/smil/style/anim-css-strokewidth-1-to-pct-pct.svg on a CLOSED TREE Backed out changeset d0990dff4fc4 (bug 1458814) Backed out changeset c61d211a9f1d (bug 1458814) Backed out changeset e7f7ea7ab4af (bug 1458814) Backed out changeset 9ac18a3eeaa5 (bug 1458814)
dom/smil/nsSMILCSSValueType.cpp
dom/smil/nsSMILCSSValueType.h
layout/style/ServoBindingList.h
layout/style/StyleAnimationValue.cpp
layout/style/StyleAnimationValue.h
layout/style/nsDOMCSSAttrDeclaration.cpp
servo/ports/geckolib/glue.rs
--- a/dom/smil/nsSMILCSSValueType.cpp
+++ b/dom/smil/nsSMILCSSValueType.cpp
@@ -11,19 +11,17 @@
 #include "nsComputedDOMStyle.h"
 #include "nsString.h"
 #include "nsSMILParserUtils.h"
 #include "nsSMILValue.h"
 #include "nsCSSProps.h"
 #include "nsCSSValue.h"
 #include "nsColor.h"
 #include "nsPresContext.h"
-#include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/ServoBindings.h"
-#include "mozilla/ServoDeclarationBlock.h"
 #include "mozilla/StyleAnimationValue.h" // For AnimationValue
 #include "mozilla/ServoCSSParser.h"
 #include "mozilla/ServoStyleSet.h"
 #include "mozilla/dom/BaseKeyframeTypesBinding.h" // For CompositeOperation
 #include "mozilla/dom/Element.h"
 #include "nsDebug.h"
 #include "nsStyleUtil.h"
 #include "nsIDocument.h"
@@ -35,43 +33,49 @@ using mozilla::StyleAnimationValue;
 typedef AutoTArray<RefPtr<RawServoAnimationValue>, 1> ServoAnimationValues;
 
 /*static*/ nsSMILCSSValueType nsSMILCSSValueType::sSingleton;
 
 struct ValueWrapper {
   ValueWrapper(nsCSSPropertyID aPropID, const AnimationValue& aValue)
     : mPropID(aPropID)
   {
-    MOZ_ASSERT(!aValue.IsNull());
-    mServoValues.AppendElement(aValue.mServo);
+    if (aValue.mServo) {
+      mServoValues.AppendElement(aValue.mServo);
+      return;
+    }
+    MOZ_CRASH("old style system disabled");
   }
   ValueWrapper(nsCSSPropertyID aPropID,
                const RefPtr<RawServoAnimationValue>& aValue)
     : mPropID(aPropID), mServoValues{(aValue)} {}
   ValueWrapper(nsCSSPropertyID aPropID, ServoAnimationValues&& aValues)
     : mPropID(aPropID), mServoValues{aValues} {}
 
   bool operator==(const ValueWrapper& aOther) const
   {
     if (mPropID != aOther.mPropID) {
       return false;
     }
 
-    MOZ_ASSERT(!mServoValues.IsEmpty());
-    size_t len = mServoValues.Length();
-    if (len != aOther.mServoValues.Length()) {
-      return false;
-    }
-    for (size_t i = 0; i < len; i++) {
-      if (!Servo_AnimationValue_DeepEqual(mServoValues[i],
-                                          aOther.mServoValues[i])) {
+    if (!mServoValues.IsEmpty()) {
+      size_t len = mServoValues.Length();
+      if (len != aOther.mServoValues.Length()) {
         return false;
       }
+      for (size_t i = 0; i < len; i++) {
+        if (!Servo_AnimationValue_DeepEqual(mServoValues[i],
+                                            aOther.mServoValues[i])) {
+          return false;
+        }
+      }
+      return true;
     }
-    return true;
+
+    MOZ_CRASH("old style system disabled");
   }
 
   bool operator!=(const ValueWrapper& aOther) const
   {
     return !(*this == aOther);
   }
 
   nsCSSPropertyID mPropID;
@@ -295,21 +299,28 @@ AddOrAccumulate(nsSMILValue& aDest, cons
       property == eCSSProperty_stroke_dasharray) {
     return false;
   }
   // Skip font shorthand since it includes font-size-adjust.
   if (property == eCSSProperty_font) {
     return false;
   }
 
-  return AddOrAccumulateForServo(aDest,
-                                 valueToAddWrapper,
-                                 destWrapper,
-                                 aCompositeOp,
-                                 aCount);
+  bool isServo = valueToAddWrapper
+                 ? !valueToAddWrapper->mServoValues.IsEmpty()
+                 : !destWrapper->mServoValues.IsEmpty();
+  if (isServo) {
+    return AddOrAccumulateForServo(aDest,
+                                   valueToAddWrapper,
+                                   destWrapper,
+                                   aCompositeOp,
+                                   aCount);
+  }
+
+  MOZ_CRASH("old style system disabled");
 }
 
 nsresult
 nsSMILCSSValueType::SandwichAdd(nsSMILValue& aDest,
                                 const nsSMILValue& aValueToAdd) const
 {
   return AddOrAccumulate(aDest, aValueToAdd, CompositeOperation::Add, 1)
          ? NS_OK
@@ -371,17 +382,22 @@ nsSMILCSSValueType::ComputeDistance(cons
 {
   MOZ_ASSERT(aFrom.mType == aTo.mType,
              "Trying to compare different types");
   MOZ_ASSERT(aFrom.mType == this, "Unexpected source type");
 
   const ValueWrapper* fromWrapper = ExtractValueWrapper(aFrom);
   const ValueWrapper* toWrapper = ExtractValueWrapper(aTo);
   MOZ_ASSERT(toWrapper, "expecting non-null endpoint");
-  return ComputeDistanceForServo(fromWrapper, *toWrapper, aDistance);
+
+  if (!toWrapper->mServoValues.IsEmpty()) {
+    return ComputeDistanceForServo(fromWrapper, *toWrapper, aDistance);
+  }
+
+  MOZ_CRASH("old style system disabled");
 }
 
 
 static nsresult
 InterpolateForServo(const ValueWrapper* aStartWrapper,
                     const ValueWrapper& aEndWrapper,
                     double aUnitDistance,
                     nsSMILValue& aResult)
@@ -445,20 +461,25 @@ nsSMILCSSValueType::Interpolate(const ns
   MOZ_ASSERT(aResult.mType == this, "Unexpected result type");
   MOZ_ASSERT(aUnitDistance >= 0.0 && aUnitDistance <= 1.0,
              "unit distance value out of bounds");
   MOZ_ASSERT(!aResult.mU.mPtr, "expecting barely-initialized outparam");
 
   const ValueWrapper* startWrapper = ExtractValueWrapper(aStartVal);
   const ValueWrapper* endWrapper = ExtractValueWrapper(aEndVal);
   MOZ_ASSERT(endWrapper, "expecting non-null endpoint");
-  return InterpolateForServo(startWrapper,
-                             *endWrapper,
-                             aUnitDistance,
-                             aResult);
+
+  if (!endWrapper->mServoValues.IsEmpty()) {
+    return InterpolateForServo(startWrapper,
+                               *endWrapper,
+                               aUnitDistance,
+                               aResult);
+  }
+
+  MOZ_CRASH("old style system disabled");
 }
 
 // Helper function to extract presContext
 static nsPresContext*
 GetPresContextForElement(Element* aElem)
 {
   nsIDocument* doc = aElem->GetUncomposedDoc();
   if (!doc) {
@@ -574,35 +595,44 @@ nsSMILCSSValueType::ValueFromAnimationVa
 
   sSingleton.Init(result);
   result.mU.mPtr = new ValueWrapper(aPropID, aValue);
 
   return result;
 }
 
 // static
-bool
-nsSMILCSSValueType::SetPropertyValues(const nsSMILValue& aValue,
-                                      DeclarationBlock& aDecl)
+void
+nsSMILCSSValueType::ValueToString(const nsSMILValue& aValue,
+                                  nsAString& aString)
 {
   MOZ_ASSERT(aValue.mType == &nsSMILCSSValueType::sSingleton,
              "Unexpected SMIL value type");
   const ValueWrapper* wrapper = ExtractValueWrapper(aValue);
   if (!wrapper) {
-    return false;
+    return;
+  }
+
+  if (wrapper->mServoValues.IsEmpty()) {
+    MOZ_CRASH("old style system disabled");
   }
 
-  bool changed = false;
-  for (const auto& value : wrapper->mServoValues) {
-    changed |=
-      Servo_DeclarationBlock_SetPropertyToAnimationValue(
-        aDecl.AsServo()->Raw(), value);
+  if (nsCSSProps::IsShorthand(wrapper->mPropID)) {
+    // In case of shorthand on servo, we iterate over all mServoValues array
+    // since we have multiple AnimationValues in the array for each longhand
+    // component.
+    Servo_Shorthand_AnimationValues_Serialize(wrapper->mPropID,
+                                              &wrapper->mServoValues,
+                                              &aString);
+    return;
   }
 
-  return changed;
+  Servo_AnimationValue_Serialize(wrapper->mServoValues[0],
+                                 wrapper->mPropID,
+                                 &aString);
 }
 
 // static
 nsCSSPropertyID
 nsSMILCSSValueType::PropertyFromValue(const nsSMILValue& aValue)
 {
   if (aValue.mType != &nsSMILCSSValueType::sSingleton) {
     return eCSSProperty_UNKNOWN;
@@ -632,22 +662,28 @@ nsSMILCSSValueType::FinalizeValue(nsSMIL
   }
 
   const ValueWrapper* valueToMatchWrapper = ExtractValueWrapper(aValueToMatch);
   if (!valueToMatchWrapper) {
     MOZ_ASSERT_UNREACHABLE("Value to match is empty");
     return;
   }
 
-  ServoAnimationValues zeroValues;
-  zeroValues.SetCapacity(valueToMatchWrapper->mServoValues.Length());
+  bool isServo = !valueToMatchWrapper->mServoValues.IsEmpty();
+
+  if (isServo) {
+    ServoAnimationValues zeroValues;
+    zeroValues.SetCapacity(valueToMatchWrapper->mServoValues.Length());
 
-  for (auto& valueToMatch : valueToMatchWrapper->mServoValues) {
-    RefPtr<RawServoAnimationValue> zeroValue =
-      Servo_AnimationValues_GetZeroValue(valueToMatch).Consume();
-    if (!zeroValue) {
-      return;
+    for (auto& valueToMatch : valueToMatchWrapper->mServoValues) {
+      RefPtr<RawServoAnimationValue> zeroValue =
+        Servo_AnimationValues_GetZeroValue(valueToMatch).Consume();
+      if (!zeroValue) {
+        return;
+      }
+      zeroValues.AppendElement(Move(zeroValue));
     }
-    zeroValues.AppendElement(Move(zeroValue));
+    aValue.mU.mPtr = new ValueWrapper(valueToMatchWrapper->mPropID,
+                                      Move(zeroValues));
+  } else {
+    MOZ_CRASH("old style system disabled");
   }
-  aValue.mU.mPtr = new ValueWrapper(valueToMatchWrapper->mPropID,
-                                    Move(zeroValues));
 }
--- a/dom/smil/nsSMILCSSValueType.h
+++ b/dom/smil/nsSMILCSSValueType.h
@@ -11,17 +11,16 @@
 
 #include "nsISMILType.h"
 #include "nsCSSPropertyID.h"
 #include "nsStringFwd.h"
 #include "mozilla/Attributes.h"
 
 namespace mozilla {
 struct AnimationValue;
-class DeclarationBlock;
 namespace dom {
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 /*
  * nsSMILCSSValueType: Represents a SMIL-animated CSS value.
  */
@@ -99,21 +98,26 @@ public:
    *                        nsSMILValue with the null type (i.e. rv.IsNull()
    *                        returns true).
    */
   static nsSMILValue ValueFromAnimationValue(nsCSSPropertyID aPropID,
                                              Element* aTargetElement,
                                              const AnimationValue& aValue);
 
   /**
-   * Sets the relevant property values in the declaration block.
+   * Creates a string representation of the given nsSMILValue.
    *
-   * Returns whether the declaration changed.
+   * Note: aValue is expected to be of this type (that is, it's expected to
+   * have been initialized by nsSMILCSSValueType::sSingleton).  If aValue is a
+   * freshly-initialized value the resulting string will be empty.
+   *
+   * @param       aValue   The nsSMILValue to be converted into a string.
+   * @param [out] aString  The string to be populated with the given value.
    */
-  static bool SetPropertyValues(const nsSMILValue&, mozilla::DeclarationBlock&);
+  static void ValueToString(const nsSMILValue& aValue, nsAString& aString);
 
   /**
    * Return the CSS property animated by the specified value.
    *
    * @param   aValue   The nsSMILValue to examine.
    * @return           The nsCSSPropertyID enum value of the property animated
    *                   by |aValue|, or eCSSProperty_UNKNOWN if the type of
    *                   |aValue| is not nsSMILCSSValueType.
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -481,16 +481,20 @@ SERVO_BINDING_FUNC(Servo_AnimationValues
                    RawServoAnimationValueBorrowed value_to_match)
 SERVO_BINDING_FUNC(Servo_AnimationValues_ComputeDistance, double,
                    RawServoAnimationValueBorrowed from,
                    RawServoAnimationValueBorrowed to)
 SERVO_BINDING_FUNC(Servo_AnimationValue_Serialize, void,
                    RawServoAnimationValueBorrowed value,
                    nsCSSPropertyID property,
                    nsAString* buffer)
+SERVO_BINDING_FUNC(Servo_Shorthand_AnimationValues_Serialize, void,
+                   nsCSSPropertyID shorthand_property,
+                   RawGeckoServoAnimationValueListBorrowed values,
+                   nsAString* buffer)
 SERVO_BINDING_FUNC(Servo_AnimationValue_GetOpacity, float,
                    RawServoAnimationValueBorrowed value)
 SERVO_BINDING_FUNC(Servo_AnimationValue_Opacity,
                    RawServoAnimationValueStrong,
                    float)
 SERVO_BINDING_FUNC(Servo_AnimationValue_GetTransform, void,
                    RawServoAnimationValueBorrowed value,
                    RefPtr<nsCSSValueSharedList>* list)
@@ -548,19 +552,16 @@ SERVO_BINDING_FUNC(Servo_DeclarationBloc
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetProperty, bool,
                    RawServoDeclarationBlockBorrowed declarations,
                    const nsACString* property,
                    const nsACString* value, bool is_important,
                    RawGeckoURLExtraData* data,
                    mozilla::ParsingMode parsing_mode,
                    nsCompatibility quirks_mode,
                    mozilla::css::Loader* loader)
-SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetPropertyToAnimationValue, bool,
-                   RawServoDeclarationBlockBorrowed declarations,
-                   RawServoAnimationValueBorrowed animation_value)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetPropertyById, bool,
                    RawServoDeclarationBlockBorrowed declarations,
                    nsCSSPropertyID property,
                    const nsACString* value, bool is_important,
                    RawGeckoURLExtraData* data,
                    mozilla::ParsingMode parsing_mode,
                    nsCompatibility quirks_mode,
                    mozilla::css::Loader* loader)
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -113,76 +113,102 @@ AnimationValue::operator!=(const Animati
 {
   return !operator==(aOther);
 }
 
 float
 AnimationValue::GetOpacity() const
 {
   MOZ_ASSERT(mServo);
-  return Servo_AnimationValue_GetOpacity(mServo);
+  if (mServo) {
+    return Servo_AnimationValue_GetOpacity(mServo);
+  }
+  MOZ_CRASH("old style system disabled");
 }
 
 already_AddRefed<const nsCSSValueSharedList>
 AnimationValue::GetTransformList() const
 {
   MOZ_ASSERT(mServo);
 
   RefPtr<nsCSSValueSharedList> transform;
-  Servo_AnimationValue_GetTransform(mServo, &transform);
+  if (mServo) {
+    Servo_AnimationValue_GetTransform(mServo, &transform);
+  } else {
+    MOZ_CRASH("old style system disabled");
+  }
   return transform.forget();
 }
 
 Size
 AnimationValue::GetScaleValue(const nsIFrame* aFrame) const
 {
   MOZ_ASSERT(mServo);
-  RefPtr<nsCSSValueSharedList> list;
-  Servo_AnimationValue_GetTransform(mServo, &list);
-  return nsStyleTransformMatrix::GetScaleValue(list, aFrame);
+
+  if (mServo) {
+    RefPtr<nsCSSValueSharedList> list;
+    Servo_AnimationValue_GetTransform(mServo, &list);
+    return nsStyleTransformMatrix::GetScaleValue(list, aFrame);
+  }
+  MOZ_CRASH("old style system disabled");
 }
 
 void
 AnimationValue::SerializeSpecifiedValue(nsCSSPropertyID aProperty,
                                         nsAString& aString) const
 {
   MOZ_ASSERT(mServo);
-  Servo_AnimationValue_Serialize(mServo, aProperty, &aString);
+
+  if (mServo) {
+    Servo_AnimationValue_Serialize(mServo, aProperty, &aString);
+    return;
+  }
+
+  MOZ_CRASH("old style system disabled");
 }
 
 bool
 AnimationValue::IsInterpolableWith(nsCSSPropertyID aProperty,
                                    const AnimationValue& aToValue) const
 {
   if (IsNull() || aToValue.IsNull()) {
     return false;
   }
 
   MOZ_ASSERT(mServo);
   MOZ_ASSERT(aToValue.mServo);
-  return Servo_AnimationValues_IsInterpolable(mServo, aToValue.mServo);
+
+  if (mServo) {
+    return Servo_AnimationValues_IsInterpolable(mServo, aToValue.mServo);
+  }
+
+  MOZ_CRASH("old style system disabled");
 }
 
 double
 AnimationValue::ComputeDistance(nsCSSPropertyID aProperty,
                                 const AnimationValue& aOther,
                                 ComputedStyle* aComputedStyle) const
 {
   if (IsNull() || aOther.IsNull()) {
     return 0.0;
   }
 
   MOZ_ASSERT(mServo);
   MOZ_ASSERT(aOther.mServo);
 
-  double distance =
-    Servo_AnimationValues_ComputeDistance(mServo, aOther.mServo);
-  return distance < 0.0
-         ? 0.0
-         : distance;
+  double distance= 0.0;
+  if (mServo) {
+    distance = Servo_AnimationValues_ComputeDistance(mServo, aOther.mServo);
+    return distance < 0.0
+           ? 0.0
+           : distance;
+  }
+
+  MOZ_CRASH("old style system disabled");
 }
 
 /* static */ AnimationValue
 AnimationValue::FromString(nsCSSPropertyID aProperty,
                            const nsAString& aValue,
                            Element* aElement)
 {
   MOZ_ASSERT(aElement);
--- a/layout/style/StyleAnimationValue.h
+++ b/layout/style/StyleAnimationValue.h
@@ -76,17 +76,18 @@ struct AnimationValue
     return !mServo;
   }
 
   float GetOpacity() const;
 
   // Return the transform list as a RefPtr.
   already_AddRefed<const nsCSSValueSharedList> GetTransformList() const;
 
-  // Return the scale for mServo, which is calculated with reference to aFrame.
+  // Return the scale for mGecko or mServo, which are calculated with
+  // reference to aFrame.
   mozilla::gfx::Size GetScaleValue(const nsIFrame* aFrame) const;
 
   // Uncompute this AnimationValue and then serialize it.
   void SerializeSpecifiedValue(nsCSSPropertyID aProperty,
                                nsAString& aString) const;
 
   // Check if |*this| and |aToValue| can be interpolated.
   bool IsInterpolableWith(nsCSSPropertyID aProperty,
@@ -110,16 +111,26 @@ struct AnimationValue
   static AnimationValue Opacity(float aOpacity);
   // Create an AnimationValue from a transform list.
   static AnimationValue Transform(nsCSSValueSharedList& aList);
 
   static already_AddRefed<nsCSSValue::Array>
   AppendTransformFunction(nsCSSKeyword aTransformFunction,
                           nsCSSValueList**& aListTail);
 
+  // mGecko and mServo are mutually exclusive: only one or the other should
+  // ever be set.
+  // FIXME: After obsoleting StyleAnimationValue, we should remove mGecko, and
+  // make AnimationValue a wrapper of RawServoAnimationValue to hide these
+  // FFIs.
+  // Ideally we would use conditional compilation based on MOZ_OLD_STYLE in the
+  // Servo code that wants to initialize mGecko, but that seems tricky.  So for
+  // now, just define a dummy member variable that its initialization code will
+  // work on, even when the old style system is compiled out.
+  uintptr_t mGecko;
   RefPtr<RawServoAnimationValue> mServo;
 };
 
 struct PropertyStyleAnimationValuePair
 {
   nsCSSPropertyID mProperty;
   AnimationValue mValue;
 };
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -9,17 +9,16 @@
 #include "nsDOMCSSAttrDeclaration.h"
 
 #include "mozilla/DeclarationBlock.h"
 #include "mozilla/DeclarationBlockInlines.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/MutationEventBinding.h"
 #include "mozilla/InternalMutationEvent.h"
 #include "mozilla/ServoDeclarationBlock.h"
-#include "mozAutoDocUpdate.h"
 #include "nsContentUtils.h"
 #include "nsIDocument.h"
 #include "nsIURI.h"
 #include "nsNodeUtils.h"
 #include "nsSMILCSSValueType.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsIFrame.h"
 #include "ActiveLayerTracker.h"
@@ -168,30 +167,29 @@ nsDOMCSSAttributeDeclaration::GetServoCS
   };
 }
 
 nsresult
 nsDOMCSSAttributeDeclaration::SetSMILValue(const nsCSSPropertyID aPropID,
                                            const nsSMILValue& aValue)
 {
   MOZ_ASSERT(mIsSMILOverride);
-  // No need to do the ActiveLayerTracker / ScrollLinkedEffectDetector bits,
-  // since we're in a SMIL animation anyway, no need to try to detect we're a
-  // scripted animation.
-  DeclarationBlock* olddecl = GetCSSDeclaration(eOperation_Modify);
-  if (!olddecl) {
-    return NS_ERROR_NOT_AVAILABLE;
+
+  // Convert nsSMILValue to string.
+  //
+  // FIXME(emilio): This roundtrip should go away.
+  nsAutoString valStr;
+  nsSMILCSSValueType::ValueToString(aValue, valStr);
+
+  nsAutoString oldValStr;
+  GetPropertyValue(aPropID, oldValStr);
+  if (valStr.Equals(oldValStr)) {
+    return NS_OK;
   }
-  mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
-  RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
-  bool changed = nsSMILCSSValueType::SetPropertyValues(aValue, *decl);
-  if (changed) {
-    SetCSSDeclaration(decl);
-  }
-  return NS_OK;
+  return SetPropertyValue(aPropID, valStr, nullptr);
 }
 
 nsresult
 nsDOMCSSAttributeDeclaration::SetPropertyValue(const nsCSSPropertyID aPropID,
                                                const nsAString& aValue,
                                                nsIPrincipal* aSubjectPrincipal)
 {
   // Scripted modifications to style.opacity or style.transform
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -704,16 +704,41 @@ pub extern "C" fn Servo_AnimationValue_S
     let buffer = unsafe { buffer.as_mut().unwrap() };
     let rv = PropertyDeclarationBlock::with_one(uncomputed_value, Importance::Normal)
         .single_value_to_css(&get_property_id_from_nscsspropertyid!(property, ()), buffer,
                              None, None /* No extra custom properties */);
     debug_assert!(rv.is_ok());
 }
 
 #[no_mangle]
+pub unsafe extern "C" fn Servo_Shorthand_AnimationValues_Serialize(
+    shorthand_property: nsCSSPropertyID,
+    values: RawGeckoServoAnimationValueListBorrowed,
+    buffer: *mut nsAString,
+) {
+    let property_id = get_property_id_from_nscsspropertyid!(shorthand_property, ());
+    let shorthand = match property_id.as_shorthand() {
+        Ok(shorthand) => shorthand,
+        _ => return,
+    };
+
+    // Convert RawServoAnimationValue(s) into a vector of PropertyDeclaration
+    // so that we can use reference of the PropertyDeclaration without worrying
+    // about its lifetime. (longhands_to_css() expects &PropertyDeclaration
+    // iterator.)
+    let declarations: Vec<PropertyDeclaration> =
+        values.iter().map(|v| AnimationValue::as_arc(&&*v.mRawPtr).uncompute()).collect();
+
+    let _ = shorthand.longhands_to_css(
+        declarations.iter(),
+        &mut CssWriter::new(&mut *buffer),
+    );
+}
+
+#[no_mangle]
 pub extern "C" fn Servo_AnimationValue_GetOpacity(
     value: RawServoAnimationValueBorrowed,
 ) -> f32 {
     let value = AnimationValue::as_arc(&value);
     if let AnimationValue::Opacity(opacity) = **value {
         opacity
     } else {
         panic!("The AnimationValue should be Opacity");
@@ -3580,30 +3605,16 @@ pub unsafe extern "C" fn Servo_Declarati
         data,
         parsing_mode,
         quirks_mode.into(),
         loader,
     )
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn Servo_DeclarationBlock_SetPropertyToAnimationValue(
-    declarations: RawServoDeclarationBlockBorrowed,
-    animation_value: RawServoAnimationValueBorrowed,
-) -> bool {
-    write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
-        decls.push(
-            AnimationValue::as_arc(&animation_value).uncompute(),
-            Importance::Normal,
-            DeclarationSource::CssOm,
-        )
-    })
-}
-
-#[no_mangle]
 pub unsafe extern "C" fn Servo_DeclarationBlock_SetPropertyById(
     declarations: RawServoDeclarationBlockBorrowed,
     property: nsCSSPropertyID,
     value: *const nsACString,
     is_important: bool,
     data: *mut URLExtraData,
     parsing_mode: structs::ParsingMode,
     quirks_mode: nsCompatibility,
@@ -4490,16 +4501,17 @@ impl<'a> Iterator for PrioritizedPropert
 #[no_mangle]
 pub extern "C" fn Servo_GetComputedKeyframeValues(
     keyframes: RawGeckoKeyframeListBorrowed,
     element: RawGeckoElementBorrowed,
     style: ComputedStyleBorrowed,
     raw_data: RawServoStyleSetBorrowed,
     computed_keyframes: RawGeckoComputedKeyframeValuesListBorrowedMut
 ) {
+    use std::mem;
     use style::properties::LonghandIdSet;
 
     let data = PerDocumentStyleData::from_ffi(raw_data).borrow();
     let metrics = get_metrics_provider_for_product();
 
     let element = GeckoElement(element);
     let parent_element = element.inheritance_parent();
     let parent_data = parent_element.as_ref().and_then(|e| e.borrow_data());
@@ -4550,16 +4562,20 @@ pub extern "C" fn Servo_GetComputedKeyfr
                 if seen.contains(property) {
                     return;
                 }
                 seen.insert(property);
 
                 // This is safe since we immediately write to the uninitialized values.
                 unsafe { animation_values.set_len((property_index + 1) as u32) };
                 animation_values[property_index].mProperty = property.to_nscsspropertyid();
+                // We only make sure we have enough space for this variable,
+                // but didn't construct a default value for StyleAnimationValue,
+                // so we should zero it to avoid getting undefined behaviors.
+                animation_values[property_index].mValue.mGecko = unsafe { mem::zeroed() };
                 match value {
                     Some(v) => {
                         animation_values[property_index].mValue.mServo.set_arc_leaky(Arc::new(v));
                     },
                     None => {
                         animation_values[property_index].mValue.mServo.mRawPtr = ptr::null_mut();
                     },
                 }