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
|
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Long Animation Frame Timing: queue time</title>
<meta name="timeout" content="long">
<script src=/resources/testdriver.js></script>
<script src=/resources/testdriver-actions.js></script>
<script src=/resources/testdriver-vendor.js></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/utils.js"></script>
<body>
<h1>Long Animation Frame: queue time</h1>
<div id="log"></div>
<script>
const INTERNAL_OVERHEAD_DELAY_EPSILON = 5;
promise_test(async t => {
const button = document.createElement("button");
button.innerText = "Click";
document.body.appendChild(button);
t.add_cleanup(() => button.remove());
const eventPromise = new Promise(resolve => button.addEventListener("click", event => {
busy_wait();
resolve(event);
}));
const entryPromise = new Promise(resolve => new PerformanceObserver(
(entryList, observer) => {
const scriptPredicate = s => s.name === "BUTTON.onclick";
const entry = entryList.getEntries().find(
e => e.scripts.length && e.scripts.find(scriptPredicate));
if (entry) {
resolve([entry, entry.scripts.find(scriptPredicate)]);
observer.disconnect();
}
}).observe({entryTypes: ["long-animation-frame"]}));
test_driver.click(button);
await new Promise(resolve => t.step_timeout(resolve, 0));
const event = await eventPromise;
const [entry, script] = await entryPromise;
assert_equals(script.desiredExecutionStart, event.timeStamp);
}, "event-listener entries desiredExecutionStart is the eventTimestamp");
promise_test(async t => {
const entryPromise = loaf_promise(t);
let timeBeforeSetup, timeAfterSetup;
const delay = 100;
const timeoutPromise = new Promise(resolve => {
timeBeforeSetup = performance.now();
t.step_timeout(() => {
busy_wait();
resolve();
}, delay);
timeAfterSetup = performance.now();
});
const entry = await entryPromise;
const script = entry.scripts.find(s => s.name === "TimerHandler:setTimeout");
assert_greater_than_equal(script.desiredExecutionStart, timeBeforeSetup + delay - 5);
assert_less_than_equal(script.desiredExecutionStart, timeAfterSetup + delay);
}, "desiredExecutionStart for setTimeout should be the setup time + delay");
promise_test(async t => {
const entryPromise = loaf_promise(t);
let timeBeforeSetup, timeAfterSetup;
const timeoutPromise = new Promise(resolve => {
timeBeforeSetup = performance.now();
scheduler.postTask(t.step_func(() => {
busy_wait();
resolve();
}));
timeAfterSetup = performance.now();
});
const entry = await entryPromise;
const script = entry.scripts.find(s => s.name === "SchedulerPostTaskCallback");
assert_greater_than_equal(script.desiredExecutionStart, timeBeforeSetup);
assert_less_than_equal(script.desiredExecutionStart, timeAfterSetup);
}, "desiredExecutionStart for Scheduler.postTask should be the time it was called");
promise_test(async t => {
const entryPromise = loaf_promise(t);
const rafPromise = new Promise(resolve => {
// We fire two rAFs to ensure both of them receive the same
// desiredExecutionStart
requestAnimationFrame(rafTime => {
busy_wait();
})
requestAnimationFrame(rafTime => {
busy_wait();
resolve(rafTime);
})
});
const entry = await entryPromise;
const rafTime = await rafPromise;
const scripts = entry.scripts.filter(
s => s.name === "FrameRequestCallback");
for (const script of scripts) {
assert_approx_equals(script.desiredExecutionStart, rafTime, INTERNAL_OVERHEAD_DELAY_EPSILON);
}
assert_approx_equals(entry.desiredRenderStart, rafTime, INTERNAL_OVERHEAD_DELAY_EPSILON);
}, "desiredExecutionStart & desiredRenderStart for requestAnimationFrame " +
"should be the same as the rAF argument");
promise_test(async t => {
const entryPromise = loaf_promise(t);
const timeBeforeWait = performance.now();
let timeAfterWait;
const rafPromise = new Promise(resolve => t.step_timeout(() => {
requestAnimationFrame(rafTime => {
busy_wait(very_long_frame_duration / 2);
resolve(rafTime);
});
busy_wait(very_long_frame_duration / 2);
timeAfterWait = performance.now();
}), 0);
const [entry, rafTime] = await Promise.all([entryPromise, rafPromise]);
assert_approx_equals(entry.desiredRenderStart, rafTime, INTERNAL_OVERHEAD_DELAY_EPSILON);
}, "desiredRenderStart and renderStart should reflect main thread delays");
</script>
</body>
|