@php-wasm/universal 0.6.7 → 0.6.9

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.split("#")[0],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,q,ee,O,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,q);u(this,O);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,q,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,O,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(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,c.source="request",console.error(c),c}return i}catch(s){throw this.dispatchEvent({type:"request.error",error:s,source:s.source??"php-wasm"}),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}},q=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])}},O=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() {
@@ -788,16 +789,17 @@ class PHPRequestHandler {
788
789
  /** @inheritDoc */
789
790
  async request(t) {
790
791
  const r = t.url.startsWith("http://") || t.url.startsWith("https://"), s = new URL(
791
- t.url,
792
+ // Remove the hash part of the URL as it's not meant for the server.
793
+ t.url.split("#")[0],
792
794
  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);
795
+ ), n = applyRewriteRules(
796
+ removePathPrefix(s.pathname, l(this, p)),
797
+ this.rewriteRules
798
+ ), o = `${l(this, m)}${n}`;
799
+ return seemsLikeAPHPRequestHandlerPath(o) ? await f(this, B, Y).call(this, t, s) : f(this, U, Q).call(this, o);
798
800
  }
799
801
  }
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) {
802
+ 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
803
  if (!this.php.fileExists(t))
802
804
  return new PHPResponse(
803
805
  404,
@@ -822,8 +824,8 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
822
824
  },
823
825
  r
824
826
  );
825
- }, I = new WeakSet(), K = async function(t, r) {
826
- var n, i;
827
+ }, B = new WeakSet(), Y = async function(t, r) {
828
+ var n;
827
829
  if (l(this, R).running > 0 && ((n = t.headers) == null ? void 0 : n["x-request-issuer"]) === "php")
828
830
  return console.warn(
829
831
  "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 +838,22 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
836
838
  try {
837
839
  this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", l(this, m)), this.php.addServerGlobalEntry(
838
840
  "HTTPS",
839
- l(this, F).startsWith("https://") ? "on" : ""
841
+ l(this, x).startsWith("https://") ? "on" : ""
840
842
  );
841
843
  let o = "GET";
842
- const a = {
843
- host: l(this, x),
844
+ const i = {
845
+ host: l(this, F),
844
846
  ...normalizeHeaders(t.headers || {})
845
847
  };
846
- let c = t.body;
847
- if (typeof c == "object" && !(c instanceof Uint8Array)) {
848
+ let a = t.body;
849
+ if (typeof a == "object" && !(a instanceof Uint8Array)) {
848
850
  o = "POST";
849
- const { bytes: p, contentType: U } = await encodeAsMultipart(c);
850
- c = p, a["content-type"] = U;
851
+ const { bytes: d, contentType: _ } = await encodeAsMultipart(a);
852
+ a = d, i["content-type"] = _;
851
853
  }
852
- let d;
854
+ let c;
853
855
  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);
856
+ c = f(this, I, K).call(this, r.pathname);
863
857
  } catch {
864
858
  return new PHPResponse(
865
859
  404,
@@ -870,20 +864,20 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
870
864
  return await this.php.run({
871
865
  relativeUri: ensurePathPrefix(
872
866
  toRelativeUrl(r),
873
- l(this, _)
867
+ l(this, p)
874
868
  ),
875
869
  protocol: l(this, H),
876
870
  method: t.method || o,
877
- body: c,
878
- scriptPath: d,
879
- headers: a
871
+ body: a,
872
+ scriptPath: c,
873
+ headers: i
880
874
  });
881
875
  } finally {
882
876
  s();
883
877
  }
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";
878
+ }, I = new WeakSet(), K = function(t) {
879
+ let r = removePathPrefix(t, l(this, p));
880
+ 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
881
  const s = `${l(this, m)}${r}`;
888
882
  if (this.php.fileExists(s))
889
883
  return s;
@@ -938,6 +932,12 @@ function seemsLikeAPHPFile(e) {
938
932
  function seemsLikeADirectoryRoot(e) {
939
933
  return !e.split("/").pop().includes(".");
940
934
  }
935
+ function applyRewriteRules(e, t) {
936
+ for (const r of t)
937
+ if (new RegExp(r.match).test(e))
938
+ return e.replace(r.match, r.replacement);
939
+ return e;
940
+ }
941
941
  const FileErrorCodes = {
942
942
  0: "No error occurred. System call completed successfully.",
943
943
  1: "Argument list too long.",
@@ -1024,15 +1024,15 @@ function getEmscriptenFsError(e) {
1024
1024
  }
1025
1025
  function rethrowFileSystemError(e = "") {
1026
1026
  return function(r, s, n) {
1027
- const i = n.value;
1028
- n.value = function(...o) {
1027
+ const o = n.value;
1028
+ n.value = function(...i) {
1029
1029
  try {
1030
- return i.apply(this, o);
1030
+ return o.apply(this, i);
1031
1031
  } catch (a) {
1032
1032
  const c = typeof a == "object" ? a == null ? void 0 : a.errno : null;
1033
1033
  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}`, {
1034
+ const d = FileErrorCodes[c], _ = typeof i[0] == "string" ? i[0] : null, ue = _ !== null ? e.replaceAll("{path}", _) : e;
1035
+ throw new Error(`${ue}: ${d}`, {
1036
1036
  cause: a
1037
1037
  });
1038
1038
  }
@@ -1044,7 +1044,7 @@ function rethrowFileSystemError(e = "") {
1044
1044
  const RuntimeId = Symbol("RuntimeId"), loadedRuntimes = /* @__PURE__ */ new Map();
1045
1045
  let lastRuntimeId = 0;
1046
1046
  async function loadPHPRuntime(e, t = {}) {
1047
- const [r, s, n] = makePromise(), i = e.init(currentJsRuntime, {
1047
+ const [r, s, n] = makePromise(), o = e.init(currentJsRuntime, {
1048
1048
  onAbort(a) {
1049
1049
  n(a), console.error(a);
1050
1050
  },
@@ -1060,10 +1060,10 @@ async function loadPHPRuntime(e, t = {}) {
1060
1060
  }
1061
1061
  });
1062
1062
  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;
1063
+ const i = ++lastRuntimeId;
1064
+ return o.id = i, o.originalExit = o._exit, o._exit = function(a) {
1065
+ return loadedRuntimes.delete(i), o.originalExit(a);
1066
+ }, o[RuntimeId] = i, loadedRuntimes.set(i, o), i;
1067
1067
  }
1068
1068
  function getLoadedRuntime(e) {
1069
1069
  return loadedRuntimes.get(e);
@@ -1078,12 +1078,12 @@ const currentJsRuntime = function() {
1078
1078
  return e.unshift(t), e;
1079
1079
  };
1080
1080
  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);
1081
+ for (var n = s > 1 ? void 0 : s ? __getOwnPropDesc(t, r) : t, o = e.length - 1, i; o >= 0; o--)
1082
+ (i = e[o]) && (n = (s ? i(t, r, n) : i(n)) || n);
1083
1083
  return s && n && __defProp(t, r, n), n;
1084
1084
  };
1085
1085
  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;
1086
+ var S, T, A, y, w, g, P, C, N, Z, L, X, q, ee, O, te, M, re, D, se, $, ne, j, ie, W, oe, z, ae, G, le, V, ce;
1087
1087
  class BasePHP {
1088
1088
  /**
1089
1089
  * Initializes a PHP runtime.
@@ -1093,10 +1093,11 @@ class BasePHP {
1093
1093
  * @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
1094
1094
  */
1095
1095
  constructor(e, t) {
1096
+ u(this, N);
1096
1097
  u(this, L);
1098
+ u(this, q);
1097
1099
  u(this, O);
1098
1100
  u(this, M);
1099
- u(this, q);
1100
1101
  u(this, D);
1101
1102
  u(this, $);
1102
1103
  u(this, j);
@@ -1104,7 +1105,6 @@ class BasePHP {
1104
1105
  u(this, z);
1105
1106
  u(this, G);
1106
1107
  u(this, V);
1107
- u(this, J);
1108
1108
  u(this, S, void 0);
1109
1109
  u(this, T, void 0);
1110
1110
  u(this, A, void 0);
@@ -1218,29 +1218,36 @@ class BasePHP {
1218
1218
  const t = await this.semaphore.acquire();
1219
1219
  let r;
1220
1220
  try {
1221
- if (l(this, y) || (f(this, L, X).call(this), h(this, y, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
1221
+ if (l(this, y) || (f(this, N, Z).call(this), h(this, y, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
1222
1222
  throw new Error(
1223
1223
  `The script path "${e.scriptPath}" does not exist.`
1224
1224
  );
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");
1225
+ f(this, j, ie).call(this, e.scriptPath || ""), f(this, q, ee).call(this, e.relativeUri || ""), f(this, M, re).call(this, e.method || "GET");
1226
1226
  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) {
1227
+ f(this, O, 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);
1228
+ const o = e.env || {};
1229
+ for (const a in o)
1230
+ f(this, z, ae).call(this, a, o[a]);
1231
+ const i = await f(this, V, ce).call(this);
1232
+ if (i.exitCode !== 0) {
1233
1233
  const a = {
1234
- stdout: o.text,
1235
- stderr: o.errors
1234
+ stdout: i.text,
1235
+ stderr: i.errors
1236
1236
  };
1237
1237
  console.warn("PHP.run() output was:", a);
1238
1238
  const c = new Error(
1239
- `PHP.run() failed with exit code ${o.exitCode} and the following output: ` + o.errors
1239
+ `PHP.run() failed with exit code ${i.exitCode} and the following output: ` + i.errors
1240
1240
  );
1241
- throw c.output = a, console.error(c), c;
1241
+ throw c.output = a, c.source = "request", console.error(c), c;
1242
1242
  }
1243
- return o;
1243
+ return i;
1244
+ } catch (s) {
1245
+ throw this.dispatchEvent({
1246
+ type: "request.error",
1247
+ error: s,
1248
+ // Distinguish between PHP request and PHP-wasm errors
1249
+ source: s.source ?? "php-wasm"
1250
+ }), s;
1244
1251
  } finally {
1245
1252
  try {
1246
1253
  r && this[__private__dont__use].free(r);
@@ -1364,7 +1371,7 @@ class BasePHP {
1364
1371
  h(this, y, !1), h(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1365
1372
  }
1366
1373
  }
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() {
1374
+ 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
1375
  if (this.setPhpIniEntry("auto_prepend_file", "/internal/consts.php"), this.fileExists("/internal/consts.php") || this.writeFile(
1369
1376
  "/internal/consts.php",
1370
1377
  `<?php
@@ -1389,7 +1396,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1389
1396
  );
1390
1397
  }
1391
1398
  this[__private__dont__use].ccall("php_wasm_init", null, [], []);
1392
- }, O = new WeakSet(), ee = function() {
1399
+ }, L = new WeakSet(), X = function() {
1393
1400
  const e = "/internal/headers.json";
1394
1401
  if (!this.fileExists(e))
1395
1402
  throw new Error(
@@ -1399,14 +1406,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1399
1406
  for (const s of t.headers) {
1400
1407
  if (!s.includes(": "))
1401
1408
  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);
1409
+ const n = s.indexOf(": "), o = s.substring(0, n).toLowerCase(), i = s.substring(n + 2);
1410
+ o in r || (r[o] = []), r[o].push(i);
1404
1411
  }
1405
1412
  return {
1406
1413
  headers: r,
1407
1414
  httpStatusCode: t.status
1408
1415
  };
1409
- }, M = new WeakSet(), te = function(e) {
1416
+ }, q = new WeakSet(), ee = function(e) {
1410
1417
  if (this[__private__dont__use].ccall(
1411
1418
  "wasm_set_request_uri",
1412
1419
  null,
@@ -1421,7 +1428,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1421
1428
  [t]
1422
1429
  );
1423
1430
  }
1424
- }, q = new WeakSet(), re = function(e, t) {
1431
+ }, O = new WeakSet(), te = function(e, t) {
1425
1432
  this[__private__dont__use].ccall(
1426
1433
  "wasm_set_request_host",
1427
1434
  null,
@@ -1439,14 +1446,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1439
1446
  [NUMBER],
1440
1447
  [r]
1441
1448
  ), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
1442
- }, D = new WeakSet(), se = function(e) {
1449
+ }, M = new WeakSet(), re = function(e) {
1443
1450
  this[__private__dont__use].ccall(
1444
1451
  "wasm_set_request_method",
1445
1452
  null,
1446
1453
  [STRING],
1447
1454
  [e]
1448
1455
  );
1449
- }, $ = new WeakSet(), ne = function(e) {
1456
+ }, D = new WeakSet(), se = function(e) {
1450
1457
  e.cookie && this[__private__dont__use].ccall(
1451
1458
  "wasm_set_cookies",
1452
1459
  null,
@@ -1470,7 +1477,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1470
1477
  e[t]
1471
1478
  );
1472
1479
  }
1473
- }, j = new WeakSet(), ie = function(e) {
1480
+ }, $ = new WeakSet(), ne = function(e) {
1474
1481
  let t, r;
1475
1482
  typeof e == "string" ? (console.warn(
1476
1483
  "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 +1500,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1493
1500
  [NUMBER],
1494
1501
  [r]
1495
1502
  ), s;
1496
- }, W = new WeakSet(), oe = function(e) {
1503
+ }, j = new WeakSet(), ie = function(e) {
1497
1504
  this[__private__dont__use].ccall(
1498
1505
  "wasm_set_path_translated",
1499
1506
  null,
1500
1507
  [STRING],
1501
1508
  [e]
1502
1509
  );
1503
- }, z = new WeakSet(), ae = function() {
1510
+ }, W = new WeakSet(), oe = function() {
1504
1511
  for (const e in l(this, g))
1505
1512
  this[__private__dont__use].ccall(
1506
1513
  "wasm_add_SERVER_entry",
@@ -1508,30 +1515,30 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1508
1515
  [STRING, STRING],
1509
1516
  [e, l(this, g)[e]]
1510
1517
  );
1511
- }, G = new WeakSet(), le = function(e, t) {
1518
+ }, z = new WeakSet(), ae = function(e, t) {
1512
1519
  this[__private__dont__use].ccall(
1513
1520
  "wasm_add_ENV_entry",
1514
1521
  null,
1515
1522
  [STRING, STRING],
1516
1523
  [e, t]
1517
1524
  );
1518
- }, V = new WeakSet(), ce = function(e) {
1525
+ }, G = new WeakSet(), le = function(e) {
1519
1526
  this[__private__dont__use].ccall(
1520
1527
  "wasm_set_php_code",
1521
1528
  null,
1522
1529
  [STRING],
1523
1530
  [e]
1524
1531
  );
1525
- }, J = new WeakSet(), ue = async function() {
1532
+ }, V = new WeakSet(), ce = async function() {
1526
1533
  var n;
1527
1534
  let e, t;
1528
1535
  try {
1529
- e = await new Promise((i, o) => {
1536
+ e = await new Promise((o, i) => {
1530
1537
  var c;
1531
1538
  t = (d) => {
1532
1539
  console.error(d), console.error(d.error);
1533
- const p = new Error("Rethrown");
1534
- p.cause = d.error, p.betterMessage = d.message, o(p);
1540
+ const _ = new Error("Rethrown");
1541
+ _.cause = d.error, _.betterMessage = d.message, i(_);
1535
1542
  }, (c = l(this, w)) == null || c.addEventListener(
1536
1543
  "error",
1537
1544
  t
@@ -1543,9 +1550,9 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1543
1550
  [],
1544
1551
  { async: !0 }
1545
1552
  );
1546
- return a instanceof Promise ? a.then(i, o) : i(a);
1553
+ return a instanceof Promise ? a.then(o, i) : o(a);
1547
1554
  });
1548
- } catch (i) {
1555
+ } catch (o) {
1549
1556
  for (const d in this)
1550
1557
  typeof this[d] == "function" && (this[d] = () => {
1551
1558
  throw new Error(
@@ -1553,12 +1560,12 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
1553
1560
  );
1554
1561
  });
1555
1562
  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;
1563
+ const i = o, a = "betterMessage" in i ? i.betterMessage : i.message, c = new Error(a);
1564
+ throw c.cause = i, console.error(c), c;
1558
1565
  } finally {
1559
1566
  (n = l(this, w)) == null || n.removeEventListener("error", t), h(this, g, {});
1560
1567
  }
1561
- const { headers: r, httpStatusCode: s } = f(this, O, ee).call(this);
1568
+ const { headers: r, httpStatusCode: s } = f(this, L, X).call(this);
1562
1569
  return new PHPResponse(
1563
1570
  s,
1564
1571
  r,
@@ -1617,9 +1624,9 @@ function copyFS(e, t, r) {
1617
1624
  return;
1618
1625
  }
1619
1626
  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));
1627
+ const n = e.readdir(r).filter((o) => o !== "." && o !== "..");
1628
+ for (const o of n)
1629
+ copyFS(e, t, joinPaths(r, o));
1623
1630
  }
1624
1631
  function isLocalPHP(e) {
1625
1632
  return !(e instanceof BasePHP);
@@ -1637,11 +1644,11 @@ function rotatePHPRuntime({
1637
1644
  if (++s < r)
1638
1645
  return;
1639
1646
  s = 0;
1640
- const i = await e.semaphore.acquire();
1647
+ const o = await e.semaphore.acquire();
1641
1648
  try {
1642
1649
  e.hotSwapPHPRuntime(await t());
1643
1650
  } finally {
1644
- i();
1651
+ o();
1645
1652
  }
1646
1653
  }
1647
1654
  return e.addEventListener("request.end", n), function() {
@@ -1650,9 +1657,9 @@ function rotatePHPRuntime({
1650
1657
  }
1651
1658
  async function writeFiles(e, t, r, { rmRoot: s = !1 } = {}) {
1652
1659
  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);
1660
+ for (const [n, o] of Object.entries(r)) {
1661
+ const i = joinPaths(t, n);
1662
+ await e.fileExists(dirname(i)) || await e.mkdir(dirname(i)), await e.writeFile(i, o);
1656
1663
  }
1657
1664
  }
1658
1665
  export {
@@ -1668,6 +1675,7 @@ export {
1668
1675
  SupportedPHPVersionsList,
1669
1676
  UnhandledRejectionsTarget,
1670
1677
  __private__dont__use,
1678
+ applyRewriteRules,
1671
1679
  ensurePathPrefix,
1672
1680
  isExitCodeZero,
1673
1681
  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,14 @@ 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
+ source?: 'request' | 'php-wasm';
16
+ }
9
17
  /**
10
18
  * Represents a PHP runtime initialization event.
11
19
  */
@@ -23,7 +31,7 @@ export interface PHPRuntimeBeforeDestroyEvent {
23
31
  * This is intentionally not an extension of CustomEvent
24
32
  * to make it isomorphic between different JavaScript runtimes.
25
33
  */
26
- export type PHPEvent = PHPRequestEndEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeDestroyEvent;
34
+ export type PHPEvent = PHPRequestEndEvent | PHPRequestErrorEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeDestroyEvent;
27
35
  /**
28
36
  * A callback function that handles PHP events.
29
37
  */
@@ -470,11 +478,6 @@ export interface PHPRunOptions {
470
478
  * The code snippet to eval instead of a php file.
471
479
  */
472
480
  code?: string;
473
- /**
474
- * Whether to throw an error if the PHP process exits with a non-zero code
475
- * or outputs to stderr.
476
- */
477
- throwOnError?: boolean;
478
481
  }
479
482
  /**
480
483
  * Output of the PHP.wasm runtime.
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.9",
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": "f6b98ad6d05617ee8cb1234c21318fdde17a6e56",
40
40
  "engines": {
41
41
  "node": ">=18.18.2",
42
42
  "npm": ">=8.11.0"