Bug 1456394 - Add AnimationEffect.updateTiming(); r?hiro,bz draft
authorBrian Birtles <birtles@gmail.com>
Mon, 07 May 2018 12:37:11 +0900
changeset 794000 2dc4aecf8f8c476ea8b4a6e3d4e6b68a2005df7f
parent 793999 6589f368dd17d05d17e7489fd338dda30a85a3ca
child 794001 9efc55b04eefa52a1d1cd75afc167eae9eb6ed4d
push id109561
push userbmo:bbirtles@mozilla.com
push dateFri, 11 May 2018 06:43:46 +0000
reviewershiro, bz
bugs1456394
milestone62.0a1
Bug 1456394 - Add AnimationEffect.updateTiming(); r?hiro,bz https://drafts.csswg.org/web-animations-1/#dom-animationeffect-updatetiming MozReview-Commit-ID: ISgksSpH8yH
dom/animation/AnimationEffect.cpp
dom/animation/AnimationEffect.h
dom/animation/TimingParams.cpp
dom/animation/TimingParams.h
dom/webidl/AnimationEffect.webidl
testing/web-platform/meta/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html.ini
testing/web-platform/meta/web-animations/interfaces/Animatable/getAnimations.html.ini
testing/web-platform/meta/web-animations/interfaces/Animation/cancel.html.ini
testing/web-platform/meta/web-animations/interfaces/Animation/finished.html.ini
testing/web-platform/meta/web-animations/interfaces/AnimationEffect/updateTiming.html.ini
testing/web-platform/meta/web-animations/timing-model/animation-effects/phases-and-states.html.ini
testing/web-platform/meta/web-animations/timing-model/animations/updating-the-finished-state.html.ini
--- a/dom/animation/AnimationEffect.cpp
+++ b/dom/animation/AnimationEffect.cpp
@@ -77,17 +77,27 @@ AnimationEffect::Timing()
 void
 AnimationEffect::SetSpecifiedTiming(const TimingParams& aTiming)
 {
   if (mTiming->AsTimingParams() == aTiming) {
     return;
   }
   mTiming->SetTimingParams(aTiming);
   if (mAnimation) {
+    Maybe<nsAutoAnimationMutationBatch> mb;
+    if (AsKeyframeEffect() && AsKeyframeEffect()->GetTarget()) {
+      mb.emplace(AsKeyframeEffect()->GetTarget()->mElement->OwnerDoc());
+    }
+
     mAnimation->NotifyEffectTimingUpdated();
+
+    if (mAnimation->IsRelevant()) {
+      nsNodeUtils::AnimationChanged(mAnimation);
+    }
+
     if (AsKeyframeEffect()) {
       AsKeyframeEffect()->RequestRestyle(EffectCompositor::RestyleType::Layer);
     }
   }
   // For keyframe effects, NotifyEffectTimingUpdated above will eventually cause
   // KeyframeEffect::NotifyAnimationTimingUpdated to be called so it can
   // update its registration with the target element as necessary.
 }
@@ -324,16 +334,29 @@ AnimationEffect::GetComputedTimingAsDict
     // (uint64_t) computedTiming.mCurrentIteration to UINT64_MAX
     double iteration = computedTiming.mCurrentIteration == UINT64_MAX
                        ? PositiveInfinity<double>()
                        : static_cast<double>(computedTiming.mCurrentIteration);
     aRetVal.mCurrentIteration.SetValue(iteration);
   }
 }
 
+void
+AnimationEffect::UpdateTiming(const OptionalEffectTiming& aTiming,
+                              ErrorResult& aRv)
+{
+  TimingParams timing = TimingParams::MergeOptionalEffectTiming(
+    mTiming->AsTimingParams(), aTiming, mDocument, aRv);
+  if (aRv.Failed()) {
+    return;
+  }
+
+  SetSpecifiedTiming(timing);
+}
+
 AnimationEffect::~AnimationEffect()
 {
   // mTiming is cycle collected, so we have to do null check first even though
   // mTiming shouldn't be null during the lifetime of KeyframeEffect.
   if (mTiming) {
     mTiming->Unlink();
   }
 }
--- a/dom/animation/AnimationEffect.h
+++ b/dom/animation/AnimationEffect.h
@@ -51,17 +51,20 @@ public:
 
   bool IsCurrent() const;
   bool IsInEffect() const;
   bool HasFiniteActiveDuration() const
   {
     return SpecifiedTiming().ActiveDuration() != TimeDuration::Forever();
   }
 
+  // AnimationEffect interface
   void GetTiming(EffectTiming& aRetVal) const;
+  void GetComputedTimingAsDict(ComputedEffectTiming& aRetVal) const;
+  void UpdateTiming(const OptionalEffectTiming& aTiming, ErrorResult& aRv);
 
   already_AddRefed<AnimationEffectTimingReadOnly> Timing();
   const TimingParams& SpecifiedTiming() const
   {
     return mTiming->AsTimingParams();
   }
   void SetSpecifiedTiming(const TimingParams& aTiming);
 
@@ -77,17 +80,16 @@ public:
   // (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 that gets the computed timing using the current local time as
   // calculated from the timeline time.
   ComputedTiming GetComputedTiming(const TimingParams* aTiming = nullptr) const;
-  void GetComputedTimingAsDict(ComputedEffectTiming& aRetVal) const;
 
   virtual void SetAnimation(Animation* aAnimation) = 0;
   Animation* GetAnimation() const { return mAnimation; };
 
   /**
    * Returns true if this effect animates one of the properties we consider
    * geometric properties, e.g. properties such as 'width' or 'margin-left'
    * that we try to synchronize with transform animations, on a valid target
--- a/dom/animation/TimingParams.cpp
+++ b/dom/animation/TimingParams.cpp
@@ -116,16 +116,96 @@ TimingParams::FromEffectTiming(const dom
   result.mFill = aEffectTiming.mFill;
   result.mFunction = easing;
 
   result.Update();
 
   return result;
 }
 
+/* static */ TimingParams
+TimingParams::MergeOptionalEffectTiming(
+  const TimingParams& aSource,
+  const dom::OptionalEffectTiming& aEffectTiming,
+  nsIDocument* aDocument,
+  ErrorResult& aRv)
+{
+  MOZ_ASSERT(!aRv.Failed(), "Initially return value should be ok");
+
+  TimingParams result = aSource;
+
+  // Check for errors first
+
+  Maybe<StickyTimeDuration> duration;
+  if (aEffectTiming.mDuration.WasPassed()) {
+    duration =
+      TimingParams::ParseDuration(aEffectTiming.mDuration.Value(), aRv);
+    if (aRv.Failed()) {
+      return result;
+    }
+  }
+
+  if (aEffectTiming.mIterationStart.WasPassed()) {
+    TimingParams::ValidateIterationStart(aEffectTiming.mIterationStart.Value(),
+                                         aRv);
+    if (aRv.Failed()) {
+      return result;
+    }
+  }
+
+  if (aEffectTiming.mIterations.WasPassed()) {
+    TimingParams::ValidateIterations(aEffectTiming.mIterations.Value(), aRv);
+    if (aRv.Failed()) {
+      return result;
+    }
+  }
+
+  Maybe<ComputedTimingFunction> easing;
+  if (aEffectTiming.mEasing.WasPassed()) {
+    easing =
+      TimingParams::ParseEasing(aEffectTiming.mEasing.Value(), aDocument, aRv);
+    if (aRv.Failed()) {
+      return result;
+    }
+  }
+
+  // Assign values
+
+  if (aEffectTiming.mDuration.WasPassed()) {
+    result.mDuration = duration;
+  }
+  if (aEffectTiming.mDelay.WasPassed()) {
+    result.mDelay =
+      TimeDuration::FromMilliseconds(aEffectTiming.mDelay.Value());
+  }
+  if (aEffectTiming.mEndDelay.WasPassed()) {
+    result.mEndDelay =
+      TimeDuration::FromMilliseconds(aEffectTiming.mEndDelay.Value());
+  }
+  if (aEffectTiming.mIterations.WasPassed()) {
+    result.mIterations = aEffectTiming.mIterations.Value();
+  }
+  if (aEffectTiming.mIterationStart.WasPassed()) {
+    result.mIterationStart = aEffectTiming.mIterationStart.Value();
+  }
+  if (aEffectTiming.mDirection.WasPassed()) {
+    result.mDirection = aEffectTiming.mDirection.Value();
+  }
+  if (aEffectTiming.mFill.WasPassed()) {
+    result.mFill = aEffectTiming.mFill.Value();
+  }
+  if (aEffectTiming.mEasing.WasPassed()) {
+    result.mFunction = easing;
+  }
+
+  result.Update();
+
+  return result;
+}
+
 /* static */ Maybe<ComputedTimingFunction>
 TimingParams::ParseEasing(const nsAString& aEasing,
                           nsIDocument* aDocument,
                           ErrorResult& aRv)
 {
   MOZ_ASSERT(aDocument);
 
   nsTimingFunction timingFunction;
--- a/dom/animation/TimingParams.h
+++ b/dom/animation/TimingParams.h
@@ -74,16 +74,27 @@ struct TimingParams
     nsIDocument* aDocument, ErrorResult& aRv);
   static TimingParams FromOptionsUnion(
     const dom::UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
     nsIDocument* aDocument, ErrorResult& aRv);
   static TimingParams FromEffectTiming(
     const dom::EffectTiming& aEffectTiming,
     nsIDocument* aDocument,
     ErrorResult& aRv);
+  // Returns a copy of |aSource| where each timing property in |aSource| that
+  // is also specified in |aEffectTiming| is replaced with the value from
+  // |aEffectTiming|.
+  //
+  // If any of the values in |aEffectTiming| are invalid, |aRv.Failed()| will be
+  // true and an unmodified copy of |aSource| will be returned.
+  static TimingParams MergeOptionalEffectTiming(
+    const TimingParams& aSource,
+    const dom::OptionalEffectTiming& aEffectTiming,
+    nsIDocument* aDocument,
+    ErrorResult& aRv);
 
   // Range-checks and validates an UnrestrictedDoubleOrString or
   // OwningUnrestrictedDoubleOrString object and converts to a
   // StickyTimeDuration value or Nothing() if aDuration is "auto".
   // Caller must check aRv.Failed().
   template <class DoubleOrString>
   static Maybe<StickyTimeDuration> ParseDuration(DoubleOrString& aDuration,
                                                  ErrorResult& aRv)
--- a/dom/webidl/AnimationEffect.webidl
+++ b/dom/webidl/AnimationEffect.webidl
@@ -31,24 +31,37 @@ dictionary EffectTiming {
   FillMode                            fill = "auto";
   double                              iterationStart = 0.0;
   unrestricted double                 iterations = 1.0;
   (unrestricted double or DOMString)  duration = "auto";
   PlaybackDirection                   direction = "normal";
   DOMString                           easing = "linear";
 };
 
+dictionary OptionalEffectTiming {
+  double                              delay;
+  double                              endDelay;
+  FillMode                            fill;
+  double                              iterationStart;
+  unrestricted double                 iterations;
+  (unrestricted double or DOMString)  duration;
+  PlaybackDirection                   direction;
+  DOMString                           easing;
+};
+
 dictionary ComputedEffectTiming : EffectTiming {
   unrestricted double   endTime = 0.0;
   unrestricted double   activeDuration = 0.0;
   double?               localTime = null;
   double?               progress = null;
   unrestricted double?  currentIteration = null;
 };
 
 [Func="nsDocument::IsWebAnimationsEnabled"]
 interface AnimationEffect {
   [Cached, Constant]
   readonly attribute AnimationEffectTimingReadOnly timing;
   EffectTiming getTiming();
   [BinaryName="getComputedTimingAsDict"]
   ComputedEffectTiming getComputedTiming();
+  [Throws]
+  void updateTiming(optional OptionalEffectTiming timing);
 };
deleted file mode 100644
--- a/testing/web-platform/meta/web-animations/animation-model/keyframe-effects/effect-value-iteration-composite-operation.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[effect-value-iteration-composite-operation.html]
-  [duration changes with an iteration composition operation of accumulate]
-    expected: FAIL
-
--- a/testing/web-platform/meta/web-animations/interfaces/Animatable/getAnimations.html.ini
+++ b/testing/web-platform/meta/web-animations/interfaces/Animatable/getAnimations.html.ini
@@ -1,10 +1,4 @@
 [getAnimations.html]
-  [Returns animations based on dynamic changes to individual animations' duration]
-    expected: FAIL
-
   [Returns animations based on dynamic changes to individual animations' end delay]
     expected: FAIL
 
-  [Returns animations based on dynamic changes to individual animations' iteration count]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/web-animations/interfaces/Animation/cancel.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[cancel.html]
-  [After cancelling an animation, it can still be seeked]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/web-animations/interfaces/Animation/finished.html.ini
+++ /dev/null
@@ -1,4 +0,0 @@
-[finished.html]
-  [Test finished promise changes for animation duration changes]
-    expected: FAIL
-
--- a/testing/web-platform/meta/web-animations/interfaces/AnimationEffect/updateTiming.html.ini
+++ b/testing/web-platform/meta/web-animations/interfaces/AnimationEffect/updateTiming.html.ini
@@ -1,160 +1,7 @@
 [updateTiming.html]
-  [Allows setting the delay to a positive number]
-    expected: FAIL
-
-  [Allows setting the delay to a negative number]
-    expected: FAIL
-
-  [Allows setting the delay of an animation in progress: positive delay that causes the animation to be no longer in-effect]
-    expected: FAIL
-
-  [Allows setting the delay of an animation in progress: negative delay that seeks into the active interval]
-    expected: FAIL
-
-  [Allows setting the delay of an animation in progress: large negative delay that causes the animation to be finished]
-    expected: FAIL
-
   [Allows setting the endDelay to a positive number]
     expected: FAIL
 
   [Allows setting the endDelay to a negative number]
     expected: FAIL
 
-  [Allows setting the fill to 'none']
-    expected: FAIL
-
-  [Allows setting the fill to 'forwards']
-    expected: FAIL
-
-  [Allows setting the fill to 'backwards']
-    expected: FAIL
-
-  [Allows setting the fill to 'both']
-    expected: FAIL
-
-  [Allows setting the iterationStart of an animation in progress: backwards-filling]
-    expected: FAIL
-
-  [Allows setting the iterationStart of an animation in progress: active phase]
-    expected: FAIL
-
-  [Allows setting the iterationStart of an animation in progress: forwards-filling]
-    expected: FAIL
-
-  [Allows setting iterations to a double value]
-    expected: FAIL
-
-  [Allows setting iterations to infinity]
-    expected: FAIL
-
-  [Allows setting the iterations of an animation in progress]
-    expected: FAIL
-
-  [Allows setting the duration to 123.45]
-    expected: FAIL
-
-  [Allows setting the duration to auto]
-    expected: FAIL
-
-  [Allows setting the duration to Infinity]
-    expected: FAIL
-
-  [Allows setting the duration of an animation in progress]
-    expected: FAIL
-
-  [Allows setting the duration of an animation in progress such that the the start and current time do not change]
-    expected: FAIL
-
-  [Allows setting the direction to each of the possible keywords]
-    expected: FAIL
-
-  [Allows setting the direction of an animation in progress from 'normal' to 'reverse']
-    expected: FAIL
-
-  [Allows setting the direction of an animation in progress from 'normal' to 'reverse' while at start of active interval]
-    expected: FAIL
-
-  [Allows setting the direction of an animation in progress from 'normal' to 'reverse' while filling backwards]
-    expected: FAIL
-
-  [Allows setting the direction of an animation in progress from 'normal' to 'alternate']
-    expected: FAIL
-
-  [Allows setting the direction of an animation in progress from 'alternate' to 'alternate-reverse']
-    expected: FAIL
-
-  [Allows setting the easing to a step-start function]
-    expected: FAIL
-
-  [Allows setting the easing to a steps(1, start) function]
-    expected: FAIL
-
-  [Allows setting the easing to a steps(2, start) function]
-    expected: FAIL
-
-  [Allows setting the easing to a step-end function]
-    expected: FAIL
-
-  [Allows setting the easing to a steps(1) function]
-    expected: FAIL
-
-  [Allows setting the easing to a steps(1, end) function]
-    expected: FAIL
-
-  [Allows setting the easing to a steps(2, end) function]
-    expected: FAIL
-
-  [Allows setting the easing to a frames function]
-    expected: FAIL
-
-  [Allows setting the easing to a linear function]
-    expected: FAIL
-
-  [Allows setting the easing to a ease function]
-    expected: FAIL
-
-  [Allows setting the easing to a ease-in function]
-    expected: FAIL
-
-  [Allows setting the easing to a ease-in-out function]
-    expected: FAIL
-
-  [Allows setting the easing to a ease-out function]
-    expected: FAIL
-
-  [Allows setting the easing to a easing function which produces values greater than 1]
-    expected: FAIL
-
-  [Allows setting the easing to a easing function which produces values less than 1]
-    expected: FAIL
-
-  [Updates the specified value when setting the easing to 'ease']
-    expected: FAIL
-
-  [Updates the specified value when setting the easing to 'linear']
-    expected: FAIL
-
-  [Updates the specified value when setting the easing to 'ease-in']
-    expected: FAIL
-
-  [Updates the specified value when setting the easing to 'ease-out']
-    expected: FAIL
-
-  [Updates the specified value when setting the easing to 'ease-in-out']
-    expected: FAIL
-
-  [Updates the specified value when setting the easing to 'cubic-bezier(0.1, 5, 0.23, 0)']
-    expected: FAIL
-
-  [Updates the specified value when setting the easing to 'steps(3, start)']
-    expected: FAIL
-
-  [Updates the specified value when setting the easing to 'steps(3)']
-    expected: FAIL
-
-  [Updates the specified value when setting the easing to 'frames(3)']
-    expected: FAIL
-
-  [Allows setting the easing of an animation in progress]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/web-animations/timing-model/animation-effects/phases-and-states.html.ini
+++ /dev/null
@@ -1,34 +0,0 @@
-[phases-and-states.html]
-  [Phase calculation for a simple animation effect]
-    expected: FAIL
-
-  [Phase calculation for an animation effect with a positive start delay]
-    expected: FAIL
-
-  [Phase calculation for an animation effect with a negative start delay]
-    expected: FAIL
-
-  [Phase calculation for an animation effect with a positive end delay]
-    expected: FAIL
-
-  [Phase calculation for an animation effect with a negative end delay lesser in magnitude than the active duration]
-    expected: FAIL
-
-  [Phase calculation for an animation effect with a negative end delay equal in magnitude to the active duration]
-    expected: FAIL
-
-  [Phase calculation for an animation effect with a negative end delay greater in magnitude than the active duration]
-    expected: FAIL
-
-  [Phase calculation for an animation effect with a positive start delay and a negative end delay lesser in magnitude than the active duration]
-    expected: FAIL
-
-  [Phase calculation for an animation effect with a negative start delay and a negative end delay equal in magnitude to the active duration]
-    expected: FAIL
-
-  [Phase calculation for an animation effect with a negative start delay and a negative end delay equal greater in magnitude than the active duration]
-    expected: FAIL
-
-  [Phase calculation for a simple animation effect with negative playback rate]
-    expected: FAIL
-
deleted file mode 100644
--- a/testing/web-platform/meta/web-animations/timing-model/animations/updating-the-finished-state.html.ini
+++ /dev/null
@@ -1,13 +0,0 @@
-[updating-the-finished-state.html]
-  [Updating the finished state when playing before end]
-    expected: FAIL
-
-  [Updating the finished state when current time is unresolved]
-    expected: FAIL
-
-  [Updating the finished state when there is a pending task]
-    expected: FAIL
-
-  [Updating the finished state when start time is unresolved and did seek = false]
-    expected: FAIL
-