iframe.html (1411B)
1 <!DOCTYPE html> 2 <title>Helper IFrame</title> 3 <script> 4 'use strict'; 5 6 // Map of lock_id => function that releases a lock. 7 8 const held = new Map(); 9 let next_lock_id = 1; 10 11 self.addEventListener('message', e => { 12 function respond(data) { 13 parent.postMessage(Object.assign(data, {rqid: e.data.rqid}), '*'); 14 } 15 16 switch (e.data.op) { 17 case 'request': 18 navigator.locks.request( 19 e.data.name, { 20 mode: e.data.mode || 'exclusive', 21 ifAvailable: e.data.ifAvailable || false 22 }, lock => { 23 if (lock === null) { 24 respond({ack: 'request', failed: true}); 25 return; 26 } 27 let lock_id = next_lock_id++; 28 let release; 29 const promise = new Promise(r => { release = r; }); 30 held.set(lock_id, release); 31 respond({ack: 'request', lock_id: lock_id}); 32 return promise 33 }); 34 break; 35 36 case 'release': 37 held.get(e.data.lock_id)(); 38 held.delete(e.data.lock_id); 39 respond({ack: 'release', lock_id: e.data.lock_id}); 40 break; 41 42 case 'client_id': 43 navigator.locks.request(e.data.name, async lock => { 44 const lock_state = await navigator.locks.query(); 45 const held_lock = 46 lock_state.held.filter(l => l.name === lock.name)[0]; 47 respond({ack: 'client_id', client_id: held_lock.clientId}); 48 }); 49 break; 50 } 51 }); 52 </script>