worker.js (1408B)
1 'use strict'; 2 3 // Map of id => function that releases a lock. 4 5 const held = new Map(); 6 let next_lock_id = 1; 7 8 function processMessage(e) { 9 const target = this; 10 11 function respond(data) { 12 target.postMessage(Object.assign(data, {rqid: e.data.rqid})); 13 } 14 15 switch (e.data.op) { 16 case 'request': { 17 const controller = new AbortController(); 18 navigator.locks.request( 19 e.data.name, { 20 mode: e.data.mode || 'exclusive', 21 ifAvailable: e.data.ifAvailable || false, 22 signal: e.data.abortImmediately ? controller.signal : undefined, 23 }, lock => { 24 if (lock === null) { 25 respond({ack: 'request', failed: true}); 26 return; 27 } 28 let lock_id = next_lock_id++; 29 let release; 30 const promise = new Promise(r => { release = r; }); 31 held.set(lock_id, release); 32 respond({ack: 'request', lock_id: lock_id}); 33 return promise; 34 }).catch(e => { 35 respond({ack: 'request', error: e.name}); 36 }); 37 if (e.data.abortImmediately) { 38 controller.abort(); 39 } 40 break; 41 } 42 43 case 'release': 44 held.get(e.data.lock_id)(); 45 held.delete(e.data.lock_id); 46 respond({ack: 'release', lock_id: e.data.lock_id}); 47 break; 48 } 49 } 50 51 self.addEventListener('message', processMessage); 52 53 self.addEventListener('connect', ev => { 54 // Shared worker case 55 ev.ports[0].onmessage = processMessage; 56 });