diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /testing/web-platform/tests/scheduler/tentative | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/scheduler/tentative')
6 files changed, 523 insertions, 0 deletions
diff --git a/testing/web-platform/tests/scheduler/tentative/yield/yield-abort.any.js b/testing/web-platform/tests/scheduler/tentative/yield/yield-abort.any.js new file mode 100644 index 0000000000..e96694f5ab --- /dev/null +++ b/testing/web-platform/tests/scheduler/tentative/yield/yield-abort.any.js @@ -0,0 +1,85 @@ +'use strict'; + +promise_test(t => { + const signal = AbortSignal.abort(); + return scheduler.postTask(async () => { + const p = scheduler.yield({signal}); + await promise_rejects_dom(t, 'AbortError', p); + }); +}, 'yield() with an aborted signal'); + +promise_test(t => { + const controller = new TaskController(); + const signal = controller.signal; + const task = scheduler.postTask(async () => { + controller.abort(); + const p = scheduler.yield({signal: 'inherit'}); + await promise_rejects_dom(t, 'AbortError', p); + }, {signal}); + return promise_rejects_dom(t, 'AbortError', task); +}, 'yield() with an aborted signal (inherit signal)'); + +promise_test(t => { + const controller = new TaskController(); + const signal = controller.signal; + const task = scheduler.postTask(async () => { + controller.abort(); + const p = scheduler.yield({signal: 'inherit', priority: 'background'}); + await promise_rejects_dom(t, 'AbortError', p); + }, {signal}); + return promise_rejects_dom(t, 'AbortError', task); +}, 'yield() with an aborted signal (inherit signal priority override)'); + +promise_test(t => { + const controller = new TaskController(); + const signal = controller.signal; + const task = scheduler.postTask(async () => { + controller.abort(); + await scheduler.yield({priority: 'inherit'}); + }, {signal}); + return promise_rejects_dom(t, 'AbortError', task); +}, 'yield() with an aborted signal (inherit priority only)'); + +promise_test(t => { + const controller = new TaskController(); + const signal = controller.signal; + return scheduler.postTask(async () => { + scheduler.postTask(async () => {controller.abort();}, {priority: 'user-blocking'}); + t.step(() => assert_false(signal.aborted)); + const p = scheduler.yield({signal}); + await promise_rejects_dom(t, 'AbortError', p); + }); +}, 'yield() aborted in a separate task'); + +promise_test(t => { + const controller = new TaskController(); + const signal = controller.signal; + return scheduler.postTask(async () => { + scheduler.postTask(async () => {controller.abort();}, {priority: 'user-blocking'}); + t.step(() => assert_false(signal.aborted)); + const p = scheduler.yield({signal: 'inherit'}); + await promise_rejects_dom(t, 'AbortError', p); + }, {signal}); +}, 'yield() aborted in a separate task (inherit)'); + +promise_test(t => { + const controller = new TaskController(); + const signal = controller.signal; + return scheduler.postTask(async () => { + scheduler.postTask(async () => {controller.abort();}, {priority: 'user-blocking'}); + t.step(() => assert_false(signal.aborted)); + const p = scheduler.yield({signal: 'inherit', priority: 'background'}); + await promise_rejects_dom(t, 'AbortError', p); + }, {signal}); +}, 'yield() aborted in a separate task (inherit signal priority override)'); + +promise_test(t => { + const controller = new TaskController(); + const signal = controller.signal; + return scheduler.postTask(async () => { + scheduler.postTask(async () => {controller.abort();}, {priority: 'user-blocking'}); + t.step(() => assert_false(signal.aborted)); + await scheduler.yield({priority: 'inherit'}); + t.step(() => assert_true(signal.aborted)); + }, {signal}); +}, 'yield() aborted in a separate task (inherit priority only)'); diff --git a/testing/web-platform/tests/scheduler/tentative/yield/yield-inherit-across-promises.any.js b/testing/web-platform/tests/scheduler/tentative/yield/yield-inherit-across-promises.any.js new file mode 100644 index 0000000000..eaa0125a78 --- /dev/null +++ b/testing/web-platform/tests/scheduler/tentative/yield/yield-inherit-across-promises.any.js @@ -0,0 +1,65 @@ +'use strict'; + +function postInheritPriorityTestTask(config) { + const ids = []; + const task = scheduler.postTask(async () => { + await new Promise(resolve => setTimeout(resolve)); + await fetch('/common/blank.html'); + await new Promise(resolve => setTimeout(resolve)); + const subtask = scheduler.postTask(() => { ids.push('subtask'); }, {priority: config.subTaskPriority}); + await scheduler.yield(config.yieldOptions); + ids.push('yield'); + await subtask; + }, config.taskOptions); + return {task, ids} +} + +for (let priority of ['user-blocking', 'background']) { + const expected = priority == 'user-blocking' ? 'yield,subtask' : 'subtask,yield'; + promise_test(async t => { + const config = { + taskOptions: {priority}, + subTaskPriority: 'user-blocking', + yieldOptions: {priority: 'inherit'}, + }; + const {task, ids} = postInheritPriorityTestTask(config); + await task; + assert_equals(ids.join(), expected); + }, `yield() inherits priority (string) across promises (${priority})`); + + promise_test(async t => { + const signal = (new TaskController({priority})).signal; + const config = { + taskOptions: {signal}, + subTaskPriority: 'user-blocking', + yieldOptions: {signal: 'inherit'}, + }; + const {task, ids} = postInheritPriorityTestTask(config); + await task; + assert_equals(ids.join(), expected); + }, `yield() inherits priority (signal) across promises (${priority})`); + + promise_test(async t => { + const config = { + taskOptions: {priority}, + subTaskPriority: 'user-blocking', + yieldOptions: {signal: 'inherit'}, + }; + const {task, ids} = postInheritPriorityTestTask(config); + await task; + assert_equals(ids.join(), expected); + }, `yield() inherits priority (priority string with signal inherit) across promises (${priority})`); +} + +promise_test(async t => { + const controller = new TaskController(); + const signal = controller.signal; + return scheduler.postTask(async () => { + await new Promise(resolve => setTimeout(resolve)); + await fetch('/common/blank.html'); + await new Promise(resolve => setTimeout(resolve)); + controller.abort(); + const p = scheduler.yield({signal: 'inherit'}); + await promise_rejects_dom(t, 'AbortError', p); + }, {signal}); +}, `yield() inherits abort across promises`); diff --git a/testing/web-platform/tests/scheduler/tentative/yield/yield-priority-idle-callbacks.html b/testing/web-platform/tests/scheduler/tentative/yield/yield-priority-idle-callbacks.html new file mode 100644 index 0000000000..d47e8c5eba --- /dev/null +++ b/testing/web-platform/tests/scheduler/tentative/yield/yield-priority-idle-callbacks.html @@ -0,0 +1,60 @@ +<!doctype html> +<title>Scheduler: yield inheritance in requestIdleCallback</title> +<link rel="help" href="https://github.com/WICG/scheduling-apis"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +'use strict'; + +// Queues a requestIdleCallback that schedules 2 user-visible tasks, 2 +// background tasks, another requestIdleCallback, and then yields 3 times using +// `yieldParams`. +// +// Returns {tasks, ids} where `tasks` is an array of promises associated with +// the tasks and `ids` is an array of task ids appended to by the scheduled +// tasks. +function postTestTasks(yieldParams) { + const ids = []; + const task = new Promise(resolve => { + requestIdleCallback(async () => { + ids.push('i1'); + + const subtasks = []; + subtasks.push(scheduler.postTask(() => { ids.push('uv1'); })); + subtasks.push(scheduler.postTask(() => { ids.push('uv2'); })); + subtasks.push(scheduler.postTask(() => { ids.push('bg1'); }, {priority: 'background'})); + subtasks.push(scheduler.postTask(() => { ids.push('bg2'); }, {priority: 'background'})); + subtasks.push(new Promise(resolve => { + requestIdleCallback(() => { + ids.push('i2'); + resolve(); + }); + })); + + for (let i = 1; i <= 3; i++) { + await scheduler.yield(yieldParams); + ids.push('y' + i); + } + await Promise.all(subtasks); + resolve(); + }); + }); + return {task, ids}; +} + +const expected_inherited_task_order = 'i1,uv1,uv2,y1,y2,y3,bg1,bg2,i2'; + +promise_test(async t => { + const {task, ids} = postTestTasks({priority: "inherit"}); + await task; + assert_equals(ids.join(), expected_inherited_task_order); +}, 'requestIdleCallback() yields at background priority when inheriting priority'); + +promise_test(async t => { + const {task, ids} = postTestTasks({signal: "inherit"}); + await task; + assert_equals(ids.join(), expected_inherited_task_order); +}, 'requestIdleCallback() yields at background priority when inheriting signal'); + +</script> diff --git a/testing/web-platform/tests/scheduler/tentative/yield/yield-priority-posttask.any.js b/testing/web-platform/tests/scheduler/tentative/yield/yield-priority-posttask.any.js new file mode 100644 index 0000000000..0700094dcf --- /dev/null +++ b/testing/web-platform/tests/scheduler/tentative/yield/yield-priority-posttask.any.js @@ -0,0 +1,193 @@ +'use strict'; + +// Posts a postTask task with `yieldyTaskParams` that yields 3 times using +// `yieldParams`, then posts 2 tasks of each priority, in descending order. +// +// Returns {tasks, ids} where `tasks` is an array of promises returned by +// postTask and `ids` is an array of task ids appended to by the scheduled +// tasks. +function postTestTasks(yieldyTaskParams, yieldParams) { + const tasks = []; + const ids = []; + + tasks.push(scheduler.postTask(async () => { + ids.push('y0'); + for (let i = 1; i < 4; i++) { + await scheduler.yield(yieldParams); + ids.push('y' + i); + } + }, yieldyTaskParams)); + + tasks.push( + scheduler.postTask(() => {ids.push('ub1')}, {priority: 'user-blocking'})); + tasks.push( + scheduler.postTask(() => {ids.push('ub2')}, {priority: 'user-blocking'})); + tasks.push( + scheduler.postTask(() => {ids.push('uv1')}, {priority: 'user-visible'})); + tasks.push( + scheduler.postTask(() => {ids.push('uv2')}, {priority: 'user-visible'})); + tasks.push( + scheduler.postTask(() => {ids.push('bg1')}, {priority: 'background'})); + tasks.push( + scheduler.postTask(() => {ids.push('bg2')}, {priority: 'background'})); + return {tasks, ids}; +} + +// Expected task orders for `postTestTasks` tasks. +const taskOrders = { + 'user-blocking': 'y0,y1,y2,y3,ub1,ub2,uv1,uv2,bg1,bg2', + 'user-visible': 'ub1,ub2,y0,y1,y2,y3,uv1,uv2,bg1,bg2', + 'background': 'ub1,ub2,uv1,uv2,y0,y1,y2,y3,bg1,bg2', +}; + +const priorityConfigs = [ + {options: {}, expected: taskOrders['user-visible']}, + {options: {priority: 'user-visible'}, expected: taskOrders['user-visible']}, + {options: {priority: 'user-blocking'}, expected: taskOrders['user-blocking']}, + {options: {priority: 'background'}, expected: taskOrders['background']}, +]; + +const fixedPrioritySignals = { + 'user-blocking': (new TaskController({priority: 'user-blocking'})).signal, + 'user-visible': (new TaskController({priority: 'user-visible'})).signal, + 'background': (new TaskController({priority: 'background'})).signal, +}; + +const signalConfigs = [ + { + options: {signal: fixedPrioritySignals['user-visible']}, + expected: taskOrders['user-visible'] + }, + { + options: {signal: fixedPrioritySignals['user-blocking']}, + expected: taskOrders['user-blocking'] + }, + { + options: {signal: fixedPrioritySignals['background']}, + expected: taskOrders['background'] + }, +]; + +promise_test(async t => { + for (const config of priorityConfigs) { + const {tasks, ids} = postTestTasks(config.options, config.options); + await Promise.all(tasks); + assert_equals(ids.join(), config.expected); + } +}, 'yield() with postTask tasks (priority option)'); + +promise_test(async t => { + for (const config of signalConfigs) { + const {tasks, ids} = postTestTasks(config.options, config.options); + await Promise.all(tasks); + assert_equals(ids.join(), config.expected); + } +}, 'yield() with postTask tasks (signal option)'); + +promise_test(async t => { + for (const config of priorityConfigs) { + const {tasks, ids} = + postTestTasks(config.options, {priority: 'inherit'}); + await Promise.all(tasks); + assert_equals(ids.join(), config.expected); + } +}, 'yield() with postTask tasks (inherit priority)'); + +promise_test(async t => { + for (const config of signalConfigs) { + const {tasks, ids} = + postTestTasks(config.options, {signal: 'inherit'}); + await Promise.all(tasks); + assert_equals(ids.join(), config.expected); + } +}, 'yield() with postTask tasks (inherit signal)'); + +promise_test(async t => { + const expected = 'y0,ub1,ub2,uv1,uv2,y1,y2,y3,bg1,bg2'; + const {tasks, ids} = postTestTasks( + {priority: 'user-blocking'}, {priority: 'background'}); + await Promise.all(tasks); + assert_equals(ids.join(), expected); +}, 'yield() with different priority from task (priority)'); + +promise_test(async t => { + const expected = 'y0,ub1,ub2,uv1,uv2,y1,y2,y3,bg1,bg2'; + const bgSignal = (new TaskController({priority: 'background'})).signal; + const {tasks, ids} = + postTestTasks({priority: 'user-blocking'}, {signal: bgSignal}); + await Promise.all(tasks); + assert_equals(ids.join(), expected); +}, 'yield() with different priority from task (signal)'); + +promise_test(async t => { + const bgSignal = (new TaskController({priority: 'background'})).signal; + const {tasks, ids} = postTestTasks( + {priority: 'user-blocking'}, + {signal: bgSignal, priority: 'user-blocking'}); + await Promise.all(tasks); + assert_equals(ids.join(), taskOrders['user-blocking']); +}, 'yield() priority overrides signal'); + +promise_test(async t => { + const ids = []; + + const controller = new TaskController(); + const signal = controller.signal; + + await scheduler.postTask(async () => { + ids.push('y0'); + + const subtasks = []; + subtasks.push(scheduler.postTask(() => { ids.push('uv1'); })); + subtasks.push(scheduler.postTask(() => { ids.push('uv2'); })); + + // 'user-visible' continuations. + await scheduler.yield({signal: 'inherit'}); + ids.push('y1'); + await scheduler.yield({signal: 'inherit'}); + ids.push('y2'); + + controller.setPriority('background'); + + // 'background' continuations. + await scheduler.yield({signal: 'inherit'}); + ids.push('y3'); + await scheduler.yield({signal: 'inherit'}); + ids.push('y4'); + + await Promise.all(subtasks); + }, {signal}); + + assert_equals(ids.join(), 'y0,y1,y2,uv1,uv2,y3,y4'); +}, 'yield() with TaskSignal has dynamic priority') + +promise_test(async t => { + const ids = []; + + await scheduler.postTask(async () => { + ids.push('y0'); + + const subtasks = []; + subtasks.push(scheduler.postTask(() => { ids.push('ub1'); }, {priority: 'user-blocking'})); + subtasks.push(scheduler.postTask(() => { ids.push('uv1'); })); + + // Ignore inherited signal (user-visible continuations). + await scheduler.yield(); + ids.push('y1'); + await scheduler.yield(); + ids.push('y2'); + + subtasks.push(scheduler.postTask(() => { ids.push('ub2'); }, {priority: 'user-blocking'})); + subtasks.push(scheduler.postTask(() => { ids.push('uv2'); })); + + // Now use inherited signal (user-blocking continuations). + await scheduler.yield({signal: 'inherit'}); + ids.push('y3'); + await scheduler.yield({signal: 'inherit'}); + ids.push('y4'); + + await Promise.all(subtasks); + }, {priority: 'user-blocking'}); + + assert_equals(ids.join(), 'y0,ub1,y1,y2,y3,y4,ub2,uv1,uv2'); +}, 'yield() mixed inheritance and default') diff --git a/testing/web-platform/tests/scheduler/tentative/yield/yield-priority-timers.any.js b/testing/web-platform/tests/scheduler/tentative/yield/yield-priority-timers.any.js new file mode 100644 index 0000000000..ff5a3d4b33 --- /dev/null +++ b/testing/web-platform/tests/scheduler/tentative/yield/yield-priority-timers.any.js @@ -0,0 +1,94 @@ +'use strict'; + +// Queues a zero ms timer that yields 3 times using `yieldParams`, then posts 2 +// more 0 ms timers. +// +// Returns {tasks, ids} where `tasks` is an array of promises associated with +// the timers and `ids` is an array of task ids appended to by the scheduled +// tasks. +function postTestTasks(yieldParams) { + const tasks = []; + const ids = []; + + tasks.push(new Promise(resolve => { + setTimeout(async () => { + ids.push('t1'); + for (let i = 1; i < 4; i++) { + await scheduler.yield(yieldParams); + ids.push('y' + i); + } + resolve(); + }); + })); + + tasks.push(new Promise(resolve => { + setTimeout(() => { ids.push('t2'); resolve(); }); + })); + tasks.push(new Promise(resolve => { + setTimeout(() => { ids.push('t3'); resolve(); }); + })); + return {tasks, ids}; +} + +// Expected task orders for `postTestTasks` tasks. +const taskOrders = { + 'user-blocking': 't1,y1,y2,y3,t2,t3', + 'user-visible': 't1,y1,y2,y3,t2,t3', + 'background': 't1,t2,t3,y1,y2,y3', +}; + +const priorityConfigs = [ + {options: {}, expected: taskOrders['user-visible']}, + {options: {priority: 'user-visible'}, expected: taskOrders['user-visible']}, + {options: {priority: 'user-blocking'}, expected: taskOrders['user-blocking']}, + {options: {priority: 'background'}, expected: taskOrders['background']}, +]; + +const fixedPrioritySignals = { + 'user-blocking': (new TaskController({priority: 'user-blocking'})).signal, + 'user-visible': (new TaskController({priority: 'user-visible'})).signal, + 'background': (new TaskController({priority: 'background'})).signal, +}; + +const signalConfigs = [ + { + options: {signal: fixedPrioritySignals['user-visible']}, + expected: taskOrders['user-visible'] + }, + { + options: {signal: fixedPrioritySignals['user-blocking']}, + expected: taskOrders['user-blocking'] + }, + { + options: {signal: fixedPrioritySignals['background']}, + expected: taskOrders['background'] + }, +]; + +promise_test(async t => { + for (const config of priorityConfigs) { + const {tasks, ids} = postTestTasks(config.options); + await Promise.all(tasks); + assert_equals(ids.join(), config.expected); + } +}, 'yield() with timer tasks (priority option)'); + +promise_test(async t => { + for (const config of signalConfigs) { + const {tasks, ids} = postTestTasks(config.options); + await Promise.all(tasks); + assert_equals(ids.join(), config.expected); + } +}, 'yield() with timer tasks (signal option)'); + +promise_test(async t => { + const {tasks, ids} = postTestTasks({priority: 'inherit'}); + await Promise.all(tasks); + assert_equals(ids.join(), taskOrders['user-visible']); +}, 'yield() with timer tasks (inherit priority)'); + +promise_test(async t => { + const {tasks, ids} = postTestTasks({signal: 'inherit'}); + await Promise.all(tasks); + assert_equals(ids.join(), taskOrders['user-visible']); +}, 'yield() with timer tasks (inherit signal)'); diff --git a/testing/web-platform/tests/scheduler/tentative/yield/yield-then-detach.html b/testing/web-platform/tests/scheduler/tentative/yield/yield-then-detach.html new file mode 100644 index 0000000000..835f9e7a62 --- /dev/null +++ b/testing/web-platform/tests/scheduler/tentative/yield/yield-then-detach.html @@ -0,0 +1,26 @@ +<!doctype html> +<title>Scheduler: yield in Detached Scheduler</title> +<link rel="help" href="https://github.com/WICG/scheduling-apis"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +'use strict'; + +promise_test(async t => { + await new Promise(resolve => window.onload = resolve); + + const frame = document.body.appendChild(document.createElement('iframe')); + const iframeDOMException = frame.contentWindow.DOMException; + const iframeScheduler = frame.contentWindow.scheduler; + + let didRun = false; + iframeScheduler.yield().then(() => { didRun = true; }); + + document.body.removeChild(frame); + await promise_rejects_dom(t, 'NotSupportedError', iframeDOMException, iframeScheduler.yield()); + await new Promise(resolve => t.step_timeout(resolve, 10)); + assert_false(didRun, 'The continuation should not have run.'); +}, 'Test scheduler.yield() from an iframe that is removed'); + +</script> |