mirror of
https://github.com/servo/servo.git
synced 2025-07-17 12:23:40 +01:00
109 lines
3.5 KiB
JavaScript
109 lines
3.5 KiB
JavaScript
// META: title=Web Locks API: navigator.locks.query ordering
|
|
// META: script=resources/helpers.js
|
|
|
|
'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');
|