@volter/browser-substrate 0.1.115 → 0.1.116
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/package-packs.js +4 -4
- package/dist/cli/package-packs.js.map +1 -1
- package/dist/shell/assets/browser-opfs-filesystem-worker-CivfnvV7.js +3 -0
- package/dist/shell/assets/{browser-sandbox-bridge-CmMlTDpO.js → browser-sandbox-bridge-BOyO6Vq0.js} +2 -2
- package/dist/shell/assets/filesystem-host-B-fDKRNE.js +3 -0
- package/dist/shell/assets/{filesystem-host-D98WfBoD.js → filesystem-host-Cngy2ePX.js} +1 -1
- package/dist/shell/assets/filesystem-worker-BQAYsjDk.js +5 -0
- package/dist/shell/assets/{fork-worker-hBikLg_q.js → fork-worker-BOu5dHuR.js} +1 -1
- package/dist/shell/assets/{node-execution-worker-714dbca4282e90ae.js → node-execution-worker-e4ab9bf7f09262f8.js} +2 -2
- package/dist/shell/assets/{sandbox-qgjYY5Gr.js → sandbox-C41DorhH.js} +1 -1
- package/dist/shell/assets/{shell-C0qfPTpQ.js → shell-CdIq-SFl.js} +4 -4
- package/dist/shell/assets/worker-BCIFrV5h.js +816 -0
- package/dist/shell/assets/worker-program-worker-BEQYJYct.js +27 -0
- package/dist/shell/index.html +2 -2
- package/dist/shell/node-execution-worker.js +25 -9
- package/dist/shell/python-execution-worker.js +24 -8
- package/dist/shell/python-runtime-snapshot.bin +0 -0
- package/dist/shell/python-runtime-snapshot.json +1 -1
- package/dist/shell/sandbox.html +2 -2
- package/package.json +1 -1
- package/dist/shell/assets/browser-opfs-filesystem-worker-TLQsaODy.js +0 -3
- package/dist/shell/assets/filesystem-host-EfkgP9Jh.js +0 -3
- package/dist/shell/assets/filesystem-worker-51BLqPs5.js +0 -5
- package/dist/shell/assets/worker-BZ-Txq9L.js +0 -816
- package/dist/shell/assets/worker-program-worker-B_u8gbzh.js +0 -27
|
@@ -0,0 +1,816 @@
|
|
|
1
|
+
const Rn="EINSTALLREFUSED",Zs="[install-trap-record]";class eo extends Error{request;code=Rn;constructor(e){super(so(e)),this.request=e,this.name="InstallRefusedError"}}const to=Symbol.for("browser-substrate.install-recorder"),ro=Symbol.for("browser-substrate.install-trapped");function Bn(n){const e=globalThis;throw(e[ro]??=[]).push(n),e[to]?.(n),console.error(`[install-trap] ${n.door}: ${n.subject}`),console.info(`${Zs} ${JSON.stringify(n)}`),new eo(n)}function no(n){return typeof n!="object"||n===null?!1:n.code===Rn?!0:/^REFUSED \([^)]+\): /u.test(String(n.message??""))}function so(n){return[`REFUSED (${n.door}): ${n.subject}`,"","The tab never installs, downloads, extracts or builds a dependency, and never runs a setup step. Everything a","project uses reaches it prepared, with the image or from the catalog, and this was not. Nothing was attempted.","",...n.fix?[`To fix it: ${n.fix}`]:["To fix it, prepare the image again on a machine, from the project's folder:",""," npx @volter/browser-substrate dev"]].join(`
|
|
2
|
+
`)}const Dn=2019846480,Qt=6,ae=6,st=3,Gt=0,ht=1,xe=2,Cn=3,zn=4,Un=5,jn=0,qn=1,Wn=2,Yt=1,Jn=2,Hn=4,Vt=32,Pr=3,Ar=["file","directory","symlink"],oo=/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/u,io=new TextEncoder,ao=new TextDecoder;function Gn(n){let e=2166136261;for(let r=0;r<n.length;r+=1)e^=n.charCodeAt(r),e=Math.imul(e,16777619);return e>>>0}function dn(n,e){const r=[...n.keys()];for(const x of r)if(oo.test(x))throw new Error("A path in the store is not well-formed UTF-16.");const s=new Map;for(let x=0;x<r.length;x+=1)s.set(r[x],x);for(const x of e.keys())s.has(x)||(s.set(x,r.length),r.push(x));const c=r.length,d=new Map,u=new Uint32Array(c);let h=0;for(let x=0;x<c;x+=1){const k=r[x];let C=!0;for(let z=0;z<k.length;z+=1)if(k.charCodeAt(z)>=128){C=!1;break}C||d.set(x,io.encode(k)),u[x]=C?k.length:d.get(x).length,h+=u[x]}let w=0;for(const x of e.values())w+=x.size;let y=1;for(;y<c*2;)y<<=1;const A=Qt*4,g=xr(A+c*ae*4,8),E=g+c*st*8,B=E+y*4,D=B+w*4,M=new SharedArrayBuffer(xr(D+h,8));new Uint32Array(M,0,Qt).set([Dn,c,y,w,h,n.size]);const J=new Uint32Array(M,A,c*ae),L=new Float64Array(M,g,c*st),Q=new Uint32Array(M,E,y),P=new Uint32Array(M,B,w),R=new Uint8Array(M,D,h);let $=0,O=0;for(let x=0;x<c;x+=1){const k=r[x],C=x*ae,z=d.get(x);if(z)R.set(z,$);else for(let X=0;X<k.length;X+=1)R[$+X]=k.charCodeAt(X);const Y=u[x];J[C+Gt]=$,J[C+ht]=Y,$+=Y;let Ee=z?0:Vt;const N=n.get(k);if(N){Ee|=Yt|Ar.indexOf(N.type)<<Pr,N.pack&&(Ee|=Hn),J[C+Cn]=N.mode;const X=x*st;L[X+jn]=N.mtimeMs,L[X+qn]=N.offset,L[X+Wn]=N.length}const ne=e.get(k);if(ne){Ee|=Jn,J[C+zn]=O,J[C+Un]=ne.size;for(const X of ne){const We=s.get(`${k}/${X}`);if(We===void 0)throw new Error(`The store's children name ${k}/${X}, which its index does not hold.`);P[O++]=We}}J[C+xe]=Ee;let pe=Gn(k)&y-1;for(;Q[pe]!==0;)pe=pe+1&y-1;Q[pe]=x+1}if(O!==w)throw new Error("The shared index's children did not add up.");return M}function xr(n,e){return Math.ceil(n/e)*e}class Be{buffer;count;entryCount;records;numbers;table;childList;strings;mask;constructor(e){const r=new Uint32Array(e,0,Qt);if(r[0]!==Dn)throw new Error("Not a shared store index.");const[,s,c,d,u,h]=r;this.buffer=e,this.count=s,this.entryCount=h;const w=Qt*4,y=xr(w+s*ae*4,8),A=y+s*st*8,g=A+c*4,E=g+d*4;this.records=new Uint32Array(e,w,s*ae),this.numbers=new Float64Array(e,y,s*st),this.table=new Uint32Array(e,A,c),this.childList=new Uint32Array(e,g,d),this.strings=new Uint8Array(e,E,u),this.mask=c-1}find(e){let r=Gn(e)&this.mask;for(;;){const s=this.table[r];if(s===0)return-1;if(this.pathIs(s-1,e))return s-1;r=r+1&this.mask}}entry(e){const r=e*ae,s=this.records[r+xe];if(!(s&Yt))return;const c=e*st,d={type:Ar[s>>>Pr&3],mode:this.records[r+Cn],mtimeMs:this.numbers[c+jn],offset:this.numbers[c+qn],length:this.numbers[c+Wn]};return s&Hn&&(d.pack="packages"),d}typeAt(e){const r=this.records[e*ae+xe];return r&Yt?Ar[r>>>Pr&3]:void 0}hasEntry(e){return(this.records[e*ae+xe]&Yt)!==0}childNames(e){const r=e*ae;if(!(this.records[r+xe]&Jn))return;const s=this.records[r+zn],c=this.records[r+ht]+1,d=[];for(let u=0;u<this.records[r+Un];u+=1){const h=this.childList[s+u]*ae;d.push(this.decode(this.records[h+Gt]+c,this.records[h+ht]-c,(this.records[h+xe]&Vt)!==0))}return d}path(e){const r=e*ae;return this.decode(this.records[r+Gt],this.records[r+ht],(this.records[r+xe]&Vt)!==0)}decode(e,r,s){if(!s)return ao.decode(this.strings.slice(e,e+r));let c="";for(let d=e,u=e+r;d<u;d+=4096)c+=String.fromCharCode.apply(null,this.strings.subarray(d,Math.min(u,d+4096)));return c}pathIs(e,r){const s=e*ae,c=this.records[s+Gt],d=this.records[s+ht];if(!(this.records[s+xe]&Vt))return this.path(e)===r;if(d!==r.length)return!1;for(let u=0;u<d;u+=1)if(this.strings[c+u]!==r.charCodeAt(u))return!1;return!0}}const ue=Symbol("deleted");function Yn(n,e){return n===e||!!n&&!!e&&n.type===e.type&&n.offset===e.offset&&n.length===e.length&&n.pack===e.pack&&n.mode===e.mode&&n.mtimeMs===e.mtimeMs&&n.capacity===e.capacity}class Xe{base;overlay=new Map;delta=0;constructor(e){this.base=e}get[Symbol.toStringTag](){return"Map"}get size(){return this.base.entryCount+this.delta}get(e){const r=this.overlay.get(e);if(r!==void 0)return r===ue?void 0:r;const s=this.base.find(e);return s<0?void 0:this.base.entry(s)}typeOf(e){const r=this.overlay.get(e);if(r!==void 0)return r===ue?void 0:r.type;const s=this.base.find(e);return s<0?void 0:this.base.typeAt(s)}has(e){const r=this.overlay.get(e);if(r!==void 0)return r!==ue;const s=this.base.find(e);return s>=0&&this.base.hasEntry(s)}set(e,r){this.has(e)||(this.delta+=1);const s=this.base.find(e);return s>=0&&Yn(this.base.entry(s),r)?this.overlay.delete(e):this.overlay.set(e,r),this}delete(e){if(!this.has(e))return!1;const r=this.base.find(e);return r>=0&&this.base.hasEntry(r)?this.overlay.set(e,ue):this.overlay.delete(e),this.delta-=1,!0}clear(){throw new Error("A reader's index is not cleared; it is replaced.")}*entries(){for(const[e,r]of this.overlay)r!==ue&&(yield[e,r]);for(let e=0;e<this.base.count;e+=1){if(!this.base.hasEntry(e))continue;const r=this.base.path(e);this.overlay.has(r)||(yield[r,this.base.entry(e)])}}*keys(){for(const[e]of this.entries())yield e}*values(){for(const[,e]of this.entries())yield e}[Symbol.iterator](){return this.entries()}forEach(e,r){for(const[s,c]of this.entries())e.call(r,c,s,this)}*changed(){for(const[e,r]of this.overlay)r!==ue&&(yield[e,r])}*changes(){for(const[e,r]of this.overlay)yield[e,r===ue?null:r]}get overlaid(){return this.overlay.size}boundedChanges(){if(this.overlay.size>65536)return;const e=[];let r=0;for(const[s,c]of this.changes()){if(r+=s.length*2+128,r>8*1024*1024)return;e.push([s,c])}return e}}class Bt{base;overlay=new Map;constructor(e){this.base=e}get(e){const r=this.overlay.get(e);if(r!==void 0)return r===ue?void 0:r;const s=this.base.find(e),c=s<0?void 0:this.base.childNames(s);return c?new Set(c):void 0}mutable(e){const r=this.overlay.get(e);if(r!==void 0&&r!==ue)return r;const s=new Set(r===ue?[]:this.get(e)??[]);return this.overlay.set(e,s),s}delete(e){this.overlay.set(e,ue)}}const co="supercode-browser-filesystems",ve="packages",lo="state.json",un="/image-range-worker.js",fn="image-ranges.json",uo=2;function mr(n){const e=n;if(!e||e.version!==1||!Number.isSafeInteger(e.bytes)||e.bytes<0||!Array.isArray(e.parts)||e.image!==void 0&&(typeof e.image!="string"||!/^[a-f0-9]{16,64}$/u.test(e.image))||e.parts.length>1e5)throw new Error("Invalid immutable image ranges.");let r=0;for(const s of e.parts){if(!s||s.offset!==r||!Number.isSafeInteger(s.raw)||s.raw<0||!Number.isSafeInteger(s.bytes)||s.bytes<0||s.bytes>1024*1024*1024||s.raw>1024*1024*1024||typeof s.sha256!="string"||!/^[a-f0-9]{64}$/u.test(s.sha256)||typeof s.url!="string"||!/^\/substrate\/[A-Za-z0-9._/-]+$/u.test(s.url)||s.url.split("/").some(c=>c==="."||c===".."))throw new Error("Invalid immutable image part.");if(r+=s.raw,!Number.isSafeInteger(r))throw new Error("Immutable image ranges exceed the offset limit.")}if(r!==e.bytes)throw new Error("Immutable image ranges do not cover their reservation.");return e}const pn=new Map;class fo{ranges;directory;identity;receiptKey;client;worker;port;prefetchers=[];state;completed;firstRead;closed=!1;ready=!1;startup;cancelStartup;sharedCompletion;constructor(e,r,s,c,d,u){if(this.ranges=e,this.directory=r,this.identity=s,this.receiptKey=d,this.client=u,typeof Worker>"u"||typeof SharedArrayBuffer>"u")throw new Error("This browser cannot materialize an immutable image during a synchronous read.");if(this.state=new Int32Array(u?.state??new SharedArrayBuffer(e.parts.length*Int32Array.BYTES_PER_ELEMENT)),this.state.length!==e.parts.length)throw new Error("The image reader's line has the wrong range count.");const h=e.parts.length,w=c??new SharedArrayBuffer((2*h+1)*Int32Array.BYTES_PER_ELEMENT);if(w.byteLength!==h*Int32Array.BYTES_PER_ELEMENT&&w.byteLength!==(2*h+1)*Int32Array.BYTES_PER_ELEMENT)throw new Error("The image completion seed has the wrong range count.");this.completed=new Int32Array(w,0,h),this.firstRead=w.byteLength>h*Int32Array.BYTES_PER_ELEMENT?new Int32Array(w,h*Int32Array.BYTES_PER_ELEMENT,h+1):void 0,this.sharedCompletion=c!==void 0;for(const y of e.parts)Object.freeze(y);Object.freeze(e.parts),Object.freeze(e)}get completionBuffer(){return this.completed.buffer}get verifiedRanges(){return this.ranges}async initialize(){if(this.closed)throw new Error("This immutable image reader is closed.");if(this.ready)return;if(this.startup)return this.startup;let e=!1;for(let r=0;r<this.completed.length;r+=1)if(Atomics.load(this.completed,r)!==2){e=!0;break}if(!e){this.ready=!0,this.client?.port.close();return}if(this.client){const r=this.port=this.client.port;r.onmessage=s=>{s.data?.type!=="closing"||this.port!==r||(r.close(),this.port=void 0,this.closed||this.startMaterializer().catch(c=>console.warn("This process's image reader could not start its own materializer after its line closed.",c)))},r.start(),this.ready=!0;return}return this.startMaterializer()}startMaterializer(){const e=Date.now(),r=new Worker(un,{type:"module",name:"immutable-image-materializer"}),s=this.ready;return s||(this.worker=r),r.addEventListener("error",()=>this.fail()),r.addEventListener("messageerror",()=>this.fail()),this.startup=new Promise((c,d)=>{const u=()=>{clearTimeout(A),r.removeEventListener("message",y),r.removeEventListener("error",h),r.removeEventListener("messageerror",h),this.cancelStartup=void 0},h=()=>w(new Error("The immutable image materializer could not initialize; reload to retry.")),w=g=>{u(),r.terminate(),s||(this.closed=!0,this.fail()),d(g)},y=g=>{if(g.data?.identity===this.identity){if(g.data.type==="init-error"){w(new Error(`The immutable image materializer could not initialize: ${String(g.data.error)}`));return}g.data.type==="ready"&&(console.log(`[boot-trace] ${JSON.stringify({event:"materializer-ready",at:Date.now(),ms:Date.now()-e})}`),u(),this.ready=!0,this.worker=r,c())}},A=setTimeout(()=>w(new Error("The immutable image materializer did not initialize within 10 seconds; reload to retry.")),1e4);this.cancelStartup=w,r.addEventListener("message",y),r.addEventListener("error",h),r.addEventListener("messageerror",h);try{r.postMessage({type:"init",ranges:this.ranges,directory:this.directory,identity:this.identity,state:this.state.buffer,completed:this.completed.buffer,sharedCompletion:this.sharedCompletion,...this.receiptKey?{receiptKey:this.receiptKey}:{}})}catch(g){w(g instanceof Error?g:new Error(String(g)))}}),this.startup}readDigests(){const e=this.firstRead;if(!e)return;const r=this.ranges.parts.length,s=[];for(let c=0;c<r;c+=1){const d=Atomics.load(e,c),u=this.ranges.parts[c];d>0&&u.raw>0&&s.push([d,u.sha256])}return s.sort((c,d)=>c[0]-d[0]).map(([,c])=>c)}completedDigests(){const e=[];for(let r=0;r<this.completed.length;r+=1){const s=this.ranges.parts[r];s.raw>0&&Atomics.load(this.completed,r)===2&&e.push(s.sha256)}return e}prefetch(e,r=[]){if(this.closed||!this.ready||!this.worker)return{queued:0,done:Promise.resolve()};const s=new Map;for(let h=0;h<this.ranges.parts.length;h+=1){const w=this.ranges.parts[h];if(w.raw===0)continue;const y=s.get(w.sha256);y?y.push(h):s.set(w.sha256,[h])}const c=[];for(const h of new Set(e))for(const w of s.get(h)??[])Atomics.load(this.completed,w)!==2&&c.push(w);const d=r.length>0&&c.length>0?Math.min(r.length,8):Math.min(uo,Math.ceil(c.length/32)),u=[];for(let h=0;h<d;h+=1){const w=c.filter((E,B)=>B%d===h),y=new Worker(un,{type:"module",name:"immutable-image-prefetch"});this.prefetchers.push(y);let A;u.push(new Promise(E=>{A=E}));const g=()=>{y.terminate(),this.prefetchers=this.prefetchers.filter(E=>E!==y),A()};y.addEventListener("error",g),y.addEventListener("messageerror",g),y.addEventListener("message",E=>{E.data?.identity===this.identity&&(E.data.type==="ready"?y.postMessage(r.length>0?{type:"prefetch-stream",url:r[h]}:{type:"prefetch",indices:w}):(E.data.type==="prefetched"||E.data.type==="init-error")&&g())}),y.postMessage({type:"init",ranges:this.ranges,directory:this.directory,identity:this.identity,state:new SharedArrayBuffer(this.state.byteLength),completed:this.completed.buffer,sharedCompletion:!0,...this.receiptKey?{receiptKey:this.receiptKey}:{}})}return{queued:c.length,done:Promise.all(u).then(()=>{})}}ensure(e,r){if(this.closed)throw new Error("This immutable image reader is closed.");if(!this.ready)throw new Error("This immutable image reader has not finished asynchronous initialization.");if(r===0||e>=this.ranges.bytes)return;const s=Math.min(e+r,this.ranges.bytes);let c=0,d=this.ranges.parts.length;for(;c<d;){const u=c+d>>>1,h=this.ranges.parts[u];h.offset+h.raw<=e?c=u+1:d=u}for(let u=c;u<this.ranges.parts.length;u+=1){const h=this.ranges.parts[u];if(h.offset>=s)break;const w=this.firstRead;if(w&&Atomics.load(w,u)===0&&Atomics.compareExchange(w,u,0,Atomics.add(w,this.ranges.parts.length,1)+1),Atomics.load(this.completed,u)===2)continue;const y=this.worker??this.port;if(!y)throw new Error("This immutable image reader's line closed and its own materializer is still starting; retry the read.");y.postMessage({type:"read",index:u});const A=performance.now(),g=A+3e4;for(;Atomics.load(this.state,u)===0;){const D=g-performance.now();if(D<=0||Atomics.wait(this.state,u,0,D)==="timed-out")throw this.close(),new Error(`The image's immutable part ${h.url} did not arrive within 30 seconds; reload to retry.`)}const E=performance.now()-A,B=pn.get(this.identity)??{ranges:0,ms:0};if(B.ranges+=1,B.ms+=E,pn.set(this.identity,B),console.log(`[boot-trace] ${JSON.stringify({event:"image-blocked",at:Date.now(),reader:this.identity,index:u,range:h.sha256.slice(0,16),ms:Math.round(E)})}`),Atomics.load(this.state,u)!==2)throw new Error(`The image's immutable part ${h.url} could not be verified or stored; see the worker error and reload to retry.`)}}lineForReader(){const e=this.worker??this.port;if(this.closed||!this.ready||!e)return;const r=new MessageChannel,s=new SharedArrayBuffer(this.ranges.parts.length*Int32Array.BYTES_PER_ELEMENT);return e.postMessage({type:"client",port:r.port1,state:s},[r.port1]),{port:r.port2,state:s}}fail(){for(let e=0;e<this.state.length;e+=1)Atomics.compareExchange(this.state,e,0,-1)===0&&Atomics.notify(this.state,e)}close(){if(this.closed)return;if(this.closed=!0,this.cancelStartup){this.cancelStartup(new Error("This immutable image reader closed during initialization."));return}this.fail(),this.port?.close();const e=this.worker;e&&(e.postMessage({type:"closing"}),setTimeout(()=>e.terminate(),250));for(const r of this.prefetchers)r.dispatchEvent(new Event("error"));this.prefetchers=[]}}const yr="/packages",Dt="supercode-browser-packages",De=new TextEncoder,Ze=new TextDecoder("utf-8",{fatal:!0}),po=co,Ct="generations",hn="atomic-staging",et=lo,fe="index.json",_r="index-log.bin",tt="pack.bin",zt=8,wn=64*1024*1024,ie=1024*1024*1024,ho=.95,wo=["/workspace","/home","/opt"],Ce=0,mn=1,gr=1e6,yn=8*1024*1024,_n=250,mo=64*1024*1024,yo=256*1024*1024,gn=4*1024*1024,rt=493,Ut=420;function bn(n,e={}){const r=e.limits?.maxBytes,s=e.limits?.maxEntries??gr;if(r!==void 0&&(!Number.isSafeInteger(r)||r<1)||!Number.isSafeInteger(s)||s<1||s>gr)throw new Error("Invalid OPFS workspace limits.");let c=Number.MAX_SAFE_INTEGER,d,u,h=!1,w=!1,y=!1,A,g=0,E=0,B,D,M,b=new Map,J=new jt,L,Q,P,R,$,O,x=0,k,C=0;const z=new Map,Y=256*1024,Ee=32;let N=0,ne,pe=-1/0,X=0,We=0,F=0,U=0,Z=0,Oe=0,Ne=0,le,_t,he,Je=!1,it,$r=Promise.resolve(),He=0,V=!1,Ge=!1,K,Te=0,we=!1;function gt(){if(!(!K||we)){if(F>2147483647){bt();return}Atomics.store(K,mn,F)}}function bt(){!K||we||(we=!0,(Atomics.load(K,Ce)&1)===0&&Atomics.add(K,Ce,1))}function at(){Te+=1,Te===1&&K&&!we&&Atomics.add(K,Ce,1)}function ct(){Te-=1,!(Te>0||!K||we)&&(gt(),we||Atomics.add(K,Ce,1))}function Lr(){if(w)throw new Error("A store open for reading follows its owner's clock; it has none of its own.");return K||(K=new Int32Array(new SharedArrayBuffer(2*Int32Array.BYTES_PER_ELEMENT)),K[Ce]=Te>0||we?1:0,gt()),K.buffer}let se;const fs=8*1024*1024;let Rr=!1;function ps(t){if(w||!K||!M||Je||Te>0||we||V)return;const o=Atomics.load(K,Ce);if(o&1)return;if(t?.overlays&&b instanceof Xe){const l=b.boundedChanges();if(l)return tr({generation:M,index:b.base.buffer,changes:l,packBytes:N,logBytes:F,epoch:o,liveBytes:U,linked:g,linkedBytes:E})}if(se&&se.generation===M&&se.epoch===o&&F>=se.logBytes&&F-se.logBytes<=(t?.current?0:fs))return tr(se);let i;try{i=dn(b,ms())}catch(l){console.warn(`[pack-store] no reader seed: ${l instanceof Error?l.message:String(l)}`);return}return se={generation:M,index:i,packBytes:N,logBytes:F,epoch:o,liveBytes:U,linked:g,linkedBytes:E},ws(i),tr(se)}function tr(t){const o=e.packages?.imageCompletionSeed();return o?{...t,packagesImage:o}:t}function hs(){if(!(!P||!Q||!M||Je||Te>0||V))return{generation:M,rangesDigest:Q,completed:P.completionBuffer,...P.receiptKey?{metadata:{ranges:P.verifiedRanges,receiptKey:P.receiptKey}}:{}}}function ws(t){const o=[];if(b instanceof Xe)for(const[l,a]of b.changed())a.capacity!==void 0&&o.push([l,a]);else for(const[l,a]of b)a.capacity!==void 0&&o.push([l,a]);const i=new Be(t);b=new Xe(i),J=new Bt(i);for(const[l,a]of o)b.set(l,a)}function ms(){if(J instanceof jt)return J.map;const t=new Map;for(const o of b.keys()){const i=Le(o);if(i===o)continue;let l=t.get(i);l||(l=new Set,t.set(i,l)),l.add(o.slice(i.length+1))}return t}function ys(){!w||y||V||!k||At(F)}async function Et(t){if(V)throw new Error("This OPFS workspace is closing.");He+=1;let o,i=!1;try{return await t()}catch(l){throw i=!0,o=l,l}finally{if(He-=1,V&&He===0)try{an()}catch(l){throw i?new AggregateError([o,l],"OPFS operation and deferred close both failed."):l}}}async function kt(t){return ke(),He!==0?Promise.reject(new Error("Wait for the current OPFS storage operation before replacing its generation.")):(Ge=!0,Et(async()=>{try{return await t()}finally{Ge=!1}}))}function _s(t){if(V)throw new Error("This OPFS workspace is closing.");const o=b.get(t);if(!o||o.type==="directory")throw new Error(`OPFS workspace file does not exist: ${t}`);return St(o)}function gs(t,o,i){if(V)throw new Error("This OPFS workspace is closing.");const l=b.get(t);if(!l||l.type==="directory")throw new Error(`OPFS workspace file does not exist: ${t}`);const a=Math.min(Math.max(0,o),l.length),f=Math.min(Math.max(0,i),l.length-a);if(l.pack){const p=e.packages;if(!p)throw new Error("This store has no shared package store to read from.");return p.readExtent(l.offset+a,f)}return Pt(l.offset+a,f)}function St(t){if(t.pack){const o=e.packages;if(!o)throw new Error("This store has no shared package store to read from.");return o.readExtent(t.offset,t.length)}return Pt(t.offset,t.length)}function Pt(t,o){if(V)throw new Error("This OPFS workspace is closing.");const i=L;if(!i)throw new Error("OPFS filesystem worker is not initialized.");const l=new Uint8Array(o);if(o>0&&o<=Y&&t>=0&&t+o<=C){let a=0;for(;a<o;){const f=t+a,p=Math.floor(f/Y)*Y;let m=z.get(p);if(!m&&(m=new Uint8Array(Math.min(Y,C-p)),P?.ensure(p,m.byteLength),i.read(m,{at:p})!==m.byteLength))throw new Error("An OPFS package range could not be read completely.");z.delete(p),z.set(p,m),z.size>Ee&&z.delete(z.keys().next().value);const _=f-p,S=Math.min(o-a,m.byteLength-_);l.set(m.subarray(_,_+S),a),a+=S}return l}if(P?.ensure(t,o),o>0&&i.read(l,{at:t})!==o)throw new Error("An OPFS workspace file could not be read completely.");return l}async function bs(t,o={}){if(V&&u||!u&&He!==0)throw new Error("Wait for this OPFS workspace to finish closing before opening it again.");if(Je)throw new Error("This OPFS store is already opening a workspace.");if(u){if(D!==Cr(t))throw new Error("Close this OPFS store before opening another workspace.");return b.size>0}Je=!0,V=!1;const i=new AbortController;it=i;try{b=new Map,J=new jt,M=void 0,Q=void 0,A=void 0,le=void 0,he=void 0,N=F=U=Z=g=E=0,ye=void 0,Oe=Ne=X=We=0,pe=-1/0,D=Cr(t),w=o.readOnly===!0,$=w?o.imageCompletion:void 0,O=w?o.imageLine:void 0,y=w&&o.extentsOnly===!0,h=o.shared===!0||w,d=void 0;try{const p=await n.navigator.storage.estimate?.();p?.quota&&(c=Math.max(0,Math.floor(p.quota*ho)-(p.usage??0)))}catch{}h||await As(i.signal),i.signal.throwIfAborted();const l=await ks();i.signal.throwIfAborted();try{const p=await l.getDirectoryHandle(po,{create:!w});i.signal.throwIfAborted(),u=await p.getDirectoryHandle(D,{create:!w})}catch(p){if(i.signal.throwIfAborted(),w&&Qe(p))return!1;throw p}i.signal.throwIfAborted();let a=Lt(await $e(u,et));if(i.signal.throwIfAborted(),!a&&w)return await nr(),!1;if(!a&&h&&(await n.navigator.locks.request(Dt,{mode:"exclusive",signal:i.signal},async()=>{i.signal.throwIfAborted(),a=Lt(await $e(u,et)),i.signal.throwIfAborted(),a||(await nr(),await Gr({files:[],pack:new ArrayBuffer(0)}),await bo(u))}),i.signal.throwIfAborted(),!a))return A=await me(M,!1),i.signal.throwIfAborted(),!1;if(!a)return await nr(),i.signal.throwIfAborted(),!1;const f=async p=>{let m;try{m=await me(p.generation,!1)}catch(I){throw i.signal.throwIfAborted(),Qe(I)?new Error("The committed OPFS workspace generation is missing. Stored generations were retained.",{cause:I}):I}if(i.signal.throwIfAborted(),M=p.generation,x=p.initializedAt,Q=p.imageRanges,A=m,y)return D===ve&&n.navigator.locks?await n.navigator.locks.request(Dt,{mode:"shared",signal:i.signal},async()=>{await Ye(m),C=L.getSize()}):await Ye(m),i.signal.throwIfAborted(),!0;const _=w?o.seed:void 0;if(_&&_.generation===p.generation){const I=new Be(_.index);return b=new Xe(I),J=new Bt(I),N=_.packBytes,_.changes&&Dr({packBytes:_.packBytes,changes:_.changes}),await Ye(m),i.signal.throwIfAborted(),F=_.logBytes,{liveBytes:U,linked:g,linkedBytes:E}=_,Z=Math.max(0,N-U),Rr=!0,b.size>0}const S=w?void 0:await Js(m);if(i.signal.throwIfAborted(),S){const I=new Be(S.index);b=new Xe(I),J=new Bt(I),{packBytes:N,liveBytes:U,linked:g,linkedBytes:E}=S;const v=Atomics.load(new Int32Array(Lr()),Ce);se={generation:M,index:S.index,packBytes:N,liveBytes:U,linked:g,linkedBytes:E,logBytes:0,epoch:v}}else b=pr(await $e(m,fe)),i.signal.throwIfAborted(),Ke(),N=rr(b);await Ye(m),i.signal.throwIfAborted();const T=S?await Hs(S):0;return i.signal.throwIfAborted(),T&&(ye={generation:M,bytes:T},se&&(se.logBytes=T)),At(T,!!S),S?Z=Math.max(0,N-U):lt(),Jr(),h&&!w&&!S&&b.size>=1e4&&(Pe(),await ft(m,b,{access:k,bytes:F,packBytes:N})),h||(L.truncate(N),await Qr(u,hn,!0),await sr(M),i.signal.throwIfAborted(),Z>mo&&Z>U&&await Ls()),i.signal.throwIfAborted(),b.size>0};return h&&!w?await n.navigator.locks.request(Dt,{mode:"exclusive",signal:i.signal},async()=>{if(a=Lt(await $e(u,et)),!a)throw new Error("The committed package store state is missing. Stored data was retained.");return f(a)}):await f(a)}catch(l){const a=[l];try{Ve()}catch(f){a.push(f)}try{B?.()}catch(f){a.push(f)}throw B=void 0,u=void 0,a.length>1?new AggregateError(a,"OPFS workspace open and cleanup failed."):l}finally{Je=!1,it=void 0}}function Es(t){return Et(()=>Br(t?.whole===!0))}async function Br(t=!1){if(y)throw new Error("A store opened for its extents alone has no index to follow.");if(w&&u){const f=Lt(await $e(u,et));if(!f)throw new Error("The committed OPFS workspace state is missing. Stored data was retained.");if(f.generation!==M||t){const p=await me(f.generation,!1),m=pr(await $e(p,fe));N=rr(m),f.generation!==M&&(M=f.generation,x=f.initializedAt,Q=f.imageRanges,await Ye(p)),M=f.generation,A=p,b=m,Ke(),At(),lt();return}}const o=k;if(!o||!A)return;const i=o.getSize();let l=!1;i<F&&(b=pr(await $e(A,fe)),Ke(),N=rr(b),F=0,l=!0);const a=F;At(F),(l||F!==a)&<()}async function ks(){let t;for(let o=0;o<10;o+=1){it?.signal.throwIfAborted();try{return await n.navigator.storage.getDirectory()}catch(i){t=i,await new Promise(l=>setTimeout(l,200))}}throw t instanceof Error?t:new Error("This browser workspace's storage is unavailable.")}const Ss=1e4;async function te(t,o){let i;const l=it?.signal;for(let f=0;f<2;f+=1){l?.throwIfAborted();const p=t.createSyncAccessHandle({mode:"readwrite-unsafe"});let m,_,S=!1;try{const T=new Promise((v,W)=>{_=()=>W(l?.reason??new DOMException("Workspace open was cancelled.","AbortError")),l?.addEventListener("abort",_,{once:!0}),l?.aborted&&_()}),I=await Promise.race([p.then(v=>({access:v})).catch(v=>{i=v}),new Promise(v=>{m=setTimeout(()=>v(void 0),Ss)}),T]);if(l?.throwIfAborted(),I)return S=!0,I.access}finally{m!==void 0&&clearTimeout(m),_&&l?.removeEventListener("abort",_),S||p.then(T=>T.close(),()=>{}).catch(T=>console.error("Late workspace handle cleanup failed.",T))}if(i instanceof TypeError)throw new Error(`This browser cannot share a workspace's files between pages: its file access handles have no readwrite-unsafe mode (Chrome 121 or newer has one). ${i.message}`);await new Promise(T=>setTimeout(T,500))}const a=i instanceof Error?` (${i.message})`:"";throw new Error(`This browser workspace's ${o} is held by another page${a}.`)}async function Ye(t){Ve();const o=await t.getFileHandle(tt);L=await te(o,"store");try{if(L.getSize()<N)throw new Error("The committed OPFS workspace pack is incomplete. Stored data was retained.");const i=await t.getFileHandle(_r);if(k=await te(i,"record of changes"),F=k.getSize(),Q){const l=$,a=l&&l.generation===M&&l.rangesDigest===Q?l:void 0;let f,p;if(a?.metadata){if(f=mr(a.metadata.ranges),p=a.metadata.receiptKey,!/^[a-f0-9]{64}$/u.test(p))throw new Error("The owner's immutable receipt key is invalid.")}else{const _=await(await t.getFileHandle(fn)).getFile(),S=new Uint8Array(await _.arrayBuffer());if(await ge(S)!==Q)throw new Error("The committed immutable image ranges have changed. Stored data was retained.");f=mr(JSON.parse(Ze.decode(S))),p=await ge(De.encode(JSON.stringify(f)))}if(f.bytes>L.getSize())throw new Error("The immutable image reservation is incomplete. Stored data was retained.");const m=a?O:void 0;m||O?.port.close(),O=void 0,P=new fo(f,t,`${D}.${M}`,a?.completed,p,m),console.log(`[boot-trace] ${JSON.stringify({event:"image-reader-open",at:Date.now(),reader:`${D}.${M}`,offered:l!==void 0,shared:a!==void 0,...l&&!a?{offeredGeneration:l.generation,generation:M,rangesMatch:l.rangesDigest===Q}:{}})}`),await P.initialize(),R=f.image}}catch(i){throw Ve(),i}}function Ve(){P?.close(),P=void 0,R=void 0;const t=L,o=k;L=void 0,k=void 0,F=0,C=0,z.clear();try{t?.close()}finally{o?.close()}}function At(t=0,o=!1){const i=k;if(!i)throw new Error("OPFS filesystem worker is not initialized.");const l=i.getSize();if(l<=t){F=l;return}const a=new Uint8Array(l-t);if(i.read(a,{at:t})!==a.byteLength)throw new Error("The OPFS workspace index log could not be read.");const f=L?.getSize()??1/0,p=new DataView(a.buffer);let m=0;const _=a.byteLength;for(;m+zt<=_;){const S=p.getUint32(m,!0),T=p.getUint32(m+4,!0),I=m+zt;if(S===0||S>wn||I+S>_)break;const v=a.subarray(I,I+S);if(nn(v)!==T)break;let W;try{W=Vs(JSON.parse(Ze.decode(v)))}catch{break}if(W.packBytes>f)break;Dr(W,o),m=I+S}m!==_&&!h&&i.truncate(t+m),F=t+m}function Dr(t,o=!1){for(const[i,l]of t.changes){const a=b.get(i);if(l&&Yn(a,l)){vt(i);continue}o&&(a?.pack?(g-=1,E-=a.length):a&&(U-=a.length),l?.pack?(g+=1,E+=l.length):l&&(U+=l.length)),l===null?(b.delete(i),Ur(i)):(b.set(i,l),vt(i))}N=Math.max(N,t.packBytes)}function lt(){U=0,g=0,E=0;for(const t of b.values())t.pack?(g+=1,E+=t.length):U+=t.length;Z=Math.max(0,N-U)}function rr(t){let o=0;for(const i of t.values())i.pack||(o=Math.max(o,i.offset+i.length));return o}const Ps=5e3;async function As(t){if(!n.navigator.locks)return;if(!D)throw new Error("OPFS filesystem project is not initialized.");const o=new AbortController,i=setTimeout(()=>o.abort(),Ps);try{await new Promise((l,a)=>{n.navigator.locks.request(`supercode-browser-filesystem-${D}`,{mode:"exclusive",signal:t?AbortSignal.any([t,o.signal]):o.signal},async()=>{clearTimeout(i),l(),await new Promise(f=>{B=f})}).catch(()=>a(t?.aborted?t.reason:new Error("This browser workspace is already open in another tab.")))})}finally{clearTimeout(i)}}function Cr(t){if(typeof t!="string"||!/^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/u.test(t))throw new Error("OPFS filesystem projectId is invalid.");return t}async function Me(){if(!u)throw new Error("OPFS filesystem worker is not initialized.");return u}async function me(t,o){return(await(await Me()).getDirectoryHandle(Ct,{create:o})).getDirectoryHandle(t,{create:o})}async function nr(){let t;try{t=await(await Me()).getDirectoryHandle(Ct)}catch(o){if(Qe(o))return;throw o}for await(const o of t.entries())throw new Error("OPFS workspace state is missing but stored generations exist. Stored data was retained.")}async function sr(t){const o=await Me();let i;try{i=await o.getDirectoryHandle(Ct)}catch(l){if(Qe(l))return;throw l}for await(const[l]of i.entries())l!==t&&await Xr(i,l)}function ke(){if(V)throw new Error("This OPFS workspace is closing.");if(Ge)throw new Error("This OPFS workspace is replacing its generation; wait for that operation before writing.");if(w)throw new Error("This store is open for reading; its owner writes it.");if(he)throw he}async function xs(t){sn(t)}let or=!1,xt=0,ye,ir=!1;function zr(){if(xt>0)return;const t=ye&&ye.generation===M&&ye.bytes<=F?ye.bytes:0;F-t>yn&&!or&&(or=!0,(h?n.navigator.locks.request(Dt,{mode:"exclusive"},async()=>{if(!u||V)return;await Br();const i=ye,l=i&&i.generation===M&&i.bytes<=F?i.bytes:0;F-l>yn&&await Tt()}):Tt()).catch(i=>console.error("The workspace's log could not be checkpointed; it is replayed at the next open.",i)).finally(()=>{or=!1})),!h&&!ir&&Z>yo&&Z>U&&(ir=!0,Et(Rs).catch(o=>console.error("The workspace could not be compacted; it keeps its generation.",o)).finally(()=>{ir=!1}))}async function vs(t){ke(),xt+=1;try{return await t()}finally{xt-=1,xt===0&&!V&&u&&zr()}}function Is(t,o){const i=be(t.path);if(t.operation==="write"){if(b.get(i)?.type==="directory")throw new Error(`OPFS write target is a directory: ${i}`);if(!(t.content instanceof Uint8Array))throw new Error("OPFS write requires file content.");const a=t.content;if(a.byteLength>ie)throw new Error(`${i} is ${a.byteLength} bytes; an OPFS workspace file holds at most ${ie}.`);It(i,a.byteLength),Fe(i,o);const f=Nt(a);re(i,{type:t.symlink?"symlink":"file",mode:t.mode??b.get(i)?.mode??Ut,mtimeMs:t.mtimeMs??Date.now(),offset:f,length:a.byteLength},o);return}if(t.operation==="append"){const a=b.get(i);if(a&&a.type!=="file")throw new Error(`OPFS append target is not a file: ${i}`);if(!(t.content instanceof Uint8Array))throw new Error("OPFS append requires file content.");const f=t.content,p=(a?.length??0)+f.byteLength;if(p>ie)throw new Error(`${i} is ${p} bytes; an OPFS workspace file holds at most ${ie}.`);It(i,p),Fe(i,o);const m=t.mode??a?.mode??Ut,_=t.mtimeMs??Date.now(),S=a&&!a.pack?a.capacity??a.length:0;if(D!==ve&&a&&!a.pack&&a.length>0&&(p<=S||a.offset+S===N)){Ot(a.offset+a.length,f),re(i,{...a,mode:m,mtimeMs:_,length:p,capacity:Math.max(S,p)},o),Z-=Math.max(a.length,a.capacity??0),Oe-=1,Ne-=a.length;return}const T=new Uint8Array(p);a&&a.length>0&&T.set(St(a),0),T.set(f,p-f.byteLength);const I=Nt(T),v=Math.min(ie,Math.max(p,p*2,64*1024));v>p&&Hr(I+v),re(i,{type:"file",mode:m,mtimeMs:_,offset:I,length:p,capacity:v},o);return}if(t.operation==="write-at"){const a=b.get(i);if(a&&a.type!=="file")throw new Error(`OPFS write target is not a file: ${i}`);if(!(t.content instanceof Uint8Array))throw new Error("OPFS write requires file content.");const f=t.content,p=t.position,m=a?.length??0;if(f.byteLength===0&&a)return;const _=f.byteLength===0?m:Math.max(m,p+f.byteLength);if(_>ie)throw new Error(`${i} is ${_} bytes; an OPFS workspace file holds at most ${ie}.`);It(i,_),Fe(i,o);const S=t.mode??a?.mode??Ut,T=t.mtimeMs??Date.now(),I=a&&!a.pack?a.capacity??a.length:0;if(D!==ve&&a&&!a.pack&&m>0&&(_<=I||a.offset+I===N)){if(p>m&&Ot(a.offset+m,new Uint8Array(p-m)),_t&&p<m){const oe=Math.min(m,p+f.byteLength);_t.push([a.offset+p,Pt(a.offset+p,oe-p)])}Ot(a.offset+p,f),re(i,{...a,mode:S,mtimeMs:T,length:_,capacity:Math.max(I,_)},o),_!==m&&(Z-=Math.max(a.length,a.capacity??0),Oe-=1,Ne-=a.length);return}const v=new Uint8Array(_);a&&m>0&&v.set(St(a),0),f.byteLength>0&&v.set(f,p);const W=Nt(v),H=Math.min(ie,Math.max(_,_*2,64*1024));H>_&&Hr(W+H),re(i,{type:"file",mode:S,mtimeMs:T,offset:W,length:_,capacity:H},o);return}if(t.operation==="mkdir"){Fe(i,o);const a=b.get(i);if(a&&a.type!=="directory")throw new Error(`OPFS path is a file: ${i}`);re(i,{type:"directory",mode:t.mode??a?.mode??rt,mtimeMs:t.mtimeMs??a?.mtimeMs??Date.now(),offset:0,length:0},o);return}if(t.operation==="remove"){cr(i,o),Se().includes(i)&&re(i,{type:"directory",mode:rt,mtimeMs:Date.now(),offset:0,length:0},o);return}if(t.operation==="link"){Os(i,Wr(t.source),o);return}if(t.operation==="rename"){Ns(i,be(t.destination),o);return}const l=b.get(i);if(!l)throw new Error(`OPFS metadata target does not exist: ${i}`);re(i,{...l,mode:t.mode??l.mode,mtimeMs:t.mtimeMs??l.mtimeMs},o)}function re(t,o,i){const l=b.get(t);le&&!le.has(t)&&le.set(t,l);const a=l!==void 0&&l.type===o.type&&l.offset===o.offset&&l.length===o.length&&l.pack===o.pack;l&&!a&&(jr(l),l.type!=="directory"&&o.type!=="directory"&&l.length>0&&!l.pack&&(Oe+=1,Ne+=l.length)),b.set(t,o),vt(t),a||(o.pack?(g+=1,E+=o.length):U+=o.length),i.push([t,o])}function vt(t){const o=Le(t);o!==t&&J.mutable(o).add(t.slice(o.length+1))}function Ur(t){const o=Le(t);J.get(o)?.has(t.slice(o.length+1))&&J.mutable(o).delete(t.slice(o.length+1)),J.delete(t)}function Ke(){J=new jt;for(const t of b.keys())vt(t)}function ar(t){const o=[],i=l=>{const a=b.get(l);if(!a)return;o.push([l,a]);const f=J.get(l);if(f)for(const p of f)i(`${l}/${p}`)};return i(t),o}function jr(t,o){if(t.pack){g-=1,E-=t.length;return}U-=t.length,Z+=Math.max(t.length,t.capacity??0)}function qr(t,o){const i=b.get(t);i&&(le&&!le.has(t)&&le.set(t,i),b.delete(t),Ur(t),jr(i),o.push([t,null]))}function Os(t,o,i){const l=e.packages;if(!l)throw new Error("This store has no shared package store to link from.");const a=Wr(o),f=l.descendants(a);if(f.length===0)throw new Error(`The shared package store does not hold ${o}.`);Fe(t,i),cr(t,i),_e(b.size+f.length);for(const[p,m]of f){const _=p===a?t:`${t}${p.slice(a.length)}`;re(_,m.type==="directory"?{type:"directory",mode:m.mode,mtimeMs:m.mtimeMs,offset:0,length:0}:{type:m.type,mode:m.mode,mtimeMs:m.mtimeMs,offset:m.offset,length:m.length,pack:ve},i)}}function Fe(t,o){const i=Le(t);if(i!==t&&b.get(i)?.type==="directory"){_e(b.size+(b.has(t)?0:1));return}const l=[];let a=dt(t)??Se()[0];if(b.has(a)||l.push(a),t!==a)for(const p of hr(tn(Le(t)))){a=`${a}/${p}`;const m=b.get(a);if(m&&m.type!=="directory")throw new Error(`OPFS path parent is a file: ${a}`);m||l.push(a)}_e(b.size+l.length+(b.has(t)?0:1));const f=Date.now();for(const p of l)re(p,{type:"directory",mode:rt,mtimeMs:f,offset:0,length:0},o)}function cr(t,o){for(const[i]of ar(t))qr(i,o)}function Ns(t,o,i){if(t===o)return;if(o.startsWith(`${t}/`))throw new Error("An OPFS rename cannot move a directory into itself.");const l=ar(t);if(l.length===0){if(b.has(o))return;throw new Error(`OPFS rename source does not exist: ${t}`)}Fe(o,i),cr(o,i);for(const[a]of l)qr(a,i);for(const[a,f]of l)re(`${o}${a.slice(t.length)}`,f,i);_e(b.size)}function Wr(t){if(typeof t!="string"||!t.startsWith(`${yr}/`)||t.includes("\0")||t.length>4096)throw new Error("Invalid shared store path.");return hr(t.slice(yr.length+1)),t}function Se(){return D===ve?[yr]:wo}function dt(t){return Se().find(o=>t===o||t.startsWith(`${o}/`))}function lr(){return r!==void 0?r:(d??=U,Math.min(Number.MAX_SAFE_INTEGER,d+c))}function dr(){return r!==void 0?"its configured limit":"the origin's storage quota"}function It(t,o){const i=b.get(t),l=i&&!i.pack?i.length:0,a=lr();if(U-l+o>a){const f=h?"the origin's shared packages":"the project's own files";throw new Error(`OPFS workspace exceeds ${dr()}: writing ${t} (${o} bytes) would take ${f} past ${a} bytes (${U} bytes held, ${l} replaced).`)}}function _e(t){if(t>s)throw new Error("OPFS workspace exceeds its entry limit.")}function Jr(){_e(b.size);const t=lr();if(U>t)throw new Error(`OPFS workspace exceeds ${dr()}: ${h?"the origin's shared packages":"the project's own files"} hold ${U} bytes, past ${t}.`)}function Ot(t,o){const i=L;if(!i)throw new Error("OPFS filesystem worker is not initialized.");let l=0;for(;l<o.byteLength;){const a=i.write(o.subarray(l),{at:t+l});if(a<=0)throw new Error("An OPFS workspace file could not be written completely.");l+=a}N=Math.max(N,t+o.byteLength)}function Hr(t){const o=L;if(!o)throw new Error("OPFS filesystem worker is not initialized.");t<=N||(o.truncate(t),N=t)}function Nt(t){const o=L;if(!o)throw new Error("OPFS filesystem worker is not initialized.");const i=N;let l=0;for(;l<t.byteLength;){const a=o.write(t.subarray(l),{at:i+l});if(a<=0)throw new Error("An OPFS workspace file could not be written completely.");l+=a}return N=i+t.byteLength,i}function Ts(t){const o=L;if(o.getSize()>=N&&t.getSize()>=F)return;o.flush(),t.flush();const i=o.getSize(),l=t.getSize();if(!(i>=N&&l>=F))throw Object.assign(new Error(`This browser is keeping less than the tab wrote (the store's pack holds ${i} of ${N} bytes, its log ${l} of ${F}): its storage is full, as a private window's is well below its quota.`),{name:"QuotaExceededError",code:"ENOSPC"})}function Ms(t,o={}){const i=k;if(!i||!L)throw new Error("OPFS filesystem worker is not initialized.");if(t.length===0)return;const l=De.encode(JSON.stringify({packBytes:N,changes:t}));if(l.byteLength>wn)throw new Error("An OPFS workspace index record exceeds its size limit.");const a=new Uint8Array(zt+l.byteLength),f=new DataView(a.buffer);f.setUint32(0,l.byteLength,!0),f.setUint32(4,nn(l),!0),a.set(l,zt);let p=0;for(;p<a.byteLength;){const m=i.write(a.subarray(p),{at:F+p});if(m<=0)throw new Error("The OPFS workspace index log could not be written completely.");p+=m}F+=a.byteLength,Ts(i),o.publish!==!1&>(),performance.now()-pe>=_n?Pe():ne===void 0&&(ne=setTimeout(Pe,_n))}function Pe(){if(ne!==void 0&&(clearTimeout(ne),ne=void 0),he)throw he;const t=performance.now();L?.flush(),k?.flush(),pe=performance.now(),X+=1,We+=pe-t}function Tt(){const t=$r,o=Et(()=>t.catch(()=>{}).then(Fs));return $r=o,o}async function Fs(){if(ke(),!M)return;const t=M,o=k,i=await me(t,!1);if(!o||o!==k||t!==M)throw new Error("OPFS workspace changed generations before its checkpoint could start.");Pe();const l=F;if(await ft(i,b,{access:o,bytes:l,packBytes:N}),t===M&&(ye={generation:t,bytes:l}),o===k&&t===M&&l===F){at();try{o.truncate(0),o.flush(),F=0,ye={generation:t,bytes:0}}finally{ct()}}}function Gr(t){return kt(()=>$s(ur(t)))}async function $s(t){const o=crypto.randomUUID(),i=await me(o,!0),l=await i.getFileHandle(tt,{create:!0}),a=await te(l,"store"),f=new Map;let p=0;try{for(const _ of t.files){let S=0,T=0;if(_.type!=="directory"){const I=new Uint8Array(t.pack,_.offset??0,_.length??0);S=p,T=I.byteLength;let v=0;for(;v<T;){const W=a.write(I.subarray(v),{at:S+v});if(W<=0)throw new Error("An OPFS workspace file could not be written completely.");v+=W}p+=T}f.set(_.path,{type:_.type,mode:_.mode??(_.type==="directory"?rt:Ut),mtimeMs:_.mtimeMs??Date.now(),offset:S,length:T})}for(const _ of Se())f.has(_)||f.set(_,{type:"directory",mode:rt,mtimeMs:Date.now(),offset:0,length:0});_e(f.size),a.truncate(p),a.flush()}finally{a.close()}const m=await ft(i,f);await Mt(o,i,f,p,m)}async function Ls(){await Yr(()=>!0)}async function Rs(){let t=!1,o=!1,i=!1;try{await Bs(()=>{t=!0},()=>{o=!0},()=>{i=!0})}finally{t&&(o||i)?ct():t&&bt()}}async function Bs(t,o,i){const l=crypto.randomUUID(),a=await me(l,!0),f=await te(await a.getFileHandle(tt,{create:!0}),"store");let p,m=!1;try{p=await te(await a.getFileHandle(_r,{create:!0}),"record of changes"),p.truncate(0);const _=new Uint8Array(gn);let S=0;const T=q=>{if(q.pack)return{...q};if(q.type==="directory"||q.length===0)return{...q,offset:0,length:0};const ee=L;if(!ee)throw new Error("OPFS filesystem worker is not initialized.");const Re=S;let de=0;for(;de<q.length;){const pt=Math.min(_.byteLength,q.length-de),cn=_.subarray(0,pt);if(P?.ensure(q.offset+de,pt),ee.read(cn,{at:q.offset+de})!==pt)throw new Error("An OPFS workspace file could not be read completely.");let Rt=0;for(;Rt<pt;){const ln=f.write(cn.subarray(Rt),{at:Re+de+Rt});if(ln<=0)throw new Error("An OPFS workspace file could not be written completely.");Rt+=ln}de+=pt}S+=q.length;const{capacity:wr,...Xs}=q;return{...Xs,offset:Re}},I=new Map;let v=performance.now();for(const[q,ee]of[...b]){if(V||Ge)return;b.get(q)===ee&&(I.set(ee,T(ee)),performance.now()-v>8&&(await new Promise(Re=>setTimeout(Re,0)),v=performance.now()))}if(V||Ge||!L||!k)return;at(),t();const W=new Map;for(const[q,ee]of b)W.set(q,I.get(ee)??T(ee));f.truncate(S),f.flush(),p.flush(),Pe();const H={pack:L,log:k};L=f,k=p,F=0,b=W,Ke(),N=S,M=l,A=a,lt(),m=!0;const oe=new Map(W);try{H.pack.close()}finally{H.log.close()}try{await ft(a,oe);const q={storageVersion:4,generation:l,initializedAt:Date.now()};await ut(await Me(),et,q)}catch(q){throw he=new Error("The workspace moved to a compacted generation it could not record; it takes no more writes, which its next open would discard.",{cause:q}),he}o(),await sr(l)}finally{if(!m){i();try{f.close()}finally{p?.close()}await Xr(await(await Me()).getDirectoryHandle(Ct),l)}}}async function Ds(t){ke(),at();try{await Cs(t)}finally{ct()}}async function Cs(t){let o=!1;for(const[i,l]of b){if(!l.pack||l.length===0)continue;const a=t.get(l.offset);if(a===void 0)throw new Error(`The shared store no longer holds the bytes of ${i}.`);a!==l.offset&&(b.set(i,{...l,offset:a}),o=!0)}o&&await Tt()}function Yr(t){return kt(()=>zs(t))}async function zs(t){const o=L;if(!o)throw new Error("OPFS filesystem worker is not initialized.");const i=new Map,l=crypto.randomUUID(),a=await me(l,!0),f=await a.getFileHandle(tt,{create:!0}),p=await te(f,"store"),m=new Map,_=new Uint8Array(gn);let S=0;try{for(const[I,v]of b){if(!t(I,v))continue;if(v.pack){m.set(I,{...v});continue}if(v.type==="directory"||v.length===0){m.set(I,{...v,offset:0,length:0});continue}const W=S;i.set(v.offset,W);let H=0;for(;H<v.length;){const ee=Math.min(_.byteLength,v.length-H),Re=_.subarray(0,ee);if(P?.ensure(v.offset+H,ee),o.read(Re,{at:v.offset+H})!==ee)throw new Error("An OPFS workspace file could not be read completely.");let de=0;for(;de<ee;){const wr=p.write(Re.subarray(de),{at:W+H+de});if(wr<=0)throw new Error("An OPFS workspace file could not be written completely.");de+=wr}H+=ee}S+=v.length;const{capacity:oe,...q}=v;m.set(I,{...q,offset:W,length:v.length})}p.truncate(S),p.flush()}finally{p.close()}const T=await ft(a,m);return await Mt(l,a,m,S,T),i}async function Mt(t,o,i,l,a,f){at();try{await Us(t,o,i,l,a,f)}finally{ct()}}async function Us(t,o,i,l,a,f){const p=await o.getFileHandle(_r,{create:!0}),m=await te(p,"record of changes");try{m.truncate(0),m.flush()}finally{m.close()}const _={storageVersion:f?5:4,generation:t,initializedAt:Date.now(),...f?{imageRanges:f}:{}};if(await ut(await Me(),et,_),Ve(),M=t,x=_.initializedAt,Q=f,a){const S=new Be(a.index);b=new Xe(S),J=new Bt(S),se=void 0}else b=i,Ke();N=l,A=o,await Ye(o),a?({liveBytes:U,linked:g,linkedBytes:E}=a,Z=Math.max(0,N-U)):lt(),h||await sr(t)}async function js(t,o,i,l,a=!1){if(ke(),!h||D!==ve)throw new Error("Only the shared package store can reserve immutable image extents.");if(N!==0||[...b.values()].some(I=>I.type!=="directory"))return!1;const f=mr(l);if(f.bytes!==t.packBytes||t.entries>gr||t.liveBytes>t.packBytes||o.byteLength!==t.json.raw||i.byteLength!==t.binary.raw||!await $t(o,t.json.sha256,a)||!await $t(i,t.binary.sha256,a))throw new Error("The image's prepared metadata does not match its document.");const p=o.subarray(0,4096).indexOf(10);if(p<0)throw new Error("The prepared index has no bounded retained header.");const m=JSON.parse(`${Ze.decode(o.subarray(0,p-1))}}`),_={packBytes:t.packBytes,liveBytes:t.liveBytes,linked:0,linkedBytes:0},S=m.retainedIndex;if(S.version!==1||S.digest!==await Vr(t.binary.sha256,_)||S.packBytes!==_.packBytes||S.liveBytes!==_.liveBytes||S.linked!==0||S.linkedBytes!==0)throw new Error("The prepared index's retained measures are inconsistent.");const T=new SharedArrayBuffer(i.byteLength);if(new Uint8Array(T).set(i),new Be(T).entryCount!==t.entries)throw new Error("The prepared index has the wrong number of entries.");return kt(async()=>{const I=crypto.randomUUID(),v=await me(I,!0),W=await v.getFileHandle(tt,{create:!0}),H=await te(W,"immutable image reservation");try{H.truncate(t.packBytes),H.flush()}finally{H.close()}const oe=De.encode(JSON.stringify(f));return await Ae(v,fn,oe),await Ae(v,Ft,i),await Ae(v,fe,o),await Mt(I,v,new Map,t.packBytes,{index:T,..._},await ge(oe)),!0})}async function qs(t,o,i,l=!1,a){if(ke(),h||!e.packages||!a&&!e.packages.deferredImage)throw new Error("Prepared project paths require a verified shared image.");if(N!==0||[...b.values()].some(S=>S.type!=="directory"))return!1;if(o.byteLength!==t.json.raw||i.byteLength!==t.binary.raw||!await $t(o,t.json.sha256,l)||!await $t(i,t.binary.sha256,l))throw new Error("The image's prepared project does not match its descriptor.");const f=o.subarray(0,4096).indexOf(10);if(f<0)throw new Error("The prepared project has no bounded retained header.");const p=JSON.parse(`${Ze.decode(o.subarray(0,f-1))}}`).retainedIndex,m={packBytes:0,liveBytes:0,linked:t.linked,linkedBytes:t.linkedBytes};if(p.version!==1||p.digest!==await Vr(t.binary.sha256,m)||p.packBytes!==0||p.liveBytes!==0||p.linked!==t.linked||p.linkedBytes!==t.linkedBytes)throw new Error("The prepared project's retained measures are inconsistent.");const _=new SharedArrayBuffer(i.byteLength);if(new Uint8Array(_).set(i),new Be(_).entryCount!==t.entries||t.entries>s)throw new Error("The prepared project has invalid entry bounds.");return kt(async()=>{const S=crypto.randomUUID(),T=await me(S,!0),I=await T.getFileHandle(tt,{create:!0}),v=await te(I,"prepared project");try{v.truncate(0),v.flush()}finally{v.close()}if(await Ae(T,Ft,i),await Ae(T,fe,o),a&&!await a)return!1;if(!e.packages?.deferredImage)throw new Error("Prepared project paths require a verified shared image.");return await Mt(S,T,new Map,0,{index:_,...m}),!0})}async function Ws(){if(V)throw new Error("This OPFS workspace is closing.");if(!L)throw new Error("OPFS filesystem worker is not initialized.");const t=[],o=[...b.keys()].sort((p,m)=>rn(p)-rn(m)||(p<m?-1:1));let i=0;for(const p of b.values())p.type!=="directory"&&(i+=p.length);const l=new ArrayBuffer(i),a=new Uint8Array(l);let f=0;for(const p of o){const m=b.get(p);if(m.type==="directory"){t.push({path:p,type:"directory",mode:m.mode,mtimeMs:m.mtimeMs});continue}m.length>0&&a.set(St(m),f),t.push({path:p,type:m.type,offset:f,length:m.length,mode:m.mode,mtimeMs:m.mtimeMs}),f+=m.length}for(const p of[...Se()].reverse())b.has(p)||t.unshift({path:p,type:"directory",mode:rt,mtimeMs:Date.now()});return ur({files:t,pack:l})}async function ut(t,o,i){await Ae(t,o,De.encode(JSON.stringify(i)))}async function Ae(t,o,i){const l=await(await Me()).getDirectoryHandle(hn,{create:!0}),a=crypto.randomUUID(),f=await l.getFileHandle(a,{create:!0}),p=await te(f,"index");try{let m=0;for(;m<i.byteLength;){const _=p.write(i.subarray(m),{at:m});if(_<=0)throw new Error("An OPFS workspace file could not be written completely.");m+=_}p.truncate(i.byteLength),p.flush()}finally{p.close()}try{await f.move(t,o)}finally{await Qr(l,a,!1)}}const Ft="index.shared";async function ge(t){const o=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(o),i=>i.toString(16).padStart(2,"0")).join("")}async function $t(t,o,i){return i||await ge(t)===o}function Vr(t,o){const{packBytes:i,liveBytes:l,linked:a,linkedBytes:f,journalPrefix:p}=o;return ge(De.encode(`${JSON.stringify({packBytes:i,liveBytes:l,linked:a,linkedBytes:f,...p?{journalPrefix:p}:{}})}:${t}`))}async function Kr(t,o){const{packBytes:i,liveBytes:l,linked:a,linkedBytes:f,journalPrefix:p}=o;return ge(De.encode(`${JSON.stringify({packBytes:i,liveBytes:l,linked:a,linkedBytes:f,...p?{journalPrefix:p}:{}})}:${await ge(t)}`))}async function ft(t,o,i){const l=Ys(o);if(typeof SharedArrayBuffer>"u"||o.size<1e4){await ut(t,fe,l);return}const a=new Map(l.entries),f=new Map,p={packBytes:i?.packBytes??0,liveBytes:0,linked:0,linkedBytes:0};for(const[W,H]of a){const oe=Le(W);if(oe!==W){let q=f.get(oe);q||(q=new Set,f.set(oe,q)),q.add(W.slice(oe.length+1))}H.pack?(p.linked+=1,p.linkedBytes+=H.length):(p.liveBytes+=H.length,p.packBytes=Math.max(p.packBytes,H.offset+H.length))}let m;try{m=dn(a,f)}catch{await ut(t,fe,l);return}const _=JSON.stringify(l.entries),S=i?new Uint8Array(i.bytes):void 0;if(S&&i.access.read(S,{at:0})!==S.byteLength)throw new Error("The checkpoint's journal prefix could not be read completely.");const T=S?{bytes:S.byteLength,digest:await ge(S)}:void 0,I=new Uint8Array(m).slice(),v={version:T?2:1,digest:await Kr(I,{...p,...T?{journalPrefix:T}:{}}),...p,...T?{journalPrefix:T}:{}};try{await Ae(t,Ft,I)}catch{await ut(t,fe,{entries:JSON.parse(_)});return}return await Ae(t,fe,De.encode(`{"retainedIndex":${JSON.stringify(v)},
|
|
3
|
+
"entries":${_}}`)),{index:m,...p}}async function Js(t){if(!(typeof SharedArrayBuffer>"u"))try{const o=await t.getFileHandle(fe),i=await te(o,"index");let l;try{const I=new Uint8Array(Math.min(512,i.getSize())),v=i.read(I,{at:0});l=Ze.decode(I.subarray(0,v))}finally{i.close()}const a=l.split(`
|
|
4
|
+
`,1)[0];if(!a.startsWith('{"retainedIndex":')||!a.endsWith(","))return;const f=JSON.parse(a.slice(0,-1)+"}").retainedIndex;if(f.version!==1&&f.version!==2||!/^[a-f0-9]{64}$/u.test(f.digest)||![f.packBytes,f.liveBytes,f.linked,f.linkedBytes].every(I=>Number.isSafeInteger(I)&&I>=0)||f.version===1&&f.journalPrefix!==void 0||f.version===2&&(!f.journalPrefix||!Number.isSafeInteger(f.journalPrefix.bytes)||f.journalPrefix.bytes<0||!/^[a-f0-9]{64}$/u.test(f.journalPrefix.digest)))return;const p=await t.getFileHandle(Ft),m=await te(p,"index");let _;try{const I=m.getSize();if(I>256*1024*1024||(_=new Uint8Array(I),m.read(_,{at:0})!==I))return}finally{m.close()}if(await Kr(_,f)!==f.digest)return;const S=new SharedArrayBuffer(_.byteLength);new Uint8Array(S).set(_);const T=new Be(S);return _e(T.entryCount),{...f,index:S}}catch{return}}async function Hs(t){const o=t.journalPrefix;if(!o||!k||!L||o.bytes>k.getSize()||t.packBytes>L.getSize())return 0;const i=new Uint8Array(o.bytes);return k.read(i,{at:0})!==i.byteLength?0:await ge(i)===o.digest?o.bytes:0}async function $e(t,o){let i;try{i=await t.getFileHandle(o)}catch(f){if(Qe(f))return;throw f}let l;if(w){l=await(await i.getFile()).text();try{return JSON.parse(l)}catch(f){throw new Error(`Invalid OPFS workspace metadata (${o}). Stored data was retained.`,{cause:f})}}const a=await te(i,"index");try{const f=a.getSize(),p=new Uint8Array(f);if(f>0&&a.read(p,{at:0})!==f)throw new Error("An OPFS workspace file could not be read completely.");l=Ze.decode(p)}finally{a.close()}try{return JSON.parse(l)}catch(f){throw new Error(`Invalid OPFS workspace metadata (${o}). Stored data was retained.`,{cause:f})}}async function Qr(t,o,i){try{await t.removeEntry(o,{recursive:i})}catch(l){if(!Qe(l))throw l}}async function Xr(t,o){try{await t.removeEntry(o,{recursive:!0})}catch{}}function Zr(t){if(!t||typeof t!="object"||Array.isArray(t))throw new Error("Invalid OPFS filesystem mutation.");if(t.operation!=="write"&&t.operation!=="append"&&t.operation!=="write-at"&&t.operation!=="mkdir"&&t.operation!=="remove"&&t.operation!=="rename"&&t.operation!=="metadata"&&t.operation!=="link")throw new Error("Invalid OPFS filesystem mutation.");if(be(t.path),t.operation==="rename"&&be(t.destination),(t.operation==="write"||t.operation==="append"||t.operation==="write-at")&&!(t.content instanceof Uint8Array))throw new Error("Invalid OPFS file content.");if(t.operation==="write-at"&&(!Number.isSafeInteger(t.position)||t.position<0))throw new Error("Invalid OPFS write position.");return fr(t),t}function Gs(t){if(!Array.isArray(t)||t.length===0||t.length>128)throw new Error("Invalid OPFS filesystem mutation batch.");return t.map(o=>Zr(o))}function ur(t){if(!t||!Array.isArray(t.files)||t.files.length>s||!(t.pack instanceof ArrayBuffer))throw new Error("Invalid OPFS workspace snapshot.");const o=new Set,i=new Map(Se().map(a=>[a,"directory"]));let l=0;for(const a of t.files){if(!a||typeof a!="object")throw new Error("Invalid OPFS workspace snapshot entry.");if(be(a.path),a.type!=="file"&&a.type!=="directory"&&a.type!=="symlink"||o.has(a.path))throw new Error("Invalid or duplicate OPFS workspace entry.");if(o.add(a.path),i.set(a.path,a.type),Se().includes(a.path)&&a.type!=="directory")throw new Error("The OPFS workspace root must be a directory.");if(a.type!=="directory"){const f=a.offset??0,p=a.length??0;if(!Number.isSafeInteger(f)||!Number.isSafeInteger(p)||f<0||p<0||p>ie||f+p>t.pack.byteLength)throw new Error("Invalid OPFS workspace file.");if(l+=p,l>lr())throw new Error(`OPFS workspace exceeds ${dr()}.`)}else if((a.offset??0)!==0||(a.length??0)!==0)throw new Error("An OPFS workspace directory cannot contain file bytes.");fr(a)}_e(i.size);for(const a of t.files)if(!Se().includes(a.path)&&i.get(Le(a.path))!=="directory")throw new Error(`An OPFS workspace snapshot has no directory parent for ${a.path}.`);return t}function fr(t){if(t.mode!==void 0&&(!Number.isSafeInteger(t.mode)||t.mode<0||t.mode>4095))throw new Error("Invalid OPFS file mode.");if(t.mtimeMs!==void 0&&(typeof t.mtimeMs!="number"||!Number.isFinite(t.mtimeMs)||t.mtimeMs<0))throw new Error("Invalid OPFS modification time.")}function Ys(t){return{entries:[...t]}}function pr(t){const o=new Map;if(t===void 0)throw new Error("The committed OPFS workspace index is missing. Stored data was retained.");if(!t||typeof t!="object"||!Array.isArray(t.entries))throw new Error("Invalid OPFS workspace index.");const i=t.entries;_e(i.length);for(const l of i){if(!Array.isArray(l)||l.length!==2)throw new Error("Invalid OPFS workspace index entry.");const a=be(l[0]);if(o.has(a))throw new Error("Duplicate OPFS workspace index entry.");o.set(a,en(l[1]))}return o}function en(t){if(!t||typeof t!="object"||Array.isArray(t))throw new Error("Invalid OPFS workspace index entry.");const o=t;if(o.type!=="file"&&o.type!=="directory"&&o.type!=="symlink")throw new Error("Invalid OPFS workspace index entry.");if(fr(o),o.mode===void 0||o.mtimeMs===void 0)throw new Error("Invalid OPFS workspace index entry.");if(!Number.isSafeInteger(o.offset)||o.offset<0||!Number.isSafeInteger(o.length)||o.length<0||o.length>ie)throw new Error("Invalid OPFS workspace index extent.");if(o.pack!==void 0&&o.pack!==ve)throw new Error("Invalid OPFS workspace index entry.");return{type:o.type,mode:o.mode,mtimeMs:o.mtimeMs,offset:o.offset,length:o.length,...o.pack?{pack:o.pack}:{}}}function Vs(t){if(!t||typeof t!="object"||Array.isArray(t))throw new Error("Invalid OPFS workspace index record.");const o=t;if(!Number.isSafeInteger(o.packBytes)||o.packBytes<0||!Array.isArray(o.changes))throw new Error("Invalid OPFS workspace index record.");const i=[];for(const l of o.changes){if(!Array.isArray(l)||l.length!==2)throw new Error("Invalid OPFS workspace index record.");i.push([be(l[0]),l[1]===null?null:en(l[1])])}return{packBytes:o.packBytes,changes:i}}function Lt(t){if(t===void 0)return;if(!t||typeof t!="object"||Array.isArray(t))throw new Error("Invalid OPFS workspace state. Stored data was retained.");const o=t;if(o.storageVersion!==4&&o.storageVersion!==5||o.storageVersion===5&&(typeof o.imageRanges!="string"||!/^[a-f0-9]{64}$/u.test(o.imageRanges))||o.storageVersion===4&&o.imageRanges!==void 0||typeof o.generation!="string"||!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu.test(o.generation)||typeof o.initializedAt!="number"||!Number.isFinite(o.initializedAt))throw new Error("Invalid or unsupported OPFS workspace state. Stored data was retained.");return o}function be(t){if(typeof t!="string"||dt(t)===void 0||t.includes("\0")||t.length>4096)throw new Error("Invalid OPFS workspace path.");return tn(t),t}function tn(t){const o=dt(t);if(o===void 0)throw new Error("Invalid OPFS workspace path.");const i=t===o?"":t.slice(o.length+1);return hr(i),i}function hr(t){const o=t===""?[]:t.split("/");if(o.some(i=>!i||i==="."||i===".."||i.includes("\0")))throw new Error("Invalid OPFS workspace path segment.");return o}function Le(t){const o=t.slice(0,t.lastIndexOf("/"));return o===""||dt(o)===void 0?dt(t)??t:o}function rn(t){let o=1;for(let i=0;i<t.length;i+=1)t.charCodeAt(i)===47&&(o+=1);return o}function Qe(t){return t instanceof DOMException&&t.name==="NotFoundError"}function nn(t){let o=2166136261;for(let i=0;i<t.byteLength;i+=1)o^=t[i],o=Math.imul(o,16777619);return o>>>0}typeof addEventListener=="function"&&addEventListener("close",()=>{L?.flush(),k?.flush(),Ve(),B?.()});function sn(t,o={}){if(ke(),le)throw new Error("An OPFS mutation batch cannot be nested.");for(const i of t)Zr(i);return t.length?on(i=>{for(const l of t)Is(l,i)},o):[]}function Ks(t,o,i={}){if(ke(),le)throw new Error("An OPFS mutation batch cannot be nested.");for(const l of o){if(be(l.path),l.type!=="file"&&l.type!=="directory"&&l.type!=="symlink")throw new Error(`OPFS extent ${l.path} has no valid type.`);if(l.type==="directory")continue;const{offset:a,length:f}=l;if(a===void 0||f===void 0||!Number.isSafeInteger(a)||!Number.isSafeInteger(f)||a<0||f<0||a+f>t.byteLength)throw new Error(`OPFS extent ${l.path} lies outside its bytes.`);if(f>ie)throw new Error(`${l.path} is ${f} bytes; an OPFS workspace file holds at most ${ie}.`)}return o.length?on(l=>{const a=t.byteLength>0?Nt(t):N;for(const f of o){const p=be(f.path);Fe(p,l);const m=b.get(p);if(f.type==="directory"){if(m&&m.type!=="directory")throw new Error(`OPFS path is a file: ${p}`);re(p,{type:"directory",mode:f.mode,mtimeMs:f.mtimeMs,offset:0,length:0},l);continue}if(m?.type==="directory")throw new Error(`OPFS write target is a directory: ${p}`);It(p,f.length),re(p,{type:f.type,mode:f.mode,mtimeMs:f.mtimeMs,offset:a+f.offset,length:f.length},l)}},i):[]}function on(t,o){if(!L||!k)throw new Error("OPFS filesystem worker is not initialized.");const i={packBytes:N,logBytes:F,liveBytes:U,deadBytes:Z,rewrites:Oe,rewrittenBytes:Ne,linked:g,linkedBytes:E},l=new Map;le=l;const a=[];_t=a;const f=[];try{return t(f),Jr(),Ms(f,{publish:!o.durable}),o.durable&&(Pe(),gt()),zr(),f}catch(p){const m=K!==void 0&&!we&&Atomics.load(K,mn)!==i.logBytes;m&&at();for(const[_,S]of l)S===void 0?b.delete(_):b.set(_,S);Ke();try{for(let _=a.length-1;_>=0;_-=1)Ot(a[_][0],a[_][1])}catch(_){p=new AggregateError([p,_],"OPFS could not restore bytes a failed batch wrote over.")}({packBytes:N,logBytes:F,liveBytes:U,deadBytes:Z,rewrites:Oe,rewrittenBytes:Ne,linked:g,linkedBytes:E}=i),ne!==void 0&&(clearTimeout(ne),ne=void 0);try{k.truncate(F),k.flush(),L.truncate(N),L.flush()}catch(_){throw bt(),he=new AggregateError([p,_],"OPFS could not roll back a failed batch; reopen this workspace before writing again."),he}throw m&&ct(),p}finally{le=void 0,_t=void 0}}function Qs(){if(Je){it?.abort(new DOMException("The workspace was closed while opening.","AbortError"));return}V||(V=!0,He===0&&an())}function an(){bt();try{Pe()}finally{try{Ve()}finally{const t=B;B=void 0,u=void 0;try{t?.()}finally{e.ownsPackages&&e.packages?.close()}}}}return{initialize:bs,opened:()=>u!==void 0&&!V,stats:()=>({entries:b.size,liveBytes:U,deadBytes:Z,packBytes:N,rewrites:Oe,rewrittenBytes:Ne,linked:g,linkedBytes:E,flushes:X,flushMs:We}),applyNow:sn,applyExtentsNow:Ks,close:Qs,readExtent:Pt,descendants:ar,retain:Yr,remapLinks:Ds,childrenOf:t=>[...J.get(t)??[]].sort(),refresh:Es,follow:ys,clock:Lr,readerSeed:ps,imageCompletionSeed:hs,imageLine:()=>P?.lineForReader()??e.packages?.imageLine(),imageStartupSet:()=>P?.readDigests()??P?.completedDigests()??[],prefetchImage:(t,o)=>P?.prefetch(t,o)??{queued:0,done:Promise.resolve()},seeded:()=>Rr,get logBytes(){return F},checkpoint:Tt,deferMaintenance:vs,installPreparedImage:js,installPreparedProject:qs,get deferredImage(){return R},get imagePlacedAt(){return u&&Q?x:void 0},get entries(){return b},get packBytes(){return N},read:_s,readRange:gs,snapshot:Ws,replace:Gr,apply:xs,flush:()=>{if(V||!u)throw new Error("This OPFS workspace is not open.");if(Ge)throw new Error("Wait for the OPFS generation replacement before flushing it.");Pe()},validateSnapshot:ur,validateMutationBatch:Gs}}async function _o(n,e,r,s){const c=bn(n);await c.initialize(ve,{readOnly:!0,extentsOnly:!0});const d=bn(n,{packages:c,ownsPackages:!0});let u;try{u=await d.initialize(e,{readOnly:!0,...r?{seed:r}:{}})}catch(h){throw d.close(),c.close(),h}if(!u&&!d.opened()){c.close();return}return d}const go="sweep.json";async function bo(n){const r=await(await n.getFileHandle(go,{create:!0})).createWritable();await r.write(JSON.stringify({at:Date.now()})),await r.close()}class jt{map=new Map;get(e){return this.map.get(e)}mutable(e){let r=this.map.get(e);return r||(r=new Set,this.map.set(e,r)),r}delete(e){this.map.delete(e)}}function Eo(n){const e=n.toBase64;if(typeof e=="function")return e.call(n);let r="";for(let s=0;s<n.byteLength;s+=32768)r+=String.fromCharCode(...n.subarray(s,s+32768));return btoa(r)}function Vn(n){const e=Uint8Array.fromBase64;if(typeof e=="function")return e(n);const r=atob(n),s=new Uint8Array(r.length);for(let c=0;c<r.length;c+=1)s[c]=r.charCodeAt(c);return s}function ko(n,e,r){const{appended:s,superseded:c}=r?So(n,e,r):{appended:new Map,superseded:new Set},d=[...e.removed].sort((h,w)=>qt(w)-qt(h));for(const h of d)n.existsSync(h)&&(n.statSync(h).isDirectory()?n.rmdirSync(h):n.unlinkSync(h));const u=[...e.files].filter(h=>!c.has(h.path)).sort((h,w)=>qt(h.path)-qt(w.path));for(const h of u){if(h.type==="directory")n.existsSync(h.path)&&!n.statSync(h.path).isDirectory()&&n.unlinkSync(h.path),n.mkdirSync(h.path,{recursive:!0});else if(je(h)){n.existsSync(h.path)&&n.statSync(h.path).isDirectory()&&n.rmdirSync(h.path);const w=h.path.slice(0,h.path.lastIndexOf("/"))||"/";w!=="/"&&!n.existsSync(w)&&n.mkdirSync(w,{recursive:!0});const y=n.existsSync(h.path)?n.statSync(h.path).mode:void 0,A=y!==void 0&&(y&128)===0;A&&n.chmodSync?.(h.path,y&4095|128),n.writeFileSync(h.path,s.get(h.path)??wt(h)),A&&h.mode===void 0&&n.chmodSync?.(h.path,y&4095)}else if(!n.existsSync(h.path)||n.statSync(h.path).isDirectory())continue;h.mode!==void 0&&n.chmodSync?.(h.path,h.mode),h.mtimeMs!==void 0&&n.utimesSync?.(h.path,new Date(h.mtimeMs),new Date(h.mtimeMs))}}function So(n,e,r){const s=new Map,c=new Set,d=r.byPath,u=d instanceof Map?d:new Map(r.files.map(y=>[y.path,y])),h=new Map(e.files.map(y=>[y.path,y])),w=new Set([...e.files.map(y=>y.path),...e.removed]);for(const y of w){const A=u.get(y),g=Io(n,y);if(A!==void 0&&Er(A,h.get(y))||g===void 0&&h.get(y)!==void 0)continue;const E=h.get(y);if(!(g!==void 0&&E!==void 0&&E.type===g.type&&(j(E).mtimeMs??0)>(j(g).mtimeMs??0))&&!(A!==void 0&&g!==void 0&&A.type===g.type&&(j(g).mtimeMs??0)<(j(A).mtimeMs??0))&&!Er(A,g)&&!Er(h.get(y),g)){if(Ao(A,g,h.get(y)))continue;const B=Po(n,y,A,g,h.get(y),r.bytesOf?.bind(r));if(B){s.set(y,B);continue}const D=h.get(y);if(A!==void 0&&g!==void 0&&D!==void 0&&D.type===g.type&&(j(D).mtimeMs??0)>=(j(A).mtimeMs??0)&&(j(g).mtimeMs??0)>(j(D).mtimeMs??0)&&(j(g).mtimeMs??0)>(j(A).mtimeMs??0)){c.add(y);continue}throw new Error(`Browser filesystem write conflict at ${y}. ${JSON.stringify({base:br(A),current:br(g),proposed:br(h.get(y))})}`)}}return{appended:s,superseded:c}}function Po(n,e,r,s,c,d){if(r?.type!=="file"||s?.type!=="file"||c?.type!=="file"||!je(c)||!n.readFileSync||j(s).mode!==j(c).mode)return;const u=je(r)?wt(r):d?.(e);if(!u||u.length===0)return;const h=wt(c),w=n.readFileSync(e),y=typeof w=="string"?new TextEncoder().encode(w):w,A=E=>E.length>=u.length&&Qn(E.subarray(0,u.length),u);if(h.length<=u.length||!A(h)||!A(y))return;const g=new Uint8Array(y.length+h.length-u.length);return g.set(y,0),g.set(h.subarray(u.length),y.length),g}function br(n){return n?{type:n.type,...j(n)}:null}function Ao(n,e,r){return e?.type!=="directory"||r?.type!=="directory"?!1:n===void 0?j(e).mode===j(r).mode:j(e).mode===j(r).mode&&n.type==="directory"&&j(n).mode===j(e).mode}function xo(n,e){const r=new Set(e.removed),s=new Map(e.files.map(d=>[d.path,d])),c=[];for(const d of n.files){if(r.has(d.path))continue;const u=s.get(d.path);if(u){c.push(u),s.delete(d.path);continue}c.push(d)}for(const d of s.values())c.push(d);return{files:c}}function vo(n,e,r={}){const s=new Map(n.files.map(d=>[d.path,d])),c=new Map(e.files.map(d=>[d.path,d]));return{files:e.files.filter(d=>{const u=s.get(d.path);return d.path==="/"&&!u?!1:!u||u.type!==d.type||!Kn(u,d)||r.written===!0&&d.type==="file"&&!je(u)&&je(d)||j(u).mode!==j(d).mode||j(u).mtimeMs!==j(d).mtimeMs}),removed:n.files.flatMap(d=>c.has(d.path)?[]:[d.path])}}function qt(n){let e=1;for(let r=0;r<n.length;r+=1)n.charCodeAt(r)===47&&(e+=1);return e}function Io(n,e){if(!n.existsSync(e))return;const r=n.statSync(e),s={...r.mode!==void 0?{mode:r.mode}:{},...r.mtimeMs!==void 0?{mtimeMs:r.mtimeMs}:{}};return r.isDirectory()?{path:e,type:"directory",...s}:{path:e,type:"file",...r.size!==void 0?{size:r.size}:{},...s}}function Er(n,e){return n===void 0?e===void 0:e!==void 0&&n.type===e.type&&Kn(n,e)&&j(n).mode===j(e).mode&&j(n).mtimeMs===j(e).mtimeMs}function j(n){const e=n;return{...e.mode===void 0?{}:{mode:e.mode&4095},...e.mtimeMs===void 0?{}:{mtimeMs:e.mtimeMs}}}function Kn(n,e){return n.type!=="file"||e.type!=="file"?!0:n.content!==void 0&&e.content!==void 0?n.content===e.content:je(n)&&je(e)?Qn(wt(n),wt(e)):En(n)===En(e)}function En(n){if(n.size!==void 0)return n.size;if(n.bytes!==void 0)return n.bytes.byteLength;if(n.content===void 0)return;const e=n.content.endsWith("==")?2:n.content.endsWith("=")?1:0;return Math.floor(n.content.length*3/4)-e}function je(n){return n!==void 0&&(n.bytes!==void 0||n.content!==void 0)}function wt(n){return n.bytes??(n.content===void 0?void 0:Vn(n.content))}function Qn(n,e){if(n===e)return!0;if(n.byteLength!==e.byteLength)return!1;let r=0;if(n.byteOffset%4===0&&e.byteOffset%4===0){const s=n.byteLength>>>2,c=new Uint32Array(n.buffer,n.byteOffset,s),d=new Uint32Array(e.buffer,e.byteOffset,s);for(let u=0;u<s;u+=1)if(c[u]!==d[u])return!1;r=s<<2}for(;r<n.byteLength;r+=1)if(n[r]!==e[r])return!1;return!0}const Fr="314.0.6",Oo=`https://cdn.jsdelivr.net/pyodide/v${Fr}/full/`,No=[{file:"pyodide.mjs",integrity:"sha256-aeP2zOw+FLRl32C+V3ymL1NiUUBrmgDM4BnqxSUqJJU=",bytes:17931},{file:"pyodide.asm.mjs",integrity:"sha256-KsXro2XsEoOcdcA7ObO+HdY7eYhSzEYLAUtSI4vgQvc=",bytes:1250344},{file:"pyodide.asm.wasm",integrity:"sha256-OgoA3+qjSKwg+e8JkEIz0y0z9kQzlmLUrzaPiiAQ83o=",bytes:9598218},{file:"python_stdlib.zip",integrity:"sha256-gMW+a6v+AylwaXA0EMPClATc8lJdKxKHRrrlU2+Ugx8=",bytes:2545564},{file:"pyodide-lock.json",integrity:"sha256-P9rvCenjZcheACc3cg+NCrjyeMHCRKLd5qN2Y89IitQ=",bytes:114440}];function To(n){const e=No.find(r=>r.file===n);if(!e)throw new Error(`Pyodide ${Fr} publishes no pinned ${n}.`);return e}async function Mo(n){const e=new Uint8Array(await crypto.subtle.digest("SHA-256",n));let r="";for(const s of e)r+=String.fromCharCode(s);return`sha256-${btoa(r)}`}async function kn(n,e){const r=To(n),s=await Mo(e);if(s!==r.integrity)throw new Error(`Pyodide ${Fr} ${n} is ${s}, not the pinned ${r.integrity}.`)}const G="/workspace";let Sn,Kt="program";function Fo(){return Kt}async function $o(n,e){const r=Kt;Kt=n;try{return await e()}finally{Kt=r}}async function Lo(n){return new Uint8Array(await new Response(new Blob([n]).stream().pipeThrough(new DecompressionStream("gzip"))).arrayBuffer())}function Xn(n=Oo,e){return Sn??=(async()=>{const r=e?await Lo(e).catch(()=>{}):void 0,s=async(c,d)=>{if(r)try{const u=await c.loadPyodide({...d,_loadSnapshot:r});return await u.runPythonAsync(`import random
|
|
5
|
+
random.seed()`),delete u._api?.config?._loadSnapshot,u}catch(u){console.warn(`[python] the interpreter snapshot did not restore; starting Python: ${u instanceof Error?u.message:String(u)}`)}return await c.loadPyodide(d)};return $o("runtime",async()=>{if(n.startsWith("/")){const A=await import(`file://${n}pyodide.mjs`),g=await import(`file://${n}pyodide.asm.mjs`);return await s(A,{indexURL:n,createPyodideModule:g.default})}const[c,d]=await Promise.all([fetch(`${n}pyodide.mjs`),fetch(`${n}pyodide.asm.mjs`)]);if(!c.ok)throw new Error(`Could not load Pyodide (${c.status}).`);if(!d.ok)throw new Error(`Could not load the Pyodide runtime module (${d.status}).`);const[u,h]=await Promise.all([c.bytes(),d.bytes()]);await kn("pyodide.mjs",u),await kn("pyodide.asm.mjs",h);const w=URL.createObjectURL(new Blob([u],{type:"text/javascript"})),y=URL.createObjectURL(new Blob([h],{type:"text/javascript"}));try{const A=await import(w),g=await import(y);return await s(A,{indexURL:n,createPyodideModule:g.default})}finally{URL.revokeObjectURL(w),URL.revokeObjectURL(y)}})})(),Sn}const Ro=16384;function Bo(n){return{existsSync:e=>n.analyzePath(e).exists,statSync:e=>{const r=n.stat(e),s=(r.mode&61440)===Ro;return{isDirectory:()=>s,...typeof r.size=="number"?{size:r.size}:{},...vr(r)}},readFile:e=>Promise.resolve(n.readFile(e)),writeFileSync:(e,r)=>n.writeFile(e,typeof r=="string"?new TextEncoder().encode(r):r),mkdirSync:e=>n.mkdirTree(e),unlinkSync:e=>n.unlink(e),rmdirSync:e=>n.rmdir(e),chmodSync:(e,r)=>n.chmod(e,r),utimesSync:(e,r,s)=>n.utime(e,Pn(r),Pn(s))}}function Do(n,e,r){ko(Bo(n),e,r)}function Pn(n){return typeof n=="number"?n:Number(n)}function Co(n,e){rs(n,G),n.mkdirTree(G);const r=e.files.slice().sort((s,c)=>An(s.path)-An(c.path));for(const s of r)s.path!==G&&!s.path.startsWith(`${G}/`)||(s.type==="directory"?n.mkdirTree(s.path):(n.mkdirTree(s.path.slice(0,s.path.lastIndexOf("/"))||"/"),n.writeFile(s.path,zo(s.content??""))));for(const s of r){const c=s;c.path!==G&&!c.path.startsWith(`${G}/`)||(c.mode!==void 0&&n.chmod(c.path,c.mode),c.mtimeMs!==void 0&&n.utime(c.path,c.mtimeMs,c.mtimeMs))}}function Zn(n,e){const s=[...e.files.filter(c=>c.path!==G&&!c.path.startsWith(`${G}/`))];return ts(n,G,s),{files:s}}function Xt(n,e){const r=n.startsWith("/")?n:`${e}/${n}`,s=[];for(const c of r.split("/"))!c||c==="."||(c===".."?s.pop():s.push(c));return`/${s.join("/")}`}function qe(n){return n.slice(n.lastIndexOf("/")+1)}function es(n){let e="";for(let r=0;r<n.byteLength;r+=32768)e+=String.fromCharCode(...n.subarray(r,r+32768));return btoa(e)}function zo(n){const e=atob(n);return Uint8Array.from(e,r=>r.charCodeAt(0))}function ts(n,e,r){const s=n.stat(e),c=vr(s);r.push({path:e,type:"directory",...c});for(const d of n.readdir(e)){if(d==="."||d==="..")continue;const u=`${e}/${d}`,h=n.stat(u);(h.mode&61440)===16384?ts(n,u,r):r.push({path:u,type:"file",content:es(n.readFile(u)),...vr(h)})}}function rs(n,e){if(n.analyzePath(e).exists)for(const r of n.readdir(e)){if(r==="."||r==="..")continue;const s=`${e}/${r}`;(n.stat(s).mode&61440)===16384?(rs(n,s),n.rmdir(s)):n.unlink(s)}}function An(n){let e=1;for(let r=0;r<n.length;r+=1)n.charCodeAt(r)===47&&(e+=1);return e}function vr(n){const e=typeof n.mtime=="number"?n.mtime:Number(n.mtime);return{mode:n.mode&4095,...typeof e=="number"&&Number.isFinite(e)?{mtimeMs:e}:{}}}const Ir=16384,Uo=32768,xn=44;function jo(n,e){const r=n,s=r.filesystems?.MEMFS;if(!s||typeof r.mount!="function"||typeof s.createNode!="function")return;const c={dirty:new Set,removed:new Set},d=()=>r.genericErrors?.[xn]??new r.ErrnoError(xn),u=P=>P.packPath??G;function h(P,R,$){const O=e.entries.get($);if(!O)throw d();const x=O.mode&4095|(O.type==="directory"?Ir:Uo),k=s.createNode(P,R,x,0);return k.packPath=$,k.timestamp=O.mtimeMs,k.atime=k.mtime=k.ctime=O.mtimeMs,O.type==="directory"?(k.packListed=!1,k.node_ops=E(k.node_ops)):(k.packLoaded=!1,k.usedBytes=O.length,k.node_ops=D(k.node_ops),k.stream_ops=b(k.stream_ops)),k}function w(P){if(P.packLoaded!==!1||!P.packPath)return;const R=e.read(P.packPath);P.contents=R,P.usedBytes=R.byteLength,P.packLoaded=!0}function y(P){r.isDir(P.mode)||c.dirty.add(A(P))}function A(P){const R=[];let $=P;for(;$&&$.parent!==$;)R.unshift($.name),$=$.parent;return`${G}/${R.join("/")}`.replace(/\/+$/u,"")||G}const g=new WeakMap;function E(P){const R=g.get(P);if(R)return R;const $={...P,lookup:(O,x)=>{const k=`${u(O)}/${x}`;if(!c.removed.has(k)&&e.entries.has(k))return h(O,x,k);throw d()},readdir:O=>{const x=P.readdir(O),k=new Set(x),C=u(O);for(const z of e.childrenOf(C))c.removed.has(`${C}/${z}`)||k.add(z);return[...k]},mknod:(O,x,k,C)=>{const z=`${u(O)}/${x}`;c.removed.delete(z);const Y=P.mknod(O,x,k,C);return Y.packPath=z,r.isDir(k)?(Y.packListed=!0,Y.node_ops=E(Y.node_ops)):(Y.packLoaded=!0,c.dirty.add(z),Y.node_ops=D(Y.node_ops),Y.stream_ops=b(Y.stream_ops)),Y},unlink:(O,x)=>{const k=`${u(O)}/${x}`;P.unlink(O,x),c.dirty.delete(k),c.removed.add(k)},rmdir:(O,x)=>{const k=`${u(O)}/${x}`;for(const C of e.childrenOf(k))if(!c.removed.has(`${k}/${C}`))throw new r.ErrnoError(55);P.rmdir(O,x),c.removed.add(k)},rename:(O,x,k)=>{const C=A(O);r.isFile(O.mode)?w(O):J(O),P.rename(O,x,k);const z=`${u(x)}/${k}`;L(O,C,z),c.removed.add(C),c.removed.delete(z)}};return g.set(P,$),$}const B=new WeakMap;function D(P){const R=B.get(P);if(R)return R;const $={...P,setattr:(O,x)=>{x.size!==void 0&&w(O),P.setattr(O,x),(x.size!==void 0||x.mode!==void 0||x.timestamp!==void 0)&&y(O)}};return B.set(P,$),$}const M=new WeakMap;function b(P){const R=M.get(P);if(R)return R;const $={...P,open:O=>{w(O.node),P.open?.(O)},write:(O,x,k,C,z,Y)=>{w(O.node);const Ee=P.write(O,x,k,C,z,Y);return y(O.node),Ee}};return M.set(P,$),$}function J(P){const R=u(P);for(const $ of e.childrenOf(R)){if(c.removed.has(`${R}/${$}`))continue;const x=P.contents[$]??h(P,$,`${R}/${$}`);r.isDir(x.mode)?J(x):w(x)}P.packListed=!0}function L(P,R,$){if(P.packPath=$,r.isFile(P.mode)){c.dirty.delete(R),c.dirty.add($);return}for(const[O,x]of Object.entries(P.contents))L(x,`${R}/${O}`,`${$}/${O}`)}const Q={mount:()=>{const P=s.createNode(null,"/",Ir|493,0);return P.packPath=G,P.node_ops=E(P.node_ops),P}};if(r.analyzePath(G).exists){try{r.unmount(G)}catch{}try{r.rmdir(G)}catch{}}return r.mkdirTree(G),r.mount(Q,{},G),c}function qo(n,e,r){const s=r.files.filter(d=>d.path!==G&&!d.path.startsWith(`${G}/`)),c=d=>{const u=n.stat(d),h=typeof u.mtime=="number"?u.mtime:Number(u.mtime),w={mode:u.mode&4095,...typeof h=="number"&&Number.isFinite(h)?{mtimeMs:h}:{}};if((u.mode&61440)===Ir){s.push({path:d,type:"directory",...w});for(const y of n.readdir(d))y==="."||y===".."||c(`${d}/${y}`);return}e.dirty.has(d)?s.push({path:d,type:"file",content:es(n.readFile(d)),...w}):s.push({path:d,type:"file",...typeof u.size=="number"?{size:u.size}:{},...w})};return c(G),{files:s}}const ze="/workspace/.supercode/python-requirements.txt",vn=64,Wo=256;async function Jo(n){const e=Ko(n.FS);e.length!==0&&(Bn({door:"pip install",subject:`${e.join(" ")}, recorded in ${ze} by an earlier session`,fix:`a Python project's packages cannot yet be carried as packs; remove ${ze} to run Python without them.`}),await ns(n,e),os(n.FS,await ss(n)))}async function Ho(n,e){e.requirements.length!==0&&(await ns(n,e.requirements),os(n.FS,await ss(n)))}function Go(n){const e=new Map;let r;for(const s of n.split(`
|
|
6
|
+
`)){const c=s.trim();if(c==="[[package]]"){r=void 0;continue}if(c.startsWith("[")&&c!=="[[package]]"){r=void 0;continue}const d=/^name\s*=\s*"([^"]+)"$/u.exec(c);if(d){r=d[1];continue}const u=/^version\s*=\s*"([^"]+)"$/u.exec(c);u&&r&&!e.has(r)&&e.set(r,u[1])}return e}function Yo(n,e){const r=/^[A-Za-z0-9._-]+/u.exec(n.trim())?.[0];if(!r)return n;const s=e.get(r)??e.get(r.toLowerCase())??e.get(r.replace(/_/gu,"-").toLowerCase());return s?`${r}==${s}`:n}function Vo(n,e,r){const s=qe(e[0]??""),c=s==="pip"||s==="pip3"?e.slice(1):(s==="python"||s==="python3")&&e[1]==="-m"&&e[2]==="pip"?e.slice(3):void 0;if(!c)return;if(c[0]!=="install")throw new Error("pip in the tab supports only `pip install <packages> [-r requirements.txt]`, and only as a temporary path: a project's Python dependencies are meant to be prepared on a machine by `npx @volter/browser-substrate dev`.");const d=[];let u=!1;for(let w=1;w<c.length;w+=1){const y=c[w];if(!(y==="--disable-pip-version-check"||y==="-q"||y==="--quiet")){if(y==="-r"||y==="--requirement"){const A=c[++w];if(!A)throw new Error(`${y} requires a file path.`);const g=Xt(A,r);if(!n.analyzePath(g).exists)throw new Error(`pip: requirements file not found: ${g}`);d.push(...is(new TextDecoder().decode(n.readFile(g)))),u=!0;continue}if(y.startsWith("-"))throw new Error(`browser pip does not support option: ${y}`);d.push(y)}}if(d.length===0&&!u)throw new Error("pip install requires at least one package.");const h=Xt("uv.lock",r);if(n.analyzePath(h).exists){const w=Go(new TextDecoder().decode(n.readFile(h)));if(w.size>0){const y=d.map(A=>Yo(A,w));return ot(y),{requirements:y,lockfile:{file:"uv.lock",pins:w.size}}}}return ot(d),{requirements:d}}async function ns(n,e){ot(e),Bn({door:"pip install",subject:e.join(" "),detail:{requirements:e.join(" ")},fix:"a Python project's packages cannot yet be carried as packs, so the tab cannot provide them."})}async function ss(n){const e=await n.runPythonAsync(`
|
|
7
|
+
import json, micropip
|
|
8
|
+
json.dumps(sorted(
|
|
9
|
+
f"{name}=={package.version}"
|
|
10
|
+
for name, package in micropip.list().items()
|
|
11
|
+
if name.lower() != "micropip"
|
|
12
|
+
))
|
|
13
|
+
`),r=JSON.parse(String(e));if(!Array.isArray(r)||r.some(s=>typeof s!="string"))throw new Error("micropip returned an invalid package inventory.");return ot(r),r}function Ko(n){return n.analyzePath(ze).exists?is(new TextDecoder().decode(n.readFile(ze))):[]}function os(n,e){ot(e),n.mkdirTree(ze.slice(0,ze.lastIndexOf("/"))),n.writeFile(ze,new TextEncoder().encode(`${e.join(`
|
|
14
|
+
`)}
|
|
15
|
+
`))}function is(n){const e=n.split(/\r?\n/u).map(r=>r.replace(/\s+#.*$/u,"").trim()).filter(Boolean);return ot(e),e}function ot(n){if(n.length>vn)throw new Error(`Python package limit is ${vn}.`);for(const e of n){if(!e||e.length>Wo||/[\u0000-\u001f\u007f]/u.test(e))throw new Error("Invalid Python package requirement.");if(/^(?:https?|emfs):/iu.test(e)||e.endsWith(".whl"))throw new Error("Direct wheel URLs are not accepted; install a named package from the verified index.")}}const Qo=String.raw`
|
|
16
|
+
import asyncio, base64, json
|
|
17
|
+
from urllib.parse import urlsplit
|
|
18
|
+
|
|
19
|
+
async def __browser_runtime_start_asgi_lifespan():
|
|
20
|
+
queue = asyncio.Queue()
|
|
21
|
+
ready = asyncio.Event()
|
|
22
|
+
shutdown_ready = asyncio.Event()
|
|
23
|
+
outcome = {"startup_error": None, "shutdown_error": None, "responded": False, "unsupported": False}
|
|
24
|
+
lifespan_state = {}
|
|
25
|
+
|
|
26
|
+
async def receive():
|
|
27
|
+
return await queue.get()
|
|
28
|
+
|
|
29
|
+
async def send(message):
|
|
30
|
+
outcome["responded"] = True
|
|
31
|
+
kind = message.get("type")
|
|
32
|
+
if kind == "lifespan.startup.complete":
|
|
33
|
+
ready.set()
|
|
34
|
+
elif kind == "lifespan.startup.failed":
|
|
35
|
+
outcome["startup_error"] = str(message.get("message", "ASGI lifespan startup failed"))
|
|
36
|
+
ready.set()
|
|
37
|
+
elif kind == "lifespan.shutdown.complete":
|
|
38
|
+
shutdown_ready.set()
|
|
39
|
+
elif kind == "lifespan.shutdown.failed":
|
|
40
|
+
outcome["shutdown_error"] = str(message.get("message", "ASGI lifespan shutdown failed"))
|
|
41
|
+
shutdown_ready.set()
|
|
42
|
+
|
|
43
|
+
async def run():
|
|
44
|
+
try:
|
|
45
|
+
await globals()["__browser_runtime_asgi_app"](
|
|
46
|
+
{"type": "lifespan", "asgi": {"version": "3.0", "spec_version": "2.0"}, "state": lifespan_state},
|
|
47
|
+
receive,
|
|
48
|
+
send,
|
|
49
|
+
)
|
|
50
|
+
except BaseException as error:
|
|
51
|
+
if outcome["responded"]:
|
|
52
|
+
outcome["startup_error"] = str(error)
|
|
53
|
+
else:
|
|
54
|
+
outcome["unsupported"] = True
|
|
55
|
+
ready.set()
|
|
56
|
+
shutdown_ready.set()
|
|
57
|
+
|
|
58
|
+
task = asyncio.create_task(run())
|
|
59
|
+
globals()["__browser_runtime_asgi_lifespan_task"] = task
|
|
60
|
+
globals()["__browser_runtime_asgi_lifespan_queue"] = queue
|
|
61
|
+
globals()["__browser_runtime_asgi_lifespan_outcome"] = outcome
|
|
62
|
+
globals()["__browser_runtime_asgi_lifespan_shutdown_ready"] = shutdown_ready
|
|
63
|
+
globals()["__browser_runtime_asgi_lifespan_state"] = lifespan_state
|
|
64
|
+
await queue.put({"type": "lifespan.startup"})
|
|
65
|
+
try:
|
|
66
|
+
await asyncio.wait_for(ready.wait(), timeout=5)
|
|
67
|
+
except TimeoutError:
|
|
68
|
+
task.cancel()
|
|
69
|
+
raise RuntimeError("ASGI lifespan startup timed out")
|
|
70
|
+
if outcome["startup_error"] is not None:
|
|
71
|
+
task.cancel()
|
|
72
|
+
raise RuntimeError(outcome["startup_error"])
|
|
73
|
+
|
|
74
|
+
async def __browser_runtime_stop_asgi_lifespan():
|
|
75
|
+
task = globals().get("__browser_runtime_asgi_lifespan_task")
|
|
76
|
+
queue = globals().get("__browser_runtime_asgi_lifespan_queue")
|
|
77
|
+
outcome = globals().get("__browser_runtime_asgi_lifespan_outcome", {})
|
|
78
|
+
shutdown_ready = globals().get("__browser_runtime_asgi_lifespan_shutdown_ready")
|
|
79
|
+
if task is None or queue is None or shutdown_ready is None or outcome.get("unsupported") or task.done():
|
|
80
|
+
return
|
|
81
|
+
await queue.put({"type": "lifespan.shutdown"})
|
|
82
|
+
try:
|
|
83
|
+
await asyncio.wait_for(shutdown_ready.wait(), timeout=5)
|
|
84
|
+
except TimeoutError:
|
|
85
|
+
task.cancel()
|
|
86
|
+
raise RuntimeError("ASGI lifespan shutdown timed out")
|
|
87
|
+
if outcome.get("shutdown_error") is not None:
|
|
88
|
+
task.cancel()
|
|
89
|
+
raise RuntimeError(outcome["shutdown_error"])
|
|
90
|
+
await asyncio.wait_for(task, timeout=5)
|
|
91
|
+
|
|
92
|
+
__browser_runtime_asgi_sockets = {}
|
|
93
|
+
|
|
94
|
+
async def __browser_runtime_stop_asgi_websockets():
|
|
95
|
+
sockets = list(globals()["__browser_runtime_asgi_sockets"].values())
|
|
96
|
+
if not sockets:
|
|
97
|
+
return
|
|
98
|
+
for socket in sockets:
|
|
99
|
+
await socket["queue"].put({"type": "websocket.disconnect", "code": 1001, "reason": "Server shutdown"})
|
|
100
|
+
tasks = [socket["task"] for socket in sockets]
|
|
101
|
+
try:
|
|
102
|
+
await asyncio.wait_for(asyncio.gather(*tasks, return_exceptions=True), timeout=2)
|
|
103
|
+
except TimeoutError:
|
|
104
|
+
for task in tasks:
|
|
105
|
+
if not task.done():
|
|
106
|
+
task.cancel()
|
|
107
|
+
|
|
108
|
+
async def __browser_runtime_open_asgi_websocket(payload_json):
|
|
109
|
+
payload = json.loads(payload_json)
|
|
110
|
+
connection_id = int(payload["connectionId"])
|
|
111
|
+
parsed = urlsplit(payload["path"])
|
|
112
|
+
protocols = [str(value) for value in payload.get("protocols", [])]
|
|
113
|
+
queue = asyncio.Queue()
|
|
114
|
+
state = {"accepted": False, "closed": False}
|
|
115
|
+
|
|
116
|
+
async def receive():
|
|
117
|
+
return await queue.get()
|
|
118
|
+
|
|
119
|
+
async def send(message):
|
|
120
|
+
kind = message.get("type")
|
|
121
|
+
if kind == "websocket.accept":
|
|
122
|
+
if state["accepted"] or state["closed"]:
|
|
123
|
+
raise RuntimeError("ASGI WebSocket accepted more than once")
|
|
124
|
+
state["accepted"] = True
|
|
125
|
+
globals()["__browser_runtime_asgi_websocket_callback"](json.dumps({
|
|
126
|
+
"type": "opened",
|
|
127
|
+
"connectionId": connection_id,
|
|
128
|
+
"protocol": str(message.get("subprotocol") or ""),
|
|
129
|
+
}))
|
|
130
|
+
elif kind == "websocket.send":
|
|
131
|
+
if not state["accepted"] or state["closed"]:
|
|
132
|
+
raise RuntimeError("ASGI WebSocket sent data before accept or after close")
|
|
133
|
+
if message.get("bytes") is not None:
|
|
134
|
+
frame = {
|
|
135
|
+
"type": "message",
|
|
136
|
+
"connectionId": connection_id,
|
|
137
|
+
"kind": "binary",
|
|
138
|
+
"base64": base64.b64encode(bytes(message["bytes"])).decode("ascii"),
|
|
139
|
+
}
|
|
140
|
+
else:
|
|
141
|
+
frame = {
|
|
142
|
+
"type": "message",
|
|
143
|
+
"connectionId": connection_id,
|
|
144
|
+
"kind": "text",
|
|
145
|
+
"text": str(message.get("text", "")),
|
|
146
|
+
}
|
|
147
|
+
globals()["__browser_runtime_asgi_websocket_callback"](json.dumps(frame))
|
|
148
|
+
elif kind == "websocket.close":
|
|
149
|
+
if state["closed"]:
|
|
150
|
+
return
|
|
151
|
+
state["closed"] = True
|
|
152
|
+
globals()["__browser_runtime_asgi_websocket_callback"](json.dumps({
|
|
153
|
+
"type": "close",
|
|
154
|
+
"connectionId": connection_id,
|
|
155
|
+
"code": int(message.get("code", 1000)),
|
|
156
|
+
"reason": str(message.get("reason", "")),
|
|
157
|
+
"clean": True,
|
|
158
|
+
}))
|
|
159
|
+
|
|
160
|
+
async def run():
|
|
161
|
+
try:
|
|
162
|
+
scope = {
|
|
163
|
+
"type": "websocket",
|
|
164
|
+
"asgi": {"version": "3.0", "spec_version": "2.3"},
|
|
165
|
+
"scheme": "ws",
|
|
166
|
+
"path": parsed.path,
|
|
167
|
+
"raw_path": parsed.path.encode("utf-8"),
|
|
168
|
+
"query_string": parsed.query.encode("ascii"),
|
|
169
|
+
"root_path": "",
|
|
170
|
+
"headers": [],
|
|
171
|
+
"server": ("localhost", int(globals()["__browser_runtime_asgi_port"])),
|
|
172
|
+
"client": ("127.0.0.1", 0),
|
|
173
|
+
"subprotocols": protocols,
|
|
174
|
+
"state": dict(globals().get("__browser_runtime_asgi_lifespan_state", {})),
|
|
175
|
+
}
|
|
176
|
+
await globals()["__browser_runtime_asgi_app"](scope, receive, send)
|
|
177
|
+
except BaseException as error:
|
|
178
|
+
globals()["__browser_runtime_asgi_websocket_callback"](json.dumps({
|
|
179
|
+
"type": "error",
|
|
180
|
+
"connectionId": connection_id,
|
|
181
|
+
"error": str(error),
|
|
182
|
+
}))
|
|
183
|
+
if not state["closed"]:
|
|
184
|
+
state["closed"] = True
|
|
185
|
+
globals()["__browser_runtime_asgi_websocket_callback"](json.dumps({
|
|
186
|
+
"type": "close",
|
|
187
|
+
"connectionId": connection_id,
|
|
188
|
+
"code": 1011,
|
|
189
|
+
"reason": "Python ASGI WebSocket failed",
|
|
190
|
+
"clean": False,
|
|
191
|
+
}))
|
|
192
|
+
finally:
|
|
193
|
+
if not state["closed"]:
|
|
194
|
+
state["closed"] = True
|
|
195
|
+
globals()["__browser_runtime_asgi_websocket_callback"](json.dumps({
|
|
196
|
+
"type": "close",
|
|
197
|
+
"connectionId": connection_id,
|
|
198
|
+
"code": 1000,
|
|
199
|
+
"reason": "",
|
|
200
|
+
"clean": True,
|
|
201
|
+
}))
|
|
202
|
+
globals()["__browser_runtime_asgi_sockets"].pop(connection_id, None)
|
|
203
|
+
|
|
204
|
+
task = asyncio.create_task(run())
|
|
205
|
+
globals()["__browser_runtime_asgi_sockets"][connection_id] = {"queue": queue, "task": task}
|
|
206
|
+
await queue.put({"type": "websocket.connect"})
|
|
207
|
+
await asyncio.sleep(0)
|
|
208
|
+
|
|
209
|
+
async def __browser_runtime_asgi_websocket_event(payload_json):
|
|
210
|
+
payload = json.loads(payload_json)
|
|
211
|
+
connection_id = int(payload["connectionId"])
|
|
212
|
+
socket = globals()["__browser_runtime_asgi_sockets"].get(connection_id)
|
|
213
|
+
if socket is None:
|
|
214
|
+
return
|
|
215
|
+
if payload["type"] == "websocket-message":
|
|
216
|
+
data = payload["data"]
|
|
217
|
+
if data["kind"] == "binary":
|
|
218
|
+
event = {"type": "websocket.receive", "bytes": base64.b64decode(data.get("base64", ""))}
|
|
219
|
+
else:
|
|
220
|
+
event = {"type": "websocket.receive", "text": str(data.get("text", ""))}
|
|
221
|
+
else:
|
|
222
|
+
event = {
|
|
223
|
+
"type": "websocket.disconnect",
|
|
224
|
+
"code": int(payload.get("code", 1000)),
|
|
225
|
+
"reason": str(payload.get("reason", "")),
|
|
226
|
+
}
|
|
227
|
+
await socket["queue"].put(event)
|
|
228
|
+
await asyncio.sleep(0)
|
|
229
|
+
|
|
230
|
+
def __browser_runtime_asgi_headers(response_start):
|
|
231
|
+
response_headers = {}
|
|
232
|
+
for raw_name, raw_value in response_start.get("headers", []):
|
|
233
|
+
name = bytes(raw_name).decode("latin-1")
|
|
234
|
+
value = bytes(raw_value).decode("latin-1")
|
|
235
|
+
if name in response_headers:
|
|
236
|
+
existing = response_headers[name]
|
|
237
|
+
response_headers[name] = existing + [value] if isinstance(existing, list) else [existing, value]
|
|
238
|
+
else:
|
|
239
|
+
response_headers[name] = value
|
|
240
|
+
return response_headers
|
|
241
|
+
|
|
242
|
+
async def __browser_runtime_handle_asgi(payload_json, streaming=False):
|
|
243
|
+
payload = json.loads(payload_json)
|
|
244
|
+
parsed = urlsplit(payload["url"])
|
|
245
|
+
body = base64.b64decode(payload.get("bodyBase64", ""))
|
|
246
|
+
request_headers = [
|
|
247
|
+
(str(name).lower().encode("latin-1"), str(value).encode("latin-1"))
|
|
248
|
+
for name, value in payload.get("headers", {}).items()
|
|
249
|
+
]
|
|
250
|
+
scope = {
|
|
251
|
+
"type": "http",
|
|
252
|
+
"asgi": {"version": "3.0", "spec_version": "2.3"},
|
|
253
|
+
"http_version": "1.1",
|
|
254
|
+
"method": payload["method"],
|
|
255
|
+
"scheme": "http",
|
|
256
|
+
"path": parsed.path,
|
|
257
|
+
"raw_path": parsed.path.encode("utf-8"),
|
|
258
|
+
"query_string": parsed.query.encode("ascii"),
|
|
259
|
+
"root_path": "",
|
|
260
|
+
"headers": request_headers,
|
|
261
|
+
"server": ("localhost", int(globals()["__browser_runtime_asgi_port"])),
|
|
262
|
+
"client": ("127.0.0.1", 0),
|
|
263
|
+
"state": dict(globals().get("__browser_runtime_asgi_lifespan_state", {})),
|
|
264
|
+
}
|
|
265
|
+
received = False
|
|
266
|
+
response_start = None
|
|
267
|
+
response_chunks = []
|
|
268
|
+
stream_started = False
|
|
269
|
+
|
|
270
|
+
def start_stream():
|
|
271
|
+
nonlocal response_start, stream_started
|
|
272
|
+
if stream_started:
|
|
273
|
+
return
|
|
274
|
+
response_start = response_start or {"status": 500, "headers": []}
|
|
275
|
+
globals()["__browser_runtime_asgi_stream_callback"](json.dumps({
|
|
276
|
+
"type": "start",
|
|
277
|
+
"statusCode": int(response_start["status"]),
|
|
278
|
+
"statusMessage": "",
|
|
279
|
+
"headers": __browser_runtime_asgi_headers(response_start),
|
|
280
|
+
}))
|
|
281
|
+
stream_started = True
|
|
282
|
+
|
|
283
|
+
async def receive():
|
|
284
|
+
nonlocal received
|
|
285
|
+
if received:
|
|
286
|
+
return {"type": "http.disconnect"}
|
|
287
|
+
received = True
|
|
288
|
+
return {"type": "http.request", "body": body, "more_body": False}
|
|
289
|
+
|
|
290
|
+
async def send(message):
|
|
291
|
+
nonlocal response_start
|
|
292
|
+
if message["type"] == "http.response.start":
|
|
293
|
+
response_start = message
|
|
294
|
+
if streaming:
|
|
295
|
+
start_stream()
|
|
296
|
+
elif message["type"] == "http.response.body":
|
|
297
|
+
chunk = bytes(message.get("body", b""))
|
|
298
|
+
if streaming:
|
|
299
|
+
start_stream()
|
|
300
|
+
if chunk:
|
|
301
|
+
globals()["__browser_runtime_asgi_stream_callback"](json.dumps({
|
|
302
|
+
"type": "chunk",
|
|
303
|
+
"bodyBase64": base64.b64encode(chunk).decode("ascii"),
|
|
304
|
+
}))
|
|
305
|
+
else:
|
|
306
|
+
response_chunks.append(chunk)
|
|
307
|
+
|
|
308
|
+
await globals()["__browser_runtime_asgi_app"](scope, receive, send)
|
|
309
|
+
response_start = response_start or {"status": 500, "headers": []}
|
|
310
|
+
if streaming:
|
|
311
|
+
start_stream()
|
|
312
|
+
return "{}"
|
|
313
|
+
return json.dumps({
|
|
314
|
+
"statusCode": int(response_start["status"]),
|
|
315
|
+
"statusMessage": "",
|
|
316
|
+
"headers": __browser_runtime_asgi_headers(response_start),
|
|
317
|
+
"bodyBase64": base64.b64encode(b"".join(response_chunks)).decode("ascii"),
|
|
318
|
+
})
|
|
319
|
+
`;class Xo{pyodide;port;commit;acknowledgements=new Map;nextRequestId=1;requestQueue=Promise.resolve();constructor(e,r,s){this.pyodide=e,this.port=r,this.commit=s,e.globals.set("__browser_runtime_asgi_websocket_callback",c=>{const d=JSON.parse(String(c));d.type==="opened"?this.port.postMessage({type:"websocket-opened",connectionId:d.connectionId,protocol:d.protocol??""}):d.type==="message"?this.port.postMessage({type:"websocket-message",connectionId:d.connectionId,data:d.kind==="binary"?{kind:"binary",base64:d.base64??""}:{kind:"text",text:d.text??""}}):d.type==="close"?this.port.postMessage({type:"websocket-close",connectionId:d.connectionId,code:d.code??1e3,reason:d.reason??"",clean:d.clean!==!1}):d.type==="error"&&this.port.postMessage({type:"websocket-error",connectionId:d.connectionId,error:d.error??"Python ASGI WebSocket failed."})}),r.onmessage=c=>{const d=c.data;if(d.type==="ack"){const u=this.acknowledgements.get(d.requestId);if(!u)return;this.acknowledgements.delete(d.requestId),u(d.result);return}this.requestQueue=this.requestQueue.then(()=>d.type==="http-request"?this.handleRequest(d):this.handleWebSocket(d))},r.start()}listenStatic(e,r){return this.listen({type:"listen",requestId:0,port:e,server:"static",root:r})}listenWsgi(e){return this.listen({type:"listen",requestId:0,port:e,server:"wsgi"})}listenAsgi(e){return this.listen({type:"listen",requestId:0,port:e,server:"asgi"})}idle(){return this.requestQueue}listen(e){const r=this.nextRequestId++;return new Promise(s=>{const c=setTimeout(()=>{this.acknowledgements.delete(r),s(-110)},5e3);this.acknowledgements.set(r,d=>{clearTimeout(c),s(d)}),this.port.postMessage({...e,requestId:r})})}async handleRequest(e){const r=e.application==="asgi"&&e.streaming===!0;try{const s=JSON.stringify({method:e.method,url:e.url,headers:e.headers,bodyBase64:e.bodyBase64}),c=e.application==="asgi"?"__browser_runtime_handle_asgi":"__browser_runtime_handle_wsgi";r&&this.pyodide.globals.set("__browser_runtime_asgi_stream_callback",w=>{const y=JSON.parse(String(w));y.type==="start"?this.port.postMessage({type:"http-stream-start",requestId:e.requestId,statusCode:y.statusCode??500,statusMessage:y.statusMessage??"",headers:y.headers??{}}):y.type==="chunk"&&this.port.postMessage({type:"http-stream-chunk",requestId:e.requestId,bodyBase64:y.bodyBase64??""})});const d=e.application==="asgi"?`await ${c}(${JSON.stringify(s)}, ${r?"True":"False"})`:`${c}(${JSON.stringify(s)})`,u=await this.pyodide.runPythonAsync(d);if(r){await this.commit(),this.port.postMessage({type:"http-stream-end",requestId:e.requestId});return}const h=JSON.parse(String(u));await this.commit(),this.port.postMessage({type:"http-response",requestId:e.requestId,...h})}catch(s){if(e.application==="asgi"&&e.streaming===!0){this.port.postMessage({type:"http-stream-error",requestId:e.requestId,error:s instanceof Error?s.message:String(s)});return}this.port.postMessage({type:"http-response",requestId:e.requestId,statusCode:500,statusMessage:"Internal Server Error",headers:{},bodyBase64:"",error:s instanceof Error?s.message:String(s)})}finally{r&&this.pyodide.globals.set("__browser_runtime_asgi_stream_callback",()=>{})}}async handleWebSocket(e){const r=JSON.stringify(e);try{e.type==="websocket-open"?await this.pyodide.runPythonAsync(`await __browser_runtime_open_asgi_websocket(${JSON.stringify(r)})`):await this.pyodide.runPythonAsync(`await __browser_runtime_asgi_websocket_event(${JSON.stringify(r)})`)}catch(s){this.port.postMessage({type:"websocket-error",connectionId:e.connectionId,error:s instanceof Error?s.message:String(s)}),this.port.postMessage({type:"websocket-close",connectionId:e.connectionId,code:1011,reason:"Python ASGI WebSocket failed",clean:!1})}}}function Zo(n,e,r,s){return`
|
|
320
|
+
import os, sys
|
|
321
|
+
os.chdir(${JSON.stringify(n)})
|
|
322
|
+
os.environ.clear()
|
|
323
|
+
os.environ.update(${JSON.stringify(e)})
|
|
324
|
+
# This lane is an event loop: Django's guard against blocking inside one
|
|
325
|
+
# would refuse every ORM call, and blocking is what everything here does.
|
|
326
|
+
os.environ.setdefault("DJANGO_ALLOW_ASYNC_UNSAFE", "true")
|
|
327
|
+
sys.argv = ${JSON.stringify(r)}
|
|
328
|
+
globals()["__name__"] = "__main__"
|
|
329
|
+
try:
|
|
330
|
+
import flask as __browser_runtime_flask
|
|
331
|
+
def __browser_runtime_flask_run(self, host=None, port=None, **options):
|
|
332
|
+
globals()["__browser_runtime_wsgi_app"] = self
|
|
333
|
+
globals()["__browser_runtime_wsgi_port"] = int(port or 5000)
|
|
334
|
+
__browser_runtime_flask.Flask.run = __browser_runtime_flask_run
|
|
335
|
+
except ImportError:
|
|
336
|
+
pass
|
|
337
|
+
exec(compile(${JSON.stringify(s)}, ${JSON.stringify(r[0]??"<string>")}, "exec"), globals(), globals())
|
|
338
|
+
`}const In=String.raw`
|
|
339
|
+
import base64, io, json, sys
|
|
340
|
+
from urllib.parse import urlsplit
|
|
341
|
+
|
|
342
|
+
def __browser_runtime_handle_wsgi(payload_json):
|
|
343
|
+
payload = json.loads(payload_json)
|
|
344
|
+
parsed = urlsplit(payload["url"])
|
|
345
|
+
body = base64.b64decode(payload.get("bodyBase64", ""))
|
|
346
|
+
headers = payload.get("headers", {})
|
|
347
|
+
environ = {
|
|
348
|
+
"REQUEST_METHOD": payload["method"],
|
|
349
|
+
"SCRIPT_NAME": "",
|
|
350
|
+
"PATH_INFO": parsed.path,
|
|
351
|
+
"QUERY_STRING": parsed.query,
|
|
352
|
+
"SERVER_NAME": "localhost",
|
|
353
|
+
"SERVER_PORT": str(globals()["__browser_runtime_wsgi_port"]),
|
|
354
|
+
"SERVER_PROTOCOL": "HTTP/1.1",
|
|
355
|
+
"REMOTE_ADDR": "127.0.0.1",
|
|
356
|
+
"wsgi.version": (1, 0),
|
|
357
|
+
"wsgi.url_scheme": "http",
|
|
358
|
+
"wsgi.input": io.BytesIO(body),
|
|
359
|
+
"wsgi.errors": sys.stderr,
|
|
360
|
+
"wsgi.multithread": False,
|
|
361
|
+
"wsgi.multiprocess": False,
|
|
362
|
+
"wsgi.run_once": False,
|
|
363
|
+
}
|
|
364
|
+
for name, value in headers.items():
|
|
365
|
+
key = name.upper().replace("-", "_")
|
|
366
|
+
if key == "CONTENT_TYPE":
|
|
367
|
+
environ["CONTENT_TYPE"] = value
|
|
368
|
+
elif key == "CONTENT_LENGTH":
|
|
369
|
+
environ["CONTENT_LENGTH"] = value
|
|
370
|
+
else:
|
|
371
|
+
environ["HTTP_" + key] = value
|
|
372
|
+
if body and "CONTENT_LENGTH" not in environ:
|
|
373
|
+
environ["CONTENT_LENGTH"] = str(len(body))
|
|
374
|
+
captured = {}
|
|
375
|
+
def start_response(status, response_headers, exc_info=None):
|
|
376
|
+
captured["status"] = status
|
|
377
|
+
captured["headers"] = response_headers
|
|
378
|
+
chunks = globals()["__browser_runtime_wsgi_app"](environ, start_response)
|
|
379
|
+
try:
|
|
380
|
+
response_body = b"".join(chunks)
|
|
381
|
+
finally:
|
|
382
|
+
if hasattr(chunks, "close"):
|
|
383
|
+
chunks.close()
|
|
384
|
+
status_parts = captured.get("status", "500 Internal Server Error").split(" ", 1)
|
|
385
|
+
response_headers = {}
|
|
386
|
+
for name, value in captured.get("headers", []):
|
|
387
|
+
if name in response_headers:
|
|
388
|
+
existing = response_headers[name]
|
|
389
|
+
response_headers[name] = existing + [value] if isinstance(existing, list) else [existing, value]
|
|
390
|
+
else:
|
|
391
|
+
response_headers[name] = value
|
|
392
|
+
return json.dumps({
|
|
393
|
+
"statusCode": int(status_parts[0]),
|
|
394
|
+
"statusMessage": status_parts[1] if len(status_parts) > 1 else "",
|
|
395
|
+
"headers": response_headers,
|
|
396
|
+
"bodyBase64": base64.b64encode(response_body).decode("ascii"),
|
|
397
|
+
})
|
|
398
|
+
`,On=16*1024*1024,ei=3e4,ti=5*6e4;class ri{port;applyChanges;enabled;nextRequestId=1;constructor(e,r,s,c=!0){this.port=r,this.applyChanges=s,this.enabled=c,e.globals.set("__browser_runtime_run_process",d=>this.run(d)),e.globals.set("__browser_runtime_process_exchange",d=>this.exchange(d))}run(e){this.assertEnabled();const r=JSON.parse(e),s=new SharedArrayBuffer(2*Int32Array.BYTES_PER_ELEMENT),c=new SharedArrayBuffer(On),d=new Int32Array(s),u=this.nextRequestId++;if(this.port.postMessage({type:"process-run",requestId:u,...r,control:s,response:c}),Atomics.wait(d,0,0,ei)==="timed-out"||Atomics.load(d,0)!==1)throw this.port.postMessage({type:"process-cancel",requestId:u}),new Error("Python subprocess timed out after 30 seconds.");const w=Atomics.load(d,1);if(!Number.isSafeInteger(w)||w<0||w>c.byteLength)throw new Error("Invalid Python subprocess response.");const y=new Uint8Array(w);y.set(new Uint8Array(c,0,w));const A=JSON.parse(new TextDecoder().decode(y));if(A.error)throw new Error(A.error);if(!A.result||!A.patch)throw new Error("Incomplete Python subprocess response.");return this.applyChanges(A.patch),JSON.stringify(A.result)}exchange(e){this.assertEnabled();const r=JSON.parse(e),s=new SharedArrayBuffer(2*Int32Array.BYTES_PER_ELEMENT),c=new SharedArrayBuffer(On),d=new Int32Array(s);if(this.port.postMessage({...r,requestId:this.nextRequestId++,control:s,response:c}),Atomics.wait(d,0,0,ti)==="timed-out"||Atomics.load(d,0)!==1)throw new Error("Python Popen operation timed out after 5 minutes.");const h=Atomics.load(d,1);if(!Number.isSafeInteger(h)||h<0||h>c.byteLength)throw new Error("Invalid Python Popen response.");const w=new Uint8Array(h);w.set(new Uint8Array(c,0,h));const y=JSON.parse(new TextDecoder().decode(w));if(y.patch&&this.applyChanges(y.patch),y.error)throw new Error(y.error);return JSON.stringify(y)}assertEnabled(){if(!this.enabled)throw new Error("Python subprocesses require a same-origin shared-memory worker.")}}const ni=String.raw`
|
|
399
|
+
import base64 as __browser_runtime_base64
|
|
400
|
+
import codecs as _browser_runtime_codecs
|
|
401
|
+
import json as __browser_runtime_json
|
|
402
|
+
import os
|
|
403
|
+
import shlex as __browser_runtime_shlex
|
|
404
|
+
import subprocess as __browser_runtime_subprocess
|
|
405
|
+
import sys
|
|
406
|
+
|
|
407
|
+
def __browser_runtime_subprocess_run(args, *, stdin=None, input=None, stdout=None, stderr=None,
|
|
408
|
+
capture_output=False, shell=False, cwd=None, timeout=None,
|
|
409
|
+
check=False, encoding=None, errors=None, text=False, env=None, **kwargs):
|
|
410
|
+
if timeout is not None:
|
|
411
|
+
raise NotImplementedError("browser subprocess timeout is fixed at 30 seconds")
|
|
412
|
+
if kwargs:
|
|
413
|
+
raise NotImplementedError("unsupported browser subprocess options: " + ", ".join(kwargs.keys()))
|
|
414
|
+
if capture_output:
|
|
415
|
+
if stdout is not None or stderr is not None:
|
|
416
|
+
raise ValueError("stdout and stderr arguments may not be used with capture_output")
|
|
417
|
+
stdout = stderr = __browser_runtime_subprocess.PIPE
|
|
418
|
+
if stdin not in (None, __browser_runtime_subprocess.PIPE, __browser_runtime_subprocess.DEVNULL):
|
|
419
|
+
raise NotImplementedError("browser subprocess stdin must be PIPE, DEVNULL, or None")
|
|
420
|
+
if stdout not in (None, __browser_runtime_subprocess.PIPE, __browser_runtime_subprocess.DEVNULL):
|
|
421
|
+
raise NotImplementedError("browser subprocess stdout must be PIPE, DEVNULL, or None")
|
|
422
|
+
if stderr not in (None, __browser_runtime_subprocess.PIPE, __browser_runtime_subprocess.DEVNULL, __browser_runtime_subprocess.STDOUT):
|
|
423
|
+
raise NotImplementedError("browser subprocess stderr must be PIPE, DEVNULL, STDOUT, or None")
|
|
424
|
+
if input is not None and stdin not in (None, __browser_runtime_subprocess.PIPE):
|
|
425
|
+
raise ValueError("stdin argument may not be used with input")
|
|
426
|
+
if isinstance(args, str):
|
|
427
|
+
command = args if shell else __browser_runtime_shlex.join([args])
|
|
428
|
+
else:
|
|
429
|
+
command = __browser_runtime_shlex.join([str(value) for value in args])
|
|
430
|
+
if input is None:
|
|
431
|
+
input_bytes = b""
|
|
432
|
+
elif isinstance(input, str):
|
|
433
|
+
input_bytes = input.encode(encoding or "utf-8", errors or "strict")
|
|
434
|
+
else:
|
|
435
|
+
input_bytes = bytes(input)
|
|
436
|
+
payload = __browser_runtime_json.dumps({
|
|
437
|
+
"command": command,
|
|
438
|
+
"cwd": os.path.abspath(cwd or os.getcwd()),
|
|
439
|
+
"env": {str(key): str(value) for key, value in (env or os.environ).items()},
|
|
440
|
+
"stdinBase64": __browser_runtime_base64.b64encode(input_bytes).decode("ascii"),
|
|
441
|
+
})
|
|
442
|
+
result = __browser_runtime_json.loads(__browser_runtime_run_process(payload))
|
|
443
|
+
use_text = text or encoding is not None or errors is not None
|
|
444
|
+
out_text, err_text = result["stdout"], result["stderr"]
|
|
445
|
+
if stderr == __browser_runtime_subprocess.STDOUT:
|
|
446
|
+
out_text += err_text
|
|
447
|
+
err_text = ""
|
|
448
|
+
if stdout != __browser_runtime_subprocess.PIPE:
|
|
449
|
+
if stdout != __browser_runtime_subprocess.DEVNULL and out_text:
|
|
450
|
+
sys.stdout.write(out_text)
|
|
451
|
+
completed_stdout = None
|
|
452
|
+
else:
|
|
453
|
+
completed_stdout = out_text if use_text else out_text.encode(encoding or "utf-8", errors or "strict")
|
|
454
|
+
if stderr not in (__browser_runtime_subprocess.PIPE, __browser_runtime_subprocess.STDOUT):
|
|
455
|
+
if stderr != __browser_runtime_subprocess.DEVNULL and err_text:
|
|
456
|
+
sys.stderr.write(err_text)
|
|
457
|
+
completed_stderr = None
|
|
458
|
+
else:
|
|
459
|
+
completed_stderr = None if stderr == __browser_runtime_subprocess.STDOUT else (err_text if use_text else err_text.encode(encoding or "utf-8", errors or "strict"))
|
|
460
|
+
completed = __browser_runtime_subprocess.CompletedProcess(args, int(result["exitCode"]), completed_stdout, completed_stderr)
|
|
461
|
+
if check:
|
|
462
|
+
completed.check_returncode()
|
|
463
|
+
return completed
|
|
464
|
+
|
|
465
|
+
def __browser_runtime_subprocess_call(*popenargs, timeout=None, **kwargs):
|
|
466
|
+
return __browser_runtime_subprocess_run(*popenargs, timeout=timeout, **kwargs).returncode
|
|
467
|
+
|
|
468
|
+
def __browser_runtime_subprocess_check_call(*popenargs, **kwargs):
|
|
469
|
+
result = __browser_runtime_subprocess_run(*popenargs, **kwargs)
|
|
470
|
+
result.check_returncode()
|
|
471
|
+
return 0
|
|
472
|
+
|
|
473
|
+
def __browser_runtime_process_command(args, shell):
|
|
474
|
+
if isinstance(args, str):
|
|
475
|
+
return args if shell else __browser_runtime_shlex.join([args])
|
|
476
|
+
return __browser_runtime_shlex.join([str(value) for value in args])
|
|
477
|
+
|
|
478
|
+
def __browser_runtime_process_action(payload):
|
|
479
|
+
return __browser_runtime_json.loads(__browser_runtime_process_exchange(__browser_runtime_json.dumps(payload)))
|
|
480
|
+
|
|
481
|
+
_browser_runtime_base64 = __browser_runtime_base64
|
|
482
|
+
_browser_runtime_process_action = __browser_runtime_process_action
|
|
483
|
+
_browser_runtime_process_command = __browser_runtime_process_command
|
|
484
|
+
_browser_runtime_subprocess = __browser_runtime_subprocess
|
|
485
|
+
|
|
486
|
+
class __browser_runtime_BrowserPipe:
|
|
487
|
+
def __init__(self, process, stream, writable=False):
|
|
488
|
+
self.process = process
|
|
489
|
+
self.stream = stream
|
|
490
|
+
self.writable = writable
|
|
491
|
+
self.closed = False
|
|
492
|
+
self._buffer = "" if self.process.text_mode else bytearray()
|
|
493
|
+
self._decoder = _browser_runtime_codecs.getincrementaldecoder(self.process.encoding)(self.process.errors) if self.process.text_mode else None
|
|
494
|
+
self._eof = False
|
|
495
|
+
|
|
496
|
+
def write(self, value):
|
|
497
|
+
if not self.writable or self.closed:
|
|
498
|
+
raise ValueError("write to closed or read-only browser subprocess pipe")
|
|
499
|
+
raw = value.encode(self.process.encoding, self.process.errors) if isinstance(value, str) else bytes(value)
|
|
500
|
+
result = self.process._action("write", stdinBase64=_browser_runtime_base64.b64encode(raw).decode("ascii"))
|
|
501
|
+
return len(value) if isinstance(value, str) else int(result.get("written", len(raw)))
|
|
502
|
+
|
|
503
|
+
def flush(self):
|
|
504
|
+
if self.closed:
|
|
505
|
+
raise ValueError("flush of closed browser subprocess pipe")
|
|
506
|
+
|
|
507
|
+
def close(self):
|
|
508
|
+
if self.closed:
|
|
509
|
+
return
|
|
510
|
+
self.closed = True
|
|
511
|
+
if self.writable:
|
|
512
|
+
self.process._action("close")
|
|
513
|
+
|
|
514
|
+
def _pull(self, maximum=65536):
|
|
515
|
+
if self.writable or self.closed:
|
|
516
|
+
raise ValueError("read from closed or write-only browser subprocess pipe")
|
|
517
|
+
if self._eof:
|
|
518
|
+
return
|
|
519
|
+
result = self.process._action("read", stream=self.stream, maximum=maximum)
|
|
520
|
+
raw = _browser_runtime_base64.b64decode(result.get("dataBase64", ""))
|
|
521
|
+
self._eof = bool(result.get("eof", False))
|
|
522
|
+
if self.process.text_mode:
|
|
523
|
+
self._buffer += self._decoder.decode(raw, final=self._eof)
|
|
524
|
+
elif raw:
|
|
525
|
+
self._buffer.extend(raw)
|
|
526
|
+
|
|
527
|
+
def read(self, size=-1):
|
|
528
|
+
if size is None or size < 0:
|
|
529
|
+
while not self._eof:
|
|
530
|
+
self._pull()
|
|
531
|
+
value = self._buffer if self.process.text_mode else bytes(self._buffer)
|
|
532
|
+
self._buffer = "" if self.process.text_mode else bytearray()
|
|
533
|
+
return value
|
|
534
|
+
if size == 0:
|
|
535
|
+
return "" if self.process.text_mode else b""
|
|
536
|
+
while not self._buffer and not self._eof:
|
|
537
|
+
self._pull(min(max(size, 1), 1048576))
|
|
538
|
+
count = min(size, len(self._buffer))
|
|
539
|
+
value = self._buffer[:count] if self.process.text_mode else bytes(self._buffer[:count])
|
|
540
|
+
if self.process.text_mode:
|
|
541
|
+
self._buffer = self._buffer[count:]
|
|
542
|
+
else:
|
|
543
|
+
del self._buffer[:count]
|
|
544
|
+
return value
|
|
545
|
+
|
|
546
|
+
def readline(self, size=-1):
|
|
547
|
+
limit = None if size is None or size < 0 else size
|
|
548
|
+
newline_value = "\n" if self.process.text_mode else b"\n"
|
|
549
|
+
while not self._eof and newline_value not in self._buffer and (limit is None or len(self._buffer) < limit):
|
|
550
|
+
self._pull()
|
|
551
|
+
newline = self._buffer.find(newline_value)
|
|
552
|
+
count = len(self._buffer) if newline < 0 else newline + 1
|
|
553
|
+
if limit is not None:
|
|
554
|
+
count = min(count, limit)
|
|
555
|
+
value = self._buffer[:count] if self.process.text_mode else bytes(self._buffer[:count])
|
|
556
|
+
if self.process.text_mode:
|
|
557
|
+
self._buffer = self._buffer[count:]
|
|
558
|
+
else:
|
|
559
|
+
del self._buffer[:count]
|
|
560
|
+
return value
|
|
561
|
+
|
|
562
|
+
def readlines(self, hint=-1):
|
|
563
|
+
lines = []
|
|
564
|
+
total = 0
|
|
565
|
+
while True:
|
|
566
|
+
line = self.readline()
|
|
567
|
+
if not line:
|
|
568
|
+
break
|
|
569
|
+
lines.append(line)
|
|
570
|
+
total += len(line)
|
|
571
|
+
if hint is not None and hint >= 0 and total >= hint:
|
|
572
|
+
break
|
|
573
|
+
return lines
|
|
574
|
+
|
|
575
|
+
def __iter__(self):
|
|
576
|
+
return self
|
|
577
|
+
|
|
578
|
+
def __next__(self):
|
|
579
|
+
line = self.readline()
|
|
580
|
+
if not line:
|
|
581
|
+
raise StopIteration
|
|
582
|
+
return line
|
|
583
|
+
|
|
584
|
+
def __enter__(self):
|
|
585
|
+
return self
|
|
586
|
+
|
|
587
|
+
def __exit__(self, exc_type, value, traceback):
|
|
588
|
+
self.close()
|
|
589
|
+
|
|
590
|
+
_browser_runtime_BrowserPipe = __browser_runtime_BrowserPipe
|
|
591
|
+
|
|
592
|
+
class __browser_runtime_BrowserPopen:
|
|
593
|
+
def __init__(self, args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None,
|
|
594
|
+
preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None,
|
|
595
|
+
universal_newlines=None, startupinfo=None, creationflags=0,
|
|
596
|
+
restore_signals=True, start_new_session=False, pass_fds=(), *, user=None,
|
|
597
|
+
group=None, extra_groups=None, encoding=None, errors=None, text=None,
|
|
598
|
+
umask=-1, pipesize=-1, process_group=None):
|
|
599
|
+
unsupported = {
|
|
600
|
+
"executable": executable, "preexec_fn": preexec_fn, "startupinfo": startupinfo,
|
|
601
|
+
"creationflags": creationflags or None, "start_new_session": start_new_session or None,
|
|
602
|
+
"pass_fds": pass_fds or None, "user": user, "group": group,
|
|
603
|
+
"extra_groups": extra_groups, "umask": None if umask == -1 else umask,
|
|
604
|
+
"pipesize": None if pipesize == -1 else pipesize, "process_group": process_group,
|
|
605
|
+
}
|
|
606
|
+
rejected = [name for name, value in unsupported.items() if value is not None]
|
|
607
|
+
if rejected:
|
|
608
|
+
raise NotImplementedError("unsupported browser Popen options: " + ", ".join(rejected))
|
|
609
|
+
if stdin not in (None, _browser_runtime_subprocess.PIPE, _browser_runtime_subprocess.DEVNULL):
|
|
610
|
+
raise NotImplementedError("browser Popen stdin must be PIPE, DEVNULL, or None")
|
|
611
|
+
if stdout not in (None, _browser_runtime_subprocess.PIPE, _browser_runtime_subprocess.DEVNULL):
|
|
612
|
+
raise NotImplementedError("browser Popen stdout must be PIPE, DEVNULL, or None")
|
|
613
|
+
if stderr not in (None, _browser_runtime_subprocess.PIPE, _browser_runtime_subprocess.DEVNULL, _browser_runtime_subprocess.STDOUT):
|
|
614
|
+
raise NotImplementedError("browser Popen stderr must be PIPE, DEVNULL, STDOUT, or None")
|
|
615
|
+
self.args = args
|
|
616
|
+
self.returncode = None
|
|
617
|
+
self.encoding = encoding or "utf-8"
|
|
618
|
+
self.errors = errors or "strict"
|
|
619
|
+
self.text_mode = bool(text or universal_newlines or encoding is not None or errors is not None)
|
|
620
|
+
self._stdout_mode = stdout
|
|
621
|
+
self._stderr_mode = stderr
|
|
622
|
+
self._stdout = "" if self.text_mode else b""
|
|
623
|
+
self._stderr = "" if self.text_mode else b""
|
|
624
|
+
self._completion = None
|
|
625
|
+
result = _browser_runtime_process_action({
|
|
626
|
+
"type": "process-start",
|
|
627
|
+
"command": _browser_runtime_process_command(args, shell),
|
|
628
|
+
"cwd": os.path.abspath(cwd or os.getcwd()),
|
|
629
|
+
"env": {str(key): str(value) for key, value in (env or os.environ).items()},
|
|
630
|
+
"stdinPipe": stdin == _browser_runtime_subprocess.PIPE,
|
|
631
|
+
"stdoutPipe": stdout == _browser_runtime_subprocess.PIPE,
|
|
632
|
+
"stderrPipe": stderr == _browser_runtime_subprocess.PIPE,
|
|
633
|
+
"stderrToStdout": stderr == _browser_runtime_subprocess.STDOUT,
|
|
634
|
+
})
|
|
635
|
+
self.pid = int(result["childId"])
|
|
636
|
+
self.stdin = _browser_runtime_BrowserPipe(self, "stdin", True) if stdin == _browser_runtime_subprocess.PIPE else None
|
|
637
|
+
self.stdout = _browser_runtime_BrowserPipe(self, "stdout") if stdout == _browser_runtime_subprocess.PIPE else None
|
|
638
|
+
self.stderr = _browser_runtime_BrowserPipe(self, "stderr") if stderr == _browser_runtime_subprocess.PIPE else None
|
|
639
|
+
|
|
640
|
+
def _action(self, action, **values):
|
|
641
|
+
return _browser_runtime_process_action({"type": "process-action", "childId": self.pid, "action": action, **values})
|
|
642
|
+
|
|
643
|
+
def _wait_result(self, input_value=None, close_stdin=False):
|
|
644
|
+
if self._completion is not None:
|
|
645
|
+
return self._completion
|
|
646
|
+
raw_input = b""
|
|
647
|
+
if input_value is not None:
|
|
648
|
+
if self.stdin is None:
|
|
649
|
+
raise ValueError("Cannot send input after starting communication without stdin=PIPE")
|
|
650
|
+
raw_input = input_value.encode(self.encoding, self.errors) if isinstance(input_value, str) else bytes(input_value)
|
|
651
|
+
result = self._action(
|
|
652
|
+
"wait",
|
|
653
|
+
stdinBase64=_browser_runtime_base64.b64encode(raw_input).decode("ascii"),
|
|
654
|
+
closeStdin=close_stdin,
|
|
655
|
+
)
|
|
656
|
+
completed = result["result"]
|
|
657
|
+
self.returncode = int(completed["exitCode"])
|
|
658
|
+
out_text, err_text = completed["stdout"], completed["stderr"]
|
|
659
|
+
if self._stdout_mode == _browser_runtime_subprocess.PIPE:
|
|
660
|
+
self._stdout = ("" if self.text_mode else b"") if self.stdout.closed else self.stdout.read()
|
|
661
|
+
out_text = ""
|
|
662
|
+
else:
|
|
663
|
+
self._stdout = "" if self.text_mode else b""
|
|
664
|
+
if self._stderr_mode == _browser_runtime_subprocess.PIPE:
|
|
665
|
+
self._stderr = ("" if self.text_mode else b"") if self.stderr.closed else self.stderr.read()
|
|
666
|
+
err_text = ""
|
|
667
|
+
else:
|
|
668
|
+
self._stderr = "" if self.text_mode else b""
|
|
669
|
+
if self._stderr_mode == _browser_runtime_subprocess.STDOUT and self._stdout_mode != _browser_runtime_subprocess.PIPE:
|
|
670
|
+
out_text += err_text
|
|
671
|
+
err_text = ""
|
|
672
|
+
if self._stdout_mode not in (_browser_runtime_subprocess.PIPE, _browser_runtime_subprocess.DEVNULL) and out_text:
|
|
673
|
+
sys.stdout.write(out_text)
|
|
674
|
+
if self._stderr_mode not in (_browser_runtime_subprocess.PIPE, _browser_runtime_subprocess.DEVNULL, _browser_runtime_subprocess.STDOUT) and err_text:
|
|
675
|
+
sys.stderr.write(err_text)
|
|
676
|
+
self._completion = completed
|
|
677
|
+
self._action("release")
|
|
678
|
+
return completed
|
|
679
|
+
|
|
680
|
+
def poll(self):
|
|
681
|
+
if self.returncode is None:
|
|
682
|
+
value = self._action("poll").get("returncode")
|
|
683
|
+
if value is not None:
|
|
684
|
+
self.returncode = int(value)
|
|
685
|
+
return self.returncode
|
|
686
|
+
|
|
687
|
+
def wait(self, timeout=None):
|
|
688
|
+
if timeout is not None:
|
|
689
|
+
raise NotImplementedError("browser Popen wait timeout is fixed at five minutes")
|
|
690
|
+
self._wait_result()
|
|
691
|
+
return self.returncode
|
|
692
|
+
|
|
693
|
+
def communicate(self, input=None, timeout=None):
|
|
694
|
+
if timeout is not None:
|
|
695
|
+
raise NotImplementedError("browser Popen communicate timeout is fixed at five minutes")
|
|
696
|
+
self._wait_result(input, self.stdin is not None)
|
|
697
|
+
if self.stdin is not None:
|
|
698
|
+
self.stdin.closed = True
|
|
699
|
+
return (
|
|
700
|
+
self._stdout if self._stdout_mode == _browser_runtime_subprocess.PIPE else None,
|
|
701
|
+
self._stderr if self._stderr_mode == _browser_runtime_subprocess.PIPE else None,
|
|
702
|
+
)
|
|
703
|
+
|
|
704
|
+
def terminate(self):
|
|
705
|
+
if self.returncode is None:
|
|
706
|
+
self._action("terminate")
|
|
707
|
+
|
|
708
|
+
kill = terminate
|
|
709
|
+
|
|
710
|
+
def send_signal(self, sig):
|
|
711
|
+
self.terminate()
|
|
712
|
+
|
|
713
|
+
def __enter__(self):
|
|
714
|
+
return self
|
|
715
|
+
|
|
716
|
+
def __exit__(self, exc_type, value, traceback):
|
|
717
|
+
if self.stdin is not None and not self.stdin.closed:
|
|
718
|
+
self.stdin.close()
|
|
719
|
+
self.wait()
|
|
720
|
+
|
|
721
|
+
__browser_runtime_subprocess.run = __browser_runtime_subprocess_run
|
|
722
|
+
__browser_runtime_subprocess.call = __browser_runtime_subprocess_call
|
|
723
|
+
__browser_runtime_subprocess.check_call = __browser_runtime_subprocess_check_call
|
|
724
|
+
__browser_runtime_subprocess.Popen = __browser_runtime_BrowserPopen
|
|
725
|
+
`,Nn=-4,kr=3;class Zt{channel;control;payload;encoder=new TextEncoder;decoder=new TextDecoder("utf-8",{fatal:!0});nextRequestId=1;constructor(e){this.channel=e,this.control=new Int32Array(e.control),this.payload=new Uint8Array(e.payload)}static waited={calls:0,ms:0};request(e){const r=performance.now();try{return this.requestNow(e)}finally{Zt.waited.calls+=1,Zt.waited.ms+=performance.now()-r}}requestNow(e){if(Atomics.load(this.control,kr))return{result:Nn};const r=this.encoder.encode(JSON.stringify(e));if(r.byteLength>this.payload.byteLength)return{result:-90};if(Atomics.load(this.control,0)!==0)throw new Error("Concurrent file-lock RPC on one channel.");const s=this.nextRequestId;this.nextRequestId=s>=1073741821?1:s+2,this.control.fill(0,0,kr),this.payload.set(r),Atomics.store(this.control,1,r.byteLength),Atomics.store(this.control,0,s);try{for(this.channel.port.postMessage(s);Atomics.load(this.control,0)!==s+1;){if(Atomics.load(this.control,kr))return{result:Nn};const u=Atomics.load(this.control,0);u!==s+1&&Atomics.wait(this.control,0,u)}const c=Atomics.load(this.control,2);if(c<1||c>this.payload.byteLength)return{result:-5};const d=JSON.parse(this.decoder.decode(this.payload.slice(0,c)));return!d||!Number.isSafeInteger(d.result)?{result:-5}:d}finally{Atomics.store(this.control,0,0)}}}var Ie;(function(n){n[n.Inspect=1]="Inspect",n[n.Read=2]="Read",n[n.WriteStart=3]="WriteStart",n[n.WriteChunk=4]="WriteChunk",n[n.WriteFinish=5]="WriteFinish",n[n.Remove=6]="Remove"})(Ie||(Ie={}));const Wt=512*1024,Tn=256*1024*1024,Mn=5,si=new TextEncoder,oi=new TextDecoder("utf-8",{fatal:!0});class ii{channel;control;payload;nextRequestId=1;constructor(e){this.channel=e,this.control=new Int32Array(e.control),this.payload=new Uint8Array(e.payload)}pull(e){const r=this.call(Ie.Inspect,{path:e});if(!r.exists)return;const s=Or(r.length,0,Tn),c=new Uint8Array(s);for(let d=0;d<s;d+=Wt){const u=Math.min(Wt,s-d),h=this.call(Ie.Read,{path:e,offset:d,length:u}),w=Vn(h.content);if(w.byteLength!==u)throw new Error("Invalid coherent file response.");c.set(w,d)}return{bytes:c,...r.mode===void 0?{}:{mode:r.mode},...r.mtimeMs===void 0?{}:{mtimeMs:r.mtimeMs},parents:ai(e,r.parents)}}push(e,r){if(!r){this.call(Ie.Remove,{path:e});return}if(r.bytes.byteLength>Tn)throw new Error("Coherent file exceeds 256 MiB.");this.call(Ie.WriteStart,{path:e,length:r.bytes.byteLength,...r.mode===void 0?{}:{mode:r.mode},...r.mtimeMs===void 0?{}:{mtimeMs:r.mtimeMs},...r.parents===void 0?{}:{parents:r.parents}});for(let s=0;s<r.bytes.byteLength;s+=Wt){const c=r.bytes.subarray(s,s+Wt);this.call(Ie.WriteChunk,{offset:s,content:Eo(c)})}this.call(Ie.WriteFinish)}call(e,r={}){const s=()=>{if(Atomics.load(this.control,Mn))throw Object.assign(new Error("Browser file coherence was cancelled."),{errno:125})};s();const c=si.encode(JSON.stringify(r));if(c.byteLength>this.payload.byteLength)throw new Error("File-coherence request is too large.");if(Atomics.load(this.control,0)!==0)throw new Error("Concurrent file-coherence RPC on one channel.");const d=this.nextRequestId;this.nextRequestId=d>=1073741821?1:d+2,this.control.fill(0,0,Mn),this.payload.set(c),Atomics.store(this.control,1,e),Atomics.store(this.control,3,c.byteLength),Atomics.store(this.control,0,d);try{for(this.channel.port.postMessage(d);Atomics.load(this.control,0)!==d+1;){s();const y=Atomics.load(this.control,0);y!==d+1&&Atomics.wait(this.control,0,y)}const u=Atomics.load(this.control,2),h=Or(Atomics.load(this.control,4),0,this.payload.byteLength),w=h===0?void 0:JSON.parse(oi.decode(this.payload.slice(0,h)));if(u<0)throw Object.assign(new Error(`Browser file coherence failed with ${u}.`),{errno:-u});return w}finally{Atomics.store(this.control,0,0)}}}function Fn(n){const e=n.replace(/-(?:journal|shm|wal)$/u,"");return[e,`${e}-journal`,`${e}-wal`,`${e}-shm`]}function ai(n,e){if(e===void 0)return[];const r=new Set(ci(n));if(!Array.isArray(e)||e.length>r.size)throw Ue("Invalid coherent file parents.");return e.map(s=>{if(typeof s!="object"||s===null)throw Ue("Invalid coherent file parent.");const c=s,d=as(c.path);if(!r.delete(d))throw Ue("Coherent metadata must name distinct ancestors of its file.");return{path:d,...li(c)}})}function ci(n){const e=[];for(const r of as(n).split("/"))!r||r==="."||(r===".."?e.pop():e.push(r));return e.slice(0,-1).map((r,s)=>`/${e.slice(0,s+1).join("/")}`)}function li(n){const e=n.mode===void 0?void 0:Or(n.mode,0,65535),r=n.mtimeMs===void 0?void 0:ui(n.mtimeMs);return{...e===void 0?{}:{mode:e},...r===void 0?{}:{mtimeMs:r}}}function as(n){const e=di(n);if(!e.startsWith("/")||e.length>4096||e.includes("\0"))throw Ue("Invalid coherent file path.");return e}function di(n){if(typeof n!="string")throw Ue("Expected a string.");return n}function Or(n,e,r){if(!Number.isSafeInteger(n)||n<e||n>r)throw Ue("Expected a bounded integer.");return n}function ui(n){if(typeof n!="number"||!Number.isFinite(n))throw Ue("Expected a finite number.");return n}function Ue(n){return Object.assign(new Error(n),{errno:22})}class fi{filesystem;locks;coherence;counts=new Map;owner;constructor(e,r,s,c){this.filesystem=e,this.locks=r,this.coherence=s,this.owner=`${c}:sqlite`}install(e){return e.globals.set("_browser_runtime_sqlite_acquire",r=>this.acquire(r)),e.globals.set("_browser_runtime_sqlite_release",r=>this.release(r)),e.runPythonAsync(pi)}releaseAll(){for(const e of[...this.counts.keys()])this.counts.set(e,1),this.release(e)}acquire(e){if(!e.startsWith("/")||e.includes("\0"))throw new Error("Invalid SQLite path.");const r=this.counts.get(e)??0;if(r>0){this.counts.set(e,r+1);return}const s=this.locks.request({operation:"set",owner:this.owner,namespace:"posix",path:e,range:{start:0},mode:"write",pid:1,blocking:!0});if(s.result<0)throw new Error(`SQLite lock acquisition failed with ${s.result}.`);try{for(const c of Fn(e))this.writeLocal(c,this.coherence.pull(c));this.counts.set(e,1)}catch(c){throw this.locks.request({operation:"unlock",owner:this.owner,namespace:"posix",path:e,range:{start:0}}),c}}release(e){const r=this.counts.get(e)??0;if(r>1){this.counts.set(e,r-1);return}if(r===0)return;for(const c of Fn(e))this.coherence.push(c,this.readLocal(c));const s=this.locks.request({operation:"unlock",owner:this.owner,namespace:"posix",path:e,range:{start:0}});if(s.result<0)throw new Error(`SQLite lock release failed with ${s.result}.`);this.counts.delete(e)}readLocal(e){if(!this.filesystem.analyzePath(e).exists)return;const r=this.filesystem.stat(e);if((r.mode&61440)===16384)return;const s=typeof r.mtime=="number"?r.mtime:Number(r.mtime);return{bytes:this.filesystem.readFile(e),mode:r.mode&4095,...typeof s=="number"&&Number.isFinite(s)?{mtimeMs:s}:{}}}writeLocal(e,r){if(!r){this.filesystem.analyzePath(e).exists&&(this.filesystem.stat(e).mode&61440)!==16384&&this.filesystem.unlink(e);return}const s=e.slice(0,e.lastIndexOf("/"))||"/";this.filesystem.analyzePath(s).exists||this.filesystem.mkdirTree(s),this.filesystem.writeFile(e,r.bytes),r.mode!==void 0&&this.filesystem.chmod(e,r.mode),r.mtimeMs!==void 0&&this.filesystem.utime(e,r.mtimeMs,r.mtimeMs)}}const pi=String.raw`
|
|
726
|
+
import os as _browser_runtime_sqlite_os, sqlite3 as _browser_runtime_sqlite
|
|
727
|
+
|
|
728
|
+
_browser_runtime_sqlite_connect_original = _browser_runtime_sqlite.connect
|
|
729
|
+
|
|
730
|
+
def _browser_runtime_sqlite_path(database, uri=False):
|
|
731
|
+
try:
|
|
732
|
+
value = _browser_runtime_sqlite_os.fspath(database)
|
|
733
|
+
except TypeError:
|
|
734
|
+
return None
|
|
735
|
+
if isinstance(value, bytes):
|
|
736
|
+
value = _browser_runtime_sqlite_os.fsdecode(value)
|
|
737
|
+
if value == ":memory:" or value.startswith("file::memory:"):
|
|
738
|
+
return None
|
|
739
|
+
if uri and value.startswith("file:"):
|
|
740
|
+
value = value[5:].split("?", 1)[0]
|
|
741
|
+
return _browser_runtime_sqlite_os.path.abspath(value)
|
|
742
|
+
|
|
743
|
+
class _BrowserRuntimeSqliteConnection(_browser_runtime_sqlite.Connection):
|
|
744
|
+
def __init__(self, *args, **kwargs):
|
|
745
|
+
database = args[0] if args else kwargs.get("database")
|
|
746
|
+
self._browser_runtime_path = _browser_runtime_sqlite_path(database, bool(kwargs.get("uri", False)))
|
|
747
|
+
self._browser_runtime_released = False
|
|
748
|
+
if self._browser_runtime_path:
|
|
749
|
+
_browser_runtime_sqlite_acquire(self._browser_runtime_path)
|
|
750
|
+
try:
|
|
751
|
+
super().__init__(*args, **kwargs)
|
|
752
|
+
except BaseException:
|
|
753
|
+
if self._browser_runtime_path:
|
|
754
|
+
_browser_runtime_sqlite_release(self._browser_runtime_path)
|
|
755
|
+
self._browser_runtime_released = True
|
|
756
|
+
raise
|
|
757
|
+
|
|
758
|
+
def close(self):
|
|
759
|
+
if self._browser_runtime_released:
|
|
760
|
+
return super().close()
|
|
761
|
+
try:
|
|
762
|
+
return super().close()
|
|
763
|
+
finally:
|
|
764
|
+
if self._browser_runtime_path:
|
|
765
|
+
_browser_runtime_sqlite_release(self._browser_runtime_path)
|
|
766
|
+
self._browser_runtime_released = True
|
|
767
|
+
|
|
768
|
+
def _browser_runtime_sqlite_connect(database, *args, **kwargs):
|
|
769
|
+
factory = kwargs.get("factory")
|
|
770
|
+
if factory is not None and factory is not _browser_runtime_sqlite.Connection:
|
|
771
|
+
raise NotImplementedError("custom sqlite connection factories are not yet supported by browser coherence")
|
|
772
|
+
kwargs["factory"] = _BrowserRuntimeSqliteConnection
|
|
773
|
+
return _browser_runtime_sqlite_connect_original(database, *args, **kwargs)
|
|
774
|
+
|
|
775
|
+
_browser_runtime_sqlite.connect = _browser_runtime_sqlite_connect
|
|
776
|
+
_browser_runtime_sqlite.dbapi2.connect = _browser_runtime_sqlite_connect
|
|
777
|
+
`,cs=globalThis;let hi=1;const Nr=new Map;let ls=!1,$n=!1,Tr,yt,ds,mt;function er(n){const e=vo(mt??yt??{files:[]},n);return mt=n,e}function wi(n,e){const r=mt??yt??{files:[]};Do(n.FS,e,r),mt=xo(r,e)}let nt=n=>Zn(n.FS,yt??{files:[]}),Sr,mi=1;const Mr=new Map;Ai();cs.onmessage=n=>{const e=n.data;if(e.type==="run"){yi(e);return}if(e.type==="prepare"){Xn(e.runtimeIndexUrl,e.runtimeSnapshot).catch(()=>{});return}if(e.type==="shutdown"){Si();return}if(e.type==="network-response"||e.type==="network-error"){const s=Mr.get(e.requestId);if(!s)return;Mr.delete(e.requestId),e.type==="network-error"?s.reject(new Error(e.error)):s.resolve(new Response(e.body,{status:e.status,statusText:e.statusText,headers:e.headers}));return}const r=Nr.get(e.commitId);r&&(Nr.delete(e.commitId),e.error?r.reject(new Error(e.error)):r.resolve())};async function yi(n){let e,r;yt=n.filesystem,mt=n.filesystem;try{if(e=await Xn(n.runtimeIndexUrl,n.runtimeSnapshot),e.setStdout({batched:E=>ce({type:"stdout",chunk:`${E}
|
|
778
|
+
`})}),e.setStderr({batched:E=>ce({type:"stderr",chunk:`${E}
|
|
779
|
+
`})}),n.store){const E=await _o({navigator:cs.navigator},n.store.projectId);if(!E)throw new Error("The project's store is not there to read.");Sr=E;const B=jo(e.FS,E);if(!B)throw new Error("This Pyodide exposes no filesystem to mount the workspace over.");nt=D=>qo(D.FS,B,n.filesystem)}else Co(e.FS,n.filesystem),nt=E=>Zn(E.FS,n.filesystem);n.fileLocks&&n.fileCoherence&&(r=new fi(e.FS,new Zt(n.fileLocks.channel),new ii(n.fileCoherence),n.fileLocks.owner),await r.install(e)),ds=()=>nt(e);const s=()=>ki(nt(e)),c=new Xo(e,n.serverPort,s);new ri(e,n.serverPort,E=>wi(e,E),n.sharedMemoryChannels),await e.runPythonAsync(ni),await e.runPythonAsync(`
|
|
780
|
+
import base64 as __browser_runtime_stdin_base64, io as __browser_runtime_stdin_io, sys as __browser_runtime_stdin_sys
|
|
781
|
+
__browser_runtime_stdin_sys.stdin = __browser_runtime_stdin_io.TextIOWrapper(
|
|
782
|
+
__browser_runtime_stdin_io.BytesIO(__browser_runtime_stdin_base64.b64decode(${JSON.stringify(n.stdinBase64)})),
|
|
783
|
+
encoding="utf-8",
|
|
784
|
+
)
|
|
785
|
+
`),Ln(async()=>{r?.releaseAll(),await s(),Jt(130,e)});const d=gi(n.argv,n.cwd);if(d){const E=await c.listenStatic(d.port,d.root);if(E<0)throw new Error(`python http.server could not listen on port ${d.port} (${E}).`);ce({type:"stdout",chunk:`Serving HTTP on 0.0.0.0 port ${d.port} (http://localhost:${d.port}/) ...
|
|
786
|
+
`}),await Ht();return}await Jo(e);const u=Vo(e.FS,n.argv,n.cwd);if(u){await Ho(e,u),ce({type:"stdout",chunk:`Successfully installed ${u.requirements.join(" ")}
|
|
787
|
+
`}),r?.releaseAll(),Jt(0,e);return}const h=Ei(n.argv);if(h){await e.runPythonAsync(`
|
|
788
|
+
import importlib, os, sys
|
|
789
|
+
os.chdir(${JSON.stringify(n.cwd)})
|
|
790
|
+
os.environ.clear()
|
|
791
|
+
os.environ.update(${JSON.stringify(n.env)})
|
|
792
|
+
sys.argv = ${JSON.stringify(n.argv)}
|
|
793
|
+
if ${JSON.stringify(n.cwd)} not in sys.path:
|
|
794
|
+
sys.path.insert(0, ${JSON.stringify(n.cwd)})
|
|
795
|
+
__browser_runtime_asgi_module = importlib.import_module(${JSON.stringify(h.module)})
|
|
796
|
+
__browser_runtime_asgi_app = __browser_runtime_asgi_module
|
|
797
|
+
for __browser_runtime_asgi_part in ${JSON.stringify(h.attribute.split("."))}:
|
|
798
|
+
__browser_runtime_asgi_app = getattr(__browser_runtime_asgi_app, __browser_runtime_asgi_part)
|
|
799
|
+
__browser_runtime_asgi_port = ${h.port}
|
|
800
|
+
`),await e.runPythonAsync(Qo),await e.runPythonAsync("await __browser_runtime_start_asgi_lifespan()"),await s();const E=await c.listenAsgi(h.port);if(E<0)throw new Error(`Python ASGI app could not listen on port ${h.port} (${E}).`);ce({type:"stdout",chunk:`Serving Python ASGI app on http://localhost:${h.port}/ ...
|
|
801
|
+
`}),Ln(async()=>{await c.idle(),await e.runPythonAsync("await __browser_runtime_stop_asgi_websockets()"),await e.runPythonAsync("await __browser_runtime_stop_asgi_lifespan()"),r?.releaseAll(),await s(),Jt(130,e)}),await Ht();return}const w=bi(n.argv,n.env);if(w){await e.runPythonAsync(`
|
|
802
|
+
import importlib, os, sys
|
|
803
|
+
os.chdir(${JSON.stringify(n.cwd)})
|
|
804
|
+
os.environ.clear()
|
|
805
|
+
os.environ.update(${JSON.stringify(n.env)})
|
|
806
|
+
sys.argv = ${JSON.stringify(n.argv)}
|
|
807
|
+
if ${JSON.stringify(n.cwd)} not in sys.path:
|
|
808
|
+
sys.path.insert(0, ${JSON.stringify(n.cwd)})
|
|
809
|
+
__browser_runtime_wsgi_module = importlib.import_module(${JSON.stringify(w.module)})
|
|
810
|
+
__browser_runtime_wsgi_app = __browser_runtime_wsgi_module
|
|
811
|
+
for __browser_runtime_wsgi_part in ${JSON.stringify(w.attribute.split("."))}:
|
|
812
|
+
__browser_runtime_wsgi_app = getattr(__browser_runtime_wsgi_app, __browser_runtime_wsgi_part)
|
|
813
|
+
__browser_runtime_wsgi_port = ${w.port}
|
|
814
|
+
`),await e.runPythonAsync(In),await s();const E=await c.listenWsgi(w.port);if(E<0)throw new Error(`Python WSGI app could not listen on port ${w.port} (${E}).`);ce({type:"stdout",chunk:`Serving Python WSGI app on http://localhost:${w.port}/ ...
|
|
815
|
+
`}),await Ht();return}const{code:y,argv:A}=_i(e.FS,n.argv,n.cwd);await e.runPythonAsync(Zo(n.cwd,n.env,A,y));const g=Number(await e.runPythonAsync("int(globals().get('__browser_runtime_wsgi_port', 0))"));if(g>0){await e.runPythonAsync(In),await s();const E=await c.listenWsgi(g);if(E<0)throw new Error(`Python WSGI app could not listen on port ${g} (${E}).`);ce({type:"stdout",chunk:`Serving Python WSGI app on http://localhost:${g}/ ...
|
|
816
|
+
`}),await Ht();return}r?.releaseAll(),Jt(0,e)}catch(s){try{r?.releaseAll()}catch{}const c=no(s),d=c?s.message:s instanceof Error?s.stack??s.message:String(s);let u={files:[],removed:[]};try{e&&(u=er(nt(e)))}catch{}ce({type:"result",exitCode:c?2:1,patch:u,error:d})}finally{Sr?.close(),Sr=void 0}}function _i(n,e,r){const s=qe(e[0]??""),c=s==="python"||s==="python3"?e.slice(1):e;if(c[0]==="-c"&&c[1]!==void 0)return{code:c[1],argv:["-c",...c.slice(2)]};const d=c[0];if(!d||d.startsWith("-"))throw new Error("usage: python [-c command] | script.py [args...]");const u=Xt(d,r);if(!n.analyzePath(u).exists)throw new Error(`python: can't open file '${d}': No such file or directory`);return{code:new TextDecoder().decode(n.readFile(u)),argv:[d,...c.slice(1)]}}function gi(n,e){const r=qe(n[0]??""),s=r==="python"||r==="python3"?n.slice(1):n;if(s[0]!=="-m"||s[1]!=="http.server")return;let c=8e3,d=e;for(let u=2;u<s.length;u+=1)s[u]==="--directory"&&s[u+1]?d=Xt(s[++u],e):s[u].startsWith("-")||(c=Number(s[u]));if(!Number.isSafeInteger(c)||c<=0||c>65535)throw new Error("http.server port must be 1..65535.");return{port:c,root:d}}function bi(n,e){const r=qe(n[0]??""),s=r==="python"||r==="python3"?n.slice(1):n,c=s[0]==="-m"&&s[1]==="gunicorn"?s.slice(2):qe(s[0]??"")==="gunicorn"?s.slice(1):void 0;if(!c)return;let d=Number(e.PORT??"")||8e3,u;const h=new Set(["-w","--workers","-k","--worker-class","-t","--timeout","--graceful-timeout","--keep-alive","--access-logfile","--error-logfile","--log-level","--log-file","-c","--config","--chdir","-n","--name","-u","--user","-g","--group","--threads","--max-requests"]);for(let A=0;A<c.length;A+=1){const g=c[A];if(g==="--bind"||g==="-b"){const E=c[++A]??"",B=Number(E.slice(E.lastIndexOf(":")+1));Number.isSafeInteger(B)&&B>0&&(d=B)}else if(g.startsWith("--bind=")){const E=Number(g.slice(g.lastIndexOf(":")+1));Number.isSafeInteger(E)&&E>0&&(d=E)}else if(h.has(g))A+=1;else{if(g.startsWith("-"))continue;if(!u)u=g;else throw new Error(`browser gunicorn does not support argument: ${g}`)}}if(!u)throw new Error("gunicorn requires a WSGI target such as wsgi:app.");const[w,y="application"]=u.split(":",2);if(!w||!/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/u.test(w)||!/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/u.test(y))throw new Error("Invalid gunicorn WSGI target.");return{module:w,attribute:y,port:d}}function Ei(n){const e=qe(n[0]??""),r=e==="python"||e==="python3"?n.slice(1):n,s=r[0]==="-m"&&r[1]==="uvicorn"?r.slice(2):qe(r[0]??"")==="uvicorn"?r.slice(1):void 0;if(!s)return;let c=8e3,d;for(let w=0;w<s.length;w+=1)if(s[w]==="--port"&&s[w+1])c=Number(s[++w]);else if(s[w]==="--host"&&s[w+1])w+=1;else{if(s[w]==="--no-access-log")continue;if(s[w].startsWith("-"))throw new Error(`browser uvicorn does not support option: ${s[w]}`);if(!d)d=s[w];else throw new Error(`browser uvicorn does not support argument: ${s[w]}`)}if(!d||!d.includes(":"))throw new Error("uvicorn requires an ASGI target such as main:app.");const[u,h]=d.split(":",2);if(!u||!h||!/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/u.test(u)||!/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/u.test(h))throw new Error("Invalid uvicorn ASGI target.");if(!Number.isSafeInteger(c)||c<=0||c>65535)throw new Error("uvicorn port must be 1..65535.");return{module:u,attribute:h,port:c}}function Jt(n,e){ce({type:"result",exitCode:n,patch:er(nt(e))})}function ki(n){const e=hi++;return new Promise((r,s)=>{Nr.set(e,{resolve:r,reject:s}),ce({type:"commit",commitId:e,patch:er(n)})})}function Ln(n){Tr=n,us()}function Si(){ls=!0,us()}function us(){const n=yt;!ls||$n||!Tr||!n||($n=!0,Tr().catch(e=>ce({type:"result",exitCode:1,patch:er(Pi(n)),error:e instanceof Error?e.stack??e.message:String(e)})))}function Pi(n){try{return ds?.()??n}catch{return n}}function Ht(){return new Promise(()=>{})}function Ai(){Object.defineProperty(globalThis,"fetch",{value:async(e,r)=>{const s=new Request(e,r),c=mi++,d=[];s.headers.forEach((w,y)=>d.push([y,w]));const u=s.method==="GET"||s.method==="HEAD"?new ArrayBuffer(0):await s.arrayBuffer(),h=new Promise((w,y)=>Mr.set(c,{resolve:w,reject:y}));return ce({type:"network-request",requestId:c,purpose:Fo(),url:s.url,method:s.method,headers:d,body:u},[u]),h},configurable:!1,writable:!1});for(const e of["XMLHttpRequest","WebSocket","EventSource","BroadcastChannel","SharedWorker"])try{Object.defineProperty(globalThis,e,{value:void 0,configurable:!1,writable:!1})}catch{}}function ce(n,e=[]){postMessage(n,e)}
|