/* Cache the single page-owned app response before it registers the worker. */ (function (root) { 'use strict'; const doc=root.document, manifest=root.Lazy.manifest, key=root.Lazy.url('/app.js'); let domReady=doc.readyState==='complete', appSawDom=false; doc.addEventListener('DOMContentLoaded',()=>{domReady=true;appSawDom=typeof root.boot==='function';},{once:true}); function execute(node) { doc.head.append(node); node.remove(); delete root.Lazy.appResponse; // app.js keeps its original DOMContentLoaded listener. Async response // consumption can finish after that event; boot exactly once in that case. if(domReady)root.boot(); } async function start() { if(!manifest.appCache || !root.crypto?.subtle) { await new Promise((resolve,reject)=>{ const node=doc.createElement('script');node.src=key; node.onload=()=>{if(domReady&&!appSawDom)root.boot();resolve();};node.onerror=()=>reject(Error('Unable to load player')); doc.head.append(node); }); return; } const expected=manifest.files['/app.js'].h; let cache; try { cache=await root.caches?.open('ytplayer-assets'); } catch {} let response=await cache?.match(key); if(!response || response.headers.get('X-Asset-Hash')!==expected)response=await (root.Lazy.appResponse || root.fetch(key,{credentials:'same-origin'})); if(!response.ok || response.headers.get('X-Asset-Hash')!==expected)throw Error('Player asset hash mismatch'); const bytes=await response.clone().arrayBuffer(); const digest=new Uint8Array(await root.crypto.subtle.digest('SHA-256',bytes)); const hex=Array.from(digest,b=>b.toString(16).padStart(2,'0')).join(''); const permission="'sha256-"+root.btoa(String.fromCharCode(...digest))+"'"; if(hex.slice(0,10)!==expected || !doc.querySelector('meta[http-equiv="Content-Security-Policy"]').content.includes(permission))throw Error('Player body hash mismatch'); // CacheStorage may share a full quota with saved music. Never remove data // to make room; boot from these verified bytes even if caching is refused. try { await cache?.put(key,response); } catch(error) { root.console.warn('[app-cache]',error.message); } const node=doc.createElement('script');node.textContent=new root.TextDecoder().decode(bytes); execute(node); } const ready=start(); root.AppBootstrap={ready}; ready.catch(error=>root.console.error('[app-cache]',error.message)); })(typeof window!=='undefined'?window:globalThis);