tor-browser

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

timelines.html (4979B)


      1 <!doctype html>
      2 <meta charset=utf-8>
      3 <title>Timelines</title>
      4 <link rel="help" href="https://drafts.csswg.org/web-animations/#timelines">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script src="../../testcommon.js"></script>
      8 <style>
      9 @keyframes opacity-animation {
     10  from { opacity: 1; }
     11  to { opacity: 0; }
     12 }
     13 </style>
     14 <div id="log"></div>
     15 <script>
     16 'use strict';
     17 
     18 promise_test(t => {
     19  const valueAtStart = document.timeline.currentTime;
     20  const timeAtStart = window.performance.now();
     21  while (window.performance.now() - timeAtStart < 50) {
     22    // Wait 50ms
     23  }
     24  assert_equals(document.timeline.currentTime, valueAtStart,
     25    'Timeline time does not change within an animation frame');
     26  return waitForAnimationFrames(1).then(() => {
     27    assert_greater_than(document.timeline.currentTime, valueAtStart,
     28      'Timeline time increases between animation frames');
     29  });
     30 }, 'Timeline time increases once per animation frame');
     31 
     32 async_test(t => {
     33  const iframe = document.createElement('iframe');
     34  iframe.width = 10;
     35  iframe.height = 10;
     36 
     37  iframe.addEventListener('load', t.step_func(() => {
     38    const iframeTimeline = iframe.contentDocument.timeline;
     39    const valueAtStart   = iframeTimeline.currentTime;
     40    const timeAtStart    = window.performance.now();
     41    while (iframe.contentWindow.performance.now() - timeAtStart < 50) {
     42      // Wait 50ms
     43    }
     44    assert_equals(iframeTimeline.currentTime, valueAtStart,
     45      'Timeline time within an iframe does not change within an '
     46      + ' animation frame');
     47 
     48    iframe.contentWindow.requestAnimationFrame(t.step_func_done(() => {
     49      assert_greater_than(iframeTimeline.currentTime, valueAtStart,
     50        'Timeline time within an iframe increases between animation frames');
     51      iframe.remove();
     52    }));
     53  }));
     54 
     55  document.body.appendChild(iframe);
     56 }, 'Timeline time increases once per animation frame in an iframe');
     57 
     58 async_test(t => {
     59  const startTime = document.timeline.currentTime;
     60  let firstRafTime;
     61 
     62  requestAnimationFrame(() => {
     63    t.step(() => {
     64      assert_greater_than_equal(document.timeline.currentTime, startTime,
     65                                'Timeline time should have progressed');
     66      firstRafTime = document.timeline.currentTime;
     67    });
     68  });
     69 
     70  requestAnimationFrame(() => {
     71    t.step(() => {
     72      assert_equals(document.timeline.currentTime, firstRafTime,
     73                    'Timeline time should be the same');
     74    });
     75    t.done();
     76  });
     77 }, 'Timeline time should be the same for all RAF callbacks in an animation'
     78   + ' frame');
     79 
     80 promise_test(async t => {
     81  // A microtask checkpoint is run as part of the process of updating
     82  // timelines to ensure that any microtasks queued during promise
     83  // resolution are handled before dispatching animation events.
     84  const div = createDiv(t);
     85  const events = [];
     86  let microtaskFrameTime = undefined;
     87  let finishFrameTime = undefined;
     88  const waitForMicrotask = (animation) => {
     89    return new Promise(resolve => {
     90      queueMicrotask(() => {
     91        events.push('microtask');
     92        microtaskFrameTime = document.timeline.currentTime;
     93        resolve();
     94      });
     95    });
     96  }
     97  const waitForFinishEvent = (animation) => {
     98    return new Promise(resolve => {
     99      animation.onfinish = (event) => {
    100        events.push('finish');
    101        finishFrameTime = event.timelineTime;
    102        resolve();
    103      };
    104    });
    105  }
    106 
    107  await waitForNextFrame();
    108 
    109  const animation = div.animate({ opacity: [0, 1] }, 1000 * MS_PER_SEC);
    110  const finishPromise = waitForFinishEvent(animation);
    111  await animation.ready;
    112 
    113  // Advance the timing to effect end, to asynchronously queue up a finish task.
    114  // Queue up microtask, which must be processed ahead of the finish event.
    115  // See "Perform a microtask checkpoint" step in
    116  // https://www.w3.org/TR/web-animations-1/#timelines.
    117  animation.currentTime = animation.effect.getComputedTiming().duration;
    118  const microtaskPromise = waitForMicrotask(animation);
    119  await Promise.all([finishPromise, microtaskPromise]);
    120  assert_array_equals(events, ['microtask', 'finish']);
    121  assert_times_equal(microtaskFrameTime, finishFrameTime);
    122 
    123 }, 'Performs a microtask checkpoint after updating timelines');
    124 
    125 async_test(t => {
    126  const div = createDiv(t);
    127  let readyPromiseRan = false;
    128  let finishedPromiseRan = false;
    129  div.style.animation = 'opacity-animation 1ms';
    130  let anim = div.getAnimations()[0];
    131  anim.ready.then(t.step_func(() => {
    132    readyPromiseRan = true;
    133  }));
    134  div.addEventListener('animationstart', t.step_func(() => {
    135    assert_true(readyPromiseRan, 'It should run ready promise before animationstart event');
    136  }));
    137  anim.finished.then(t.step_func(() => {
    138    finishedPromiseRan = true;
    139  }));
    140  div.addEventListener('animationend', t.step_func_done(() => {
    141    assert_true(finishedPromiseRan, 'It should run finished promise before animationend event');
    142  }));
    143 }, 'Runs finished promise before animation events');
    144 </script>