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); }