зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1822437 [wpt PR 39001] - Scheduling APIs: Implement scheduler.yield() prototype (part 1), a=testonly
Automatic update from web-platform-tests Scheduling APIs: Implement scheduler.yield() prototype (part 1) This adds the full API surface of scheduler.yield() to the IDL and implements all the options except inheritance (split off to keep the size reasonable). Details: - The scheduler's fixed and dynamic priority collections are mirrored for continuations, and algorithms have been updated to select the collection based on WebSchedulingQueueType. - When yield is called, the options are used to get a TaskSignal for the continuation, using the same algorithm as postTask(). This in turn is used to select the continuation queue which is used to schedule a DOMTaskContinuation (wrapper around resolving the yield() promise). - Passing "inherit" for the signal or priority option will CHECK. This will be implemented in a follow-up CL. - Tentative WPT test coverage is added for the implemented portion of the API. Bug: 979020 Change-Id: I601cd0ce801f02bdc236995124a36951431da5b9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4324266 Reviewed-by: Nate Chapin <japhet@chromium.org> Commit-Queue: Scott Haseley <shaseley@chromium.org> Cr-Commit-Position: refs/heads/main@{#1118256} -- wpt-commits: 8ab8d9d6ae09d7cf62657115a1fd4366b7de8b11 wpt-pr: 39001
This commit is contained in:
Родитель
f013d1378d
Коммит
5ded787e91
|
@ -215,6 +215,7 @@ SET TIMEOUT: resize-observer/resources/iframe.html
|
|||
SET TIMEOUT: resource-timing/resources/nested-contexts.js
|
||||
SET TIMEOUT: reporting/resources/first-csp-report.https.sub.html
|
||||
SET TIMEOUT: reporting/resources/second-csp-report.https.sub.html
|
||||
SET TIMEOUT: scheduler/tentative/yield/yield-priority-timers.any.js
|
||||
SET TIMEOUT: secure-contexts/basic-popup-and-iframe-tests.https.js
|
||||
SET TIMEOUT: service-workers/cache-storage/cache-abort.https.any.js
|
||||
SET TIMEOUT: service-workers/service-worker/activation.https.html
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
'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;
|
||||
return scheduler.postTask(async () => {
|
||||
scheduler.postTask(async () => {controller.abort();}, {priority: 'user-blocking'});
|
||||
assert_false(signal.aborted);
|
||||
const p = scheduler.yield({signal});
|
||||
await promise_rejects_dom(t, 'AbortError', p);
|
||||
});
|
||||
}, 'yield() aborted in a separate task');
|
|
@ -0,0 +1,111 @@
|
|||
'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 => {
|
||||
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');
|
|
@ -0,0 +1,82 @@
|
|||
'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)');
|
|
@ -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>
|
Загрузка…
Ссылка в новой задаче