haikuwebkit/LayoutTests/webanimations/css-transition-retargeting-...

63 lines
2.3 KiB
HTML
Raw Permalink Normal View History

[Web Animations] REGRESSION: Bootstrap Carousel component v4.1 regressed with Web Animations https://bugs.webkit.org/show_bug.cgi?id=213376 <rdar://problem/64531242> Reviewed by Dean Jackson. Source/WebCore: An older version of the Bootstrap CSS and JS library had a rather odd way to implement a completion callback for a transition: it would register a "transitionend" event but also set a timeout of the transition's duration and use whichever came first as a callback to run completion tasks for the transition. Additionally, in that callback, it would set the transitioned value to the same computed value but using a different specified value, for instance setting the "transform" CSS property to "translateX(0)" instead of "translateY(0)". In our implementation this would make the completed transition repeat. Indeed, we would first incorrectly assume that the transition was still "running" and not "finished", per the CSS Transitions spec terminology as we only update that status when we update animations under Page::updateRendering(). We now update an existing transition's status first in AnimationTimeline::updateCSSTransitionsForElementAndProperty(). Another issue is that when we considered the existing transition to be running, even though it was finished, we would use the "timeline time at creation" to compute its current progress, which would yield situations where we computed the before-change style to be the existing transition's current computed value, except that transition's progress was 0 since the "timeline time at creation" happens before the transition's resolved start time. We now only use the "timeline time at creation" in the situations it was designed to be used: either when the transition has not yet had a resolved start time, or its resolved start time is the current timeline time (ie. it was just set). To be able to compare the transition's resolved start time and the current timeline time, we also updated the internal start time getter and setter methods to use Seconds instead of double which is only needed for the JS bindings. Test: webanimations/css-transition-retargeting-to-same-value-upon-completion-with-timeout.html * animation/AnimationTimeline.cpp: (WebCore::AnimationTimeline::updateCSSTransitionsForElementAndProperty): * animation/DeclarativeAnimation.cpp: (WebCore::DeclarativeAnimation::bindingsStartTime const): (WebCore::DeclarativeAnimation::setBindingsStartTime): * animation/WebAnimation.cpp: (WebCore::WebAnimation::bindingsStartTime const): (WebCore::WebAnimation::setBindingsStartTime): (WebCore::WebAnimation::setStartTime): (WebCore::WebAnimation::startTime const): Deleted. * animation/WebAnimation.h: (WebCore::WebAnimation::startTime const): (WebCore::WebAnimation::bindingsStartTime const): Deleted. LayoutTests: Add a test that uses a timeout instead of a "transitionend" event to retarget a transition upon completion to the same computed value but not the same specified value to check that we generate a transition that has no visual effect. * webanimations/css-transition-retargeting-to-same-value-upon-completion-with-timeout-expected.txt: Added. * webanimations/css-transition-retargeting-to-same-value-upon-completion-with-timeout.html: Added. Canonical link: https://commits.webkit.org/226577@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@263729 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2020-06-30 05:56:53 +00:00
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.target {
transform: translateX(100px);
transition: transform 100ms linear;
}
.target.in-flight {
transform: translateX(0);
}
.target.in-flight.retargeted {
transform: translateY(0);
}
</style>
<body>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script>
'use strict';
promise_test(async test => {
const target = document.body.appendChild(document.createElement("div"));
target.classList.add("target");
const getAnimation = () => {
const animations = target.getAnimations();
assert_equals(animations.length, 1, "There is one animation applied to the target.");
const transition = animations[0];
assert_true(transition instanceof CSSTransition, "There is one transition applied to the target.");
return transition;
}
let initialTransition;
let retargetedTransition;
// Start the initial transition.
await new Promise(requestAnimationFrame);
target.classList.add("in-flight");
initialTransition = getAnimation();
// Wait until the animation is complete and retarget the transition to the same value.
await(initialTransition.ready);
await(new Promise(resolve => setTimeout(resolve, 100)));
target.classList.add("retargeted");
retargetedTransition = getAnimation();
assert_not_equals(initialTransition, retargetedTransition, "Retargeting yielded a new transition.");
const transformAtKeyframeIndex = (animation, index) => new DOMMatrixReadOnly(animation.effect.getKeyframes()[index].transform).toString();
assert_not_equals(transformAtKeyframeIndex(initialTransition, 0), transformAtKeyframeIndex(retargetedTransition, 0), "The initial and retargeted transitions have different from values.");
assert_equals(transformAtKeyframeIndex(initialTransition, 1), transformAtKeyframeIndex(retargetedTransition, 1), "The initial and retargeted transitions have the same to values.");
assert_equals(transformAtKeyframeIndex(retargetedTransition, 0), transformAtKeyframeIndex(retargetedTransition, 1), "The retargeted transition from and to values are the same.");
}, `A CSS transition that is retargeted upon completion based on a timer should not use its to style as its before-change style.`);
</script>
</body>