@php-wasm/universal 0.6.0 → 0.6.2

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/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var Z=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var a=(e,t,r)=>(Z(e,t,"read from private field"),r?r.call(e):t.get(e)),c=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r)},u=(e,t,r,s)=>(Z(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var h=(e,t,r)=>(Z(e,t,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});if(typeof File>"u"){class e extends Blob{constructor(r,s,i){super(r);let n;i!=null&&i.lastModified&&(n=new Date),(!n||isNaN(n.getFullYear()))&&(n=new Date),this.lastModifiedDate=n,this.lastModified=n.getMilliseconds(),this.name=s||""}}global.File=e}function asPromise(e){return new Promise(function(t,r){e.onload=e.onerror=function(s){e.onload=e.onerror=null,s.type==="load"?t(e.result):r(new Error("Failed to read the blob/file"))}})}typeof Blob.prototype.arrayBuffer>"u"&&(Blob.prototype.arrayBuffer=function(){const t=new FileReader;return t.readAsArrayBuffer(this),asPromise(t)});typeof Blob.prototype.text>"u"&&(Blob.prototype.text=function(){const t=new FileReader;return t.readAsText(this),asPromise(t)});function isByobSupported(){const e=new Uint8Array([1,2,3,4]),r=new File([e],"test").stream();try{return r.getReader({mode:"byob"}),!0}catch{return!1}}(typeof Blob.prototype.stream>"u"||!isByobSupported())&&(Blob.prototype.stream=function(){let e=0;const t=this;return new ReadableStream({type:"bytes",autoAllocateChunkSize:512*1024,async pull(r){const s=r.byobRequest.view,n=await t.slice(e,e+s.byteLength).arrayBuffer(),o=new Uint8Array(n);new Uint8Array(s.buffer).set(o);const l=o.byteLength;r.byobRequest.respond(l),e+=l,e>=t.size&&r.close()}})});if(typeof CustomEvent>"u"){class e extends Event{constructor(r,s={}){super(r,s),this.detail=s.detail}initCustomEvent(){}}globalThis.CustomEvent=e}const kError=Symbol("error"),kMessage=Symbol("message");class ErrorEvent2 extends Event{constructor(t,r={}){super(t),this[kError]=r.error===void 0?null:r.error,this[kMessage]=r.message===void 0?"":r.message}get error(){return this[kError]}get message(){return this[kMessage]}}Object.defineProperty(ErrorEvent2.prototype,"error",{enumerable:!0});Object.defineProperty(ErrorEvent2.prototype,"message",{enumerable:!0});const ErrorEvent=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:ErrorEvent2;function isExitCodeZero(e){return e instanceof Error?"exitCode"in e&&(e==null?void 0:e.exitCode)===0||(e==null?void 0:e.name)==="ExitStatus"&&"status"in e&&e.status===0:!1}class UnhandledRejectionsTarget extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(t,r){++this.listenersCount,super.addEventListener(t,r)}removeEventListener(t,r){--this.listenersCount,super.removeEventListener(t,r)}hasListeners(){return this.listenersCount>0}}function improveWASMErrorReporting(e){e.asm={...e.asm};const t=new UnhandledRejectionsTarget;for(const r in e.asm)if(typeof e.asm[r]=="function"){const s=e.asm[r];e.asm[r]=function(...i){var n;try{return s(...i)}catch(o){if(!(o instanceof Error))throw o;const l=clarifyErrorMessage(o,(n=e.lastAsyncifyStackSource)==null?void 0:n.stack);if(e.lastAsyncifyStackSource&&(o.cause=e.lastAsyncifyStackSource),t.hasListeners()){t.dispatchEvent(new ErrorEvent("error",{error:o,message:l}));return}throw isExitCodeZero(o)||showCriticalErrorBox(l),o}}}return t}let functionsMaybeMissingFromAsyncify=[];function getFunctionsMaybeMissingFromAsyncify(){return functionsMaybeMissingFromAsyncify}function clarifyErrorMessage(e,t){if(e.message==="unreachable"){let r=UNREACHABLE_ERROR;t||(r+=`
1
+ "use strict";var K=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var a=(e,t,r)=>(K(e,t,"read from private field"),r?r.call(e):t.get(e)),c=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r)},u=(e,t,r,s)=>(K(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var p=(e,t,r)=>(K(e,t,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});if(typeof File>"u"){class e extends Blob{constructor(r,s,i){super(r);let n;i!=null&&i.lastModified&&(n=new Date),(!n||isNaN(n.getFullYear()))&&(n=new Date),this.lastModifiedDate=n,this.lastModified=n.getMilliseconds(),this.name=s||""}}global.File=e}function asPromise(e){return new Promise(function(t,r){e.onload=e.onerror=function(s){e.onload=e.onerror=null,s.type==="load"?t(e.result):r(new Error("Failed to read the blob/file"))}})}typeof Blob.prototype.arrayBuffer>"u"&&(Blob.prototype.arrayBuffer=function(){const t=new FileReader;return t.readAsArrayBuffer(this),asPromise(t)});typeof Blob.prototype.text>"u"&&(Blob.prototype.text=function(){const t=new FileReader;return t.readAsText(this),asPromise(t)});function isByobSupported(){const e=new Uint8Array([1,2,3,4]),r=new File([e],"test").stream();try{return r.getReader({mode:"byob"}),!0}catch{return!1}}(typeof Blob.prototype.stream>"u"||!isByobSupported())&&(Blob.prototype.stream=function(){let e=0;const t=this;return new ReadableStream({type:"bytes",autoAllocateChunkSize:512*1024,async pull(r){const s=r.byobRequest.view,n=await t.slice(e,e+s.byteLength).arrayBuffer(),o=new Uint8Array(n);new Uint8Array(s.buffer).set(o);const l=o.byteLength;r.byobRequest.respond(l),e+=l,e>=t.size&&r.close()}})});if(typeof CustomEvent>"u"){class e extends Event{constructor(r,s={}){super(r,s),this.detail=s.detail}initCustomEvent(){}}globalThis.CustomEvent=e}const kError=Symbol("error"),kMessage=Symbol("message");class ErrorEvent2 extends Event{constructor(t,r={}){super(t),this[kError]=r.error===void 0?null:r.error,this[kMessage]=r.message===void 0?"":r.message}get error(){return this[kError]}get message(){return this[kMessage]}}Object.defineProperty(ErrorEvent2.prototype,"error",{enumerable:!0});Object.defineProperty(ErrorEvent2.prototype,"message",{enumerable:!0});const ErrorEvent=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:ErrorEvent2;function isExitCodeZero(e){return e instanceof Error?"exitCode"in e&&(e==null?void 0:e.exitCode)===0||(e==null?void 0:e.name)==="ExitStatus"&&"status"in e&&e.status===0:!1}class UnhandledRejectionsTarget extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(t,r){++this.listenersCount,super.addEventListener(t,r)}removeEventListener(t,r){--this.listenersCount,super.removeEventListener(t,r)}hasListeners(){return this.listenersCount>0}}function improveWASMErrorReporting(e){e.asm={...e.asm};const t=new UnhandledRejectionsTarget;for(const r in e.asm)if(typeof e.asm[r]=="function"){const s=e.asm[r];e.asm[r]=function(...i){var n;try{return s(...i)}catch(o){if(!(o instanceof Error))throw o;const l=clarifyErrorMessage(o,(n=e.lastAsyncifyStackSource)==null?void 0:n.stack);if(e.lastAsyncifyStackSource&&(o.cause=e.lastAsyncifyStackSource),t.hasListeners()){t.dispatchEvent(new ErrorEvent("error",{error:o,message:l}));return}throw isExitCodeZero(o)||showCriticalErrorBox(l),o}}}return t}let functionsMaybeMissingFromAsyncify=[];function getFunctionsMaybeMissingFromAsyncify(){return functionsMaybeMissingFromAsyncify}function clarifyErrorMessage(e,t){if(e.message==="unreachable"){let r=UNREACHABLE_ERROR;t||(r+=`
2
2
 
3
3
  This stack trace is lacking. For a better one initialize
4
4
  the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
@@ -32,9 +32,9 @@ CLI option:
32
32
  ${eol}
33
33
  ${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
34
34
  `))console.log(`${eol} ${t} `);console.log(`${reset}`)}}function extractPHPFunctionsFromStack(e){try{const t=e.split(`
35
- `).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(t))}catch{return[]}}class Semaphore{constructor({concurrency:t}){this._running=0,this.concurrency=t,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(t=>this.queue.push(t));else{this._running++;let t=!1;return()=>{t||(t=!0,this._running--,this.queue.length>0&&this.queue.shift()())}}}async run(t){const r=await this.acquire();try{return await t()}finally{r()}}}function joinPaths(...e){let t=e.join("/");const r=t[0]==="/",s=t.substring(t.length-1)==="/";return t=normalizePath(t),!t&&!r&&(t="."),t&&s&&(t+="/"),t}function dirname(e){if(e==="/")return"/";e=normalizePath(e);const t=e.lastIndexOf("/");return t===-1?"":t===0?"/":e.substr(0,t)}function normalizePath(e){const t=e[0]==="/";return e=normalizePathsArray(e.split("/").filter(r=>!!r),!t).join("/"),(t?"/":"")+e.replace(/\/$/,"")}function normalizePathsArray(e,t){let r=0;for(let s=e.length-1;s>=0;s--){const i=e[s];i==="."?e.splice(s,1):i===".."?(e.splice(s,1),r++):r&&(e.splice(s,1),r--)}if(t)for(;r;r--)e.unshift("..");return e}function createSpawnHandler(e){return function(t){const r=new ChildProcess,s=new ProcessApi(r);return setTimeout(async()=>{await e(t,s),r.emit("spawn",!0)}),r}}class EventEmitter{constructor(){this.listeners={}}emit(t,r){this.listeners[t]&&this.listeners[t].forEach(function(s){s(r)})}on(t,r){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(r)}}class ProcessApi extends EventEmitter{constructor(t){super(),this.childProcess=t,this.exited=!1,this.stdinData=[],t.on("stdin",r=>{this.stdinData?this.stdinData.push(r.slice()):this.emit("stdin",r)})}stdout(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stdout.emit("data",t)}stderr(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stderr.emit("data",t)}exit(t){this.exited||(this.exited=!0,this.childProcess.emit("exit",t))}flushStdin(){if(this.stdinData)for(let t=0;t<this.stdinData.length;t++)this.emit("stdin",this.stdinData[t]);this.stdinData=null}}let lastPid=9743;class ChildProcess extends EventEmitter{constructor(t=lastPid++){super(),this.pid=t,this.stdout=new EventEmitter,this.stderr=new EventEmitter;const r=this;this.stdin={write:s=>{r.emit("stdin",s)}}}}function concatUint8Array(...e){const t=new Uint8Array(e.reduce((s,i)=>s+i.length,0));let r=0;for(const s of e)t.set(s,r),r+=s.length;return t}function concatBytes(e){if(e===void 0){let t=new Uint8Array;return new TransformStream({transform(r){t=concatUint8Array(t,r)},flush(r){r.enqueue(t)}})}else{const t=new ArrayBuffer(e||0);let r=0;return new TransformStream({transform(s){new Uint8Array(t).set(s,r),r+=s.byteLength},flush(s){s.enqueue(new Uint8Array(t))}})}}function limitBytes(e,t){if(t===0)return new ReadableStream({start(i){i.close()}});const r=e.getReader({mode:"byob"});let s=0;return new ReadableStream({async pull(i){const{value:n,done:o}=await r.read(new Uint8Array(t-s));if(o){r.releaseLock(),i.close();return}s+=n.length,i.enqueue(n),s>=t&&(r.releaseLock(),i.close())},cancel(){r.cancel()}})}async function collectBytes(e,t){return t!==void 0&&(e=limitBytes(e,t)),await e.pipeThrough(concatBytes(t)).getReader().read().then(({value:r})=>r)}class StreamedFile extends File{constructor(t,r,s){super([],r,{type:s}),this.readableStream=t}slice(){throw new Error("slice() is not possible on a StreamedFile")}stream(){return this.readableStream}async text(){return new TextDecoder().decode(await this.arrayBuffer())}async arrayBuffer(){return await collectBytes(this.stream())}}ReadableStream.prototype[Symbol.asyncIterator]||(ReadableStream.prototype[Symbol.asyncIterator]=async function*(){const e=this.getReader();try{for(;;){const{done:t,value:r}=await e.read();if(t)return;yield r}}finally{e.releaseLock()}},ReadableStream.prototype.iterate=ReadableStream.prototype[Symbol.asyncIterator]);function streamReadFileFromPHP(e,t){return new ReadableStream({async pull(r){const s=await e.readFileAsBuffer(t);r.enqueue(s),r.close()}})}async function*iteratePhpFiles(e,t,{relativePaths:r=!0,pathPrefix:s,exceptPaths:i=[]}={}){t=normalizePath(t);const n=[t];for(;n.length;){const o=n.pop();if(!o)return;const l=await e.listFiles(o);for(const p of l){const d=`${o}/${p}`;if(i.includes(d.substring(t.length+1)))continue;await e.isDir(d)?n.push(d):yield new StreamedFile(streamReadFileFromPHP(e,d),r?joinPaths(s||"",d.substring(t.length+1)):d)}}}function writeFilesStreamToPhp(e,t){return new WritableStream({async write(r){const s=joinPaths(t,r.name);r.type==="directory"?await e.mkdir(s):(await e.mkdir(dirname(s)),await e.writeFile(s,new Uint8Array(await r.arrayBuffer())))}})}class PHPResponse{constructor(t,r,s,i="",n=0){this.httpStatusCode=t,this.headers=r,this.bytes=s,this.exitCode=n,this.errors=i}static fromRawData(t){return new PHPResponse(t.httpStatusCode,t.headers,t.bytes,t.errors,t.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const SupportedPHPVersions=["8.3","8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0"],LatestSupportedPHPVersion=SupportedPHPVersions[0],SupportedPHPVersionsList=SupportedPHPVersions,SupportedPHPExtensionsList=["iconv","mbstring","xml-bundle","gd"],SupportedPHPExtensionBundles={"kitchen-sink":SupportedPHPExtensionsList};var v,b;class PHPBrowser{constructor(t,r={}){c(this,v,void 0);c(this,b,void 0);this.requestHandler=t,u(this,v,{}),u(this,b,{handleRedirects:!1,maxRedirects:4,...r})}async request(t,r=0){const s=await this.requestHandler.request({...t,headers:{...t.headers,cookie:this.serializeCookies()}});if(s.headers["set-cookie"]&&this.setCookies(s.headers["set-cookie"]),a(this,b).handleRedirects&&s.headers.location&&r<a(this,b).maxRedirects){const i=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:i.toString(),method:"GET",headers:{}},r+1)}return s}pathToInternalUrl(t){return this.requestHandler.pathToInternalUrl(t)}internalUrlToPath(t){return this.requestHandler.internalUrlToPath(t)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}setCookies(t){for(const r of t)try{if(!r.includes("="))continue;const s=r.indexOf("="),i=r.substring(0,s),n=r.substring(s+1).split(";")[0];a(this,v)[i]=n}catch(s){console.error(s)}}serializeCookies(){const t=[];for(const r in a(this,v))t.push(`${r}=${a(this,v)[r]}`);return t.join("; ")}}v=new WeakMap,b=new WeakMap;const DEFAULT_BASE_URL="http://example.com";function toRelativeUrl(e){return e.toString().substring(e.origin.length)}function removePathPrefix(e,t){return!t||!e.startsWith(t)?e:e.substring(t.length)}function ensurePathPrefix(e,t){return!t||e.startsWith(t)?e:t+e}var w,x,A,R,H,_,F,T,L,K,U,Q,N,X;class PHPRequestHandler{constructor(t,r={}){c(this,L);c(this,U);c(this,N);c(this,w,void 0);c(this,x,void 0);c(this,A,void 0);c(this,R,void 0);c(this,H,void 0);c(this,_,void 0);c(this,F,void 0);c(this,T,void 0);u(this,T,new Semaphore({concurrency:1}));const{documentRoot:s="/www/",absoluteUrl:i=typeof location=="object"?location==null?void 0:location.href:""}=r;this.php=t,u(this,w,s);const n=new URL(i);u(this,A,n.hostname),u(this,R,n.port?Number(n.port):n.protocol==="https:"?443:80),u(this,x,(n.protocol||"").replace(":",""));const o=a(this,R)!==443&&a(this,R)!==80;u(this,H,[a(this,A),o?`:${a(this,R)}`:""].join("")),u(this,_,n.pathname.replace(/\/+$/,"")),u(this,F,[`${a(this,x)}://`,a(this,H),a(this,_)].join(""))}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(a(this,_))&&(r.pathname=r.pathname.slice(a(this,_).length)),toRelativeUrl(r)}get isRequestRunning(){return a(this,T).running>0}get absoluteUrl(){return a(this,F)}get documentRoot(){return a(this,w)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url,r?void 0:DEFAULT_BASE_URL),i=removePathPrefix(s.pathname,a(this,_)),n=`${a(this,w)}${i}`;return seemsLikeAPHPRequestHandlerPath(n)?await h(this,U,Q).call(this,t,s):h(this,L,K).call(this,n)}}w=new WeakMap,x=new WeakMap,A=new WeakMap,R=new WeakMap,H=new WeakMap,_=new WeakMap,F=new WeakMap,T=new WeakMap,L=new WeakSet,K=function(t){if(!this.php.fileExists(t))return new PHPResponse(404,{"x-file-type":["static"]},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new PHPResponse(200,{"content-length":[`${r.byteLength}`],"content-type":[inferMimeType(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)},U=new WeakSet,Q=async function(t,r){var i,n;const s=await a(this,T).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",a(this,w)),this.php.addServerGlobalEntry("HTTPS",a(this,F).startsWith("https://")?"on":"");let o="GET";const l={host:a(this,H),...normalizeHeaders(t.headers||{})},p=[];if(t.files&&Object.keys(t.files).length){o="POST";for(const P in t.files){const I=t.files[P];p.push({key:P,name:I.name,type:I.type,data:new Uint8Array(await I.arrayBuffer())})}(i=l["content-type"])!=null&&i.startsWith("multipart/form-data")&&(t.formData=parseMultipartFormDataString(t.body||""),l["content-type"]="application/x-www-form-urlencoded",delete t.body)}let d;t.formData!==void 0?(o="POST",l["content-type"]=l["content-type"]||"application/x-www-form-urlencoded",d=new URLSearchParams(t.formData).toString()):d=t.body;let f;try{let P=r.pathname;if((n=t.headers)!=null&&n["x-rewrite-url"])try{P=new URL(t.headers["x-rewrite-url"]).pathname}catch{}f=h(this,N,X).call(this,P)}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),a(this,_)),protocol:a(this,x),method:t.method||o,body:d,fileInfos:p,scriptPath:f,headers:l})}finally{s()}},N=new WeakSet,X=function(t){let r=removePathPrefix(t,a(this,_));r.includes(".php")?r=r.split(".php")[0]+".php":(r.endsWith("/")||(r+="/"),r.endsWith("index.php")||(r+="index.php"));const s=`${a(this,w)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};function parseMultipartFormDataString(e){const t={},r=e.match(/--(.*)\r\n/);if(!r)return t;const s=r[1],i=e.split(`--${s}`);return i.shift(),i.pop(),i.forEach(n=>{const o=n.indexOf(`\r
35
+ `).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(t))}catch{return[]}}class Semaphore{constructor({concurrency:t}){this._running=0,this.concurrency=t,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(t=>this.queue.push(t));else{this._running++;let t=!1;return()=>{t||(t=!0,this._running--,this.queue.length>0&&this.queue.shift()())}}}async run(t){const r=await this.acquire();try{return await t()}finally{r()}}}function joinPaths(...e){let t=e.join("/");const r=t[0]==="/",s=t.substring(t.length-1)==="/";return t=normalizePath(t),!t&&!r&&(t="."),t&&s&&(t+="/"),t}function dirname(e){if(e==="/")return"/";e=normalizePath(e);const t=e.lastIndexOf("/");return t===-1?"":t===0?"/":e.substr(0,t)}function normalizePath(e){const t=e[0]==="/";return e=normalizePathsArray(e.split("/").filter(r=>!!r),!t).join("/"),(t?"/":"")+e.replace(/\/$/,"")}function normalizePathsArray(e,t){let r=0;for(let s=e.length-1;s>=0;s--){const i=e[s];i==="."?e.splice(s,1):i===".."?(e.splice(s,1),r++):r&&(e.splice(s,1),r--)}if(t)for(;r;r--)e.unshift("..");return e}function createSpawnHandler(e){return function(t){const r=new ChildProcess,s=new ProcessApi(r);return setTimeout(async()=>{await e(t,s),r.emit("spawn",!0)}),r}}class EventEmitter{constructor(){this.listeners={}}emit(t,r){this.listeners[t]&&this.listeners[t].forEach(function(s){s(r)})}on(t,r){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(r)}}class ProcessApi extends EventEmitter{constructor(t){super(),this.childProcess=t,this.exited=!1,this.stdinData=[],t.on("stdin",r=>{this.stdinData?this.stdinData.push(r.slice()):this.emit("stdin",r)})}stdout(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stdout.emit("data",t)}stderr(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stderr.emit("data",t)}exit(t){this.exited||(this.exited=!0,this.childProcess.emit("exit",t))}flushStdin(){if(this.stdinData)for(let t=0;t<this.stdinData.length;t++)this.emit("stdin",this.stdinData[t]);this.stdinData=null}}let lastPid=9743;class ChildProcess extends EventEmitter{constructor(t=lastPid++){super(),this.pid=t,this.stdout=new EventEmitter,this.stderr=new EventEmitter;const r=this;this.stdin={write:s=>{r.emit("stdin",s)}}}}function concatUint8Array(...e){const t=new Uint8Array(e.reduce((s,i)=>s+i.length,0));let r=0;for(const s of e)t.set(s,r),r+=s.length;return t}function concatBytes(e){if(e===void 0){let t=new Uint8Array;return new TransformStream({transform(r){t=concatUint8Array(t,r)},flush(r){r.enqueue(t)}})}else{const t=new ArrayBuffer(e||0);let r=0;return new TransformStream({transform(s){new Uint8Array(t).set(s,r),r+=s.byteLength},flush(s){s.enqueue(new Uint8Array(t))}})}}function limitBytes(e,t){if(t===0)return new ReadableStream({start(i){i.close()}});const r=e.getReader({mode:"byob"});let s=0;return new ReadableStream({async pull(i){const{value:n,done:o}=await r.read(new Uint8Array(t-s));if(o){r.releaseLock(),i.close();return}s+=n.length,i.enqueue(n),s>=t&&(r.releaseLock(),i.close())},cancel(){r.cancel()}})}async function collectBytes(e,t){return t!==void 0&&(e=limitBytes(e,t)),await e.pipeThrough(concatBytes(t)).getReader().read().then(({value:r})=>r)}class StreamedFile extends File{constructor(t,r,s){super([],r,{type:s}),this.readableStream=t}slice(){throw new Error("slice() is not possible on a StreamedFile")}stream(){return this.readableStream}async text(){return new TextDecoder().decode(await this.arrayBuffer())}async arrayBuffer(){return await collectBytes(this.stream())}}ReadableStream.prototype[Symbol.asyncIterator]||(ReadableStream.prototype[Symbol.asyncIterator]=async function*(){const e=this.getReader();try{for(;;){const{done:t,value:r}=await e.read();if(t)return;yield r}}finally{e.releaseLock()}},ReadableStream.prototype.iterate=ReadableStream.prototype[Symbol.asyncIterator]);function streamReadFileFromPHP(e,t){return new ReadableStream({async pull(r){const s=await e.readFileAsBuffer(t);r.enqueue(s),r.close()}})}async function*iteratePhpFiles(e,t,{relativePaths:r=!0,pathPrefix:s,exceptPaths:i=[]}={}){t=normalizePath(t);const n=[t];for(;n.length;){const o=n.pop();if(!o)return;const l=await e.listFiles(o);for(const h of l){const d=`${o}/${h}`;if(i.includes(d.substring(t.length+1)))continue;await e.isDir(d)?n.push(d):yield new StreamedFile(streamReadFileFromPHP(e,d),r?joinPaths(s||"",d.substring(t.length+1)):d)}}}function writeFilesStreamToPhp(e,t){return new WritableStream({async write(r){const s=joinPaths(t,r.name);r.type==="directory"?await e.mkdir(s):(await e.mkdir(dirname(s)),await e.writeFile(s,new Uint8Array(await r.arrayBuffer())))}})}class PHPResponse{constructor(t,r,s,i="",n=0){this.httpStatusCode=t,this.headers=r,this.bytes=s,this.exitCode=n,this.errors=i}static fromRawData(t){return new PHPResponse(t.httpStatusCode,t.headers,t.bytes,t.errors,t.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const SupportedPHPVersions=["8.3","8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0"],LatestSupportedPHPVersion=SupportedPHPVersions[0],SupportedPHPVersionsList=SupportedPHPVersions,SupportedPHPExtensionsList=["iconv","mbstring","xml-bundle","gd"],SupportedPHPExtensionBundles={"kitchen-sink":SupportedPHPExtensionsList};var E,x;class PHPBrowser{constructor(t,r={}){c(this,E,void 0);c(this,x,void 0);this.requestHandler=t,u(this,E,{}),u(this,x,{handleRedirects:!1,maxRedirects:4,...r})}async request(t,r=0){const s=await this.requestHandler.request({...t,headers:{...t.headers,cookie:this.serializeCookies()}});if(s.headers["set-cookie"]&&this.setCookies(s.headers["set-cookie"]),a(this,x).handleRedirects&&s.headers.location&&r<a(this,x).maxRedirects){const i=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:i.toString(),method:"GET",headers:{}},r+1)}return s}pathToInternalUrl(t){return this.requestHandler.pathToInternalUrl(t)}internalUrlToPath(t){return this.requestHandler.internalUrlToPath(t)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}setCookies(t){for(const r of t)try{if(!r.includes("="))continue;const s=r.indexOf("="),i=r.substring(0,s),n=r.substring(s+1).split(";")[0];a(this,E)[i]=n}catch(s){console.error(s)}}serializeCookies(){const t=[];for(const r in a(this,E))t.push(`${r}=${a(this,E)[r]}`);return t.join("; ")}}E=new WeakMap,x=new WeakMap;const DEFAULT_BASE_URL="http://example.com";function toRelativeUrl(e){return e.toString().substring(e.origin.length)}function removePathPrefix(e,t){return!t||!e.startsWith(t)?e:e.substring(t.length)}function ensurePathPrefix(e,t){return!t||e.startsWith(t)?e:t+e}var P,H,A,v,F,m,T,R,U,Q,N,X,M,ee;class PHPRequestHandler{constructor(t,r={}){c(this,U);c(this,N);c(this,M);c(this,P,void 0);c(this,H,void 0);c(this,A,void 0);c(this,v,void 0);c(this,F,void 0);c(this,m,void 0);c(this,T,void 0);c(this,R,void 0);u(this,R,new Semaphore({concurrency:1}));const{documentRoot:s="/www/",absoluteUrl:i=typeof location=="object"?location==null?void 0:location.href:""}=r;this.php=t,u(this,P,s);const n=new URL(i);u(this,A,n.hostname),u(this,v,n.port?Number(n.port):n.protocol==="https:"?443:80),u(this,H,(n.protocol||"").replace(":",""));const o=a(this,v)!==443&&a(this,v)!==80;u(this,F,[a(this,A),o?`:${a(this,v)}`:""].join("")),u(this,m,n.pathname.replace(/\/+$/,"")),u(this,T,[`${a(this,H)}://`,a(this,F),a(this,m)].join(""))}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(a(this,m))&&(r.pathname=r.pathname.slice(a(this,m).length)),toRelativeUrl(r)}get isRequestRunning(){return a(this,R).running>0}get absoluteUrl(){return a(this,T)}get documentRoot(){return a(this,P)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url,r?void 0:DEFAULT_BASE_URL),i=removePathPrefix(s.pathname,a(this,m)),n=`${a(this,P)}${i}`;return seemsLikeAPHPRequestHandlerPath(n)?await p(this,N,X).call(this,t,s):p(this,U,Q).call(this,n)}}P=new WeakMap,H=new WeakMap,A=new WeakMap,v=new WeakMap,F=new WeakMap,m=new WeakMap,T=new WeakMap,R=new WeakMap,U=new WeakSet,Q=function(t){if(!this.php.fileExists(t))return new PHPResponse(404,{"x-file-type":["static"]},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new PHPResponse(200,{"content-length":[`${r.byteLength}`],"content-type":[inferMimeType(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)},N=new WeakSet,X=async function(t,r){var i,n,o;if(a(this,R).running>0&&((i=t.headers)==null?void 0:i["x-request-issuer"])==="php")return console.warn("Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."),new PHPResponse(502,{},new TextEncoder().encode("502 Bad Gateway"));const s=await a(this,R).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",a(this,P)),this.php.addServerGlobalEntry("HTTPS",a(this,T).startsWith("https://")?"on":"");let l="GET";const h={host:a(this,F),...normalizeHeaders(t.headers||{})},d=[];if(t.files&&Object.keys(t.files).length){l="POST";for(const b in t.files){const L=t.files[b];d.push({key:b,name:L.name,type:L.type,data:new Uint8Array(await L.arrayBuffer())})}(n=h["content-type"])!=null&&n.startsWith("multipart/form-data")&&(t.formData=parseMultipartFormDataString(t.body||""),h["content-type"]="application/x-www-form-urlencoded",delete t.body)}let f;t.formData!==void 0?(l="POST",h["content-type"]=h["content-type"]||"application/x-www-form-urlencoded",f=new URLSearchParams(t.formData).toString()):f=t.body;let I;try{let b=r.pathname;if((o=t.headers)!=null&&o["x-rewrite-url"])try{b=new URL(t.headers["x-rewrite-url"]).pathname}catch{}I=p(this,M,ee).call(this,b)}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),a(this,m)),protocol:a(this,H),method:t.method||l,body:f,fileInfos:d,scriptPath:I,headers:h})}finally{s()}},M=new WeakSet,ee=function(t){let r=removePathPrefix(t,a(this,m));r.includes(".php")?r=r.split(".php")[0]+".php":(r.endsWith("/")||(r+="/"),r.endsWith("index.php")||(r+="index.php"));const s=`${a(this,P)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};function parseMultipartFormDataString(e){const t={},r=e.match(/--(.*)\r\n/);if(!r)return t;const s=r[1],i=e.split(`--${s}`);return i.shift(),i.pop(),i.forEach(n=>{const o=n.indexOf(`\r
36
36
  \r
37
- `),l=n.substring(0,o).trim(),p=n.substring(o+4).trim(),d=l.match(/name="([^"]+)"/);if(d){const f=d[1];t[f]=p}}),t}function inferMimeType(e){switch(e.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}function seemsLikeAPHPRequestHandlerPath(e){return seemsLikeAPHPFile(e)||seemsLikeADirectoryRoot(e)}function seemsLikeAPHPFile(e){return e.endsWith(".php")||e.includes(".php/")}function seemsLikeADirectoryRoot(e){return!e.split("/").pop().includes(".")}const FileErrorCodes={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function getEmscriptenFsError(e){const t=typeof e=="object"?e==null?void 0:e.errno:null;if(t in FileErrorCodes)return FileErrorCodes[t]}function rethrowFileSystemError(e=""){return function(r,s,i){const n=i.value;i.value=function(...o){try{return n.apply(this,o)}catch(l){const p=typeof l=="object"?l==null?void 0:l.errno:null;if(p in FileErrorCodes){const d=FileErrorCodes[p],f=typeof o[0]=="string"?o[0]:null,P=f!==null?e.replaceAll("{path}",f):e;throw new Error(`${P}: ${d}`,{cause:l})}throw l}}}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(e,t={}){const[r,s,i]=makePromise(),n=e.init(currentJsRuntime,{onAbort(l){i(l),console.error(l)},ENV:{},locateFile:l=>l,...t,noInitialRun:!0,onRuntimeInitialized(){t.onRuntimeInitialized&&t.onRuntimeInitialized(),s()}});await r;const o=++lastRuntimeId;return n.id=o,n.originalExit=n._exit,n._exit=function(l){return loadedRuntimes.delete(o),n.originalExit(l)},n[RuntimeId]=o,loadedRuntimes.set(o,n),o}function getLoadedRuntime(e){return loadedRuntimes.get(e)}const currentJsRuntime=function(){var e;return typeof process<"u"&&((e=process.release)==null?void 0:e.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),makePromise=()=>{const e=[],t=new Promise((r,s)=>{e.push(r,s)});return e.unshift(t),e};var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__decorateClass=(e,t,r,s)=>{for(var i=s>1?void 0:s?__getOwnPropDesc(t,r):t,n=e.length-1,o;n>=0;n--)(o=e[n])&&(i=(s?o(t,r,i):o(i))||i);return s&&i&&__defProp(t,r,i),i};const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");var S,C,B,m,g,E,y,k,M,ee,O,te,D,re,q,se,$,ne,j,ie,z,oe,W,ae,G,le,V,ce,J,ue,Y,de;class BasePHP{constructor(e,t){c(this,M);c(this,O);c(this,D);c(this,q);c(this,$);c(this,j);c(this,z);c(this,W);c(this,G);c(this,V);c(this,J);c(this,Y);c(this,S,void 0);c(this,C,void 0);c(this,B,void 0);c(this,m,void 0);c(this,g,void 0);c(this,E,void 0);c(this,y,void 0);c(this,k,void 0);u(this,S,[]),u(this,m,!1),u(this,g,null),u(this,E,{}),u(this,y,new Map),u(this,k,[]),this.semaphore=new Semaphore({concurrency:1}),e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new PHPBrowser(new PHPRequestHandler(this,t)))}addEventListener(e,t){a(this,y).has(e)||a(this,y).set(e,new Set),a(this,y).get(e).add(t)}removeEventListener(e,t){var r;(r=a(this,y).get(e))==null||r.delete(t)}dispatchEvent(e){const t=a(this,y).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){a(this,k).push(e)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const t=getLoadedRuntime(e);if(!t)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=t,t.onMessage=async r=>{for(const s of a(this,k)){const i=await s(r);if(i)return i}return""},u(this,g,improveWASMErrorReporting(t)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(e){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[e])!==0)throw new Error("Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?");u(this,B,e)}setPhpIniPath(e){if(a(this,m))throw new Error("Cannot set PHP ini path after calling run().");u(this,C,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(a(this,m))throw new Error("Cannot set PHP ini entries after calling run().");a(this,S).push([e,t])}chdir(e){this[__private__dont__use].FS.chdir(e)}async request(e,t){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,t)}async run(e){const t=await this.semaphore.acquire();let r;try{a(this,m)||(h(this,M,ee).call(this),u(this,m,!0)),h(this,W,ae).call(this,e.scriptPath||""),h(this,D,re).call(this,e.relativeUri||""),h(this,$,ne).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),i=s.host||"example.com:443";if(h(this,q,se).call(this,i,e.protocol||"http"),h(this,j,ie).call(this,s),e.body&&(r=h(this,z,oe).call(this,e.body)),e.fileInfos)for(const o of e.fileInfos)h(this,V,ce).call(this,o);typeof e.code=="string"&&h(this,J,ue).call(this," ?>"+e.code),h(this,G,le).call(this);const n=await h(this,Y,de).call(this);if(e.throwOnError&&n.exitCode!==0){const o={stdout:n.text,stderr:n.errors};console.warn("PHP.run() output was:",o);const l=new Error(`PHP.run() failed with exit code ${n.exitCode} and the following output`);throw l.output=o,l}return n}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){a(this,E)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/tmp/consts.json")&&this.readFileAsText("/tmp/consts.json")||"{}")}catch{}this.writeFile("/tmp/consts.json",JSON.stringify({...r,[e]:t}))}mkdir(e){this[__private__dont__use].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[__private__dont__use].FS.readFile(e)}writeFile(e,t){this[__private__dont__use].FS.writeFile(e,t)}unlink(e){this[__private__dont__use].FS.unlink(e)}mv(e,t){try{this[__private__dont__use].FS.rename(e,t)}catch(r){const s=getEmscriptenFsError(r);throw s?new Error(`Could not move ${e} to ${t}: ${s}`,{cause:r}):r}}rmdir(e,t={recursive:!0}){t!=null&&t.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[__private__dont__use].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[__private__dont__use].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(i=>`${s}/${i}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[__private__dont__use].FS.isDir(this[__private__dont__use].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[__private__dont__use].FS.lookupPath(e),!0}catch{return!1}}hotSwapPHPRuntime(e){const t=this[__private__dont__use].FS;try{this.exit()}catch{}if(this.initializeRuntime(e),a(this,C)&&this.setPhpIniPath(a(this,C)),a(this,B)&&this.setSapiName(a(this,B)),this.requestHandler){const r=this.documentRoot;recreateMemFS(this[__private__dont__use].FS,t,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}u(this,m,!1),u(this,g,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,C=new WeakMap,B=new WeakMap,m=new WeakMap,g=new WeakMap,E=new WeakMap,y=new WeakMap,k=new WeakMap,M=new WeakSet,ee=function(){if(this.setPhpIniEntry("auto_prepend_file","/tmp/consts.php"),this.fileExists("/tmp/consts.php")||this.writeFile("/tmp/consts.php",`<?php
37
+ `),l=n.substring(0,o).trim(),h=n.substring(o+4).trim(),d=l.match(/name="([^"]+)"/);if(d){const f=d[1];t[f]=h}}),t}function inferMimeType(e){switch(e.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}function seemsLikeAPHPRequestHandlerPath(e){return seemsLikeAPHPFile(e)||seemsLikeADirectoryRoot(e)}function seemsLikeAPHPFile(e){return e.endsWith(".php")||e.includes(".php/")}function seemsLikeADirectoryRoot(e){return!e.split("/").pop().includes(".")}const FileErrorCodes={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function getEmscriptenFsError(e){const t=typeof e=="object"?e==null?void 0:e.errno:null;if(t in FileErrorCodes)return FileErrorCodes[t]}function rethrowFileSystemError(e=""){return function(r,s,i){const n=i.value;i.value=function(...o){try{return n.apply(this,o)}catch(l){const h=typeof l=="object"?l==null?void 0:l.errno:null;if(h in FileErrorCodes){const d=FileErrorCodes[h],f=typeof o[0]=="string"?o[0]:null,I=f!==null?e.replaceAll("{path}",f):e;throw new Error(`${I}: ${d}`,{cause:l})}throw l}}}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(e,t={}){const[r,s,i]=makePromise(),n=e.init(currentJsRuntime,{onAbort(l){i(l),console.error(l)},ENV:{},locateFile:l=>l,...t,noInitialRun:!0,onRuntimeInitialized(){t.onRuntimeInitialized&&t.onRuntimeInitialized(),s()}});await r;const o=++lastRuntimeId;return n.id=o,n.originalExit=n._exit,n._exit=function(l){return loadedRuntimes.delete(o),n.originalExit(l)},n[RuntimeId]=o,loadedRuntimes.set(o,n),o}function getLoadedRuntime(e){return loadedRuntimes.get(e)}const currentJsRuntime=function(){var e;return typeof process<"u"&&((e=process.release)==null?void 0:e.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),makePromise=()=>{const e=[],t=new Promise((r,s)=>{e.push(r,s)});return e.unshift(t),e};var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__decorateClass=(e,t,r,s)=>{for(var i=s>1?void 0:s?__getOwnPropDesc(t,r):t,n=e.length-1,o;n>=0;n--)(o=e[n])&&(i=(s?o(t,r,i):o(i))||i);return s&&i&&__defProp(t,r,i),i};const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");var S,C,k,_,w,g,y,B,q,te,O,re,D,se,$,ne,j,ie,z,oe,G,ae,W,le,V,ce,J,ue,Y,de,Z,he;class BasePHP{constructor(e,t){c(this,q);c(this,O);c(this,D);c(this,$);c(this,j);c(this,z);c(this,G);c(this,W);c(this,V);c(this,J);c(this,Y);c(this,Z);c(this,S,void 0);c(this,C,void 0);c(this,k,void 0);c(this,_,void 0);c(this,w,void 0);c(this,g,void 0);c(this,y,void 0);c(this,B,void 0);u(this,S,[]),u(this,_,!1),u(this,w,null),u(this,g,{}),u(this,y,new Map),u(this,B,[]),this.semaphore=new Semaphore({concurrency:1}),e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new PHPBrowser(new PHPRequestHandler(this,t)))}addEventListener(e,t){a(this,y).has(e)||a(this,y).set(e,new Set),a(this,y).get(e).add(t)}removeEventListener(e,t){var r;(r=a(this,y).get(e))==null||r.delete(t)}dispatchEvent(e){const t=a(this,y).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){a(this,B).push(e)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const t=getLoadedRuntime(e);if(!t)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=t,t.onMessage=async r=>{for(const s of a(this,B)){const i=await s(r);if(i)return i}return""},u(this,w,improveWASMErrorReporting(t)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(e){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[e])!==0)throw new Error("Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?");u(this,k,e)}setPhpIniPath(e){if(a(this,_))throw new Error("Cannot set PHP ini path after calling run().");u(this,C,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(a(this,_))throw new Error("Cannot set PHP ini entries after calling run().");a(this,S).push([e,t])}chdir(e){this[__private__dont__use].FS.chdir(e)}async request(e,t){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,t)}async run(e){const t=await this.semaphore.acquire();let r;try{a(this,_)||(p(this,q,te).call(this),u(this,_,!0)),p(this,W,le).call(this,e.scriptPath||""),p(this,D,se).call(this,e.relativeUri||""),p(this,j,ie).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),i=s.host||"example.com:443";if(p(this,$,ne).call(this,i,e.protocol||"http"),p(this,z,oe).call(this,s),e.body&&(r=p(this,G,ae).call(this,e.body)),e.fileInfos)for(const o of e.fileInfos)p(this,J,ue).call(this,o);typeof e.code=="string"&&p(this,Y,de).call(this," ?>"+e.code),p(this,V,ce).call(this);const n=await p(this,Z,he).call(this);if(e.throwOnError&&n.exitCode!==0){const o={stdout:n.text,stderr:n.errors};console.warn("PHP.run() output was:",o);const l=new Error(`PHP.run() failed with exit code ${n.exitCode} and the following output`);throw l.output=o,l}return n}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){a(this,g)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/tmp/consts.json")&&this.readFileAsText("/tmp/consts.json")||"{}")}catch{}this.writeFile("/tmp/consts.json",JSON.stringify({...r,[e]:t}))}mkdir(e){this[__private__dont__use].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[__private__dont__use].FS.readFile(e)}writeFile(e,t){this[__private__dont__use].FS.writeFile(e,t)}unlink(e){this[__private__dont__use].FS.unlink(e)}mv(e,t){try{this[__private__dont__use].FS.rename(e,t)}catch(r){const s=getEmscriptenFsError(r);throw s?new Error(`Could not move ${e} to ${t}: ${s}`,{cause:r}):r}}rmdir(e,t={recursive:!0}){t!=null&&t.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[__private__dont__use].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[__private__dont__use].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(i=>`${s}/${i}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[__private__dont__use].FS.isDir(this[__private__dont__use].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[__private__dont__use].FS.lookupPath(e),!0}catch{return!1}}hotSwapPHPRuntime(e){const t=this[__private__dont__use].FS;try{this.exit()}catch{}if(this.initializeRuntime(e),a(this,C)&&this.setPhpIniPath(a(this,C)),a(this,k)&&this.setSapiName(a(this,k)),this.requestHandler){const r=this.documentRoot;recreateMemFS(this[__private__dont__use].FS,t,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}u(this,_,!1),u(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,C=new WeakMap,k=new WeakMap,_=new WeakMap,w=new WeakMap,g=new WeakMap,y=new WeakMap,B=new WeakMap,q=new WeakSet,te=function(){if(this.setPhpIniEntry("auto_prepend_file","/tmp/consts.php"),this.fileExists("/tmp/consts.php")||this.writeFile("/tmp/consts.php",`<?php
38
38
  if(file_exists('/tmp/consts.json')) {
39
39
  $consts = json_decode(file_get_contents('/tmp/consts.json'), true);
40
40
  foreach ($consts as $const => $value) {
@@ -45,4 +45,4 @@ ${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
45
45
  }`),a(this,S).length>0){const e=a(this,S).map(([t,r])=>`${t}=${r}`).join(`
46
46
  `)+`
47
47
 
48
- `;this[__private__dont__use].ccall("wasm_set_phpini_entries",null,[STRING],[e])}this[__private__dont__use].ccall("php_wasm_init",null,[],[])},O=new WeakSet,te=function(){const e="/tmp/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const t=JSON.parse(this.readFileAsText(e)),r={};for(const s of t.headers){if(!s.includes(": "))continue;const i=s.indexOf(": "),n=s.substring(0,i).toLowerCase(),o=s.substring(i+2);n in r||(r[n]=[]),r[n].push(o)}return{headers:r,httpStatusCode:t.status}},D=new WeakSet,re=function(e){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[t])}},q=new WeakSet,se=function(e,t){this[__private__dont__use].ccall("wasm_set_request_host",null,[STRING],[e]);let r;try{r=parseInt(new URL(e).port,10)}catch{}(!r||isNaN(r)||r===80)&&(r=t==="https"?443:80),this[__private__dont__use].ccall("wasm_set_request_port",null,[NUMBER],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")},$=new WeakSet,ne=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},j=new WeakSet,ie=function(e){e.cookie&&this[__private__dont__use].ccall("wasm_set_cookies",null,[STRING],[e.cookie]),e["content-type"]&&this[__private__dont__use].ccall("wasm_set_content_type",null,[STRING],[e["content-type"]]),e["content-length"]&&this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[parseInt(e["content-length"],10)]);for(const t in e){let r="HTTP_";["content-type","content-length"].includes(t.toLowerCase())&&(r=""),this.addServerGlobalEntry(`${r}${t.toUpperCase().replace(/-/g,"_")}`,e[t])}},z=new WeakSet,oe=function(e){const t=this[__private__dont__use].lengthBytesUTF8(e),r=this[__private__dont__use].malloc(t+1);if(!r)throw new Error("Could not allocate memory for the request body.");return this[__private__dont__use].stringToUTF8(e,r,t+1),this[__private__dont__use].ccall("wasm_set_request_body",null,[NUMBER],[r]),this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[new TextEncoder().encode(e).length]),r},W=new WeakSet,ae=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},G=new WeakSet,le=function(){for(const e in a(this,E))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,a(this,E)[e]])},V=new WeakSet,ce=function(e){const{key:t,name:r,type:s,data:i}=e,n=`/tmp/${Math.random().toFixed(20)}`;this.writeFile(n,i);const o=0;this[__private__dont__use].ccall("wasm_add_uploaded_file",null,[STRING,STRING,STRING,STRING,NUMBER,NUMBER],[t,r,s,n,o,i.byteLength])},J=new WeakSet,ue=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},Y=new WeakSet,de=async function(){var i;let e,t;try{e=await new Promise((n,o)=>{var p;t=d=>{const f=new Error("Rethrown");f.cause=d.error,f.betterMessage=d.message,o(f)},(p=a(this,g))==null||p.addEventListener("error",t);const l=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return l instanceof Promise?l.then(n,o):n(l)})}catch(n){for(const d in this)typeof this[d]=="function"&&(this[d]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=getFunctionsMaybeMissingFromAsyncify();const o=n,l="betterMessage"in o?o.betterMessage:o.message,p=new Error(l);throw p.cause=o,p}finally{(i=a(this,g))==null||i.removeEventListener("error",t),u(this,E,{})}const{headers:r,httpStatusCode:s}=h(this,O,te).call(this);return new PHPResponse(s,r,this.readFileAsBuffer("/tmp/stdout"),this.readFileAsText("/tmp/stderr"),e)};__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdir",1);__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdirTree",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsText",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsBuffer",1);__decorateClass([rethrowFileSystemError('Could not write to "{path}"')],BasePHP.prototype,"writeFile",1);__decorateClass([rethrowFileSystemError('Could not unlink "{path}"')],BasePHP.prototype,"unlink",1);__decorateClass([rethrowFileSystemError('Could not remove directory "{path}"')],BasePHP.prototype,"rmdir",1);__decorateClass([rethrowFileSystemError('Could not list files in "{path}"')],BasePHP.prototype,"listFiles",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"isDir",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"fileExists",1);function normalizeHeaders(e){const t={};for(const r in e)t[r.toLowerCase()]=e[r];return t}function recreateMemFS(e,t,r){let s;try{s=t.lookupPath(r)}catch{return}if(!("contents"in s.node))return;try{e=e.lookupPath(r);return}catch{}if(!t.isDir(s.node.mode)){e.writeFile(r,t.readFile(r));return}e.mkdirTree(r);const i=t.readdir(r).filter(n=>n!=="."&&n!=="..");for(const n of i)recreateMemFS(e,t,joinPaths(r,n))}function isLocalPHP(e){return!(e instanceof BasePHP)}function isRemotePHP(e){return!isLocalPHP(e)}function rotatePHPRuntime({php:e,recreateRuntime:t,maxRequests:r}){let s=0;async function i(){if(++s<r)return;s=0;const n=await e.semaphore.acquire();try{e.hotSwapPHPRuntime(await t())}finally{n()}}return e.addEventListener("request.end",i),function(){e.removeEventListener("request.end",i)}}exports.BasePHP=BasePHP;exports.DEFAULT_BASE_URL=DEFAULT_BASE_URL;exports.LatestSupportedPHPVersion=LatestSupportedPHPVersion;exports.PHPBrowser=PHPBrowser;exports.PHPRequestHandler=PHPRequestHandler;exports.PHPResponse=PHPResponse;exports.SupportedPHPExtensionBundles=SupportedPHPExtensionBundles;exports.SupportedPHPExtensionsList=SupportedPHPExtensionsList;exports.SupportedPHPVersions=SupportedPHPVersions;exports.SupportedPHPVersionsList=SupportedPHPVersionsList;exports.UnhandledRejectionsTarget=UnhandledRejectionsTarget;exports.__private__dont__use=__private__dont__use;exports.ensurePathPrefix=ensurePathPrefix;exports.isExitCodeZero=isExitCodeZero;exports.isLocalPHP=isLocalPHP;exports.isRemotePHP=isRemotePHP;exports.iterateFiles=iteratePhpFiles;exports.loadPHPRuntime=loadPHPRuntime;exports.removePathPrefix=removePathPrefix;exports.rethrowFileSystemError=rethrowFileSystemError;exports.rotatePHPRuntime=rotatePHPRuntime;exports.toRelativeUrl=toRelativeUrl;exports.writeFilesStreamToPhp=writeFilesStreamToPhp;
48
+ `;this[__private__dont__use].ccall("wasm_set_phpini_entries",null,[STRING],[e])}this[__private__dont__use].ccall("php_wasm_init",null,[],[])},O=new WeakSet,re=function(){const e="/tmp/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const t=JSON.parse(this.readFileAsText(e)),r={};for(const s of t.headers){if(!s.includes(": "))continue;const i=s.indexOf(": "),n=s.substring(0,i).toLowerCase(),o=s.substring(i+2);n in r||(r[n]=[]),r[n].push(o)}return{headers:r,httpStatusCode:t.status}},D=new WeakSet,se=function(e){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[t])}},$=new WeakSet,ne=function(e,t){this[__private__dont__use].ccall("wasm_set_request_host",null,[STRING],[e]);let r;try{r=parseInt(new URL(e).port,10)}catch{}(!r||isNaN(r)||r===80)&&(r=t==="https"?443:80),this[__private__dont__use].ccall("wasm_set_request_port",null,[NUMBER],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")},j=new WeakSet,ie=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},z=new WeakSet,oe=function(e){e.cookie&&this[__private__dont__use].ccall("wasm_set_cookies",null,[STRING],[e.cookie]),e["content-type"]&&this[__private__dont__use].ccall("wasm_set_content_type",null,[STRING],[e["content-type"]]),e["content-length"]&&this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[parseInt(e["content-length"],10)]);for(const t in e){let r="HTTP_";["content-type","content-length"].includes(t.toLowerCase())&&(r=""),this.addServerGlobalEntry(`${r}${t.toUpperCase().replace(/-/g,"_")}`,e[t])}},G=new WeakSet,ae=function(e){const t=this[__private__dont__use].lengthBytesUTF8(e),r=this[__private__dont__use].malloc(t+1);if(!r)throw new Error("Could not allocate memory for the request body.");return this[__private__dont__use].stringToUTF8(e,r,t+1),this[__private__dont__use].ccall("wasm_set_request_body",null,[NUMBER],[r]),this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[new TextEncoder().encode(e).length]),r},W=new WeakSet,le=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},V=new WeakSet,ce=function(){for(const e in a(this,g))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,a(this,g)[e]])},J=new WeakSet,ue=function(e){const{key:t,name:r,type:s,data:i}=e,n=`/tmp/${Math.random().toFixed(20)}`;this.writeFile(n,i);const o=0;this[__private__dont__use].ccall("wasm_add_uploaded_file",null,[STRING,STRING,STRING,STRING,NUMBER,NUMBER],[t,r,s,n,o,i.byteLength])},Y=new WeakSet,de=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},Z=new WeakSet,he=async function(){var i;let e,t;try{e=await new Promise((n,o)=>{var h;t=d=>{const f=new Error("Rethrown");f.cause=d.error,f.betterMessage=d.message,o(f)},(h=a(this,w))==null||h.addEventListener("error",t);const l=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return l instanceof Promise?l.then(n,o):n(l)})}catch(n){for(const d in this)typeof this[d]=="function"&&(this[d]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=getFunctionsMaybeMissingFromAsyncify();const o=n,l="betterMessage"in o?o.betterMessage:o.message,h=new Error(l);throw h.cause=o,h}finally{(i=a(this,w))==null||i.removeEventListener("error",t),u(this,g,{})}const{headers:r,httpStatusCode:s}=p(this,O,re).call(this);return new PHPResponse(s,r,this.readFileAsBuffer("/tmp/stdout"),this.readFileAsText("/tmp/stderr"),e)};__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdir",1);__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdirTree",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsText",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsBuffer",1);__decorateClass([rethrowFileSystemError('Could not write to "{path}"')],BasePHP.prototype,"writeFile",1);__decorateClass([rethrowFileSystemError('Could not unlink "{path}"')],BasePHP.prototype,"unlink",1);__decorateClass([rethrowFileSystemError('Could not remove directory "{path}"')],BasePHP.prototype,"rmdir",1);__decorateClass([rethrowFileSystemError('Could not list files in "{path}"')],BasePHP.prototype,"listFiles",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"isDir",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"fileExists",1);function normalizeHeaders(e){const t={};for(const r in e)t[r.toLowerCase()]=e[r];return t}function recreateMemFS(e,t,r){let s;try{s=t.lookupPath(r)}catch{return}if(!("contents"in s.node))return;try{e=e.lookupPath(r);return}catch{}if(!t.isDir(s.node.mode)){e.writeFile(r,t.readFile(r));return}e.mkdirTree(r);const i=t.readdir(r).filter(n=>n!=="."&&n!=="..");for(const n of i)recreateMemFS(e,t,joinPaths(r,n))}function isLocalPHP(e){return!(e instanceof BasePHP)}function isRemotePHP(e){return!isLocalPHP(e)}function rotatePHPRuntime({php:e,recreateRuntime:t,maxRequests:r}){let s=0;async function i(){if(++s<r)return;s=0;const n=await e.semaphore.acquire();try{e.hotSwapPHPRuntime(await t())}finally{n()}}return e.addEventListener("request.end",i),function(){e.removeEventListener("request.end",i)}}async function writeFiles(e,t,r,{rmRoot:s=!1}={}){s&&await e.isDir(t)&&await e.rmdir(t,{recursive:!0});for(const[i,n]of Object.entries(r)){const o=joinPaths(t,i);await e.fileExists(dirname(o))||await e.mkdir(dirname(o)),await e.writeFile(o,n)}}exports.BasePHP=BasePHP;exports.DEFAULT_BASE_URL=DEFAULT_BASE_URL;exports.LatestSupportedPHPVersion=LatestSupportedPHPVersion;exports.PHPBrowser=PHPBrowser;exports.PHPRequestHandler=PHPRequestHandler;exports.PHPResponse=PHPResponse;exports.SupportedPHPExtensionBundles=SupportedPHPExtensionBundles;exports.SupportedPHPExtensionsList=SupportedPHPExtensionsList;exports.SupportedPHPVersions=SupportedPHPVersions;exports.SupportedPHPVersionsList=SupportedPHPVersionsList;exports.UnhandledRejectionsTarget=UnhandledRejectionsTarget;exports.__private__dont__use=__private__dont__use;exports.ensurePathPrefix=ensurePathPrefix;exports.isExitCodeZero=isExitCodeZero;exports.isLocalPHP=isLocalPHP;exports.isRemotePHP=isRemotePHP;exports.iterateFiles=iteratePhpFiles;exports.loadPHPRuntime=loadPHPRuntime;exports.removePathPrefix=removePathPrefix;exports.rethrowFileSystemError=rethrowFileSystemError;exports.rotatePHPRuntime=rotatePHPRuntime;exports.toRelativeUrl=toRelativeUrl;exports.writeFiles=writeFiles;exports.writeFilesStreamToPhp=writeFilesStreamToPhp;
package/index.js CHANGED
@@ -1,13 +1,13 @@
1
- var Z = (e, t, r) => {
1
+ var K = (e, t, r) => {
2
2
  if (!t.has(e))
3
3
  throw TypeError("Cannot " + r);
4
4
  };
5
- var a = (e, t, r) => (Z(e, t, "read from private field"), r ? r.call(e) : t.get(e)), c = (e, t, r) => {
5
+ var a = (e, t, r) => (K(e, t, "read from private field"), r ? r.call(e) : t.get(e)), c = (e, t, r) => {
6
6
  if (t.has(e))
7
7
  throw TypeError("Cannot add the same private member more than once");
8
8
  t instanceof WeakSet ? t.add(e) : t.set(e, r);
9
- }, u = (e, t, r, s) => (Z(e, t, "write to private field"), s ? s.call(e, r) : t.set(e, r), r);
10
- var h = (e, t, r) => (Z(e, t, "access private method"), r);
9
+ }, u = (e, t, r, s) => (K(e, t, "write to private field"), s ? s.call(e, r) : t.set(e, r), r);
10
+ var f = (e, t, r) => (K(e, t, "access private method"), r);
11
11
  if (typeof File > "u") {
12
12
  class e extends Blob {
13
13
  constructor(r, s, i) {
@@ -468,8 +468,8 @@ async function* iteratePhpFiles(e, t, {
468
468
  if (!o)
469
469
  return;
470
470
  const l = await e.listFiles(o);
471
- for (const p of l) {
472
- const d = `${o}/${p}`;
471
+ for (const h of l) {
472
+ const d = `${o}/${h}`;
473
473
  if (i.includes(d.substring(t.length + 1)))
474
474
  continue;
475
475
  await e.isDir(d) ? n.push(d) : yield new StreamedFile(
@@ -546,16 +546,16 @@ const SupportedPHPVersions = [
546
546
  ], SupportedPHPExtensionBundles = {
547
547
  "kitchen-sink": SupportedPHPExtensionsList
548
548
  };
549
- var v, S;
549
+ var E, H;
550
550
  class PHPBrowser {
551
551
  /**
552
552
  * @param server - The PHP server to browse.
553
553
  * @param config - The browser configuration.
554
554
  */
555
555
  constructor(t, r = {}) {
556
- c(this, v, void 0);
557
- c(this, S, void 0);
558
- this.requestHandler = t, u(this, v, {}), u(this, S, {
556
+ c(this, E, void 0);
557
+ c(this, H, void 0);
558
+ this.requestHandler = t, u(this, E, {}), u(this, H, {
559
559
  handleRedirects: !1,
560
560
  maxRedirects: 4,
561
561
  ...r
@@ -583,7 +583,7 @@ class PHPBrowser {
583
583
  cookie: this.serializeCookies()
584
584
  }
585
585
  });
586
- if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), a(this, S).handleRedirects && s.headers.location && r < a(this, S).maxRedirects) {
586
+ if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), a(this, H).handleRedirects && s.headers.location && r < a(this, H).maxRedirects) {
587
587
  const i = new URL(
588
588
  s.headers.location[0],
589
589
  this.requestHandler.absoluteUrl
@@ -621,19 +621,19 @@ class PHPBrowser {
621
621
  if (!r.includes("="))
622
622
  continue;
623
623
  const s = r.indexOf("="), i = r.substring(0, s), n = r.substring(s + 1).split(";")[0];
624
- a(this, v)[i] = n;
624
+ a(this, E)[i] = n;
625
625
  } catch (s) {
626
626
  console.error(s);
627
627
  }
628
628
  }
629
629
  serializeCookies() {
630
630
  const t = [];
631
- for (const r in a(this, v))
632
- t.push(`${r}=${a(this, v)[r]}`);
631
+ for (const r in a(this, E))
632
+ t.push(`${r}=${a(this, E)[r]}`);
633
633
  return t.join("; ");
634
634
  }
635
635
  }
636
- v = new WeakMap(), S = new WeakMap();
636
+ E = new WeakMap(), H = new WeakMap();
637
637
  const DEFAULT_BASE_URL = "http://example.com";
638
638
  function toRelativeUrl(e) {
639
639
  return e.toString().substring(e.origin.length);
@@ -644,7 +644,7 @@ function removePathPrefix(e, t) {
644
644
  function ensurePathPrefix(e, t) {
645
645
  return !t || e.startsWith(t) ? e : t + e;
646
646
  }
647
- var w, x, A, R, H, _, F, T, U, K, L, Q, N, X;
647
+ var P, x, A, v, F, m, T, R, L, Q, N, X, M, ee;
648
648
  class PHPRequestHandler {
649
649
  /**
650
650
  * @param php - The PHP instance.
@@ -657,7 +657,7 @@ class PHPRequestHandler {
657
657
  * @param fsPath - Absolute path of the static file to serve.
658
658
  * @returns The response.
659
659
  */
660
- c(this, U);
660
+ c(this, L);
661
661
  /**
662
662
  * Runs the requested PHP file with all the request and $_SERVER
663
663
  * superglobals populated.
@@ -665,7 +665,7 @@ class PHPRequestHandler {
665
665
  * @param request - The request.
666
666
  * @returns The response.
667
667
  */
668
- c(this, L);
668
+ c(this, N);
669
669
  /**
670
670
  * Resolve the requested path to the filesystem path of the requested PHP file.
671
671
  *
@@ -675,31 +675,31 @@ class PHPRequestHandler {
675
675
  * @throws {Error} If the requested path doesn't exist.
676
676
  * @returns The resolved filesystem path.
677
677
  */
678
- c(this, N);
679
- c(this, w, void 0);
678
+ c(this, M);
679
+ c(this, P, void 0);
680
680
  c(this, x, void 0);
681
681
  c(this, A, void 0);
682
- c(this, R, void 0);
683
- c(this, H, void 0);
684
- c(this, _, void 0);
682
+ c(this, v, void 0);
685
683
  c(this, F, void 0);
684
+ c(this, m, void 0);
686
685
  c(this, T, void 0);
687
- u(this, T, new Semaphore({ concurrency: 1 }));
686
+ c(this, R, void 0);
687
+ u(this, R, new Semaphore({ concurrency: 1 }));
688
688
  const {
689
689
  documentRoot: s = "/www/",
690
690
  absoluteUrl: i = typeof location == "object" ? location == null ? void 0 : location.href : ""
691
691
  } = r;
692
- this.php = t, u(this, w, s);
692
+ this.php = t, u(this, P, s);
693
693
  const n = new URL(i);
694
- u(this, A, n.hostname), u(this, R, n.port ? Number(n.port) : n.protocol === "https:" ? 443 : 80), u(this, x, (n.protocol || "").replace(":", ""));
695
- const o = a(this, R) !== 443 && a(this, R) !== 80;
696
- u(this, H, [
694
+ u(this, A, n.hostname), u(this, v, n.port ? Number(n.port) : n.protocol === "https:" ? 443 : 80), u(this, x, (n.protocol || "").replace(":", ""));
695
+ const o = a(this, v) !== 443 && a(this, v) !== 80;
696
+ u(this, F, [
697
697
  a(this, A),
698
- o ? `:${a(this, R)}` : ""
699
- ].join("")), u(this, _, n.pathname.replace(/\/+$/, "")), u(this, F, [
698
+ o ? `:${a(this, v)}` : ""
699
+ ].join("")), u(this, m, n.pathname.replace(/\/+$/, "")), u(this, T, [
700
700
  `${a(this, x)}://`,
701
- a(this, H),
702
- a(this, _)
701
+ a(this, F),
702
+ a(this, m)
703
703
  ].join(""));
704
704
  }
705
705
  /** @inheritDoc */
@@ -709,18 +709,18 @@ class PHPRequestHandler {
709
709
  /** @inheritDoc */
710
710
  internalUrlToPath(t) {
711
711
  const r = new URL(t);
712
- return r.pathname.startsWith(a(this, _)) && (r.pathname = r.pathname.slice(a(this, _).length)), toRelativeUrl(r);
712
+ return r.pathname.startsWith(a(this, m)) && (r.pathname = r.pathname.slice(a(this, m).length)), toRelativeUrl(r);
713
713
  }
714
714
  get isRequestRunning() {
715
- return a(this, T).running > 0;
715
+ return a(this, R).running > 0;
716
716
  }
717
717
  /** @inheritDoc */
718
718
  get absoluteUrl() {
719
- return a(this, F);
719
+ return a(this, T);
720
720
  }
721
721
  /** @inheritDoc */
722
722
  get documentRoot() {
723
- return a(this, w);
723
+ return a(this, P);
724
724
  }
725
725
  /** @inheritDoc */
726
726
  async request(t) {
@@ -729,12 +729,12 @@ class PHPRequestHandler {
729
729
  r ? void 0 : DEFAULT_BASE_URL
730
730
  ), i = removePathPrefix(
731
731
  s.pathname,
732
- a(this, _)
733
- ), n = `${a(this, w)}${i}`;
734
- return seemsLikeAPHPRequestHandlerPath(n) ? await h(this, L, Q).call(this, t, s) : h(this, U, K).call(this, n);
732
+ a(this, m)
733
+ ), n = `${a(this, P)}${i}`;
734
+ return seemsLikeAPHPRequestHandlerPath(n) ? await f(this, N, X).call(this, t, s) : f(this, L, Q).call(this, n);
735
735
  }
736
736
  }
737
- w = new WeakMap(), x = new WeakMap(), A = new WeakMap(), R = new WeakMap(), H = new WeakMap(), _ = new WeakMap(), F = new WeakMap(), T = new WeakMap(), U = new WeakSet(), K = function(t) {
737
+ P = new WeakMap(), x = new WeakMap(), A = new WeakMap(), v = new WeakMap(), F = new WeakMap(), m = new WeakMap(), T = new WeakMap(), R = new WeakMap(), L = new WeakSet(), Q = function(t) {
738
738
  if (!this.php.fileExists(t))
739
739
  return new PHPResponse(
740
740
  404,
@@ -759,49 +759,57 @@ w = new WeakMap(), x = new WeakMap(), A = new WeakMap(), R = new WeakMap(), H =
759
759
  },
760
760
  r
761
761
  );
762
- }, L = new WeakSet(), Q = async function(t, r) {
763
- var i, n;
764
- const s = await a(this, T).acquire();
762
+ }, N = new WeakSet(), X = async function(t, r) {
763
+ var i, n, o;
764
+ if (a(this, R).running > 0 && ((i = t.headers) == null ? void 0 : i["x-request-issuer"]) === "php")
765
+ return console.warn(
766
+ "Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."
767
+ ), new PHPResponse(
768
+ 502,
769
+ {},
770
+ new TextEncoder().encode("502 Bad Gateway")
771
+ );
772
+ const s = await a(this, R).acquire();
765
773
  try {
766
- this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", a(this, w)), this.php.addServerGlobalEntry(
774
+ this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", a(this, P)), this.php.addServerGlobalEntry(
767
775
  "HTTPS",
768
- a(this, F).startsWith("https://") ? "on" : ""
776
+ a(this, T).startsWith("https://") ? "on" : ""
769
777
  );
770
- let o = "GET";
771
- const l = {
772
- host: a(this, H),
778
+ let l = "GET";
779
+ const h = {
780
+ host: a(this, F),
773
781
  ...normalizeHeaders(t.headers || {})
774
- }, p = [];
782
+ }, d = [];
775
783
  if (t.files && Object.keys(t.files).length) {
776
- o = "POST";
777
- for (const P in t.files) {
778
- const I = t.files[P];
779
- p.push({
780
- key: P,
781
- name: I.name,
782
- type: I.type,
783
- data: new Uint8Array(await I.arrayBuffer())
784
+ l = "POST";
785
+ for (const S in t.files) {
786
+ const U = t.files[S];
787
+ d.push({
788
+ key: S,
789
+ name: U.name,
790
+ type: U.type,
791
+ data: new Uint8Array(await U.arrayBuffer())
784
792
  });
785
793
  }
786
- (i = l["content-type"]) != null && i.startsWith("multipart/form-data") && (t.formData = parseMultipartFormDataString(
794
+ (n = h["content-type"]) != null && n.startsWith("multipart/form-data") && (t.formData = parseMultipartFormDataString(
787
795
  t.body || ""
788
- ), l["content-type"] = "application/x-www-form-urlencoded", delete t.body);
796
+ ), h["content-type"] = "application/x-www-form-urlencoded", delete t.body);
789
797
  }
790
- let d;
791
- t.formData !== void 0 ? (o = "POST", l["content-type"] = l["content-type"] || "application/x-www-form-urlencoded", d = new URLSearchParams(
798
+ let p;
799
+ t.formData !== void 0 ? (l = "POST", h["content-type"] = h["content-type"] || "application/x-www-form-urlencoded", p = new URLSearchParams(
792
800
  t.formData
793
- ).toString()) : d = t.body;
794
- let f;
801
+ ).toString()) : p = t.body;
802
+ let I;
795
803
  try {
796
- let P = r.pathname;
797
- if ((n = t.headers) != null && n["x-rewrite-url"])
804
+ let S = r.pathname;
805
+ if ((o = t.headers) != null && o["x-rewrite-url"])
798
806
  try {
799
- P = new URL(
807
+ S = new URL(
800
808
  t.headers["x-rewrite-url"]
801
809
  ).pathname;
802
810
  } catch {
803
811
  }
804
- f = h(this, N, X).call(this, P);
812
+ I = f(this, M, ee).call(this, S);
805
813
  } catch {
806
814
  return new PHPResponse(
807
815
  404,
@@ -812,22 +820,22 @@ w = new WeakMap(), x = new WeakMap(), A = new WeakMap(), R = new WeakMap(), H =
812
820
  return await this.php.run({
813
821
  relativeUri: ensurePathPrefix(
814
822
  toRelativeUrl(r),
815
- a(this, _)
823
+ a(this, m)
816
824
  ),
817
825
  protocol: a(this, x),
818
- method: t.method || o,
819
- body: d,
820
- fileInfos: p,
821
- scriptPath: f,
822
- headers: l
826
+ method: t.method || l,
827
+ body: p,
828
+ fileInfos: d,
829
+ scriptPath: I,
830
+ headers: h
823
831
  });
824
832
  } finally {
825
833
  s();
826
834
  }
827
- }, N = new WeakSet(), X = function(t) {
828
- let r = removePathPrefix(t, a(this, _));
835
+ }, M = new WeakSet(), ee = function(t) {
836
+ let r = removePathPrefix(t, a(this, m));
829
837
  r.includes(".php") ? r = r.split(".php")[0] + ".php" : (r.endsWith("/") || (r += "/"), r.endsWith("index.php") || (r += "index.php"));
830
- const s = `${a(this, w)}${r}`;
838
+ const s = `${a(this, P)}${r}`;
831
839
  if (this.php.fileExists(s))
832
840
  return s;
833
841
  throw new Error(`File not found: ${s}`);
@@ -840,10 +848,10 @@ function parseMultipartFormDataString(e) {
840
848
  return i.shift(), i.pop(), i.forEach((n) => {
841
849
  const o = n.indexOf(`\r
842
850
  \r
843
- `), l = n.substring(0, o).trim(), p = n.substring(o + 4).trim(), d = l.match(/name="([^"]+)"/);
851
+ `), l = n.substring(0, o).trim(), h = n.substring(o + 4).trim(), d = l.match(/name="([^"]+)"/);
844
852
  if (d) {
845
- const f = d[1];
846
- t[f] = p;
853
+ const p = d[1];
854
+ t[p] = h;
847
855
  }
848
856
  }), t;
849
857
  }
@@ -987,10 +995,10 @@ function rethrowFileSystemError(e = "") {
987
995
  try {
988
996
  return n.apply(this, o);
989
997
  } catch (l) {
990
- const p = typeof l == "object" ? l == null ? void 0 : l.errno : null;
991
- if (p in FileErrorCodes) {
992
- const d = FileErrorCodes[p], f = typeof o[0] == "string" ? o[0] : null, P = f !== null ? e.replaceAll("{path}", f) : e;
993
- throw new Error(`${P}: ${d}`, {
998
+ const h = typeof l == "object" ? l == null ? void 0 : l.errno : null;
999
+ if (h in FileErrorCodes) {
1000
+ const d = FileErrorCodes[h], p = typeof o[0] == "string" ? o[0] : null, I = p !== null ? e.replaceAll("{path}", p) : e;
1001
+ throw new Error(`${I}: ${d}`, {
994
1002
  cause: l
995
1003
  });
996
1004
  }
@@ -1041,7 +1049,7 @@ var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyD
1041
1049
  return s && i && __defProp(t, r, i), i;
1042
1050
  };
1043
1051
  const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
1044
- var b, C, k, m, g, E, y, B, M, ee, O, te, D, re, $, se, q, ne, j, ie, z, oe, W, ae, G, le, V, ce, J, ue, Y, de;
1052
+ var b, C, k, _, w, g, y, B, q, te, O, re, D, se, $, ne, j, ie, z, oe, G, ae, W, le, V, ce, J, ue, Y, de, Z, he;
1045
1053
  class BasePHP {
1046
1054
  /**
1047
1055
  * Initializes a PHP runtime.
@@ -1051,15 +1059,15 @@ class BasePHP {
1051
1059
  * @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
1052
1060
  */
1053
1061
  constructor(e, t) {
1054
- c(this, M);
1062
+ c(this, q);
1055
1063
  c(this, O);
1056
1064
  c(this, D);
1057
1065
  c(this, $);
1058
- c(this, q);
1059
1066
  c(this, j);
1060
1067
  c(this, z);
1061
- c(this, W);
1062
1068
  c(this, G);
1069
+ c(this, W);
1070
+ c(this, V);
1063
1071
  /**
1064
1072
  * Adds file information to $_FILES superglobal in PHP.
1065
1073
  *
@@ -1069,18 +1077,18 @@ class BasePHP {
1069
1077
  *
1070
1078
  * @param fileInfo - File details
1071
1079
  */
1072
- c(this, V);
1073
1080
  c(this, J);
1074
1081
  c(this, Y);
1082
+ c(this, Z);
1075
1083
  c(this, b, void 0);
1076
1084
  c(this, C, void 0);
1077
1085
  c(this, k, void 0);
1078
- c(this, m, void 0);
1086
+ c(this, _, void 0);
1087
+ c(this, w, void 0);
1079
1088
  c(this, g, void 0);
1080
- c(this, E, void 0);
1081
1089
  c(this, y, void 0);
1082
1090
  c(this, B, void 0);
1083
- u(this, b, []), u(this, m, !1), u(this, g, null), u(this, E, {}), u(this, y, /* @__PURE__ */ new Map()), u(this, B, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new PHPBrowser(
1091
+ u(this, b, []), u(this, _, !1), u(this, w, null), u(this, g, {}), u(this, y, /* @__PURE__ */ new Map()), u(this, B, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new PHPBrowser(
1084
1092
  new PHPRequestHandler(this, t)
1085
1093
  ));
1086
1094
  }
@@ -1136,7 +1144,7 @@ class BasePHP {
1136
1144
  return i;
1137
1145
  }
1138
1146
  return "";
1139
- }, u(this, g, improveWASMErrorReporting(t)), this.dispatchEvent({
1147
+ }, u(this, w, improveWASMErrorReporting(t)), this.dispatchEvent({
1140
1148
  type: "runtime.initialized"
1141
1149
  });
1142
1150
  }
@@ -1155,7 +1163,7 @@ class BasePHP {
1155
1163
  }
1156
1164
  /** @inheritDoc */
1157
1165
  setPhpIniPath(e) {
1158
- if (a(this, m))
1166
+ if (a(this, _))
1159
1167
  throw new Error("Cannot set PHP ini path after calling run().");
1160
1168
  u(this, C, e), this[__private__dont__use].ccall(
1161
1169
  "wasm_set_phpini_path",
@@ -1166,7 +1174,7 @@ class BasePHP {
1166
1174
  }
1167
1175
  /** @inheritDoc */
1168
1176
  setPhpIniEntry(e, t) {
1169
- if (a(this, m))
1177
+ if (a(this, _))
1170
1178
  throw new Error("Cannot set PHP ini entries after calling run().");
1171
1179
  a(this, b).push([e, t]);
1172
1180
  }
@@ -1185,13 +1193,13 @@ class BasePHP {
1185
1193
  const t = await this.semaphore.acquire();
1186
1194
  let r;
1187
1195
  try {
1188
- a(this, m) || (h(this, M, ee).call(this), u(this, m, !0)), h(this, W, ae).call(this, e.scriptPath || ""), h(this, D, re).call(this, e.relativeUri || ""), h(this, q, ne).call(this, e.method || "GET");
1196
+ a(this, _) || (f(this, q, te).call(this), u(this, _, !0)), f(this, W, le).call(this, e.scriptPath || ""), f(this, D, se).call(this, e.relativeUri || ""), f(this, j, ie).call(this, e.method || "GET");
1189
1197
  const s = normalizeHeaders(e.headers || {}), i = s.host || "example.com:443";
1190
- if (h(this, $, se).call(this, i, e.protocol || "http"), h(this, j, ie).call(this, s), e.body && (r = h(this, z, oe).call(this, e.body)), e.fileInfos)
1198
+ if (f(this, $, ne).call(this, i, e.protocol || "http"), f(this, z, oe).call(this, s), e.body && (r = f(this, G, ae).call(this, e.body)), e.fileInfos)
1191
1199
  for (const o of e.fileInfos)
1192
- h(this, V, ce).call(this, o);
1193
- typeof e.code == "string" && h(this, J, ue).call(this, " ?>" + e.code), h(this, G, le).call(this);
1194
- const n = await h(this, Y, de).call(this);
1200
+ f(this, J, ue).call(this, o);
1201
+ typeof e.code == "string" && f(this, Y, de).call(this, " ?>" + e.code), f(this, V, ce).call(this);
1202
+ const n = await f(this, Z, he).call(this);
1195
1203
  if (e.throwOnError && n.exitCode !== 0) {
1196
1204
  const o = {
1197
1205
  stdout: n.text,
@@ -1215,7 +1223,7 @@ class BasePHP {
1215
1223
  }
1216
1224
  }
1217
1225
  addServerGlobalEntry(e, t) {
1218
- a(this, E)[e] = t;
1226
+ a(this, g)[e] = t;
1219
1227
  }
1220
1228
  defineConstant(e, t) {
1221
1229
  let r = {};
@@ -1324,10 +1332,10 @@ class BasePHP {
1324
1332
  this[__private__dont__use]._exit(e);
1325
1333
  } catch {
1326
1334
  }
1327
- u(this, m, !1), u(this, g, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1335
+ u(this, _, !1), u(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1328
1336
  }
1329
1337
  }
1330
- b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), m = new WeakMap(), g = new WeakMap(), E = new WeakMap(), y = new WeakMap(), B = new WeakMap(), M = new WeakSet(), ee = function() {
1338
+ b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), _ = new WeakMap(), w = new WeakMap(), g = new WeakMap(), y = new WeakMap(), B = new WeakMap(), q = new WeakSet(), te = function() {
1331
1339
  if (this.setPhpIniEntry("auto_prepend_file", "/tmp/consts.php"), this.fileExists("/tmp/consts.php") || this.writeFile(
1332
1340
  "/tmp/consts.php",
1333
1341
  `<?php
@@ -1352,7 +1360,7 @@ b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), m = new WeakMap(), g =
1352
1360
  );
1353
1361
  }
1354
1362
  this[__private__dont__use].ccall("php_wasm_init", null, [], []);
1355
- }, O = new WeakSet(), te = function() {
1363
+ }, O = new WeakSet(), re = function() {
1356
1364
  const e = "/tmp/headers.json";
1357
1365
  if (!this.fileExists(e))
1358
1366
  throw new Error(
@@ -1369,7 +1377,7 @@ b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), m = new WeakMap(), g =
1369
1377
  headers: r,
1370
1378
  httpStatusCode: t.status
1371
1379
  };
1372
- }, D = new WeakSet(), re = function(e) {
1380
+ }, D = new WeakSet(), se = function(e) {
1373
1381
  if (this[__private__dont__use].ccall(
1374
1382
  "wasm_set_request_uri",
1375
1383
  null,
@@ -1384,7 +1392,7 @@ b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), m = new WeakMap(), g =
1384
1392
  [t]
1385
1393
  );
1386
1394
  }
1387
- }, $ = new WeakSet(), se = function(e, t) {
1395
+ }, $ = new WeakSet(), ne = function(e, t) {
1388
1396
  this[__private__dont__use].ccall(
1389
1397
  "wasm_set_request_host",
1390
1398
  null,
@@ -1402,14 +1410,14 @@ b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), m = new WeakMap(), g =
1402
1410
  [NUMBER],
1403
1411
  [r]
1404
1412
  ), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
1405
- }, q = new WeakSet(), ne = function(e) {
1413
+ }, j = new WeakSet(), ie = function(e) {
1406
1414
  this[__private__dont__use].ccall(
1407
1415
  "wasm_set_request_method",
1408
1416
  null,
1409
1417
  [STRING],
1410
1418
  [e]
1411
1419
  );
1412
- }, j = new WeakSet(), ie = function(e) {
1420
+ }, z = new WeakSet(), oe = function(e) {
1413
1421
  e.cookie && this[__private__dont__use].ccall(
1414
1422
  "wasm_set_cookies",
1415
1423
  null,
@@ -1433,7 +1441,7 @@ b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), m = new WeakMap(), g =
1433
1441
  e[t]
1434
1442
  );
1435
1443
  }
1436
- }, z = new WeakSet(), oe = function(e) {
1444
+ }, G = new WeakSet(), ae = function(e) {
1437
1445
  const t = this[__private__dont__use].lengthBytesUTF8(e), r = this[__private__dont__use].malloc(t + 1);
1438
1446
  if (!r)
1439
1447
  throw new Error("Could not allocate memory for the request body.");
@@ -1452,22 +1460,22 @@ b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), m = new WeakMap(), g =
1452
1460
  [NUMBER],
1453
1461
  [new TextEncoder().encode(e).length]
1454
1462
  ), r;
1455
- }, W = new WeakSet(), ae = function(e) {
1463
+ }, W = new WeakSet(), le = function(e) {
1456
1464
  this[__private__dont__use].ccall(
1457
1465
  "wasm_set_path_translated",
1458
1466
  null,
1459
1467
  [STRING],
1460
1468
  [e]
1461
1469
  );
1462
- }, G = new WeakSet(), le = function() {
1463
- for (const e in a(this, E))
1470
+ }, V = new WeakSet(), ce = function() {
1471
+ for (const e in a(this, g))
1464
1472
  this[__private__dont__use].ccall(
1465
1473
  "wasm_add_SERVER_entry",
1466
1474
  null,
1467
1475
  [STRING, STRING],
1468
- [e, a(this, E)[e]]
1476
+ [e, a(this, g)[e]]
1469
1477
  );
1470
- }, V = new WeakSet(), ce = function(e) {
1478
+ }, J = new WeakSet(), ue = function(e) {
1471
1479
  const { key: t, name: r, type: s, data: i } = e, n = `/tmp/${Math.random().toFixed(20)}`;
1472
1480
  this.writeFile(n, i);
1473
1481
  const o = 0;
@@ -1477,23 +1485,23 @@ b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), m = new WeakMap(), g =
1477
1485
  [STRING, STRING, STRING, STRING, NUMBER, NUMBER],
1478
1486
  [t, r, s, n, o, i.byteLength]
1479
1487
  );
1480
- }, J = new WeakSet(), ue = function(e) {
1488
+ }, Y = new WeakSet(), de = function(e) {
1481
1489
  this[__private__dont__use].ccall(
1482
1490
  "wasm_set_php_code",
1483
1491
  null,
1484
1492
  [STRING],
1485
1493
  [e]
1486
1494
  );
1487
- }, Y = new WeakSet(), de = async function() {
1495
+ }, Z = new WeakSet(), he = async function() {
1488
1496
  var i;
1489
1497
  let e, t;
1490
1498
  try {
1491
1499
  e = await new Promise((n, o) => {
1492
- var p;
1500
+ var h;
1493
1501
  t = (d) => {
1494
- const f = new Error("Rethrown");
1495
- f.cause = d.error, f.betterMessage = d.message, o(f);
1496
- }, (p = a(this, g)) == null || p.addEventListener(
1502
+ const p = new Error("Rethrown");
1503
+ p.cause = d.error, p.betterMessage = d.message, o(p);
1504
+ }, (h = a(this, w)) == null || h.addEventListener(
1497
1505
  "error",
1498
1506
  t
1499
1507
  );
@@ -1514,12 +1522,12 @@ b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), m = new WeakMap(), g =
1514
1522
  );
1515
1523
  });
1516
1524
  this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
1517
- const o = n, l = "betterMessage" in o ? o.betterMessage : o.message, p = new Error(l);
1518
- throw p.cause = o, p;
1525
+ const o = n, l = "betterMessage" in o ? o.betterMessage : o.message, h = new Error(l);
1526
+ throw h.cause = o, h;
1519
1527
  } finally {
1520
- (i = a(this, g)) == null || i.removeEventListener("error", t), u(this, E, {});
1528
+ (i = a(this, w)) == null || i.removeEventListener("error", t), u(this, g, {});
1521
1529
  }
1522
- const { headers: r, httpStatusCode: s } = h(this, O, te).call(this);
1530
+ const { headers: r, httpStatusCode: s } = f(this, O, re).call(this);
1523
1531
  return new PHPResponse(
1524
1532
  s,
1525
1533
  r,
@@ -1614,6 +1622,13 @@ function rotatePHPRuntime({
1614
1622
  e.removeEventListener("request.end", i);
1615
1623
  };
1616
1624
  }
1625
+ async function writeFiles(e, t, r, { rmRoot: s = !1 } = {}) {
1626
+ s && await e.isDir(t) && await e.rmdir(t, { recursive: !0 });
1627
+ for (const [i, n] of Object.entries(r)) {
1628
+ const o = joinPaths(t, i);
1629
+ await e.fileExists(dirname(o)) || await e.mkdir(dirname(o)), await e.writeFile(o, n);
1630
+ }
1631
+ }
1617
1632
  export {
1618
1633
  BasePHP,
1619
1634
  DEFAULT_BASE_URL,
@@ -1637,5 +1652,6 @@ export {
1637
1652
  rethrowFileSystemError,
1638
1653
  rotatePHPRuntime,
1639
1654
  toRelativeUrl,
1655
+ writeFiles,
1640
1656
  writeFilesStreamToPhp
1641
1657
  };
package/lib/index.d.ts CHANGED
@@ -21,5 +21,6 @@ export { PHPRequestHandler } from './php-request-handler';
21
21
  export type { PHPBrowserConfiguration } from './php-browser';
22
22
  export { PHPBrowser } from './php-browser';
23
23
  export { rotatePHPRuntime } from './rotate-php-runtime';
24
+ export { writeFiles } from './write-files';
24
25
  export { DEFAULT_BASE_URL, ensurePathPrefix, removePathPrefix, toRelativeUrl, } from './urls';
25
26
  export { isExitCodeZero } from './is-exit-code-zero';
@@ -169,7 +169,7 @@ export interface IsomorphicLocalPHP extends RequestHandler {
169
169
  * @param key - The name of the constant.
170
170
  * @param value - The value of the constant.
171
171
  */
172
- defineConstant(key: string, value: string | number | null): void;
172
+ defineConstant(key: string, value: boolean | string | number | null): void;
173
173
  /**
174
174
  * Adds an event listener for a PHP event.
175
175
  * @param eventType - The type of event to listen for.
@@ -0,0 +1,26 @@
1
+ import { UniversalPHP } from './universal-php';
2
+ export interface WriteFilesOptions {
3
+ /**
4
+ * Whether to wipe out the contents of the
5
+ * root directory before writing the new files.
6
+ */
7
+ rmRoot?: boolean;
8
+ }
9
+ /**
10
+ * Writes multiple files to a specified directory in the Playground
11
+ * filesystem.
12
+ *
13
+ * @example ```ts
14
+ * await writeFiles(php, '/test', {
15
+ * 'file.txt': 'file',
16
+ * 'sub/file.txt': 'file',
17
+ * 'sub1/sub2/file.txt': 'file',
18
+ * });
19
+ * ```
20
+ *
21
+ * @param php
22
+ * @param root
23
+ * @param newFiles
24
+ * @param options
25
+ */
26
+ export declare function writeFiles(php: UniversalPHP, root: string, newFiles: Record<string, Uint8Array | string>, { rmRoot }?: WriteFilesOptions): Promise<void>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/universal",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "PHP.wasm – emscripten bindings for PHP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -36,7 +36,7 @@
36
36
  "main": "./index.cjs",
37
37
  "module": "./index.js",
38
38
  "license": "GPL-2.0-or-later",
39
- "gitHead": "3f137306ec8e3b10ec0674a1fe69ee43349edb4a",
39
+ "gitHead": "3c0de0d0847c3550a75a026bef9724eac421afbf",
40
40
  "engines": {
41
41
  "node": ">=18.18.2",
42
42
  "npm": ">=8.11.0"