| // META: title=Web Locks API: Mixed Modes | |
| // META: script=resources/helpers.js | |
| // META: global=window,dedicatedworker,sharedworker,serviceworker | |
| 'use strict'; | |
| promise_test(async t => { | |
| let unblock; | |
| const blocked = new Promise(r => { unblock = r; }); | |
| const granted = []; | |
| // These should be granted immediately, and held until unblocked. | |
| navigator.locks.request('a', {mode: 'shared'}, async lock => { | |
| granted.push('a-shared-1'); await blocked; }); | |
| navigator.locks.request('a', {mode: 'shared'}, async lock => { | |
| granted.push('a-shared-2'); await blocked; }); | |
| navigator.locks.request('a', {mode: 'shared'}, async lock => { | |
| granted.push('a-shared-3'); await blocked; }); | |
| // This should be blocked. | |
| let exclusive_lock; | |
| const exclusive_request = navigator.locks.request('a', async lock => { | |
| granted.push('a-exclusive'); | |
| exclusive_lock = lock; | |
| }); | |
| // This should be granted immediately (different name). | |
| await navigator.locks.request('b', {mode: 'exclusive'}, lock => { | |
| granted.push('b-exclusive'); }); | |
| assert_array_equals( | |
| granted, ['a-shared-1', 'a-shared-2', 'a-shared-3', 'b-exclusive']); | |
| // Release the shared locks granted above. | |
| unblock(); | |
| // Now the blocked request can be granted. | |
| await exclusive_request; | |
| assert_equals(exclusive_lock.mode, 'exclusive'); | |
| assert_array_equals( | |
| granted, | |
| ['a-shared-1', 'a-shared-2', 'a-shared-3', 'b-exclusive', 'a-exclusive']); | |
| }, 'Lock requests are granted in order'); | |
| promise_test(async t => { | |
| const res = uniqueName(t); | |
| let [promise, resolve] = makePromiseAndResolveFunc(); | |
| const exclusive = navigator.locks.request(res, () => promise); | |
| for (let i = 0; i < 5; i++) { | |
| requestLockAndHold(t, res, { mode: "shared" }); | |
| } | |
| let answer = await navigator.locks.query(); | |
| assert_equals(answer.held.length, 1, "An exclusive lock is held"); | |
| assert_equals(answer.pending.length, 5, "Requests for shared locks are pending"); | |
| resolve(); | |
| await exclusive; | |
| answer = await navigator.locks.query(); | |
| assert_equals(answer.held.length, 5, "Shared locks are held"); | |
| assert_true(answer.held.every(l => l.mode === "shared"), "All held locks are shared ones"); | |
| }, 'Releasing exclusive lock grants multiple shared locks'); | |
| promise_test(async t => { | |
| const res = uniqueName(t); | |
| let [sharedPromise, sharedResolve] = makePromiseAndResolveFunc(); | |
| let [exclusivePromise, exclusiveResolve] = makePromiseAndResolveFunc(); | |
| const sharedReleasedPromise = Promise.all(new Array(5).fill(0).map( | |
| () => navigator.locks.request(res, { mode: "shared" }, () => sharedPromise)) | |
| ); | |
| const exclusiveReleasedPromise = navigator.locks.request(res, () => exclusivePromise); | |
| for (let i = 0; i < 5; i++) { | |
| requestLockAndHold(t, res, { mode: "shared" }); | |
| } | |
| let answer = await navigator.locks.query(); | |
| assert_equals(answer.held.length, 5, "Shared locks are held"); | |
| assert_true(answer.held.every(l => l.mode === "shared"), "All held locks are shared ones"); | |
| sharedResolve(); | |
| await sharedReleasedPromise; | |
| answer = await navigator.locks.query(); | |
| assert_equals(answer.held.length, 1, "An exclusive lock is held"); | |
| assert_equals(answer.held[0].mode, "exclusive"); | |
| exclusiveResolve(); | |
| await exclusiveReleasedPromise; | |
| answer = await navigator.locks.query(); | |
| assert_equals(answer.held.length, 5, "The next shared locks are held"); | |
| assert_true(answer.held.every(l => l.mode === "shared"), "All held locks are shared ones"); | |
| }, 'An exclusive lock between shared locks'); |