Skip to content

Commit 073a34f

Browse files
Joone Hurchromium-wpt-export-bot
authored andcommitted
Add scriptCount to Long Animation Frame timing
Introduce the `scriptCount` member on `PerformanceLongAnimationFrameTiming`. It reports the number of top-level JavaScript entry points observed within the entry's interval, counted regardless of each entry point's individual duration. Test: external/wpt/long-animation-frame/loaf-script-count.tentative.html Bug: 534893134 Change-Id: Ia3e03132ab9254c4ed7b3d944f188d7683210e89 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/8115510 Reviewed-by: Noam Rosenthal <nrosenthal@google.com> Commit-Queue: Joone Hur <joonehur@microsoft.com> Cr-Commit-Position: refs/heads/main@{#1664728}
1 parent ecacb90 commit 073a34f

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<!DOCTYPE HTML>
2+
<meta charset=utf-8>
3+
<title>Long Animation Frame Timing: scriptCount</title>
4+
<meta name="timeout" content="long">
5+
<script src="/resources/testharness.js"></script>
6+
<script src="/resources/testharnessreport.js"></script>
7+
<script src="resources/utils.js"></script>
8+
9+
<body>
10+
<h1>Long Animation Frame: scriptCount</h1>
11+
<div id="log"></div>
12+
<script>
13+
// `scriptCount` is the number of top-level JavaScript entry points observed
14+
// within a long-animation-frame entry. Unlike `scripts`, it counts entry points
15+
// regardless of their individual duration, so it can exceed `scripts.length`
16+
// (which only lists entry points over the per-script reporting threshold).
17+
//
18+
// The member is gated on the LongAnimationFrameWorker feature; run with
19+
// --enable-blink-features=LongAnimationFrameWorker.
20+
function loaf_overlapping(t, getReferenceTime) {
21+
return new Promise(resolve => {
22+
const observer = new PerformanceObserver((entries, obs) => {
23+
const reference_time = getReferenceTime();
24+
if (reference_time === null) {
25+
return;
26+
}
27+
const entry = entries.getEntries().find(
28+
e => e.startTime < reference_time &&
29+
reference_time < e.startTime + e.duration);
30+
if (entry) {
31+
obs.disconnect();
32+
resolve(entry);
33+
}
34+
});
35+
t.add_cleanup(() => observer.disconnect());
36+
observer.observe({type: "long-animation-frame", buffered: true});
37+
});
38+
}
39+
40+
promise_test(async t => {
41+
await windowLoaded;
42+
assert_implements(
43+
"scriptCount" in PerformanceLongAnimationFrameTiming.prototype,
44+
"scriptCount is not supported " +
45+
"(run with --enable-blink-features=LongAnimationFrameWorker).");
46+
47+
const entry = await generate_long_animation_frame();
48+
assert_equals(typeof entry.scriptCount, "number",
49+
"scriptCount is a number");
50+
assert_greater_than_equal(entry.scriptCount, 1,
51+
"a long animation frame has at least one script entry point");
52+
assert_greater_than_equal(entry.scriptCount, entry.scripts.length,
53+
"scriptCount is never smaller than scripts.length");
54+
}, "A long animation frame reports scriptCount (>= scripts.length)");
55+
56+
promise_test(async t => {
57+
await windowLoaded;
58+
assert_implements(
59+
"scriptCount" in PerformanceLongAnimationFrameTiming.prototype,
60+
"scriptCount is not supported " +
61+
"(run with --enable-blink-features=LongAnimationFrameWorker).");
62+
63+
// Short entry points (< the 5 ms per-script threshold) do not appear in
64+
// `scripts`, but they still increment `scriptCount`. Produce a rendering
65+
// frame that runs a long callback together with several short tasks that
66+
// coalesce into the same frame, and assert scriptCount exceeds scripts.length.
67+
const SHORT_TASKS = 5;
68+
let found = false;
69+
for (let attempt = 0; attempt < 10 && !found; ++attempt) {
70+
let reference_time = null;
71+
const loaf = loaf_overlapping(t, () => reference_time);
72+
73+
// Several short tasks (< 5 ms each) scheduled before the rendering frame.
74+
// While the frame is pending they accumulate into the same LoAF but stay
75+
// out of `scripts`.
76+
for (let i = 0; i < SHORT_TASKS; ++i) {
77+
t.step_timeout(() => busy_wait(1), 0);
78+
}
79+
// A long rendering-frame callback anchors the LoAF and marks the reference
80+
// time in the middle of its busy run.
81+
requestAnimationFrame(() => {
82+
busy_wait(very_long_frame_duration / 2);
83+
reference_time = performance.now();
84+
busy_wait(very_long_frame_duration / 2);
85+
});
86+
87+
const entry = await Promise.race([
88+
loaf,
89+
new Promise(resolve => t.step_timeout(
90+
() => resolve(null), waiting_for_long_frame_timeout)),
91+
]);
92+
93+
if (entry && entry.scriptCount > entry.scripts.length) {
94+
found = true;
95+
}
96+
}
97+
assert_true(found,
98+
"scriptCount should exceed scripts.length when short entry points run " +
99+
"in the same long animation frame");
100+
}, "scriptCount counts short entry points that are absent from scripts");
101+
</script>
102+
</body>

0 commit comments

Comments
 (0)