| // 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'); |