/** Imports compiled ESM directly: no TypeScript stripping or application bundler. */ import {createRegistry,builtinComponents,createDocument} from '/package/modules/canvas-core/index.js'; import {openProjectEngine} from '/package/modules/canvas-runtime/index.js'; import {createFoundryPersistence} from '/package/modules/canvas-service/index.js'; import {createBrowserStorage,createBrowserDigests,createBrowserImageDecoder} from '/package/modules/canvas-runtime/browser.js'; export async function run(){ const assert=(condition,message)=>{if(!condition)throw Error(message);},results=[]; const name=`headless-package-${crypto.randomUUID()}`,storage=createBrowserStorage({name}),digests=createBrowserDigests(),images=createBrowserImageDecoder(); const scope={accountId:crypto.randomUUID(),workspaceId:crypto.randomUUID(),projectId:crypto.randomUUID()},registry=createRegistry(builtinComponents()),document=createDocument(scope.projectId,[{id:scope.projectId,parent:null}],[]); const workerUrls=[],NativeWorker=globalThis.Worker;let active=0; globalThis.Worker=class extends NativeWorker{constructor(url,...args){super(url,...args);workerUrls.push(String(url));active++;this.live=true;}terminate(){if(this.live){this.live=false;active--;}super.terminate();}}; let engine; try{ const canvas=new OffscreenCanvas(4,2);canvas.getContext('2d').fillRect(0,0,4,2);const bytes=await canvas.convertToBlob({type:'image/png'}); const dimensions=await images.decode(bytes);assert(dimensions.width===4&&dimensions.height===2,'compiled image Worker dimensions'); const digest=await digests.digest(bytes),expected=[...new Uint8Array(await crypto.subtle.digest('SHA-256',await bytes.arrayBuffer()))].map(value=>value.toString(16).padStart(2,'0')).join('');assert(digest===expected,'compiled digest Worker SHA256'); assert(workerUrls.some(url=>url.endsWith('/image.worker.js'))&&workerUrls.some(url=>url.endsWith('/digest.worker.js')),'Worker URLs did not resolve emitted JS');assert(active===0,'compiled Workers leaked'); results.push('compiled image and digest module Workers load emitted JS, decode a real PNG, match native SHA256 and terminate'); const largeBytes=new Blob([new Uint8Array(16*1024*1024).fill(97)]),largeExpected=[...new Uint8Array(await crypto.subtle.digest('SHA-256',await largeBytes.arrayBuffer()))].map(value=>value.toString(16).padStart(2,'0')).join(''),started=performance.now(),largeDigest=await digests.digest(largeBytes),digestMs=performance.now()-started;assert(largeDigest===largeExpected&&active===0,'large compiled digest returned wrong bytes or retained its Worker');results.push('16 MiB compiled digest Worker matched SHA256 in '+digestMs.toFixed(1)+' ms (observation, not an SLA)'); // Keep networking explicitly held: verify the actual browser durability adapter // independently of an invented backend protocol implementation. const persistence={...createFoundryPersistence({registry,rootId:scope.projectId,workspaceId:scope.workspaceId,transport:async()=>{throw Error('unexpected network');}}),supportsRequest:()=>false}; const open=()=>openProjectEngine({scope,registry,document,versions:new Map([[scope.projectId,1]]),storage,persistence,createId:()=>crypto.randomUUID()}); engine=await open(); const target={id:crypto.randomUUID(),incarnation:1}; assert(engine.editor.dispatch({type:'element.create',element:{...target,ownerCanvasId:scope.projectId,componentId:'text',dataVersion:1,structure:'node',data:{title:'Packed recovery',text:'persisted'},geometry:{x:12,y:24,width:160,height:80,rotation:0}}}).status==='applied','compiled command rejected'); engine.sessions.attach('temporary-view'); await engine.settle();const revision=engine.getSnapshot().rootRevision;await engine.close();engine=await open(); assert(engine.getSnapshot().rootRevision>=revision,'compiled IndexedDB recovery revision regressed');assert(engine.getSnapshot().document.elements.get(target.id)?.data.text==='persisted','compiled durable document lost');assert(engine.getSnapshot().history.undo.length===1,'compiled durable history lost');assert(engine.sessions.getSnapshot().views.size===0,'transient sessions persisted');await engine.settle(); results.push('compiled browser storage and engine claim/release Web Locks and recover an edited document/history from IndexedDB without persisting views'); return results; }finally{await engine?.close();images.close();digests.close();storage.close();globalThis.Worker=NativeWorker;indexedDB.deleteDatabase(name);} }