diff --git a/testing/web-platform/tests/long-animation-frame/tentative/loaf-event-listener.html b/testing/web-platform/tests/long-animation-frame/tentative/loaf-event-listener.html
new file mode 100644
index 000000000000..6349c28b3202
--- /dev/null
+++ b/testing/web-platform/tests/long-animation-frame/tentative/loaf-event-listener.html
@@ -0,0 +1,33 @@
+
+
+
Long Animation Frame Timing: basic
+
+
+
+
+
+
+Long Animation Frame: event handlers
+
+
+
diff --git a/testing/web-platform/tests/long-animation-frame/tentative/loaf-idle.html b/testing/web-platform/tests/long-animation-frame/tentative/loaf-idle.html
new file mode 100644
index 000000000000..bc9f910bb148
--- /dev/null
+++ b/testing/web-platform/tests/long-animation-frame/tentative/loaf-idle.html
@@ -0,0 +1,36 @@
+
+
+Long Animation Frame Timing: requestIdleCallback
+
+
+
+
+
+
+Long Animation Frame: requestIdleCallback
+
+
+
diff --git a/testing/web-platform/tests/long-animation-frame/tentative/loaf-iframe-popup.html b/testing/web-platform/tests/long-animation-frame/tentative/loaf-iframe-popup.html
index 83def5729984..565273b6c6ad 100644
--- a/testing/web-platform/tests/long-animation-frame/tentative/loaf-iframe-popup.html
+++ b/testing/web-platform/tests/long-animation-frame/tentative/loaf-iframe-popup.html
@@ -15,7 +15,7 @@ const host_info = get_host_info();
const {ORIGIN, REMOTE_ORIGIN, HTTP_NOTSAMESITE_ORIGIN} = host_info;
promise_test(async t => {
- const executor = await prepare_exec_iframe(t, ORIGIN);
+ const [executor] = await prepare_exec_iframe(t, ORIGIN);
await expect_no_long_frame(() => executor.execute_script((duration) => {
const deadline = performance.now() + duration;
while (performance.now() < deadline) {}
@@ -23,7 +23,7 @@ promise_test(async t => {
}, 'A long busy wait without render in a same-origin iframe is not a long animation frame');
promise_test(async t => {
- const executor = await prepare_exec_iframe(t, HTTP_NOTSAMESITE_ORIGIN);
+ const [executor] = await prepare_exec_iframe(t, HTTP_NOTSAMESITE_ORIGIN);
await expect_no_long_frame(() => executor.execute_script((duration) => {
const deadline = performance.now() + duration;
while (performance.now() < deadline) {}
@@ -31,7 +31,7 @@ promise_test(async t => {
}, 'A long busy wait in a cross-origin iframe is not a long animation frame');
promise_test(async t => {
- const executor = await prepare_exec_iframe(t, ORIGIN);
+ const [executor] = await prepare_exec_iframe(t, ORIGIN);
await expect_long_frame(() => executor.execute_script(async (duration) => {
await new Promise(resolve => window.requestAnimationFrame(resolve));
const deadline = performance.now() + duration;
@@ -40,7 +40,7 @@ promise_test(async t => {
}, 'A long busy wait in a same-origin requestAnimationFrame is a long animation frame');
promise_test(async t => {
- const executor = await prepare_exec_popup(t, ORIGIN);
+ const [executor] = await prepare_exec_popup(t, ORIGIN);
await expect_no_long_frame(() => executor.execute_script((duration) => {
const deadline = performance.now() + duration;
while (performance.now() < deadline) {}
@@ -49,7 +49,7 @@ promise_test(async t => {
for (const origin of ["ORIGIN", "REMOTE_ORIGIN", "HTTP_NOTSAMESITE_ORIGIN"]) {
promise_test(async t => {
- const executor = await prepare_exec_iframe(t, host_info[origin]);
+ const [executor] = await prepare_exec_iframe(t, host_info[origin]);
const entry = await executor.execute_script(async (duration) => {
const entryPromise = new Promise(resolve => new PerformanceObserver(list => {
resolve(list.getEntries(0));
diff --git a/testing/web-platform/tests/long-animation-frame/tentative/loaf-promise.html b/testing/web-platform/tests/long-animation-frame/tentative/loaf-promise.html
new file mode 100644
index 000000000000..3e936ed04af9
--- /dev/null
+++ b/testing/web-platform/tests/long-animation-frame/tentative/loaf-promise.html
@@ -0,0 +1,40 @@
+
+
+Long Animation Frame Timing: basic
+
+
+
+
+
+
+
+Long Animation Frame: promise resolvers
+
+
+
diff --git a/testing/web-platform/tests/long-animation-frame/tentative/loaf-script-block.html b/testing/web-platform/tests/long-animation-frame/tentative/loaf-script-block.html
new file mode 100644
index 000000000000..f896a737ce7c
--- /dev/null
+++ b/testing/web-platform/tests/long-animation-frame/tentative/loaf-script-block.html
@@ -0,0 +1,47 @@
+
+
+Long Animation Frame Timing: basic
+
+
+
+
+
+
+Long Animation Frame: script blocks
+
+
+
diff --git a/testing/web-platform/tests/long-animation-frame/tentative/loaf-script-window-attribution.html b/testing/web-platform/tests/long-animation-frame/tentative/loaf-script-window-attribution.html
new file mode 100644
index 000000000000..001bb537f79d
--- /dev/null
+++ b/testing/web-platform/tests/long-animation-frame/tentative/loaf-script-window-attribution.html
@@ -0,0 +1,62 @@
+
+
+
+Long Animation Frame Timing: window attribution
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/long-animation-frame/tentative/loaf-user-callback.html b/testing/web-platform/tests/long-animation-frame/tentative/loaf-user-callback.html
new file mode 100644
index 000000000000..bc8fdd05e10f
--- /dev/null
+++ b/testing/web-platform/tests/long-animation-frame/tentative/loaf-user-callback.html
@@ -0,0 +1,52 @@
+
+
+Long Animation Frame Timing: basic
+
+
+
+
+
+
+Long Animation Frame: user callbacks
+
+
+
diff --git a/testing/web-platform/tests/long-animation-frame/tentative/resources/busy.js b/testing/web-platform/tests/long-animation-frame/tentative/resources/busy.js
new file mode 100644
index 000000000000..9d761b6de5ee
--- /dev/null
+++ b/testing/web-platform/tests/long-animation-frame/tentative/resources/busy.js
@@ -0,0 +1,4 @@
+(() => {
+ const deadline = performance.now() + 360;
+ while (performance.now() < deadline) {}
+})();
diff --git a/testing/web-platform/tests/long-animation-frame/tentative/resources/utils.js b/testing/web-platform/tests/long-animation-frame/tentative/resources/utils.js
index 47c138b1e62e..730545bbcc91 100644
--- a/testing/web-platform/tests/long-animation-frame/tentative/resources/utils.js
+++ b/testing/web-platform/tests/long-animation-frame/tentative/resources/utils.js
@@ -5,14 +5,18 @@ setup(() =>
const very_long_frame_duration = 360;
-function loaf_promise() {
+function loaf_promise(t) {
return new Promise(resolve => {
const observer = new PerformanceObserver(entries => {
const entry = entries.getEntries()[0];
- if (entry.duration >= very_long_frame_duration)
+ if (entry.duration >= very_long_frame_duration) {
+ observer.disconnect();
resolve(entry);
+ }
});
+ t.add_cleanup(() => observer.disconnect());
+
observer.observe({entryTypes: ['long-animation-frame']});
});
}
@@ -28,9 +32,9 @@ async function expect_long_frame(cb, t) {
await windowLoaded;
await new Promise(resolve => t.step_timeout(resolve, 0));
const timeout = new Promise((resolve, reject) =>
- t.step_timeout(() => reject("timeout"), no_long_frame_timeout));
- const receivedLongFrame = loaf_promise();
- await cb();
+ t.step_timeout(() => resolve("timeout"), no_long_frame_timeout));
+ const receivedLongFrame = loaf_promise(t);
+ await cb(t);
const entry = await Promise.race([
receivedLongFrame,
timeout
@@ -38,10 +42,24 @@ async function expect_long_frame(cb, t) {
return entry;
}
+async function expect_long_frame_with_script(cb, predicate, t) {
+ for (let i = 0; i < 10; ++i) {
+ const entry = await expect_long_frame(cb, t);
+ if (!entry.scripts.length)
+ continue;
+ for (const script of entry.scripts) {
+ if (predicate(script))
+ return [entry, script];
+ }
+ }
+
+ return [];
+}
+
async function expect_no_long_frame(cb, t) {
await windowLoaded;
for (let i = 0; i < 5; ++i) {
- const receivedLongFrame = loaf_promise();
+ const receivedLongFrame = loaf_promise(t);
await cb();
const result = await Promise.race([receivedLongFrame,
new Promise(resolve => t.step_timeout(() => resolve("timeout"),
@@ -62,7 +80,7 @@ async function prepare_exec_iframe(t, origin) {
iframe.src = url.href;
document.body.appendChild(iframe);
await new Promise(resolve => iframe.addEventListener("load", resolve));
- return new RemoteContext(uuid);
+ return [new RemoteContext(uuid), iframe];
}
@@ -72,5 +90,38 @@ async function prepare_exec_popup(t, origin) {
url.searchParams.set("uuid", uuid);
const popup = window.open(url);
t.add_cleanup(() => popup.close());
- return new RemoteContext(uuid);
+ return [new RemoteContext(uuid), popup];
+}
+function test_loaf_script(cb, name, type, label) {
+ promise_test(async t => {
+ const [entry, script] = await expect_long_frame_with_script(cb,
+ script => (script.type === type && script.duration >= very_long_frame_duration), t);
+
+ assert_true(!!entry, "Entry detected");
+ assert_equals(script.name, name);
+ assert_greater_than_equal(script.duration, very_long_frame_duration);
+ assert_greater_than_equal(entry.duration, script.duration);
+ assert_greater_than_equal(script.executionStart, script.startTime);
+ assert_greater_than_equal(script.startTime, entry.startTime)
+ assert_equals(script.window, window);
+ assert_equals(script.forcedStyleAndLayoutDuration, 0);
+ assert_equals(script.windowAttribution, "self");
+}, `LoAF script: ${name} ${type},${label ? ` ${label}` : ''}`);
+
+}
+
+function test_self_user_callback(cb, name) {
+ test_loaf_script(cb, name, "user-callback");
+}
+
+function test_self_event_listener(cb, name) {
+ test_loaf_script(cb, name, "event-listener");
+}
+
+function test_promise_script(cb, resolve_or_reject, name, label) {
+ test_loaf_script(cb, name, `${resolve_or_reject}-promise`, label);
+}
+
+function test_self_script_block(cb, name, type) {
+ test_loaf_script(cb, name, type);
}