// META: title=Web Locks API: Lock held until callback result resolves // META: script=resources/helpers.js // META: global=window,dedicatedworker,sharedworker,serviceworker 'use strict'; // For uncaught rejections. setup({allow_uncaught_exception: true}); function snooze(t, ms) { return new Promise(r => t.step_timeout(r, ms)); } promise_test(async t => { const res = uniqueName(t); const p = navigator.locks.request(res, lock => 123); assert_equals(Promise.resolve(p), p, 'request() result is a Promise'); assert_equals(await p, 123, 'promise resolves to the returned value'); }, 'callback\'s result is promisified if not async'); promise_test(async t => { const res = uniqueName(t); // Resolved when the lock is granted. let granted; const lock_granted_promise = new Promise(r => { granted = r; }); // Lock is held until this is resolved. let resolve; const lock_release_promise = new Promise(r => { resolve = r; }); const order = []; navigator.locks.request(res, lock => { granted(lock); return lock_release_promise; }); await lock_granted_promise; await Promise.all([ snooze(t, 50).then(() => { order.push('1st lock released'); resolve(); }), navigator.locks.request(res, () => { order.push('2nd lock granted'); }) ]); assert_array_equals(order, ['1st lock released', '2nd lock granted']); }, 'lock is held until callback\'s returned promise resolves'); promise_test(async t => { const res = uniqueName(t); // Resolved when the lock is granted. let granted; const lock_granted_promise = new Promise(r => { granted = r; }); // Lock is held until this is rejected. let reject; const lock_release_promise = new Promise((_, r) => { reject = r; }); const order = []; navigator.locks.request(res, lock => { granted(lock); return lock_release_promise; }); await lock_granted_promise; await Promise.all([ snooze(t, 50).then(() => { order.push('reject'); reject(new Error('this uncaught rejection is expected')); }), navigator.locks.request(res, () => { order.push('2nd lock granted'); }) ]); assert_array_equals(order, ['reject', '2nd lock granted']); }, 'lock is held until callback\'s returned promise rejects'); promise_test(async t => { const res = uniqueName(t); let callback_called = false; await navigator.locks.request(res, async lock => { await navigator.locks.request(res, {ifAvailable: true}, lock => { callback_called = true; assert_equals(lock, null, 'lock request should fail if held'); }); }); assert_true(callback_called, 'callback should have executed'); }, 'held lock prevents the same client from acquiring it');