Bug 1456394 - Add AnimationEffect.updateTiming(); r?hiro,bz
https://drafts.csswg.org/web-animations-1/#dom-animationeffect-updatetiming
MozReview-Commit-ID: ISgksSpH8yH
--- 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
-