File: timelines.html

package info (click to toggle)
thunderbird 1%3A143.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 4,703,968 kB
  • sloc: cpp: 7,770,492; javascript: 5,943,842; ansic: 3,918,754; python: 1,418,263; xml: 653,354; asm: 474,045; java: 183,079; sh: 111,238; makefile: 20,410; perl: 14,359; objc: 13,059; yacc: 4,583; pascal: 3,405; lex: 1,720; ruby: 999; exp: 762; sql: 715; awk: 580; php: 436; lisp: 430; sed: 69; csh: 10
file content (144 lines) | stat: -rw-r--r-- 4,979 bytes parent folder | download | duplicates (14)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
<!doctype html>
<meta charset=utf-8>
<title>Timelines</title>
<link rel="help" href="https://drafts.csswg.org/web-animations/#timelines">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="../../testcommon.js"></script>
<style>
@keyframes opacity-animation {
  from { opacity: 1; }
  to { opacity: 0; }
}
</style>
<div id="log"></div>
<script>
'use strict';

promise_test(t => {
  const valueAtStart = document.timeline.currentTime;
  const timeAtStart = window.performance.now();
  while (window.performance.now() - timeAtStart < 50) {
    // Wait 50ms
  }
  assert_equals(document.timeline.currentTime, valueAtStart,
    'Timeline time does not change within an animation frame');
  return waitForAnimationFrames(1).then(() => {
    assert_greater_than(document.timeline.currentTime, valueAtStart,
      'Timeline time increases between animation frames');
  });
}, 'Timeline time increases once per animation frame');

async_test(t => {
  const iframe = document.createElement('iframe');
  iframe.width = 10;
  iframe.height = 10;

  iframe.addEventListener('load', t.step_func(() => {
    const iframeTimeline = iframe.contentDocument.timeline;
    const valueAtStart   = iframeTimeline.currentTime;
    const timeAtStart    = window.performance.now();
    while (iframe.contentWindow.performance.now() - timeAtStart < 50) {
      // Wait 50ms
    }
    assert_equals(iframeTimeline.currentTime, valueAtStart,
      'Timeline time within an iframe does not change within an '
      + ' animation frame');

    iframe.contentWindow.requestAnimationFrame(t.step_func_done(() => {
      assert_greater_than(iframeTimeline.currentTime, valueAtStart,
        'Timeline time within an iframe increases between animation frames');
      iframe.remove();
    }));
  }));

  document.body.appendChild(iframe);
}, 'Timeline time increases once per animation frame in an iframe');

async_test(t => {
  const startTime = document.timeline.currentTime;
  let firstRafTime;

  requestAnimationFrame(() => {
    t.step(() => {
      assert_greater_than_equal(document.timeline.currentTime, startTime,
                                'Timeline time should have progressed');
      firstRafTime = document.timeline.currentTime;
    });
  });

  requestAnimationFrame(() => {
    t.step(() => {
      assert_equals(document.timeline.currentTime, firstRafTime,
                    'Timeline time should be the same');
    });
    t.done();
  });
}, 'Timeline time should be the same for all RAF callbacks in an animation'
   + ' frame');

promise_test(async t => {
  // A microtask checkpoint is run as part of the process of updating
  // timelines to ensure that any microtasks queued during promise
  // resolution are handled before dispatching animation events.
  const div = createDiv(t);
  const events = [];
  let microtaskFrameTime = undefined;
  let finishFrameTime = undefined;
  const waitForMicrotask = (animation) => {
    return new Promise(resolve => {
      queueMicrotask(() => {
        events.push('microtask');
        microtaskFrameTime = document.timeline.currentTime;
        resolve();
      });
    });
  }
  const waitForFinishEvent = (animation) => {
    return new Promise(resolve => {
      animation.onfinish = (event) => {
        events.push('finish');
        finishFrameTime = event.timelineTime;
        resolve();
      };
    });
  }

  await waitForNextFrame();

  const animation = div.animate({ opacity: [0, 1] }, 1000 * MS_PER_SEC);
  const finishPromise = waitForFinishEvent(animation);
  await animation.ready;

  // Advance the timing to effect end, to asynchronously queue up a finish task.
  // Queue up microtask, which must be processed ahead of the finish event.
  // See "Perform a microtask checkpoint" step in
  // https://www.w3.org/TR/web-animations-1/#timelines.
  animation.currentTime = animation.effect.getComputedTiming().duration;
  const microtaskPromise = waitForMicrotask(animation);
  await Promise.all([finishPromise, microtaskPromise]);
  assert_array_equals(events, ['microtask', 'finish']);
  assert_times_equal(microtaskFrameTime, finishFrameTime);

}, 'Performs a microtask checkpoint after updating timelines');

async_test(t => {
  const div = createDiv(t);
  let readyPromiseRan = false;
  let finishedPromiseRan = false;
  div.style.animation = 'opacity-animation 1ms';
  let anim = div.getAnimations()[0];
  anim.ready.then(t.step_func(() => {
    readyPromiseRan = true;
  }));
  div.addEventListener('animationstart', t.step_func(() => {
    assert_true(readyPromiseRan, 'It should run ready promise before animationstart event');
  }));
  anim.finished.then(t.step_func(() => {
    finishedPromiseRan = true;
  }));
  div.addEventListener('animationend', t.step_func_done(() => {
    assert_true(finishedPromiseRan, 'It should run finished promise before animationend event');
  }));
}, 'Runs finished promise before animation events');
</script>