@php-wasm/universal 0.6.6 → 0.6.8

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 J=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var a=(e,t,r)=>(J(e,t,"read from private field"),r?r.call(e):t.get(e)),u=(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)},h=(e,t,r,s)=>(J(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var p=(e,t,r)=>(J(e,t,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});if(typeof File>"u"){class e extends Blob{constructor(r,s,n){super(r);let i;n!=null&&n.lastModified&&(i=new Date),(!i||isNaN(i.getFullYear()))&&(i=new Date),this.lastModifiedDate=i,this.lastModified=i.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,i=await t.slice(e,e+s.byteLength).arrayBuffer(),o=new Uint8Array(i);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(...n){var i;try{return s(...n)}catch(o){if(!(o instanceof Error))throw o;const l=clarifyErrorMessage(o,(i=e.lastAsyncifyStackSource)==null?void 0:i.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 J=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var l=(e,t,r)=>(J(e,t,"read from private field"),r?r.call(e):t.get(e)),u=(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)},h=(e,t,r,s)=>(J(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var p=(e,t,r)=>(J(e,t,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const currentJsRuntime$1=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"}();if(currentJsRuntime$1==="NODE"){let e=function(r){return new Promise(function(s,n){r.onload=r.onerror=function(o){r.onload=r.onerror=null,o.type==="load"?s(r.result):n(new Error("Failed to read the blob/file"))}})},t=function(){const r=new Uint8Array([1,2,3,4]),n=new File([r],"test").stream();try{return n.getReader({mode:"byob"}),!0}catch{return!1}};if(typeof File>"u"){class r extends Blob{constructor(n,o,i){super(n);let a;i!=null&&i.lastModified&&(a=new Date),(!a||isNaN(a.getFullYear()))&&(a=new Date),this.lastModifiedDate=a,this.lastModified=a.getMilliseconds(),this.name=o||""}}global.File=r}typeof Blob.prototype.arrayBuffer>"u"&&(Blob.prototype.arrayBuffer=function(){const s=new FileReader;return s.readAsArrayBuffer(this),e(s)}),typeof Blob.prototype.text>"u"&&(Blob.prototype.text=function(){const s=new FileReader;return s.readAsText(this),e(s)}),(typeof Blob.prototype.stream>"u"||!t())&&(Blob.prototype.stream=function(){let r=0;const s=this;return new ReadableStream({type:"bytes",autoAllocateChunkSize:512*1024,async pull(n){const o=n.byobRequest.view,a=await s.slice(r,r+o.byteLength).arrayBuffer(),c=new Uint8Array(a);new Uint8Array(o.buffer).set(c);const d=c.byteLength;n.byobRequest.respond(d),r+=d,r>=s.size&&n.close()}})})}if(currentJsRuntime$1==="NODE"&&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(...n){var o;try{return s(...n)}catch(i){if(!(i instanceof Error))throw i;const a=clarifyErrorMessage(i,(o=e.lastAsyncifyStackSource)==null?void 0:o.stack);if(e.lastAsyncifyStackSource&&(i.cause=e.lastAsyncifyStackSource),t.hasListeners()){t.dispatchEvent(new ErrorEvent("error",{error:i,message:a}));return}throw isExitCodeZero(i)||showCriticalErrorBox(a),i}}}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,13 +32,13 @@ 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 n=e[s];n==="."?e.splice(s,1):n===".."?(e.splice(s,1),r++):r&&(e.splice(s,1),r--)}if(t)for(;r;r--)e.unshift("..");return e}function splitShellCommand(e){let s=0,n="";const i=[];let o="";for(let l=0;l<e.length;l++){const c=e[l];c==="\\"?((e[l+1]==='"'||e[l+1]==="'")&&l++,o+=e[l]):s===0?c==='"'||c==="'"?(s=1,n=c):c.match(/\s/)?(o.trim().length&&i.push(o.trim()),o=c):i.length&&!o?o=i.pop()+c:o+=c:s===1&&(c===n?(s=0,n=""):o+=c)}return o&&i.push(o.trim()),i}function createSpawnHandler(e){return function(t,r=[],s={}){const n=new ChildProcess,i=new ProcessApi(n);return setTimeout(async()=>{let o=[];if(r.length)o=[t,...r];else if(typeof t=="string")o=splitShellCommand(t);else if(Array.isArray(t))o=t;else throw new Error("Invalid command ",t);await e(o,i,s),n.emit("spawn",!0)}),n}}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)}stdoutEnd(){this.childProcess.stdout.emit("end",{})}stderr(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stderr.emit("data",t)}stderrEnd(){this.childProcess.stderr.emit("end",{})}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,n)=>s+n.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(n){n.close()}});const r=e.getReader({mode:"byob"});let s=0;return new ReadableStream({async pull(n){const{value:i,done:o}=await r.read(new Uint8Array(t-s));if(o){r.releaseLock(),n.close();return}s+=i.length,n.enqueue(i),s>=t&&(r.releaseLock(),n.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:n=[]}={}){t=normalizePath(t);const i=[t];for(;i.length;){const o=i.pop();if(!o)return;const l=await e.listFiles(o);for(const c of l){const d=`${o}/${c}`;if(n.includes(d.substring(t.length+1)))continue;await e.isDir(d)?i.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,n="",i=0){this.httpStatusCode=t,this.headers=r,this.bytes=s,this.exitCode=i,this.errors=n}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,b;class PHPBrowser{constructor(t,r={}){u(this,E,void 0);u(this,b,void 0);this.requestHandler=t,h(this,E,{}),h(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 n=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:n.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("="),n=r.substring(0,s),i=r.substring(s+1).split(";")[0];a(this,E)[n]=i}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,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}async function encodeAsMultipart(e){const t=`----${Math.random().toString(36).slice(2)}`,r=`multipart/form-data; boundary=${t}`,s=new TextEncoder,n=[];for(const[c,d]of Object.entries(e))n.push(`--${t}\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 n=e[s];n==="."?e.splice(s,1):n===".."?(e.splice(s,1),r++):r&&(e.splice(s,1),r--)}if(t)for(;r;r--)e.unshift("..");return e}function splitShellCommand(e){let s=0,n="";const o=[];let i="";for(let a=0;a<e.length;a++){const c=e[a];c==="\\"?((e[a+1]==='"'||e[a+1]==="'")&&a++,i+=e[a]):s===0?c==='"'||c==="'"?(s=1,n=c):c.match(/\s/)?(i.trim().length&&o.push(i.trim()),i=c):o.length&&!i?i=o.pop()+c:i+=c:s===1&&(c===n?(s=0,n=""):i+=c)}return i&&o.push(i.trim()),o}function createSpawnHandler(e){return function(t,r=[],s={}){const n=new ChildProcess,o=new ProcessApi(n);return setTimeout(async()=>{let i=[];if(r.length)i=[t,...r];else if(typeof t=="string")i=splitShellCommand(t);else if(Array.isArray(t))i=t;else throw new Error("Invalid command ",t);await e(i,o,s),n.emit("spawn",!0)}),n}}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)}stdoutEnd(){this.childProcess.stdout.emit("end",{})}stderr(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stderr.emit("data",t)}stderrEnd(){this.childProcess.stderr.emit("end",{})}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,n)=>s+n.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(n){n.close()}});const r=e.getReader({mode:"byob"});let s=0;return new ReadableStream({async pull(n){const{value:o,done:i}=await r.read(new Uint8Array(t-s));if(i){r.releaseLock(),n.close();return}s+=o.length,n.enqueue(o),s>=t&&(r.releaseLock(),n.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:n=[]}={}){t=normalizePath(t);const o=[t];for(;o.length;){const i=o.pop();if(!i)return;const a=await e.listFiles(i);for(const c of a){const d=`${i}/${c}`;if(n.includes(d.substring(t.length+1)))continue;await e.isDir(d)?o.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,n="",o=0){this.httpStatusCode=t,this.headers=r,this.bytes=s,this.exitCode=o,this.errors=n}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,b;class PHPBrowser{constructor(t,r={}){u(this,E,void 0);u(this,b,void 0);this.requestHandler=t,h(this,E,{}),h(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"]),l(this,b).handleRedirects&&s.headers.location&&r<l(this,b).maxRedirects){const n=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:n.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("="),n=r.substring(0,s),o=r.substring(s+1).split(";")[0];l(this,E)[n]=o}catch(s){console.error(s)}}serializeCookies(){const t=[];for(const r in l(this,E))t.push(`${r}=${l(this,E)[r]}`);return t.join("; ")}}E=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}async function encodeAsMultipart(e){const t=`----${Math.random().toString(36).slice(2)}`,r=`multipart/form-data; boundary=${t}`,s=new TextEncoder,n=[];for(const[c,d]of Object.entries(e))n.push(`--${t}\r
36
36
  `),n.push(`Content-Disposition: form-data; name="${c}"`),d instanceof File&&n.push(`; filename="${d.name}"`),n.push(`\r
37
37
  `),d instanceof File&&(n.push("Content-Type: application/octet-stream"),n.push(`\r
38
38
  `)),n.push(`\r
39
39
  `),d instanceof File?n.push(await fileToUint8Array(d)):n.push(d),n.push(`\r
40
40
  `);n.push(`--${t}--\r
41
- `);const i=n.reduce((c,d)=>c+d.length,0),o=new Uint8Array(i);let l=0;for(const c of n)o.set(typeof c=="string"?s.encode(c):c,l),l+=c.length;return{bytes:o,contentType:r}}function fileToUint8Array(e){return new Promise(t=>{const r=new FileReader;r.onload=()=>{t(new Uint8Array(r.result))},r.readAsArrayBuffer(e)})}var m,x,U,v,H,_,F,R,B,Y,I,Z,L,K;class PHPRequestHandler{constructor(t,r={}){u(this,B);u(this,I);u(this,L);u(this,m,void 0);u(this,x,void 0);u(this,U,void 0);u(this,v,void 0);u(this,H,void 0);u(this,_,void 0);u(this,F,void 0);u(this,R,void 0);h(this,R,new Semaphore({concurrency:1}));const{documentRoot:s="/www/",absoluteUrl:n=typeof location=="object"?location==null?void 0:location.href:""}=r;this.php=t,h(this,m,s);const i=new URL(n);h(this,U,i.hostname),h(this,v,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,x,(i.protocol||"").replace(":",""));const o=a(this,v)!==443&&a(this,v)!==80;h(this,H,[a(this,U),o?`:${a(this,v)}`:""].join("")),h(this,_,i.pathname.replace(/\/+$/,"")),h(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,R).running>0}get absoluteUrl(){return a(this,F)}get documentRoot(){return a(this,m)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url,r?void 0:DEFAULT_BASE_URL),n=removePathPrefix(s.pathname,a(this,_)),i=`${a(this,m)}${n}`;return seemsLikeAPHPRequestHandlerPath(i)?await p(this,I,Z).call(this,t,s):p(this,B,Y).call(this,i)}}m=new WeakMap,x=new WeakMap,U=new WeakMap,v=new WeakMap,H=new WeakMap,_=new WeakMap,F=new WeakMap,R=new WeakMap,B=new WeakSet,Y=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)},I=new WeakSet,Z=async function(t,r){var n,i;if(a(this,R).running>0&&((n=t.headers)==null?void 0:n["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,m)),this.php.addServerGlobalEntry("HTTPS",a(this,F).startsWith("https://")?"on":"");let o="GET";const l={host:a(this,H),...normalizeHeaders(t.headers||{})};let c=t.body;if(typeof c=="object"&&!(c instanceof Uint8Array)){o="POST";const{bytes:f,contentType:k}=await encodeAsMultipart(c);c=f,l["content-type"]=k}let d;try{let f=r.pathname;if((i=t.headers)!=null&&i["x-rewrite-url"])try{f=new URL(t.headers["x-rewrite-url"]).pathname}catch{}d=p(this,L,K).call(this,f)}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:c,scriptPath:d,headers:l})}finally{s()}},L=new WeakSet,K=function(t){let r=removePathPrefix(t,a(this,_));r.includes(".php")?r=r.split(".php")[0]+".php":this.php.isDir(`${a(this,m)}${r}`)?(r.endsWith("/")||(r=`${r}/`),r=`${r}index.php`):r="/index.php";const s=`${a(this,m)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};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,n){const i=n.value;n.value=function(...o){try{return i.apply(this,o)}catch(l){const c=typeof l=="object"?l==null?void 0:l.errno:null;if(c in FileErrorCodes){const d=FileErrorCodes[c],f=typeof o[0]=="string"?o[0]:null,k=f!==null?e.replaceAll("{path}",f):e;throw new Error(`${k}: ${d}`,{cause:l})}throw l}}}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(e,t={}){const[r,s,n]=makePromise(),i=e.init(currentJsRuntime,{onAbort(l){n(l),console.error(l)},ENV:{},locateFile:l=>l,...t,noInitialRun:!0,onRuntimeInitialized(){t.onRuntimeInitialized&&t.onRuntimeInitialized(),s()}});await r;const o=++lastRuntimeId;return i.id=o,i.originalExit=i._exit,i._exit=function(l){return loadedRuntimes.delete(o),i.originalExit(l)},i[RuntimeId]=o,loadedRuntimes.set(o,i),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 n=s>1?void 0:s?__getOwnPropDesc(t,r):t,i=e.length-1,o;i>=0;i--)(o=e[i])&&(n=(s?o(t,r,n):o(n))||n);return s&&n&&__defProp(t,r,n),n};const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");var S,T,A,y,w,g,P,C,N,X,M,ee,q,te,O,re,D,se,$,ne,j,ie,z,oe,W,ae,G,le,V,ce,Q,ue;class BasePHP{constructor(e,t){u(this,N);u(this,M);u(this,q);u(this,O);u(this,D);u(this,$);u(this,j);u(this,z);u(this,W);u(this,G);u(this,V);u(this,Q);u(this,S,void 0);u(this,T,void 0);u(this,A,void 0);u(this,y,void 0);u(this,w,void 0);u(this,g,void 0);u(this,P,void 0);u(this,C,void 0);h(this,S,[]),h(this,y,!1),h(this,w,null),h(this,g,{}),h(this,P,new Map),h(this,C,[]),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,P).has(e)||a(this,P).set(e,new Set),a(this,P).get(e).add(t)}removeEventListener(e,t){var r;(r=a(this,P).get(e))==null||r.delete(t)}dispatchEvent(e){const t=a(this,P).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){a(this,C).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,C)){const n=await s(r);if(n)return n}return""},h(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?");h(this,A,e)}setPhpIniPath(e){if(a(this,y))throw new Error("Cannot set PHP ini path after calling run().");h(this,T,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(a(this,y))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{if(a(this,y)||(p(this,N,X).call(this),h(this,y,!0)),e.scriptPath&&!this.fileExists(e.scriptPath))throw new Error(`The script path "${e.scriptPath}" does not exist.`);p(this,z,oe).call(this,e.scriptPath||""),p(this,q,te).call(this,e.relativeUri||""),p(this,D,se).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";p(this,O,re).call(this,n,e.protocol||"http"),p(this,$,ne).call(this,s),e.body&&(r=p(this,j,ie).call(this,e.body)),typeof e.code=="string"&&p(this,V,ce).call(this," ?>"+e.code),p(this,W,ae).call(this);const i=e.env||{};for(const l in i)p(this,G,le).call(this,l,i[l]);const o=await p(this,Q,ue).call(this);if(e.throwOnError&&o.exitCode!==0){const l={stdout:o.text,stderr:o.errors};console.warn("PHP.run() output was:",l);const c=new Error(`PHP.run() failed with exit code ${o.exitCode} and the following output: `+o.errors);throw c.output=l,console.error(c),c}return o}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("/internal/consts.json")&&this.readFileAsText("/internal/consts.json")||"{}")}catch{}this.writeFile("/internal/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(n=>`${s}/${n}`)}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,T)&&this.setPhpIniPath(a(this,T)),a(this,A)&&this.setSapiName(a(this,A)),this.requestHandler){const r=this.documentRoot;copyFS(t,this[__private__dont__use].FS,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}h(this,y,!1),h(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,T=new WeakMap,A=new WeakMap,y=new WeakMap,w=new WeakMap,g=new WeakMap,P=new WeakMap,C=new WeakMap,N=new WeakSet,X=function(){if(this.setPhpIniEntry("auto_prepend_file","/internal/consts.php"),this.fileExists("/internal/consts.php")||this.writeFile("/internal/consts.php",`<?php
41
+ `);const o=n.reduce((c,d)=>c+d.length,0),i=new Uint8Array(o);let a=0;for(const c of n)i.set(typeof c=="string"?s.encode(c):c,a),a+=c.length;return{bytes:i,contentType:r}}function fileToUint8Array(e){return new Promise(t=>{const r=new FileReader;r.onload=()=>{t(new Uint8Array(r.result))},r.readAsArrayBuffer(e)})}var m,x,k,R,H,f,F,v,U,Q,B,Y,I,Z;class PHPRequestHandler{constructor(t,r={}){u(this,U);u(this,B);u(this,I);u(this,m,void 0);u(this,x,void 0);u(this,k,void 0);u(this,R,void 0);u(this,H,void 0);u(this,f,void 0);u(this,F,void 0);u(this,v,void 0);h(this,v,new Semaphore({concurrency:1}));const{documentRoot:s="/www/",absoluteUrl:n=typeof location=="object"?location==null?void 0:location.href:"",rewriteRules:o=[]}=r;this.php=t,h(this,m,s);const i=new URL(n);h(this,k,i.hostname),h(this,R,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,x,(i.protocol||"").replace(":",""));const a=l(this,R)!==443&&l(this,R)!==80;h(this,H,[l(this,k),a?`:${l(this,R)}`:""].join("")),h(this,f,i.pathname.replace(/\/+$/,"")),h(this,F,[`${l(this,x)}://`,l(this,H),l(this,f)].join("")),this.rewriteRules=o}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(l(this,f))&&(r.pathname=r.pathname.slice(l(this,f).length)),toRelativeUrl(r)}get isRequestRunning(){return l(this,v).running>0}get absoluteUrl(){return l(this,F)}get documentRoot(){return l(this,m)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url,r?void 0:DEFAULT_BASE_URL),n=applyRewriteRules(removePathPrefix(s.pathname,l(this,f)),this.rewriteRules),o=`${l(this,m)}${n}`;return seemsLikeAPHPRequestHandlerPath(o)?await p(this,B,Y).call(this,t,s):p(this,U,Q).call(this,o)}}m=new WeakMap,x=new WeakMap,k=new WeakMap,R=new WeakMap,H=new WeakMap,f=new WeakMap,F=new WeakMap,v=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)},B=new WeakSet,Y=async function(t,r){var n;if(l(this,v).running>0&&((n=t.headers)==null?void 0:n["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 l(this,v).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",l(this,m)),this.php.addServerGlobalEntry("HTTPS",l(this,F).startsWith("https://")?"on":"");let o="GET";const i={host:l(this,H),...normalizeHeaders(t.headers||{})};let a=t.body;if(typeof a=="object"&&!(a instanceof Uint8Array)){o="POST";const{bytes:d,contentType:_}=await encodeAsMultipart(a);a=d,i["content-type"]=_}let c;try{c=p(this,I,Z).call(this,r.pathname)}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),l(this,f)),protocol:l(this,x),method:t.method||o,body:a,scriptPath:c,headers:i})}finally{s()}},I=new WeakSet,Z=function(t){let r=removePathPrefix(t,l(this,f));r=applyRewriteRules(r,this.rewriteRules),r.includes(".php")?r=r.split(".php")[0]+".php":this.php.isDir(`${l(this,m)}${r}`)?(r.endsWith("/")||(r=`${r}/`),r=`${r}index.php`):r="/index.php";const s=`${l(this,m)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};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(".")}function applyRewriteRules(e,t){for(const r of t)if(new RegExp(r.match).test(e))return e.replace(r.match,r.replacement);return e}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,n){const o=n.value;n.value=function(...i){try{return o.apply(this,i)}catch(a){const c=typeof a=="object"?a==null?void 0:a.errno:null;if(c in FileErrorCodes){const d=FileErrorCodes[c],_=typeof i[0]=="string"?i[0]:null,ue=_!==null?e.replaceAll("{path}",_):e;throw new Error(`${ue}: ${d}`,{cause:a})}throw a}}}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(e,t={}){const[r,s,n]=makePromise(),o=e.init(currentJsRuntime,{onAbort(a){n(a),console.error(a)},ENV:{},locateFile:a=>a,...t,noInitialRun:!0,onRuntimeInitialized(){t.onRuntimeInitialized&&t.onRuntimeInitialized(),s()}});await r;const i=++lastRuntimeId;return o.id=i,o.originalExit=o._exit,o._exit=function(a){return loadedRuntimes.delete(i),o.originalExit(a)},o[RuntimeId]=i,loadedRuntimes.set(i,o),i}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 n=s>1?void 0:s?__getOwnPropDesc(t,r):t,o=e.length-1,i;o>=0;o--)(i=e[o])&&(n=(s?i(t,r,n):i(n))||n);return s&&n&&__defProp(t,r,n),n};const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");var S,T,A,y,w,g,P,C,L,K,N,X,O,ee,q,te,M,re,D,se,$,ne,j,ie,W,oe,z,ae,G,le,V,ce;class BasePHP{constructor(e,t){u(this,L);u(this,N);u(this,O);u(this,q);u(this,M);u(this,D);u(this,$);u(this,j);u(this,W);u(this,z);u(this,G);u(this,V);u(this,S,void 0);u(this,T,void 0);u(this,A,void 0);u(this,y,void 0);u(this,w,void 0);u(this,g,void 0);u(this,P,void 0);u(this,C,void 0);h(this,S,[]),h(this,y,!1),h(this,w,null),h(this,g,{}),h(this,P,new Map),h(this,C,[]),this.semaphore=new Semaphore({concurrency:1}),e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new PHPBrowser(new PHPRequestHandler(this,t)))}addEventListener(e,t){l(this,P).has(e)||l(this,P).set(e,new Set),l(this,P).get(e).add(t)}removeEventListener(e,t){var r;(r=l(this,P).get(e))==null||r.delete(t)}dispatchEvent(e){const t=l(this,P).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){l(this,C).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 l(this,C)){const n=await s(r);if(n)return n}return""},h(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?");h(this,A,e)}setPhpIniPath(e){if(l(this,y))throw new Error("Cannot set PHP ini path after calling run().");h(this,T,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(l(this,y))throw new Error("Cannot set PHP ini entries after calling run().");l(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{if(l(this,y)||(p(this,L,K).call(this),h(this,y,!0)),e.scriptPath&&!this.fileExists(e.scriptPath))throw new Error(`The script path "${e.scriptPath}" does not exist.`);p(this,j,ie).call(this,e.scriptPath||""),p(this,O,ee).call(this,e.relativeUri||""),p(this,M,re).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";p(this,q,te).call(this,n,e.protocol||"http"),p(this,D,se).call(this,s),e.body&&(r=p(this,$,ne).call(this,e.body)),typeof e.code=="string"&&p(this,G,le).call(this," ?>"+e.code),p(this,W,oe).call(this);const o=e.env||{};for(const a in o)p(this,z,ae).call(this,a,o[a]);const i=await p(this,V,ce).call(this);if(e.throwOnError&&i.exitCode!==0){const a={stdout:i.text,stderr:i.errors};console.warn("PHP.run() output was:",a);const c=new Error(`PHP.run() failed with exit code ${i.exitCode} and the following output: `+i.errors);throw c.output=a,console.error(c),c}return i}catch(s){throw this.dispatchEvent({type:"request.error",error:s}),s}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){l(this,g)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/internal/consts.json")&&this.readFileAsText("/internal/consts.json")||"{}")}catch{}this.writeFile("/internal/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(n=>`${s}/${n}`)}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),l(this,T)&&this.setPhpIniPath(l(this,T)),l(this,A)&&this.setSapiName(l(this,A)),this.requestHandler){const r=this.documentRoot;copyFS(t,this[__private__dont__use].FS,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}h(this,y,!1),h(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,T=new WeakMap,A=new WeakMap,y=new WeakMap,w=new WeakMap,g=new WeakMap,P=new WeakMap,C=new WeakMap,L=new WeakSet,K=function(){if(this.setPhpIniEntry("auto_prepend_file","/internal/consts.php"),this.fileExists("/internal/consts.php")||this.writeFile("/internal/consts.php",`<?php
42
42
  if(file_exists('/internal/consts.json')) {
43
43
  $consts = json_decode(file_get_contents('/internal/consts.json'), true);
44
44
  foreach ($consts as $const => $value) {
@@ -46,7 +46,7 @@ ${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
46
46
  define($const, $value);
47
47
  }
48
48
  }
49
- }`),a(this,S).length>0){const e=a(this,S).map(([t,r])=>`${t}=${r}`).join(`
49
+ }`),l(this,S).length>0){const e=l(this,S).map(([t,r])=>`${t}=${r}`).join(`
50
50
  `)+`
51
51
 
52
- `;this[__private__dont__use].ccall("wasm_set_phpini_entries",null,[STRING],[e])}this[__private__dont__use].ccall("php_wasm_init",null,[],[])},M=new WeakSet,ee=function(){const e="/internal/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 n=s.indexOf(": "),i=s.substring(0,n).toLowerCase(),o=s.substring(n+2);i in r||(r[i]=[]),r[i].push(o)}return{headers:r,httpStatusCode:t.status}},q=new WeakSet,te=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])}},O=new WeakSet,re=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")},D=new WeakSet,se=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},$=new WeakSet,ne=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])}},j=new WeakSet,ie=function(e){let t,r;typeof e=="string"?(console.warn("Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"),r=this[__private__dont__use].lengthBytesUTF8(e),t=r+1):(r=e.byteLength,t=e.byteLength);const s=this[__private__dont__use].malloc(t);if(!s)throw new Error("Could not allocate memory for the request body.");return typeof e=="string"?this[__private__dont__use].stringToUTF8(e,s,t+1):this[__private__dont__use].HEAPU8.set(e,s),this[__private__dont__use].ccall("wasm_set_request_body",null,[NUMBER],[s]),this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[r]),s},z=new WeakSet,oe=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},W=new WeakSet,ae=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]])},G=new WeakSet,le=function(e,t){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[e,t])},V=new WeakSet,ce=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},Q=new WeakSet,ue=async function(){var n;let e,t;try{e=await new Promise((i,o)=>{var c;t=d=>{console.error(d),console.error(d.error);const f=new Error("Rethrown");f.cause=d.error,f.betterMessage=d.message,o(f)},(c=a(this,w))==null||c.addEventListener("error",t);const l=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return l instanceof Promise?l.then(i,o):i(l)})}catch(i){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=i,l="betterMessage"in o?o.betterMessage:o.message,c=new Error(l);throw c.cause=o,console.error(c),c}finally{(n=a(this,w))==null||n.removeEventListener("error",t),h(this,g,{})}const{headers:r,httpStatusCode:s}=p(this,M,ee).call(this);return new PHPResponse(s,r,this.readFileAsBuffer("/internal/stdout"),this.readFileAsText("/internal/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 copyFS(e,t,r){let s;try{s=e.lookupPath(r)}catch{return}if(!("contents"in s.node))return;if(!e.isDir(s.node.mode)){t.writeFile(r,e.readFile(r));return}t.mkdirTree(r);const n=e.readdir(r).filter(i=>i!=="."&&i!=="..");for(const i of n)copyFS(e,t,joinPaths(r,i))}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 n(){if(++s<r)return;s=0;const i=await e.semaphore.acquire();try{e.hotSwapPHPRuntime(await t())}finally{i()}}return e.addEventListener("request.end",n),function(){e.removeEventListener("request.end",n)}}async function writeFiles(e,t,r,{rmRoot:s=!1}={}){s&&await e.isDir(t)&&await e.rmdir(t,{recursive:!0});for(const[n,i]of Object.entries(r)){const o=joinPaths(t,n);await e.fileExists(dirname(o))||await e.mkdir(dirname(o)),await e.writeFile(o,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.writeFiles=writeFiles;exports.writeFilesStreamToPhp=writeFilesStreamToPhp;
52
+ `;this[__private__dont__use].ccall("wasm_set_phpini_entries",null,[STRING],[e])}this[__private__dont__use].ccall("php_wasm_init",null,[],[])},N=new WeakSet,X=function(){const e="/internal/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 n=s.indexOf(": "),o=s.substring(0,n).toLowerCase(),i=s.substring(n+2);o in r||(r[o]=[]),r[o].push(i)}return{headers:r,httpStatusCode:t.status}},O=new WeakSet,ee=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,te=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")},M=new WeakSet,re=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},D=new WeakSet,se=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])}},$=new WeakSet,ne=function(e){let t,r;typeof e=="string"?(console.warn("Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"),r=this[__private__dont__use].lengthBytesUTF8(e),t=r+1):(r=e.byteLength,t=e.byteLength);const s=this[__private__dont__use].malloc(t);if(!s)throw new Error("Could not allocate memory for the request body.");return typeof e=="string"?this[__private__dont__use].stringToUTF8(e,s,t+1):this[__private__dont__use].HEAPU8.set(e,s),this[__private__dont__use].ccall("wasm_set_request_body",null,[NUMBER],[s]),this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[r]),s},j=new WeakSet,ie=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},W=new WeakSet,oe=function(){for(const e in l(this,g))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,l(this,g)[e]])},z=new WeakSet,ae=function(e,t){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[e,t])},G=new WeakSet,le=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},V=new WeakSet,ce=async function(){var n;let e,t;try{e=await new Promise((o,i)=>{var c;t=d=>{console.error(d),console.error(d.error);const _=new Error("Rethrown");_.cause=d.error,_.betterMessage=d.message,i(_)},(c=l(this,w))==null||c.addEventListener("error",t);const a=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return a instanceof Promise?a.then(o,i):o(a)})}catch(o){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 i=o,a="betterMessage"in i?i.betterMessage:i.message,c=new Error(a);throw c.cause=i,console.error(c),c}finally{(n=l(this,w))==null||n.removeEventListener("error",t),h(this,g,{})}const{headers:r,httpStatusCode:s}=p(this,N,X).call(this);return new PHPResponse(s,r,this.readFileAsBuffer("/internal/stdout"),this.readFileAsText("/internal/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 copyFS(e,t,r){let s;try{s=e.lookupPath(r)}catch{return}if(!("contents"in s.node))return;if(!e.isDir(s.node.mode)){t.writeFile(r,e.readFile(r));return}t.mkdirTree(r);const n=e.readdir(r).filter(o=>o!=="."&&o!=="..");for(const o of n)copyFS(e,t,joinPaths(r,o))}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 n(){if(++s<r)return;s=0;const o=await e.semaphore.acquire();try{e.hotSwapPHPRuntime(await t())}finally{o()}}return e.addEventListener("request.end",n),function(){e.removeEventListener("request.end",n)}}async function writeFiles(e,t,r,{rmRoot:s=!1}={}){s&&await e.isDir(t)&&await e.rmdir(t,{recursive:!0});for(const[n,o]of Object.entries(r)){const i=joinPaths(t,n);await e.fileExists(dirname(i))||await e.mkdir(dirname(i)),await e.writeFile(i,o)}}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.applyRewriteRules=applyRewriteRules;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
@@ -2,62 +2,72 @@ var J = (e, t, r) => {
2
2
  if (!t.has(e))
3
3
  throw TypeError("Cannot " + r);
4
4
  };
5
- var a = (e, t, r) => (J(e, t, "read from private field"), r ? r.call(e) : t.get(e)), u = (e, t, r) => {
5
+ var l = (e, t, r) => (J(e, t, "read from private field"), r ? r.call(e) : t.get(e)), u = (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
9
  }, h = (e, t, r, s) => (J(e, t, "write to private field"), s ? s.call(e, r) : t.set(e, r), r);
10
10
  var f = (e, t, r) => (J(e, t, "access private method"), r);
11
- if (typeof File > "u") {
12
- class e extends Blob {
13
- constructor(r, s, n) {
14
- super(r);
15
- let i;
16
- n != null && n.lastModified && (i = /* @__PURE__ */ new Date()), (!i || isNaN(i.getFullYear())) && (i = /* @__PURE__ */ new Date()), this.lastModifiedDate = i, this.lastModified = i.getMilliseconds(), this.name = s || "";
11
+ const currentJsRuntime$1 = function() {
12
+ var e;
13
+ return typeof process < "u" && ((e = process.release) == null ? void 0 : e.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : (
14
+ // @ts-ignore
15
+ typeof WorkerGlobalScope < "u" && // @ts-ignore
16
+ self instanceof WorkerGlobalScope ? "WORKER" : "NODE"
17
+ );
18
+ }();
19
+ if (currentJsRuntime$1 === "NODE") {
20
+ let e = function(r) {
21
+ return new Promise(function(s, n) {
22
+ r.onload = r.onerror = function(o) {
23
+ r.onload = r.onerror = null, o.type === "load" ? s(r.result) : n(new Error("Failed to read the blob/file"));
24
+ };
25
+ });
26
+ }, t = function() {
27
+ const r = new Uint8Array([1, 2, 3, 4]), n = new File([r], "test").stream();
28
+ try {
29
+ return n.getReader({ mode: "byob" }), !0;
30
+ } catch {
31
+ return !1;
17
32
  }
18
- }
19
- global.File = e;
20
- }
21
- function asPromise(e) {
22
- return new Promise(function(t, r) {
23
- e.onload = e.onerror = function(s) {
24
- e.onload = e.onerror = null, s.type === "load" ? t(e.result) : r(new Error("Failed to read the blob/file"));
25
- };
26
- });
27
- }
28
- typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
29
- const t = new FileReader();
30
- return t.readAsArrayBuffer(this), asPromise(t);
31
- });
32
- typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
33
- const t = new FileReader();
34
- return t.readAsText(this), asPromise(t);
35
- });
36
- function isByobSupported() {
37
- const e = new Uint8Array([1, 2, 3, 4]), r = new File([e], "test").stream();
38
- try {
39
- return r.getReader({ mode: "byob" }), !0;
40
- } catch {
41
- return !1;
42
- }
43
- }
44
- (typeof Blob.prototype.stream > "u" || !isByobSupported()) && (Blob.prototype.stream = function() {
45
- let e = 0;
46
- const t = this;
47
- return new ReadableStream({
48
- type: "bytes",
49
- // 0.5 MB seems like a reasonable chunk size, let's adjust
50
- // this if needed.
51
- autoAllocateChunkSize: 512 * 1024,
52
- async pull(r) {
53
- const s = r.byobRequest.view, i = await t.slice(e, e + s.byteLength).arrayBuffer(), o = new Uint8Array(i);
54
- new Uint8Array(s.buffer).set(o);
55
- const l = o.byteLength;
56
- r.byobRequest.respond(l), e += l, e >= t.size && r.close();
33
+ };
34
+ if (typeof File > "u") {
35
+ class r extends Blob {
36
+ constructor(n, o, i) {
37
+ super(n);
38
+ let a;
39
+ i != null && i.lastModified && (a = /* @__PURE__ */ new Date()), (!a || isNaN(a.getFullYear())) && (a = /* @__PURE__ */ new Date()), this.lastModifiedDate = a, this.lastModified = a.getMilliseconds(), this.name = o || "";
40
+ }
57
41
  }
42
+ global.File = r;
43
+ }
44
+ typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
45
+ const s = new FileReader();
46
+ return s.readAsArrayBuffer(this), e(s);
47
+ }), typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
48
+ const s = new FileReader();
49
+ return s.readAsText(this), e(s);
50
+ }), (typeof Blob.prototype.stream > "u" || !t()) && (Blob.prototype.stream = function() {
51
+ let r = 0;
52
+ const s = this;
53
+ return new ReadableStream({
54
+ type: "bytes",
55
+ // 0.5 MB seems like a reasonable chunk size, let's adjust
56
+ // this if needed.
57
+ autoAllocateChunkSize: 512 * 1024,
58
+ async pull(n) {
59
+ const o = n.byobRequest.view, a = await s.slice(
60
+ r,
61
+ r + o.byteLength
62
+ ).arrayBuffer(), c = new Uint8Array(a);
63
+ new Uint8Array(o.buffer).set(c);
64
+ const d = c.byteLength;
65
+ n.byobRequest.respond(d), r += d, r >= s.size && n.close();
66
+ }
67
+ });
58
68
  });
59
- });
60
- if (typeof CustomEvent > "u") {
69
+ }
70
+ if (currentJsRuntime$1 === "NODE" && typeof CustomEvent > "u") {
61
71
  class e extends Event {
62
72
  constructor(r, s = {}) {
63
73
  super(r, s), this.detail = s.detail;
@@ -115,26 +125,26 @@ function improveWASMErrorReporting(e) {
115
125
  if (typeof e.asm[r] == "function") {
116
126
  const s = e.asm[r];
117
127
  e.asm[r] = function(...n) {
118
- var i;
128
+ var o;
119
129
  try {
120
130
  return s(...n);
121
- } catch (o) {
122
- if (!(o instanceof Error))
123
- throw o;
124
- const l = clarifyErrorMessage(
125
- o,
126
- (i = e.lastAsyncifyStackSource) == null ? void 0 : i.stack
131
+ } catch (i) {
132
+ if (!(i instanceof Error))
133
+ throw i;
134
+ const a = clarifyErrorMessage(
135
+ i,
136
+ (o = e.lastAsyncifyStackSource) == null ? void 0 : o.stack
127
137
  );
128
- if (e.lastAsyncifyStackSource && (o.cause = e.lastAsyncifyStackSource), t.hasListeners()) {
138
+ if (e.lastAsyncifyStackSource && (i.cause = e.lastAsyncifyStackSource), t.hasListeners()) {
129
139
  t.dispatchEvent(
130
140
  new ErrorEvent("error", {
131
- error: o,
132
- message: l
141
+ error: i,
142
+ message: a
133
143
  })
134
144
  );
135
145
  return;
136
146
  }
137
- throw isExitCodeZero(o) || showCriticalErrorBox(l), o;
147
+ throw isExitCodeZero(i) || showCriticalErrorBox(a), i;
138
148
  }
139
149
  };
140
150
  }
@@ -276,28 +286,28 @@ function normalizePathsArray(e, t) {
276
286
  }
277
287
  function splitShellCommand(e) {
278
288
  let s = 0, n = "";
279
- const i = [];
280
- let o = "";
281
- for (let l = 0; l < e.length; l++) {
282
- const c = e[l];
283
- c === "\\" ? ((e[l + 1] === '"' || e[l + 1] === "'") && l++, o += e[l]) : s === 0 ? c === '"' || c === "'" ? (s = 1, n = c) : c.match(/\s/) ? (o.trim().length && i.push(o.trim()), o = c) : i.length && !o ? o = i.pop() + c : o += c : s === 1 && (c === n ? (s = 0, n = "") : o += c);
289
+ const o = [];
290
+ let i = "";
291
+ for (let a = 0; a < e.length; a++) {
292
+ const c = e[a];
293
+ c === "\\" ? ((e[a + 1] === '"' || e[a + 1] === "'") && a++, i += e[a]) : s === 0 ? c === '"' || c === "'" ? (s = 1, n = c) : c.match(/\s/) ? (i.trim().length && o.push(i.trim()), i = c) : o.length && !i ? i = o.pop() + c : i += c : s === 1 && (c === n ? (s = 0, n = "") : i += c);
284
294
  }
285
- return o && i.push(o.trim()), i;
295
+ return i && o.push(i.trim()), o;
286
296
  }
287
297
  function createSpawnHandler(e) {
288
298
  return function(t, r = [], s = {}) {
289
- const n = new ChildProcess(), i = new ProcessApi(n);
299
+ const n = new ChildProcess(), o = new ProcessApi(n);
290
300
  return setTimeout(async () => {
291
- let o = [];
301
+ let i = [];
292
302
  if (r.length)
293
- o = [t, ...r];
303
+ i = [t, ...r];
294
304
  else if (typeof t == "string")
295
- o = splitShellCommand(t);
305
+ i = splitShellCommand(t);
296
306
  else if (Array.isArray(t))
297
- o = t;
307
+ i = t;
298
308
  else
299
309
  throw new Error("Invalid command ", t);
300
- await e(o, i, s), n.emit("spawn", !0);
310
+ await e(i, o, s), n.emit("spawn", !0);
301
311
  }), n;
302
312
  };
303
313
  }
@@ -398,14 +408,14 @@ function limitBytes(e, t) {
398
408
  let s = 0;
399
409
  return new ReadableStream({
400
410
  async pull(n) {
401
- const { value: i, done: o } = await r.read(
411
+ const { value: o, done: i } = await r.read(
402
412
  new Uint8Array(t - s)
403
413
  );
404
- if (o) {
414
+ if (i) {
405
415
  r.releaseLock(), n.close();
406
416
  return;
407
417
  }
408
- s += i.length, n.enqueue(i), s >= t && (r.releaseLock(), n.close());
418
+ s += o.length, n.enqueue(o), s >= t && (r.releaseLock(), n.close());
409
419
  },
410
420
  cancel() {
411
421
  r.cancel();
@@ -487,17 +497,17 @@ async function* iteratePhpFiles(e, t, {
487
497
  exceptPaths: n = []
488
498
  } = {}) {
489
499
  t = normalizePath(t);
490
- const i = [t];
491
- for (; i.length; ) {
492
- const o = i.pop();
493
- if (!o)
500
+ const o = [t];
501
+ for (; o.length; ) {
502
+ const i = o.pop();
503
+ if (!i)
494
504
  return;
495
- const l = await e.listFiles(o);
496
- for (const c of l) {
497
- const d = `${o}/${c}`;
505
+ const a = await e.listFiles(i);
506
+ for (const c of a) {
507
+ const d = `${i}/${c}`;
498
508
  if (n.includes(d.substring(t.length + 1)))
499
509
  continue;
500
- await e.isDir(d) ? i.push(d) : yield new StreamedFile(
510
+ await e.isDir(d) ? o.push(d) : yield new StreamedFile(
501
511
  streamReadFileFromPHP(e, d),
502
512
  r ? joinPaths(
503
513
  s || "",
@@ -519,8 +529,8 @@ function writeFilesStreamToPhp(e, t) {
519
529
  });
520
530
  }
521
531
  class PHPResponse {
522
- constructor(t, r, s, n = "", i = 0) {
523
- this.httpStatusCode = t, this.headers = r, this.bytes = s, this.exitCode = i, this.errors = n;
532
+ constructor(t, r, s, n = "", o = 0) {
533
+ this.httpStatusCode = t, this.headers = r, this.bytes = s, this.exitCode = o, this.errors = n;
524
534
  }
525
535
  static fromRawData(t) {
526
536
  return new PHPResponse(
@@ -608,7 +618,7 @@ class PHPBrowser {
608
618
  cookie: this.serializeCookies()
609
619
  }
610
620
  });
611
- if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), a(this, b).handleRedirects && s.headers.location && r < a(this, b).maxRedirects) {
621
+ if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), l(this, b).handleRedirects && s.headers.location && r < l(this, b).maxRedirects) {
612
622
  const n = new URL(
613
623
  s.headers.location[0],
614
624
  this.requestHandler.absoluteUrl
@@ -645,16 +655,16 @@ class PHPBrowser {
645
655
  try {
646
656
  if (!r.includes("="))
647
657
  continue;
648
- const s = r.indexOf("="), n = r.substring(0, s), i = r.substring(s + 1).split(";")[0];
649
- a(this, E)[n] = i;
658
+ const s = r.indexOf("="), n = r.substring(0, s), o = r.substring(s + 1).split(";")[0];
659
+ l(this, E)[n] = o;
650
660
  } catch (s) {
651
661
  console.error(s);
652
662
  }
653
663
  }
654
664
  serializeCookies() {
655
665
  const t = [];
656
- for (const r in a(this, E))
657
- t.push(`${r}=${a(this, E)[r]}`);
666
+ for (const r in l(this, E))
667
+ t.push(`${r}=${l(this, E)[r]}`);
658
668
  return t.join("; ");
659
669
  }
660
670
  }
@@ -680,14 +690,14 @@ async function encodeAsMultipart(e) {
680
690
  `);
681
691
  n.push(`--${t}--\r
682
692
  `);
683
- const i = n.reduce((c, d) => c + d.length, 0), o = new Uint8Array(i);
684
- let l = 0;
693
+ const o = n.reduce((c, d) => c + d.length, 0), i = new Uint8Array(o);
694
+ let a = 0;
685
695
  for (const c of n)
686
- o.set(
696
+ i.set(
687
697
  typeof c == "string" ? s.encode(c) : c,
688
- l
689
- ), l += c.length;
690
- return { bytes: o, contentType: r };
698
+ a
699
+ ), a += c.length;
700
+ return { bytes: i, contentType: r };
691
701
  }
692
702
  function fileToUint8Array(e) {
693
703
  return new Promise((t) => {
@@ -697,7 +707,7 @@ function fileToUint8Array(e) {
697
707
  }, r.readAsArrayBuffer(e);
698
708
  });
699
709
  }
700
- var m, H, k, v, x, _, F, R, B, Y, I, Z, L, K;
710
+ var m, H, k, v, F, p, x, R, U, Q, B, Y, I, K;
701
711
  class PHPRequestHandler {
702
712
  /**
703
713
  * @param php - The PHP instance.
@@ -710,7 +720,7 @@ class PHPRequestHandler {
710
720
  * @param fsPath - Absolute path of the static file to serve.
711
721
  * @returns The response.
712
722
  */
713
- u(this, B);
723
+ u(this, U);
714
724
  /**
715
725
  * Runs the requested PHP file with all the request and $_SERVER
716
726
  * superglobals populated.
@@ -718,7 +728,7 @@ class PHPRequestHandler {
718
728
  * @param request - The request.
719
729
  * @returns The response.
720
730
  */
721
- u(this, I);
731
+ u(this, B);
722
732
  /**
723
733
  * Resolve the requested path to the filesystem path of the requested PHP file.
724
734
  *
@@ -728,32 +738,33 @@ class PHPRequestHandler {
728
738
  * @throws {Error} If the requested path doesn't exist.
729
739
  * @returns The resolved filesystem path.
730
740
  */
731
- u(this, L);
741
+ u(this, I);
732
742
  u(this, m, void 0);
733
743
  u(this, H, void 0);
734
744
  u(this, k, void 0);
735
745
  u(this, v, void 0);
736
- u(this, x, void 0);
737
- u(this, _, void 0);
738
746
  u(this, F, void 0);
747
+ u(this, p, void 0);
748
+ u(this, x, void 0);
739
749
  u(this, R, void 0);
740
750
  h(this, R, new Semaphore({ concurrency: 1 }));
741
751
  const {
742
752
  documentRoot: s = "/www/",
743
- absoluteUrl: n = typeof location == "object" ? location == null ? void 0 : location.href : ""
753
+ absoluteUrl: n = typeof location == "object" ? location == null ? void 0 : location.href : "",
754
+ rewriteRules: o = []
744
755
  } = r;
745
756
  this.php = t, h(this, m, s);
746
757
  const i = new URL(n);
747
758
  h(this, k, i.hostname), h(this, v, i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80), h(this, H, (i.protocol || "").replace(":", ""));
748
- const o = a(this, v) !== 443 && a(this, v) !== 80;
749
- h(this, x, [
750
- a(this, k),
751
- o ? `:${a(this, v)}` : ""
752
- ].join("")), h(this, _, i.pathname.replace(/\/+$/, "")), h(this, F, [
753
- `${a(this, H)}://`,
754
- a(this, x),
755
- a(this, _)
756
- ].join(""));
759
+ const a = l(this, v) !== 443 && l(this, v) !== 80;
760
+ h(this, F, [
761
+ l(this, k),
762
+ a ? `:${l(this, v)}` : ""
763
+ ].join("")), h(this, p, i.pathname.replace(/\/+$/, "")), h(this, x, [
764
+ `${l(this, H)}://`,
765
+ l(this, F),
766
+ l(this, p)
767
+ ].join("")), this.rewriteRules = o;
757
768
  }
758
769
  /** @inheritDoc */
759
770
  pathToInternalUrl(t) {
@@ -762,32 +773,32 @@ class PHPRequestHandler {
762
773
  /** @inheritDoc */
763
774
  internalUrlToPath(t) {
764
775
  const r = new URL(t);
765
- return r.pathname.startsWith(a(this, _)) && (r.pathname = r.pathname.slice(a(this, _).length)), toRelativeUrl(r);
776
+ return r.pathname.startsWith(l(this, p)) && (r.pathname = r.pathname.slice(l(this, p).length)), toRelativeUrl(r);
766
777
  }
767
778
  get isRequestRunning() {
768
- return a(this, R).running > 0;
779
+ return l(this, R).running > 0;
769
780
  }
770
781
  /** @inheritDoc */
771
782
  get absoluteUrl() {
772
- return a(this, F);
783
+ return l(this, x);
773
784
  }
774
785
  /** @inheritDoc */
775
786
  get documentRoot() {
776
- return a(this, m);
787
+ return l(this, m);
777
788
  }
778
789
  /** @inheritDoc */
779
790
  async request(t) {
780
791
  const r = t.url.startsWith("http://") || t.url.startsWith("https://"), s = new URL(
781
792
  t.url,
782
793
  r ? void 0 : DEFAULT_BASE_URL
783
- ), n = removePathPrefix(
784
- s.pathname,
785
- a(this, _)
786
- ), i = `${a(this, m)}${n}`;
787
- return seemsLikeAPHPRequestHandlerPath(i) ? await f(this, I, Z).call(this, t, s) : f(this, B, Y).call(this, i);
794
+ ), n = applyRewriteRules(
795
+ removePathPrefix(s.pathname, l(this, p)),
796
+ this.rewriteRules
797
+ ), o = `${l(this, m)}${n}`;
798
+ return seemsLikeAPHPRequestHandlerPath(o) ? await f(this, B, Y).call(this, t, s) : f(this, U, Q).call(this, o);
788
799
  }
789
800
  }
790
- m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x = new WeakMap(), _ = new WeakMap(), F = new WeakMap(), R = new WeakMap(), B = new WeakSet(), Y = function(t) {
801
+ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), F = new WeakMap(), p = new WeakMap(), x = new WeakMap(), R = new WeakMap(), U = new WeakSet(), Q = function(t) {
791
802
  if (!this.php.fileExists(t))
792
803
  return new PHPResponse(
793
804
  404,
@@ -812,9 +823,9 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
812
823
  },
813
824
  r
814
825
  );
815
- }, I = new WeakSet(), Z = async function(t, r) {
816
- var n, i;
817
- if (a(this, R).running > 0 && ((n = t.headers) == null ? void 0 : n["x-request-issuer"]) === "php")
826
+ }, B = new WeakSet(), Y = async function(t, r) {
827
+ var n;
828
+ if (l(this, R).running > 0 && ((n = t.headers) == null ? void 0 : n["x-request-issuer"]) === "php")
818
829
  return console.warn(
819
830
  "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."
820
831
  ), new PHPResponse(
@@ -822,34 +833,26 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
822
833
  {},
823
834
  new TextEncoder().encode("502 Bad Gateway")
824
835
  );
825
- const s = await a(this, R).acquire();
836
+ const s = await l(this, R).acquire();
826
837
  try {
827
- this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", a(this, m)), this.php.addServerGlobalEntry(
838
+ this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", l(this, m)), this.php.addServerGlobalEntry(
828
839
  "HTTPS",
829
- a(this, F).startsWith("https://") ? "on" : ""
840
+ l(this, x).startsWith("https://") ? "on" : ""
830
841
  );
831
842
  let o = "GET";
832
- const l = {
833
- host: a(this, x),
843
+ const i = {
844
+ host: l(this, F),
834
845
  ...normalizeHeaders(t.headers || {})
835
846
  };
836
- let c = t.body;
837
- if (typeof c == "object" && !(c instanceof Uint8Array)) {
847
+ let a = t.body;
848
+ if (typeof a == "object" && !(a instanceof Uint8Array)) {
838
849
  o = "POST";
839
- const { bytes: p, contentType: U } = await encodeAsMultipart(c);
840
- c = p, l["content-type"] = U;
850
+ const { bytes: d, contentType: _ } = await encodeAsMultipart(a);
851
+ a = d, i["content-type"] = _;
841
852
  }
842
- let d;
853
+ let c;
843
854
  try {
844
- let p = r.pathname;
845
- if ((i = t.headers) != null && i["x-rewrite-url"])
846
- try {
847
- p = new URL(
848
- t.headers["x-rewrite-url"]
849
- ).pathname;
850
- } catch {
851
- }
852
- d = f(this, L, K).call(this, p);
855
+ c = f(this, I, K).call(this, r.pathname);
853
856
  } catch {
854
857
  return new PHPResponse(
855
858
  404,
@@ -860,21 +863,21 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
860
863
  return await this.php.run({
861
864
  relativeUri: ensurePathPrefix(
862
865
  toRelativeUrl(r),
863
- a(this, _)
866
+ l(this, p)
864
867
  ),
865
- protocol: a(this, H),
868
+ protocol: l(this, H),
866
869
  method: t.method || o,
867
- body: c,
868
- scriptPath: d,
869
- headers: l
870
+ body: a,
871
+ scriptPath: c,
872
+ headers: i
870
873
  });
871
874
  } finally {
872
875
  s();
873
876
  }
874
- }, L = new WeakSet(), K = function(t) {
875
- let r = removePathPrefix(t, a(this, _));
876
- r.includes(".php") ? r = r.split(".php")[0] + ".php" : this.php.isDir(`${a(this, m)}${r}`) ? (r.endsWith("/") || (r = `${r}/`), r = `${r}index.php`) : r = "/index.php";
877
- const s = `${a(this, m)}${r}`;
877
+ }, I = new WeakSet(), K = function(t) {
878
+ let r = removePathPrefix(t, l(this, p));
879
+ r = applyRewriteRules(r, this.rewriteRules), r.includes(".php") ? r = r.split(".php")[0] + ".php" : this.php.isDir(`${l(this, m)}${r}`) ? (r.endsWith("/") || (r = `${r}/`), r = `${r}index.php`) : r = "/index.php";
880
+ const s = `${l(this, m)}${r}`;
878
881
  if (this.php.fileExists(s))
879
882
  return s;
880
883
  throw new Error(`File not found: ${s}`);
@@ -928,6 +931,12 @@ function seemsLikeAPHPFile(e) {
928
931
  function seemsLikeADirectoryRoot(e) {
929
932
  return !e.split("/").pop().includes(".");
930
933
  }
934
+ function applyRewriteRules(e, t) {
935
+ for (const r of t)
936
+ if (new RegExp(r.match).test(e))
937
+ return e.replace(r.match, r.replacement);
938
+ return e;
939
+ }
931
940
  const FileErrorCodes = {
932
941
  0: "No error occurred. System call completed successfully.",
933
942
  1: "Argument list too long.",
@@ -1014,19 +1023,19 @@ function getEmscriptenFsError(e) {
1014
1023
  }
1015
1024
  function rethrowFileSystemError(e = "") {
1016
1025
  return function(r, s, n) {
1017
- const i = n.value;
1018
- n.value = function(...o) {
1026
+ const o = n.value;
1027
+ n.value = function(...i) {
1019
1028
  try {
1020
- return i.apply(this, o);
1021
- } catch (l) {
1022
- const c = typeof l == "object" ? l == null ? void 0 : l.errno : null;
1029
+ return o.apply(this, i);
1030
+ } catch (a) {
1031
+ const c = typeof a == "object" ? a == null ? void 0 : a.errno : null;
1023
1032
  if (c in FileErrorCodes) {
1024
- const d = FileErrorCodes[c], p = typeof o[0] == "string" ? o[0] : null, U = p !== null ? e.replaceAll("{path}", p) : e;
1025
- throw new Error(`${U}: ${d}`, {
1026
- cause: l
1033
+ const d = FileErrorCodes[c], _ = typeof i[0] == "string" ? i[0] : null, ue = _ !== null ? e.replaceAll("{path}", _) : e;
1034
+ throw new Error(`${ue}: ${d}`, {
1035
+ cause: a
1027
1036
  });
1028
1037
  }
1029
- throw l;
1038
+ throw a;
1030
1039
  }
1031
1040
  };
1032
1041
  };
@@ -1034,15 +1043,15 @@ function rethrowFileSystemError(e = "") {
1034
1043
  const RuntimeId = Symbol("RuntimeId"), loadedRuntimes = /* @__PURE__ */ new Map();
1035
1044
  let lastRuntimeId = 0;
1036
1045
  async function loadPHPRuntime(e, t = {}) {
1037
- const [r, s, n] = makePromise(), i = e.init(currentJsRuntime, {
1038
- onAbort(l) {
1039
- n(l), console.error(l);
1046
+ const [r, s, n] = makePromise(), o = e.init(currentJsRuntime, {
1047
+ onAbort(a) {
1048
+ n(a), console.error(a);
1040
1049
  },
1041
1050
  ENV: {},
1042
1051
  // Emscripten sometimes prepends a '/' to the path, which
1043
1052
  // breaks vite dev mode. An identity `locateFile` function
1044
1053
  // fixes it.
1045
- locateFile: (l) => l,
1054
+ locateFile: (a) => a,
1046
1055
  ...t,
1047
1056
  noInitialRun: !0,
1048
1057
  onRuntimeInitialized() {
@@ -1050,10 +1059,10 @@ async function loadPHPRuntime(e, t = {}) {
1050
1059
  }
1051
1060
  });
1052
1061
  await r;
1053
- const o = ++lastRuntimeId;
1054
- return i.id = o, i.originalExit = i._exit, i._exit = function(l) {
1055
- return loadedRuntimes.delete(o), i.originalExit(l);
1056
- }, i[RuntimeId] = o, loadedRuntimes.set(o, i), o;
1062
+ const i = ++lastRuntimeId;
1063
+ return o.id = i, o.originalExit = o._exit, o._exit = function(a) {
1064
+ return loadedRuntimes.delete(i), o.originalExit(a);
1065
+ }, o[RuntimeId] = i, loadedRuntimes.set(i, o), i;
1057
1066
  }
1058
1067
  function getLoadedRuntime(e) {
1059
1068
  return loadedRuntimes.get(e);
@@ -1068,12 +1077,12 @@ const currentJsRuntime = function() {
1068
1077
  return e.unshift(t), e;
1069
1078
  };
1070
1079
  var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyDescriptor, __decorateClass = (e, t, r, s) => {
1071
- for (var n = s > 1 ? void 0 : s ? __getOwnPropDesc(t, r) : t, i = e.length - 1, o; i >= 0; i--)
1072
- (o = e[i]) && (n = (s ? o(t, r, n) : o(n)) || n);
1080
+ for (var n = s > 1 ? void 0 : s ? __getOwnPropDesc(t, r) : t, o = e.length - 1, i; o >= 0; o--)
1081
+ (i = e[o]) && (n = (s ? i(t, r, n) : i(n)) || n);
1073
1082
  return s && n && __defProp(t, r, n), n;
1074
1083
  };
1075
1084
  const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
1076
- var S, T, A, y, w, g, P, C, N, X, M, ee, q, te, O, re, $, se, D, ne, j, ie, z, oe, W, ae, G, le, V, ce, Q, ue;
1085
+ var S, T, A, y, w, g, P, C, N, Z, L, X, O, ee, q, te, M, re, D, se, $, ne, j, ie, W, oe, z, ae, G, le, V, ce;
1077
1086
  class BasePHP {
1078
1087
  /**
1079
1088
  * Initializes a PHP runtime.
@@ -1084,17 +1093,17 @@ class BasePHP {
1084
1093
  */
1085
1094
  constructor(e, t) {
1086
1095
  u(this, N);
1087
- u(this, M);
1088
- u(this, q);
1096
+ u(this, L);
1089
1097
  u(this, O);
1090
- u(this, $);
1098
+ u(this, q);
1099
+ u(this, M);
1091
1100
  u(this, D);
1101
+ u(this, $);
1092
1102
  u(this, j);
1093
- u(this, z);
1094
1103
  u(this, W);
1104
+ u(this, z);
1095
1105
  u(this, G);
1096
1106
  u(this, V);
1097
- u(this, Q);
1098
1107
  u(this, S, void 0);
1099
1108
  u(this, T, void 0);
1100
1109
  u(this, A, void 0);
@@ -1108,21 +1117,21 @@ class BasePHP {
1108
1117
  ));
1109
1118
  }
1110
1119
  addEventListener(e, t) {
1111
- a(this, P).has(e) || a(this, P).set(e, /* @__PURE__ */ new Set()), a(this, P).get(e).add(t);
1120
+ l(this, P).has(e) || l(this, P).set(e, /* @__PURE__ */ new Set()), l(this, P).get(e).add(t);
1112
1121
  }
1113
1122
  removeEventListener(e, t) {
1114
1123
  var r;
1115
- (r = a(this, P).get(e)) == null || r.delete(t);
1124
+ (r = l(this, P).get(e)) == null || r.delete(t);
1116
1125
  }
1117
1126
  dispatchEvent(e) {
1118
- const t = a(this, P).get(e.type);
1127
+ const t = l(this, P).get(e.type);
1119
1128
  if (t)
1120
1129
  for (const r of t)
1121
1130
  r(e);
1122
1131
  }
1123
1132
  /** @inheritDoc */
1124
1133
  async onMessage(e) {
1125
- a(this, C).push(e);
1134
+ l(this, C).push(e);
1126
1135
  }
1127
1136
  /** @inheritDoc */
1128
1137
  async setSpawnHandler(handler) {
@@ -1153,7 +1162,7 @@ class BasePHP {
1153
1162
  if (!t)
1154
1163
  throw new Error("Invalid PHP runtime id.");
1155
1164
  this[__private__dont__use] = t, t.onMessage = async (r) => {
1156
- for (const s of a(this, C)) {
1165
+ for (const s of l(this, C)) {
1157
1166
  const n = await s(r);
1158
1167
  if (n)
1159
1168
  return n;
@@ -1178,7 +1187,7 @@ class BasePHP {
1178
1187
  }
1179
1188
  /** @inheritDoc */
1180
1189
  setPhpIniPath(e) {
1181
- if (a(this, y))
1190
+ if (l(this, y))
1182
1191
  throw new Error("Cannot set PHP ini path after calling run().");
1183
1192
  h(this, T, e), this[__private__dont__use].ccall(
1184
1193
  "wasm_set_phpini_path",
@@ -1189,9 +1198,9 @@ class BasePHP {
1189
1198
  }
1190
1199
  /** @inheritDoc */
1191
1200
  setPhpIniEntry(e, t) {
1192
- if (a(this, y))
1201
+ if (l(this, y))
1193
1202
  throw new Error("Cannot set PHP ini entries after calling run().");
1194
- a(this, S).push([e, t]);
1203
+ l(this, S).push([e, t]);
1195
1204
  }
1196
1205
  /** @inheritDoc */
1197
1206
  chdir(e) {
@@ -1208,29 +1217,34 @@ class BasePHP {
1208
1217
  const t = await this.semaphore.acquire();
1209
1218
  let r;
1210
1219
  try {
1211
- if (a(this, y) || (f(this, N, X).call(this), h(this, y, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
1220
+ if (l(this, y) || (f(this, N, Z).call(this), h(this, y, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
1212
1221
  throw new Error(
1213
1222
  `The script path "${e.scriptPath}" does not exist.`
1214
1223
  );
1215
- f(this, z, oe).call(this, e.scriptPath || ""), f(this, q, te).call(this, e.relativeUri || ""), f(this, $, se).call(this, e.method || "GET");
1224
+ f(this, j, ie).call(this, e.scriptPath || ""), f(this, O, ee).call(this, e.relativeUri || ""), f(this, M, re).call(this, e.method || "GET");
1216
1225
  const s = normalizeHeaders(e.headers || {}), n = s.host || "example.com:443";
1217
- f(this, O, re).call(this, n, e.protocol || "http"), f(this, D, ne).call(this, s), e.body && (r = f(this, j, ie).call(this, e.body)), typeof e.code == "string" && f(this, V, ce).call(this, " ?>" + e.code), f(this, W, ae).call(this);
1218
- const i = e.env || {};
1219
- for (const l in i)
1220
- f(this, G, le).call(this, l, i[l]);
1221
- const o = await f(this, Q, ue).call(this);
1222
- if (e.throwOnError && o.exitCode !== 0) {
1223
- const l = {
1224
- stdout: o.text,
1225
- stderr: o.errors
1226
+ f(this, q, te).call(this, n, e.protocol || "http"), f(this, D, se).call(this, s), e.body && (r = f(this, $, ne).call(this, e.body)), typeof e.code == "string" && f(this, G, le).call(this, " ?>" + e.code), f(this, W, oe).call(this);
1227
+ const o = e.env || {};
1228
+ for (const a in o)
1229
+ f(this, z, ae).call(this, a, o[a]);
1230
+ const i = await f(this, V, ce).call(this);
1231
+ if (e.throwOnError && i.exitCode !== 0) {
1232
+ const a = {
1233
+ stdout: i.text,
1234
+ stderr: i.errors
1226
1235
  };
1227
- console.warn("PHP.run() output was:", l);
1236
+ console.warn("PHP.run() output was:", a);
1228
1237
  const c = new Error(
1229
- `PHP.run() failed with exit code ${o.exitCode} and the following output: ` + o.errors
1238
+ `PHP.run() failed with exit code ${i.exitCode} and the following output: ` + i.errors
1230
1239
  );
1231
- throw c.output = l, console.error(c), c;
1240
+ throw c.output = a, console.error(c), c;
1232
1241
  }
1233
- return o;
1242
+ return i;
1243
+ } catch (s) {
1244
+ throw this.dispatchEvent({
1245
+ type: "request.error",
1246
+ error: s
1247
+ }), s;
1234
1248
  } finally {
1235
1249
  try {
1236
1250
  r && this[__private__dont__use].free(r);
@@ -1242,7 +1256,7 @@ class BasePHP {
1242
1256
  }
1243
1257
  }
1244
1258
  addServerGlobalEntry(e, t) {
1245
- a(this, g)[e] = t;
1259
+ l(this, g)[e] = t;
1246
1260
  }
1247
1261
  defineConstant(e, t) {
1248
1262
  let r = {};
@@ -1338,7 +1352,7 @@ class BasePHP {
1338
1352
  this.exit();
1339
1353
  } catch {
1340
1354
  }
1341
- if (this.initializeRuntime(e), a(this, T) && this.setPhpIniPath(a(this, T)), a(this, A) && this.setSapiName(a(this, A)), this.requestHandler) {
1355
+ if (this.initializeRuntime(e), l(this, T) && this.setPhpIniPath(l(this, T)), l(this, A) && this.setSapiName(l(this, A)), this.requestHandler) {
1342
1356
  const r = this.documentRoot;
1343
1357
  copyFS(t, this[__private__dont__use].FS, r);
1344
1358
  }
@@ -1354,7 +1368,7 @@ class BasePHP {
1354
1368
  h(this, y, !1), h(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1355
1369
  }
1356
1370
  }
1357
- S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w = new WeakMap(), g = new WeakMap(), P = new WeakMap(), C = new WeakMap(), N = new WeakSet(), X = function() {
1371
+ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w = new WeakMap(), g = new WeakMap(), P = new WeakMap(), C = new WeakMap(), N = new WeakSet(), Z = function() {
1358
1372
  if (this.setPhpIniEntry("auto_prepend_file", "/internal/consts.php"), this.fileExists("/internal/consts.php") || this.writeFile(
1359
1373
  "/internal/consts.php",
1360
1374
  `<?php
@@ -1366,8 +1380,8 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1366
1380
  }
1367
1381
  }
1368
1382
  }`
1369
- ), a(this, S).length > 0) {
1370
- const e = a(this, S).map(([t, r]) => `${t}=${r}`).join(`
1383
+ ), l(this, S).length > 0) {
1384
+ const e = l(this, S).map(([t, r]) => `${t}=${r}`).join(`
1371
1385
  `) + `
1372
1386
 
1373
1387
  `;
@@ -1379,7 +1393,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1379
1393
  );
1380
1394
  }
1381
1395
  this[__private__dont__use].ccall("php_wasm_init", null, [], []);
1382
- }, M = new WeakSet(), ee = function() {
1396
+ }, L = new WeakSet(), X = function() {
1383
1397
  const e = "/internal/headers.json";
1384
1398
  if (!this.fileExists(e))
1385
1399
  throw new Error(
@@ -1389,14 +1403,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1389
1403
  for (const s of t.headers) {
1390
1404
  if (!s.includes(": "))
1391
1405
  continue;
1392
- const n = s.indexOf(": "), i = s.substring(0, n).toLowerCase(), o = s.substring(n + 2);
1393
- i in r || (r[i] = []), r[i].push(o);
1406
+ const n = s.indexOf(": "), o = s.substring(0, n).toLowerCase(), i = s.substring(n + 2);
1407
+ o in r || (r[o] = []), r[o].push(i);
1394
1408
  }
1395
1409
  return {
1396
1410
  headers: r,
1397
1411
  httpStatusCode: t.status
1398
1412
  };
1399
- }, q = new WeakSet(), te = function(e) {
1413
+ }, O = new WeakSet(), ee = function(e) {
1400
1414
  if (this[__private__dont__use].ccall(
1401
1415
  "wasm_set_request_uri",
1402
1416
  null,
@@ -1411,7 +1425,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1411
1425
  [t]
1412
1426
  );
1413
1427
  }
1414
- }, O = new WeakSet(), re = function(e, t) {
1428
+ }, q = new WeakSet(), te = function(e, t) {
1415
1429
  this[__private__dont__use].ccall(
1416
1430
  "wasm_set_request_host",
1417
1431
  null,
@@ -1429,14 +1443,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1429
1443
  [NUMBER],
1430
1444
  [r]
1431
1445
  ), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
1432
- }, $ = new WeakSet(), se = function(e) {
1446
+ }, M = new WeakSet(), re = function(e) {
1433
1447
  this[__private__dont__use].ccall(
1434
1448
  "wasm_set_request_method",
1435
1449
  null,
1436
1450
  [STRING],
1437
1451
  [e]
1438
1452
  );
1439
- }, D = new WeakSet(), ne = function(e) {
1453
+ }, D = new WeakSet(), se = function(e) {
1440
1454
  e.cookie && this[__private__dont__use].ccall(
1441
1455
  "wasm_set_cookies",
1442
1456
  null,
@@ -1460,7 +1474,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1460
1474
  e[t]
1461
1475
  );
1462
1476
  }
1463
- }, j = new WeakSet(), ie = function(e) {
1477
+ }, $ = new WeakSet(), ne = function(e) {
1464
1478
  let t, r;
1465
1479
  typeof e == "string" ? (console.warn(
1466
1480
  "Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"
@@ -1483,59 +1497,59 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1483
1497
  [NUMBER],
1484
1498
  [r]
1485
1499
  ), s;
1486
- }, z = new WeakSet(), oe = function(e) {
1500
+ }, j = new WeakSet(), ie = function(e) {
1487
1501
  this[__private__dont__use].ccall(
1488
1502
  "wasm_set_path_translated",
1489
1503
  null,
1490
1504
  [STRING],
1491
1505
  [e]
1492
1506
  );
1493
- }, W = new WeakSet(), ae = function() {
1494
- for (const e in a(this, g))
1507
+ }, W = new WeakSet(), oe = function() {
1508
+ for (const e in l(this, g))
1495
1509
  this[__private__dont__use].ccall(
1496
1510
  "wasm_add_SERVER_entry",
1497
1511
  null,
1498
1512
  [STRING, STRING],
1499
- [e, a(this, g)[e]]
1513
+ [e, l(this, g)[e]]
1500
1514
  );
1501
- }, G = new WeakSet(), le = function(e, t) {
1515
+ }, z = new WeakSet(), ae = function(e, t) {
1502
1516
  this[__private__dont__use].ccall(
1503
1517
  "wasm_add_ENV_entry",
1504
1518
  null,
1505
1519
  [STRING, STRING],
1506
1520
  [e, t]
1507
1521
  );
1508
- }, V = new WeakSet(), ce = function(e) {
1522
+ }, G = new WeakSet(), le = function(e) {
1509
1523
  this[__private__dont__use].ccall(
1510
1524
  "wasm_set_php_code",
1511
1525
  null,
1512
1526
  [STRING],
1513
1527
  [e]
1514
1528
  );
1515
- }, Q = new WeakSet(), ue = async function() {
1529
+ }, V = new WeakSet(), ce = async function() {
1516
1530
  var n;
1517
1531
  let e, t;
1518
1532
  try {
1519
- e = await new Promise((i, o) => {
1533
+ e = await new Promise((o, i) => {
1520
1534
  var c;
1521
1535
  t = (d) => {
1522
1536
  console.error(d), console.error(d.error);
1523
- const p = new Error("Rethrown");
1524
- p.cause = d.error, p.betterMessage = d.message, o(p);
1525
- }, (c = a(this, w)) == null || c.addEventListener(
1537
+ const _ = new Error("Rethrown");
1538
+ _.cause = d.error, _.betterMessage = d.message, i(_);
1539
+ }, (c = l(this, w)) == null || c.addEventListener(
1526
1540
  "error",
1527
1541
  t
1528
1542
  );
1529
- const l = this[__private__dont__use].ccall(
1543
+ const a = this[__private__dont__use].ccall(
1530
1544
  "wasm_sapi_handle_request",
1531
1545
  NUMBER,
1532
1546
  [],
1533
1547
  [],
1534
1548
  { async: !0 }
1535
1549
  );
1536
- return l instanceof Promise ? l.then(i, o) : i(l);
1550
+ return a instanceof Promise ? a.then(o, i) : o(a);
1537
1551
  });
1538
- } catch (i) {
1552
+ } catch (o) {
1539
1553
  for (const d in this)
1540
1554
  typeof this[d] == "function" && (this[d] = () => {
1541
1555
  throw new Error(
@@ -1543,12 +1557,12 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1543
1557
  );
1544
1558
  });
1545
1559
  this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
1546
- const o = i, l = "betterMessage" in o ? o.betterMessage : o.message, c = new Error(l);
1547
- throw c.cause = o, console.error(c), c;
1560
+ const i = o, a = "betterMessage" in i ? i.betterMessage : i.message, c = new Error(a);
1561
+ throw c.cause = i, console.error(c), c;
1548
1562
  } finally {
1549
- (n = a(this, w)) == null || n.removeEventListener("error", t), h(this, g, {});
1563
+ (n = l(this, w)) == null || n.removeEventListener("error", t), h(this, g, {});
1550
1564
  }
1551
- const { headers: r, httpStatusCode: s } = f(this, M, ee).call(this);
1565
+ const { headers: r, httpStatusCode: s } = f(this, L, X).call(this);
1552
1566
  return new PHPResponse(
1553
1567
  s,
1554
1568
  r,
@@ -1607,9 +1621,9 @@ function copyFS(e, t, r) {
1607
1621
  return;
1608
1622
  }
1609
1623
  t.mkdirTree(r);
1610
- const n = e.readdir(r).filter((i) => i !== "." && i !== "..");
1611
- for (const i of n)
1612
- copyFS(e, t, joinPaths(r, i));
1624
+ const n = e.readdir(r).filter((o) => o !== "." && o !== "..");
1625
+ for (const o of n)
1626
+ copyFS(e, t, joinPaths(r, o));
1613
1627
  }
1614
1628
  function isLocalPHP(e) {
1615
1629
  return !(e instanceof BasePHP);
@@ -1627,11 +1641,11 @@ function rotatePHPRuntime({
1627
1641
  if (++s < r)
1628
1642
  return;
1629
1643
  s = 0;
1630
- const i = await e.semaphore.acquire();
1644
+ const o = await e.semaphore.acquire();
1631
1645
  try {
1632
1646
  e.hotSwapPHPRuntime(await t());
1633
1647
  } finally {
1634
- i();
1648
+ o();
1635
1649
  }
1636
1650
  }
1637
1651
  return e.addEventListener("request.end", n), function() {
@@ -1640,9 +1654,9 @@ function rotatePHPRuntime({
1640
1654
  }
1641
1655
  async function writeFiles(e, t, r, { rmRoot: s = !1 } = {}) {
1642
1656
  s && await e.isDir(t) && await e.rmdir(t, { recursive: !0 });
1643
- for (const [n, i] of Object.entries(r)) {
1644
- const o = joinPaths(t, n);
1645
- await e.fileExists(dirname(o)) || await e.mkdir(dirname(o)), await e.writeFile(o, i);
1657
+ for (const [n, o] of Object.entries(r)) {
1658
+ const i = joinPaths(t, n);
1659
+ await e.fileExists(dirname(i)) || await e.mkdir(dirname(i)), await e.writeFile(i, o);
1646
1660
  }
1647
1661
  }
1648
1662
  export {
@@ -1658,6 +1672,7 @@ export {
1658
1672
  SupportedPHPVersionsList,
1659
1673
  UnhandledRejectionsTarget,
1660
1674
  __private__dont__use,
1675
+ applyRewriteRules,
1661
1676
  ensurePathPrefix,
1662
1677
  isExitCodeZero,
1663
1678
  isLocalPHP,
package/lib/index.d.ts CHANGED
@@ -16,8 +16,8 @@ export type { DataModule, EmscriptenOptions, PHPLoaderModule, PHPRuntime, PHPRun
16
16
  export { rethrowFileSystemError } from './rethrow-file-system-error';
17
17
  export { isLocalPHP } from './is-local-php';
18
18
  export { isRemotePHP } from './is-remote-php';
19
- export type { PHPRequestHandlerConfiguration } from './php-request-handler';
20
- export { PHPRequestHandler } from './php-request-handler';
19
+ export type { PHPRequestHandlerConfiguration, RewriteRule, } from './php-request-handler';
20
+ export { PHPRequestHandler, applyRewriteRules } 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';
@@ -1,6 +1,10 @@
1
1
  import { BasePHP } from './base-php';
2
2
  import { PHPResponse } from './php-response';
3
3
  import { PHPRequest, RequestHandler } from './universal-php';
4
+ export type RewriteRule = {
5
+ match: RegExp;
6
+ replacement: string;
7
+ };
4
8
  export interface PHPRequestHandlerConfiguration {
5
9
  /**
6
10
  * The directory in the PHP filesystem where the server will look
@@ -11,10 +15,15 @@ export interface PHPRequestHandlerConfiguration {
11
15
  * Request Handler URL. Used to populate $_SERVER details like HTTP_HOST.
12
16
  */
13
17
  absoluteUrl?: string;
18
+ /**
19
+ * Rewrite rules
20
+ */
21
+ rewriteRules?: RewriteRule[];
14
22
  }
15
23
  /** @inheritDoc */
16
24
  export declare class PHPRequestHandler implements RequestHandler {
17
25
  #private;
26
+ rewriteRules: RewriteRule[];
18
27
  /**
19
28
  * The PHP instance
20
29
  */
@@ -53,3 +62,11 @@ export declare class PHPRequestHandler implements RequestHandler {
53
62
  * @returns Whether the path seems like a PHP server path.
54
63
  */
55
64
  export declare function seemsLikeAPHPRequestHandlerPath(path: string): boolean;
65
+ /**
66
+ * Applies the given rewrite rules to the given path.
67
+ *
68
+ * @param path The path to apply the rules to.
69
+ * @param rules The rules to apply.
70
+ * @returns The path with the rules applied.
71
+ */
72
+ export declare function applyRewriteRules(path: string, rules: RewriteRule[]): string;
@@ -6,6 +6,13 @@ import { PHPResponse } from './php-response';
6
6
  export interface PHPRequestEndEvent {
7
7
  type: 'request.end';
8
8
  }
9
+ /**
10
+ * Represents an error event related to the PHP request.
11
+ */
12
+ export interface PHPRequestErrorEvent {
13
+ type: 'request.error';
14
+ error: Error;
15
+ }
9
16
  /**
10
17
  * Represents a PHP runtime initialization event.
11
18
  */
@@ -23,7 +30,7 @@ export interface PHPRuntimeBeforeDestroyEvent {
23
30
  * This is intentionally not an extension of CustomEvent
24
31
  * to make it isomorphic between different JavaScript runtimes.
25
32
  */
26
- export type PHPEvent = PHPRequestEndEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeDestroyEvent;
33
+ export type PHPEvent = PHPRequestEndEvent | PHPRequestErrorEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeDestroyEvent;
27
34
  /**
28
35
  * A callback function that handles PHP events.
29
36
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/universal",
3
- "version": "0.6.6",
3
+ "version": "0.6.8",
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": "90f82ca946f8573b358c1320be0b6b8674f67cfc",
39
+ "gitHead": "cb7b1af260489022238495a2fc0d96f767a1294a",
40
40
  "engines": {
41
41
  "node": ">=18.18.2",
42
42
  "npm": ">=8.11.0"