blob: 3317cd02eb9a152f9a7be35b7052fcd082b752e9 [file] [log] [blame]
// META: title=Web Locks API: navigator.locks.query ordering
// META: script=resources/helpers.js
// META: global=window,dedicatedworker,sharedworker,serviceworker
'use strict';
// Grab a lock and hold until a release function is called. Resolves
// to a release function.
function getLockAndHoldUntilReleased(name, options) {
let release;
const promise = new Promise(resolve => { release = resolve; });
return new Promise(resolve => {
navigator.locks.request(name, options || {}, lock => {
resolve(release);
return promise;
}).catch(_ => {});
});
}
promise_test(async t => {
const res1 = uniqueName(t);
const res2 = uniqueName(t);
const res3 = uniqueName(t);
// These will never be released.
await Promise.all([
getLockAndHoldUntilReleased(res1),
getLockAndHoldUntilReleased(res2),
getLockAndHoldUntilReleased(res3)
]);
// These requests should be blocked.
navigator.locks.request(res3, {mode: 'shared'}, lock => {});
navigator.locks.request(res2, {mode: 'shared'}, lock => {});
navigator.locks.request(res1, {mode: 'shared'}, lock => {});
const state = await navigator.locks.query();
const relevant_pending_names = state.pending.map(lock => lock.name)
.filter(name => [res1, res2, res3].includes(name));
assert_array_equals(relevant_pending_names, [res3, res2, res1],
'Pending locks should appear in order.');
}, 'Requests appear in state in order made');
promise_test(async t => {
const res1 = uniqueName(t);
const res2 = uniqueName(t);
const res3 = uniqueName(t);
// These should be granted, and will be held until released.
const [release1, release2, release3] = await Promise.all([
getLockAndHoldUntilReleased(res1),
getLockAndHoldUntilReleased(res2),
getLockAndHoldUntilReleased(res3)
]);
// These requests should be blocked.
const requests = [
getLockAndHoldUntilReleased(res1),
getLockAndHoldUntilReleased(res2),
getLockAndHoldUntilReleased(res3)
];
// Ensure the requests have had a chance to get queued by
// waiting for something else to make it through the queue.
await navigator.locks.request(uniqueName(t), lock => {});
// Now release the previous holders.
release2();
release3();
release1();
// Wait until the subsequent requests make it through.
await Promise.all(requests);
const state = await navigator.locks.query();
const relevant_held_names = state.held.map(lock => lock.name)
.filter(name => [res1, res2, res3].includes(name));
assert_array_equals(relevant_held_names, [res2, res3, res1],
'Held locks should appear in granted order.');
}, 'Held locks appear in state in order granted');
promise_test(async t => {
const res1 = uniqueName(t);
const res2 = uniqueName(t);
const res3 = uniqueName(t);
// These should be granted, and will be held until stolen.
await Promise.all([
getLockAndHoldUntilReleased(res1),
getLockAndHoldUntilReleased(res2),
getLockAndHoldUntilReleased(res3)
]);
// Steal in a different order.
await Promise.all([
getLockAndHoldUntilReleased(res3, {steal: true}),
getLockAndHoldUntilReleased(res1, {steal: true}),
getLockAndHoldUntilReleased(res2, {steal: true})
]);
const state = await navigator.locks.query();
const relevant_held_names = state.held.map(lock => lock.name)
.filter(name => [res1, res2, res3].includes(name));
assert_array_equals(relevant_held_names, [res3, res1, res2],
'Held locks should appear in granted order.');
}, 'Held locks appear in state in order granted, including when stolen');