Bug 1355348 - Make nsSMILCSSValueType store an AnimationValue instead of a StyleAnimationValue; r=heycam
authorBrian Birtles <birtles@gmail.com>
Wed, 26 Apr 2017 13:00:12 +0900
changeset 569348 d3553e38c07dd3fd7704db10635a7f527594af80
parent 569347 e5f624959d3dbae43c5f5e0f2364cabf62fc5936
child 569349 f1bd37850558adee8d03085d77eb1809af51cb63
push id56143
push userbmo:jeremychen@mozilla.com
push dateThu, 27 Apr 2017 10:17:21 +0000
reviewersheycam
bugs1355348
milestone55.0a1
Bug 1355348 - Make nsSMILCSSValueType store an AnimationValue instead of a StyleAnimationValue; r=heycam MozReview-Commit-ID: 7EF9CN2SdwQ
dom/smil/nsSMILCSSProperty.cpp
dom/smil/nsSMILCSSValueType.cpp
dom/smil/nsSMILCSSValueType.h
--- a/dom/smil/nsSMILCSSProperty.cpp
+++ b/dom/smil/nsSMILCSSProperty.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* representation of a SMIL-animatable CSS property on an element */
 
 #include "nsSMILCSSProperty.h"
 
 #include "mozilla/dom/Element.h"
 #include "mozilla/Move.h"
+#include "mozilla/ServoBindings.h"
 #include "mozilla/StyleAnimationValue.h"
 #include "nsICSSDeclaration.h"
 #include "nsSMILCSSValueType.h"
 #include "nsSMILValue.h"
 #include "nsCSSProps.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -59,20 +60,29 @@ nsSMILCSSProperty::GetBaseValue() const
     //
     // In any case, just return a dummy value (initialized with the right
     // type, so as not to indicate failure).
     nsSMILValue tmpVal(&nsSMILCSSValueType::sSingleton);
     Swap(baseValue, tmpVal);
     return baseValue;
   }
 
-  StyleAnimationValue computedValue;
-  if (!StyleAnimationValue::ExtractComputedValue(mPropID,
-                                                 mBaseStyleContext,
-                                                 computedValue)) {
+  AnimationValue computedValue;
+  if (mElement->IsStyledByServo()) {
+    const ServoComputedValues* currentStyle =
+      mBaseStyleContext->StyleSource().AsServoComputedValues();
+    computedValue.mServo =
+      Servo_ComputedValues_ExtractAnimationValue(currentStyle, mPropID)
+      .Consume();
+    if (!computedValue.mServo) {
+      return baseValue;
+    }
+  } else if (!StyleAnimationValue::ExtractComputedValue(mPropID,
+                                                        mBaseStyleContext,
+                                                        computedValue.mGecko)) {
     return baseValue;
   }
 
   baseValue =
     nsSMILCSSValueType::ValueFromAnimationValue(mPropID, mElement,
                                                 computedValue);
   return baseValue;
 }
@@ -103,20 +113,17 @@ nsSMILCSSProperty::ValueFromString(const
 
 nsresult
 nsSMILCSSProperty::SetAnimValue(const nsSMILValue& aValue)
 {
   NS_ENSURE_TRUE(IsPropertyAnimatable(mPropID), NS_ERROR_FAILURE);
 
   // Convert nsSMILValue to string
   nsAutoString valStr;
-  if (!nsSMILCSSValueType::ValueToString(aValue, valStr)) {
-    NS_WARNING("Failed to convert nsSMILValue for CSS property into a string");
-    return NS_ERROR_FAILURE;
-  }
+  nsSMILCSSValueType::ValueToString(aValue, valStr);
 
   // Use string value to style the target element
   nsICSSDeclaration* overrideDecl = mElement->GetSMILOverrideStyle();
   if (overrideDecl) {
     nsAutoString oldValStr;
     overrideDecl->GetPropertyValue(mPropID, oldValStr);
     if (valStr.Equals(oldValStr)) {
       return NS_OK;
--- a/dom/smil/nsSMILCSSValueType.cpp
+++ b/dom/smil/nsSMILCSSValueType.cpp
@@ -7,51 +7,61 @@
 /* representation of a value for a SMIL-animated CSS property */
 
 #include "nsSMILCSSValueType.h"
 
 #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/StyleAnimationValue.h"
+#include "mozilla/Keyframe.h" // For PropertyValuePair
+#include "mozilla/ServoBindings.h"
+#include "mozilla/ServoComputedValuesWithParent.h"
+#include "mozilla/StyleAnimationValue.h" // For AnimationValue
+#include "mozilla/StyleSetHandleInlines.h"
 #include "mozilla/dom/Element.h"
 #include "nsDebug.h"
 #include "nsStyleUtil.h"
 #include "nsIDocument.h"
 
 using namespace mozilla::dom;
 using mozilla::StyleAnimationValue;
 
 /*static*/ nsSMILCSSValueType nsSMILCSSValueType::sSingleton;
 
 struct ValueWrapper {
-  ValueWrapper(nsCSSPropertyID aPropID, const StyleAnimationValue& aValue) :
-    mPropID(aPropID), mCSSValue(aValue) {}
+  ValueWrapper(nsCSSPropertyID aPropID, const AnimationValue& aValue)
+    : mPropID(aPropID), mCSSValue(aValue) {}
+  ValueWrapper(nsCSSPropertyID aPropID, const StyleAnimationValue& aValue)
+    : mPropID(aPropID), mCSSValue(aValue) {}
+  ValueWrapper(nsCSSPropertyID aPropID,
+               const RefPtr<RawServoAnimationValue>& aValue)
+    : mPropID(aPropID), mCSSValue(aValue) {}
 
   nsCSSPropertyID mPropID;
-  StyleAnimationValue mCSSValue;
+  AnimationValue mCSSValue;
 };
 
 // Helper Methods
 // --------------
-static const StyleAnimationValue*
+static const AnimationValue*
 GetZeroValueForUnit(StyleAnimationValue::Unit aUnit)
 {
-  static const StyleAnimationValue
-    sZeroCoord(0, StyleAnimationValue::CoordConstructor);
-  static const StyleAnimationValue
-    sZeroPercent(0.0f, StyleAnimationValue::PercentConstructor);
-  static const StyleAnimationValue
-    sZeroFloat(0.0f,  StyleAnimationValue::FloatConstructor);
-  static const StyleAnimationValue
-    sZeroColor(NS_RGB(0,0,0), StyleAnimationValue::ColorConstructor);
+  static const AnimationValue sZeroCoord(
+    StyleAnimationValue(0, StyleAnimationValue::CoordConstructor));
+  static const AnimationValue sZeroPercent(
+    StyleAnimationValue(0.0f, StyleAnimationValue::PercentConstructor));
+  static const AnimationValue sZeroFloat(
+    StyleAnimationValue(0.0f,  StyleAnimationValue::FloatConstructor));
+  static const AnimationValue sZeroColor(
+    StyleAnimationValue(NS_RGB(0,0,0), StyleAnimationValue::ColorConstructor));
 
   MOZ_ASSERT(aUnit != StyleAnimationValue::eUnit_Null,
              "Need non-null unit for a zero value");
   switch (aUnit) {
     case StyleAnimationValue::eUnit_Coord:
       return &sZeroCoord;
     case StyleAnimationValue::eUnit_Percent:
       return &sZeroPercent;
@@ -70,44 +80,58 @@ GetZeroValueForUnit(StyleAnimationValue:
 // for the other argument's Unit (if applicable; otherwise, we return false).
 //
 // If neither argument is null, this method generally does nothing, though it
 // may apply a workaround for the special case where a 0 length-value is mixed
 // with a eUnit_Float value.  (See comment below.)
 //
 // Returns true on success, or false.
 static bool
-FinalizeStyleAnimationValues(const StyleAnimationValue*& aValue1,
-                             const StyleAnimationValue*& aValue2)
+FinalizeStyleAnimationValues(const AnimationValue*& aValue1,
+                             const AnimationValue*& aValue2)
 {
   MOZ_ASSERT(aValue1 || aValue2,
              "expecting at least one non-null value");
+  MOZ_ASSERT(!aValue1 || !aValue2 || !aValue1->mServo == !aValue2->mServo,
+             "If both values are specified, they should be for the same"
+             " style system");
+
+  bool isServo = aValue1 ? aValue1->mServo : aValue2->mServo;
+
+  if (isServo) {
+    // Bug 1355349: Implement additive animation for Stylo
+    if (!aValue1 || !aValue2) {
+      NS_WARNING("stylo: Missing values are not yet supported (bug 1355349)");
+      return false;
+    }
+    return true;
+  }
 
   // Are we missing either val? (If so, it's an implied 0 in other val's units)
   if (!aValue1) {
-    aValue1 = GetZeroValueForUnit(aValue2->GetUnit());
+    aValue1 = GetZeroValueForUnit(aValue2->mGecko.GetUnit());
     return !!aValue1; // Fail if we have no zero value for this unit.
   }
   if (!aValue2) {
-    aValue2 = GetZeroValueForUnit(aValue1->GetUnit());
+    aValue2 = GetZeroValueForUnit(aValue1->mGecko.GetUnit());
     return !!aValue2; // Fail if we have no zero value for this unit.
   }
 
   // Ok, both values were specified.
   // Need to handle a special-case, though: unitless nonzero length (parsed as
   // eUnit_Float) mixed with unitless 0 length (parsed as eUnit_Coord).  These
   // won't interoperate in StyleAnimationValue, since their Units don't match.
   // In this case, we replace the eUnit_Coord 0 value with eUnit_Float 0 value.
-  const StyleAnimationValue& zeroCoord =
+  const AnimationValue& zeroCoord =
     *GetZeroValueForUnit(StyleAnimationValue::eUnit_Coord);
   if (*aValue1 == zeroCoord &&
-      aValue2->GetUnit() == StyleAnimationValue::eUnit_Float) {
+      aValue2->mGecko.GetUnit() == StyleAnimationValue::eUnit_Float) {
     aValue1 = GetZeroValueForUnit(StyleAnimationValue::eUnit_Float);
   } else if (*aValue2 == zeroCoord &&
-             aValue1->GetUnit() == StyleAnimationValue::eUnit_Float) {
+             aValue1->mGecko.GetUnit() == StyleAnimationValue::eUnit_Float) {
     aValue2 = GetZeroValueForUnit(StyleAnimationValue::eUnit_Float);
   }
 
   return true;
 }
 
 static void
 InvertSign(StyleAnimationValue& aValue)
@@ -229,65 +253,83 @@ nsSMILCSSValueType::Add(nsSMILValue& aDe
                             destWrapper->mPropID);
   // Special case: font-size-adjust and stroke-dasharray are explicitly
   // non-additive (even though StyleAnimationValue *could* support adding them)
   if (property == eCSSProperty_font_size_adjust ||
       property == eCSSProperty_stroke_dasharray) {
     return NS_ERROR_FAILURE;
   }
 
-  const StyleAnimationValue* valueToAdd = valueToAddWrapper ?
-    &valueToAddWrapper->mCSSValue : nullptr;
-  const StyleAnimationValue* destValue = destWrapper ?
-    &destWrapper->mCSSValue : nullptr;
+  const AnimationValue* valueToAdd = valueToAddWrapper
+                                     ? &valueToAddWrapper->mCSSValue
+                                     : nullptr;
+  const AnimationValue* destValue = destWrapper
+                                    ? &destWrapper->mCSSValue
+                                    : nullptr;
   if (!FinalizeStyleAnimationValues(valueToAdd, destValue)) {
     return NS_ERROR_FAILURE;
   }
   // Did FinalizeStyleAnimationValues change destValue?
   // If so, update outparam to use the new value.
   if (destWrapper && &destWrapper->mCSSValue != destValue) {
     destWrapper->mCSSValue = *destValue;
   }
 
   // Handle barely-initialized "zero" destination.
   if (!destWrapper) {
-    aDest.mU.mPtr = destWrapper =
-      new ValueWrapper(property, *destValue);
+    aDest.mU.mPtr = destWrapper = new ValueWrapper(property, *destValue);
+  }
+
+  // Bug 1355349: Implement additive animation for Stylo
+  if (destWrapper->mCSSValue.mServo) {
+    NS_WARNING("stylo: Additive animation not supported yet (bug 1355349)");
+    return NS_ERROR_FAILURE;
   }
 
   return StyleAnimationValue::Add(property,
-                                  destWrapper->mCSSValue, *valueToAdd, aCount) ?
-    NS_OK : NS_ERROR_FAILURE;
+                                  destWrapper->mCSSValue.mGecko,
+                                  valueToAdd->mGecko, aCount)
+         ? NS_OK
+         : NS_ERROR_FAILURE;
 }
 
 nsresult
 nsSMILCSSValueType::ComputeDistance(const nsSMILValue& aFrom,
                                     const nsSMILValue& aTo,
                                     double& aDistance) const
 {
   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");
 
-  const StyleAnimationValue* fromCSSValue = fromWrapper ?
-    &fromWrapper->mCSSValue : nullptr;
-  const StyleAnimationValue* toCSSValue = &toWrapper->mCSSValue;
+  const AnimationValue* fromCSSValue = fromWrapper
+                                       ? &fromWrapper->mCSSValue
+                                       : nullptr;
+  const AnimationValue* toCSSValue = &toWrapper->mCSSValue;
   if (!FinalizeStyleAnimationValues(fromCSSValue, toCSSValue)) {
     return NS_ERROR_FAILURE;
   }
 
+  if (toCSSValue->mServo) {
+    aDistance = Servo_AnimationValues_ComputeDistance(fromCSSValue->mServo,
+                                                      toCSSValue->mServo);
+    return NS_OK;
+  }
+
   return StyleAnimationValue::ComputeDistance(toWrapper->mPropID,
-                                              *fromCSSValue, *toCSSValue,
+                                              fromCSSValue->mGecko,
+                                              toCSSValue->mGecko,
                                               nullptr,
-                                              aDistance) ?
-    NS_OK : NS_ERROR_FAILURE;
+                                              aDistance)
+         ? NS_OK
+         : NS_ERROR_FAILURE;
 }
 
 nsresult
 nsSMILCSSValueType::Interpolate(const nsSMILValue& aStartVal,
                                 const nsSMILValue& aEndVal,
                                 double aUnitDistance,
                                 nsSMILValue& aResult) const
 {
@@ -299,26 +341,44 @@ nsSMILCSSValueType::Interpolate(const ns
   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");
 
-  const StyleAnimationValue* startCSSValue = startWrapper ?
-    &startWrapper->mCSSValue : nullptr;
-  const StyleAnimationValue* endCSSValue = &endWrapper->mCSSValue;
+  const AnimationValue* startCSSValue = startWrapper
+                                        ? &startWrapper->mCSSValue
+                                        : nullptr;
+  const AnimationValue* endCSSValue = &endWrapper->mCSSValue;
   if (!FinalizeStyleAnimationValues(startCSSValue, endCSSValue)) {
     return NS_ERROR_FAILURE;
   }
 
+  MOZ_ASSERT(!startCSSValue ||
+             !startCSSValue->mServo == !endCSSValue->mServo,
+             "Start and end values should use the same style system");
+
+  if (endCSSValue->mServo) {
+    RefPtr<RawServoAnimationValue> resultValue =
+      Servo_AnimationValues_Interpolate(startCSSValue->mServo,
+                                        endCSSValue->mServo,
+                                        aUnitDistance).Consume();
+    if (!resultValue) {
+      return NS_ERROR_FAILURE;
+    }
+    aResult.mU.mPtr = new ValueWrapper(endWrapper->mPropID, resultValue);
+    return NS_OK;
+  }
+
   StyleAnimationValue resultValue;
   if (StyleAnimationValue::Interpolate(endWrapper->mPropID,
-                                       *startCSSValue, *endCSSValue,
+                                       startCSSValue->mGecko,
+                                       endCSSValue->mGecko,
                                        aUnitDistance, resultValue)) {
     aResult.mU.mPtr = new ValueWrapper(endWrapper->mPropID, resultValue);
     return NS_OK;
   }
   return NS_ERROR_FAILURE;
 }
 
 // Helper function to extract presContext
@@ -361,32 +421,26 @@ GetNonNegativePropValue(const nsAString&
   return Substring(aString, subStringBegin);
 }
 
 // Helper function to parse a string into a StyleAnimationValue
 static bool
 ValueFromStringHelper(nsCSSPropertyID aPropID,
                       Element* aTargetElement,
                       nsPresContext* aPresContext,
+                      nsStyleContext* aStyleContext,
                       const nsAString& aString,
                       StyleAnimationValue& aStyleAnimValue,
                       bool* aIsContextSensitive)
 {
-  RefPtr<nsStyleContext> styleContext =
-    nsComputedDOMStyle::GetStyleContext(aTargetElement, nullptr,
-                                        aPresContext->PresShell());
-  if (!styleContext) {
-    return false;
-  }
-
   bool isNegative = false;
   const nsDependentSubstring subString =
     GetNonNegativePropValue(aString, aPropID, isNegative);
 
-  if (!StyleAnimationValue::ComputeValue(aPropID, aTargetElement, styleContext,
+  if (!StyleAnimationValue::ComputeValue(aPropID, aTargetElement, aStyleContext,
                                          subString, true, aStyleAnimValue,
                                          aIsContextSensitive)) {
     return false;
   }
   if (isNegative) {
     InvertSign(aStyleAnimValue);
   }
 
@@ -395,16 +449,105 @@ ValueFromStringHelper(nsCSSPropertyID aP
     MOZ_ASSERT(aStyleAnimValue.GetUnit() == StyleAnimationValue::eUnit_Coord,
                "'font-size' value with unexpected style unit");
     aStyleAnimValue.SetCoordValue(aStyleAnimValue.GetCoordValue() /
                                   aPresContext->EffectiveTextZoom());
   }
   return true;
 }
 
+static already_AddRefed<RawServoAnimationValue>
+ValueFromStringHelper(nsCSSPropertyID aPropID,
+                      Element* aTargetElement,
+                      nsPresContext* aPresContext,
+                      nsStyleContext* aStyleContext,
+                      const nsAString& aString)
+{
+  // FIXME (bug 1358966): Support shorthand properties
+  if (nsCSSProps::IsShorthand(aPropID)) {
+    return nullptr;
+  }
+
+  // Get a suitable style context for Servo
+  const ServoComputedValues* currentStyle =
+    aStyleContext->StyleSource().AsServoComputedValues();
+  // Bug 1349004: Remove GetParentAllowServo
+  const ServoComputedValues* parentStyle =
+    aStyleContext->GetParentAllowServo()
+    ? aStyleContext->GetParentAllowServo()->StyleSource()
+      .AsServoComputedValues()
+    : nullptr;
+  const ServoComputedValuesWithParent servoStyles =
+    { currentStyle, parentStyle };
+
+  // FIXME (bug 1357295): Handle negative values properly
+#ifdef DEBUG
+  {
+    bool isNegative = false;
+    Unused << GetNonNegativePropValue(aString, aPropID, isNegative);
+    if (isNegative) {
+      NS_WARNING("stylo: Special negative value handling not yet supported"
+                 " (bug 1357295)");
+    }
+  }
+#endif // DEBUG
+
+  // Parse property
+  nsIDocument* doc = aTargetElement->GetUncomposedDoc();
+  if (!doc) {
+    return nullptr;
+  }
+  // FIXME this is using the wrong base uri (bug 1343919)
+  RefPtr<URLExtraData> data = new URLExtraData(doc->GetDocumentURI(),
+                                               doc->GetDocumentURI(),
+                                               doc->NodePrincipal());
+  NS_ConvertUTF16toUTF8 value(aString);
+  RefPtr<RawServoDeclarationBlock> servoDeclarationBlock =
+    Servo_ParseProperty(aPropID, &value, data).Consume();
+  if (!servoDeclarationBlock) {
+    return nullptr;
+  }
+
+  // Compute value
+  PropertyValuePair propValuePair;
+  propValuePair.mProperty = aPropID;
+  propValuePair.mServoDeclarationBlock = servoDeclarationBlock;
+  AutoTArray<Keyframe, 1> keyframes;
+  keyframes.AppendElement()->mPropertyValues.AppendElement(Move(propValuePair));
+  nsTArray<ComputedKeyframeValues> computedValues =
+    aPresContext->StyleSet()->AsServo()
+      ->GetComputedKeyframeValuesFor(keyframes, aTargetElement, servoStyles);
+
+  // Pull out the appropriate value
+  if (computedValues.IsEmpty() || computedValues[0].IsEmpty()) {
+    return nullptr;
+  }
+  // So long as we don't support shorthands (bug 1358966) the following
+  // assertion should hold.
+  MOZ_ASSERT(computedValues.Length() == 1 &&
+             computedValues[0].Length() == 1,
+             "Should only have a single property with a single value");
+  AnimationValue computedValue = computedValues[0][0].mValue;
+  if (!computedValue.mServo) {
+    return nullptr;
+  }
+
+  if (aPropID == eCSSProperty_font_size) {
+    // FIXME (bug 1357296): Divide out text-zoom, since SVG is supposed to
+    // ignore it.
+    if (aPresContext->EffectiveTextZoom() != 1.0) {
+      NS_WARNING("stylo: Dividing out text-zoom not yet supported"
+                 " (bug 1357296)");
+    }
+  }
+
+  // Result should be already add-refed
+  return computedValue.mServo.forget();
+}
+
 // static
 void
 nsSMILCSSValueType::ValueFromString(nsCSSPropertyID aPropID,
                                     Element* aTargetElement,
                                     const nsAString& aString,
                                     nsSMILValue& aValue,
                                     bool* aIsContextSensitive)
 {
@@ -418,29 +561,53 @@ nsSMILCSSValueType::ValueFromString(nsCS
   nsIDocument* doc = aTargetElement->GetUncomposedDoc();
   if (doc && !nsStyleUtil::CSPAllowsInlineStyle(nullptr,
                                                 doc->NodePrincipal(),
                                                 doc->GetDocumentURI(),
                                                 0, aString, nullptr)) {
     return;
   }
 
+  RefPtr<nsStyleContext> styleContext =
+    nsComputedDOMStyle::GetStyleContext(aTargetElement, nullptr,
+                                        presContext->PresShell());
+  if (!styleContext) {
+    return;
+  }
+
+  if (aTargetElement->IsStyledByServo()) {
+    RefPtr<RawServoAnimationValue> parsedValue =
+      ValueFromStringHelper(aPropID, aTargetElement, presContext,
+                            styleContext, aString);
+    if (aIsContextSensitive) {
+      // FIXME: Bug 1358955 - detect context-sensitive values and set this value
+      // appropriately.
+      *aIsContextSensitive = false;
+    }
+
+    if (parsedValue) {
+      sSingleton.Init(aValue);
+      aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue);
+    }
+    return;
+  }
+
   StyleAnimationValue parsedValue;
-  if (ValueFromStringHelper(aPropID, aTargetElement, presContext,
+  if (ValueFromStringHelper(aPropID, aTargetElement, presContext, styleContext,
                             aString, parsedValue, aIsContextSensitive)) {
     sSingleton.Init(aValue);
     aValue.mU.mPtr = new ValueWrapper(aPropID, parsedValue);
   }
 }
 
 // static
 nsSMILValue
 nsSMILCSSValueType::ValueFromAnimationValue(nsCSSPropertyID aPropID,
                                             Element* aTargetElement,
-                                            const StyleAnimationValue& aValue)
+                                            const AnimationValue& aValue)
 {
   nsSMILValue result;
 
   nsIDocument* doc = aTargetElement->GetUncomposedDoc();
   // We'd like to avoid serializing |aValue| if possible, and since the
   // string passed to CSPAllowsInlineStyle is only used for reporting violations
   // and an intermediate CSS value is not likely to be particularly useful
   // in that case, we just use a generic placeholder string instead.
@@ -455,26 +622,28 @@ nsSMILCSSValueType::ValueFromAnimationVa
 
   sSingleton.Init(result);
   result.mU.mPtr = new ValueWrapper(aPropID, aValue);
 
   return result;
 }
 
 // static
-bool
+void
 nsSMILCSSValueType::ValueToString(const nsSMILValue& aValue,
                                   nsAString& aString)
 {
   MOZ_ASSERT(aValue.mType == &nsSMILCSSValueType::sSingleton,
              "Unexpected SMIL value type");
   const ValueWrapper* wrapper = ExtractValueWrapper(aValue);
-  return !wrapper ||
-    StyleAnimationValue::UncomputeValue(wrapper->mPropID,
-                                        wrapper->mCSSValue, aString);
+  if (!wrapper) {
+    return;
+  }
+
+  wrapper->mCSSValue.SerializeSpecifiedValue(wrapper->mPropID, aString);
 }
 
 // static
 nsCSSPropertyID
 nsSMILCSSValueType::PropertyFromValue(const nsSMILValue& aValue)
 {
   if (aValue.mType != &nsSMILCSSValueType::sSingleton) {
     return eCSSProperty_UNKNOWN;
--- a/dom/smil/nsSMILCSSValueType.h
+++ b/dom/smil/nsSMILCSSValueType.h
@@ -11,30 +11,30 @@
 
 #include "nsISMILType.h"
 #include "nsCSSPropertyID.h"
 #include "mozilla/Attributes.h"
 
 class nsAString;
 
 namespace mozilla {
-class StyleAnimationValue;
+struct AnimationValue;
 namespace dom {
 class Element;
 } // namespace dom
 } // namespace mozilla
 
 /*
  * nsSMILCSSValueType: Represents a SMIL-animated CSS value.
  */
 class nsSMILCSSValueType : public nsISMILType
 {
 public:
   typedef mozilla::dom::Element Element;
-  typedef mozilla::StyleAnimationValue StyleAnimationValue;
+  typedef mozilla::AnimationValue AnimationValue;
 
   // Singleton for nsSMILValue objects to hold onto.
   static nsSMILCSSValueType sSingleton;
 
 protected:
   // nsISMILType Methods
   // -------------------
   virtual void     Init(nsSMILValue& aValue) const override;
@@ -94,31 +94,29 @@ public:
    *                        applies.
    * @param aValue          The animation value to use.
    * @return                A new nsSMILValue. On failure, returns an
    *                        nsSMILValue with the null type (i.e. rv.IsNull()
    *                        returns true).
    */
   static nsSMILValue ValueFromAnimationValue(nsCSSPropertyID aPropID,
                                              Element* aTargetElement,
-                                             const StyleAnimationValue& aValue);
+                                             const AnimationValue& aValue);
 
   /**
    * Creates a string representation of the given nsSMILValue.
    *
    * 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, this method will succeed, though the resulting
-   * string will be empty.
+   * 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.
-   * @return               true on success, false on failure.
    */
-  static bool ValueToString(const nsSMILValue& aValue, nsAString& aString);
+  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.