tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

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 }