@php-wasm/universal 0.6.7 → 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 Q=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var l=(e,t,r)=>(Q(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)=>(Q(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var p=(e,t,r)=>(Q(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(i){r.onload=r.onerror=null,i.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,i,o){super(n);let a;o!=null&&o.lastModified&&(a=new Date),(!a||isNaN(a.getFullYear()))&&(a=new Date),this.lastModifiedDate=a,this.lastModified=a.getMilliseconds(),this.name=i||""}}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 i=n.byobRequest.view,a=await s.slice(r,r+i.byteLength).arrayBuffer(),c=new Uint8Array(a);new Uint8Array(i.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 i;try{return s(...n)}catch(o){if(!(o instanceof Error))throw o;const a=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:a}));return}throw isExitCodeZero(o)||showCriticalErrorBox(a),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 a=0;a<e.length;a++){const c=e[a];c==="\\"?((e[a+1]==='"'||e[a+1]==="'")&&a++,o+=e[a]):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 a=await e.listFiles(o);for(const c of a){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"]),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),i=r.substring(s+1).split(";")[0];l(this,E)[n]=i}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
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 a=0;for(const c of n)o.set(typeof c=="string"?s.encode(c):c,a),a+=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,k,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,k,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,k,i.hostname),h(this,v,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,x,(i.protocol||"").replace(":",""));const o=l(this,v)!==443&&l(this,v)!==80;h(this,H,[l(this,k),o?`:${l(this,v)}`:""].join("")),h(this,_,i.pathname.replace(/\/+$/,"")),h(this,F,[`${l(this,x)}://`,l(this,H),l(this,_)].join(""))}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(l(this,_))&&(r.pathname=r.pathname.slice(l(this,_).length)),toRelativeUrl(r)}get isRequestRunning(){return l(this,R).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=removePathPrefix(s.pathname,l(this,_)),i=`${l(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,k=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(l(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 l(this,R).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 a={host:l(this,H),...normalizeHeaders(t.headers||{})};let c=t.body;if(typeof c=="object"&&!(c instanceof Uint8Array)){o="POST";const{bytes:f,contentType:U}=await encodeAsMultipart(c);c=f,a["content-type"]=U}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),l(this,_)),protocol:l(this,x),method:t.method||o,body:c,scriptPath:d,headers:a})}finally{s()}},L=new WeakSet,K=function(t){let r=removePathPrefix(t,l(this,_));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(".")}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(a){const c=typeof a=="object"?a==null?void 0:a.errno:null;if(c in FileErrorCodes){const d=FileErrorCodes[c],f=typeof o[0]=="string"?o[0]:null,U=f!==null?e.replaceAll("{path}",f):e;throw new Error(`${U}: ${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(),i=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 o=++lastRuntimeId;return i.id=o,i.originalExit=i._exit,i._exit=function(a){return loadedRuntimes.delete(o),i.originalExit(a)},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,O,ee,M,te,q,re,D,se,$,ne,j,ie,W,oe,z,ae,G,le,V,ce,J,ue;class BasePHP{constructor(e,t){u(this,N);u(this,O);u(this,M);u(this,q);u(this,D);u(this,$);u(this,j);u(this,W);u(this,z);u(this,G);u(this,V);u(this,J);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,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,W,oe).call(this,e.scriptPath||""),p(this,M,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,q,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,z,ae).call(this);const i=e.env||{};for(const a in i)p(this,G,le).call(this,a,i[a]);const o=await p(this,J,ue).call(this);if(e.throwOnError&&o.exitCode!==0){const a={stdout:o.text,stderr:o.errors};console.warn("PHP.run() output was:",a);const c=new Error(`PHP.run() failed with exit code ${o.exitCode} and the following output: `+o.errors);throw c.output=a,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){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,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) {
@@ -49,4 +49,4 @@ ${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
49
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,[],[])},O=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}},M=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])}},q=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},W=new WeakSet,oe=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},z=new WeakSet,ae=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]])},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])},J=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=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(i,o):i(a)})}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,a="betterMessage"in o?o.betterMessage:o.message,c=new Error(a);throw c.cause=o,console.error(c),c}finally{(n=l(this,w))==null||n.removeEventListener("error",t),h(this,g,{})}const{headers:r,httpStatusCode:s}=p(this,O,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
@@ -1,13 +1,13 @@
1
- var Q = (e, t, r) => {
1
+ var J = (e, t, r) => {
2
2
  if (!t.has(e))
3
3
  throw TypeError("Cannot " + r);
4
4
  };
5
- var l = (e, t, r) => (Q(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
- }, h = (e, t, r, s) => (Q(e, t, "write to private field"), s ? s.call(e, r) : t.set(e, r), r);
10
- var f = (e, t, r) => (Q(e, t, "access private method"), r);
9
+ }, h = (e, t, r, s) => (J(e, t, "write to private field"), s ? s.call(e, r) : t.set(e, r), r);
10
+ var f = (e, t, r) => (J(e, t, "access private method"), r);
11
11
  const currentJsRuntime$1 = function() {
12
12
  var e;
13
13
  return typeof process < "u" && ((e = process.release) == null ? void 0 : e.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : (
@@ -19,8 +19,8 @@ const currentJsRuntime$1 = function() {
19
19
  if (currentJsRuntime$1 === "NODE") {
20
20
  let e = function(r) {
21
21
  return new Promise(function(s, n) {
22
- r.onload = r.onerror = function(i) {
23
- r.onload = r.onerror = null, i.type === "load" ? s(r.result) : n(new Error("Failed to read the blob/file"));
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
24
  };
25
25
  });
26
26
  }, t = function() {
@@ -33,10 +33,10 @@ if (currentJsRuntime$1 === "NODE") {
33
33
  };
34
34
  if (typeof File > "u") {
35
35
  class r extends Blob {
36
- constructor(n, i, o) {
36
+ constructor(n, o, i) {
37
37
  super(n);
38
38
  let a;
39
- o != null && o.lastModified && (a = /* @__PURE__ */ new Date()), (!a || isNaN(a.getFullYear())) && (a = /* @__PURE__ */ new Date()), this.lastModifiedDate = a, this.lastModified = a.getMilliseconds(), this.name = i || "";
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
40
  }
41
41
  }
42
42
  global.File = r;
@@ -56,11 +56,11 @@ if (currentJsRuntime$1 === "NODE") {
56
56
  // this if needed.
57
57
  autoAllocateChunkSize: 512 * 1024,
58
58
  async pull(n) {
59
- const i = n.byobRequest.view, a = await s.slice(
59
+ const o = n.byobRequest.view, a = await s.slice(
60
60
  r,
61
- r + i.byteLength
61
+ r + o.byteLength
62
62
  ).arrayBuffer(), c = new Uint8Array(a);
63
- new Uint8Array(i.buffer).set(c);
63
+ new Uint8Array(o.buffer).set(c);
64
64
  const d = c.byteLength;
65
65
  n.byobRequest.respond(d), r += d, r >= s.size && n.close();
66
66
  }
@@ -125,26 +125,26 @@ function improveWASMErrorReporting(e) {
125
125
  if (typeof e.asm[r] == "function") {
126
126
  const s = e.asm[r];
127
127
  e.asm[r] = function(...n) {
128
- var i;
128
+ var o;
129
129
  try {
130
130
  return s(...n);
131
- } catch (o) {
132
- if (!(o instanceof Error))
133
- throw o;
131
+ } catch (i) {
132
+ if (!(i instanceof Error))
133
+ throw i;
134
134
  const a = clarifyErrorMessage(
135
- o,
136
- (i = e.lastAsyncifyStackSource) == null ? void 0 : i.stack
135
+ i,
136
+ (o = e.lastAsyncifyStackSource) == null ? void 0 : o.stack
137
137
  );
138
- if (e.lastAsyncifyStackSource && (o.cause = e.lastAsyncifyStackSource), t.hasListeners()) {
138
+ if (e.lastAsyncifyStackSource && (i.cause = e.lastAsyncifyStackSource), t.hasListeners()) {
139
139
  t.dispatchEvent(
140
140
  new ErrorEvent("error", {
141
- error: o,
141
+ error: i,
142
142
  message: a
143
143
  })
144
144
  );
145
145
  return;
146
146
  }
147
- throw isExitCodeZero(o) || showCriticalErrorBox(a), o;
147
+ throw isExitCodeZero(i) || showCriticalErrorBox(a), i;
148
148
  }
149
149
  };
150
150
  }
@@ -286,28 +286,28 @@ function normalizePathsArray(e, t) {
286
286
  }
287
287
  function splitShellCommand(e) {
288
288
  let s = 0, n = "";
289
- const i = [];
290
- let o = "";
289
+ const o = [];
290
+ let i = "";
291
291
  for (let a = 0; a < e.length; a++) {
292
292
  const c = e[a];
293
- c === "\\" ? ((e[a + 1] === '"' || e[a + 1] === "'") && a++, o += e[a]) : 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);
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);
294
294
  }
295
- return o && i.push(o.trim()), i;
295
+ return i && o.push(i.trim()), o;
296
296
  }
297
297
  function createSpawnHandler(e) {
298
298
  return function(t, r = [], s = {}) {
299
- const n = new ChildProcess(), i = new ProcessApi(n);
299
+ const n = new ChildProcess(), o = new ProcessApi(n);
300
300
  return setTimeout(async () => {
301
- let o = [];
301
+ let i = [];
302
302
  if (r.length)
303
- o = [t, ...r];
303
+ i = [t, ...r];
304
304
  else if (typeof t == "string")
305
- o = splitShellCommand(t);
305
+ i = splitShellCommand(t);
306
306
  else if (Array.isArray(t))
307
- o = t;
307
+ i = t;
308
308
  else
309
309
  throw new Error("Invalid command ", t);
310
- await e(o, i, s), n.emit("spawn", !0);
310
+ await e(i, o, s), n.emit("spawn", !0);
311
311
  }), n;
312
312
  };
313
313
  }
@@ -408,14 +408,14 @@ function limitBytes(e, t) {
408
408
  let s = 0;
409
409
  return new ReadableStream({
410
410
  async pull(n) {
411
- const { value: i, done: o } = await r.read(
411
+ const { value: o, done: i } = await r.read(
412
412
  new Uint8Array(t - s)
413
413
  );
414
- if (o) {
414
+ if (i) {
415
415
  r.releaseLock(), n.close();
416
416
  return;
417
417
  }
418
- 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());
419
419
  },
420
420
  cancel() {
421
421
  r.cancel();
@@ -497,17 +497,17 @@ async function* iteratePhpFiles(e, t, {
497
497
  exceptPaths: n = []
498
498
  } = {}) {
499
499
  t = normalizePath(t);
500
- const i = [t];
501
- for (; i.length; ) {
502
- const o = i.pop();
503
- if (!o)
500
+ const o = [t];
501
+ for (; o.length; ) {
502
+ const i = o.pop();
503
+ if (!i)
504
504
  return;
505
- const a = await e.listFiles(o);
505
+ const a = await e.listFiles(i);
506
506
  for (const c of a) {
507
- const d = `${o}/${c}`;
507
+ const d = `${i}/${c}`;
508
508
  if (n.includes(d.substring(t.length + 1)))
509
509
  continue;
510
- await e.isDir(d) ? i.push(d) : yield new StreamedFile(
510
+ await e.isDir(d) ? o.push(d) : yield new StreamedFile(
511
511
  streamReadFileFromPHP(e, d),
512
512
  r ? joinPaths(
513
513
  s || "",
@@ -529,8 +529,8 @@ function writeFilesStreamToPhp(e, t) {
529
529
  });
530
530
  }
531
531
  class PHPResponse {
532
- constructor(t, r, s, n = "", i = 0) {
533
- 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;
534
534
  }
535
535
  static fromRawData(t) {
536
536
  return new PHPResponse(
@@ -655,8 +655,8 @@ class PHPBrowser {
655
655
  try {
656
656
  if (!r.includes("="))
657
657
  continue;
658
- const s = r.indexOf("="), n = r.substring(0, s), i = r.substring(s + 1).split(";")[0];
659
- l(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;
660
660
  } catch (s) {
661
661
  console.error(s);
662
662
  }
@@ -690,14 +690,14 @@ async function encodeAsMultipart(e) {
690
690
  `);
691
691
  n.push(`--${t}--\r
692
692
  `);
693
- const i = n.reduce((c, d) => c + d.length, 0), o = new Uint8Array(i);
693
+ const o = n.reduce((c, d) => c + d.length, 0), i = new Uint8Array(o);
694
694
  let a = 0;
695
695
  for (const c of n)
696
- o.set(
696
+ i.set(
697
697
  typeof c == "string" ? s.encode(c) : c,
698
698
  a
699
699
  ), a += c.length;
700
- return { bytes: o, contentType: r };
700
+ return { bytes: i, contentType: r };
701
701
  }
702
702
  function fileToUint8Array(e) {
703
703
  return new Promise((t) => {
@@ -707,7 +707,7 @@ function fileToUint8Array(e) {
707
707
  }, r.readAsArrayBuffer(e);
708
708
  });
709
709
  }
710
- var m, H, k, v, x, _, F, R, B, Y, I, K, N, Z;
710
+ var m, H, k, v, F, p, x, R, U, Q, B, Y, I, K;
711
711
  class PHPRequestHandler {
712
712
  /**
713
713
  * @param php - The PHP instance.
@@ -720,7 +720,7 @@ class PHPRequestHandler {
720
720
  * @param fsPath - Absolute path of the static file to serve.
721
721
  * @returns The response.
722
722
  */
723
- u(this, B);
723
+ u(this, U);
724
724
  /**
725
725
  * Runs the requested PHP file with all the request and $_SERVER
726
726
  * superglobals populated.
@@ -728,7 +728,7 @@ class PHPRequestHandler {
728
728
  * @param request - The request.
729
729
  * @returns The response.
730
730
  */
731
- u(this, I);
731
+ u(this, B);
732
732
  /**
733
733
  * Resolve the requested path to the filesystem path of the requested PHP file.
734
734
  *
@@ -738,32 +738,33 @@ class PHPRequestHandler {
738
738
  * @throws {Error} If the requested path doesn't exist.
739
739
  * @returns The resolved filesystem path.
740
740
  */
741
- u(this, N);
741
+ u(this, I);
742
742
  u(this, m, void 0);
743
743
  u(this, H, void 0);
744
744
  u(this, k, void 0);
745
745
  u(this, v, void 0);
746
- u(this, x, void 0);
747
- u(this, _, void 0);
748
746
  u(this, F, void 0);
747
+ u(this, p, void 0);
748
+ u(this, x, void 0);
749
749
  u(this, R, void 0);
750
750
  h(this, R, new Semaphore({ concurrency: 1 }));
751
751
  const {
752
752
  documentRoot: s = "/www/",
753
- 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 = []
754
755
  } = r;
755
756
  this.php = t, h(this, m, s);
756
757
  const i = new URL(n);
757
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(":", ""));
758
- const o = l(this, v) !== 443 && l(this, v) !== 80;
759
- h(this, x, [
759
+ const a = l(this, v) !== 443 && l(this, v) !== 80;
760
+ h(this, F, [
760
761
  l(this, k),
761
- o ? `:${l(this, v)}` : ""
762
- ].join("")), h(this, _, i.pathname.replace(/\/+$/, "")), h(this, F, [
762
+ a ? `:${l(this, v)}` : ""
763
+ ].join("")), h(this, p, i.pathname.replace(/\/+$/, "")), h(this, x, [
763
764
  `${l(this, H)}://`,
764
- l(this, x),
765
- l(this, _)
766
- ].join(""));
765
+ l(this, F),
766
+ l(this, p)
767
+ ].join("")), this.rewriteRules = o;
767
768
  }
768
769
  /** @inheritDoc */
769
770
  pathToInternalUrl(t) {
@@ -772,14 +773,14 @@ class PHPRequestHandler {
772
773
  /** @inheritDoc */
773
774
  internalUrlToPath(t) {
774
775
  const r = new URL(t);
775
- return r.pathname.startsWith(l(this, _)) && (r.pathname = r.pathname.slice(l(this, _).length)), toRelativeUrl(r);
776
+ return r.pathname.startsWith(l(this, p)) && (r.pathname = r.pathname.slice(l(this, p).length)), toRelativeUrl(r);
776
777
  }
777
778
  get isRequestRunning() {
778
779
  return l(this, R).running > 0;
779
780
  }
780
781
  /** @inheritDoc */
781
782
  get absoluteUrl() {
782
- return l(this, F);
783
+ return l(this, x);
783
784
  }
784
785
  /** @inheritDoc */
785
786
  get documentRoot() {
@@ -790,14 +791,14 @@ class PHPRequestHandler {
790
791
  const r = t.url.startsWith("http://") || t.url.startsWith("https://"), s = new URL(
791
792
  t.url,
792
793
  r ? void 0 : DEFAULT_BASE_URL
793
- ), n = removePathPrefix(
794
- s.pathname,
795
- l(this, _)
796
- ), i = `${l(this, m)}${n}`;
797
- return seemsLikeAPHPRequestHandlerPath(i) ? await f(this, I, K).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);
798
799
  }
799
800
  }
800
- 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) {
801
802
  if (!this.php.fileExists(t))
802
803
  return new PHPResponse(
803
804
  404,
@@ -822,8 +823,8 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
822
823
  },
823
824
  r
824
825
  );
825
- }, I = new WeakSet(), K = async function(t, r) {
826
- var n, i;
826
+ }, B = new WeakSet(), Y = async function(t, r) {
827
+ var n;
827
828
  if (l(this, R).running > 0 && ((n = t.headers) == null ? void 0 : n["x-request-issuer"]) === "php")
828
829
  return console.warn(
829
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."
@@ -836,30 +837,22 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
836
837
  try {
837
838
  this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", l(this, m)), this.php.addServerGlobalEntry(
838
839
  "HTTPS",
839
- l(this, F).startsWith("https://") ? "on" : ""
840
+ l(this, x).startsWith("https://") ? "on" : ""
840
841
  );
841
842
  let o = "GET";
842
- const a = {
843
- host: l(this, x),
843
+ const i = {
844
+ host: l(this, F),
844
845
  ...normalizeHeaders(t.headers || {})
845
846
  };
846
- let c = t.body;
847
- if (typeof c == "object" && !(c instanceof Uint8Array)) {
847
+ let a = t.body;
848
+ if (typeof a == "object" && !(a instanceof Uint8Array)) {
848
849
  o = "POST";
849
- const { bytes: p, contentType: U } = await encodeAsMultipart(c);
850
- c = p, a["content-type"] = U;
850
+ const { bytes: d, contentType: _ } = await encodeAsMultipart(a);
851
+ a = d, i["content-type"] = _;
851
852
  }
852
- let d;
853
+ let c;
853
854
  try {
854
- let p = r.pathname;
855
- if ((i = t.headers) != null && i["x-rewrite-url"])
856
- try {
857
- p = new URL(
858
- t.headers["x-rewrite-url"]
859
- ).pathname;
860
- } catch {
861
- }
862
- d = f(this, N, Z).call(this, p);
855
+ c = f(this, I, K).call(this, r.pathname);
863
856
  } catch {
864
857
  return new PHPResponse(
865
858
  404,
@@ -870,20 +863,20 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
870
863
  return await this.php.run({
871
864
  relativeUri: ensurePathPrefix(
872
865
  toRelativeUrl(r),
873
- l(this, _)
866
+ l(this, p)
874
867
  ),
875
868
  protocol: l(this, H),
876
869
  method: t.method || o,
877
- body: c,
878
- scriptPath: d,
879
- headers: a
870
+ body: a,
871
+ scriptPath: c,
872
+ headers: i
880
873
  });
881
874
  } finally {
882
875
  s();
883
876
  }
884
- }, N = new WeakSet(), Z = function(t) {
885
- let r = removePathPrefix(t, l(this, _));
886
- 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";
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";
887
880
  const s = `${l(this, m)}${r}`;
888
881
  if (this.php.fileExists(s))
889
882
  return s;
@@ -938,6 +931,12 @@ function seemsLikeAPHPFile(e) {
938
931
  function seemsLikeADirectoryRoot(e) {
939
932
  return !e.split("/").pop().includes(".");
940
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
+ }
941
940
  const FileErrorCodes = {
942
941
  0: "No error occurred. System call completed successfully.",
943
942
  1: "Argument list too long.",
@@ -1024,15 +1023,15 @@ function getEmscriptenFsError(e) {
1024
1023
  }
1025
1024
  function rethrowFileSystemError(e = "") {
1026
1025
  return function(r, s, n) {
1027
- const i = n.value;
1028
- n.value = function(...o) {
1026
+ const o = n.value;
1027
+ n.value = function(...i) {
1029
1028
  try {
1030
- return i.apply(this, o);
1029
+ return o.apply(this, i);
1031
1030
  } catch (a) {
1032
1031
  const c = typeof a == "object" ? a == null ? void 0 : a.errno : null;
1033
1032
  if (c in FileErrorCodes) {
1034
- const d = FileErrorCodes[c], p = typeof o[0] == "string" ? o[0] : null, U = p !== null ? e.replaceAll("{path}", p) : e;
1035
- throw new Error(`${U}: ${d}`, {
1033
+ const d = FileErrorCodes[c], _ = typeof i[0] == "string" ? i[0] : null, ue = _ !== null ? e.replaceAll("{path}", _) : e;
1034
+ throw new Error(`${ue}: ${d}`, {
1036
1035
  cause: a
1037
1036
  });
1038
1037
  }
@@ -1044,7 +1043,7 @@ function rethrowFileSystemError(e = "") {
1044
1043
  const RuntimeId = Symbol("RuntimeId"), loadedRuntimes = /* @__PURE__ */ new Map();
1045
1044
  let lastRuntimeId = 0;
1046
1045
  async function loadPHPRuntime(e, t = {}) {
1047
- const [r, s, n] = makePromise(), i = e.init(currentJsRuntime, {
1046
+ const [r, s, n] = makePromise(), o = e.init(currentJsRuntime, {
1048
1047
  onAbort(a) {
1049
1048
  n(a), console.error(a);
1050
1049
  },
@@ -1060,10 +1059,10 @@ async function loadPHPRuntime(e, t = {}) {
1060
1059
  }
1061
1060
  });
1062
1061
  await r;
1063
- const o = ++lastRuntimeId;
1064
- return i.id = o, i.originalExit = i._exit, i._exit = function(a) {
1065
- return loadedRuntimes.delete(o), i.originalExit(a);
1066
- }, 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;
1067
1066
  }
1068
1067
  function getLoadedRuntime(e) {
1069
1068
  return loadedRuntimes.get(e);
@@ -1078,12 +1077,12 @@ const currentJsRuntime = function() {
1078
1077
  return e.unshift(t), e;
1079
1078
  };
1080
1079
  var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyDescriptor, __decorateClass = (e, t, r, s) => {
1081
- for (var n = s > 1 ? void 0 : s ? __getOwnPropDesc(t, r) : t, i = e.length - 1, o; i >= 0; i--)
1082
- (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);
1083
1082
  return s && n && __defProp(t, r, n), n;
1084
1083
  };
1085
1084
  const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
1086
- var S, T, A, y, w, g, P, C, L, X, O, ee, M, te, q, re, D, se, $, ne, j, ie, W, oe, z, ae, G, le, V, ce, J, 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;
1087
1086
  class BasePHP {
1088
1087
  /**
1089
1088
  * Initializes a PHP runtime.
@@ -1093,10 +1092,11 @@ class BasePHP {
1093
1092
  * @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
1094
1093
  */
1095
1094
  constructor(e, t) {
1095
+ u(this, N);
1096
1096
  u(this, L);
1097
1097
  u(this, O);
1098
- u(this, M);
1099
1098
  u(this, q);
1099
+ u(this, M);
1100
1100
  u(this, D);
1101
1101
  u(this, $);
1102
1102
  u(this, j);
@@ -1104,7 +1104,6 @@ class BasePHP {
1104
1104
  u(this, z);
1105
1105
  u(this, G);
1106
1106
  u(this, V);
1107
- u(this, J);
1108
1107
  u(this, S, void 0);
1109
1108
  u(this, T, void 0);
1110
1109
  u(this, A, void 0);
@@ -1218,29 +1217,34 @@ class BasePHP {
1218
1217
  const t = await this.semaphore.acquire();
1219
1218
  let r;
1220
1219
  try {
1221
- if (l(this, y) || (f(this, L, 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))
1222
1221
  throw new Error(
1223
1222
  `The script path "${e.scriptPath}" does not exist.`
1224
1223
  );
1225
- f(this, W, oe).call(this, e.scriptPath || ""), f(this, M, te).call(this, e.relativeUri || ""), f(this, D, 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");
1226
1225
  const s = normalizeHeaders(e.headers || {}), n = s.host || "example.com:443";
1227
- f(this, q, re).call(this, n, e.protocol || "http"), f(this, $, 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, z, ae).call(this);
1228
- const i = e.env || {};
1229
- for (const a in i)
1230
- f(this, G, le).call(this, a, i[a]);
1231
- const o = await f(this, J, ue).call(this);
1232
- if (e.throwOnError && o.exitCode !== 0) {
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) {
1233
1232
  const a = {
1234
- stdout: o.text,
1235
- stderr: o.errors
1233
+ stdout: i.text,
1234
+ stderr: i.errors
1236
1235
  };
1237
1236
  console.warn("PHP.run() output was:", a);
1238
1237
  const c = new Error(
1239
- `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
1240
1239
  );
1241
1240
  throw c.output = a, console.error(c), c;
1242
1241
  }
1243
- return o;
1242
+ return i;
1243
+ } catch (s) {
1244
+ throw this.dispatchEvent({
1245
+ type: "request.error",
1246
+ error: s
1247
+ }), s;
1244
1248
  } finally {
1245
1249
  try {
1246
1250
  r && this[__private__dont__use].free(r);
@@ -1364,7 +1368,7 @@ class BasePHP {
1364
1368
  h(this, y, !1), h(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1365
1369
  }
1366
1370
  }
1367
- 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(), 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() {
1368
1372
  if (this.setPhpIniEntry("auto_prepend_file", "/internal/consts.php"), this.fileExists("/internal/consts.php") || this.writeFile(
1369
1373
  "/internal/consts.php",
1370
1374
  `<?php
@@ -1389,7 +1393,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1389
1393
  );
1390
1394
  }
1391
1395
  this[__private__dont__use].ccall("php_wasm_init", null, [], []);
1392
- }, O = new WeakSet(), ee = function() {
1396
+ }, L = new WeakSet(), X = function() {
1393
1397
  const e = "/internal/headers.json";
1394
1398
  if (!this.fileExists(e))
1395
1399
  throw new Error(
@@ -1399,14 +1403,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1399
1403
  for (const s of t.headers) {
1400
1404
  if (!s.includes(": "))
1401
1405
  continue;
1402
- const n = s.indexOf(": "), i = s.substring(0, n).toLowerCase(), o = s.substring(n + 2);
1403
- 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);
1404
1408
  }
1405
1409
  return {
1406
1410
  headers: r,
1407
1411
  httpStatusCode: t.status
1408
1412
  };
1409
- }, M = new WeakSet(), te = function(e) {
1413
+ }, O = new WeakSet(), ee = function(e) {
1410
1414
  if (this[__private__dont__use].ccall(
1411
1415
  "wasm_set_request_uri",
1412
1416
  null,
@@ -1421,7 +1425,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1421
1425
  [t]
1422
1426
  );
1423
1427
  }
1424
- }, q = new WeakSet(), re = function(e, t) {
1428
+ }, q = new WeakSet(), te = function(e, t) {
1425
1429
  this[__private__dont__use].ccall(
1426
1430
  "wasm_set_request_host",
1427
1431
  null,
@@ -1439,14 +1443,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1439
1443
  [NUMBER],
1440
1444
  [r]
1441
1445
  ), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
1442
- }, D = new WeakSet(), se = function(e) {
1446
+ }, M = new WeakSet(), re = function(e) {
1443
1447
  this[__private__dont__use].ccall(
1444
1448
  "wasm_set_request_method",
1445
1449
  null,
1446
1450
  [STRING],
1447
1451
  [e]
1448
1452
  );
1449
- }, $ = new WeakSet(), ne = function(e) {
1453
+ }, D = new WeakSet(), se = function(e) {
1450
1454
  e.cookie && this[__private__dont__use].ccall(
1451
1455
  "wasm_set_cookies",
1452
1456
  null,
@@ -1470,7 +1474,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1470
1474
  e[t]
1471
1475
  );
1472
1476
  }
1473
- }, j = new WeakSet(), ie = function(e) {
1477
+ }, $ = new WeakSet(), ne = function(e) {
1474
1478
  let t, r;
1475
1479
  typeof e == "string" ? (console.warn(
1476
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"
@@ -1493,14 +1497,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1493
1497
  [NUMBER],
1494
1498
  [r]
1495
1499
  ), s;
1496
- }, W = new WeakSet(), oe = function(e) {
1500
+ }, j = new WeakSet(), ie = function(e) {
1497
1501
  this[__private__dont__use].ccall(
1498
1502
  "wasm_set_path_translated",
1499
1503
  null,
1500
1504
  [STRING],
1501
1505
  [e]
1502
1506
  );
1503
- }, z = new WeakSet(), ae = function() {
1507
+ }, W = new WeakSet(), oe = function() {
1504
1508
  for (const e in l(this, g))
1505
1509
  this[__private__dont__use].ccall(
1506
1510
  "wasm_add_SERVER_entry",
@@ -1508,30 +1512,30 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1508
1512
  [STRING, STRING],
1509
1513
  [e, l(this, g)[e]]
1510
1514
  );
1511
- }, G = new WeakSet(), le = function(e, t) {
1515
+ }, z = new WeakSet(), ae = function(e, t) {
1512
1516
  this[__private__dont__use].ccall(
1513
1517
  "wasm_add_ENV_entry",
1514
1518
  null,
1515
1519
  [STRING, STRING],
1516
1520
  [e, t]
1517
1521
  );
1518
- }, V = new WeakSet(), ce = function(e) {
1522
+ }, G = new WeakSet(), le = function(e) {
1519
1523
  this[__private__dont__use].ccall(
1520
1524
  "wasm_set_php_code",
1521
1525
  null,
1522
1526
  [STRING],
1523
1527
  [e]
1524
1528
  );
1525
- }, J = new WeakSet(), ue = async function() {
1529
+ }, V = new WeakSet(), ce = async function() {
1526
1530
  var n;
1527
1531
  let e, t;
1528
1532
  try {
1529
- e = await new Promise((i, o) => {
1533
+ e = await new Promise((o, i) => {
1530
1534
  var c;
1531
1535
  t = (d) => {
1532
1536
  console.error(d), console.error(d.error);
1533
- const p = new Error("Rethrown");
1534
- p.cause = d.error, p.betterMessage = d.message, o(p);
1537
+ const _ = new Error("Rethrown");
1538
+ _.cause = d.error, _.betterMessage = d.message, i(_);
1535
1539
  }, (c = l(this, w)) == null || c.addEventListener(
1536
1540
  "error",
1537
1541
  t
@@ -1543,9 +1547,9 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1543
1547
  [],
1544
1548
  { async: !0 }
1545
1549
  );
1546
- return a instanceof Promise ? a.then(i, o) : i(a);
1550
+ return a instanceof Promise ? a.then(o, i) : o(a);
1547
1551
  });
1548
- } catch (i) {
1552
+ } catch (o) {
1549
1553
  for (const d in this)
1550
1554
  typeof this[d] == "function" && (this[d] = () => {
1551
1555
  throw new Error(
@@ -1553,12 +1557,12 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1553
1557
  );
1554
1558
  });
1555
1559
  this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
1556
- const o = i, a = "betterMessage" in o ? o.betterMessage : o.message, c = new Error(a);
1557
- 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;
1558
1562
  } finally {
1559
1563
  (n = l(this, w)) == null || n.removeEventListener("error", t), h(this, g, {});
1560
1564
  }
1561
- const { headers: r, httpStatusCode: s } = f(this, O, ee).call(this);
1565
+ const { headers: r, httpStatusCode: s } = f(this, L, X).call(this);
1562
1566
  return new PHPResponse(
1563
1567
  s,
1564
1568
  r,
@@ -1617,9 +1621,9 @@ function copyFS(e, t, r) {
1617
1621
  return;
1618
1622
  }
1619
1623
  t.mkdirTree(r);
1620
- const n = e.readdir(r).filter((i) => i !== "." && i !== "..");
1621
- for (const i of n)
1622
- 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));
1623
1627
  }
1624
1628
  function isLocalPHP(e) {
1625
1629
  return !(e instanceof BasePHP);
@@ -1637,11 +1641,11 @@ function rotatePHPRuntime({
1637
1641
  if (++s < r)
1638
1642
  return;
1639
1643
  s = 0;
1640
- const i = await e.semaphore.acquire();
1644
+ const o = await e.semaphore.acquire();
1641
1645
  try {
1642
1646
  e.hotSwapPHPRuntime(await t());
1643
1647
  } finally {
1644
- i();
1648
+ o();
1645
1649
  }
1646
1650
  }
1647
1651
  return e.addEventListener("request.end", n), function() {
@@ -1650,9 +1654,9 @@ function rotatePHPRuntime({
1650
1654
  }
1651
1655
  async function writeFiles(e, t, r, { rmRoot: s = !1 } = {}) {
1652
1656
  s && await e.isDir(t) && await e.rmdir(t, { recursive: !0 });
1653
- for (const [n, i] of Object.entries(r)) {
1654
- const o = joinPaths(t, n);
1655
- 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);
1656
1660
  }
1657
1661
  }
1658
1662
  export {
@@ -1668,6 +1672,7 @@ export {
1668
1672
  SupportedPHPVersionsList,
1669
1673
  UnhandledRejectionsTarget,
1670
1674
  __private__dont__use,
1675
+ applyRewriteRules,
1671
1676
  ensurePathPrefix,
1672
1677
  isExitCodeZero,
1673
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.7",
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": "c4c52563eee8997b94cd4a0875e10fb5d8ccda42",
39
+ "gitHead": "cb7b1af260489022238495a2fc0d96f767a1294a",
40
40
  "engines": {
41
41
  "node": ">=18.18.2",
42
42
  "npm": ">=8.11.0"