backend-resume-probe.mjs (2476B)
1 // Exercise actual page-facing request IDs, independently of private runtime IO. 2 export async function probeResume(backend){ 3 const worker=new Worker(new URL('./wasm-worker.js?backend='+backend,document.querySelector('script[type=module][src]').src),{type:'module'}),events=[]; 4 worker.onmessage=e=>events.push(e.data); 5 const assert=(ok,message)=>{if(!ok)throw Error(message);}; 6 const sleep=()=>new Promise(r=>setTimeout(r,40)); 7 const wait=async(predicate,start=0)=>{ 8 const deadline=performance.now()+10000; 9 while(performance.now()<deadline){const messages=events.slice(start);const failure=messages.find(x=>x.type==='error');if(failure)throw Error(failure.message);const found=messages.find(predicate);if(found)return found;await sleep();} 10 throw Error('Resume probe timed out'); 11 }; 12 try{ 13 worker.postMessage({type:'compile',source:'main = t "tricuIO" (t 1 (t 11 t))'}); 14 await wait(x=>x.type==='compiled'); 15 const run={type:'run',export:'main',arguments:[],output:'string',mode:'io',step:true}; 16 worker.postMessage(run);const step=await wait(x=>x.type==='state'&&x.state==='step'); 17 worker.postMessage({type:'resume',id:step.id,value:'wrong-kind'}); 18 worker.postMessage({type:'resume',id:step.id+999});await sleep(); 19 assert(!events.some(x=>x.type==='error'||x.type==='done'||x.state==='input'),'Malformed/stale step consumed pending wait'); 20 worker.postMessage({type:'resume',id:step.id});const input=await wait(x=>x.type==='state'&&x.state==='input'); 21 for(const value of [undefined,'bad\nline','\ud800','a'.repeat(257)])worker.postMessage({type:'resume',id:input.id,value}); 22 worker.postMessage({type:'resume',id:step.id,value:'stale'});await sleep(); 23 assert(!events.some(x=>x.type==='error'||x.type==='done'),'Invalid line consumed pending wait'); 24 worker.postMessage({type:'resume',id:input.id,value:'λ雪🙂'}); 25 assert((await wait(x=>x.type==='done')).result.value==='λ雪🙂','Resume value mismatch'); 26 const mark=events.length;worker.postMessage({...run,step:false}); 27 const next=await wait(x=>x.type==='state'&&x.state==='input',mark);assert(next.id>input.id,'Request IDs reused'); 28 worker.postMessage({type:'resume',id:input.id,value:'stale'});await sleep(); 29 assert(!events.slice(mark).some(x=>x.type==='done'),'Previous run token accepted'); 30 worker.postMessage({type:'resume',id:next.id,value:'fresh'}); 31 assert((await wait(x=>x.type==='done',mark)).result.value==='fresh','Fresh run failed'); 32 }finally{worker.terminate();} 33 }