Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (260670 => 260671)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2020-04-24 21:42:50 UTC (rev 260671)
@@ -1,3 +1,20 @@
+2020-04-24 Antoine Quint <grao...@apple.com>
+
+ [Web Animations] Ensure calling Web Animations APIs override future CSS Animations style properties
+ https://bugs.webkit.org/show_bug.cgi?id=210988
+
+ Reviewed by Dean Jackson.
+
+ Mark all WPT tests related to Web Animations APIs overrides for CSS Animations as PASS, save for one
+ failing assertion which is caused by AnimationTimeline::updateCSSAnimations() not updating the animation
+ when the underlying @keyframes rule changed. This is due to Animation::animationsMatch() not checking on
+ the actual keyframes, tracked by webkit.org/b/210989.
+
+ * web-platform-tests/css/css-animations/AnimationEffect-updateTiming.tentative-expected.txt:
+ * web-platform-tests/css/css-animations/CSSAnimation-effect.tentative-expected.txt:
+ * web-platform-tests/css/css-animations/CSSAnimation-pausing.tentative-expected.txt:
+ * web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative-expected.txt:
+
2020-04-24 Alexey Shvayka <shvaikal...@gmail.com>
Re-sync wpt/WebIDL/ecmascript-binding and wpt/custom-elements/htmlconstructor from upstream
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/AnimationEffect-updateTiming.tentative-expected.txt (260670 => 260671)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/AnimationEffect-updateTiming.tentative-expected.txt 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/AnimationEffect-updateTiming.tentative-expected.txt 2020-04-24 21:42:50 UTC (rev 260671)
@@ -1,7 +1,7 @@
-FAIL AnimationEffect.updateTiming({ duration }) causes changes to the animation-duration to be ignored assert_equals: Delay should be the value set by style expected 6000 but got 0
-FAIL AnimationEffect.updateTiming({ iterations, direction }) causes changes to the animation-iteration-count and animation-direction to be ignored assert_equals: Delay should be the value set by style expected 6000 but got 0
-FAIL AnimationEffect.updateTiming({ delay, fill }) causes changes to the animation-delay and animation-fill-mode to be ignored assert_equals: Iterations should be the value set by style expected 6 but got 1
-FAIL AnimationEffect.updateTiming() does override to changes from animation-* properties if there is an error assert_equals: Duration should be the value set by style expected 4000 but got 100000
+PASS AnimationEffect.updateTiming({ duration }) causes changes to the animation-duration to be ignored
+PASS AnimationEffect.updateTiming({ iterations, direction }) causes changes to the animation-iteration-count and animation-direction to be ignored
+PASS AnimationEffect.updateTiming({ delay, fill }) causes changes to the animation-delay and animation-fill-mode to be ignored
+PASS AnimationEffect.updateTiming() does override to changes from animation-* properties if there is an error
PASS AnimationEffect properties that do not map to animation-* properties should not be changed when animation-* style is updated
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/CSSAnimation-effect.tentative-expected.txt (260670 => 260671)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/CSSAnimation-effect.tentative-expected.txt 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/CSSAnimation-effect.tentative-expected.txt 2020-04-24 21:42:50 UTC (rev 260671)
@@ -5,5 +5,5 @@
PASS A play-pending animation's effect whose effect is replaced still exits the pending state
PASS CSS animation events are dispatched at the original element even after setting an effect with a different target element
PASS After replacing a finished animation's effect with a longer one it fires an animationstart event
-FAIL Replacing the effect of a CSSAnimation causes subsequent changes to corresponding animation-* properties to be ignored undefined is not an object (evaluating 'animation.effect.getKeyframes()[0].left')
+PASS Replacing the effect of a CSSAnimation causes subsequent changes to corresponding animation-* properties to be ignored
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/CSSAnimation-pausing.tentative-expected.txt (260670 => 260671)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/CSSAnimation-pausing.tentative-expected.txt 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/CSSAnimation-pausing.tentative-expected.txt 2020-04-24 21:42:50 UTC (rev 260671)
@@ -1,11 +1,11 @@
-FAIL play() overrides animation-play-state assert_equals: Should still be running even after flipping the animation-play-state expected "running" but got "paused"
+PASS play() overrides animation-play-state
PASS play() does NOT override the animation-play-state if there was an error
PASS pause() overrides animation-play-state
-FAIL reverse() overrides animation-play-state when it starts playing the animation assert_equals: Should still be running even after flipping the animation-play-state expected "running" but got "paused"
+PASS reverse() overrides animation-play-state when it starts playing the animation
PASS reverse() does NOT override animation-play-state if the animation is already running
-FAIL Setting the startTime to null overrides animation-play-state if the animation is already running assert_equals: Should still be paused even after flipping the animation-play-state expected "paused" but got "running"
-FAIL Setting the startTime to non-null overrides animation-play-state if the animation is paused assert_equals: Should still be running even after flipping the animation-play-state expected "running" but got "paused"
+PASS Setting the startTime to null overrides animation-play-state if the animation is already running
+PASS Setting the startTime to non-null overrides animation-play-state if the animation is paused
PASS Setting the startTime to non-null does NOT override the animation-play-state if the animation is already running
PASS Setting the current time completes a pending pause
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative-expected.txt (260670 => 260671)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative-expected.txt 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/css/css-animations/KeyframeEffect-setKeyframes.tentative-expected.txt 2020-04-24 21:42:50 UTC (rev 260671)
@@ -1,5 +1,5 @@
-FAIL KeyframeEffect.setKeyframes() causes subsequent changes to @keyframes rules to be ignored undefined is not an object (evaluating 'Object.keys(actual)')
-FAIL KeyframeEffect.setKeyframes() causes subsequent changes to animation-timing-function to be ignored undefined is not an object (evaluating 'animation.effect.getKeyframes()[0].easing')
-FAIL KeyframeEffect.setKeyframes() should NOT cause subsequent changes to @keyframes rules to be ignored if it threw undefined is not an object (evaluating 'Object.keys(actual)')
+PASS KeyframeEffect.setKeyframes() causes subsequent changes to @keyframes rules to be ignored
+PASS KeyframeEffect.setKeyframes() causes subsequent changes to animation-timing-function to be ignored
+FAIL KeyframeEffect.setKeyframes() should NOT cause subsequent changes to @keyframes rules to be ignored if it threw assert_equals: value for 'left' on Keyframes reflect the value set via style should match expected "300px" but got "100px"
Modified: trunk/Source/WebCore/ChangeLog (260670 => 260671)
--- trunk/Source/WebCore/ChangeLog 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/ChangeLog 2020-04-24 21:42:50 UTC (rev 260671)
@@ -1,3 +1,74 @@
+2020-04-24 Antoine Quint <grao...@apple.com>
+
+ [Web Animations] Ensure calling Web Animations APIs override future CSS Animations style properties
+ https://bugs.webkit.org/show_bug.cgi?id=210988
+
+ Reviewed by Dean Jackson.
+
+ The CSS Animations Level 2 spec specifies how the Web Animations APIs and the CSS Animations style
+ properties should interact in https://drafts.csswg.org/css-animations-2/#animations. This patch
+ implements the specified behavior and this is reflected by progress on the relevant WPT tests.
+
+ The gist of this change is that once a Web Animations API is called on an animation created using
+ CSS Animations, any changes made to related CSS Animations style properties on the target element
+ will be ignored so that the overrides applied via the Web Animations API remain in effect.
+
+ For instance, calling pause() or play() in a way that changes the playback state of the CSS Animation
+ will mean that future changes to the CSS animation-play-state property are ignored.
+
+ To do this we make more IDL properties and methods use dedicated methods to distinguish between the
+ bindings entry-point and internal usage of the same methods to integrate the behavior only when the
+ API itself is being used.
+
+ * animation/AnimationEffect.cpp:
+ (WebCore::AnimationEffect::getBindingsTiming const): Ensure we flush styles when animation.effect.getTiming()
+ is called.
+ (WebCore::AnimationEffect::getBindingsComputedTiming const): Ensure we flush styles when
+ animation.effect.getComputedTiming() is called.
+ (WebCore::AnimationEffect::bindingsUpdateTiming): Notify the associated CSSAnimation object, if any, when
+ animation.effect.updateTiming() is called such that the CSSAnimation may apply the relevant overrides.
+ * animation/AnimationEffect.h:
+ * animation/AnimationEffect.idl:
+ * animation/CSSAnimation.cpp:
+ (WebCore::CSSAnimation::syncPropertiesWithBackingAnimation): Only apply new values of CSS Animations style
+ properties if there are no overrides for them resulting from calling related Web Animations APIs.
+ (WebCore::CSSAnimation::bindingsPlay): Mark animation-play-state as overridden if play() is called.
+ (WebCore::CSSAnimation::bindingsPause): Mark animation-play-state as overridden if pause() is called.
+ (WebCore::CSSAnimation::setBindingsEffect): Mark all animation style properties, except for animation-name
+ and animation-play-state as overridden if animation.effect is set.
+ (WebCore::CSSAnimation::setBindingsStartTime): Mark animation-play-state as overridden if animation.startTime
+ is set.
+ (WebCore::CSSAnimation::bindingsReverse): Mark animation-play-state as overridden if reverse() is called.
+ (WebCore::CSSAnimation::effectTimingWasUpdatedUsingBindings): Mark each CSS property associated with a key
+ found on the timing object passed to animation.effect.updateTiming() as overridden.
+ (WebCore::CSSAnimation::effectKeyframesWereSetUsingBindings): Mark animation-timing-function as overridden
+ if animation.effect.setKeyframes() is called.
+ * animation/CSSAnimation.h:
+ * animation/DeclarativeAnimation.cpp:
+ (WebCore::DeclarativeAnimation::bindingsStartTime const):
+ (WebCore::DeclarativeAnimation::setBindingsStartTime):
+ (WebCore::DeclarativeAnimation::startTime const): Deleted.
+ (WebCore::DeclarativeAnimation::setStartTime): Deleted.
+ * animation/DeclarativeAnimation.h:
+ * animation/KeyframeEffect.cpp:
+ (WebCore::KeyframeEffect::getBindingsKeyframes): Ensure we flush styles when animation.effect.getKeyframes()
+ is called.
+ (WebCore::KeyframeEffect::getKeyframes): Only use the CSS-originated animation path if we don't have JS-originated
+ keyframes.
+ (WebCore::KeyframeEffect::setBindingsKeyframes): Notify the associated CSSAnimation object, if any, when
+ animation.effect.setKeyframes() is called such that the CSSAnimation may apply the relevant overrides.
+ (WebCore::KeyframeEffect::processKeyframes): Correctly return early if part of the processing yields an exception.
+ * animation/KeyframeEffect.h:
+ * animation/KeyframeEffect.idl:
+ * animation/WebAnimation.cpp:
+ (WebCore::WebAnimation::setBindingsEffect):
+ (WebCore::WebAnimation::setBindingsStartTime):
+ (WebCore::WebAnimation::bindingsReverse):
+ * animation/WebAnimation.h:
+ (WebCore::WebAnimation::bindingsEffect const):
+ (WebCore::WebAnimation::bindingsStartTime const):
+ * animation/WebAnimation.idl:
+
2020-04-24 Chris Dumez <cdu...@apple.com>
ASSERTION FAILED: m_wrapper under HTMLMediaElement::setIsPlayingToWirelessTarget
Modified: trunk/Source/WebCore/animation/AnimationEffect.cpp (260670 => 260671)
--- trunk/Source/WebCore/animation/AnimationEffect.cpp 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/AnimationEffect.cpp 2020-04-24 21:42:50 UTC (rev 260671)
@@ -26,8 +26,10 @@
#include "config.h"
#include "AnimationEffect.h"
+#include "CSSAnimation.h"
#include "FillMode.h"
#include "JSComputedEffectTiming.h"
+#include "WebAnimation.h"
#include "WebAnimationUtilities.h"
namespace WebCore {
@@ -41,6 +43,13 @@
{
}
+EffectTiming AnimationEffect::getBindingsTiming() const
+{
+ if (is<DeclarativeAnimation>(animation()))
+ downcast<DeclarativeAnimation>(*animation()).flushPendingStyleChanges();
+ return getTiming();
+}
+
EffectTiming AnimationEffect::getTiming() const
{
EffectTiming timing;
@@ -151,6 +160,13 @@
return { localTime, activeTime, m_endTime, m_activeDuration, phase };
}
+ComputedEffectTiming AnimationEffect::getBindingsComputedTiming() const
+{
+ if (is<DeclarativeAnimation>(animation()))
+ downcast<DeclarativeAnimation>(*animation()).flushPendingStyleChanges();
+ return getComputedTiming();
+}
+
ComputedEffectTiming AnimationEffect::getComputedTiming() const
{
// The Web Animations spec introduces a number of animation effect time-related definitions that refer
@@ -336,6 +352,14 @@
return computedTiming;
}
+ExceptionOr<void> AnimationEffect::bindingsUpdateTiming(Optional<OptionalEffectTiming> timing)
+{
+ auto retVal = updateTiming(timing);
+ if (!retVal.hasException() && timing && is<CSSAnimation>(animation()))
+ downcast<CSSAnimation>(*animation()).effectTimingWasUpdatedUsingBindings(*timing);
+ return retVal;
+}
+
ExceptionOr<void> AnimationEffect::updateTiming(Optional<OptionalEffectTiming> timing)
{
// 6.5.4. Updating the timing of an AnimationEffect
Modified: trunk/Source/WebCore/animation/AnimationEffect.h (260670 => 260671)
--- trunk/Source/WebCore/animation/AnimationEffect.h 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/AnimationEffect.h 2020-04-24 21:42:50 UTC (rev 260671)
@@ -53,9 +53,12 @@
virtual bool isKeyframeEffect() const { return false; }
+ EffectTiming getBindingsTiming() const;
EffectTiming getTiming() const;
BasicEffectTiming getBasicTiming() const;
+ ComputedEffectTiming getBindingsComputedTiming() const;
ComputedEffectTiming getComputedTiming() const;
+ ExceptionOr<void> bindingsUpdateTiming(Optional<OptionalEffectTiming>);
ExceptionOr<void> updateTiming(Optional<OptionalEffectTiming>);
virtual void apply(RenderStyle&) = 0;
Modified: trunk/Source/WebCore/animation/AnimationEffect.idl (260670 => 260671)
--- trunk/Source/WebCore/animation/AnimationEffect.idl 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/AnimationEffect.idl 2020-04-24 21:42:50 UTC (rev 260671)
@@ -28,7 +28,7 @@
Exposed=Window,
CustomToJSObject
] interface AnimationEffect {
- EffectTiming getTiming();
- ComputedEffectTiming getComputedTiming();
- [MayThrowException] void updateTiming(optional OptionalEffectTiming timing);
+ [ImplementedAs=getBindingsTiming] EffectTiming getTiming();
+ [ImplementedAs=getBindingsComputedTiming] ComputedEffectTiming getComputedTiming();
+ [MayThrowException, ImplementedAs=bindingsUpdateTiming] void updateTiming(optional OptionalEffectTiming timing);
};
Modified: trunk/Source/WebCore/animation/CSSAnimation.cpp (260670 => 260671)
--- trunk/Source/WebCore/animation/CSSAnimation.cpp 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/CSSAnimation.cpp 2020-04-24 21:42:50 UTC (rev 260671)
@@ -67,50 +67,61 @@
auto previousTiming = animationEffect->getComputedTiming();
- switch (animation.fillMode()) {
- case AnimationFillMode::None:
- animationEffect->setFill(FillMode::None);
- break;
- case AnimationFillMode::Backwards:
- animationEffect->setFill(FillMode::Backwards);
- break;
- case AnimationFillMode::Forwards:
- animationEffect->setFill(FillMode::Forwards);
- break;
- case AnimationFillMode::Both:
- animationEffect->setFill(FillMode::Both);
- break;
+ if (!m_overriddenProperties.contains(Property::FillMode)) {
+ switch (animation.fillMode()) {
+ case AnimationFillMode::None:
+ animationEffect->setFill(FillMode::None);
+ break;
+ case AnimationFillMode::Backwards:
+ animationEffect->setFill(FillMode::Backwards);
+ break;
+ case AnimationFillMode::Forwards:
+ animationEffect->setFill(FillMode::Forwards);
+ break;
+ case AnimationFillMode::Both:
+ animationEffect->setFill(FillMode::Both);
+ break;
+ }
}
- switch (animation.direction()) {
- case Animation::AnimationDirectionNormal:
- animationEffect->setDirection(PlaybackDirection::Normal);
- break;
- case Animation::AnimationDirectionAlternate:
- animationEffect->setDirection(PlaybackDirection::Alternate);
- break;
- case Animation::AnimationDirectionReverse:
- animationEffect->setDirection(PlaybackDirection::Reverse);
- break;
- case Animation::AnimationDirectionAlternateReverse:
- animationEffect->setDirection(PlaybackDirection::AlternateReverse);
- break;
+ if (!m_overriddenProperties.contains(Property::Direction)) {
+ switch (animation.direction()) {
+ case Animation::AnimationDirectionNormal:
+ animationEffect->setDirection(PlaybackDirection::Normal);
+ break;
+ case Animation::AnimationDirectionAlternate:
+ animationEffect->setDirection(PlaybackDirection::Alternate);
+ break;
+ case Animation::AnimationDirectionReverse:
+ animationEffect->setDirection(PlaybackDirection::Reverse);
+ break;
+ case Animation::AnimationDirectionAlternateReverse:
+ animationEffect->setDirection(PlaybackDirection::AlternateReverse);
+ break;
+ }
}
- auto iterationCount = animation.iterationCount();
- animationEffect->setIterations(iterationCount == Animation::IterationCountInfinite ? std::numeric_limits<double>::infinity() : iterationCount);
+ if (!m_overriddenProperties.contains(Property::IterationCount)) {
+ auto iterationCount = animation.iterationCount();
+ animationEffect->setIterations(iterationCount == Animation::IterationCountInfinite ? std::numeric_limits<double>::infinity() : iterationCount);
+ }
- animationEffect->setDelay(Seconds(animation.delay()));
- animationEffect->setIterationDuration(Seconds(animation.duration()));
+ if (!m_overriddenProperties.contains(Property::Delay))
+ animationEffect->setDelay(Seconds(animation.delay()));
+
+ if (!m_overriddenProperties.contains(Property::Duration))
+ animationEffect->setIterationDuration(Seconds(animation.duration()));
+
animationEffect->updateStaticTimingProperties();
effectTimingDidChange(previousTiming);
// Synchronize the play state
- if (animation.playState() == AnimationPlayState::Playing && playState() == WebAnimation::PlayState::Paused) {
- if (!m_stickyPaused)
+ if (!m_overriddenProperties.contains(Property::PlayState)) {
+ if (animation.playState() == AnimationPlayState::Playing && playState() == WebAnimation::PlayState::Paused)
play();
- } else if (animation.playState() == AnimationPlayState::Paused && playState() == WebAnimation::PlayState::Running)
- pause();
+ else if (animation.playState() == AnimationPlayState::Paused && playState() == WebAnimation::PlayState::Running)
+ pause();
+ }
unsuspendEffectInvalidation();
}
@@ -117,16 +128,121 @@
ExceptionOr<void> CSSAnimation::bindingsPlay()
{
- m_stickyPaused = false;
- return DeclarativeAnimation::bindingsPlay();
+ // https://drafts.csswg.org/css-animations-2/#animations
+
+ // After a successful call to play() or pause() on a CSSAnimation, any subsequent change to the animation-play-state will
+ // no longer cause the CSSAnimation to be played or paused.
+
+ auto retVal = DeclarativeAnimation::bindingsPlay();
+ if (!retVal.hasException())
+ m_overriddenProperties.add(Property::PlayState);
+ return retVal;
}
ExceptionOr<void> CSSAnimation::bindingsPause()
{
- m_stickyPaused = true;
- return DeclarativeAnimation::bindingsPause();
+ // https://drafts.csswg.org/css-animations-2/#animations
+
+ // After a successful call to play() or pause() on a CSSAnimation, any subsequent change to the animation-play-state will
+ // no longer cause the CSSAnimation to be played or paused.
+
+ auto retVal = DeclarativeAnimation::bindingsPause();
+ if (!retVal.hasException())
+ m_overriddenProperties.add(Property::PlayState);
+ return retVal;
}
+void CSSAnimation::setBindingsEffect(RefPtr<AnimationEffect>&& newEffect)
+{
+ // https://drafts.csswg.org/css-animations-2/#animations
+
+ // After successfully setting the effect of a CSSAnimation to null or some AnimationEffect other than the original KeyframeEffect,
+ // all subsequent changes to animation properties other than animation-name or animation-play-state will not be reflected in that
+ // animation. Similarly, any change to matching @keyframes rules will not be reflected in that animation. However, if the last
+ // matching @keyframes rule is removed the animation must still be canceled.
+
+ auto* previousEffect = effect();
+ DeclarativeAnimation::setBindingsEffect(WTFMove(newEffect));
+ if (effect() != previousEffect) {
+ m_overriddenProperties.add(Property::Duration);
+ m_overriddenProperties.add(Property::TimingFunction);
+ m_overriddenProperties.add(Property::IterationCount);
+ m_overriddenProperties.add(Property::Direction);
+ m_overriddenProperties.add(Property::Delay);
+ m_overriddenProperties.add(Property::FillMode);
+ }
+}
+
+void CSSAnimation::setBindingsStartTime(Optional<double> startTime)
+{
+ // https://drafts.csswg.org/css-animations-2/#animations
+
+ // After a successful call to reverse() on a CSSAnimation or after successfully setting the startTime on a CSSAnimation,
+ // if, as a result of that call the play state of the CSSAnimation changes to or from the paused play state, any subsequent
+ // change to the animation-play-state will no longer cause the CSSAnimation to be played or paused.
+
+ auto previousPlayState = playState();
+ DeclarativeAnimation::setBindingsStartTime(startTime);
+ auto currentPlayState = playState();
+ if (currentPlayState != previousPlayState && (currentPlayState == PlayState::Paused || previousPlayState == PlayState::Paused))
+ m_overriddenProperties.add(Property::PlayState);
+}
+
+ExceptionOr<void> CSSAnimation::bindingsReverse()
+{
+ // https://drafts.csswg.org/css-animations-2/#animations
+
+ // After a successful call to reverse() on a CSSAnimation or after successfully setting the startTime on a CSSAnimation,
+ // if, as a result of that call the play state of the CSSAnimation changes to or from the paused play state, any subsequent
+ // change to the animation-play-state will no longer cause the CSSAnimation to be played or paused.
+
+ auto previousPlayState = playState();
+ auto retVal = DeclarativeAnimation::bindingsReverse();
+ if (!retVal.hasException()) {
+ auto currentPlayState = playState();
+ if (currentPlayState != previousPlayState && (currentPlayState == PlayState::Paused || previousPlayState == PlayState::Paused))
+ m_overriddenProperties.add(Property::PlayState);
+ }
+ return retVal;
+}
+
+void CSSAnimation::effectTimingWasUpdatedUsingBindings(OptionalEffectTiming timing)
+{
+ // https://drafts.csswg.org/css-animations-2/#animations
+
+ // After a successful call to updateTiming() on the KeyframeEffect associated with a CSSAnimation, for each property
+ // included in the timing parameter, any subsequent change to a corresponding animation property will not be reflected
+ // in that animation.
+
+ if (timing.duration)
+ m_overriddenProperties.add(Property::Duration);
+
+ if (timing.iterations)
+ m_overriddenProperties.add(Property::IterationCount);
+
+ if (timing.delay)
+ m_overriddenProperties.add(Property::Delay);
+
+ if (!timing.easing.isNull())
+ m_overriddenProperties.add(Property::TimingFunction);
+
+ if (timing.fill)
+ m_overriddenProperties.add(Property::FillMode);
+
+ if (timing.direction)
+ m_overriddenProperties.add(Property::Direction);
+}
+
+void CSSAnimation::effectKeyframesWereSetUsingBindings()
+{
+ // https://drafts.csswg.org/css-animations-2/#animations
+
+ // After a successful call to setKeyframes() on the KeyframeEffect associated with a CSSAnimation, any subsequent change to
+ // matching @keyframes rules or the resolved value of the animation-timing-function property for the target element will not
+ // be reflected in that animation.
+ m_overriddenProperties.add(Property::TimingFunction);
+}
+
Ref<AnimationEventBase> CSSAnimation::createEvent(const AtomString& eventType, double elapsedTime, const String& pseudoId, Optional<Seconds> timelineTime)
{
return AnimationEvent::create(eventType, m_animationName, elapsedTime, pseudoId, timelineTime, this);
Modified: trunk/Source/WebCore/animation/CSSAnimation.h (260670 => 260671)
--- trunk/Source/WebCore/animation/CSSAnimation.h 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/CSSAnimation.h 2020-04-24 21:42:50 UTC (rev 260671)
@@ -26,6 +26,7 @@
#pragma once
#include "DeclarativeAnimation.h"
+#include <wtf/OptionSet.h>
#include <wtf/Ref.h>
namespace WebCore {
@@ -43,8 +44,8 @@
bool isCSSAnimation() const override { return true; }
const String& animationName() const { return m_animationName; }
- ExceptionOr<void> bindingsPlay() final;
- ExceptionOr<void> bindingsPause() final;
+ void effectTimingWasUpdatedUsingBindings(OptionalEffectTiming);
+ void effectKeyframesWereSetUsingBindings();
private:
CSSAnimation(Element&, const Animation&);
@@ -52,8 +53,25 @@
void syncPropertiesWithBackingAnimation() final;
Ref<AnimationEventBase> createEvent(const AtomString& eventType, double elapsedTime, const String& pseudoId, Optional<Seconds> timelineTime) final;
+ ExceptionOr<void> bindingsPlay() final;
+ ExceptionOr<void> bindingsPause() final;
+ void setBindingsEffect(RefPtr<AnimationEffect>&&) final;
+ void setBindingsStartTime(Optional<double>) final;
+ ExceptionOr<void> bindingsReverse() final;
+
+ enum class Property : uint8_t {
+ Name = 1 << 0,
+ Duration = 1 << 1,
+ TimingFunction = 1 << 2,
+ IterationCount = 1 << 3,
+ Direction = 1 << 4,
+ PlayState = 1 << 5,
+ Delay = 1 << 6,
+ FillMode = 1 << 7
+ };
+
String m_animationName;
- bool m_stickyPaused { false };
+ OptionSet<Property> m_overriddenProperties;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/animation/DeclarativeAnimation.cpp (260670 => 260671)
--- trunk/Source/WebCore/animation/DeclarativeAnimation.cpp 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/DeclarativeAnimation.cpp 2020-04-24 21:42:50 UTC (rev 260671)
@@ -129,13 +129,13 @@
{
}
-Optional<double> DeclarativeAnimation::startTime() const
+Optional<double> DeclarativeAnimation::bindingsStartTime() const
{
flushPendingStyleChanges();
return WebAnimation::startTime();
}
-void DeclarativeAnimation::setStartTime(Optional<double> startTime)
+void DeclarativeAnimation::setBindingsStartTime(Optional<double> startTime)
{
flushPendingStyleChanges();
return WebAnimation::setStartTime(startTime);
Modified: trunk/Source/WebCore/animation/DeclarativeAnimation.h (260670 => 260671)
--- trunk/Source/WebCore/animation/DeclarativeAnimation.h 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/DeclarativeAnimation.h 2020-04-24 21:42:50 UTC (rev 260671)
@@ -50,8 +50,8 @@
void setBackingAnimation(const Animation&);
void cancelFromStyle();
- Optional<double> startTime() const final;
- void setStartTime(Optional<double>) final;
+ Optional<double> bindingsStartTime() const final;
+ void setBindingsStartTime(Optional<double>) override;
Optional<double> bindingsCurrentTime() const final;
ExceptionOr<void> setBindingsCurrentTime(Optional<double>) final;
WebAnimation::PlayState bindingsPlayState() const final;
@@ -69,6 +69,8 @@
bool canHaveGlobalPosition() final;
+ void flushPendingStyleChanges() const;
+
protected:
DeclarativeAnimation(Element&, const Animation&);
@@ -81,7 +83,6 @@
private:
void disassociateFromOwningElement();
- void flushPendingStyleChanges() const;
AnimationEffectPhase phaseWithoutEffect() const;
void enqueueDOMEvent(const AtomString&, Seconds);
Modified: trunk/Source/WebCore/animation/KeyframeEffect.cpp (260670 => 260671)
--- trunk/Source/WebCore/animation/KeyframeEffect.cpp 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/KeyframeEffect.cpp 2020-04-24 21:42:50 UTC (rev 260671)
@@ -574,6 +574,13 @@
setBlendingKeyframes(keyframeList);
}
+Vector<Strong<JSObject>> KeyframeEffect::getBindingsKeyframes(JSGlobalObject& lexicalGlobalObject)
+{
+ if (is<DeclarativeAnimation>(animation()))
+ downcast<DeclarativeAnimation>(*animation()).flushPendingStyleChanges();
+ return getKeyframes(lexicalGlobalObject);
+}
+
Vector<Strong<JSObject>> KeyframeEffect::getKeyframes(JSGlobalObject& lexicalGlobalObject)
{
// https://drafts.csswg.org/web-animations-1/#dom-keyframeeffectreadonly-getkeyframes
@@ -589,7 +596,7 @@
// 2. Let keyframes be the result of applying the procedure to compute missing keyframe offsets to the keyframes for this keyframe effect.
// 3. For each keyframe in keyframes perform the following steps:
- if (is<DeclarativeAnimation>(animation())) {
+ if (m_parsedKeyframes.isEmpty() && m_blendingKeyframesSource != BlendingKeyframesSource::WebAnimation) {
auto* target = m_target.get();
auto* renderer = this->renderer();
@@ -683,6 +690,14 @@
return result;
}
+ExceptionOr<void> KeyframeEffect::setBindingsKeyframes(JSGlobalObject& lexicalGlobalObject, Strong<JSObject>&& keyframesInput)
+{
+ auto retVal = setKeyframes(lexicalGlobalObject, WTFMove(keyframesInput));
+ if (!retVal.hasException() && is<CSSAnimation>(animation()))
+ downcast<CSSAnimation>(*animation()).effectKeyframesWereSetUsingBindings();
+ return retVal;
+}
+
ExceptionOr<void> KeyframeEffect::setKeyframes(JSGlobalObject& lexicalGlobalObject, Strong<JSObject>&& keyframesInput)
{
auto processKeyframesResult = processKeyframes(lexicalGlobalObject, WTFMove(keyframesInput));
@@ -711,10 +726,15 @@
// 5. Perform the steps corresponding to the first matching condition from below,
Vector<String> unusedEasings;
- if (!method.isUndefined())
- processIterableKeyframes(lexicalGlobalObject, WTFMove(keyframesInput), WTFMove(method), parsedKeyframes);
- else
- processPropertyIndexedKeyframes(lexicalGlobalObject, WTFMove(keyframesInput), parsedKeyframes, unusedEasings);
+ if (!method.isUndefined()) {
+ auto retVal = processIterableKeyframes(lexicalGlobalObject, WTFMove(keyframesInput), WTFMove(method), parsedKeyframes);
+ if (retVal.hasException())
+ return retVal.releaseException();
+ } else {
+ auto retVal = processPropertyIndexedKeyframes(lexicalGlobalObject, WTFMove(keyframesInput), parsedKeyframes, unusedEasings);
+ if (retVal.hasException())
+ return retVal.releaseException();
+ }
// 6. If processed keyframes is not loosely sorted by offset, throw a TypeError and abort these steps.
// 7. If there exist any keyframe in processed keyframes whose keyframe offset is non-null and less than
Modified: trunk/Source/WebCore/animation/KeyframeEffect.h (260670 => 260671)
--- trunk/Source/WebCore/animation/KeyframeEffect.h 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/KeyframeEffect.h 2020-04-24 21:42:50 UTC (rev 260671)
@@ -109,7 +109,9 @@
const String pseudoElement() const;
ExceptionOr<void> setPseudoElement(const String&);
+ Vector<JSC::Strong<JSC::JSObject>> getBindingsKeyframes(JSC::JSGlobalObject&);
Vector<JSC::Strong<JSC::JSObject>> getKeyframes(JSC::JSGlobalObject&);
+ ExceptionOr<void> setBindingsKeyframes(JSC::JSGlobalObject&, JSC::Strong<JSC::JSObject>&&);
ExceptionOr<void> setKeyframes(JSC::JSGlobalObject&, JSC::Strong<JSC::JSObject>&&);
IterationCompositeOperation iterationComposite() const { return m_iterationCompositeOperation; }
Modified: trunk/Source/WebCore/animation/KeyframeEffect.idl (260670 => 260671)
--- trunk/Source/WebCore/animation/KeyframeEffect.idl 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/KeyframeEffect.idl 2020-04-24 21:42:50 UTC (rev 260671)
@@ -38,8 +38,8 @@
[MayThrowException] attribute CSSOMString? pseudoElement;
[EnabledAtRuntime=WebAnimationsCompositeOperations] attribute IterationCompositeOperation iterationComposite;
[EnabledAtRuntime=WebAnimationsCompositeOperations] attribute CompositeOperation composite;
- [CallWith=GlobalObject] sequence<object> getKeyframes();
- [MayThrowException, CallWith=GlobalObject] void setKeyframes(object? keyframes);
+ [CallWith=GlobalObject, ImplementedAs=getBindingsKeyframes] sequence<object> getKeyframes();
+ [MayThrowException, CallWith=GlobalObject, ImplementedAs=setBindingsKeyframes] void setKeyframes(object? keyframes);
};
dictionary BasePropertyIndexedKeyframe {
Modified: trunk/Source/WebCore/animation/WebAnimation.cpp (260670 => 260671)
--- trunk/Source/WebCore/animation/WebAnimation.cpp 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/WebAnimation.cpp 2020-04-24 21:42:50 UTC (rev 260671)
@@ -145,6 +145,11 @@
InspectorInstrumentation::didChangeWebAnimationEffectTiming(*this);
}
+void WebAnimation::setBindingsEffect(RefPtr<AnimationEffect>&& newEffect)
+{
+ setEffect(WTFMove(newEffect));
+}
+
void WebAnimation::setEffect(RefPtr<AnimationEffect>&& newEffect)
{
// 3.4.3. Setting the target effect of an animation
@@ -297,6 +302,11 @@
return secondsToWebAnimationsAPITime(m_startTime.value());
}
+void WebAnimation::setBindingsStartTime(Optional<double> startTime)
+{
+ setStartTime(startTime);
+}
+
void WebAnimation::setStartTime(Optional<double> startTime)
{
// 3.4.6 The procedure to set the start time of animation, animation, to new start time, is as follows:
@@ -1097,6 +1107,11 @@
return { };
}
+ExceptionOr<void> WebAnimation::bindingsReverse()
+{
+ return reverse();
+}
+
ExceptionOr<void> WebAnimation::reverse()
{
LOG_WITH_STREAM(Animations, stream << "WebAnimation " << this << " reverse (current time is " << currentTime() << ")");
Modified: trunk/Source/WebCore/animation/WebAnimation.h (260670 => 260671)
--- trunk/Source/WebCore/animation/WebAnimation.h 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/WebAnimation.h 2020-04-24 21:42:50 UTC (rev 260671)
@@ -66,6 +66,8 @@
const String& id() const { return m_id; }
void setId(const String& id) { m_id = id; }
+ AnimationEffect* bindingsEffect() const { return effect(); }
+ virtual void setBindingsEffect(RefPtr<AnimationEffect>&&);
AnimationEffect* effect() const { return m_effect.get(); }
void setEffect(RefPtr<AnimationEffect>&&);
AnimationTimeline* timeline() const { return m_timeline.get(); }
@@ -98,12 +100,15 @@
ExceptionOr<void> play();
void updatePlaybackRate(double);
ExceptionOr<void> pause();
+ virtual ExceptionOr<void> bindingsReverse();
ExceptionOr<void> reverse();
void persist();
ExceptionOr<void> commitStyles();
- virtual Optional<double> startTime() const;
- virtual void setStartTime(Optional<double>);
+ virtual Optional<double> bindingsStartTime() const { return startTime(); }
+ virtual void setBindingsStartTime(Optional<double>);
+ Optional<double> startTime() const;
+ void setStartTime(Optional<double>);
virtual Optional<double> bindingsCurrentTime() const;
virtual ExceptionOr<void> setBindingsCurrentTime(Optional<double>);
virtual PlayState bindingsPlayState() const { return playState(); }
Modified: trunk/Source/WebCore/animation/WebAnimation.idl (260670 => 260671)
--- trunk/Source/WebCore/animation/WebAnimation.idl 2020-04-24 21:41:32 UTC (rev 260670)
+++ trunk/Source/WebCore/animation/WebAnimation.idl 2020-04-24 21:42:50 UTC (rev 260671)
@@ -44,9 +44,9 @@
CustomToJSObject
] interface WebAnimation : EventTarget {
attribute DOMString id;
- attribute AnimationEffect? effect;
+ [ImplementedAs=bindingsEffect] attribute AnimationEffect? effect;
[RuntimeConditionallyReadWrite=WebAnimationsMutableTimelines] attribute AnimationTimeline? timeline;
- attribute double? startTime;
+ [ImplementedAs=bindingsStartTime] attribute double? startTime;
[MayThrowException, ImplementedAs=bindingsCurrentTime] attribute double? currentTime;
attribute double playbackRate;
[ImplementedAs=bindingsPlayState] readonly attribute AnimationPlayState playState;
@@ -62,7 +62,7 @@
[MayThrowException, ImplementedAs=bindingsPlay] void play();
[MayThrowException, ImplementedAs=bindingsPause] void pause();
void updatePlaybackRate(double playbackRate);
- [MayThrowException] void reverse();
+ [MayThrowException, ImplementedAs=bindingsReverse] void reverse();
void persist();
[MayThrowException] void commitStyles();
};