mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-10 21:28:04 +02:00
Automatic update from web-platform-tests Snapshot scroll timeline state once per animation frame. This change simplifies previous scroll timeline snapshotting model implemented in https://chromium-review.googlesource.com/c/chromium/src/+/2005629. In previous model snapshotting is allowed any time scroll timeline is invalidated outside of document lifecycle update, e.g. in user scripts. Such invalidations may cause scroll animations to be stale after layout run, which is against existing invariant that requires clean layout state after document update. This change allows snapshotting just once per animation frame. Scripts that cause scroll timeline invalidation need to wait for next animation frame to read updated scroll timeline current time. Changes made: - Snapshot scroll timeline phase and time once per animation frame at top of frame. - On scroll timeline invalidation request a new frame where new state is snapshotted. - Updated tests that read scroll timeline current time after scroller invalidation to wait for next frame. Bug: 944449 Change-Id: I9b2f15f8f6456ef1c01ff7bedf72545ed7618b96 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2129232 Commit-Queue: Majid Valipour <majidvp@chromium.org> Reviewed-by: Robert Flack <flackr@chromium.org> Reviewed-by: Majid Valipour <majidvp@chromium.org> Cr-Commit-Position: refs/heads/master@{#755797} -- wpt-commits: 167fc7a89f441e9548454d54f260a6d19cf973b6 wpt-pr: 22581
105 lines
3.6 KiB
HTML
105 lines
3.6 KiB
HTML
<!DOCTYPE html>
|
|
<meta charset="utf-8">
|
|
<title>ScrollTimeline invalidation</title>
|
|
<link rel="help" href="https://wicg.github.io/scroll-animations/#current-time-algorithm">
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="/web-animations/testcommon.js"></script>
|
|
<script src="testcommon.js"></script>
|
|
<style>
|
|
.scroller {
|
|
overflow: auto;
|
|
height: 100px;
|
|
width: 100px;
|
|
}
|
|
.contents {
|
|
height: 1000px;
|
|
width: 100%;
|
|
}
|
|
</style>
|
|
<div id="log"></div>
|
|
|
|
<script>
|
|
'use strict';
|
|
|
|
promise_test(async t => {
|
|
const animation = createScrollLinkedAnimation(t);
|
|
animation.effect.updateTiming({ duration: 350 });
|
|
const scroller = animation.timeline.scrollSource;
|
|
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
|
scroller.scrollTop = 0.2 * maxScroll;
|
|
// Wait for new animation frame which allows the timeline to compute new
|
|
// current time.
|
|
await waitForNextFrame();
|
|
|
|
animation.play();
|
|
await animation.ready;
|
|
|
|
// Change scroller content size.
|
|
scroller.firstChild.style.height = "500px";
|
|
|
|
await animation.finished;
|
|
const newTime = animation.effect.getTiming().duration;
|
|
assert_times_equal(animation.currentTime, newTime,
|
|
'Animation current time is updated after scroller invalidation.');
|
|
|
|
assert_times_equal(
|
|
animation.effect.getComputedTiming().localTime, newTime,
|
|
'Effect local time is updated after scroller invalidation.');
|
|
}, 'Animation current time and effect local time are updated after scroller ' +
|
|
'content size changes.');
|
|
|
|
promise_test(async t => {
|
|
const animation = createScrollLinkedAnimation(t);
|
|
animation.effect.updateTiming({ duration: 350 });
|
|
const scroller = animation.timeline.scrollSource;
|
|
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
|
scroller.scrollTop = 0.2 * maxScroll;
|
|
// Wait for new animation frame which allows the timeline to compute new
|
|
// current time.
|
|
await waitForNextFrame();
|
|
|
|
animation.play();
|
|
await animation.ready;
|
|
|
|
// Change scroller size.
|
|
scroller.style.height = "500px";
|
|
|
|
await animation.finished;
|
|
const newTime = animation.effect.getTiming().duration;
|
|
assert_times_equal(animation.currentTime, newTime,
|
|
'Animation current time is updated after scroller invalidation.');
|
|
|
|
assert_times_equal(
|
|
animation.effect.getComputedTiming().localTime, newTime,
|
|
'Effect local time is updated after scroller invalidation.');
|
|
}, 'Animation current time and effect local time are updated after scroller ' +
|
|
'size changes.');
|
|
|
|
promise_test(async t => {
|
|
const timeline = createScrollTimeline(t);
|
|
const scroller = timeline.scrollSource;
|
|
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
|
// Instantiate scroll animation that resizes its scroll timeline scroller.
|
|
const animation = new Animation(
|
|
new KeyframeEffect(
|
|
timeline.scrollSource.firstChild,
|
|
[{ height: '1000px' }, { height: '2000px' }],
|
|
{ duration: 1000, }
|
|
), timeline);
|
|
animation.play();
|
|
await animation.ready;
|
|
await waitForNextFrame();
|
|
scroller.scrollTop = 0.2 * maxScroll;
|
|
// Wait for new animation frame which allows the timeline to compute new
|
|
// current time.
|
|
await waitForNextFrame();
|
|
assert_times_equal(timeline.currentTime, 200,
|
|
'Timeline current time is updated after animation frame.');
|
|
await waitForNextFrame();
|
|
assert_times_equal(timeline.currentTime, 163.636,
|
|
'Timeline current time is updated after two animation frames and ' +
|
|
'reflects single layout run.');
|
|
}, 'If scroll animation resizes its scroll timeline scroller, ' +
|
|
'layout runs only once to reflect the initial update.');
|
|
</script>
|