const { test } = require('node:test'); const assert = require('node:assert/strict'); const { readFileSync } = require('node:fs'); const vm = require('node:vm'); function fixture(current, held = []) { const inserted = [], listeners = {}, writes = []; const manifest = { buildTag: 'own', groups: { core: { files: [] }, 'layout:classic': { files: ['/classic.css'] }, 'layout:glass-stage': { files: ['/glass.css', '/one.js', '/two.js'] }, 'feature:test': { contract:1, files: ['/one.js', '/two.js'] } }, files: { '/classic.css': {h:'c'}, '/glass.css':{h:'g'}, '/one.js':{h:'1'}, '/two.js':{h:'2'} } }; const doc = { readyState:'loading', documentElement: { dataset:{} }, getElementById: () => ({ textContent:JSON.stringify(manifest) }), querySelectorAll: () => [], createElement: tag => ({ tagName:tag.toUpperCase() }), write: value => writes.push(value), addEventListener: (t,f) => listeners[t]=f }; doc.head = { append: node => { inserted.push(node); queueMicrotask(() => node.onload?.()); } }; const root = { document:doc, localStorage:{ getItem:() => '{"settings":{"layout":"glass-stage"}}' }, console, Promise, URL, setTimeout, clearTimeout, navigator:{}, addEventListener(){} }; if (current) root.caches = { open: async () => ({ match: async key => key === '/__ytp_asset_state' ? new Response(JSON.stringify({current})) : held.includes(key) ? new Response('', {headers:{'X-Asset-Hash':key.split('=')[1]}}) : undefined }) }; root.window=root; root.globalThis=root; vm.runInNewContext(readFileSync(require.resolve('./lazy.js'),'utf8'), root); return { root, inserted, writes, listeners, manifest }; } test('external head bootstrap selects remembered CSS before paint without fetching a manifest', () => { const {root,writes}=fixture(); assert.equal(root.document.documentElement.dataset.layout,'glass-stage'); assert.deepEqual(writes,['']); }); test('lazy groups execute ordered classic scripts once, sharing concurrent calls and dependencies', async () => { const {root,inserted}=fixture(); const one=root.Lazy.load('feature:test'), two=root.Lazy.load('feature:test'); await Promise.all([one,two]); assert.deepEqual(inserted.map(n=>n.src),['/one.js?v=1','/two.js?v=2']); assert.equal(root.Lazy.loaded('feature:test'),true); await root.Lazy.load('layout:glass-stage'); assert.equal(inserted.filter(n=>n.tagName==='SCRIPT').length,2); }); test('failed injection can retry and proxy dispatches only after execution', async () => { const {root,inserted}=fixture(); const append=root.document.head.append; root.document.head.append=n=>{inserted.push(n);queueMicrotask(()=>n.onerror?.());}; await assert.rejects(root.Lazy.load('feature:test'),/one.js/); root.document.head.append=append; root.TestApi={open:value=>value+1}; const proxy=root.Lazy.proxy('feature:test',['open'],'TestApi'); assert.equal(await proxy.open(4),5); assert.equal(root.Lazy.url('/two.js'),'/two.js?v=2'); await assert.rejects(root.Lazy.load('feature:missing'),/Unknown/); }); test('executing groups are pinned even after a newer compatible manifest arrives', async () => { const f=fixture(); await f.root.Lazy.load('feature:test'); const newer=JSON.parse(JSON.stringify(f.manifest)); newer.files['/one.js'].h='new'; f.root.caches={open:async()=>({match:async key=>key==='/__ytp_asset_state'?new Response(JSON.stringify({current:newer})):new Response('',{headers:{'X-Asset-Hash':'new'}})})}; await f.root.Lazy.load('feature:test'); assert.deepEqual(f.inserted.map(n=>n.src),['/one.js?v=1','/two.js?v=2']); }); test('unexecuted compatible group immediately uses newly cached file URLs', async () => { const next=fixture().manifest; next.buildTag='new'; next.files['/one.js'].h='new'; const f=fixture(next,['/one.js?v=new','/two.js?v=2']); await f.root.Lazy.load('feature:test'); assert.deepEqual(f.inserted.map(n=>n.src),['/one.js?v=new','/two.js?v=2']); assert.equal(f.root.Lazy.reloadRequired,false); }); test('unexecuted incompatible group keeps its running-build N-1 URLs and requires reload', async () => { const next=fixture().manifest; next.buildTag='new'; next.files['/one.js'].h='new'; next.groups['feature:test'].contract=2; const f=fixture(next,['/one.js?v=new','/two.js?v=2']); const events=[]; f.root.CustomEvent=class {constructor(type,opts){this.type=type;this.detail=opts.detail}}; f.root.dispatchEvent=e=>events.push(e.type); await f.root.Lazy.load('feature:test'); assert.deepEqual(f.inserted.map(n=>n.src),['/one.js?v=1','/two.js?v=2']); assert.equal(f.root.Lazy.reloadRequired,true); assert.ok(events.includes('ytp-reload-required')); }); test('workers receive the pinned import URL map in their first message', () => { const f=fixture(), sent=[]; f.root.Worker=class { constructor(url){this.url=url;} postMessage(message,transfer){sent.push({message,transfer});} }; f.manifest.files['/worker.js']={h:'w'}; f.root.Lazy.manifest.files['/worker.js']={h:'w'}; const worker=f.root.Lazy.worker('/worker.js');worker.postMessage({op:'open'},['transfer']);worker.postMessage({op:'finish'}); assert.equal(worker.url,'/worker.js?v=w');assert.equal(sent[0].message.assetUrls.sha256,f.root.Lazy.url('/sha256.js'));assert.equal(sent[0].message.assetUrls.wasm,f.root.Lazy.url('/sha256-wasm.js'));assert.deepEqual(sent[0].transfer,['transfer']);assert.equal(sent[1].message.assetUrls,undefined); }); test('new group files with a changed dependency contract cannot run against the old dependency',async()=>{ const next=fixture().manifest;next.buildTag='next';next.groups['feature:test'].dependencies=['feature:dep'];next.groups['feature:dep']={contract:2,files:[]};next.files['/one.js'].h='new'; const f=fixture(next,['/one.js?v=new','/two.js?v=2']);f.root.Lazy.manifest.groups['feature:test'].dependencies=['feature:dep'];f.root.Lazy.manifest.groups['feature:dep']={contract:1,files:[]}; await f.root.Lazy.load('feature:test');assert.deepEqual(f.inserted.map(n=>n.src),['/one.js?v=1','/two.js?v=2']);assert.equal(f.root.Lazy.reloadRequired,true); }); test('classic chunk registry proxies use window.YT and keep the executed singleton pinned',async()=>{ const {root,inserted}=fixture();root.YT={TestApi:{open:n=>n+2}}; const proxy=root.Lazy.proxy('feature:test',['open'],'TestApi'); assert.equal(await proxy.open(3),5); const singleton=root.YT.TestApi;await root.Lazy.load('feature:test'); assert.equal(root.YT.TestApi,singleton);assert.equal(inserted.length,2); });