tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

scroll-timeline-invalidation.html (5252B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>ScrollTimeline invalidation</title>
      4 <link rel="help" href="https://wicg.github.io/scroll-animations/#current-time-algorithm">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script src="/web-animations/testcommon.js"></script>
      8 <script src="testcommon.js"></script>
      9 <style>
     10  .scroller {
     11    overflow: auto;
     12    height: 100px;
     13    width: 100px;
     14    will-change: transform;
     15  }
     16  .contents {
     17    height: 1000px;
     18    width: 100%;
     19  }
     20 </style>
     21 <div id="log"></div>
     22 
     23 <script>
     24 'use strict';
     25 
     26 promise_test(async t => {
     27  const animation = createScrollLinkedAnimation(t);
     28  const effect_duration = 350;
     29  animation.effect.updateTiming({ duration: effect_duration });
     30  const scroller = animation.timeline.source;
     31  let maxScroll = scroller.scrollHeight - scroller.clientHeight;
     32  scroller.scrollTop = 0.2 * maxScroll;
     33  const initial_progress = (scroller.scrollTop / maxScroll) * 100;
     34 
     35  animation.play();
     36  await animation.ready;
     37 
     38  // Animation current time is at 20% because scroller was scrolled to 20%
     39  assert_percents_equal(animation.currentTime, 20);
     40  assert_equals(scroller.scrollTop, 180);
     41  assert_equals(maxScroll, 900);
     42 
     43  // Shrink scroller content size (from 1000 to 500).
     44  // scroller.scrollTop maintains the same offset, which means shrinking the
     45  // content has the effect of skipping the animation forward.
     46  scroller.firstChild.style.height = "500px";
     47  maxScroll = scroller.scrollHeight - scroller.clientHeight;
     48 
     49  assert_equals(scroller.scrollTop, 180);
     50  assert_equals(maxScroll, 400);
     51  await waitForNextFrame();
     52 
     53  const expected_progress = (scroller.scrollTop / maxScroll) * 100;
     54  assert_true(expected_progress > initial_progress)
     55  // @ 45%
     56  assert_percents_equal(animation.currentTime, expected_progress);
     57  assert_percents_equal(animation.timeline.currentTime, expected_progress);
     58  assert_percents_equal(animation.effect.getComputedTiming().localTime, expected_progress);
     59 }, 'Animation current time and effect local time are updated after scroller ' +
     60   'content size changes.');
     61 
     62 promise_test(async t => {
     63  const animation = createScrollLinkedAnimation(t);
     64  animation.effect.updateTiming({ duration: 350 });
     65  const scroller = animation.timeline.source;
     66  let maxScroll = scroller.scrollHeight - scroller.clientHeight;
     67  const scrollOffset = 0.2 * maxScroll
     68  scroller.scrollTop = scrollOffset;
     69  const initial_progress = (scroller.scrollTop / maxScroll) * 100;
     70 
     71  animation.play();
     72  await animation.ready;
     73 
     74  // Animation current time is at 20% because scroller was scrolled to 20%
     75  // assert_equals(animation.currentTime.value, 20);
     76  assert_percents_equal(animation.currentTime, 20);
     77  assert_equals(scroller.scrollTop, scrollOffset);
     78  assert_equals(maxScroll, 900);
     79 
     80  // Change scroller size.
     81  scroller.style.height = "500px";
     82  maxScroll = scroller.scrollHeight - scroller.clientHeight;
     83 
     84  assert_equals(scroller.scrollTop, scrollOffset);
     85  assert_equals(maxScroll, 500);
     86  await waitForNextFrame();
     87 
     88  const expected_progress = (scroller.scrollTop / maxScroll) * 100;
     89  assert_true(expected_progress > initial_progress);
     90  // @ 45%
     91  assert_percents_equal(animation.currentTime, expected_progress);
     92  assert_percents_equal(animation.timeline.currentTime, expected_progress);
     93  assert_percents_equal(animation.effect.getComputedTiming().localTime,
     94                        expected_progress);
     95 }, 'Animation current time and effect local time are updated after scroller ' +
     96   'size changes.');
     97 
     98 promise_test(async t => {
     99  await waitForNextFrame();
    100 
    101  const timeline = createScrollTimeline(t);
    102  const scroller = timeline.source;
    103  const maxScroll = scroller.scrollHeight - scroller.clientHeight;
    104  // Instantiate scroll animation that resizes its scroll timeline scroller.
    105  const animation = new Animation(
    106    new KeyframeEffect(
    107      timeline.source.firstChild,
    108      [{ height: '1000px', easing: 'steps(2, jump-none)'},
    109       { height: '2000px' }],
    110    ), timeline);
    111 
    112  animation.play();
    113  await animation.ready;
    114 
    115  assert_percents_equal(timeline.currentTime, 0);
    116  assert_equals(scroller.scrollHeight, 1000);
    117 
    118  await runAndWaitForFrameUpdate(() => {
    119    scroller.scrollTop = 0.6 * maxScroll;
    120  });
    121 
    122  // Applying the animation effect alters the height of the scroll content and
    123  // makes the scroll timeline stale.
    124  // https://github.com/w3c/csswg-drafts/issues/8694
    125 
    126  // runAndWaitForFrameUpdate will yield after the requestAnimationFrame callbacks
    127  // have been serviced, which is prior to when stale timelines are updated.
    128  // https://github.com/w3c/csswg-drafts/issues/12120
    129  assert_approx_equals(timeline.currentTime.value, 60, 0.1);
    130 
    131  // Now wait another beat such that the rest of the HTML Processing Model event loop
    132  // has run and we can check whether stale timelines have been updated.
    133  await new Promise(setTimeout);
    134 
    135  // With a single layout, timeline current time would be at 60%, but the
    136  // timeline would be stale.
    137  const expected_progress = 60 * maxScroll / (maxScroll + 1000);
    138  assert_approx_equals(timeline.currentTime.value, expected_progress, 0.1);
    139 
    140 }, 'If scroll animation resizes its scroll timeline scroller, ' +
    141   'layout reruns once per frame.');
    142 </script>