1/// <reference lib="webworker" /> 2console.log('service worker registration'); 3let sw = self; 4 5/** 6 * Push Notifications 7 */ 8 9sw.addEventListener('push', (event) => { 10 try { 11 const { title = 'Push Notification', ...options } = event?.data?.json() || {}; 12 event.waitUntil(sw.registration.showNotification(title, options)); 13 } 14 catch (error) { 15 console.error('Error processing push event:', error); 16 } 17}); 18 19sw.addEventListener('notificationclick', function (event) { 20 event.notification.close(); 21 22 const data = event?.notification?.data || {}; 23 let url = data?.url || '/'; 24 if (!data?.url) { 25 const auction_id = (data?.auction?.auction_id || data?.lot?.auction?.auction_id || data?.lot?.auction_id); 26 if (auction_id) { 27 url = '/auctions/' + auction_id; 28 } 29 30 const auction_lot_id = data?.lot?.auction_lot_id; 31 if (auction_lot_id) { 32 url = '/auctions/' + auction_id + '/lot/' + auction_lot_id; 33 } 34 } 35 36 event.waitUntil( 37 sw.clients.matchAll({ type: 'window', includeUncontrolled: true }).then((clients) => { 38 for (const client of clients) {
39 if (client.url.includes(url) && 'focus' in client) { 40 return client.focus(); 41 } 42 } 43 return sw.clients.openWindow(url); 44 }) 45 ); 46}); 47 48 49/** 50 * File Downloads 51 */ 52const WRITE = 0; 53const PULL = 0; 54const ERROR = 1; 55const ABORT = 1; 56const CLOSE = 2; 57const PING = 3; 58 59/** @implements {UnderlyingSource} */ 60class MessagePortSource { 61 62 /** @type {ReadableStreamController<any>} controller */ 63 controller; 64 65 /** @param {MessagePort} port */ 66 constructor (port) { 67 this.port = port; 68 this.port.onmessage = evt => this.onMessage(evt.data); 69 } 70 71 /** 72 * @param {ReadableStreamController<any>} controller 73 */ 74 start (controller) { 75 this.controller = controller; 76 } 77 78 pull () { 79 this.port.postMessage({ type: PULL }); 80 } 81 82 /** @param {Error} reason */ 83 cancel (reason) { 84 // Firefox can notify a cancel event, chrome can't 85 // https://bugs.chromium.org/p/chromium/issues/detail?id=638494 86 this.port.postMessage({ type: ERROR, reason: reason.message }); 87 this.port.close(); 88 } 89 90 /** @param {{ type: number; chunk: Uint8Array; reason: any; }} message */ 91 onMessage (message) { 92 // enqueue() will call pull() if needed when there's no backpressure 93 if (message.type === WRITE) { 94 this.controller.enqueue(message.chunk); 95 } 96 if (message.type === ABORT) { 97 this.controller.error(message.reason) 98 this.port.close(); 99 } 100 if (message.type === CLOSE) { 101 this.controller.close(); 102 this.port.close(); 103 } 104 } 105} 106 107sw.addEventListener('install', () => { 108 self.skipWaiting(); 109}); 110 111sw.addEventListener('activate', event => { 112 event.waitUntil(self.clients.claim()); 113}); 114 115const map = new Map(); 116 117// This should be called once per download 118// Each event has a dataChannel that the data will be piped through 119globalThis.addEventListener('message', evt => { 120 const data = evt.data; 121 if (data.url && data.readablePort) { 122 data.rs = new ReadableStream( 123 new MessagePortSource(evt.data.readablePort), 124 new CountQueuingStrategy({ highWaterMark: 4 }) 125 ); 126 map.set(data.url, data); 127 } 128}); 129 130globalThis.addEventListener('fetch', evt => { 131 const url = evt.request.url; 132 const data = map.get(url); 133 if (!data) return null; 134 map.delete(url); 135 evt.respondWith(new Response(data.rs, { 136 headers: data.headers 137 })); 138});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.