Bug 1339690 - Part 3: Drop spacing mode. draft
authorBoris Chiou <boris.chiou@gmail.com>
Tue, 13 Jun 2017 15:09:19 +0800
changeset 594706 8790c59e9c2b2e0686439b517dc12d63b8f0d233
parent 594705 ff4bd5f5bc8de1be3d273ea1e9f4aafef19bbf1c
child 594707 ecd6fe9074f421d6e856131004ef09afa3c4f664
push id64112
push userbmo:boris.chiou@gmail.com
push dateThu, 15 Jun 2017 10:38:49 +0000
bugs1339690
milestone56.0a1
Bug 1339690 - Part 3: Drop spacing mode. MozReview-Commit-ID: 1c7jpzWQjVP
dom/animation/KeyframeEffect.cpp
dom/animation/KeyframeEffect.h
dom/animation/KeyframeEffectParams.cpp
dom/animation/KeyframeEffectParams.h
dom/animation/KeyframeEffectReadOnly.cpp
dom/animation/KeyframeEffectReadOnly.h
dom/animation/KeyframeUtils.cpp
dom/animation/KeyframeUtils.h
dom/animation/moz.build
dom/bindings/Bindings.conf
dom/bindings/Errors.msg
dom/locales/en-US/chrome/dom/dom.properties
dom/webidl/KeyframeEffect.webidl
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -5,19 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/KeyframeEffect.h"
 
 #include "mozilla/dom/KeyframeAnimationOptionsBinding.h"
   // For UnrestrictedDoubleOrKeyframeAnimationOptions
 #include "mozilla/dom/AnimationEffectTiming.h"
 #include "mozilla/dom/KeyframeEffectBinding.h"
-#include "mozilla/KeyframeUtils.h"
 #include "nsDOMMutationObserver.h" // For nsAutoAnimationMutationBatch
-#include "nsIScriptError.h"
 
 namespace mozilla {
 namespace dom {
 
 KeyframeEffect::KeyframeEffect(nsIDocument* aDocument,
                                const Maybe<OwningAnimationTarget>& aTarget,
                                const TimingParams& aTiming,
                                const KeyframeEffectParams& aOptions)
@@ -108,31 +106,26 @@ KeyframeEffect::SetTarget(const Nullable
 
   mTarget = newTarget;
 
   if (mTarget) {
     UpdateTargetRegistration();
     RefPtr<nsStyleContext> styleContext = GetTargetStyleContext();
     if (styleContext) {
       UpdateProperties(styleContext);
-    } else if (mEffectOptions.mSpacingMode == SpacingMode::paced) {
-      KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
     }
 
     MaybeUpdateFrameForCompositor();
 
     RequestRestyle(EffectCompositor::RestyleType::Layer);
 
     nsAutoAnimationMutationBatch mb(mTarget->mElement->OwnerDoc());
     if (mAnimation) {
       nsNodeUtils::AnimationAdded(mAnimation);
     }
-  } else if (mEffectOptions.mSpacingMode == SpacingMode::paced) {
-    // New target is null, so fall back to distribute spacing.
-    KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
   }
 
   // If the new target frame is also oversized we should probably record that
   // too so we have a more complete picture of the type of frame sizes we
   // encounter, hence we reset the telemetry flag here.
   mRecordedContentTooLarge = false;
   mRecordedFrameSize = false;
 }
@@ -176,66 +169,10 @@ KeyframeEffect::SetComposite(const Compo
   if (mTarget) {
     RefPtr<nsStyleContext> styleContext = GetTargetStyleContext();
     if (styleContext) {
       UpdateProperties(styleContext);
     }
   }
 }
 
-void
-KeyframeEffect::SetSpacing(JSContext* aCx,
-                           const nsAString& aSpacing,
-                           CallerType aCallerType,
-                           ErrorResult& aRv)
-{
-  SpacingMode spacingMode = SpacingMode::distribute;
-  nsCSSPropertyID pacedProperty = eCSSProperty_UNKNOWN;
-  nsAutoString invalidPacedProperty;
-  KeyframeEffectParams::ParseSpacing(aSpacing,
-                                     spacingMode,
-                                     pacedProperty,
-                                     invalidPacedProperty,
-                                     aCallerType,
-                                     aRv);
-  if (aRv.Failed()) {
-    return;
-  }
-
-  if (!invalidPacedProperty.IsEmpty()) {
-    const char16_t* params[] = { invalidPacedProperty.get() };
-    nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aCx);
-    nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
-                                    NS_LITERAL_CSTRING("Animation"),
-                                    doc,
-                                    nsContentUtils::eDOM_PROPERTIES,
-                                    "UnanimatablePacedProperty",
-                                    params, ArrayLength(params));
-  }
-
-  if (mEffectOptions.mSpacingMode == spacingMode &&
-      mEffectOptions.mPacedProperty == pacedProperty) {
-    return;
-  }
-
-  mEffectOptions.mSpacingMode = spacingMode;
-  mEffectOptions.mPacedProperty = pacedProperty;
-
-  // Apply spacing. We apply distribute here. If the new spacing is paced,
-  // UpdateProperties() will apply it.
-  if (mEffectOptions.mSpacingMode == SpacingMode::distribute) {
-    KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
-  }
-
-  if (mAnimation && mAnimation->IsRelevant()) {
-    nsNodeUtils::AnimationChanged(mAnimation);
-  }
-
-  if (mTarget) {
-    RefPtr<nsStyleContext> styleContext = GetTargetStyleContext();
-    if (styleContext) {
-      UpdateProperties(styleContext);
-    }
-  }
-}
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -67,22 +67,16 @@ public:
 
   // This method calls GetTargetStyleContext which is not safe to use when
   // we are in the middle of updating style. If we need to use this when
   // updating style, we should pass the nsStyleContext into this method and use
   // that to update the properties rather than calling
   // GetStyleContext.
   void SetTarget(const Nullable<ElementOrCSSPseudoElement>& aTarget);
 
-  void GetSpacing(nsString& aRetVal, CallerType aCallerType)
-  {
-    KeyframeEffectReadOnly::GetSpacing(aRetVal);
-  }
-  void SetSpacing(JSContext* aCx, const nsAString& aSpacing,
-                  CallerType aCallerType, ErrorResult& aRv);
   IterationCompositeOperation IterationComposite(CallerType aCallerType)
   {
     return KeyframeEffectReadOnly::IterationComposite();
   }
   void SetIterationComposite(
     const IterationCompositeOperation& aIterationComposite,
     CallerType aCallerType);
   void SetComposite(const CompositeOperation& aComposite);
deleted file mode 100644
--- a/dom/animation/KeyframeEffectParams.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/KeyframeEffectParams.h"
-
-#include "mozilla/AnimationUtils.h"
-#include "mozilla/ErrorResult.h"
-#include "mozilla/KeyframeUtils.h"
-#include "mozilla/RangedPtr.h"
-#include "nsReadableUtils.h"
-
-namespace mozilla {
-
-static inline bool
-IsLetter(char16_t aCh)
-{
-  return (0x41 <= aCh && aCh <= 0x5A) || (0x61 <= aCh && aCh <= 0x7A);
-}
-
-static inline bool
-IsDigit(char16_t aCh)
-{
-  return 0x30 <= aCh && aCh <= 0x39;
-}
-
-static inline bool
-IsNameStartCode(char16_t aCh)
-{
-  return IsLetter(aCh) || aCh >= 0x80 || aCh == '_';
-}
-
-static inline bool
-IsNameCode(char16_t aCh)
-{
-  return IsNameStartCode(aCh) || IsDigit(aCh) || aCh == '-';
-}
-
-static inline bool
-IsNewLine(char16_t aCh)
-{
-  // 0x0A (LF), 0x0C (FF), 0x0D (CR), or pairs of CR followed by LF are
-  // replaced by LF.
-  return aCh == 0x0A || aCh == 0x0C || aCh == 0x0D;
-}
-
-static inline bool
-IsValidEscape(char16_t aFirst, char16_t aSecond)
-{
-  return aFirst == '\\' && !IsNewLine(aSecond);
-}
-
-static bool
-IsIdentStart(RangedPtr<const char16_t> aIter,
-             const char16_t* const aEnd)
-{
-  if (aIter == aEnd) {
-    return false;
-  }
-
-  if (*aIter == '-') {
-    if (aIter + 1 == aEnd) {
-      return false;
-    }
-    char16_t second = *(aIter + 1);
-    return IsNameStartCode(second) ||
-           second == '-' ||
-           (aIter + 2 != aEnd && IsValidEscape(second, *(aIter + 2)));
-  }
-  return IsNameStartCode(*aIter) ||
-         (aIter + 1 != aEnd && IsValidEscape(*aIter, *(aIter + 1)));
-}
-
-static void
-ConsumeIdentToken(RangedPtr<const char16_t>& aIter,
-                  const char16_t* const aEnd,
-                  nsAString& aResult)
-{
-  aResult.Truncate();
-
-  // Check if it starts with an identifier.
-  if (!IsIdentStart(aIter, aEnd)) {
-    return;
-  }
-
-  // Start to consume.
-  while (aIter != aEnd) {
-    if (IsNameCode(*aIter)) {
-      aResult.Append(*aIter);
-    } else if (*aIter == '\\') {
-      const RangedPtr<const char16_t> secondChar = aIter + 1;
-      if (secondChar == aEnd || !IsValidEscape(*aIter, *secondChar)) {
-        break;
-      }
-      // Consume '\\' and append the character following this '\\'.
-      ++aIter;
-      aResult.Append(*aIter);
-    } else {
-      break;
-    }
-    ++aIter;
-  }
-}
-
-/* static */ void
-KeyframeEffectParams::ParseSpacing(const nsAString& aSpacing,
-                                   SpacingMode& aSpacingMode,
-                                   nsCSSPropertyID& aPacedProperty,
-                                   nsAString& aInvalidPacedProperty,
-                                   dom::CallerType aCallerType,
-                                   ErrorResult& aRv)
-{
-  aInvalidPacedProperty.Truncate();
-
-  // Ignore spacing if the core API is not enabled since it is not yet ready to
-  // ship.
-  if (!AnimationUtils::IsCoreAPIEnabledForCaller(aCallerType)) {
-    aSpacingMode = SpacingMode::distribute;
-    return;
-  }
-
-  // Parse spacing.
-  // distribute | paced({ident})
-  // https://w3c.github.io/web-animations/#dom-keyframeeffectreadonly-spacing
-  // 1. distribute spacing.
-  if (aSpacing.EqualsLiteral("distribute")) {
-    aSpacingMode = SpacingMode::distribute;
-    return;
-  }
-
-  // 2. paced spacing.
-  static const nsLiteralString kPacedPrefix = NS_LITERAL_STRING("paced(");
-  if (!StringBeginsWith(aSpacing, kPacedPrefix)) {
-    aRv.ThrowTypeError<dom::MSG_INVALID_SPACING_MODE_ERROR>(aSpacing);
-    return;
-  }
-
-  RangedPtr<const char16_t> iter(aSpacing.Data() + kPacedPrefix.Length(),
-                                 aSpacing.Data(), aSpacing.Length());
-  const char16_t* const end = aSpacing.EndReading();
-
-  nsAutoString identToken;
-  ConsumeIdentToken(iter, end, identToken);
-  if (identToken.IsEmpty()) {
-    aRv.ThrowTypeError<dom::MSG_INVALID_SPACING_MODE_ERROR>(aSpacing);
-    return;
-  }
-
-  aPacedProperty =
-    nsCSSProps::LookupProperty(identToken, CSSEnabledState::eForAllContent);
-  if (aPacedProperty == eCSSProperty_UNKNOWN ||
-      aPacedProperty == eCSSPropertyExtra_variable ||
-      // We just unconditionally pass Gecko as the backend type here since
-      // Servo doesn't support paced timing and this feature will soon be
-      // removed (bug 1339690).
-      !KeyframeUtils::IsAnimatableProperty(aPacedProperty,
-                                           StyleBackendType::Gecko)) {
-    aPacedProperty = eCSSProperty_UNKNOWN;
-    aInvalidPacedProperty = identToken;
-  }
-
-  if (end - iter.get() != 1 || *iter != ')') {
-    aRv.ThrowTypeError<dom::MSG_INVALID_SPACING_MODE_ERROR>(aSpacing);
-    return;
-  }
-
-  aSpacingMode = aPacedProperty == eCSSProperty_UNKNOWN
-                 ? SpacingMode::distribute
-                 : SpacingMode::paced;
-}
-
-} // namespace mozilla
--- a/dom/animation/KeyframeEffectParams.h
+++ b/dom/animation/KeyframeEffectParams.h
@@ -2,69 +2,26 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_KeyframeEffectParams_h
 #define mozilla_KeyframeEffectParams_h
 
-#include "nsCSSProps.h"
-#include "nsString.h"
 // X11 has a #define for None
 #ifdef None
 #undef None
 #endif
 #include "mozilla/dom/KeyframeEffectBinding.h" // IterationCompositeOperation
-#include "mozilla/dom/BindingDeclarations.h"   // CallerType
 
 namespace mozilla {
 
-class ErrorResult;
-
-enum class SpacingMode
-{
-  distribute,
-  paced
-};
-
 struct KeyframeEffectParams
 {
-  void GetSpacingAsString(nsAString& aSpacing) const
-  {
-    if (mSpacingMode == SpacingMode::distribute) {
-      aSpacing.AssignLiteral("distribute");
-    } else {
-      aSpacing.AssignLiteral("paced(");
-      aSpacing.AppendASCII(nsCSSProps::GetStringValue(mPacedProperty).get());
-      aSpacing.AppendLiteral(")");
-    }
-  }
-
-  /**
-   * Parse spacing string.
-   *
-   * @param aSpacing The input spacing string.
-   * @param [out] aSpacingMode The parsed spacing mode.
-   * @param [out] aPacedProperty The parsed CSS property if using paced spacing.
-   * @param [out] aInvalidPacedProperty A string that, if we parsed a string of
-   *                                    the form 'paced(<ident>)' where <ident>
-   *                                    is not a recognized animatable property,
-   *                                    will be set to <ident>.
-   * @param [out] aRv The error result.
-   */
-  static void ParseSpacing(const nsAString& aSpacing,
-                           SpacingMode& aSpacingMode,
-                           nsCSSPropertyID& aPacedProperty,
-                           nsAString& aInvalidPacedProperty,
-                           dom::CallerType aCallerType,
-                           ErrorResult& aRv);
-
   dom::IterationCompositeOperation mIterationComposite =
     dom::IterationCompositeOperation::Replace;
   dom::CompositeOperation mComposite = dom::CompositeOperation::Replace;
-  SpacingMode mSpacingMode = SpacingMode::distribute;
-  nsCSSPropertyID mPacedProperty = eCSSProperty_UNKNOWN;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_KeyframeEffectParams_h
--- a/dom/animation/KeyframeEffectReadOnly.cpp
+++ b/dom/animation/KeyframeEffectReadOnly.cpp
@@ -18,17 +18,16 @@
 #include "mozilla/FloatingPoint.h" // For IsFinite
 #include "mozilla/LookAndFeel.h" // For LookAndFeel::GetInt
 #include "mozilla/KeyframeUtils.h"
 #include "mozilla/ServoBindings.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TypeTraits.h"
 #include "Layers.h" // For Layer
 #include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetStyleContext
-#include "nsContentUtils.h"  // nsContentUtils::ReportToConsole
 #include "nsCSSPropertyIDSet.h"
 #include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
 #include "nsCSSPseudoElements.h" // For CSSPseudoElementType
 #include "nsIPresShell.h"
 #include "nsIScriptError.h"
 
 namespace mozilla {
 
@@ -213,20 +212,16 @@ KeyframeEffectReadOnly::DoSetKeyframes(n
                 "StyleType should be nsStyleContext* or "
                 "const ServoComputedValues*");
 
   if (KeyframesEqualIgnoringComputedOffsets(aKeyframes, mKeyframes)) {
     return;
   }
 
   mKeyframes = Move(aKeyframes);
-  // Apply distribute spacing irrespective of the spacing mode. We will apply
-  // the specified spacing mode when we generate computed animation property
-  // values from the keyframes since both operations require a style context
-  // and need to be performed whenever the style context changes.
   KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
 
   if (mAnimation && mAnimation->IsRelevant()) {
     nsNodeUtils::AnimationChanged(mAnimation);
   }
 
   // We need to call UpdateProperties() if the StyleType is not nullptr.
   if (aStyle) {
@@ -783,37 +778,30 @@ KeyframeEffectOptionsFromUnion(
 {
   MOZ_ASSERT(aOptions.IsKeyframeAnimationOptions());
   return aOptions.GetAsKeyframeAnimationOptions();
 }
 
 template <class OptionsType>
 static KeyframeEffectParams
 KeyframeEffectParamsFromUnion(const OptionsType& aOptions,
-                              nsAString& aInvalidPacedProperty,
-                              CallerType aCallerType,
-                              ErrorResult& aRv)
+                              CallerType aCallerType)
 {
   KeyframeEffectParams result;
-  if (!aOptions.IsUnrestrictedDouble()) {
-    const KeyframeEffectOptions& options =
-      KeyframeEffectOptionsFromUnion(aOptions);
-    KeyframeEffectParams::ParseSpacing(options.mSpacing,
-                                       result.mSpacingMode,
-                                       result.mPacedProperty,
-                                       aInvalidPacedProperty,
-                                       aCallerType,
-                                       aRv);
-    // Ignore iterationComposite if the Web Animations API is not enabled,
-    // then the default value 'Replace' will be used.
-    if (AnimationUtils::IsCoreAPIEnabledForCaller(aCallerType)) {
-      result.mIterationComposite = options.mIterationComposite;
-      result.mComposite = options.mComposite;
-    }
+  if (aOptions.IsUnrestrictedDouble() ||
+      // Ignore iterationComposite if the Web Animations API is not enabled,
+      // then the default value 'Replace' will be used.
+      !AnimationUtils::IsCoreAPIEnabledForCaller(aCallerType)) {
+    return result;
   }
+
+  const KeyframeEffectOptions& options =
+    KeyframeEffectOptionsFromUnion(aOptions);
+  result.mIterationComposite = options.mIterationComposite;
+  result.mComposite = options.mComposite;
   return result;
 }
 
 /* static */ Maybe<OwningAnimationTarget>
 KeyframeEffectReadOnly::ConvertTarget(
   const Nullable<ElementOrCSSPseudoElement>& aTarget)
 {
   // Return value optimization.
@@ -852,33 +840,18 @@ KeyframeEffectReadOnly::ConstructKeyfram
   }
 
   TimingParams timingParams =
     TimingParams::FromOptionsUnion(aOptions, doc, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
-  nsAutoString invalidPacedProperty;
   KeyframeEffectParams effectOptions =
-    KeyframeEffectParamsFromUnion(aOptions, invalidPacedProperty,
-                                  aGlobal.CallerType(), aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  if (!invalidPacedProperty.IsEmpty()) {
-    const char16_t* params[] = { invalidPacedProperty.get() };
-    nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
-                                    NS_LITERAL_CSTRING("Animation"),
-                                    doc,
-                                    nsContentUtils::eDOM_PROPERTIES,
-                                    "UnanimatablePacedProperty",
-                                    params, ArrayLength(params));
-  }
+    KeyframeEffectParamsFromUnion(aOptions, aGlobal.CallerType());
 
   Maybe<OwningAnimationTarget> target = ConvertTarget(aTarget);
   RefPtr<KeyframeEffectType> effect =
     new KeyframeEffectType(doc, target, timingParams, effectOptions);
 
   effect->SetKeyframes(aGlobal.Context(), aKeyframes, aRv);
   if (aRv.Failed()) {
     return nullptr;
@@ -949,25 +922,16 @@ KeyframeEffectReadOnly::BuildProperties(
   // make a copy of |mKeyframes| first and iterate over that instead.
   auto keyframesCopy(mKeyframes);
 
   nsTArray<ComputedKeyframeValues> computedValues =
     KeyframeUtils::GetComputedKeyframeValues(keyframesCopy,
                                              mTarget->mElement,
                                              aStyle);
 
-  // FIXME: Bug 1332633: we have to implement ComputeDistance for
-  //        RawServoAnimationValue.
-  if (mEffectOptions.mSpacingMode == SpacingMode::paced &&
-      !mDocument->IsStyledByServo()) {
-    KeyframeUtils::ApplySpacing(keyframesCopy, SpacingMode::paced,
-                                mEffectOptions.mPacedProperty,
-                                computedValues, aStyle);
-  }
-
   result =
     KeyframeUtils::GetAnimationPropertiesFromKeyframes(
       keyframesCopy,
       computedValues,
       mEffectOptions.mComposite);
 
 #ifdef DEBUG
   MOZ_ASSERT(SpecifiedKeyframeArraysAreEqual(mKeyframes, keyframesCopy),
--- a/dom/animation/KeyframeEffectReadOnly.h
+++ b/dom/animation/KeyframeEffectReadOnly.h
@@ -153,20 +153,16 @@ public:
   void GetKeyframes(JSContext*& aCx,
                     nsTArray<JSObject*>& aResult,
                     ErrorResult& aRv);
   void GetProperties(nsTArray<AnimationPropertyDetails>& aProperties,
                      ErrorResult& aRv) const;
 
   IterationCompositeOperation IterationComposite() const;
   CompositeOperation Composite() const;
-  void GetSpacing(nsString& aRetVal) const
-  {
-    mEffectOptions.GetSpacingAsString(aRetVal);
-  }
   void NotifyAnimationTimingUpdated();
   void RequestRestyle(EffectCompositor::RestyleType aRestyleType);
   void SetAnimation(Animation* aAnimation) override;
   void SetKeyframes(JSContext* aContext, JS::Handle<JSObject*> aKeyframes,
                     ErrorResult& aRv);
   void SetKeyframes(nsTArray<Keyframe>&& aKeyframes,
                     nsStyleContext* aStyleContext);
   void SetKeyframes(nsTArray<Keyframe>&& aKeyframes,
--- a/dom/animation/KeyframeUtils.cpp
+++ b/dom/animation/KeyframeUtils.cpp
@@ -31,20 +31,16 @@
 namespace mozilla {
 
 // ------------------------------------------------------------------
 //
 // Internal data types
 //
 // ------------------------------------------------------------------
 
-// This is used while calculating paced spacing. If the keyframe is not pacable,
-// we set its cumulative distance to kNotPaceable, so we can use this to check.
-const double kNotPaceable = -1.0;
-
 // For the aAllowList parameter of AppendStringOrStringSequence and
 // GetPropertyValuesPairs.
 enum class ListAllowance { eDisallow, eAllow };
 
 /**
  * A comparator to sort nsCSSPropertyID values such that longhands are sorted
  * before shorthands, and shorthands with fewer components are sorted before
  * shorthands with more components.
@@ -408,31 +404,18 @@ GetKeyframeListFromPropertyIndexedKeyfra
                                            nsTArray<Keyframe>& aResult,
                                            ErrorResult& aRv);
 
 static bool
 RequiresAdditiveAnimation(const nsTArray<Keyframe>& aKeyframes,
                           nsIDocument* aDocument);
 
 static void
-DistributeRange(const Range<Keyframe>& aSpacingRange,
-                const Range<Keyframe>& aRangeToAdjust);
-
-static void
 DistributeRange(const Range<Keyframe>& aSpacingRange);
 
-static void
-PaceRange(const Range<Keyframe>& aKeyframes,
-          const Range<double>& aCumulativeDistances);
-
-static nsTArray<double>
-GetCumulativeDistances(const nsTArray<ComputedKeyframeValues>& aValues,
-                       nsCSSPropertyID aProperty,
-                       nsStyleContext* aStyleContext);
-
 // ------------------------------------------------------------------
 //
 // Public API
 //
 // ------------------------------------------------------------------
 
 /* static */ nsTArray<Keyframe>
 KeyframeUtils::GetKeyframesFromObject(JSContext* aCx,
@@ -477,42 +460,22 @@ KeyframeUtils::GetKeyframesFromObject(JS
     keyframes.Clear();
     aRv.Throw(NS_ERROR_DOM_ANIM_MISSING_PROPS_ERR);
   }
 
   return keyframes;
 }
 
 /* static */ void
-KeyframeUtils::ApplySpacing(nsTArray<Keyframe>& aKeyframes,
-                            SpacingMode aSpacingMode,
-                            nsCSSPropertyID aProperty,
-                            nsTArray<ComputedKeyframeValues>& aComputedValues,
-                            nsStyleContext* aStyleContext)
+KeyframeUtils::ApplyDistributeSpacing(nsTArray<Keyframe>& aKeyframes)
 {
   if (aKeyframes.IsEmpty()) {
     return;
   }
 
-  nsTArray<double> cumulativeDistances;
-  if (aSpacingMode == SpacingMode::paced) {
-    // We just unconditionally pass Gecko as the backend type here since
-    // Servo doesn't support paced timing and this feature will soon be removed
-    // (bug 1339690).
-    MOZ_ASSERT(IsAnimatableProperty(aProperty, StyleBackendType::Gecko),
-               "Paced property should be animatable");
-
-    cumulativeDistances = GetCumulativeDistances(aComputedValues, aProperty,
-                                                 aStyleContext);
-    // Reset the computed offsets if using paced spacing.
-    for (Keyframe& keyframe : aKeyframes) {
-      keyframe.mComputedOffset = Keyframe::kComputedOffsetNotSet;
-    }
-  }
-
   // If the first keyframe has an unspecified offset, fill it in with 0%.
   // If there is only a single keyframe, then it gets 100%.
   if (aKeyframes.Length() > 1) {
     Keyframe& firstElement = aKeyframes[0];
     firstElement.mComputedOffset = firstElement.mOffset.valueOr(0.0);
     // We will fill in the last keyframe's offset below
   } else {
     Keyframe& lastElement = aKeyframes.LastElement();
@@ -527,80 +490,21 @@ KeyframeUtils::ApplySpacing(nsTArray<Key
     // Find keyframe A and keyframe B *between* which we will apply spacing.
     RangedPtr<Keyframe> keyframeB = keyframeA + 1;
     while (keyframeB->mOffset.isNothing() && keyframeB != last) {
       ++keyframeB;
     }
     keyframeB->mComputedOffset = keyframeB->mOffset.valueOr(1.0);
 
     // Fill computed offsets in (keyframe A, keyframe B).
-    if (aSpacingMode == SpacingMode::distribute) {
-      DistributeRange(Range<Keyframe>(keyframeA, keyframeB + 1));
-    } else {
-      // a) Find Paced A (first paceable keyframe) and
-      //    Paced B (last paceable keyframe) in [keyframe A, keyframe B].
-      RangedPtr<Keyframe> pacedA = keyframeA;
-      while (pacedA < keyframeB &&
-             cumulativeDistances[pacedA - begin] == kNotPaceable) {
-        ++pacedA;
-      }
-      RangedPtr<Keyframe> pacedB = keyframeB;
-      while (pacedB > keyframeA &&
-             cumulativeDistances[pacedB - begin] == kNotPaceable) {
-        --pacedB;
-      }
-      // As spec says, if there is no paceable keyframe
-      // in [keyframe A, keyframe B], we let Paced A and Paced B refer to
-      // keyframe B.
-      if (pacedA > pacedB) {
-        pacedA = pacedB = keyframeB;
-      }
-      // b) Apply distributing offsets in (keyframe A, Paced A] and
-      //    [Paced B, keyframe B).
-      DistributeRange(Range<Keyframe>(keyframeA, keyframeB + 1),
-                      Range<Keyframe>(keyframeA + 1, pacedA + 1));
-      DistributeRange(Range<Keyframe>(keyframeA, keyframeB + 1),
-                      Range<Keyframe>(pacedB, keyframeB));
-      // c) Apply paced offsets to each paceable keyframe in (Paced A, Paced B).
-      //    We pass the range [Paced A, Paced B] since PaceRange needs the end
-      //    points of the range in order to calculate the correct offset.
-      PaceRange(Range<Keyframe>(pacedA, pacedB + 1),
-                Range<double>(&cumulativeDistances[pacedA - begin],
-                              pacedB - pacedA + 1));
-      // d) Fill in any computed offsets in (Paced A, Paced B) that are still
-      //    not set (e.g. because the keyframe was not paceable, or because the
-      //    cumulative distance between paceable properties was zero).
-      for (RangedPtr<Keyframe> frame = pacedA + 1; frame < pacedB; ++frame) {
-        if (frame->mComputedOffset != Keyframe::kComputedOffsetNotSet) {
-          continue;
-        }
-
-        RangedPtr<Keyframe> start = frame - 1;
-        RangedPtr<Keyframe> end = frame + 1;
-        while (end < pacedB &&
-               end->mComputedOffset == Keyframe::kComputedOffsetNotSet) {
-          ++end;
-        }
-        DistributeRange(Range<Keyframe>(start, end + 1));
-        frame = end;
-      }
-    }
+    DistributeRange(Range<Keyframe>(keyframeA, keyframeB + 1));
     keyframeA = keyframeB;
   }
 }
 
-/* static */ void
-KeyframeUtils::ApplyDistributeSpacing(nsTArray<Keyframe>& aKeyframes)
-{
-  nsTArray<ComputedKeyframeValues> emptyArray;
-  // FIXME: Bug 1339690: below static_cast should be dropped.
-  ApplySpacing(aKeyframes, SpacingMode::distribute, eCSSProperty_UNKNOWN,
-               emptyArray, static_cast<nsStyleContext*>(nullptr));
-}
-
 /* static */ nsTArray<ComputedKeyframeValues>
 KeyframeUtils::GetComputedKeyframeValues(
   const nsTArray<Keyframe>& aKeyframes,
   dom::Element* aElement,
   const ServoComputedValues* aComputedValues)
 {
   MOZ_ASSERT(aElement);
   MOZ_ASSERT(aElement->IsStyledByServo());
@@ -1562,17 +1466,17 @@ RequiresAdditiveAnimation(const nsTArray
     }
   };
 
   StyleBackendType styleBackend = aDocument->GetStyleBackendType();
 
   for (size_t i = 0, len = aKeyframes.Length(); i < len; i++) {
     const Keyframe& frame = aKeyframes[i];
 
-    // We won't have called ApplySpacing when this is called so
+    // We won't have called ApplyDistributeSpacing when this is called so
     // we can't use frame.mComputedOffset. Instead we do a rough version
     // of that algorithm that substitutes null offsets with 0.0 for the first
     // frame, 1.0 for the last frame, and 0.5 for everything else.
     double computedOffset = i == len - 1
                             ? 1.0
                             : i == 0 ? 0.0 : 0.5;
     double offsetToUse = frame.mOffset
                          ? frame.mOffset.value()
@@ -1615,17 +1519,17 @@ RequiresAdditiveAnimation(const nsTArray
 /**
  * Evenly distribute the computed offsets in (A, B).
  * We pass the range keyframes in [A, B] and use A, B to calculate distributing
  * computed offsets in (A, B). The second range, aRangeToAdjust, is passed, so
  * we can know which keyframe we want to apply to. aRangeToAdjust should be in
  * the range of aSpacingRange.
  *
  * @param aSpacingRange The sequence of keyframes between whose endpoints we
- *   should apply distribute spacing.
+ *   should apply distribute offsets.
  * @param aRangeToAdjust The range of keyframes we want to apply to.
  */
 static void
 DistributeRange(const Range<Keyframe>& aSpacingRange,
                 const Range<Keyframe>& aRangeToAdjust)
 {
   MOZ_ASSERT(aRangeToAdjust.begin() >= aSpacingRange.begin() &&
              aRangeToAdjust.end() <= aSpacingRange.end(),
@@ -1652,175 +1556,9 @@ static void
 DistributeRange(const Range<Keyframe>& aSpacingRange)
 {
   // We don't need to apply distribute spacing to keyframe A and keyframe B.
   DistributeRange(aSpacingRange,
                   Range<Keyframe>(aSpacingRange.begin() + 1,
                                   aSpacingRange.end() - 1));
 }
 
-/**
- * Apply paced spacing to all paceable keyframes in between the endpoints of the
- * given range.
- *
- * @param aKeyframes The range of keyframes between whose endpoints we should
- *   apply paced spacing. Both endpoints should be paceable, i.e. the
- *   corresponding elements in |aCumulativeDist| should not be kNotPaceable.
- *   Within this function, we refer to the start and end points of this range
- *   as Paced A and Paced B respectively in keeping with the notation used in
- *   the spec.
- * @param aCumulativeDistances The sequence of cumulative distances of the paced
- *   property as returned by GetCumulativeDistances(). This acts as a
- *   parallel range to |aKeyframes|.
- */
-static void
-PaceRange(const Range<Keyframe>& aKeyframes,
-          const Range<double>& aCumulativeDistances)
-{
-  MOZ_ASSERT(aKeyframes.length() == aCumulativeDistances.length(),
-             "Range length mismatch");
-
-  const size_t len = aKeyframes.length();
-  // If there is nothing between the end points, there is nothing to space.
-  if (len < 3) {
-    return;
-  }
-
-  const double distA = *(aCumulativeDistances.begin());
-  const double distB = *(aCumulativeDistances.end() - 1);
-  MOZ_ASSERT(distA != kNotPaceable && distB != kNotPaceable,
-             "Both Paced A and Paced B should be paceable");
-
-  // If the total distance is zero, we should fall back to distribute spacing.
-  // The caller will fill-in any keyframes without a computed offset using
-  // distribute spacing so we can just return here.
-  if (distA == distB) {
-    return;
-  }
-
-  const RangedPtr<Keyframe> pacedA = aKeyframes.begin();
-  const RangedPtr<Keyframe> pacedB = aKeyframes.end() - 1;
-  MOZ_ASSERT(pacedA->mComputedOffset != Keyframe::kComputedOffsetNotSet &&
-             pacedB->mComputedOffset != Keyframe::kComputedOffsetNotSet,
-             "Both Paced A and Paced B should have valid computed offsets");
-
-  // Apply computed offset.
-  const double offsetA     = pacedA->mComputedOffset;
-  const double diffOffset  = pacedB->mComputedOffset - offsetA;
-  const double initialDist = distA;
-  const double totalDist   = distB - initialDist;
-  for (auto iter = pacedA + 1; iter != pacedB; ++iter) {
-    size_t k = iter - aKeyframes.begin();
-    if (aCumulativeDistances[k] == kNotPaceable) {
-      continue;
-    }
-
-    double dist = aCumulativeDistances[k] - initialDist;
-    iter->mComputedOffset = offsetA + diffOffset * dist / totalDist;
-  }
-}
-
-/**
- * Get cumulative distances for the paced property.
- *
- * @param aValues The computed values returned by GetComputedKeyframeValues.
- * @param aPacedProperty The paced property.
- * @param aStyleContext The style context for computing distance on transform.
- * @return The cumulative distances for the paced property. The length will be
- *   the same as aValues.
- */
-static nsTArray<double>
-GetCumulativeDistances(const nsTArray<ComputedKeyframeValues>& aValues,
-                       nsCSSPropertyID aPacedProperty,
-                       nsStyleContext* aStyleContext)
-{
-  // a) If aPacedProperty is a shorthand property, get its components.
-  //    Otherwise, just add the longhand property into the set.
-  size_t pacedPropertyCount = 0;
-  nsCSSPropertyIDSet pacedPropertySet;
-  bool isShorthand = nsCSSProps::IsShorthand(aPacedProperty);
-  if (isShorthand) {
-    CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aPacedProperty,
-                                         CSSEnabledState::eForAllContent) {
-      pacedPropertySet.AddProperty(*p);
-      ++pacedPropertyCount;
-    }
-  } else {
-    pacedPropertySet.AddProperty(aPacedProperty);
-    pacedPropertyCount = 1;
-  }
-
-  // b) Search each component (shorthand) or the longhand property, and
-  //    calculate the cumulative distances of paceable keyframe pairs.
-  const size_t len = aValues.Length();
-  nsTArray<double> cumulativeDistances(len);
-  // cumulativeDistances is a parallel array to |aValues|, so set its length to
-  // the length of |aValues|.
-  cumulativeDistances.SetLength(len);
-  ComputedKeyframeValues prevPacedValues;
-  size_t preIdx = 0;
-  for (size_t i = 0; i < len; ++i) {
-    // Find computed values of the paced property.
-    ComputedKeyframeValues pacedValues;
-    for (const PropertyStyleAnimationValuePair& pair : aValues[i]) {
-      if (pacedPropertySet.HasProperty(pair.mProperty)) {
-        pacedValues.AppendElement(pair);
-      }
-    }
-
-    // Check we have values for all the paceable longhand components.
-    if (pacedValues.Length() != pacedPropertyCount) {
-      // This keyframe is not paceable, assign kNotPaceable and skip it.
-      cumulativeDistances[i] = kNotPaceable;
-      continue;
-    }
-
-    // Sort the pacedValues first, so the order of subproperties of
-    // pacedValues is always the same as that of prevPacedValues.
-    if (isShorthand) {
-      pacedValues.Sort(
-        TPropertyPriorityComparator<PropertyStyleAnimationValuePair>());
-    }
-
-    if (prevPacedValues.IsEmpty()) {
-      // This is the first paceable keyframe so its cumulative distance is 0.0.
-      cumulativeDistances[i] = 0.0;
-    } else {
-      double dist = 0.0;
-      if (isShorthand) {
-        // Apply the distance by the square root of the sum of squares of
-        // longhand component distances.
-        for (size_t propIdx = 0; propIdx < pacedPropertyCount; ++propIdx) {
-          nsCSSPropertyID prop = prevPacedValues[propIdx].mProperty;
-          MOZ_ASSERT(pacedValues[propIdx].mProperty == prop,
-                     "Property mismatch");
-
-          double componentDistance = 0.0;
-          if (StyleAnimationValue::ComputeDistance(
-                prop,
-                prevPacedValues[propIdx].mValue.mGecko,
-                pacedValues[propIdx].mValue.mGecko,
-                aStyleContext,
-                componentDistance)) {
-            dist += componentDistance * componentDistance;
-          }
-        }
-        dist = sqrt(dist);
-      } else {
-        // If the property is longhand, we just use the 1st value.
-        // If ComputeDistance() fails, |dist| will remain zero so there will be
-        // no distance between the previous paced value and this value.
-        Unused <<
-          StyleAnimationValue::ComputeDistance(aPacedProperty,
-                                               prevPacedValues[0].mValue.mGecko,
-                                               pacedValues[0].mValue.mGecko,
-                                               aStyleContext,
-                                               dist);
-      }
-      cumulativeDistances[i] = cumulativeDistances[preIdx] + dist;
-    }
-    prevPacedValues.SwapElements(pacedValues);
-    preIdx = i;
-  }
-  return cumulativeDistances;
-}
-
 } // namespace mozilla
--- a/dom/animation/KeyframeUtils.h
+++ b/dom/animation/KeyframeUtils.h
@@ -2,19 +2,20 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_KeyframeUtils_h
 #define mozilla_KeyframeUtils_h
 
+#include "mozilla/KeyframeEffectParams.h" // For CompositeOperation
+#include "nsCSSPropertyID.h"
 #include "nsTArrayForwardDeclare.h" // For nsTArray
 #include "js/RootingAPI.h" // For JS::Handle
-#include "mozilla/KeyframeEffectParams.h" // SpacingMode
 
 struct JSContext;
 class JSObject;
 class nsIDocument;
 class nsStyleContext;
 struct ServoComputedValues;
 struct RawServoDeclarationBlock;
 
@@ -86,67 +87,37 @@ public:
                             nsStyleContext* aStyleContext);
 
   static nsTArray<ComputedKeyframeValues>
   GetComputedKeyframeValues(const nsTArray<Keyframe>& aKeyframes,
                             dom::Element* aElement,
                             const ServoComputedValues* aComputedValues);
 
   /**
-   * Fills in the mComputedOffset member of each keyframe in the given array
-   * using the specified spacing mode.
-   *
-   * https://w3c.github.io/web-animations/#spacing-keyframes
+   * Calculate the computed offset of keyframes by evenly distributing keyframes
+   * with a missing offset.
    *
-   * @param aKeyframes The set of keyframes to adjust.
-   * @param aSpacingMode The spacing mode to apply.
-   * @param aProperty The paced property. Only used when |aSpacingMode| is
-   *   SpacingMode::paced. In all other cases it is ignored and hence may be
-   *   any value, e.g. eCSSProperty_UNKNOWN.
-   * @param aComputedValues The set of computed keyframe values as returned by
-   *   GetComputedKeyframeValues. Only used when |aSpacingMode| is
-   *   SpacingMode::paced. In all other cases this parameter is unused and may
-   *   be any value including an empty array.
-   * @param aStyleContext The style context used for calculating paced spacing
-   *                      on transform.
-   */
-  static void ApplySpacing(nsTArray<Keyframe>& aKeyframes,
-                           SpacingMode aSpacingMode,
-                           nsCSSPropertyID aProperty,
-                           nsTArray<ComputedKeyframeValues>& aComputedValues,
-                           nsStyleContext* aStyleContext);
-  static void ApplySpacing(nsTArray<Keyframe>& aKeyframes,
-                           SpacingMode aSpacingMode,
-                           nsCSSPropertyID aProperty,
-                           nsTArray<ComputedKeyframeValues>& aComputedValues,
-                           const ServoComputedValues* aServoValues)
-  {
-    NS_WARNING("stylo: ApplySpacing not implemented yet");
-  }
-
-  /**
-   * Wrapper for ApplySpacing to simplify using distribute spacing.
+   * @see https://w3c.github.io/web-animations/#calculating-computed-keyframes
    *
    * @param aKeyframes The set of keyframes to adjust.
    */
   static void ApplyDistributeSpacing(nsTArray<Keyframe>& aKeyframes);
 
   /**
    * Converts an array of Keyframe objects into an array of AnimationProperty
    * objects. This involves creating an array of computed values for each
    * longhand property and determining the offset and timing function to use
    * for each value.
    *
    * @param aKeyframes The input keyframes.
    * @param aComputedValues The computed keyframe values (as returned by
    *   GetComputedKeyframeValues) used to fill in the individual
    *   AnimationPropertySegment objects. Although these values could be
    *   calculated from |aKeyframes|, passing them in as a separate parameter
-   *   allows the result of GetComputedKeyframeValues to be re-used both
-   *   here and in ApplySpacing.
+   *   allows the result of GetComputedKeyframeValues to be re-used here.
    * @param aEffectComposite The composite operation specified on the effect.
    *   For any keyframes in |aKeyframes| that do not specify a composite
    *   operation, this value will be used.
    * @return The set of animation properties. If an error occurs, the returned
    *   array will be empty.
    */
   static nsTArray<AnimationProperty> GetAnimationPropertiesFromKeyframes(
     const nsTArray<Keyframe>& aKeyframes,
--- a/dom/animation/moz.build
+++ b/dom/animation/moz.build
@@ -51,17 +51,16 @@ UNIFIED_SOURCES += [
     'AnimationUtils.cpp',
     'AnimValuesStyleRule.cpp',
     'ComputedTimingFunction.cpp',
     'CSSPseudoElement.cpp',
     'DocumentTimeline.cpp',
     'EffectCompositor.cpp',
     'EffectSet.cpp',
     'KeyframeEffect.cpp',
-    'KeyframeEffectParams.cpp',
     'KeyframeEffectReadOnly.cpp',
     'KeyframeUtils.cpp',
     'PendingAnimationTracker.cpp',
     'TimingParams.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/dom/base',
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -553,20 +553,16 @@ DOMInterfaces = {
     'nativeType': 'mozilla::dom::DOMIntersectionObserverEntry',
     'headerFile': 'DOMIntersectionObserver.h',
 },
 
 'KeyEvent': {
     'concrete': False
 },
 
-'KeyframeEffect': {
-    'implicitJSContext': { 'setterOnly': [ 'spacing' ] }
-},
-
 'LegacyMozTCPSocket': {
     'headerFile': 'TCPSocket.h',
     'wrapperCache': False,
 },
 
 'LocalMediaStream': {
     'headerFile': 'DOMMediaStream.h',
     'nativeType': 'mozilla::DOMLocalMediaStream'
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -89,17 +89,16 @@ MSG_DEF(MSG_IS_NOT_PROMISE, 1, JSEXN_TYP
 MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} encountered an error during installation.")
 MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
 MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, JSEXN_TYPEERR, "{0} can't be a typed array on SharedArrayBuffer")
 MSG_DEF(MSG_TYPEDARRAY_IS_DETACHED, 1, JSEXN_TYPEERR, "{0} can't be a detached buffer")
 MSG_DEF(MSG_CACHE_ADD_FAILED_RESPONSE, 3, JSEXN_TYPEERR, "Cache got {0} response with bad status {1} while trying to add request {2}")
 MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 2, JSEXN_TYPEERR, "Failed to update the ServiceWorker for scope {0} because the registration has been {1} since the update was scheduled.")
 MSG_DEF(MSG_INVALID_DURATION_ERROR, 1, JSEXN_TYPEERR, "Invalid duration '{0}'.")
 MSG_DEF(MSG_INVALID_EASING_ERROR, 1, JSEXN_TYPEERR, "Invalid easing '{0}'.")
-MSG_DEF(MSG_INVALID_SPACING_MODE_ERROR, 1, JSEXN_TYPEERR, "Invalid spacing '{0}'.")
 MSG_DEF(MSG_USELESS_SETTIMEOUT, 1, JSEXN_TYPEERR, "Useless {0} call (missing quotes around argument?)")
 MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens")
 MSG_DEF(MSG_CACHE_STREAM_CLOSED, 0, JSEXN_TYPEERR, "Response body is a cache file stream that has already been closed.")
 MSG_DEF(MSG_TIME_VALUE_OUT_OF_RANGE, 1, JSEXN_TYPEERR, "{0} is outside the supported range for time values.")
 MSG_DEF(MSG_ONLY_IF_CACHED_WITHOUT_SAME_ORIGIN, 1, JSEXN_TYPEERR, "Request mode '{0}' was used, but request cache mode 'only-if-cached' can only be used with request mode 'same-origin'.")
 MSG_DEF(MSG_THRESHOLD_RANGE_ERROR, 0, JSEXN_RANGEERR, "Threshold values must all be in the range [0, 1].")
 MSG_DEF(MSG_WORKER_THREAD_SHUTTING_DOWN, 0, JSEXN_TYPEERR, "The Worker thread is shutting down.")
 MSG_DEF(MSG_CACHE_OPEN_FAILED, 0, JSEXN_TYPEERR, "CacheStorage.open() failed to access the storage system.")
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -304,18 +304,16 @@ PushMessageBadCryptoError=The ServiceWorker for scope ‘%1$S’ failed to decrypt a push message. For help with encryption, please see https://developer.mozilla.org/docs/Web/API/Push_API/Using_the_Push_API#Encryption
 # LOCALIZATION NOTE: %1$S is the type of a DOM event. 'passive' is a literal parameter from the DOM spec.
 PreventDefaultFromPassiveListenerWarning=Ignoring ‘preventDefault()’ call on event of type ‘%1$S’ from a listener registered as ‘passive’.
 FileLastModifiedDateWarning=File.lastModifiedDate is deprecated. Use File.lastModified instead.
 # LOCALIZATION NOTE: 'ImageBitmapRenderingContext.transferImageBitmap' and 'ImageBitmapRenderingContext.transferFromImageBitmap' should not be translated
 ImageBitmapRenderingContext_TransferImageBitmap=ImageBitmapRenderingContext.transferImageBitmap is deprecated and will be removed soon. Use ImageBitmapRenderingContext.transferFromImageBitmap instead.
 ChromeScriptedDOMParserWithoutPrincipal=Creating DOMParser without a principal is deprecated.
 IIRFilterChannelCountChangeWarning=IIRFilterNode channel count changes may produce audio glitches.
 BiquadFilterChannelCountChangeWarning=BiquadFilterNode channel count changes may produce audio glitches.
-# LOCALIZATION NOTE: %1$S is the unanimatable paced property.
-UnanimatablePacedProperty=Paced property ‘%1$S’ is not an animatable property.
 # LOCALIZATION NOTE: Do not translate ".jpeg"
 GenericImageNameJPEG=image.jpeg
 # LOCALIZATION NOTE: Do not translate ".gif"
 GenericImageNameGIF=image.gif
 # LOCALIZATION NOTE: Do not translate ".png"
 GenericImageNamePNG=image.png
 GenericFileName=file
 # LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name
--- a/dom/webidl/KeyframeEffect.webidl
+++ b/dom/webidl/KeyframeEffect.webidl
@@ -13,29 +13,27 @@
 enum IterationCompositeOperation {
   "replace",
   "accumulate"
 };
 
 dictionary KeyframeEffectOptions : AnimationEffectTimingProperties {
   IterationCompositeOperation iterationComposite = "replace";
   CompositeOperation          composite = "replace";
-  DOMString                   spacing = "distribute";
 };
 
 [Func="nsDocument::IsWebAnimationsEnabled",
  Constructor ((Element or CSSPseudoElement)? target,
               object? keyframes,
               optional (unrestricted double or KeyframeEffectOptions) options),
  Constructor (KeyframeEffectReadOnly source)]
 interface KeyframeEffectReadOnly : AnimationEffectReadOnly {
   readonly attribute (Element or CSSPseudoElement)?  target;
   readonly attribute IterationCompositeOperation iterationComposite;
   readonly attribute CompositeOperation          composite;
-  readonly attribute DOMString                   spacing;
 
   // We use object instead of ComputedKeyframe so that we can put the
   // property-value pairs on the object.
   [Throws] sequence<object> getKeyframes();
 };
 
 // Non-standard extensions
 dictionary AnimationPropertyValueDetails {
@@ -61,13 +59,11 @@ partial interface KeyframeEffectReadOnly
               object? keyframes,
               optional (unrestricted double or KeyframeEffectOptions) options),
  Constructor (KeyframeEffectReadOnly source)]
 interface KeyframeEffect : KeyframeEffectReadOnly {
   inherit attribute (Element or CSSPseudoElement)? target;
   [NeedsCallerType]
   inherit attribute IterationCompositeOperation    iterationComposite;
   inherit attribute CompositeOperation          composite;
-  [SetterThrows, NeedsCallerType]
-  inherit attribute DOMString                   spacing;
   [Throws]
   void setKeyframes (object? keyframes);
 };