@volter/browser-substrate 0.1.103 → 0.1.105
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/catalog/demand-input.json +133 -0
- package/dist/boot-screen.d.ts +2 -0
- package/dist/boot-screen.d.ts.map +1 -1
- package/dist/boot-screen.js +1 -1
- package/dist/boot-screen.js.map +1 -1
- package/dist/cli/archive.d.ts +1 -0
- package/dist/cli/archive.d.ts.map +1 -1
- package/dist/cli/archive.js +4 -4
- package/dist/cli/archive.js.map +1 -1
- package/dist/cli/build.d.ts +5 -1
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.js +21 -2
- package/dist/cli/build.js.map +1 -1
- package/dist/cli/cache-root.d.ts +7 -0
- package/dist/cli/cache-root.d.ts.map +1 -0
- package/dist/cli/cache-root.js +24 -0
- package/dist/cli/cache-root.js.map +1 -0
- package/dist/cli/companions.d.ts +1 -1
- package/dist/cli/companions.d.ts.map +1 -1
- package/dist/cli/companions.js +30 -16
- package/dist/cli/companions.js.map +1 -1
- package/dist/cli/dependency-plan-build.d.ts +4 -0
- package/dist/cli/dependency-plan-build.d.ts.map +1 -1
- package/dist/cli/dependency-plan-build.js +111 -30
- package/dist/cli/dependency-plan-build.js.map +1 -1
- package/dist/cli/docker-build.d.ts +1 -0
- package/dist/cli/docker-build.d.ts.map +1 -1
- package/dist/cli/docker-build.js +4 -4
- package/dist/cli/docker-build.js.map +1 -1
- package/dist/cli/dry-run.d.ts +4 -4
- package/dist/cli/dry-run.d.ts.map +1 -1
- package/dist/cli/dry-run.js +10 -9
- package/dist/cli/dry-run.js.map +1 -1
- package/dist/cli/generated-code.d.ts +2 -1
- package/dist/cli/generated-code.d.ts.map +1 -1
- package/dist/cli/generated-code.js +46 -16
- package/dist/cli/generated-code.js.map +1 -1
- package/dist/cli/host-build.d.ts +1 -0
- package/dist/cli/host-build.d.ts.map +1 -1
- package/dist/cli/host-build.js +10 -9
- package/dist/cli/host-build.js.map +1 -1
- package/dist/cli/host-managers.d.ts +3 -1
- package/dist/cli/host-managers.d.ts.map +1 -1
- package/dist/cli/host-managers.js +7 -3
- package/dist/cli/host-managers.js.map +1 -1
- package/dist/cli/image-layers.d.ts.map +1 -1
- package/dist/cli/image-layers.js +5 -2
- package/dist/cli/image-layers.js.map +1 -1
- package/dist/cli/main.d.ts +5 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +97 -34
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/pack-publication.d.ts +2 -2
- package/dist/cli/pack-publication.d.ts.map +1 -1
- package/dist/cli/pack-publication.js +3 -3
- package/dist/cli/pack-publication.js.map +1 -1
- package/dist/cli/package-pack.d.ts +1 -1
- package/dist/cli/package-pack.d.ts.map +1 -1
- package/dist/cli/package-pack.js +7 -4
- package/dist/cli/package-pack.js.map +1 -1
- package/dist/cli/package-packs.d.ts +1 -0
- package/dist/cli/package-packs.d.ts.map +1 -1
- package/dist/cli/package-packs.js +84 -14
- package/dist/cli/package-packs.js.map +1 -1
- package/dist/cli/plan-tarballs.d.ts +1 -0
- package/dist/cli/plan-tarballs.d.ts.map +1 -1
- package/dist/cli/plan-tarballs.js +6 -3
- package/dist/cli/plan-tarballs.js.map +1 -1
- package/dist/cli/preparation-memory.d.ts +17 -0
- package/dist/cli/preparation-memory.d.ts.map +1 -0
- package/dist/cli/preparation-memory.js +367 -0
- package/dist/cli/preparation-memory.js.map +1 -0
- package/dist/cli/project-build.d.ts +1 -0
- package/dist/cli/project-build.d.ts.map +1 -1
- package/dist/cli/project-build.js +100 -71
- package/dist/cli/project-build.js.map +1 -1
- package/dist/cli/provision-catalog.d.ts +49 -0
- package/dist/cli/provision-catalog.d.ts.map +1 -0
- package/dist/cli/provision-catalog.js +72 -0
- package/dist/cli/provision-catalog.js.map +1 -0
- package/dist/cli/provision-demand.d.ts +45 -0
- package/dist/cli/provision-demand.d.ts.map +1 -0
- package/dist/cli/provision-demand.js +208 -0
- package/dist/cli/provision-demand.js.map +1 -0
- package/dist/cli/rolldown-binding.d.ts +1 -1
- package/dist/cli/rolldown-binding.d.ts.map +1 -1
- package/dist/cli/rolldown-binding.js +8 -4
- package/dist/cli/rolldown-binding.js.map +1 -1
- package/dist/cli/serve.d.ts +3 -0
- package/dist/cli/serve.d.ts.map +1 -1
- package/dist/cli/serve.js +9 -2
- package/dist/cli/serve.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +75 -31
- package/dist/index.js.map +1 -1
- package/dist/origin-reset.d.ts +4 -0
- package/dist/origin-reset.d.ts.map +1 -0
- package/dist/origin-reset.js +76 -0
- package/dist/origin-reset.js.map +1 -0
- package/dist/program-dom.d.ts +2 -0
- package/dist/program-dom.d.ts.map +1 -1
- package/dist/program-dom.js +11 -1
- package/dist/program-dom.js.map +1 -1
- package/dist/program-types.d.ts +2 -0
- package/dist/program-types.d.ts.map +1 -1
- package/dist/shell/assets/browser-opfs-filesystem-worker-CmF6UKMW.js +3 -0
- package/dist/shell/assets/browser-sandbox-bridge-C8nlSsT2.js +237 -0
- package/dist/shell/assets/{filesystem-host-DJbFuokb.js → filesystem-host-BzPlXSri.js} +1 -1
- package/dist/shell/assets/filesystem-host-Pq9IHKRx.js +3 -0
- package/dist/shell/assets/filesystem-worker-CC3pSXUP.js +5 -0
- package/dist/shell/assets/{fork-worker-BXY2kfdX.js → fork-worker-4YKQ4KTo.js} +1 -1
- package/dist/shell/assets/{node-execution-worker-7e8e0c5321ca0d10.js → node-execution-worker-3ddf5efbaa427e9d.js} +8 -8
- package/dist/shell/assets/{sandbox-bMeKqKBn.js → sandbox-mhFzIWaQ.js} +1 -1
- package/dist/shell/assets/{shell-DLIQ6jHu.js → shell-BZbhxnju.js} +763 -757
- package/dist/shell/assets/worker-BmHEnCyv.js +816 -0
- package/dist/shell/assets/{worker-program-worker-B4OcKVtV.js → worker-program-worker-DueMwljE.js} +10 -10
- package/dist/shell/brand/fonts/Geist-Variable.woff2 +0 -0
- package/dist/shell/brand/fonts/GeistMono-Variable.woff2 +0 -0
- package/dist/shell/brand/fonts/InstrumentSerif-Italic.woff2 +0 -0
- package/dist/shell/brand/fonts/InstrumentSerif-Regular.woff2 +0 -0
- package/dist/shell/brand/icons/app-window.svg +1 -0
- package/dist/shell/brand/icons/at-sign.svg +1 -0
- package/dist/shell/brand/icons/box.svg +1 -0
- package/dist/shell/brand/icons/chevron-right.svg +1 -0
- package/dist/shell/brand/icons/folder.svg +1 -0
- package/dist/shell/brand/icons/info.svg +1 -0
- package/dist/shell/brand/icons/key-round.svg +1 -0
- package/dist/shell/brand/icons/link.svg +1 -0
- package/dist/shell/brand/icons/monitor.svg +1 -0
- package/dist/shell/brand/icons/plus.svg +1 -0
- package/dist/shell/brand/icons/rotate-ccw.svg +1 -0
- package/dist/shell/brand/icons/share-2.svg +1 -0
- package/dist/shell/brand/icons/square-arrow-out-up-right.svg +1 -0
- package/dist/shell/brand/icons/terminal.svg +1 -0
- package/dist/shell/brand/icons/x.svg +1 -0
- package/dist/shell/brand/substrate.svg +1 -0
- package/dist/shell/brand/tokens.css +211 -0
- package/dist/shell/brand/wordmark.svg +1 -0
- package/dist/shell/index.html +5 -3
- package/dist/shell/node-execution-worker.js +16 -13
- package/dist/shell/node-host.html +2 -0
- package/dist/shell/python-execution-worker.js +15 -12
- package/dist/shell/python-host.html +2 -0
- package/dist/shell/python-runtime-snapshot.bin +0 -0
- package/dist/shell/python-runtime-snapshot.json +1 -1
- package/dist/shell/sandbox.html +4 -2
- package/dist/toolbar-styles.generated.d.ts +1 -1
- package/dist/toolbar-styles.generated.d.ts.map +1 -1
- package/dist/toolbar-styles.generated.js +1 -1
- package/dist/toolbar-styles.generated.js.map +1 -1
- package/dist/toolbar.d.ts.map +1 -1
- package/dist/toolbar.js +3 -1
- package/dist/toolbar.js.map +1 -1
- package/package.json +1 -1
- package/dist/shell/assets/browser-opfs-filesystem-worker-k2CPzPBU.js +0 -3
- package/dist/shell/assets/browser-sandbox-bridge-BJbQoc4f.js +0 -237
- package/dist/shell/assets/filesystem-host-yMcJuvmT.js +0 -3
- package/dist/shell/assets/filesystem-worker-BbsBhZ9p.js +0 -5
- package/dist/shell/assets/worker-Ce8bBwSJ.js +0 -816
|
@@ -0,0 +1,816 @@
|
|
|
1
|
+
const Fn="EINSTALLREFUSED",Ks="[install-trap-record]";class Qs extends Error{request;code=Fn;constructor(e){super(to(e)),this.request=e,this.name="InstallRefusedError"}}const Xs=Symbol.for("browser-substrate.install-recorder"),Zs=Symbol.for("browser-substrate.install-trapped");function Ln(n){const e=globalThis;throw(e[Zs]??=[]).push(n),e[Xs]?.(n),console.error(`[install-trap] ${n.door}: ${n.subject}`),console.info(`${Ks} ${JSON.stringify(n)}`),new Qs(n)}function eo(n){return typeof n!="object"||n===null?!1:n.code===Fn?!0:/^REFUSED \([^)]+\): /u.test(String(n.message??""))}function to(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 $n=2019846480,Vt=6,oe=6,rt=3,Jt=0,ut=1,Pe=2,Rn=3,Bn=4,Dn=5,Cn=0,zn=1,Un=2,Ht=1,jn=2,qn=4,Gt=32,br=3,Er=["file","directory","symlink"],ro=/[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/u,no=new TextEncoder,so=new TextDecoder;function Wn(n){let e=2166136261;for(let t=0;t<n.length;t+=1)e^=n.charCodeAt(t),e=Math.imul(e,16777619);return e>>>0}function on(n,e){const t=[...n.keys()];for(const x of t)if(ro.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<t.length;x+=1)s.set(t[x],x);for(const x of e.keys())s.has(x)||(s.set(x,t.length),t.push(x));const a=t.length,d=new Map,f=new Uint32Array(a);let h=0;for(let x=0;x<a;x+=1){const A=t[x];let D=!0;for(let H=0;H<A.length;H+=1)if(A.charCodeAt(H)>=128){D=!1;break}D||d.set(x,no.encode(A)),f[x]=D?A.length:d.get(x).length,h+=f[x]}let m=0;for(const x of e.values())m+=x.size;let w=1;for(;w<a*2;)w<<=1;const b=Vt*4,E=kr(b+a*oe*4,8),S=E+a*rt*8,T=S+w*4,g=T+m*4,U=new SharedArrayBuffer(kr(g+h,8));new Uint32Array(U,0,Vt).set([$n,a,w,m,h,n.size]);const J=new Uint32Array(U,b,a*oe),q=new Float64Array(U,E,a*rt),_e=new Uint32Array(U,S,w),N=new Uint32Array(U,T,m),R=new Uint8Array(U,g,h);let L=0,P=0;for(let x=0;x<a;x+=1){const A=t[x],D=x*oe,H=d.get(x);if(H)R.set(H,L);else for(let M=0;M<A.length;M+=1)R[L+M]=A.charCodeAt(M);const v=f[x];J[D+Jt]=L,J[D+ut]=v,L+=v;let K=H?0:Gt;const te=n.get(A);if(te){K|=Ht|Er.indexOf(te.type)<<br,te.pack&&(K|=qn),J[D+Rn]=te.mode;const M=x*rt;q[M+Cn]=te.mtimeMs,q[M+zn]=te.offset,q[M+Un]=te.length}const ve=e.get(A);if(ve){K|=jn,J[D+Bn]=P,J[D+Dn]=ve.size;for(const M of ve){const B=s.get(`${A}/${M}`);if(B===void 0)throw new Error(`The store's children name ${A}/${M}, which its index does not hold.`);N[P++]=B}}J[D+Pe]=K;let ge=Wn(A)&w-1;for(;_e[ge]!==0;)ge=ge+1&w-1;_e[ge]=x+1}if(P!==m)throw new Error("The shared index's children did not add up.");return U}function kr(n,e){return Math.ceil(n/e)*e}class Re{buffer;count;entryCount;records;numbers;table;childList;strings;mask;constructor(e){const t=new Uint32Array(e,0,Vt);if(t[0]!==$n)throw new Error("Not a shared store index.");const[,s,a,d,f,h]=t;this.buffer=e,this.count=s,this.entryCount=h;const m=Vt*4,w=kr(m+s*oe*4,8),b=w+s*rt*8,E=b+a*4,S=E+d*4;this.records=new Uint32Array(e,m,s*oe),this.numbers=new Float64Array(e,w,s*rt),this.table=new Uint32Array(e,b,a),this.childList=new Uint32Array(e,E,d),this.strings=new Uint8Array(e,S,f),this.mask=a-1}find(e){let t=Wn(e)&this.mask;for(;;){const s=this.table[t];if(s===0)return-1;if(this.pathIs(s-1,e))return s-1;t=t+1&this.mask}}entry(e){const t=e*oe,s=this.records[t+Pe];if(!(s&Ht))return;const a=e*rt,d={type:Er[s>>>br&3],mode:this.records[t+Rn],mtimeMs:this.numbers[a+Cn],offset:this.numbers[a+zn],length:this.numbers[a+Un]};return s&qn&&(d.pack="packages"),d}typeAt(e){const t=this.records[e*oe+Pe];return t&Ht?Er[t>>>br&3]:void 0}hasEntry(e){return(this.records[e*oe+Pe]&Ht)!==0}childNames(e){const t=e*oe;if(!(this.records[t+Pe]&jn))return;const s=this.records[t+Bn],a=this.records[t+ut]+1,d=[];for(let f=0;f<this.records[t+Dn];f+=1){const h=this.childList[s+f]*oe;d.push(this.decode(this.records[h+Jt]+a,this.records[h+ut]-a,(this.records[h+Pe]&Gt)!==0))}return d}path(e){const t=e*oe;return this.decode(this.records[t+Jt],this.records[t+ut],(this.records[t+Pe]&Gt)!==0)}decode(e,t,s){if(!s)return so.decode(this.strings.slice(e,e+t));let a="";for(let d=e,f=e+t;d<f;d+=4096)a+=String.fromCharCode.apply(null,this.strings.subarray(d,Math.min(f,d+4096)));return a}pathIs(e,t){const s=e*oe,a=this.records[s+Jt],d=this.records[s+ut];if(!(this.records[s+Pe]&Gt))return this.path(e)===t;if(d!==t.length)return!1;for(let f=0;f<d;f+=1)if(this.strings[a+f]!==t.charCodeAt(f))return!1;return!0}}const le=Symbol("deleted");function Jn(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 Ke{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 t=this.overlay.get(e);if(t!==void 0)return t===le?void 0:t;const s=this.base.find(e);return s<0?void 0:this.base.entry(s)}typeOf(e){const t=this.overlay.get(e);if(t!==void 0)return t===le?void 0:t.type;const s=this.base.find(e);return s<0?void 0:this.base.typeAt(s)}has(e){const t=this.overlay.get(e);if(t!==void 0)return t!==le;const s=this.base.find(e);return s>=0&&this.base.hasEntry(s)}set(e,t){this.has(e)||(this.delta+=1);const s=this.base.find(e);return s>=0&&Jn(this.base.entry(s),t)?this.overlay.delete(e):this.overlay.set(e,t),this}delete(e){if(!this.has(e))return!1;const t=this.base.find(e);return t>=0&&this.base.hasEntry(t)?this.overlay.set(e,le):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,t]of this.overlay)t!==le&&(yield[e,t]);for(let e=0;e<this.base.count;e+=1){if(!this.base.hasEntry(e))continue;const t=this.base.path(e);this.overlay.has(t)||(yield[t,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,t){for(const[s,a]of this.entries())e.call(t,a,s,this)}*changed(){for(const[e,t]of this.overlay)t!==le&&(yield[e,t])}*changes(){for(const[e,t]of this.overlay)yield[e,t===le?null:t]}get overlaid(){return this.overlay.size}boundedChanges(){if(this.overlay.size>65536)return;const e=[];let t=0;for(const[s,a]of this.changes()){if(t+=s.length*2+128,t>8*1024*1024)return;e.push([s,a])}return e}}class $t{base;overlay=new Map;constructor(e){this.base=e}get(e){const t=this.overlay.get(e);if(t!==void 0)return t===le?void 0:t;const s=this.base.find(e),a=s<0?void 0:this.base.childNames(s);return a?new Set(a):void 0}mutable(e){const t=this.overlay.get(e);if(t!==void 0&&t!==le)return t;const s=new Set(t===le?[]:this.get(e)??[]);return this.overlay.set(e,s),s}delete(e){this.overlay.set(e,le)}}const oo="supercode-browser-filesystems",xe="packages",io="state.json",an="/image-range-worker.js",cn="image-ranges.json",ao=2;function ur(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 t=0;for(const s of e.parts){if(!s||s.offset!==t||!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(a=>a==="."||a===".."))throw new Error("Invalid immutable image part.");if(t+=s.raw,!Number.isSafeInteger(t))throw new Error("Immutable image ranges exceed the offset limit.")}if(t!==e.bytes)throw new Error("Immutable image ranges do not cover their reservation.");return e}const ln=new Map;class co{ranges;directory;identity;receiptKey;client;worker;port;prefetchers=[];state;completed;firstRead;closed=!1;ready=!1;startup;cancelStartup;sharedCompletion;constructor(e,t,s,a,d,f){if(this.ranges=e,this.directory=t,this.identity=s,this.receiptKey=d,this.client=f,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(f?.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,m=a??new SharedArrayBuffer((2*h+1)*Int32Array.BYTES_PER_ELEMENT);if(m.byteLength!==h*Int32Array.BYTES_PER_ELEMENT&&m.byteLength!==(2*h+1)*Int32Array.BYTES_PER_ELEMENT)throw new Error("The image completion seed has the wrong range count.");this.completed=new Int32Array(m,0,h),this.firstRead=m.byteLength>h*Int32Array.BYTES_PER_ELEMENT?new Int32Array(m,h*Int32Array.BYTES_PER_ELEMENT,h+1):void 0,this.sharedCompletion=a!==void 0;for(const w of e.parts)Object.freeze(w);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 t=0;t<this.completed.length;t+=1)if(Atomics.load(this.completed,t)!==2){e=!0;break}if(!e){this.ready=!0,this.client?.port.close();return}if(this.client){const t=this.port=this.client.port;t.onmessage=s=>{s.data?.type!=="closing"||this.port!==t||(t.close(),this.port=void 0,this.closed||this.startMaterializer().catch(a=>console.warn("This process's image reader could not start its own materializer after its line closed.",a)))},t.start(),this.ready=!0;return}return this.startMaterializer()}startMaterializer(){const e=Date.now(),t=new Worker(an,{type:"module",name:"immutable-image-materializer"}),s=this.ready;return s||(this.worker=t),t.addEventListener("error",()=>this.fail()),t.addEventListener("messageerror",()=>this.fail()),this.startup=new Promise((a,d)=>{const f=()=>{clearTimeout(b),t.removeEventListener("message",w),t.removeEventListener("error",h),t.removeEventListener("messageerror",h),this.cancelStartup=void 0},h=()=>m(new Error("The immutable image materializer could not initialize; reload to retry.")),m=E=>{f(),t.terminate(),s||(this.closed=!0,this.fail()),d(E)},w=E=>{if(E.data?.identity===this.identity){if(E.data.type==="init-error"){m(new Error(`The immutable image materializer could not initialize: ${String(E.data.error)}`));return}E.data.type==="ready"&&(console.log(`[boot-trace] ${JSON.stringify({event:"materializer-ready",at:Date.now(),ms:Date.now()-e})}`),f(),this.ready=!0,this.worker=t,a())}},b=setTimeout(()=>m(new Error("The immutable image materializer did not initialize within 10 seconds; reload to retry.")),1e4);this.cancelStartup=m,t.addEventListener("message",w),t.addEventListener("error",h),t.addEventListener("messageerror",h);try{t.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(E){m(E instanceof Error?E:new Error(String(E)))}}),this.startup}readDigests(){const e=this.firstRead;if(!e)return;const t=this.ranges.parts.length,s=[];for(let a=0;a<t;a+=1){const d=Atomics.load(e,a),f=this.ranges.parts[a];d>0&&f.raw>0&&s.push([d,f.sha256])}return s.sort((a,d)=>a[0]-d[0]).map(([,a])=>a)}completedDigests(){const e=[];for(let t=0;t<this.completed.length;t+=1){const s=this.ranges.parts[t];s.raw>0&&Atomics.load(this.completed,t)===2&&e.push(s.sha256)}return e}prefetch(e,t=[]){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 m=this.ranges.parts[h];if(m.raw===0)continue;const w=s.get(m.sha256);w?w.push(h):s.set(m.sha256,[h])}const a=[];for(const h of new Set(e))for(const m of s.get(h)??[])Atomics.load(this.completed,m)!==2&&a.push(m);const d=t.length>0&&a.length>0?Math.min(t.length,8):Math.min(ao,Math.ceil(a.length/32)),f=[];for(let h=0;h<d;h+=1){const m=a.filter((S,T)=>T%d===h),w=new Worker(an,{type:"module",name:"immutable-image-prefetch"});this.prefetchers.push(w);let b;f.push(new Promise(S=>{b=S}));const E=()=>{w.terminate(),this.prefetchers=this.prefetchers.filter(S=>S!==w),b()};w.addEventListener("error",E),w.addEventListener("messageerror",E),w.addEventListener("message",S=>{S.data?.identity===this.identity&&(S.data.type==="ready"?w.postMessage(t.length>0?{type:"prefetch-stream",url:t[h]}:{type:"prefetch",indices:m}):(S.data.type==="prefetched"||S.data.type==="init-error")&&E())}),w.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:a.length,done:Promise.all(f).then(()=>{})}}ensure(e,t){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(t===0||e>=this.ranges.bytes)return;const s=Math.min(e+t,this.ranges.bytes);let a=0,d=this.ranges.parts.length;for(;a<d;){const f=a+d>>>1,h=this.ranges.parts[f];h.offset+h.raw<=e?a=f+1:d=f}for(let f=a;f<this.ranges.parts.length;f+=1){const h=this.ranges.parts[f];if(h.offset>=s)break;const m=this.firstRead;if(m&&Atomics.load(m,f)===0&&Atomics.compareExchange(m,f,0,Atomics.add(m,this.ranges.parts.length,1)+1),Atomics.load(this.completed,f)===2)continue;const w=this.worker??this.port;if(!w)throw new Error("This immutable image reader's line closed and its own materializer is still starting; retry the read.");w.postMessage({type:"read",index:f});const b=performance.now(),E=b+3e4;for(;Atomics.load(this.state,f)===0;){const g=E-performance.now();if(g<=0||Atomics.wait(this.state,f,0,g)==="timed-out")throw this.close(),new Error(`The image's immutable part ${h.url} did not arrive within 30 seconds; reload to retry.`)}const S=performance.now()-b,T=ln.get(this.identity)??{ranges:0,ms:0};if(T.ranges+=1,T.ms+=S,ln.set(this.identity,T),console.log(`[boot-trace] ${JSON.stringify({event:"image-blocked",at:Date.now(),reader:this.identity,index:f,range:h.sha256.slice(0,16),ms:Math.round(S)})}`),Atomics.load(this.state,f)!==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 t=new MessageChannel,s=new SharedArrayBuffer(this.ranges.parts.length*Int32Array.BYTES_PER_ELEMENT);return e.postMessage({type:"client",port:t.port1,state:s},[t.port1]),{port:t.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 t of this.prefetchers)t.dispatchEvent(new Event("error"));this.prefetchers=[]}}const pr="/packages",Rt="supercode-browser-packages",Be=new TextEncoder,Qe=new TextDecoder("utf-8",{fatal:!0}),lo=oo,Bt="generations",dn="atomic-staging",Xe=io,de="index.json",hr="index-log.bin",Ze="pack.bin",Dt=8,fn=64*1024*1024,se=1024*1024*1024,un=4*1024*1024*1024,fo=["/workspace","/home","/opt"],De=0,pn=1,wr=1e6,hn=8*1024*1024,wn=250,uo=64*1024*1024,po=256*1024*1024,mn=4*1024*1024,et=493,Ct=420;function yn(n,e={}){const t=e.limits?.maxBytes??un,s=e.limits?.maxEntries??wr;if(!Number.isSafeInteger(t)||t<1||t>un||!Number.isSafeInteger(s)||s<1||s>wr)throw new Error("Invalid OPFS workspace limits.");let a,d=!1,f=!1,h=!1,m,w=0,b=0,E,S,T,g=new Map,U=new zt,$,J,q,_e,N,R,L=0,P,x=0;const A=new Map,D=256*1024,H=32;let v=0,K,te=-1/0,ve=0,ge=0,M=0,B=0,Q=0,Ie=0,Oe=0,ae,mt,fe,qe=!1,st,Nr=Promise.resolve(),We=0,Y=!1,Je=!1,V,Ne=0,ue=!1;function yt(){if(!(!V||ue)){if(M>2147483647){_t();return}Atomics.store(V,pn,M)}}function _t(){!V||ue||(ue=!0,(Atomics.load(V,De)&1)===0&&Atomics.add(V,De,1))}function ot(){Ne+=1,Ne===1&&V&&!ue&&Atomics.add(V,De,1)}function it(){Ne-=1,!(Ne>0||!V||ue)&&(yt(),ue||Atomics.add(V,De,1))}function Tr(){if(f)throw new Error("A store open for reading follows its owner's clock; it has none of its own.");return V||(V=new Int32Array(new SharedArrayBuffer(2*Int32Array.BYTES_PER_ELEMENT)),V[De]=Ne>0||ue?1:0,yt()),V.buffer}let re;const ls=8*1024*1024;let Mr=!1;function ds(r){if(f||!V||!T||qe||Ne>0||ue||Y)return;const o=Atomics.load(V,De);if(o&1)return;if(r?.overlays&&g instanceof Ke){const l=g.boundedChanges();if(l)return Zt({generation:T,index:g.base.buffer,changes:l,packBytes:v,logBytes:M,epoch:o,liveBytes:B,linked:w,linkedBytes:b})}if(re&&re.generation===T&&re.epoch===o&&M>=re.logBytes&&M-re.logBytes<=(r?.current?0:ls))return Zt(re);let i;try{i=on(g,ps())}catch(l){console.warn(`[pack-store] no reader seed: ${l instanceof Error?l.message:String(l)}`);return}return re={generation:T,index:i,packBytes:v,logBytes:M,epoch:o,liveBytes:B,linked:w,linkedBytes:b},us(i),Zt(re)}function Zt(r){const o=e.packages?.imageCompletionSeed();return o?{...r,packagesImage:o}:r}function fs(){if(!(!q||!J||!T||qe||Ne>0||Y))return{generation:T,rangesDigest:J,completed:q.completionBuffer,...q.receiptKey?{metadata:{ranges:q.verifiedRanges,receiptKey:q.receiptKey}}:{}}}function us(r){const o=[];if(g instanceof Ke)for(const[l,c]of g.changed())c.capacity!==void 0&&o.push([l,c]);else for(const[l,c]of g)c.capacity!==void 0&&o.push([l,c]);const i=new Re(r);g=new Ke(i),U=new $t(i);for(const[l,c]of o)g.set(l,c)}function ps(){if(U instanceof zt)return U.map;const r=new Map;for(const o of g.keys()){const i=Le(o);if(i===o)continue;let l=r.get(i);l||(l=new Set,r.set(i,l)),l.add(o.slice(i.length+1))}return r}function hs(){!f||h||Y||!P||St(M)}async function gt(r){if(Y)throw new Error("This OPFS workspace is closing.");We+=1;let o,i=!1;try{return await r()}catch(l){throw i=!0,o=l,l}finally{if(We-=1,Y&&We===0)try{rn()}catch(l){throw i?new AggregateError([o,l],"OPFS operation and deferred close both failed."):l}}}async function bt(r){return be(),We!==0?Promise.reject(new Error("Wait for the current OPFS storage operation before replacing its generation.")):(Je=!0,gt(async()=>{try{return await r()}finally{Je=!1}}))}function ws(r){if(Y)throw new Error("This OPFS workspace is closing.");const o=g.get(r);if(!o||o.type==="directory")throw new Error(`OPFS workspace file does not exist: ${r}`);return Et(o)}function ms(r,o,i){if(Y)throw new Error("This OPFS workspace is closing.");const l=g.get(r);if(!l||l.type==="directory")throw new Error(`OPFS workspace file does not exist: ${r}`);const c=Math.min(Math.max(0,o),l.length),u=Math.min(Math.max(0,i),l.length-c);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+c,u)}return kt(l.offset+c,u)}function Et(r){if(r.pack){const o=e.packages;if(!o)throw new Error("This store has no shared package store to read from.");return o.readExtent(r.offset,r.length)}return kt(r.offset,r.length)}function kt(r,o){if(Y)throw new Error("This OPFS workspace is closing.");const i=$;if(!i)throw new Error("OPFS filesystem worker is not initialized.");const l=new Uint8Array(o);if(o>0&&o<=D&&r>=0&&r+o<=x){let c=0;for(;c<o;){const u=r+c,p=Math.floor(u/D)*D;let y=A.get(p);if(!y&&(y=new Uint8Array(Math.min(D,x-p)),q?.ensure(p,y.byteLength),i.read(y,{at:p})!==y.byteLength))throw new Error("An OPFS package range could not be read completely.");A.delete(p),A.set(p,y),A.size>H&&A.delete(A.keys().next().value);const _=u-p,k=Math.min(o-c,y.byteLength-_);l.set(y.subarray(_,_+k),c),c+=k}return l}if(q?.ensure(r,o),o>0&&i.read(l,{at:r})!==o)throw new Error("An OPFS workspace file could not be read completely.");return l}async function ys(r,o={}){if(Y&&a||!a&&We!==0)throw new Error("Wait for this OPFS workspace to finish closing before opening it again.");if(qe)throw new Error("This OPFS store is already opening a workspace.");if(a){if(S!==$r(r))throw new Error("Close this OPFS store before opening another workspace.");return g.size>0}qe=!0,Y=!1;const i=new AbortController;st=i;try{g=new Map,U=new zt,T=void 0,J=void 0,m=void 0,ae=void 0,fe=void 0,v=M=B=Q=w=b=0,he=void 0,Ie=Oe=ve=ge=0,te=-1/0,S=$r(r),f=o.readOnly===!0,N=f?o.imageCompletion:void 0,R=f?o.imageLine:void 0,h=f&&o.extentsOnly===!0,d=o.shared===!0||f,d||await ks(i.signal),i.signal.throwIfAborted();const l=await gs();i.signal.throwIfAborted();try{const p=await l.getDirectoryHandle(lo,{create:!f});i.signal.throwIfAborted(),a=await p.getDirectoryHandle(S,{create:!f})}catch(p){if(i.signal.throwIfAborted(),f&&Ve(p))return!1;throw p}i.signal.throwIfAborted();let c=Ft(await Fe(a,Xe));if(i.signal.throwIfAborted(),!c&&f)return await tr(),!1;if(!c&&d&&(await n.navigator.locks.request(Rt,{mode:"exclusive",signal:i.signal},async()=>{i.signal.throwIfAborted(),c=Ft(await Fe(a,Xe)),i.signal.throwIfAborted(),c||(await tr(),await qr({files:[],pack:new ArrayBuffer(0)}),await mo(a))}),i.signal.throwIfAborted(),!c))return m=await pe(T,!1),i.signal.throwIfAborted(),!1;if(!c)return await tr(),i.signal.throwIfAborted(),!1;const u=async p=>{let y;try{y=await pe(p.generation,!1)}catch(O){throw i.signal.throwIfAborted(),Ve(O)?new Error("The committed OPFS workspace generation is missing. Stored generations were retained.",{cause:O}):O}if(i.signal.throwIfAborted(),T=p.generation,L=p.initializedAt,J=p.imageRanges,m=y,h)return S===xe&&n.navigator.locks?await n.navigator.locks.request(Rt,{mode:"shared",signal:i.signal},async()=>{await He(y),x=$.getSize()}):await He(y),i.signal.throwIfAborted(),!0;const _=f?o.seed:void 0;if(_&&_.generation===p.generation){const O=new Re(_.index);return g=new Ke(O),U=new $t(O),v=_.packBytes,_.changes&&Lr({packBytes:_.packBytes,changes:_.changes}),await He(y),i.signal.throwIfAborted(),M=_.logBytes,{liveBytes:B,linked:w,linkedBytes:b}=_,Q=Math.max(0,v-B),Mr=!0,g.size>0}const k=f?void 0:await js(y);if(i.signal.throwIfAborted(),k){const O=new Re(k.index);g=new Ke(O),U=new $t(O),{packBytes:v,liveBytes:B,linked:w,linkedBytes:b}=k;const I=Atomics.load(new Int32Array(Tr()),De);re={generation:T,index:k.index,packBytes:v,liveBytes:B,linked:w,linkedBytes:b,logBytes:0,epoch:I}}else g=lr(await Fe(y,de)),i.signal.throwIfAborted(),Ye(),v=er(g);await He(y),i.signal.throwIfAborted();const F=k?await qs(k):0;return i.signal.throwIfAborted(),F&&(he={generation:T,bytes:F},re&&(re.logBytes=F)),St(F,!!k),k?Q=Math.max(0,v-B):at(),Ur(),d&&!f&&!k&&g.size>=1e4&&(ke(),await dt(y,g,{access:P,bytes:M,packBytes:v})),d||($.truncate(v),await Gr(a,dn,!0),await rr(T),i.signal.throwIfAborted(),Q>uo&&Q>B&&await Ms()),i.signal.throwIfAborted(),g.size>0};return d&&!f?await n.navigator.locks.request(Rt,{mode:"exclusive",signal:i.signal},async()=>{if(c=Ft(await Fe(a,Xe)),!c)throw new Error("The committed package store state is missing. Stored data was retained.");return u(c)}):await u(c)}catch(l){const c=[l];try{Ge()}catch(u){c.push(u)}try{E?.()}catch(u){c.push(u)}throw E=void 0,a=void 0,c.length>1?new AggregateError(c,"OPFS workspace open and cleanup failed."):l}finally{qe=!1,st=void 0}}function _s(r){return gt(()=>Fr(r?.whole===!0))}async function Fr(r=!1){if(h)throw new Error("A store opened for its extents alone has no index to follow.");if(f&&a){const u=Ft(await Fe(a,Xe));if(!u)throw new Error("The committed OPFS workspace state is missing. Stored data was retained.");if(u.generation!==T||r){const p=await pe(u.generation,!1),y=lr(await Fe(p,de));v=er(y),u.generation!==T&&(T=u.generation,L=u.initializedAt,J=u.imageRanges,await He(p)),T=u.generation,m=p,g=y,Ye(),St(),at();return}}const o=P;if(!o||!m)return;const i=o.getSize();let l=!1;i<M&&(g=lr(await Fe(m,de)),Ye(),v=er(g),M=0,l=!0);const c=M;St(M),(l||M!==c)&&at()}async function gs(){let r;for(let o=0;o<10;o+=1){st?.signal.throwIfAborted();try{return await n.navigator.storage.getDirectory()}catch(i){r=i,await new Promise(l=>setTimeout(l,200))}}throw r instanceof Error?r:new Error("This browser workspace's storage is unavailable.")}const bs=1e4;async function Z(r,o){let i;const l=st?.signal;for(let u=0;u<2;u+=1){l?.throwIfAborted();const p=r.createSyncAccessHandle({mode:"readwrite-unsafe"});let y,_,k=!1;try{const F=new Promise((I,j)=>{_=()=>j(l?.reason??new DOMException("Workspace open was cancelled.","AbortError")),l?.addEventListener("abort",_,{once:!0}),l?.aborted&&_()}),O=await Promise.race([p.then(I=>({access:I})).catch(I=>{i=I}),new Promise(I=>{y=setTimeout(()=>I(void 0),bs)}),F]);if(l?.throwIfAborted(),O)return k=!0,O.access}finally{y!==void 0&&clearTimeout(y),_&&l?.removeEventListener("abort",_),k||p.then(F=>F.close(),()=>{}).catch(F=>console.error("Late workspace handle cleanup failed.",F))}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(F=>setTimeout(F,500))}const c=i instanceof Error?` (${i.message})`:"";throw new Error(`This browser workspace's ${o} is held by another page${c}.`)}async function He(r){Ge();const o=await r.getFileHandle(Ze);$=await Z(o,"store");try{if($.getSize()<v)throw new Error("The committed OPFS workspace pack is incomplete. Stored data was retained.");const i=await r.getFileHandle(hr);if(P=await Z(i,"record of changes"),M=P.getSize(),J){const l=N,c=l&&l.generation===T&&l.rangesDigest===J?l:void 0;let u,p;if(c?.metadata){if(u=ur(c.metadata.ranges),p=c.metadata.receiptKey,!/^[a-f0-9]{64}$/u.test(p))throw new Error("The owner's immutable receipt key is invalid.")}else{const _=await(await r.getFileHandle(cn)).getFile(),k=new Uint8Array(await _.arrayBuffer());if(await me(k)!==J)throw new Error("The committed immutable image ranges have changed. Stored data was retained.");u=ur(JSON.parse(Qe.decode(k))),p=await me(Be.encode(JSON.stringify(u)))}if(u.bytes>$.getSize())throw new Error("The immutable image reservation is incomplete. Stored data was retained.");const y=c?R:void 0;y||R?.port.close(),R=void 0,q=new co(u,r,`${S}.${T}`,c?.completed,p,y),console.log(`[boot-trace] ${JSON.stringify({event:"image-reader-open",at:Date.now(),reader:`${S}.${T}`,offered:l!==void 0,shared:c!==void 0,...l&&!c?{offeredGeneration:l.generation,generation:T,rangesMatch:l.rangesDigest===J}:{}})}`),await q.initialize(),_e=u.image}}catch(i){throw Ge(),i}}function Ge(){q?.close(),q=void 0,_e=void 0;const r=$,o=P;$=void 0,P=void 0,M=0,x=0,A.clear();try{r?.close()}finally{o?.close()}}function St(r=0,o=!1){const i=P;if(!i)throw new Error("OPFS filesystem worker is not initialized.");const l=i.getSize();if(l<=r){M=l;return}const c=new Uint8Array(l-r);if(i.read(c,{at:r})!==c.byteLength)throw new Error("The OPFS workspace index log could not be read.");const u=$?.getSize()??1/0,p=new DataView(c.buffer);let y=0;const _=c.byteLength;for(;y+Dt<=_;){const k=p.getUint32(y,!0),F=p.getUint32(y+4,!0),O=y+Dt;if(k===0||k>fn||O+k>_)break;const I=c.subarray(O,O+k);if(Zr(I)!==F)break;let j;try{j=Hs(JSON.parse(Qe.decode(I)))}catch{break}if(j.packBytes>u)break;Lr(j,o),y=O+k}y!==_&&!d&&i.truncate(r+y),M=r+y}function Lr(r,o=!1){for(const[i,l]of r.changes){const c=g.get(i);if(l&&Jn(c,l)){xt(i);continue}o&&(c?.pack?(w-=1,b-=c.length):c&&(B-=c.length),l?.pack?(w+=1,b+=l.length):l&&(B+=l.length)),l===null?(g.delete(i),Br(i)):(g.set(i,l),xt(i))}v=Math.max(v,r.packBytes)}function at(){B=0,w=0,b=0;for(const r of g.values())r.pack?(w+=1,b+=r.length):B+=r.length;Q=Math.max(0,v-B)}function er(r){let o=0;for(const i of r.values())i.pack||(o=Math.max(o,i.offset+i.length));return o}const Es=5e3;async function ks(r){if(!n.navigator.locks)return;if(!S)throw new Error("OPFS filesystem project is not initialized.");const o=new AbortController,i=setTimeout(()=>o.abort(),Es);try{await new Promise((l,c)=>{n.navigator.locks.request(`supercode-browser-filesystem-${S}`,{mode:"exclusive",signal:r?AbortSignal.any([r,o.signal]):o.signal},async()=>{clearTimeout(i),l(),await new Promise(u=>{E=u})}).catch(()=>c(r?.aborted?r.reason:new Error("This browser workspace is already open in another tab.")))})}finally{clearTimeout(i)}}function $r(r){if(typeof r!="string"||!/^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/u.test(r))throw new Error("OPFS filesystem projectId is invalid.");return r}async function Te(){if(!a)throw new Error("OPFS filesystem worker is not initialized.");return a}async function pe(r,o){return(await(await Te()).getDirectoryHandle(Bt,{create:o})).getDirectoryHandle(r,{create:o})}async function tr(){let r;try{r=await(await Te()).getDirectoryHandle(Bt)}catch(o){if(Ve(o))return;throw o}for await(const o of r.entries())throw new Error("OPFS workspace state is missing but stored generations exist. Stored data was retained.")}async function rr(r){const o=await Te();let i;try{i=await o.getDirectoryHandle(Bt)}catch(l){if(Ve(l))return;throw l}for await(const[l]of i.entries())l!==r&&await Yr(i,l)}function be(){if(Y)throw new Error("This OPFS workspace is closing.");if(Je)throw new Error("This OPFS workspace is replacing its generation; wait for that operation before writing.");if(f)throw new Error("This store is open for reading; its owner writes it.");if(fe)throw fe}async function Ss(r){en(r)}let nr=!1,Pt=0,he,sr=!1;function Rr(){if(Pt>0)return;const r=he&&he.generation===T&&he.bytes<=M?he.bytes:0;M-r>hn&&!nr&&(nr=!0,(d?n.navigator.locks.request(Rt,{mode:"exclusive"},async()=>{if(!a||Y)return;await Fr();const i=he,l=i&&i.generation===T&&i.bytes<=M?i.bytes:0;M-l>hn&&await Ot()}):Ot()).catch(i=>console.error("The workspace's log could not be checkpointed; it is replayed at the next open.",i)).finally(()=>{nr=!1})),!d&&!sr&&Q>po&&Q>B&&(sr=!0,gt(Fs).catch(o=>console.error("The workspace could not be compacted; it keeps its generation.",o)).finally(()=>{sr=!1}))}async function Ps(r){be(),Pt+=1;try{return await r()}finally{Pt-=1,Pt===0&&!Y&&a&&Rr()}}function xs(r,o){const i=ye(r.path);if(r.operation==="write"){if(g.get(i)?.type==="directory")throw new Error(`OPFS write target is a directory: ${i}`);if(!(r.content instanceof Uint8Array))throw new Error("OPFS write requires file content.");const c=r.content;if(c.byteLength>se)throw new Error(`${i} is ${c.byteLength} bytes; an OPFS workspace file holds at most ${se}.`);At(i,c.byteLength),Me(i,o);const u=It(c);ee(i,{type:r.symlink?"symlink":"file",mode:r.mode??g.get(i)?.mode??Ct,mtimeMs:r.mtimeMs??Date.now(),offset:u,length:c.byteLength},o);return}if(r.operation==="append"){const c=g.get(i);if(c&&c.type!=="file")throw new Error(`OPFS append target is not a file: ${i}`);if(!(r.content instanceof Uint8Array))throw new Error("OPFS append requires file content.");const u=r.content,p=(c?.length??0)+u.byteLength;if(p>se)throw new Error(`${i} is ${p} bytes; an OPFS workspace file holds at most ${se}.`);At(i,p),Me(i,o);const y=r.mode??c?.mode??Ct,_=r.mtimeMs??Date.now(),k=c&&!c.pack?c.capacity??c.length:0;if(S!==xe&&c&&!c.pack&&c.length>0&&(p<=k||c.offset+k===v)){vt(c.offset+c.length,u),ee(i,{...c,mode:y,mtimeMs:_,length:p,capacity:Math.max(k,p)},o),Q-=Math.max(c.length,c.capacity??0),Ie-=1,Oe-=c.length;return}const F=new Uint8Array(p);c&&c.length>0&&F.set(Et(c),0),F.set(u,p-u.byteLength);const O=It(F),I=Math.min(se,Math.max(p,p*2,64*1024));I>p&&jr(O+I),ee(i,{type:"file",mode:y,mtimeMs:_,offset:O,length:p,capacity:I},o);return}if(r.operation==="write-at"){const c=g.get(i);if(c&&c.type!=="file")throw new Error(`OPFS write target is not a file: ${i}`);if(!(r.content instanceof Uint8Array))throw new Error("OPFS write requires file content.");const u=r.content,p=r.position,y=c?.length??0;if(u.byteLength===0&&c)return;const _=u.byteLength===0?y:Math.max(y,p+u.byteLength);if(_>se)throw new Error(`${i} is ${_} bytes; an OPFS workspace file holds at most ${se}.`);At(i,_),Me(i,o);const k=r.mode??c?.mode??Ct,F=r.mtimeMs??Date.now(),O=c&&!c.pack?c.capacity??c.length:0;if(S!==xe&&c&&!c.pack&&y>0&&(_<=O||c.offset+O===v)){if(p>y&&vt(c.offset+y,new Uint8Array(p-y)),mt&&p<y){const ne=Math.min(y,p+u.byteLength);mt.push([c.offset+p,kt(c.offset+p,ne-p)])}vt(c.offset+p,u),ee(i,{...c,mode:k,mtimeMs:F,length:_,capacity:Math.max(O,_)},o),_!==y&&(Q-=Math.max(c.length,c.capacity??0),Ie-=1,Oe-=c.length);return}const I=new Uint8Array(_);c&&y>0&&I.set(Et(c),0),u.byteLength>0&&I.set(u,p);const j=It(I),W=Math.min(se,Math.max(_,_*2,64*1024));W>_&&jr(j+W),ee(i,{type:"file",mode:k,mtimeMs:F,offset:j,length:_,capacity:W},o);return}if(r.operation==="mkdir"){Me(i,o);const c=g.get(i);if(c&&c.type!=="directory")throw new Error(`OPFS path is a file: ${i}`);ee(i,{type:"directory",mode:r.mode??c?.mode??et,mtimeMs:r.mtimeMs??c?.mtimeMs??Date.now(),offset:0,length:0},o);return}if(r.operation==="remove"){ir(i,o),Ee().includes(i)&&ee(i,{type:"directory",mode:et,mtimeMs:Date.now(),offset:0,length:0},o);return}if(r.operation==="link"){As(i,zr(r.source),o);return}if(r.operation==="rename"){vs(i,ye(r.destination),o);return}const l=g.get(i);if(!l)throw new Error(`OPFS metadata target does not exist: ${i}`);ee(i,{...l,mode:r.mode??l.mode,mtimeMs:r.mtimeMs??l.mtimeMs},o)}function ee(r,o,i){const l=g.get(r);ae&&!ae.has(r)&&ae.set(r,l);const c=l!==void 0&&l.type===o.type&&l.offset===o.offset&&l.length===o.length&&l.pack===o.pack;l&&!c&&(Dr(l),l.type!=="directory"&&o.type!=="directory"&&l.length>0&&!l.pack&&(Ie+=1,Oe+=l.length)),g.set(r,o),xt(r),c||(o.pack?(w+=1,b+=o.length):B+=o.length),i.push([r,o])}function xt(r){const o=Le(r);o!==r&&U.mutable(o).add(r.slice(o.length+1))}function Br(r){const o=Le(r);U.get(o)?.has(r.slice(o.length+1))&&U.mutable(o).delete(r.slice(o.length+1)),U.delete(r)}function Ye(){U=new zt;for(const r of g.keys())xt(r)}function or(r){const o=[],i=l=>{const c=g.get(l);if(!c)return;o.push([l,c]);const u=U.get(l);if(u)for(const p of u)i(`${l}/${p}`)};return i(r),o}function Dr(r,o){if(r.pack){w-=1,b-=r.length;return}B-=r.length,Q+=Math.max(r.length,r.capacity??0)}function Cr(r,o){const i=g.get(r);i&&(ae&&!ae.has(r)&&ae.set(r,i),g.delete(r),Br(r),Dr(i),o.push([r,null]))}function As(r,o,i){const l=e.packages;if(!l)throw new Error("This store has no shared package store to link from.");const c=zr(o),u=l.descendants(c);if(u.length===0)throw new Error(`The shared package store does not hold ${o}.`);Me(r,i),ir(r,i),we(g.size+u.length);for(const[p,y]of u){const _=p===c?r:`${r}${p.slice(c.length)}`;ee(_,y.type==="directory"?{type:"directory",mode:y.mode,mtimeMs:y.mtimeMs,offset:0,length:0}:{type:y.type,mode:y.mode,mtimeMs:y.mtimeMs,offset:y.offset,length:y.length,pack:xe},i)}}function Me(r,o){const i=Le(r);if(i!==r&&g.get(i)?.type==="directory"){we(g.size+(g.has(r)?0:1));return}const l=[];let c=ct(r)??Ee()[0];if(g.has(c)||l.push(c),r!==c)for(const p of dr(Qr(Le(r)))){c=`${c}/${p}`;const y=g.get(c);if(y&&y.type!=="directory")throw new Error(`OPFS path parent is a file: ${c}`);y||l.push(c)}we(g.size+l.length+(g.has(r)?0:1));const u=Date.now();for(const p of l)ee(p,{type:"directory",mode:et,mtimeMs:u,offset:0,length:0},o)}function ir(r,o){for(const[i]of or(r))Cr(i,o)}function vs(r,o,i){if(r===o)return;if(o.startsWith(`${r}/`))throw new Error("An OPFS rename cannot move a directory into itself.");const l=or(r);if(l.length===0){if(g.has(o))return;throw new Error(`OPFS rename source does not exist: ${r}`)}Me(o,i),ir(o,i);for(const[c]of l)Cr(c,i);for(const[c,u]of l)ee(`${o}${c.slice(r.length)}`,u,i);we(g.size)}function zr(r){if(typeof r!="string"||!r.startsWith(`${pr}/`)||r.includes("\0")||r.length>4096)throw new Error("Invalid shared store path.");return dr(r.slice(pr.length+1)),r}function Ee(){return S===xe?[pr]:fo}function ct(r){return Ee().find(o=>r===o||r.startsWith(`${o}/`))}function At(r,o){const i=g.get(r),l=i&&!i.pack?i.length:0;if(B-l+o>t)throw new Error(`OPFS workspace exceeds its byte limit: writing ${r} (${o} bytes) would take the project's own files past ${t} bytes.`)}function we(r){if(r>s)throw new Error("OPFS workspace exceeds its entry limit.")}function Ur(){if(we(g.size),B>t)throw new Error(`OPFS workspace exceeds its byte limit: the project's own files hold ${B} bytes, past ${t}.`)}function vt(r,o){const i=$;if(!i)throw new Error("OPFS filesystem worker is not initialized.");let l=0;for(;l<o.byteLength;){const c=i.write(o.subarray(l),{at:r+l});if(c<=0)throw new Error("An OPFS workspace file could not be written completely.");l+=c}v=Math.max(v,r+o.byteLength)}function jr(r){const o=$;if(!o)throw new Error("OPFS filesystem worker is not initialized.");r<=v||(o.truncate(r),v=r)}function It(r){const o=$;if(!o)throw new Error("OPFS filesystem worker is not initialized.");const i=v;let l=0;for(;l<r.byteLength;){const c=o.write(r.subarray(l),{at:i+l});if(c<=0)throw new Error("An OPFS workspace file could not be written completely.");l+=c}return v=i+r.byteLength,i}function Is(r){const o=$;if(o.getSize()>=v&&r.getSize()>=M)return;o.flush(),r.flush();const i=o.getSize(),l=r.getSize();if(!(i>=v&&l>=M))throw Object.assign(new Error(`This browser is keeping less than the tab wrote (the store's pack holds ${i} of ${v} bytes, its log ${l} of ${M}): its storage is full, as a private window's is well below its quota.`),{name:"QuotaExceededError",code:"ENOSPC"})}function Os(r,o={}){const i=P;if(!i||!$)throw new Error("OPFS filesystem worker is not initialized.");if(r.length===0)return;const l=Be.encode(JSON.stringify({packBytes:v,changes:r}));if(l.byteLength>fn)throw new Error("An OPFS workspace index record exceeds its size limit.");const c=new Uint8Array(Dt+l.byteLength),u=new DataView(c.buffer);u.setUint32(0,l.byteLength,!0),u.setUint32(4,Zr(l),!0),c.set(l,Dt);let p=0;for(;p<c.byteLength;){const y=i.write(c.subarray(p),{at:M+p});if(y<=0)throw new Error("The OPFS workspace index log could not be written completely.");p+=y}M+=c.byteLength,Is(i),o.publish!==!1&&yt(),performance.now()-te>=wn?ke():K===void 0&&(K=setTimeout(ke,wn))}function ke(){if(K!==void 0&&(clearTimeout(K),K=void 0),fe)throw fe;const r=performance.now();$?.flush(),P?.flush(),te=performance.now(),ve+=1,ge+=te-r}function Ot(){const r=Nr,o=gt(()=>r.catch(()=>{}).then(Ns));return Nr=o,o}async function Ns(){if(be(),!T)return;const r=T,o=P,i=await pe(r,!1);if(!o||o!==P||r!==T)throw new Error("OPFS workspace changed generations before its checkpoint could start.");ke();const l=M;if(await dt(i,g,{access:o,bytes:l,packBytes:v}),r===T&&(he={generation:r,bytes:l}),o===P&&r===T&&l===M){ot();try{o.truncate(0),o.flush(),M=0,he={generation:r,bytes:0}}finally{it()}}}function qr(r){return bt(()=>Ts(ar(r)))}async function Ts(r){const o=crypto.randomUUID(),i=await pe(o,!0),l=await i.getFileHandle(Ze,{create:!0}),c=await Z(l,"store"),u=new Map;let p=0;try{for(const _ of r.files){let k=0,F=0;if(_.type!=="directory"){const O=new Uint8Array(r.pack,_.offset??0,_.length??0);k=p,F=O.byteLength;let I=0;for(;I<F;){const j=c.write(O.subarray(I),{at:k+I});if(j<=0)throw new Error("An OPFS workspace file could not be written completely.");I+=j}p+=F}u.set(_.path,{type:_.type,mode:_.mode??(_.type==="directory"?et:Ct),mtimeMs:_.mtimeMs??Date.now(),offset:k,length:F})}for(const _ of Ee())u.has(_)||u.set(_,{type:"directory",mode:et,mtimeMs:Date.now(),offset:0,length:0});we(u.size),c.truncate(p),c.flush()}finally{c.close()}const y=await dt(i,u);await Nt(o,i,u,p,y)}async function Ms(){await Wr(()=>!0)}async function Fs(){let r=!1,o=!1,i=!1;try{await Ls(()=>{r=!0},()=>{o=!0},()=>{i=!0})}finally{r&&(o||i)?it():r&&_t()}}async function Ls(r,o,i){const l=crypto.randomUUID(),c=await pe(l,!0),u=await Z(await c.getFileHandle(Ze,{create:!0}),"store");let p,y=!1;try{p=await Z(await c.getFileHandle(hr,{create:!0}),"record of changes"),p.truncate(0);const _=new Uint8Array(mn);let k=0;const F=z=>{if(z.pack)return{...z};if(z.type==="directory"||z.length===0)return{...z,offset:0,length:0};const X=$;if(!X)throw new Error("OPFS filesystem worker is not initialized.");const $e=k;let ce=0;for(;ce<z.length;){const ft=Math.min(_.byteLength,z.length-ce),nn=_.subarray(0,ft);if(q?.ensure(z.offset+ce,ft),X.read(nn,{at:z.offset+ce})!==ft)throw new Error("An OPFS workspace file could not be read completely.");let Lt=0;for(;Lt<ft;){const sn=u.write(nn.subarray(Lt),{at:$e+ce+Lt});if(sn<=0)throw new Error("An OPFS workspace file could not be written completely.");Lt+=sn}ce+=ft}k+=z.length;const{capacity:fr,...Vs}=z;return{...Vs,offset:$e}},O=new Map;let I=performance.now();for(const[z,X]of[...g]){if(Y||Je)return;g.get(z)===X&&(O.set(X,F(X)),performance.now()-I>8&&(await new Promise($e=>setTimeout($e,0)),I=performance.now()))}if(Y||Je||!$||!P)return;ot(),r();const j=new Map;for(const[z,X]of g)j.set(z,O.get(X)??F(X));u.truncate(k),u.flush(),p.flush(),ke();const W={pack:$,log:P};$=u,P=p,M=0,g=j,Ye(),v=k,T=l,m=c,at(),y=!0;const ne=new Map(j);try{W.pack.close()}finally{W.log.close()}try{await dt(c,ne);const z={storageVersion:4,generation:l,initializedAt:Date.now()};await lt(await Te(),Xe,z)}catch(z){throw fe=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:z}),fe}o(),await rr(l)}finally{if(!y){i();try{u.close()}finally{p?.close()}await Yr(await(await Te()).getDirectoryHandle(Bt),l)}}}async function $s(r){be(),ot();try{await Rs(r)}finally{it()}}async function Rs(r){let o=!1;for(const[i,l]of g){if(!l.pack||l.length===0)continue;const c=r.get(l.offset);if(c===void 0)throw new Error(`The shared store no longer holds the bytes of ${i}.`);c!==l.offset&&(g.set(i,{...l,offset:c}),o=!0)}o&&await Ot()}function Wr(r){return bt(()=>Bs(r))}async function Bs(r){const o=$;if(!o)throw new Error("OPFS filesystem worker is not initialized.");const i=new Map,l=crypto.randomUUID(),c=await pe(l,!0),u=await c.getFileHandle(Ze,{create:!0}),p=await Z(u,"store"),y=new Map,_=new Uint8Array(mn);let k=0;try{for(const[O,I]of g){if(!r(O,I))continue;if(I.pack){y.set(O,{...I});continue}if(I.type==="directory"||I.length===0){y.set(O,{...I,offset:0,length:0});continue}const j=k;i.set(I.offset,j);let W=0;for(;W<I.length;){const X=Math.min(_.byteLength,I.length-W),$e=_.subarray(0,X);if(q?.ensure(I.offset+W,X),o.read($e,{at:I.offset+W})!==X)throw new Error("An OPFS workspace file could not be read completely.");let ce=0;for(;ce<X;){const fr=p.write($e.subarray(ce),{at:j+W+ce});if(fr<=0)throw new Error("An OPFS workspace file could not be written completely.");ce+=fr}W+=X}k+=I.length;const{capacity:ne,...z}=I;y.set(O,{...z,offset:j,length:I.length})}p.truncate(k),p.flush()}finally{p.close()}const F=await dt(c,y);return await Nt(l,c,y,k,F),i}async function Nt(r,o,i,l,c,u){ot();try{await Ds(r,o,i,l,c,u)}finally{it()}}async function Ds(r,o,i,l,c,u){const p=await o.getFileHandle(hr,{create:!0}),y=await Z(p,"record of changes");try{y.truncate(0),y.flush()}finally{y.close()}const _={storageVersion:u?5:4,generation:r,initializedAt:Date.now(),...u?{imageRanges:u}:{}};if(await lt(await Te(),Xe,_),Ge(),T=r,L=_.initializedAt,J=u,c){const k=new Re(c.index);g=new Ke(k),U=new $t(k),re=void 0}else g=i,Ye();v=l,m=o,await He(o),c?({liveBytes:B,linked:w,linkedBytes:b}=c,Q=Math.max(0,v-B)):at(),d||await rr(r)}async function Cs(r,o,i,l,c=!1){if(be(),!d||S!==xe)throw new Error("Only the shared package store can reserve immutable image extents.");if(v!==0||[...g.values()].some(O=>O.type!=="directory"))return!1;const u=ur(l);if(u.bytes!==r.packBytes||r.entries>wr||r.liveBytes>r.packBytes||o.byteLength!==r.json.raw||i.byteLength!==r.binary.raw||!await Mt(o,r.json.sha256,c)||!await Mt(i,r.binary.sha256,c))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 y=JSON.parse(`${Qe.decode(o.subarray(0,p-1))}}`),_={packBytes:r.packBytes,liveBytes:r.liveBytes,linked:0,linkedBytes:0},k=y.retainedIndex;if(k.version!==1||k.digest!==await Jr(r.binary.sha256,_)||k.packBytes!==_.packBytes||k.liveBytes!==_.liveBytes||k.linked!==0||k.linkedBytes!==0)throw new Error("The prepared index's retained measures are inconsistent.");const F=new SharedArrayBuffer(i.byteLength);if(new Uint8Array(F).set(i),new Re(F).entryCount!==r.entries)throw new Error("The prepared index has the wrong number of entries.");return bt(async()=>{const O=crypto.randomUUID(),I=await pe(O,!0),j=await I.getFileHandle(Ze,{create:!0}),W=await Z(j,"immutable image reservation");try{W.truncate(r.packBytes),W.flush()}finally{W.close()}const ne=Be.encode(JSON.stringify(u));return await Se(I,cn,ne),await Se(I,Tt,i),await Se(I,de,o),await Nt(O,I,new Map,r.packBytes,{index:F,..._},await me(ne)),!0})}async function zs(r,o,i,l=!1,c){if(be(),d||!e.packages||!c&&!e.packages.deferredImage)throw new Error("Prepared project paths require a verified shared image.");if(v!==0||[...g.values()].some(k=>k.type!=="directory"))return!1;if(o.byteLength!==r.json.raw||i.byteLength!==r.binary.raw||!await Mt(o,r.json.sha256,l)||!await Mt(i,r.binary.sha256,l))throw new Error("The image's prepared project does not match its descriptor.");const u=o.subarray(0,4096).indexOf(10);if(u<0)throw new Error("The prepared project has no bounded retained header.");const p=JSON.parse(`${Qe.decode(o.subarray(0,u-1))}}`).retainedIndex,y={packBytes:0,liveBytes:0,linked:r.linked,linkedBytes:r.linkedBytes};if(p.version!==1||p.digest!==await Jr(r.binary.sha256,y)||p.packBytes!==0||p.liveBytes!==0||p.linked!==r.linked||p.linkedBytes!==r.linkedBytes)throw new Error("The prepared project's retained measures are inconsistent.");const _=new SharedArrayBuffer(i.byteLength);if(new Uint8Array(_).set(i),new Re(_).entryCount!==r.entries||r.entries>s)throw new Error("The prepared project has invalid entry bounds.");return bt(async()=>{const k=crypto.randomUUID(),F=await pe(k,!0),O=await F.getFileHandle(Ze,{create:!0}),I=await Z(O,"prepared project");try{I.truncate(0),I.flush()}finally{I.close()}if(await Se(F,Tt,i),await Se(F,de,o),c&&!await c)return!1;if(!e.packages?.deferredImage)throw new Error("Prepared project paths require a verified shared image.");return await Nt(k,F,new Map,0,{index:_,...y}),!0})}async function Us(){if(Y)throw new Error("This OPFS workspace is closing.");if(!$)throw new Error("OPFS filesystem worker is not initialized.");const r=[],o=[...g.keys()].sort((p,y)=>Xr(p)-Xr(y)||(p<y?-1:1));let i=0;for(const p of g.values())p.type!=="directory"&&(i+=p.length);const l=new ArrayBuffer(i),c=new Uint8Array(l);let u=0;for(const p of o){const y=g.get(p);if(y.type==="directory"){r.push({path:p,type:"directory",mode:y.mode,mtimeMs:y.mtimeMs});continue}y.length>0&&c.set(Et(y),u),r.push({path:p,type:y.type,offset:u,length:y.length,mode:y.mode,mtimeMs:y.mtimeMs}),u+=y.length}for(const p of[...Ee()].reverse())g.has(p)||r.unshift({path:p,type:"directory",mode:et,mtimeMs:Date.now()});return ar({files:r,pack:l})}async function lt(r,o,i){await Se(r,o,Be.encode(JSON.stringify(i)))}async function Se(r,o,i){const l=await(await Te()).getDirectoryHandle(dn,{create:!0}),c=crypto.randomUUID(),u=await l.getFileHandle(c,{create:!0}),p=await Z(u,"index");try{let y=0;for(;y<i.byteLength;){const _=p.write(i.subarray(y),{at:y});if(_<=0)throw new Error("An OPFS workspace file could not be written completely.");y+=_}p.truncate(i.byteLength),p.flush()}finally{p.close()}try{await u.move(r,o)}finally{await Gr(l,c,!1)}}const Tt="index.shared";async function me(r){const o=await crypto.subtle.digest("SHA-256",r);return Array.from(new Uint8Array(o),i=>i.toString(16).padStart(2,"0")).join("")}async function Mt(r,o,i){return i||await me(r)===o}function Jr(r,o){const{packBytes:i,liveBytes:l,linked:c,linkedBytes:u,journalPrefix:p}=o;return me(Be.encode(`${JSON.stringify({packBytes:i,liveBytes:l,linked:c,linkedBytes:u,...p?{journalPrefix:p}:{}})}:${r}`))}async function Hr(r,o){const{packBytes:i,liveBytes:l,linked:c,linkedBytes:u,journalPrefix:p}=o;return me(Be.encode(`${JSON.stringify({packBytes:i,liveBytes:l,linked:c,linkedBytes:u,...p?{journalPrefix:p}:{}})}:${await me(r)}`))}async function dt(r,o,i){const l=Js(o);if(typeof SharedArrayBuffer>"u"||o.size<1e4){await lt(r,de,l);return}const c=new Map(l.entries),u=new Map,p={packBytes:i?.packBytes??0,liveBytes:0,linked:0,linkedBytes:0};for(const[j,W]of c){const ne=Le(j);if(ne!==j){let z=u.get(ne);z||(z=new Set,u.set(ne,z)),z.add(j.slice(ne.length+1))}W.pack?(p.linked+=1,p.linkedBytes+=W.length):(p.liveBytes+=W.length,p.packBytes=Math.max(p.packBytes,W.offset+W.length))}let y;try{y=on(c,u)}catch{await lt(r,de,l);return}const _=JSON.stringify(l.entries),k=i?new Uint8Array(i.bytes):void 0;if(k&&i.access.read(k,{at:0})!==k.byteLength)throw new Error("The checkpoint's journal prefix could not be read completely.");const F=k?{bytes:k.byteLength,digest:await me(k)}:void 0,O=new Uint8Array(y).slice(),I={version:F?2:1,digest:await Hr(O,{...p,...F?{journalPrefix:F}:{}}),...p,...F?{journalPrefix:F}:{}};try{await Se(r,Tt,O)}catch{await lt(r,de,{entries:JSON.parse(_)});return}return await Se(r,de,Be.encode(`{"retainedIndex":${JSON.stringify(I)},
|
|
3
|
+
"entries":${_}}`)),{index:y,...p}}async function js(r){if(!(typeof SharedArrayBuffer>"u"))try{const o=await r.getFileHandle(de),i=await Z(o,"index");let l;try{const O=new Uint8Array(Math.min(512,i.getSize())),I=i.read(O,{at:0});l=Qe.decode(O.subarray(0,I))}finally{i.close()}const c=l.split(`
|
|
4
|
+
`,1)[0];if(!c.startsWith('{"retainedIndex":')||!c.endsWith(","))return;const u=JSON.parse(c.slice(0,-1)+"}").retainedIndex;if(u.version!==1&&u.version!==2||!/^[a-f0-9]{64}$/u.test(u.digest)||![u.packBytes,u.liveBytes,u.linked,u.linkedBytes].every(O=>Number.isSafeInteger(O)&&O>=0)||u.version===1&&u.journalPrefix!==void 0||u.version===2&&(!u.journalPrefix||!Number.isSafeInteger(u.journalPrefix.bytes)||u.journalPrefix.bytes<0||!/^[a-f0-9]{64}$/u.test(u.journalPrefix.digest)))return;const p=await r.getFileHandle(Tt),y=await Z(p,"index");let _;try{const O=y.getSize();if(O>256*1024*1024||(_=new Uint8Array(O),y.read(_,{at:0})!==O))return}finally{y.close()}if(await Hr(_,u)!==u.digest)return;const k=new SharedArrayBuffer(_.byteLength);new Uint8Array(k).set(_);const F=new Re(k);return we(F.entryCount),{...u,index:k}}catch{return}}async function qs(r){const o=r.journalPrefix;if(!o||!P||!$||o.bytes>P.getSize()||r.packBytes>$.getSize())return 0;const i=new Uint8Array(o.bytes);return P.read(i,{at:0})!==i.byteLength?0:await me(i)===o.digest?o.bytes:0}async function Fe(r,o){let i;try{i=await r.getFileHandle(o)}catch(u){if(Ve(u))return;throw u}let l;if(f){l=await(await i.getFile()).text();try{return JSON.parse(l)}catch(u){throw new Error(`Invalid OPFS workspace metadata (${o}). Stored data was retained.`,{cause:u})}}const c=await Z(i,"index");try{const u=c.getSize(),p=new Uint8Array(u);if(u>0&&c.read(p,{at:0})!==u)throw new Error("An OPFS workspace file could not be read completely.");l=Qe.decode(p)}finally{c.close()}try{return JSON.parse(l)}catch(u){throw new Error(`Invalid OPFS workspace metadata (${o}). Stored data was retained.`,{cause:u})}}async function Gr(r,o,i){try{await r.removeEntry(o,{recursive:i})}catch(l){if(!Ve(l))throw l}}async function Yr(r,o){try{await r.removeEntry(o,{recursive:!0})}catch{}}function Vr(r){if(!r||typeof r!="object"||Array.isArray(r))throw new Error("Invalid OPFS filesystem mutation.");if(r.operation!=="write"&&r.operation!=="append"&&r.operation!=="write-at"&&r.operation!=="mkdir"&&r.operation!=="remove"&&r.operation!=="rename"&&r.operation!=="metadata"&&r.operation!=="link")throw new Error("Invalid OPFS filesystem mutation.");if(ye(r.path),r.operation==="rename"&&ye(r.destination),(r.operation==="write"||r.operation==="append"||r.operation==="write-at")&&!(r.content instanceof Uint8Array))throw new Error("Invalid OPFS file content.");if(r.operation==="write-at"&&(!Number.isSafeInteger(r.position)||r.position<0))throw new Error("Invalid OPFS write position.");return cr(r),r}function Ws(r){if(!Array.isArray(r)||r.length===0||r.length>128)throw new Error("Invalid OPFS filesystem mutation batch.");return r.map(o=>Vr(o))}function ar(r){if(!r||!Array.isArray(r.files)||r.files.length>s||!(r.pack instanceof ArrayBuffer))throw new Error("Invalid OPFS workspace snapshot.");const o=new Set,i=new Map(Ee().map(c=>[c,"directory"]));let l=0;for(const c of r.files){if(!c||typeof c!="object")throw new Error("Invalid OPFS workspace snapshot entry.");if(ye(c.path),c.type!=="file"&&c.type!=="directory"&&c.type!=="symlink"||o.has(c.path))throw new Error("Invalid or duplicate OPFS workspace entry.");if(o.add(c.path),i.set(c.path,c.type),Ee().includes(c.path)&&c.type!=="directory")throw new Error("The OPFS workspace root must be a directory.");if(c.type!=="directory"){const u=c.offset??0,p=c.length??0;if(!Number.isSafeInteger(u)||!Number.isSafeInteger(p)||u<0||p<0||p>se||u+p>r.pack.byteLength)throw new Error("Invalid OPFS workspace file.");if(l+=p,l>t)throw new Error("OPFS workspace exceeds its byte limit.")}else if((c.offset??0)!==0||(c.length??0)!==0)throw new Error("An OPFS workspace directory cannot contain file bytes.");cr(c)}we(i.size);for(const c of r.files)if(!Ee().includes(c.path)&&i.get(Le(c.path))!=="directory")throw new Error(`An OPFS workspace snapshot has no directory parent for ${c.path}.`);return r}function cr(r){if(r.mode!==void 0&&(!Number.isSafeInteger(r.mode)||r.mode<0||r.mode>4095))throw new Error("Invalid OPFS file mode.");if(r.mtimeMs!==void 0&&(typeof r.mtimeMs!="number"||!Number.isFinite(r.mtimeMs)||r.mtimeMs<0))throw new Error("Invalid OPFS modification time.")}function Js(r){return{entries:[...r]}}function lr(r){const o=new Map;if(r===void 0)throw new Error("The committed OPFS workspace index is missing. Stored data was retained.");if(!r||typeof r!="object"||!Array.isArray(r.entries))throw new Error("Invalid OPFS workspace index.");const i=r.entries;we(i.length);for(const l of i){if(!Array.isArray(l)||l.length!==2)throw new Error("Invalid OPFS workspace index entry.");const c=ye(l[0]);if(o.has(c))throw new Error("Duplicate OPFS workspace index entry.");o.set(c,Kr(l[1]))}return o}function Kr(r){if(!r||typeof r!="object"||Array.isArray(r))throw new Error("Invalid OPFS workspace index entry.");const o=r;if(o.type!=="file"&&o.type!=="directory"&&o.type!=="symlink")throw new Error("Invalid OPFS workspace index entry.");if(cr(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>se)throw new Error("Invalid OPFS workspace index extent.");if(o.pack!==void 0&&o.pack!==xe)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 Hs(r){if(!r||typeof r!="object"||Array.isArray(r))throw new Error("Invalid OPFS workspace index record.");const o=r;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([ye(l[0]),l[1]===null?null:Kr(l[1])])}return{packBytes:o.packBytes,changes:i}}function Ft(r){if(r===void 0)return;if(!r||typeof r!="object"||Array.isArray(r))throw new Error("Invalid OPFS workspace state. Stored data was retained.");const o=r;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 ye(r){if(typeof r!="string"||ct(r)===void 0||r.includes("\0")||r.length>4096)throw new Error("Invalid OPFS workspace path.");return Qr(r),r}function Qr(r){const o=ct(r);if(o===void 0)throw new Error("Invalid OPFS workspace path.");const i=r===o?"":r.slice(o.length+1);return dr(i),i}function dr(r){const o=r===""?[]:r.split("/");if(o.some(i=>!i||i==="."||i===".."||i.includes("\0")))throw new Error("Invalid OPFS workspace path segment.");return o}function Le(r){const o=r.slice(0,r.lastIndexOf("/"));return o===""||ct(o)===void 0?ct(r)??r:o}function Xr(r){let o=1;for(let i=0;i<r.length;i+=1)r.charCodeAt(i)===47&&(o+=1);return o}function Ve(r){return r instanceof DOMException&&r.name==="NotFoundError"}function Zr(r){let o=2166136261;for(let i=0;i<r.byteLength;i+=1)o^=r[i],o=Math.imul(o,16777619);return o>>>0}typeof addEventListener=="function"&&addEventListener("close",()=>{$?.flush(),P?.flush(),Ge(),E?.()});function en(r,o={}){if(be(),ae)throw new Error("An OPFS mutation batch cannot be nested.");for(const i of r)Vr(i);return r.length?tn(i=>{for(const l of r)xs(l,i)},o):[]}function Gs(r,o,i={}){if(be(),ae)throw new Error("An OPFS mutation batch cannot be nested.");for(const l of o){if(ye(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:c,length:u}=l;if(c===void 0||u===void 0||!Number.isSafeInteger(c)||!Number.isSafeInteger(u)||c<0||u<0||c+u>r.byteLength)throw new Error(`OPFS extent ${l.path} lies outside its bytes.`);if(u>se)throw new Error(`${l.path} is ${u} bytes; an OPFS workspace file holds at most ${se}.`)}return o.length?tn(l=>{const c=r.byteLength>0?It(r):v;for(const u of o){const p=ye(u.path);Me(p,l);const y=g.get(p);if(u.type==="directory"){if(y&&y.type!=="directory")throw new Error(`OPFS path is a file: ${p}`);ee(p,{type:"directory",mode:u.mode,mtimeMs:u.mtimeMs,offset:0,length:0},l);continue}if(y?.type==="directory")throw new Error(`OPFS write target is a directory: ${p}`);At(p,u.length),ee(p,{type:u.type,mode:u.mode,mtimeMs:u.mtimeMs,offset:c+u.offset,length:u.length},l)}},i):[]}function tn(r,o){if(!$||!P)throw new Error("OPFS filesystem worker is not initialized.");const i={packBytes:v,logBytes:M,liveBytes:B,deadBytes:Q,rewrites:Ie,rewrittenBytes:Oe,linked:w,linkedBytes:b},l=new Map;ae=l;const c=[];mt=c;const u=[];try{return r(u),Ur(),Os(u,{publish:!o.durable}),o.durable&&(ke(),yt()),Rr(),u}catch(p){const y=V!==void 0&&!ue&&Atomics.load(V,pn)!==i.logBytes;y&&ot();for(const[_,k]of l)k===void 0?g.delete(_):g.set(_,k);Ye();try{for(let _=c.length-1;_>=0;_-=1)vt(c[_][0],c[_][1])}catch(_){p=new AggregateError([p,_],"OPFS could not restore bytes a failed batch wrote over.")}({packBytes:v,logBytes:M,liveBytes:B,deadBytes:Q,rewrites:Ie,rewrittenBytes:Oe,linked:w,linkedBytes:b}=i),K!==void 0&&(clearTimeout(K),K=void 0);try{P.truncate(M),P.flush(),$.truncate(v),$.flush()}catch(_){throw _t(),fe=new AggregateError([p,_],"OPFS could not roll back a failed batch; reopen this workspace before writing again."),fe}throw y&&it(),p}finally{ae=void 0,mt=void 0}}function Ys(){if(qe){st?.abort(new DOMException("The workspace was closed while opening.","AbortError"));return}Y||(Y=!0,We===0&&rn())}function rn(){_t();try{ke()}finally{try{Ge()}finally{const r=E;E=void 0,a=void 0;try{r?.()}finally{e.ownsPackages&&e.packages?.close()}}}}return{initialize:ys,opened:()=>a!==void 0&&!Y,stats:()=>({entries:g.size,liveBytes:B,deadBytes:Q,packBytes:v,rewrites:Ie,rewrittenBytes:Oe,linked:w,linkedBytes:b,flushes:ve,flushMs:ge}),applyNow:en,applyExtentsNow:Gs,close:Ys,readExtent:kt,descendants:or,retain:Wr,remapLinks:$s,childrenOf:r=>[...U.get(r)??[]].sort(),refresh:_s,follow:hs,clock:Tr,readerSeed:ds,imageCompletionSeed:fs,imageLine:()=>q?.lineForReader()??e.packages?.imageLine(),imageStartupSet:()=>q?.readDigests()??q?.completedDigests()??[],prefetchImage:(r,o)=>q?.prefetch(r,o)??{queued:0,done:Promise.resolve()},seeded:()=>Mr,get logBytes(){return M},checkpoint:Ot,deferMaintenance:Ps,installPreparedImage:Cs,installPreparedProject:zs,get deferredImage(){return _e},get imagePlacedAt(){return a&&J?L:void 0},get entries(){return g},get packBytes(){return v},read:ws,readRange:ms,snapshot:Us,replace:qr,apply:Ss,flush:()=>{if(Y||!a)throw new Error("This OPFS workspace is not open.");if(Je)throw new Error("Wait for the OPFS generation replacement before flushing it.");ke()},validateSnapshot:ar,validateMutationBatch:Ws}}async function ho(n,e,t,s){const a=yn(n);await a.initialize(xe,{readOnly:!0,extentsOnly:!0});const d=yn(n,{packages:a,ownsPackages:!0});let f;try{f=await d.initialize(e,{readOnly:!0,...t?{seed:t}:{}})}catch(h){throw d.close(),a.close(),h}if(!f&&!d.opened()){a.close();return}return d}const wo="sweep.json";async function mo(n){const t=await(await n.getFileHandle(wo,{create:!0})).createWritable();await t.write(JSON.stringify({at:Date.now()})),await t.close()}class zt{map=new Map;get(e){return this.map.get(e)}mutable(e){let t=this.map.get(e);return t||(t=new Set,this.map.set(e,t)),t}delete(e){this.map.delete(e)}}function yo(n){const e=n.toBase64;if(typeof e=="function")return e.call(n);let t="";for(let s=0;s<n.byteLength;s+=32768)t+=String.fromCharCode(...n.subarray(s,s+32768));return btoa(t)}function Hn(n){const e=Uint8Array.fromBase64;if(typeof e=="function")return e(n);const t=atob(n),s=new Uint8Array(t.length);for(let a=0;a<t.length;a+=1)s[a]=t.charCodeAt(a);return s}function _o(n,e,t){const{appended:s,superseded:a}=t?go(n,e,t):{appended:new Map,superseded:new Set},d=[...e.removed].sort((h,m)=>Ut(m)-Ut(h));for(const h of d)n.existsSync(h)&&(n.statSync(h).isDirectory()?n.rmdirSync(h):n.unlinkSync(h));const f=[...e.files].filter(h=>!a.has(h.path)).sort((h,m)=>Ut(h.path)-Ut(m.path));for(const h of f){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(Ue(h)){n.existsSync(h.path)&&n.statSync(h.path).isDirectory()&&n.rmdirSync(h.path);const m=h.path.slice(0,h.path.lastIndexOf("/"))||"/";m!=="/"&&!n.existsSync(m)&&n.mkdirSync(m,{recursive:!0});const w=n.existsSync(h.path)?n.statSync(h.path).mode:void 0,b=w!==void 0&&(w&128)===0;b&&n.chmodSync?.(h.path,w&4095|128),n.writeFileSync(h.path,s.get(h.path)??pt(h)),b&&h.mode===void 0&&n.chmodSync?.(h.path,w&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 go(n,e,t){const s=new Map,a=new Set,d=t.byPath,f=d instanceof Map?d:new Map(t.files.map(w=>[w.path,w])),h=new Map(e.files.map(w=>[w.path,w])),m=new Set([...e.files.map(w=>w.path),...e.removed]);for(const w of m){const b=f.get(w),E=Po(n,w);if(b!==void 0&&yr(b,h.get(w))||E===void 0&&h.get(w)!==void 0)continue;const S=h.get(w);if(!(E!==void 0&&S!==void 0&&S.type===E.type&&(C(S).mtimeMs??0)>(C(E).mtimeMs??0))&&!(b!==void 0&&E!==void 0&&b.type===E.type&&(C(E).mtimeMs??0)<(C(b).mtimeMs??0))&&!yr(b,E)&&!yr(h.get(w),E)){if(Eo(b,E,h.get(w)))continue;const T=bo(n,w,b,E,h.get(w),t.bytesOf?.bind(t));if(T){s.set(w,T);continue}const g=h.get(w);if(b!==void 0&&E!==void 0&&g!==void 0&&g.type===E.type&&(C(g).mtimeMs??0)>=(C(b).mtimeMs??0)&&(C(E).mtimeMs??0)>(C(g).mtimeMs??0)&&(C(E).mtimeMs??0)>(C(b).mtimeMs??0)){a.add(w);continue}throw new Error(`Browser filesystem write conflict at ${w}. ${JSON.stringify({base:mr(b),current:mr(E),proposed:mr(h.get(w))})}`)}}return{appended:s,superseded:a}}function bo(n,e,t,s,a,d){if(t?.type!=="file"||s?.type!=="file"||a?.type!=="file"||!Ue(a)||!n.readFileSync||C(s).mode!==C(a).mode)return;const f=Ue(t)?pt(t):d?.(e);if(!f||f.length===0)return;const h=pt(a),m=n.readFileSync(e),w=typeof m=="string"?new TextEncoder().encode(m):m,b=S=>S.length>=f.length&&Yn(S.subarray(0,f.length),f);if(h.length<=f.length||!b(h)||!b(w))return;const E=new Uint8Array(w.length+h.length-f.length);return E.set(w,0),E.set(h.subarray(f.length),w.length),E}function mr(n){return n?{type:n.type,...C(n)}:null}function Eo(n,e,t){return e?.type!=="directory"||t?.type!=="directory"?!1:n===void 0?C(e).mode===C(t).mode:C(e).mode===C(t).mode&&n.type==="directory"&&C(n).mode===C(e).mode}function ko(n,e){const t=new Set(e.removed),s=new Map(e.files.map(d=>[d.path,d])),a=[];for(const d of n.files){if(t.has(d.path))continue;const f=s.get(d.path);if(f){a.push(f),s.delete(d.path);continue}a.push(d)}for(const d of s.values())a.push(d);return{files:a}}function So(n,e,t={}){const s=new Map(n.files.map(d=>[d.path,d])),a=new Map(e.files.map(d=>[d.path,d]));return{files:e.files.filter(d=>{const f=s.get(d.path);return d.path==="/"&&!f?!1:!f||f.type!==d.type||!Gn(f,d)||t.written===!0&&d.type==="file"&&!Ue(f)&&Ue(d)||C(f).mode!==C(d).mode||C(f).mtimeMs!==C(d).mtimeMs}),removed:n.files.flatMap(d=>a.has(d.path)?[]:[d.path])}}function Ut(n){let e=1;for(let t=0;t<n.length;t+=1)n.charCodeAt(t)===47&&(e+=1);return e}function Po(n,e){if(!n.existsSync(e))return;const t=n.statSync(e),s={...t.mode!==void 0?{mode:t.mode}:{},...t.mtimeMs!==void 0?{mtimeMs:t.mtimeMs}:{}};return t.isDirectory()?{path:e,type:"directory",...s}:{path:e,type:"file",...t.size!==void 0?{size:t.size}:{},...s}}function yr(n,e){return n===void 0?e===void 0:e!==void 0&&n.type===e.type&&Gn(n,e)&&C(n).mode===C(e).mode&&C(n).mtimeMs===C(e).mtimeMs}function C(n){const e=n;return{...e.mode===void 0?{}:{mode:e.mode&4095},...e.mtimeMs===void 0?{}:{mtimeMs:e.mtimeMs}}}function Gn(n,e){return n.type!=="file"||e.type!=="file"?!0:n.content!==void 0&&e.content!==void 0?n.content===e.content:Ue(n)&&Ue(e)?Yn(pt(n),pt(e)):_n(n)===_n(e)}function _n(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 Ue(n){return n!==void 0&&(n.bytes!==void 0||n.content!==void 0)}function pt(n){return n.bytes??(n.content===void 0?void 0:Hn(n.content))}function Yn(n,e){if(n===e)return!0;if(n.byteLength!==e.byteLength)return!1;let t=0;if(n.byteOffset%4===0&&e.byteOffset%4===0){const s=n.byteLength>>>2,a=new Uint32Array(n.buffer,n.byteOffset,s),d=new Uint32Array(e.buffer,e.byteOffset,s);for(let f=0;f<s;f+=1)if(a[f]!==d[f])return!1;t=s<<2}for(;t<n.byteLength;t+=1)if(n[t]!==e[t])return!1;return!0}const Or="314.0.6",xo=`https://cdn.jsdelivr.net/pyodide/v${Or}/full/`,Ao=[{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 vo(n){const e=Ao.find(t=>t.file===n);if(!e)throw new Error(`Pyodide ${Or} publishes no pinned ${n}.`);return e}async function Io(n){const e=new Uint8Array(await crypto.subtle.digest("SHA-256",n));let t="";for(const s of e)t+=String.fromCharCode(s);return`sha256-${btoa(t)}`}async function gn(n,e){const t=vo(n),s=await Io(e);if(s!==t.integrity)throw new Error(`Pyodide ${Or} ${n} is ${s}, not the pinned ${t.integrity}.`)}const G="/workspace";let bn,Yt="program";function Oo(){return Yt}async function No(n,e){const t=Yt;Yt=n;try{return await e()}finally{Yt=t}}async function To(n){return new Uint8Array(await new Response(new Blob([n]).stream().pipeThrough(new DecompressionStream("gzip"))).arrayBuffer())}function Vn(n=xo,e){return bn??=(async()=>{const t=e?await To(e).catch(()=>{}):void 0,s=async(a,d)=>{if(t)try{const f=await a.loadPyodide({...d,_loadSnapshot:t});return await f.runPythonAsync(`import random
|
|
5
|
+
random.seed()`),delete f._api?.config?._loadSnapshot,f}catch(f){console.warn(`[python] the interpreter snapshot did not restore; starting Python: ${f instanceof Error?f.message:String(f)}`)}return await a.loadPyodide(d)};return No("runtime",async()=>{if(n.startsWith("/")){const b=await import(`file://${n}pyodide.mjs`),E=await import(`file://${n}pyodide.asm.mjs`);return await s(b,{indexURL:n,createPyodideModule:E.default})}const[a,d]=await Promise.all([fetch(`${n}pyodide.mjs`),fetch(`${n}pyodide.asm.mjs`)]);if(!a.ok)throw new Error(`Could not load Pyodide (${a.status}).`);if(!d.ok)throw new Error(`Could not load the Pyodide runtime module (${d.status}).`);const[f,h]=await Promise.all([a.bytes(),d.bytes()]);await gn("pyodide.mjs",f),await gn("pyodide.asm.mjs",h);const m=URL.createObjectURL(new Blob([f],{type:"text/javascript"})),w=URL.createObjectURL(new Blob([h],{type:"text/javascript"}));try{const b=await import(m),E=await import(w);return await s(b,{indexURL:n,createPyodideModule:E.default})}finally{URL.revokeObjectURL(m),URL.revokeObjectURL(w)}})})(),bn}const Mo=16384;function Fo(n){return{existsSync:e=>n.analyzePath(e).exists,statSync:e=>{const t=n.stat(e),s=(t.mode&61440)===Mo;return{isDirectory:()=>s,...typeof t.size=="number"?{size:t.size}:{},...Sr(t)}},readFile:e=>Promise.resolve(n.readFile(e)),writeFileSync:(e,t)=>n.writeFile(e,typeof t=="string"?new TextEncoder().encode(t):t),mkdirSync:e=>n.mkdirTree(e),unlinkSync:e=>n.unlink(e),rmdirSync:e=>n.rmdir(e),chmodSync:(e,t)=>n.chmod(e,t),utimesSync:(e,t,s)=>n.utime(e,En(t),En(s))}}function Lo(n,e,t){_o(Fo(n),e,t)}function En(n){return typeof n=="number"?n:Number(n)}function $o(n,e){Zn(n,G),n.mkdirTree(G);const t=e.files.slice().sort((s,a)=>kn(s.path)-kn(a.path));for(const s of t)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,Ro(s.content??""))));for(const s of t){const a=s;a.path!==G&&!a.path.startsWith(`${G}/`)||(a.mode!==void 0&&n.chmod(a.path,a.mode),a.mtimeMs!==void 0&&n.utime(a.path,a.mtimeMs,a.mtimeMs))}}function Kn(n,e){const s=[...e.files.filter(a=>a.path!==G&&!a.path.startsWith(`${G}/`))];return Xn(n,G,s),{files:s}}function Kt(n,e){const t=n.startsWith("/")?n:`${e}/${n}`,s=[];for(const a of t.split("/"))!a||a==="."||(a===".."?s.pop():s.push(a));return`/${s.join("/")}`}function je(n){return n.slice(n.lastIndexOf("/")+1)}function Qn(n){let e="";for(let t=0;t<n.byteLength;t+=32768)e+=String.fromCharCode(...n.subarray(t,t+32768));return btoa(e)}function Ro(n){const e=atob(n);return Uint8Array.from(e,t=>t.charCodeAt(0))}function Xn(n,e,t){const s=n.stat(e),a=Sr(s);t.push({path:e,type:"directory",...a});for(const d of n.readdir(e)){if(d==="."||d==="..")continue;const f=`${e}/${d}`,h=n.stat(f);(h.mode&61440)===16384?Xn(n,f,t):t.push({path:f,type:"file",content:Qn(n.readFile(f)),...Sr(h)})}}function Zn(n,e){if(n.analyzePath(e).exists)for(const t of n.readdir(e)){if(t==="."||t==="..")continue;const s=`${e}/${t}`;(n.stat(s).mode&61440)===16384?(Zn(n,s),n.rmdir(s)):n.unlink(s)}}function kn(n){let e=1;for(let t=0;t<n.length;t+=1)n.charCodeAt(t)===47&&(e+=1);return e}function Sr(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 Pr=16384,Bo=32768,Sn=44;function Do(n,e){const t=n,s=t.filesystems?.MEMFS;if(!s||typeof t.mount!="function"||typeof s.createNode!="function")return;const a={dirty:new Set,removed:new Set},d=()=>t.genericErrors?.[Sn]??new t.ErrnoError(Sn),f=N=>N.packPath??G;function h(N,R,L){const P=e.entries.get(L);if(!P)throw d();const x=P.mode&4095|(P.type==="directory"?Pr:Bo),A=s.createNode(N,R,x,0);return A.packPath=L,A.timestamp=P.mtimeMs,A.atime=A.mtime=A.ctime=P.mtimeMs,P.type==="directory"?(A.packListed=!1,A.node_ops=S(A.node_ops)):(A.packLoaded=!1,A.usedBytes=P.length,A.node_ops=g(A.node_ops),A.stream_ops=$(A.stream_ops)),A}function m(N){if(N.packLoaded!==!1||!N.packPath)return;const R=e.read(N.packPath);N.contents=R,N.usedBytes=R.byteLength,N.packLoaded=!0}function w(N){t.isDir(N.mode)||a.dirty.add(b(N))}function b(N){const R=[];let L=N;for(;L&&L.parent!==L;)R.unshift(L.name),L=L.parent;return`${G}/${R.join("/")}`.replace(/\/+$/u,"")||G}const E=new WeakMap;function S(N){const R=E.get(N);if(R)return R;const L={...N,lookup:(P,x)=>{const A=`${f(P)}/${x}`;if(!a.removed.has(A)&&e.entries.has(A))return h(P,x,A);throw d()},readdir:P=>{const x=N.readdir(P),A=new Set(x),D=f(P);for(const H of e.childrenOf(D))a.removed.has(`${D}/${H}`)||A.add(H);return[...A]},mknod:(P,x,A,D)=>{const H=`${f(P)}/${x}`;a.removed.delete(H);const v=N.mknod(P,x,A,D);return v.packPath=H,t.isDir(A)?(v.packListed=!0,v.node_ops=S(v.node_ops)):(v.packLoaded=!0,a.dirty.add(H),v.node_ops=g(v.node_ops),v.stream_ops=$(v.stream_ops)),v},unlink:(P,x)=>{const A=`${f(P)}/${x}`;N.unlink(P,x),a.dirty.delete(A),a.removed.add(A)},rmdir:(P,x)=>{const A=`${f(P)}/${x}`;for(const D of e.childrenOf(A))if(!a.removed.has(`${A}/${D}`))throw new t.ErrnoError(55);N.rmdir(P,x),a.removed.add(A)},rename:(P,x,A)=>{const D=b(P);t.isFile(P.mode)?m(P):J(P),N.rename(P,x,A);const H=`${f(x)}/${A}`;q(P,D,H),a.removed.add(D),a.removed.delete(H)}};return E.set(N,L),L}const T=new WeakMap;function g(N){const R=T.get(N);if(R)return R;const L={...N,setattr:(P,x)=>{x.size!==void 0&&m(P),N.setattr(P,x),(x.size!==void 0||x.mode!==void 0||x.timestamp!==void 0)&&w(P)}};return T.set(N,L),L}const U=new WeakMap;function $(N){const R=U.get(N);if(R)return R;const L={...N,open:P=>{m(P.node),N.open?.(P)},write:(P,x,A,D,H,v)=>{m(P.node);const K=N.write(P,x,A,D,H,v);return w(P.node),K}};return U.set(N,L),L}function J(N){const R=f(N);for(const L of e.childrenOf(R)){if(a.removed.has(`${R}/${L}`))continue;const x=N.contents[L]??h(N,L,`${R}/${L}`);t.isDir(x.mode)?J(x):m(x)}N.packListed=!0}function q(N,R,L){if(N.packPath=L,t.isFile(N.mode)){a.dirty.delete(R),a.dirty.add(L);return}for(const[P,x]of Object.entries(N.contents))q(x,`${R}/${P}`,`${L}/${P}`)}const _e={mount:()=>{const N=s.createNode(null,"/",Pr|493,0);return N.packPath=G,N.node_ops=S(N.node_ops),N}};if(t.analyzePath(G).exists){try{t.unmount(G)}catch{}try{t.rmdir(G)}catch{}}return t.mkdirTree(G),t.mount(_e,{},G),a}function Co(n,e,t){const s=t.files.filter(d=>d.path!==G&&!d.path.startsWith(`${G}/`)),a=d=>{const f=n.stat(d),h=typeof f.mtime=="number"?f.mtime:Number(f.mtime),m={mode:f.mode&4095,...typeof h=="number"&&Number.isFinite(h)?{mtimeMs:h}:{}};if((f.mode&61440)===Pr){s.push({path:d,type:"directory",...m});for(const w of n.readdir(d))w==="."||w===".."||a(`${d}/${w}`);return}e.dirty.has(d)?s.push({path:d,type:"file",content:Qn(n.readFile(d)),...m}):s.push({path:d,type:"file",...typeof f.size=="number"?{size:f.size}:{},...m})};return a(G),{files:s}}const Ce="/workspace/.supercode/python-requirements.txt",Pn=64,zo=256;async function Uo(n){const e=Ho(n.FS);e.length!==0&&(Ln({door:"pip install",subject:`${e.join(" ")}, recorded in ${Ce} by an earlier session`,fix:`a Python project's packages cannot yet be carried as packs; remove ${Ce} to run Python without them.`}),await es(n,e),rs(n.FS,await ts(n)))}async function jo(n,e){e.requirements.length!==0&&(await es(n,e.requirements),rs(n.FS,await ts(n)))}function qo(n){const e=new Map;let t;for(const s of n.split(`
|
|
6
|
+
`)){const a=s.trim();if(a==="[[package]]"){t=void 0;continue}if(a.startsWith("[")&&a!=="[[package]]"){t=void 0;continue}const d=/^name\s*=\s*"([^"]+)"$/u.exec(a);if(d){t=d[1];continue}const f=/^version\s*=\s*"([^"]+)"$/u.exec(a);f&&t&&!e.has(t)&&e.set(t,f[1])}return e}function Wo(n,e){const t=/^[A-Za-z0-9._-]+/u.exec(n.trim())?.[0];if(!t)return n;const s=e.get(t)??e.get(t.toLowerCase())??e.get(t.replace(/_/gu,"-").toLowerCase());return s?`${t}==${s}`:n}function Jo(n,e,t){const s=je(e[0]??""),a=s==="pip"||s==="pip3"?e.slice(1):(s==="python"||s==="python3")&&e[1]==="-m"&&e[2]==="pip"?e.slice(3):void 0;if(!a)return;if(a[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 f=!1;for(let m=1;m<a.length;m+=1){const w=a[m];if(!(w==="--disable-pip-version-check"||w==="-q"||w==="--quiet")){if(w==="-r"||w==="--requirement"){const b=a[++m];if(!b)throw new Error(`${w} requires a file path.`);const E=Kt(b,t);if(!n.analyzePath(E).exists)throw new Error(`pip: requirements file not found: ${E}`);d.push(...ns(new TextDecoder().decode(n.readFile(E)))),f=!0;continue}if(w.startsWith("-"))throw new Error(`browser pip does not support option: ${w}`);d.push(w)}}if(d.length===0&&!f)throw new Error("pip install requires at least one package.");const h=Kt("uv.lock",t);if(n.analyzePath(h).exists){const m=qo(new TextDecoder().decode(n.readFile(h)));if(m.size>0){const w=d.map(b=>Wo(b,m));return nt(w),{requirements:w,lockfile:{file:"uv.lock",pins:m.size}}}}return nt(d),{requirements:d}}async function es(n,e){nt(e),Ln({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 ts(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
|
+
`),t=JSON.parse(String(e));if(!Array.isArray(t)||t.some(s=>typeof s!="string"))throw new Error("micropip returned an invalid package inventory.");return nt(t),t}function Ho(n){return n.analyzePath(Ce).exists?ns(new TextDecoder().decode(n.readFile(Ce))):[]}function rs(n,e){nt(e),n.mkdirTree(Ce.slice(0,Ce.lastIndexOf("/"))),n.writeFile(Ce,new TextEncoder().encode(`${e.join(`
|
|
14
|
+
`)}
|
|
15
|
+
`))}function ns(n){const e=n.split(/\r?\n/u).map(t=>t.replace(/\s+#.*$/u,"").trim()).filter(Boolean);return nt(e),e}function nt(n){if(n.length>Pn)throw new Error(`Python package limit is ${Pn}.`);for(const e of n){if(!e||e.length>zo||/[\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 Go=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 Yo{pyodide;port;commit;acknowledgements=new Map;nextRequestId=1;requestQueue=Promise.resolve();constructor(e,t,s){this.pyodide=e,this.port=t,this.commit=s,e.globals.set("__browser_runtime_asgi_websocket_callback",a=>{const d=JSON.parse(String(a));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."})}),t.onmessage=a=>{const d=a.data;if(d.type==="ack"){const f=this.acknowledgements.get(d.requestId);if(!f)return;this.acknowledgements.delete(d.requestId),f(d.result);return}this.requestQueue=this.requestQueue.then(()=>d.type==="http-request"?this.handleRequest(d):this.handleWebSocket(d))},t.start()}listenStatic(e,t){return this.listen({type:"listen",requestId:0,port:e,server:"static",root:t})}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 t=this.nextRequestId++;return new Promise(s=>{const a=setTimeout(()=>{this.acknowledgements.delete(t),s(-110)},5e3);this.acknowledgements.set(t,d=>{clearTimeout(a),s(d)}),this.port.postMessage({...e,requestId:t})})}async handleRequest(e){const t=e.application==="asgi"&&e.streaming===!0;try{const s=JSON.stringify({method:e.method,url:e.url,headers:e.headers,bodyBase64:e.bodyBase64}),a=e.application==="asgi"?"__browser_runtime_handle_asgi":"__browser_runtime_handle_wsgi";t&&this.pyodide.globals.set("__browser_runtime_asgi_stream_callback",m=>{const w=JSON.parse(String(m));w.type==="start"?this.port.postMessage({type:"http-stream-start",requestId:e.requestId,statusCode:w.statusCode??500,statusMessage:w.statusMessage??"",headers:w.headers??{}}):w.type==="chunk"&&this.port.postMessage({type:"http-stream-chunk",requestId:e.requestId,bodyBase64:w.bodyBase64??""})});const d=e.application==="asgi"?`await ${a}(${JSON.stringify(s)}, ${t?"True":"False"})`:`${a}(${JSON.stringify(s)})`,f=await this.pyodide.runPythonAsync(d);if(t){await this.commit(),this.port.postMessage({type:"http-stream-end",requestId:e.requestId});return}const h=JSON.parse(String(f));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{t&&this.pyodide.globals.set("__browser_runtime_asgi_stream_callback",()=>{})}}async handleWebSocket(e){const t=JSON.stringify(e);try{e.type==="websocket-open"?await this.pyodide.runPythonAsync(`await __browser_runtime_open_asgi_websocket(${JSON.stringify(t)})`):await this.pyodide.runPythonAsync(`await __browser_runtime_asgi_websocket_event(${JSON.stringify(t)})`)}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 Vo(n,e,t,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(t)}
|
|
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(t[0]??"<string>")}, "exec"), globals(), globals())
|
|
338
|
+
`}const xn=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
|
+
`,An=16*1024*1024,Ko=3e4,Qo=5*6e4;class Xo{port;applyChanges;enabled;nextRequestId=1;constructor(e,t,s,a=!0){this.port=t,this.applyChanges=s,this.enabled=a,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 t=JSON.parse(e),s=new SharedArrayBuffer(2*Int32Array.BYTES_PER_ELEMENT),a=new SharedArrayBuffer(An),d=new Int32Array(s),f=this.nextRequestId++;if(this.port.postMessage({type:"process-run",requestId:f,...t,control:s,response:a}),Atomics.wait(d,0,0,Ko)==="timed-out"||Atomics.load(d,0)!==1)throw this.port.postMessage({type:"process-cancel",requestId:f}),new Error("Python subprocess timed out after 30 seconds.");const m=Atomics.load(d,1);if(!Number.isSafeInteger(m)||m<0||m>a.byteLength)throw new Error("Invalid Python subprocess response.");const w=new Uint8Array(m);w.set(new Uint8Array(a,0,m));const b=JSON.parse(new TextDecoder().decode(w));if(b.error)throw new Error(b.error);if(!b.result||!b.patch)throw new Error("Incomplete Python subprocess response.");return this.applyChanges(b.patch),JSON.stringify(b.result)}exchange(e){this.assertEnabled();const t=JSON.parse(e),s=new SharedArrayBuffer(2*Int32Array.BYTES_PER_ELEMENT),a=new SharedArrayBuffer(An),d=new Int32Array(s);if(this.port.postMessage({...t,requestId:this.nextRequestId++,control:s,response:a}),Atomics.wait(d,0,0,Qo)==="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>a.byteLength)throw new Error("Invalid Python Popen response.");const m=new Uint8Array(h);m.set(new Uint8Array(a,0,h));const w=JSON.parse(new TextDecoder().decode(m));if(w.patch&&this.applyChanges(w.patch),w.error)throw new Error(w.error);return JSON.stringify(w)}assertEnabled(){if(!this.enabled)throw new Error("Python subprocesses require a same-origin shared-memory worker.")}}const Zo=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
|
+
`,vn=-4,_r=3;class Qt{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 t=performance.now();try{return this.requestNow(e)}finally{Qt.waited.calls+=1,Qt.waited.ms+=performance.now()-t}}requestNow(e){if(Atomics.load(this.control,_r))return{result:vn};const t=this.encoder.encode(JSON.stringify(e));if(t.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,_r),this.payload.set(t),Atomics.store(this.control,1,t.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,_r))return{result:vn};const f=Atomics.load(this.control,0);f!==s+1&&Atomics.wait(this.control,0,f)}const a=Atomics.load(this.control,2);if(a<1||a>this.payload.byteLength)return{result:-5};const d=JSON.parse(this.decoder.decode(this.payload.slice(0,a)));return!d||!Number.isSafeInteger(d.result)?{result:-5}:d}finally{Atomics.store(this.control,0,0)}}}var Ae;(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"})(Ae||(Ae={}));const jt=512*1024,In=256*1024*1024,On=5,ei=new TextEncoder,ti=new TextDecoder("utf-8",{fatal:!0});class ri{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 t=this.call(Ae.Inspect,{path:e});if(!t.exists)return;const s=xr(t.length,0,In),a=new Uint8Array(s);for(let d=0;d<s;d+=jt){const f=Math.min(jt,s-d),h=this.call(Ae.Read,{path:e,offset:d,length:f}),m=Hn(h.content);if(m.byteLength!==f)throw new Error("Invalid coherent file response.");a.set(m,d)}return{bytes:a,...t.mode===void 0?{}:{mode:t.mode},...t.mtimeMs===void 0?{}:{mtimeMs:t.mtimeMs},parents:ni(e,t.parents)}}push(e,t){if(!t){this.call(Ae.Remove,{path:e});return}if(t.bytes.byteLength>In)throw new Error("Coherent file exceeds 256 MiB.");this.call(Ae.WriteStart,{path:e,length:t.bytes.byteLength,...t.mode===void 0?{}:{mode:t.mode},...t.mtimeMs===void 0?{}:{mtimeMs:t.mtimeMs},...t.parents===void 0?{}:{parents:t.parents}});for(let s=0;s<t.bytes.byteLength;s+=jt){const a=t.bytes.subarray(s,s+jt);this.call(Ae.WriteChunk,{offset:s,content:yo(a)})}this.call(Ae.WriteFinish)}call(e,t={}){const s=()=>{if(Atomics.load(this.control,On))throw Object.assign(new Error("Browser file coherence was cancelled."),{errno:125})};s();const a=ei.encode(JSON.stringify(t));if(a.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,On),this.payload.set(a),Atomics.store(this.control,1,e),Atomics.store(this.control,3,a.byteLength),Atomics.store(this.control,0,d);try{for(this.channel.port.postMessage(d);Atomics.load(this.control,0)!==d+1;){s();const w=Atomics.load(this.control,0);w!==d+1&&Atomics.wait(this.control,0,w)}const f=Atomics.load(this.control,2),h=xr(Atomics.load(this.control,4),0,this.payload.byteLength),m=h===0?void 0:JSON.parse(ti.decode(this.payload.slice(0,h)));if(f<0)throw Object.assign(new Error(`Browser file coherence failed with ${f}.`),{errno:-f});return m}finally{Atomics.store(this.control,0,0)}}}function Nn(n){const e=n.replace(/-(?:journal|shm|wal)$/u,"");return[e,`${e}-journal`,`${e}-wal`,`${e}-shm`]}function ni(n,e){if(e===void 0)return[];const t=new Set(si(n));if(!Array.isArray(e)||e.length>t.size)throw ze("Invalid coherent file parents.");return e.map(s=>{if(typeof s!="object"||s===null)throw ze("Invalid coherent file parent.");const a=s,d=ss(a.path);if(!t.delete(d))throw ze("Coherent metadata must name distinct ancestors of its file.");return{path:d,...oi(a)}})}function si(n){const e=[];for(const t of ss(n).split("/"))!t||t==="."||(t===".."?e.pop():e.push(t));return e.slice(0,-1).map((t,s)=>`/${e.slice(0,s+1).join("/")}`)}function oi(n){const e=n.mode===void 0?void 0:xr(n.mode,0,65535),t=n.mtimeMs===void 0?void 0:ai(n.mtimeMs);return{...e===void 0?{}:{mode:e},...t===void 0?{}:{mtimeMs:t}}}function ss(n){const e=ii(n);if(!e.startsWith("/")||e.length>4096||e.includes("\0"))throw ze("Invalid coherent file path.");return e}function ii(n){if(typeof n!="string")throw ze("Expected a string.");return n}function xr(n,e,t){if(!Number.isSafeInteger(n)||n<e||n>t)throw ze("Expected a bounded integer.");return n}function ai(n){if(typeof n!="number"||!Number.isFinite(n))throw ze("Expected a finite number.");return n}function ze(n){return Object.assign(new Error(n),{errno:22})}class ci{filesystem;locks;coherence;counts=new Map;owner;constructor(e,t,s,a){this.filesystem=e,this.locks=t,this.coherence=s,this.owner=`${a}:sqlite`}install(e){return e.globals.set("_browser_runtime_sqlite_acquire",t=>this.acquire(t)),e.globals.set("_browser_runtime_sqlite_release",t=>this.release(t)),e.runPythonAsync(li)}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 t=this.counts.get(e)??0;if(t>0){this.counts.set(e,t+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 a of Nn(e))this.writeLocal(a,this.coherence.pull(a));this.counts.set(e,1)}catch(a){throw this.locks.request({operation:"unlock",owner:this.owner,namespace:"posix",path:e,range:{start:0}}),a}}release(e){const t=this.counts.get(e)??0;if(t>1){this.counts.set(e,t-1);return}if(t===0)return;for(const a of Nn(e))this.coherence.push(a,this.readLocal(a));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 t=this.filesystem.stat(e);if((t.mode&61440)===16384)return;const s=typeof t.mtime=="number"?t.mtime:Number(t.mtime);return{bytes:this.filesystem.readFile(e),mode:t.mode&4095,...typeof s=="number"&&Number.isFinite(s)?{mtimeMs:s}:{}}}writeLocal(e,t){if(!t){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,t.bytes),t.mode!==void 0&&this.filesystem.chmod(e,t.mode),t.mtimeMs!==void 0&&this.filesystem.utime(e,t.mtimeMs,t.mtimeMs)}}const li=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
|
+
`,os=globalThis;let di=1;const Ar=new Map;let is=!1,Tn=!1,vr,wt,as,ht;function Xt(n){const e=So(ht??wt??{files:[]},n);return ht=n,e}function fi(n,e){const t=ht??wt??{files:[]};Lo(n.FS,e,t),ht=ko(t,e)}let tt=n=>Kn(n.FS,wt??{files:[]}),gr,ui=1;const Ir=new Map;Ei();os.onmessage=n=>{const e=n.data;if(e.type==="run"){pi(e);return}if(e.type==="prepare"){Vn(e.runtimeIndexUrl,e.runtimeSnapshot).catch(()=>{});return}if(e.type==="shutdown"){gi();return}if(e.type==="network-response"||e.type==="network-error"){const s=Ir.get(e.requestId);if(!s)return;Ir.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 t=Ar.get(e.commitId);t&&(Ar.delete(e.commitId),e.error?t.reject(new Error(e.error)):t.resolve())};async function pi(n){let e,t;wt=n.filesystem,ht=n.filesystem;try{if(e=await Vn(n.runtimeIndexUrl,n.runtimeSnapshot),e.setStdout({batched:S=>ie({type:"stdout",chunk:`${S}
|
|
778
|
+
`})}),e.setStderr({batched:S=>ie({type:"stderr",chunk:`${S}
|
|
779
|
+
`})}),n.store){const S=await ho({navigator:os.navigator},n.store.projectId);if(!S)throw new Error("The project's store is not there to read.");gr=S;const T=Do(e.FS,S);if(!T)throw new Error("This Pyodide exposes no filesystem to mount the workspace over.");tt=g=>Co(g.FS,T,n.filesystem)}else $o(e.FS,n.filesystem),tt=S=>Kn(S.FS,n.filesystem);n.fileLocks&&n.fileCoherence&&(t=new ci(e.FS,new Qt(n.fileLocks.channel),new ri(n.fileCoherence),n.fileLocks.owner),await t.install(e)),as=()=>tt(e);const s=()=>_i(tt(e)),a=new Yo(e,n.serverPort,s);new Xo(e,n.serverPort,S=>fi(e,S),n.sharedMemoryChannels),await e.runPythonAsync(Zo),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
|
+
`),Mn(async()=>{t?.releaseAll(),await s(),qt(130,e)});const d=wi(n.argv,n.cwd);if(d){const S=await a.listenStatic(d.port,d.root);if(S<0)throw new Error(`python http.server could not listen on port ${d.port} (${S}).`);ie({type:"stdout",chunk:`Serving HTTP on 0.0.0.0 port ${d.port} (http://localhost:${d.port}/) ...
|
|
786
|
+
`}),await Wt();return}await Uo(e);const f=Jo(e.FS,n.argv,n.cwd);if(f){await jo(e,f),ie({type:"stdout",chunk:`Successfully installed ${f.requirements.join(" ")}
|
|
787
|
+
`}),t?.releaseAll(),qt(0,e);return}const h=yi(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(Go),await e.runPythonAsync("await __browser_runtime_start_asgi_lifespan()"),await s();const S=await a.listenAsgi(h.port);if(S<0)throw new Error(`Python ASGI app could not listen on port ${h.port} (${S}).`);ie({type:"stdout",chunk:`Serving Python ASGI app on http://localhost:${h.port}/ ...
|
|
801
|
+
`}),Mn(async()=>{await a.idle(),await e.runPythonAsync("await __browser_runtime_stop_asgi_websockets()"),await e.runPythonAsync("await __browser_runtime_stop_asgi_lifespan()"),t?.releaseAll(),await s(),qt(130,e)}),await Wt();return}const m=mi(n.argv,n.env);if(m){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(m.module)})
|
|
810
|
+
__browser_runtime_wsgi_app = __browser_runtime_wsgi_module
|
|
811
|
+
for __browser_runtime_wsgi_part in ${JSON.stringify(m.attribute.split("."))}:
|
|
812
|
+
__browser_runtime_wsgi_app = getattr(__browser_runtime_wsgi_app, __browser_runtime_wsgi_part)
|
|
813
|
+
__browser_runtime_wsgi_port = ${m.port}
|
|
814
|
+
`),await e.runPythonAsync(xn),await s();const S=await a.listenWsgi(m.port);if(S<0)throw new Error(`Python WSGI app could not listen on port ${m.port} (${S}).`);ie({type:"stdout",chunk:`Serving Python WSGI app on http://localhost:${m.port}/ ...
|
|
815
|
+
`}),await Wt();return}const{code:w,argv:b}=hi(e.FS,n.argv,n.cwd);await e.runPythonAsync(Vo(n.cwd,n.env,b,w));const E=Number(await e.runPythonAsync("int(globals().get('__browser_runtime_wsgi_port', 0))"));if(E>0){await e.runPythonAsync(xn),await s();const S=await a.listenWsgi(E);if(S<0)throw new Error(`Python WSGI app could not listen on port ${E} (${S}).`);ie({type:"stdout",chunk:`Serving Python WSGI app on http://localhost:${E}/ ...
|
|
816
|
+
`}),await Wt();return}t?.releaseAll(),qt(0,e)}catch(s){try{t?.releaseAll()}catch{}const a=eo(s),d=a?s.message:s instanceof Error?s.stack??s.message:String(s);let f={files:[],removed:[]};try{e&&(f=Xt(tt(e)))}catch{}ie({type:"result",exitCode:a?2:1,patch:f,error:d})}finally{gr?.close(),gr=void 0}}function hi(n,e,t){const s=je(e[0]??""),a=s==="python"||s==="python3"?e.slice(1):e;if(a[0]==="-c"&&a[1]!==void 0)return{code:a[1],argv:["-c",...a.slice(2)]};const d=a[0];if(!d||d.startsWith("-"))throw new Error("usage: python [-c command] | script.py [args...]");const f=Kt(d,t);if(!n.analyzePath(f).exists)throw new Error(`python: can't open file '${d}': No such file or directory`);return{code:new TextDecoder().decode(n.readFile(f)),argv:[d,...a.slice(1)]}}function wi(n,e){const t=je(n[0]??""),s=t==="python"||t==="python3"?n.slice(1):n;if(s[0]!=="-m"||s[1]!=="http.server")return;let a=8e3,d=e;for(let f=2;f<s.length;f+=1)s[f]==="--directory"&&s[f+1]?d=Kt(s[++f],e):s[f].startsWith("-")||(a=Number(s[f]));if(!Number.isSafeInteger(a)||a<=0||a>65535)throw new Error("http.server port must be 1..65535.");return{port:a,root:d}}function mi(n,e){const t=je(n[0]??""),s=t==="python"||t==="python3"?n.slice(1):n,a=s[0]==="-m"&&s[1]==="gunicorn"?s.slice(2):je(s[0]??"")==="gunicorn"?s.slice(1):void 0;if(!a)return;let d=Number(e.PORT??"")||8e3,f;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 b=0;b<a.length;b+=1){const E=a[b];if(E==="--bind"||E==="-b"){const S=a[++b]??"",T=Number(S.slice(S.lastIndexOf(":")+1));Number.isSafeInteger(T)&&T>0&&(d=T)}else if(E.startsWith("--bind=")){const S=Number(E.slice(E.lastIndexOf(":")+1));Number.isSafeInteger(S)&&S>0&&(d=S)}else if(h.has(E))b+=1;else{if(E.startsWith("-"))continue;if(!f)f=E;else throw new Error(`browser gunicorn does not support argument: ${E}`)}}if(!f)throw new Error("gunicorn requires a WSGI target such as wsgi:app.");const[m,w="application"]=f.split(":",2);if(!m||!/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/u.test(m)||!/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/u.test(w))throw new Error("Invalid gunicorn WSGI target.");return{module:m,attribute:w,port:d}}function yi(n){const e=je(n[0]??""),t=e==="python"||e==="python3"?n.slice(1):n,s=t[0]==="-m"&&t[1]==="uvicorn"?t.slice(2):je(t[0]??"")==="uvicorn"?t.slice(1):void 0;if(!s)return;let a=8e3,d;for(let m=0;m<s.length;m+=1)if(s[m]==="--port"&&s[m+1])a=Number(s[++m]);else if(s[m]==="--host"&&s[m+1])m+=1;else{if(s[m]==="--no-access-log")continue;if(s[m].startsWith("-"))throw new Error(`browser uvicorn does not support option: ${s[m]}`);if(!d)d=s[m];else throw new Error(`browser uvicorn does not support argument: ${s[m]}`)}if(!d||!d.includes(":"))throw new Error("uvicorn requires an ASGI target such as main:app.");const[f,h]=d.split(":",2);if(!f||!h||!/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/u.test(f)||!/^[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*$/u.test(h))throw new Error("Invalid uvicorn ASGI target.");if(!Number.isSafeInteger(a)||a<=0||a>65535)throw new Error("uvicorn port must be 1..65535.");return{module:f,attribute:h,port:a}}function qt(n,e){ie({type:"result",exitCode:n,patch:Xt(tt(e))})}function _i(n){const e=di++;return new Promise((t,s)=>{Ar.set(e,{resolve:t,reject:s}),ie({type:"commit",commitId:e,patch:Xt(n)})})}function Mn(n){vr=n,cs()}function gi(){is=!0,cs()}function cs(){const n=wt;!is||Tn||!vr||!n||(Tn=!0,vr().catch(e=>ie({type:"result",exitCode:1,patch:Xt(bi(n)),error:e instanceof Error?e.stack??e.message:String(e)})))}function bi(n){try{return as?.()??n}catch{return n}}function Wt(){return new Promise(()=>{})}function Ei(){Object.defineProperty(globalThis,"fetch",{value:async(e,t)=>{const s=new Request(e,t),a=ui++,d=[];s.headers.forEach((m,w)=>d.push([w,m]));const f=s.method==="GET"||s.method==="HEAD"?new ArrayBuffer(0):await s.arrayBuffer(),h=new Promise((m,w)=>Ir.set(a,{resolve:m,reject:w}));return ie({type:"network-request",requestId:a,purpose:Oo(),url:s.url,method:s.method,headers:d,body:f},[f]),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 ie(n,e=[]){postMessage(n,e)}
|