(() => { "use strict"; let cancelled = false; // Handle skip waiting message self.addEventListener('message', event => { if (event.data && event.data.type === 'SKIP_WAITING') { self.skipWaiting() } }) // Immediately install and activate self.addEventListener("install", () => { self.skipWaiting() }) // Claim clients on activation self.addEventListener('activate', event => { event.waitUntil( Promise.all([ clients.claim(), self.skipWaiting(), caches.keys().then(cacheNames => Promise.all(cacheNames.map(cacheName => caches.delete(cacheName))) ) ]) ) }) // Handle fetch events self.addEventListener("fetch", s => { const t = (s => { const { url: t } = s.request; // Only handle webtorrent requests if (!t.includes(self.registration.scope + "webtorrent/")) { return null; } // Handle keepalive requests if (t.includes(self.registration.scope + "webtorrent/keepalive/")) { return new Response(); } // Handle cancel requests if (t.includes(self.registration.scope + "webtorrent/cancel/")) { return new Response(new ReadableStream({ cancel() { cancelled = true; } })); } // Handle streaming requests return async function({ request: s }) { const { url: t, method: n, headers: o, destination: a } = s; // Get all window clients const l = await clients.matchAll({ type: "window", includeUncontrolled: true }); // Create message channel and wait for response const [r, i] = await new Promise(e => { for (const s of l) { const l = new MessageChannel, { port1: r, port2: i } = l; r.onmessage = ({ data: s }) => { e([s, r]) }; s.postMessage({ url: t, method: n, headers: Object.fromEntries(o.entries()), scope: self.registration.scope, destination: a, type: "webtorrent" }, [i]); } }); let c = null; const d = () => { i.postMessage(false); clearTimeout(c); i.onmessage = null; }; // Handle non-streaming response if (r.body !== "STREAM") { d(); return new Response(r.body, r); } // Handle streaming response return new Response(new ReadableStream({ pull: s => new Promise(t => { i.onmessage = ({ data: e }) => { if (e) { s.enqueue(e); } else { d(); s.close(); } t(); }; if (!cancelled && a !== "document") { clearTimeout(c); c = setTimeout(() => { d(); t(); }, 5000); } i.postMessage(true); }), cancel() { d(); } }), r); }(s); })(s); if (t) { s.respondWith(t); } }); })();