ifAvailable.https.any.js (6397B)
1 // META: title=Web Locks API: ifAvailable option 2 // META: script=resources/helpers.js 3 // META: global=window,dedicatedworker,sharedworker,serviceworker 4 5 'use strict'; 6 7 promise_test(async t => { 8 const res = self.uniqueName(t); 9 let callback_called = false; 10 await navigator.locks.request(res, {ifAvailable: true}, async lock => { 11 callback_called = true; 12 assert_not_equals(lock, null, 'lock should be granted'); 13 }); 14 assert_true(callback_called, 'callback should be called'); 15 }, 'Lock request with ifAvailable - lock available'); 16 17 promise_test(async t => { 18 const res = self.uniqueName(t); 19 let callback_called = false; 20 await navigator.locks.request(res, async lock => { 21 // Request would time out if |ifAvailable| was not specified. 22 const result = await navigator.locks.request( 23 res, {ifAvailable: true}, async lock => { 24 callback_called = true; 25 assert_equals(lock, null, 'lock should not be granted'); 26 return 123; 27 }); 28 assert_equals(result, 123, 'result should be value returned by callback'); 29 }); 30 assert_true(callback_called, 'callback should be called'); 31 }, 'Lock request with ifAvailable - lock not available'); 32 33 promise_test(async t => { 34 const res = self.uniqueName(t); 35 let callback_called = false; 36 await navigator.locks.request(res, async lock => { 37 try { 38 // Request would time out if |ifAvailable| was not specified. 39 await navigator.locks.request(res, {ifAvailable: true}, async lock => { 40 callback_called = true; 41 assert_equals(lock, null, 'lock should not be granted'); 42 throw 123; 43 }); 44 assert_unreached('call should throw'); 45 } catch (ex) { 46 assert_equals(ex, 123, 'ex should be value thrown by callback'); 47 } 48 }); 49 assert_true(callback_called, 'callback should be called'); 50 }, 'Lock request with ifAvailable - lock not available, callback throws'); 51 52 promise_test(async t => { 53 const res = self.uniqueName(t); 54 let callback_called = false; 55 await navigator.locks.request(res, async lock => { 56 // Request with a different name - should be grantable. 57 await navigator.locks.request('different', {ifAvailable: true}, async lock => { 58 callback_called = true; 59 assert_not_equals(lock, null, 'lock should be granted'); 60 }); 61 }); 62 assert_true(callback_called, 'callback should be called'); 63 }, 'Lock request with ifAvailable - unrelated lock held'); 64 65 promise_test(async t => { 66 const res = self.uniqueName(t); 67 let callback_called = false; 68 await navigator.locks.request(res, {mode: 'shared'}, async lock => { 69 await navigator.locks.request( 70 res, {mode: 'shared', ifAvailable: true}, async lock => { 71 callback_called = true; 72 assert_not_equals(lock, null, 'lock should be granted'); 73 }); 74 }); 75 assert_true(callback_called, 'callback should be called'); 76 }, 'Shared lock request with ifAvailable - shared lock held'); 77 78 promise_test(async t => { 79 const res = self.uniqueName(t); 80 let callback_called = false; 81 await navigator.locks.request(res, {mode: 'shared'}, async lock => { 82 // Request would time out if |ifAvailable| was not specified. 83 await navigator.locks.request(res, {ifAvailable: true}, async lock => { 84 callback_called = true; 85 assert_equals(lock, null, 'lock should not be granted'); 86 }); 87 }); 88 assert_true(callback_called, 'callback should be called'); 89 }, 'Exclusive lock request with ifAvailable - shared lock held'); 90 91 promise_test(async t => { 92 const res = self.uniqueName(t); 93 let callback_called = false; 94 await navigator.locks.request(res, async lock => { 95 // Request would time out if |ifAvailable| was not specified. 96 await navigator.locks.request( 97 res, {mode: 'shared', ifAvailable: true}, async lock => { 98 callback_called = true; 99 assert_equals(lock, null, 'lock should not be granted'); 100 }); 101 }); 102 assert_true(callback_called, 'callback should be called'); 103 }, 'Shared lock request with ifAvailable - exclusive lock held'); 104 105 promise_test(async t => { 106 const res = self.uniqueName(t); 107 let callback_called = false; 108 await navigator.locks.request(res, async lock => { 109 callback_called = true; 110 const test_error = {name: 'test'}; 111 const p = navigator.locks.request( 112 res, {ifAvailable: true}, lock => { 113 assert_equals(lock, null, 'lock should not be available'); 114 throw test_error; 115 }); 116 assert_equals(Promise.resolve(p), p, 'request() result is a Promise'); 117 await promise_rejects_exactly(t, test_error, p, 'result should reject'); 118 }); 119 assert_true(callback_called, 'callback should be called'); 120 }, 'Returned Promise rejects if callback throws synchronously'); 121 122 promise_test(async t => { 123 const res = self.uniqueName(t); 124 let callback_called = false; 125 await navigator.locks.request(res, async lock => { 126 callback_called = true; 127 const test_error = {name: 'test'}; 128 const p = navigator.locks.request( 129 res, {ifAvailable: true}, async lock => { 130 assert_equals(lock, null, 'lock should not be available'); 131 throw test_error; 132 }); 133 assert_equals(Promise.resolve(p), p, 'request() result is a Promise'); 134 await promise_rejects_exactly(t, test_error, p, 'result should reject'); 135 }); 136 assert_true(callback_called, 'callback should be called'); 137 }, 'Returned Promise rejects if async callback yields rejected promise'); 138 139 // Regression test for: https://crbug.com/840994 140 promise_test(async t => { 141 const res1 = self.uniqueName(t); 142 const res2 = self.uniqueName(t); 143 let callback1_called = false; 144 await navigator.locks.request(res1, async lock => { 145 callback1_called = true; 146 let callback2_called = false; 147 await navigator.locks.request(res2, async lock => { 148 callback2_called = true; 149 }); 150 assert_true(callback2_called, 'callback2 should be called'); 151 152 let callback3_called = false; 153 await navigator.locks.request(res2, {ifAvailable: true}, async lock => { 154 callback3_called = true; 155 // This request would fail if the "is this grantable?" test 156 // failed, e.g. due to the release without a pending request 157 // skipping steps. 158 assert_not_equals(lock, null, 'Lock should be available'); 159 }); 160 assert_true(callback3_called, 'callback2 should be called'); 161 }); 162 assert_true(callback1_called, 'callback1 should be called'); 163 }, 'Locks are available once previous release is processed');