Bug 1049975 - Part 4: Merge two Animation::SetEffect()s. draft
authorBoris Chiou <boris.chiou@gmail.com>
Mon, 25 Jul 2016 16:56:34 +0800
changeset 405232 e78fe8ab037b42a14658ac1851a247316d8ffd21
parent 405231 c892d73b7fc6454602a515e3422122c983a80f1b
child 405233 39dd12ce13c01282d19c8a533bcb2a9f68b180a4
push id27442
push userbmo:boris.chiou@gmail.com
push dateThu, 25 Aug 2016 04:26:27 +0000
bugs1049975
milestone51.0a1
Bug 1049975 - Part 4: Merge two Animation::SetEffect()s. This is a pre-patch for part 5, which is trying to make our code closer to the spec. Some methods in KeyframeEffectReadOnly belong to AnimationEffectReadOnly, so first, use AsKeyframeEffect() to access those keyframe-related methods, and then add virtual methods for timing-related methods to AnimationEffectReadOnly. MozReview-Commit-ID: 1srA1f8JYeN
dom/animation/Animation.cpp
dom/animation/Animation.h
dom/animation/AnimationEffectReadOnly.h
dom/animation/KeyframeEffect.h
dom/base/nsDOMMutationObserver.cpp
dom/base/nsNodeUtils.cpp
layout/base/nsDisplayList.cpp
layout/base/nsLayoutUtils.cpp
layout/style/nsAnimationManager.cpp
layout/style/nsTransitionManager.cpp
layout/style/nsTransitionManager.h
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -119,17 +119,17 @@ Animation::SetId(const nsAString& aId)
   if (mId == aId) {
     return;
   }
   mId = aId;
   nsNodeUtils::AnimationChanged(this);
 }
 
 void
-Animation::SetEffect(KeyframeEffectReadOnly* aEffect)
+Animation::SetEffect(AnimationEffectReadOnly* aEffect)
 {
   RefPtr<Animation> kungFuDeathGrip(this);
 
   if (mEffect == aEffect) {
     return;
   }
   if (mEffect) {
     mEffect->SetAnimation(nullptr);
@@ -512,25 +512,30 @@ Animation::Tick()
     mPendingReadyTime.SetValue(std::min(mTimeline->GetCurrentTime().Value(),
                                         mPendingReadyTime.Value()));
     FinishPendingAt(mPendingReadyTime.Value());
     mPendingReadyTime.SetNull();
   }
 
   if (IsPossiblyOrphanedPendingAnimation()) {
     MOZ_ASSERT(mTimeline && !mTimeline->GetCurrentTime().IsNull(),
-               "Orphaned pending animtaions should have an active timeline");
+               "Orphaned pending animations should have an active timeline");
     FinishPendingAt(mTimeline->GetCurrentTime().Value());
   }
 
   UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
 
+  if (!mEffect) {
+    return;
+  }
+
   // Update layers if we are newly finished.
-  if (mEffect &&
-      !mEffect->Properties().IsEmpty() &&
+  KeyframeEffectReadOnly* keyframeEffect = mEffect->AsKeyframeEffect();
+  if (keyframeEffect &&
+      !keyframeEffect->Properties().IsEmpty() &&
       !mFinishedAtLastComposeStyle &&
       PlayState() == AnimationPlayState::Finished) {
     PostUpdate();
   }
 }
 
 void
 Animation::TriggerOnNextTick(const Nullable<TimeDuration>& aReadyTime)
@@ -821,17 +826,20 @@ Animation::ComposeStyle(RefPtr<AnimValue
         timeToUse = mTimeline->ToTimelineTime(TimeStamp::Now());
       }
       if (!timeToUse.IsNull()) {
         mHoldTime.SetValue((timeToUse.Value() - mStartTime.Value())
                             .MultDouble(mPlaybackRate));
       }
     }
 
-    mEffect->ComposeStyle(aStyleRule, aSetProperties);
+    KeyframeEffectReadOnly* keyframeEffect = mEffect->AsKeyframeEffect();
+    if (keyframeEffect) {
+      keyframeEffect->ComposeStyle(aStyleRule, aSetProperties);
+    }
   }
 
   MOZ_ASSERT(playState == PlayState(),
              "Play state should not change during the course of compositing");
   mFinishedAtLastComposeStyle = (playState == AnimationPlayState::Finished);
 }
 
 void
@@ -1110,30 +1118,35 @@ Animation::FlushStyle() const
   if (doc) {
     doc->FlushPendingNotifications(Flush_Style);
   }
 }
 
 void
 Animation::PostUpdate()
 {
-  nsPresContext* presContext = GetPresContext();
-  if (!presContext) {
-    return;
-  }
-
   if (!mEffect) {
     return;
   }
 
-  Maybe<NonOwningAnimationTarget> target = mEffect->GetTarget();
+  KeyframeEffectReadOnly* keyframeEffect = mEffect->AsKeyframeEffect();
+  if (!keyframeEffect) {
+    return;
+  }
+
+  Maybe<NonOwningAnimationTarget> target = keyframeEffect->GetTarget();
   if (!target) {
     return;
   }
 
+  nsPresContext* presContext = keyframeEffect->GetPresContext();
+  if (!presContext) {
+    return;
+  }
+
   presContext->EffectCompositor()
              ->RequestRestyle(target->mElement,
                               target->mPseudoType,
                               EffectCompositor::RestyleType::Layer,
                               CascadeLevel());
 }
 
 void
@@ -1221,31 +1234,21 @@ Animation::EffectEnd() const
   }
 
   return mEffect->SpecifiedTiming().EndTime();
 }
 
 nsIDocument*
 Animation::GetRenderedDocument() const
 {
-  if (!mEffect) {
+  if (!mEffect || !mEffect->AsKeyframeEffect()) {
     return nullptr;
   }
 
-  return mEffect->GetRenderedDocument();
-}
-
-nsPresContext*
-Animation::GetPresContext() const
-{
-  if (!mEffect) {
-    return nullptr;
-  }
-
-  return mEffect->GetPresContext();
+  return mEffect->AsKeyframeEffect()->GetRenderedDocument();
 }
 
 void
 Animation::DoFinishNotification(SyncNotifyFlag aSyncNotifyFlag)
 {
   CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
 
   if (aSyncNotifyFlag == SyncNotifyFlag::Sync) {
@@ -1307,13 +1310,15 @@ Animation::DispatchPlaybackEvent(const n
   RefPtr<AsyncEventDispatcher> asyncDispatcher =
     new AsyncEventDispatcher(this, event);
   asyncDispatcher->PostDOMEvent();
 }
 
 bool
 Animation::IsRunningOnCompositor() const
 {
-  return mEffect && mEffect->IsRunningOnCompositor();
+  return mEffect &&
+         mEffect->AsKeyframeEffect() &&
+         mEffect->AsKeyframeEffect()->IsRunningOnCompositor();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/animation/Animation.h
+++ b/dom/animation/Animation.h
@@ -92,22 +92,18 @@ public:
   // Animation interface methods
   static already_AddRefed<Animation>
   Constructor(const GlobalObject& aGlobal,
               KeyframeEffectReadOnly* aEffect,
               const Optional<AnimationTimeline*>& aTimeline,
               ErrorResult& aRv);
   void GetId(nsAString& aResult) const { aResult = mId; }
   void SetId(const nsAString& aId);
-  KeyframeEffectReadOnly* GetEffect() const { return mEffect; }
-  void SetEffect(AnimationEffectReadOnly* aEffect)
-  {
-    // TODO: Merged with SetEffect(KeyframeEffectReadOnly*) in the next patch.
-  }
-  virtual void SetEffect(KeyframeEffectReadOnly* aEffect);
+  AnimationEffectReadOnly* GetEffect() const { return mEffect; }
+  virtual void SetEffect(AnimationEffectReadOnly* aEffect);
   AnimationTimeline* GetTimeline() const { return mTimeline; }
   void SetTimeline(AnimationTimeline* aTimeline);
   Nullable<TimeDuration> GetStartTime() const { return mStartTime; }
   void SetStartTime(const Nullable<TimeDuration>& aNewStartTime);
   Nullable<TimeDuration> GetCurrentTime() const;
   void SetCurrentTime(const TimeDuration& aNewCurrentTime);
   double PlaybackRate() const { return mPlaybackRate; }
   void SetPlaybackRate(double aPlaybackRate);
@@ -373,20 +369,19 @@ protected:
    * aborting the mReady promise as necessary.
    */
   void CancelPendingTasks();
 
   bool IsPossiblyOrphanedPendingAnimation() const;
   StickyTimeDuration EffectEnd() const;
 
   nsIDocument* GetRenderedDocument() const;
-  nsPresContext* GetPresContext() const;
 
   RefPtr<AnimationTimeline> mTimeline;
-  RefPtr<KeyframeEffectReadOnly> mEffect;
+  RefPtr<AnimationEffectReadOnly> mEffect;
   // The beginning of the delay period.
   Nullable<TimeDuration> mStartTime; // Timeline timescale
   Nullable<TimeDuration> mHoldTime;  // Animation timescale
   Nullable<TimeDuration> mPendingReadyTime; // Timeline timescale
   Nullable<TimeDuration> mPreviousCurrentTime; // Animation timescale
   double mPlaybackRate;
 
   // A Promise that is replaced on each call to Play()
--- a/dom/animation/AnimationEffectReadOnly.h
+++ b/dom/animation/AnimationEffectReadOnly.h
@@ -7,38 +7,65 @@
 #ifndef mozilla_dom_AnimationEffectReadOnly_h
 #define mozilla_dom_AnimationEffectReadOnly_h
 
 #include "mozilla/dom/BindingDeclarations.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsWrapperCache.h"
 
 namespace mozilla {
+
+struct ElementPropertyTransition;
+
 namespace dom {
 
+class Animation;
 class AnimationEffectTimingReadOnly;
+class KeyframeEffectReadOnly;
 struct ComputedTimingProperties;
 
 class AnimationEffectReadOnly : public nsISupports,
                                 public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationEffectReadOnly)
 
   explicit AnimationEffectReadOnly(nsIDocument* aDocument)
     : mDocument(aDocument)
   {
   }
 
+  virtual KeyframeEffectReadOnly* AsKeyframeEffect() { return nullptr; }
+
+  virtual ElementPropertyTransition* AsTransition() { return nullptr; }
+  virtual const ElementPropertyTransition* AsTransition() const
+  {
+    return nullptr;
+  }
+
   nsISupports* GetParentObject() const { return mDocument; }
 
+  virtual bool IsInPlay() const = 0;
+  virtual bool IsCurrent() const = 0;
+  virtual bool IsInEffect() const = 0;
+
   virtual already_AddRefed<AnimationEffectTimingReadOnly> Timing() const = 0;
+  virtual const TimingParams& SpecifiedTiming() const = 0;
+  virtual void SetSpecifiedTiming(const TimingParams& aTiming) = 0;
+  virtual void NotifyAnimationTimingUpdated() = 0;
 
-  virtual void GetComputedTimingAsDict(ComputedTimingProperties& aRetVal) const = 0;
+  // Shortcut that gets the computed timing using the current local time as
+  // calculated from the timeline time.
+  virtual ComputedTiming GetComputedTiming(
+    const TimingParams* aTiming = nullptr) const = 0;
+  virtual void GetComputedTimingAsDict(
+    ComputedTimingProperties& aRetVal) const = 0;
+
+  virtual void SetAnimation(Animation* aAnimation) = 0;
 
 protected:
   virtual ~AnimationEffectReadOnly() = default;
 
 protected:
   RefPtr<nsIDocument> mDocument;
 };
 
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -200,21 +200,17 @@ public:
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(KeyframeEffectReadOnly,
                                                         AnimationEffectReadOnly)
 
   virtual JSObject* WrapObject(JSContext* aCx,
                                JS::Handle<JSObject*> aGivenProto) override;
 
-  virtual ElementPropertyTransition* AsTransition() { return nullptr; }
-  virtual const ElementPropertyTransition* AsTransition() const
-  {
-    return nullptr;
-  }
+  KeyframeEffectReadOnly* AsKeyframeEffect() override { return this; }
 
   // KeyframeEffectReadOnly interface
   static already_AddRefed<KeyframeEffectReadOnly>
   Constructor(const GlobalObject& aGlobal,
               const Nullable<ElementOrCSSPseudoElement>& aTarget,
               JS::Handle<JSObject*> aKeyframes,
               const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
               ErrorResult& aRv);
@@ -238,22 +234,22 @@ public:
   CompositeOperation Composite() const;
   void GetSpacing(nsString& aRetVal) const
   {
     mEffectOptions.GetSpacingAsString(aRetVal);
   }
 
   already_AddRefed<AnimationEffectTimingReadOnly> Timing() const override;
 
-  const TimingParams& SpecifiedTiming() const
+  const TimingParams& SpecifiedTiming() const override
   {
     return mTiming->AsTimingParams();
   }
-  void SetSpecifiedTiming(const TimingParams& aTiming);
-  void NotifyAnimationTimingUpdated();
+  void SetSpecifiedTiming(const TimingParams& aTiming) override;
+  void NotifyAnimationTimingUpdated() override;
 
   Nullable<TimeDuration> GetLocalTime() const;
 
   // This function takes as input the timing parameters of an animation and
   // returns the computed timing at the specified local time.
   //
   // The local time may be null in which case only static parameters such as the
   // active duration are calculated. All other members of the returned object
@@ -262,44 +258,45 @@ public:
   // This function returns a null mProgress member of the return value
   // if the animation should not be run
   // (because it is not currently active and is not filling at this time).
   static ComputedTiming
   GetComputedTimingAt(const Nullable<TimeDuration>& aLocalTime,
                       const TimingParams& aTiming,
                       double aPlaybackRate);
 
-  // Shortcut for that gets the computed timing using the current local time as
-  // calculated from the timeline time.
   ComputedTiming
-  GetComputedTiming(const TimingParams* aTiming = nullptr) const;
+  GetComputedTiming(const TimingParams* aTiming = nullptr) const override;
 
   void
   GetComputedTimingAsDict(ComputedTimingProperties& aRetVal) const override;
 
-  bool IsInPlay() const;
-  bool IsCurrent() const;
-  bool IsInEffect() const;
+  bool IsInPlay() const override;
+  bool IsCurrent() const override;
+  bool IsInEffect() const override;
 
-  void SetAnimation(Animation* aAnimation);
+  void SetAnimation(Animation* aAnimation) override;
   Animation* GetAnimation() const { return mAnimation; }
 
   void SetKeyframes(JSContext* aContext, JS::Handle<JSObject*> aKeyframes,
                     ErrorResult& aRv);
   void SetKeyframes(nsTArray<Keyframe>&& aKeyframes,
                     nsStyleContext* aStyleContext);
   const AnimationProperty*
   GetAnimationOfProperty(nsCSSPropertyID aProperty) const;
-  bool HasAnimationOfProperty(nsCSSPropertyID aProperty) const {
+  bool HasAnimationOfProperty(nsCSSPropertyID aProperty) const
+  {
     return GetAnimationOfProperty(aProperty) != nullptr;
   }
-  const InfallibleTArray<AnimationProperty>& Properties() const {
+  const InfallibleTArray<AnimationProperty>& Properties() const
+  {
     return mProperties;
   }
-  InfallibleTArray<AnimationProperty>& Properties() {
+  InfallibleTArray<AnimationProperty>& Properties()
+  {
     return mProperties;
   }
 
   // Update |mProperties| by recalculating from |mKeyframes| using
   // |aStyleContext| to resolve specified values.
   void UpdateProperties(nsStyleContext* aStyleContext);
 
   // Updates |aStyleRule| with the animation values produced by this
--- a/dom/base/nsDOMMutationObserver.cpp
+++ b/dom/base/nsDOMMutationObserver.cpp
@@ -385,22 +385,28 @@ void nsMutationReceiver::NodeWillBeDestr
   NS_ASSERTION(!mParent, "Shouldn't have mParent here!");
   Disconnect(true);
 }
 
 void
 nsAnimationReceiver::RecordAnimationMutation(Animation* aAnimation,
                                              AnimationMutation aMutationType)
 {
-  mozilla::dom::KeyframeEffectReadOnly* effect = aAnimation->GetEffect();
+  mozilla::dom::AnimationEffectReadOnly* effect = aAnimation->GetEffect();
   if (!effect) {
     return;
   }
 
-  Maybe<NonOwningAnimationTarget> animationTarget = effect->GetTarget();
+  mozilla::dom::KeyframeEffectReadOnly* keyframeEffect =
+    effect->AsKeyframeEffect();
+  if (!keyframeEffect) {
+    return;
+  }
+
+  Maybe<NonOwningAnimationTarget> animationTarget = keyframeEffect->GetTarget();
   if (!animationTarget) {
     return;
   }
 
   Element* elem = animationTarget->mElement;
   if (!Animations() || !(Subtree() || elem == Target()) ||
       elem->ChromeOnlyAccess()) {
     return;
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -226,18 +226,21 @@ nsNodeUtils::ContentRemoved(nsINode* aCo
   IMPL_MUTATION_NOTIFICATION(ContentRemoved, aContainer,
                              (document, container, aChild, aIndexInContainer,
                               aPreviousSibling));
 }
 
 Maybe<NonOwningAnimationTarget>
 nsNodeUtils::GetTargetForAnimation(const Animation* aAnimation)
 {
-  KeyframeEffectReadOnly* effect = aAnimation->GetEffect();
-  return effect ? effect->GetTarget() : Nothing();
+  AnimationEffectReadOnly* effect = aAnimation->GetEffect();
+  if (!effect || !effect->AsKeyframeEffect()) {
+    return Nothing();
+  }
+  return effect->AsKeyframeEffect()->GetTarget();
 }
 
 void
 nsNodeUtils::AnimationMutated(Animation* aAnimation,
                               AnimationMutationType aMutatedType)
 {
   Maybe<NonOwningAnimationTarget> target = GetTargetForAnimation(aAnimation);
   if (!target) {
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -469,20 +469,23 @@ AddAnimationsForProperty(nsIFrame* aFram
              "inconsistent property flags");
 
   // Add from first to last (since last overrides)
   for (size_t animIdx = 0; animIdx < aAnimations.Length(); animIdx++) {
     dom::Animation* anim = aAnimations[animIdx];
     if (!anim->IsPlaying()) {
       continue;
     }
-    dom::KeyframeEffectReadOnly* effect = anim->GetEffect();
-    MOZ_ASSERT(effect, "A playing animation should have an effect");
+
+    dom::KeyframeEffectReadOnly* keyframeEffect =
+      anim->GetEffect() ? anim->GetEffect()->AsKeyframeEffect() : nullptr;
+    MOZ_ASSERT(keyframeEffect,
+               "A playing animation should have a keyframe effect");
     const AnimationProperty* property =
-      effect->GetAnimationOfProperty(aProperty);
+      keyframeEffect->GetAnimationOfProperty(aProperty);
     if (!property) {
       continue;
     }
 
     // Note that if mWinsInCascade on property was  false,
     // GetAnimationOfProperty returns null instead.
     // This is what we want, since if we have an animation or transition
     // that isn't actually winning in the CSS cascade, we don't want to
@@ -506,17 +509,17 @@ AddAnimationsForProperty(nsIFrame* aFram
     // driver is advanced it will trigger any pending animations.
     if (anim->PlayState() == AnimationPlayState::Pending &&
         (!anim->GetTimeline() ||
          !anim->GetTimeline()->TracksWallclockTime())) {
       continue;
     }
 
     AddAnimationForProperty(aFrame, *property, anim, aLayer, aData, aPending);
-    effect->SetIsRunningOnCompositor(aProperty, true);
+    keyframeEffect->SetIsRunningOnCompositor(aProperty, true);
   }
 }
 
 static bool
 GenerateAndPushTextMask(nsIFrame* aFrame, nsRenderingContext* aContext,
                         const nsRect& aFillRect, nsDisplayListBuilder* aBuilder)
 {
   if (aBuilder->IsForGenerateGlyphMask() ||
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -543,17 +543,19 @@ GetMinAndMaxScaleForAnimationProperty(co
 {
   for (dom::Animation* anim : aAnimations) {
     // This method is only expected to be passed animations that are running on
     // the compositor and we only pass playing animations to the compositor,
     // which are, by definition, "relevant" animations (animations that are
     // not yet finished or which are filling forwards).
     MOZ_ASSERT(anim->IsRelevant());
 
-    dom::KeyframeEffectReadOnly* effect = anim->GetEffect();
+    dom::KeyframeEffectReadOnly* effect =
+      anim->GetEffect() ? anim->GetEffect()->AsKeyframeEffect() : nullptr;
+    MOZ_ASSERT(effect, "A playing animation should have a keyframe effect");
     for (size_t propIdx = effect->Properties().Length(); propIdx-- != 0; ) {
       AnimationProperty& prop = effect->Properties()[propIdx];
       if (prop.mProperty == eCSSProperty_transform) {
         for (uint32_t segIdx = prop.mSegments.Length(); segIdx-- != 0; ) {
           AnimationPropertySegment& segment = prop.mSegments[segIdx];
           gfxSize from = segment.mFromValue.GetScaleValue(aFrame);
           aMaxScale.width = std::max<float>(aMaxScale.width, from.width);
           aMaxScale.height = std::max<float>(aMaxScale.height, from.height);
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -331,21 +331,24 @@ UpdateOldAnimationPropertiesWithNew(
     bool aNewIsStylePaused,
     nsStyleContext* aStyleContext)
 {
   bool animationChanged = false;
 
   // Update the old from the new so we can keep the original object
   // identity (and any expando properties attached to it).
   if (aOld.GetEffect()) {
-    KeyframeEffectReadOnly* oldEffect = aOld.GetEffect();
-    animationChanged =
-      oldEffect->SpecifiedTiming() != aNewTiming;
+    AnimationEffectReadOnly* oldEffect = aOld.GetEffect();
+    animationChanged = oldEffect->SpecifiedTiming() != aNewTiming;
     oldEffect->SetSpecifiedTiming(aNewTiming);
-    oldEffect->SetKeyframes(Move(aNewKeyframes), aStyleContext);
+
+    KeyframeEffectReadOnly* oldKeyframeEffect = oldEffect->AsKeyframeEffect();
+    if (oldKeyframeEffect) {
+      oldKeyframeEffect->SetKeyframes(Move(aNewKeyframes), aStyleContext);
+    }
   }
 
   // Handle changes in play state. If the animation is idle, however,
   // changes to animation-play-state should *not* restart it.
   if (aOld.PlayState() != AnimationPlayState::Idle) {
     // CSSAnimation takes care of override behavior so that,
     // for example, if the author has called pause(), that will
     // override the animation-play-state.
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -263,17 +263,17 @@ CSSTransition::GetCurrentTimeAt(const Do
     result.SetValue((timelineTime.Value() - aStartTime)
                       .MultDouble(aPlaybackRate));
   }
 
   return result;
 }
 
 void
-CSSTransition::SetEffect(KeyframeEffectReadOnly* aEffect)
+CSSTransition::SetEffect(AnimationEffectReadOnly* aEffect)
 {
   Animation::SetEffect(aEffect);
 
   // Initialize transition property.
   ElementPropertyTransition* pt = aEffect ? aEffect->AsTransition() : nullptr;
   if (eCSSProperty_UNKNOWN == mTransitionProperty && pt) {
     mTransitionProperty = pt->TransitionProperty();
     mTransitionToValue = pt->ToValue();
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -206,17 +206,17 @@ public:
   // because the animation on the compositor may be running ahead while
   // main-thread is busy.
   static Nullable<TimeDuration> GetCurrentTimeAt(
       const DocumentTimeline& aTimeline,
       const TimeStamp& aBaseTime,
       const TimeDuration& aStartTime,
       double aPlaybackRate);
 
-  void SetEffect(KeyframeEffectReadOnly* aEffect) override;
+  void SetEffect(AnimationEffectReadOnly* aEffect) override;
 
 protected:
   virtual ~CSSTransition()
   {
     MOZ_ASSERT(!mOwningElement.IsSet(), "Owning element should be cleared "
                                         "before a CSS transition is destroyed");
   }