@php-wasm/universal 0.6.3 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var J=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var a=(e,t,r)=>(J(e,t,"read from private field"),r?r.call(e):t.get(e)),c=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r)},h=(e,t,r,s)=>(J(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var p=(e,t,r)=>(J(e,t,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});if(typeof File>"u"){class e extends Blob{constructor(r,s,n){super(r);let i;n!=null&&n.lastModified&&(i=new Date),(!i||isNaN(i.getFullYear()))&&(i=new Date),this.lastModifiedDate=i,this.lastModified=i.getMilliseconds(),this.name=s||""}}global.File=e}function asPromise(e){return new Promise(function(t,r){e.onload=e.onerror=function(s){e.onload=e.onerror=null,s.type==="load"?t(e.result):r(new Error("Failed to read the blob/file"))}})}typeof Blob.prototype.arrayBuffer>"u"&&(Blob.prototype.arrayBuffer=function(){const t=new FileReader;return t.readAsArrayBuffer(this),asPromise(t)});typeof Blob.prototype.text>"u"&&(Blob.prototype.text=function(){const t=new FileReader;return t.readAsText(this),asPromise(t)});function isByobSupported(){const e=new Uint8Array([1,2,3,4]),r=new File([e],"test").stream();try{return r.getReader({mode:"byob"}),!0}catch{return!1}}(typeof Blob.prototype.stream>"u"||!isByobSupported())&&(Blob.prototype.stream=function(){let e=0;const t=this;return new ReadableStream({type:"bytes",autoAllocateChunkSize:512*1024,async pull(r){const s=r.byobRequest.view,i=await t.slice(e,e+s.byteLength).arrayBuffer(),o=new Uint8Array(i);new Uint8Array(s.buffer).set(o);const l=o.byteLength;r.byobRequest.respond(l),e+=l,e>=t.size&&r.close()}})});if(typeof CustomEvent>"u"){class e extends Event{constructor(r,s={}){super(r,s),this.detail=s.detail}initCustomEvent(){}}globalThis.CustomEvent=e}const kError=Symbol("error"),kMessage=Symbol("message");class ErrorEvent2 extends Event{constructor(t,r={}){super(t),this[kError]=r.error===void 0?null:r.error,this[kMessage]=r.message===void 0?"":r.message}get error(){return this[kError]}get message(){return this[kMessage]}}Object.defineProperty(ErrorEvent2.prototype,"error",{enumerable:!0});Object.defineProperty(ErrorEvent2.prototype,"message",{enumerable:!0});const ErrorEvent=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:ErrorEvent2;function isExitCodeZero(e){return e instanceof Error?"exitCode"in e&&(e==null?void 0:e.exitCode)===0||(e==null?void 0:e.name)==="ExitStatus"&&"status"in e&&e.status===0:!1}class UnhandledRejectionsTarget extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(t,r){++this.listenersCount,super.addEventListener(t,r)}removeEventListener(t,r){--this.listenersCount,super.removeEventListener(t,r)}hasListeners(){return this.listenersCount>0}}function improveWASMErrorReporting(e){e.asm={...e.asm};const t=new UnhandledRejectionsTarget;for(const r in e.asm)if(typeof e.asm[r]=="function"){const s=e.asm[r];e.asm[r]=function(...n){var i;try{return s(...n)}catch(o){if(!(o instanceof Error))throw o;const l=clarifyErrorMessage(o,(i=e.lastAsyncifyStackSource)==null?void 0:i.stack);if(e.lastAsyncifyStackSource&&(o.cause=e.lastAsyncifyStackSource),t.hasListeners()){t.dispatchEvent(new ErrorEvent("error",{error:o,message:l}));return}throw isExitCodeZero(o)||showCriticalErrorBox(l),o}}}return t}let functionsMaybeMissingFromAsyncify=[];function getFunctionsMaybeMissingFromAsyncify(){return functionsMaybeMissingFromAsyncify}function clarifyErrorMessage(e,t){if(e.message==="unreachable"){let r=UNREACHABLE_ERROR;t||(r+=`
1
+ "use strict";var J=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var a=(e,t,r)=>(J(e,t,"read from private field"),r?r.call(e):t.get(e)),u=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r)},h=(e,t,r,s)=>(J(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var p=(e,t,r)=>(J(e,t,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});if(typeof File>"u"){class e extends Blob{constructor(r,s,n){super(r);let i;n!=null&&n.lastModified&&(i=new Date),(!i||isNaN(i.getFullYear()))&&(i=new Date),this.lastModifiedDate=i,this.lastModified=i.getMilliseconds(),this.name=s||""}}global.File=e}function asPromise(e){return new Promise(function(t,r){e.onload=e.onerror=function(s){e.onload=e.onerror=null,s.type==="load"?t(e.result):r(new Error("Failed to read the blob/file"))}})}typeof Blob.prototype.arrayBuffer>"u"&&(Blob.prototype.arrayBuffer=function(){const t=new FileReader;return t.readAsArrayBuffer(this),asPromise(t)});typeof Blob.prototype.text>"u"&&(Blob.prototype.text=function(){const t=new FileReader;return t.readAsText(this),asPromise(t)});function isByobSupported(){const e=new Uint8Array([1,2,3,4]),r=new File([e],"test").stream();try{return r.getReader({mode:"byob"}),!0}catch{return!1}}(typeof Blob.prototype.stream>"u"||!isByobSupported())&&(Blob.prototype.stream=function(){let e=0;const t=this;return new ReadableStream({type:"bytes",autoAllocateChunkSize:512*1024,async pull(r){const s=r.byobRequest.view,i=await t.slice(e,e+s.byteLength).arrayBuffer(),o=new Uint8Array(i);new Uint8Array(s.buffer).set(o);const l=o.byteLength;r.byobRequest.respond(l),e+=l,e>=t.size&&r.close()}})});if(typeof CustomEvent>"u"){class e extends Event{constructor(r,s={}){super(r,s),this.detail=s.detail}initCustomEvent(){}}globalThis.CustomEvent=e}const kError=Symbol("error"),kMessage=Symbol("message");class ErrorEvent2 extends Event{constructor(t,r={}){super(t),this[kError]=r.error===void 0?null:r.error,this[kMessage]=r.message===void 0?"":r.message}get error(){return this[kError]}get message(){return this[kMessage]}}Object.defineProperty(ErrorEvent2.prototype,"error",{enumerable:!0});Object.defineProperty(ErrorEvent2.prototype,"message",{enumerable:!0});const ErrorEvent=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:ErrorEvent2;function isExitCodeZero(e){return e instanceof Error?"exitCode"in e&&(e==null?void 0:e.exitCode)===0||(e==null?void 0:e.name)==="ExitStatus"&&"status"in e&&e.status===0:!1}class UnhandledRejectionsTarget extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(t,r){++this.listenersCount,super.addEventListener(t,r)}removeEventListener(t,r){--this.listenersCount,super.removeEventListener(t,r)}hasListeners(){return this.listenersCount>0}}function improveWASMErrorReporting(e){e.asm={...e.asm};const t=new UnhandledRejectionsTarget;for(const r in e.asm)if(typeof e.asm[r]=="function"){const s=e.asm[r];e.asm[r]=function(...n){var i;try{return s(...n)}catch(o){if(!(o instanceof Error))throw o;const l=clarifyErrorMessage(o,(i=e.lastAsyncifyStackSource)==null?void 0:i.stack);if(e.lastAsyncifyStackSource&&(o.cause=e.lastAsyncifyStackSource),t.hasListeners()){t.dispatchEvent(new ErrorEvent("error",{error:o,message:l}));return}throw isExitCodeZero(o)||showCriticalErrorBox(l),o}}}return t}let functionsMaybeMissingFromAsyncify=[];function getFunctionsMaybeMissingFromAsyncify(){return functionsMaybeMissingFromAsyncify}function clarifyErrorMessage(e,t){if(e.message==="unreachable"){let r=UNREACHABLE_ERROR;t||(r+=`
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,21 +32,21 @@ 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 createSpawnHandler(e){return function(t){const r=new ChildProcess,s=new ProcessApi(r);return setTimeout(async()=>{await e(t,s),r.emit("spawn",!0)}),r}}class EventEmitter{constructor(){this.listeners={}}emit(t,r){this.listeners[t]&&this.listeners[t].forEach(function(s){s(r)})}on(t,r){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(r)}}class ProcessApi extends EventEmitter{constructor(t){super(),this.childProcess=t,this.exited=!1,this.stdinData=[],t.on("stdin",r=>{this.stdinData?this.stdinData.push(r.slice()):this.emit("stdin",r)})}stdout(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stdout.emit("data",t)}stderr(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stderr.emit("data",t)}exit(t){this.exited||(this.exited=!0,this.childProcess.emit("exit",t))}flushStdin(){if(this.stdinData)for(let t=0;t<this.stdinData.length;t++)this.emit("stdin",this.stdinData[t]);this.stdinData=null}}let lastPid=9743;class ChildProcess extends EventEmitter{constructor(t=lastPid++){super(),this.pid=t,this.stdout=new EventEmitter,this.stderr=new EventEmitter;const r=this;this.stdin={write:s=>{r.emit("stdin",s)}}}}function concatUint8Array(...e){const t=new Uint8Array(e.reduce((s,n)=>s+n.length,0));let r=0;for(const s of e)t.set(s,r),r+=s.length;return t}function concatBytes(e){if(e===void 0){let t=new Uint8Array;return new TransformStream({transform(r){t=concatUint8Array(t,r)},flush(r){r.enqueue(t)}})}else{const t=new ArrayBuffer(e||0);let r=0;return new TransformStream({transform(s){new Uint8Array(t).set(s,r),r+=s.byteLength},flush(s){s.enqueue(new Uint8Array(t))}})}}function limitBytes(e,t){if(t===0)return new ReadableStream({start(n){n.close()}});const r=e.getReader({mode:"byob"});let s=0;return new ReadableStream({async pull(n){const{value:i,done:o}=await r.read(new Uint8Array(t-s));if(o){r.releaseLock(),n.close();return}s+=i.length,n.enqueue(i),s>=t&&(r.releaseLock(),n.close())},cancel(){r.cancel()}})}async function collectBytes(e,t){return t!==void 0&&(e=limitBytes(e,t)),await e.pipeThrough(concatBytes(t)).getReader().read().then(({value:r})=>r)}class StreamedFile extends File{constructor(t,r,s){super([],r,{type:s}),this.readableStream=t}slice(){throw new Error("slice() is not possible on a StreamedFile")}stream(){return this.readableStream}async text(){return new TextDecoder().decode(await this.arrayBuffer())}async arrayBuffer(){return await collectBytes(this.stream())}}ReadableStream.prototype[Symbol.asyncIterator]||(ReadableStream.prototype[Symbol.asyncIterator]=async function*(){const e=this.getReader();try{for(;;){const{done:t,value:r}=await e.read();if(t)return;yield r}}finally{e.releaseLock()}},ReadableStream.prototype.iterate=ReadableStream.prototype[Symbol.asyncIterator]);function streamReadFileFromPHP(e,t){return new ReadableStream({async pull(r){const s=await e.readFileAsBuffer(t);r.enqueue(s),r.close()}})}async function*iteratePhpFiles(e,t,{relativePaths:r=!0,pathPrefix:s,exceptPaths:n=[]}={}){t=normalizePath(t);const i=[t];for(;i.length;){const o=i.pop();if(!o)return;const l=await e.listFiles(o);for(const d of l){const u=`${o}/${d}`;if(n.includes(u.substring(t.length+1)))continue;await e.isDir(u)?i.push(u):yield new StreamedFile(streamReadFileFromPHP(e,u),r?joinPaths(s||"",u.substring(t.length+1)):u)}}}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,S;class PHPBrowser{constructor(t,r={}){c(this,E,void 0);c(this,S,void 0);this.requestHandler=t,h(this,E,{}),h(this,S,{handleRedirects:!1,maxRedirects:4,...r})}async request(t,r=0){const s=await this.requestHandler.request({...t,headers:{...t.headers,cookie:this.serializeCookies()}});if(s.headers["set-cookie"]&&this.setCookies(s.headers["set-cookie"]),a(this,S).handleRedirects&&s.headers.location&&r<a(this,S).maxRedirects){const n=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:n.toString(),method:"GET",headers:{}},r+1)}return s}pathToInternalUrl(t){return this.requestHandler.pathToInternalUrl(t)}internalUrlToPath(t){return this.requestHandler.internalUrlToPath(t)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}setCookies(t){for(const r of t)try{if(!r.includes("="))continue;const s=r.indexOf("="),n=r.substring(0,s),i=r.substring(s+1).split(";")[0];a(this,E)[n]=i}catch(s){console.error(s)}}serializeCookies(){const t=[];for(const r in a(this,E))t.push(`${r}=${a(this,E)[r]}`);return t.join("; ")}}E=new WeakMap,S=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[d,u]of Object.entries(e))n.push(`--${t}\r
36
- `),n.push(`Content-Disposition: form-data; name="${d}"`),u instanceof File&&n.push(`; filename="${u.name}"`),n.push(`\r
37
- `),u instanceof File&&n.push("Content-Type: application/octet-stream"),n.push(`\r
38
- \r
39
- `),u instanceof File?n.push(await fileToUint8Array(u)):n.push(u),n.push(`\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 i=[];let o="";for(let l=0;l<e.length;l++){const c=e[l];c==="\\"?((e[l+1]==='"'||e[l+1]==="'")&&l++,o+=e[l]):s===0?c==='"'||c==="'"?(s=1,n=c):c.match(/\s/)?(o.trim().length&&i.push(o.trim()),o=c):i.length&&!o?o=i.pop()+c:o+=c:s===1&&(c===n?(s=0,n=""):o+=c)}return o&&i.push(o.trim()),i}function createSpawnHandler(e){return function(t,r=[],s={}){const n=new ChildProcess,i=new ProcessApi(n);return setTimeout(async()=>{let o=[];if(r.length)o=[t,...r];else if(typeof t=="string")o=splitShellCommand(t);else if(Array.isArray(t))o=t;else throw new Error("Invalid command ",t);await e(o,i,s),n.emit("spawn",!0)}),n}}class EventEmitter{constructor(){this.listeners={}}emit(t,r){this.listeners[t]&&this.listeners[t].forEach(function(s){s(r)})}on(t,r){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(r)}}class ProcessApi extends EventEmitter{constructor(t){super(),this.childProcess=t,this.exited=!1,this.stdinData=[],t.on("stdin",r=>{this.stdinData?this.stdinData.push(r.slice()):this.emit("stdin",r)})}stdout(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stdout.emit("data",t)}stdoutEnd(){this.childProcess.stdout.emit("end",{})}stderr(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stderr.emit("data",t)}stderrEnd(){this.childProcess.stderr.emit("end",{})}exit(t){this.exited||(this.exited=!0,this.childProcess.emit("exit",t))}flushStdin(){if(this.stdinData)for(let t=0;t<this.stdinData.length;t++)this.emit("stdin",this.stdinData[t]);this.stdinData=null}}let lastPid=9743;class ChildProcess extends EventEmitter{constructor(t=lastPid++){super(),this.pid=t,this.stdout=new EventEmitter,this.stderr=new EventEmitter;const r=this;this.stdin={write:s=>{r.emit("stdin",s)}}}}function concatUint8Array(...e){const t=new Uint8Array(e.reduce((s,n)=>s+n.length,0));let r=0;for(const s of e)t.set(s,r),r+=s.length;return t}function concatBytes(e){if(e===void 0){let t=new Uint8Array;return new TransformStream({transform(r){t=concatUint8Array(t,r)},flush(r){r.enqueue(t)}})}else{const t=new ArrayBuffer(e||0);let r=0;return new TransformStream({transform(s){new Uint8Array(t).set(s,r),r+=s.byteLength},flush(s){s.enqueue(new Uint8Array(t))}})}}function limitBytes(e,t){if(t===0)return new ReadableStream({start(n){n.close()}});const r=e.getReader({mode:"byob"});let s=0;return new ReadableStream({async pull(n){const{value:i,done:o}=await r.read(new Uint8Array(t-s));if(o){r.releaseLock(),n.close();return}s+=i.length,n.enqueue(i),s>=t&&(r.releaseLock(),n.close())},cancel(){r.cancel()}})}async function collectBytes(e,t){return t!==void 0&&(e=limitBytes(e,t)),await e.pipeThrough(concatBytes(t)).getReader().read().then(({value:r})=>r)}class StreamedFile extends File{constructor(t,r,s){super([],r,{type:s}),this.readableStream=t}slice(){throw new Error("slice() is not possible on a StreamedFile")}stream(){return this.readableStream}async text(){return new TextDecoder().decode(await this.arrayBuffer())}async arrayBuffer(){return await collectBytes(this.stream())}}ReadableStream.prototype[Symbol.asyncIterator]||(ReadableStream.prototype[Symbol.asyncIterator]=async function*(){const e=this.getReader();try{for(;;){const{done:t,value:r}=await e.read();if(t)return;yield r}}finally{e.releaseLock()}},ReadableStream.prototype.iterate=ReadableStream.prototype[Symbol.asyncIterator]);function streamReadFileFromPHP(e,t){return new ReadableStream({async pull(r){const s=await e.readFileAsBuffer(t);r.enqueue(s),r.close()}})}async function*iteratePhpFiles(e,t,{relativePaths:r=!0,pathPrefix:s,exceptPaths:n=[]}={}){t=normalizePath(t);const i=[t];for(;i.length;){const o=i.pop();if(!o)return;const l=await e.listFiles(o);for(const c of l){const d=`${o}/${c}`;if(n.includes(d.substring(t.length+1)))continue;await e.isDir(d)?i.push(d):yield new StreamedFile(streamReadFileFromPHP(e,d),r?joinPaths(s||"",d.substring(t.length+1)):d)}}}function writeFilesStreamToPhp(e,t){return new WritableStream({async write(r){const s=joinPaths(t,r.name);r.type==="directory"?await e.mkdir(s):(await e.mkdir(dirname(s)),await e.writeFile(s,new Uint8Array(await r.arrayBuffer())))}})}class PHPResponse{constructor(t,r,s,n="",i=0){this.httpStatusCode=t,this.headers=r,this.bytes=s,this.exitCode=i,this.errors=n}static fromRawData(t){return new PHPResponse(t.httpStatusCode,t.headers,t.bytes,t.errors,t.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const SupportedPHPVersions=["8.3","8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0"],LatestSupportedPHPVersion=SupportedPHPVersions[0],SupportedPHPVersionsList=SupportedPHPVersions,SupportedPHPExtensionsList=["iconv","mbstring","xml-bundle","gd"],SupportedPHPExtensionBundles={"kitchen-sink":SupportedPHPExtensionsList};var E,b;class PHPBrowser{constructor(t,r={}){u(this,E,void 0);u(this,b,void 0);this.requestHandler=t,h(this,E,{}),h(this,b,{handleRedirects:!1,maxRedirects:4,...r})}async request(t,r=0){const s=await this.requestHandler.request({...t,headers:{...t.headers,cookie:this.serializeCookies()}});if(s.headers["set-cookie"]&&this.setCookies(s.headers["set-cookie"]),a(this,b).handleRedirects&&s.headers.location&&r<a(this,b).maxRedirects){const n=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:n.toString(),method:"GET",headers:{}},r+1)}return s}pathToInternalUrl(t){return this.requestHandler.pathToInternalUrl(t)}internalUrlToPath(t){return this.requestHandler.internalUrlToPath(t)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}setCookies(t){for(const r of t)try{if(!r.includes("="))continue;const s=r.indexOf("="),n=r.substring(0,s),i=r.substring(s+1).split(";")[0];a(this,E)[n]=i}catch(s){console.error(s)}}serializeCookies(){const t=[];for(const r in a(this,E))t.push(`${r}=${a(this,E)[r]}`);return t.join("; ")}}E=new WeakMap,b=new WeakMap;const DEFAULT_BASE_URL="http://example.com";function toRelativeUrl(e){return e.toString().substring(e.origin.length)}function removePathPrefix(e,t){return!t||!e.startsWith(t)?e:e.substring(t.length)}function ensurePathPrefix(e,t){return!t||e.startsWith(t)?e:t+e}async function encodeAsMultipart(e){const t=`----${Math.random().toString(36).slice(2)}`,r=`multipart/form-data; boundary=${t}`,s=new TextEncoder,n=[];for(const[c,d]of Object.entries(e))n.push(`--${t}\r
36
+ `),n.push(`Content-Disposition: form-data; name="${c}"`),d instanceof File&&n.push(`; filename="${d.name}"`),n.push(`\r
37
+ `),d instanceof File&&(n.push("Content-Type: application/octet-stream"),n.push(`\r
38
+ `)),n.push(`\r
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((d,u)=>d+u.length,0),o=new Uint8Array(i);let l=0;for(const d of n)o.set(typeof d=="string"?s.encode(d):d,l),l+=d.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 P,x,k,v,H,_,F,R,L,Y,U,Z,I,K;class PHPRequestHandler{constructor(t,r={}){c(this,L);c(this,U);c(this,I);c(this,P,void 0);c(this,x,void 0);c(this,k,void 0);c(this,v,void 0);c(this,H,void 0);c(this,_,void 0);c(this,F,void 0);c(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,P,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=a(this,v)!==443&&a(this,v)!==80;h(this,H,[a(this,k),o?`:${a(this,v)}`:""].join("")),h(this,_,i.pathname.replace(/\/+$/,"")),h(this,F,[`${a(this,x)}://`,a(this,H),a(this,_)].join(""))}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(a(this,_))&&(r.pathname=r.pathname.slice(a(this,_).length)),toRelativeUrl(r)}get isRequestRunning(){return a(this,R).running>0}get absoluteUrl(){return a(this,F)}get documentRoot(){return a(this,P)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url,r?void 0:DEFAULT_BASE_URL),n=removePathPrefix(s.pathname,a(this,_)),i=`${a(this,P)}${n}`;return seemsLikeAPHPRequestHandlerPath(i)?await p(this,U,Z).call(this,t,s):p(this,L,Y).call(this,i)}}P=new WeakMap,x=new WeakMap,k=new WeakMap,v=new WeakMap,H=new WeakMap,_=new WeakMap,F=new WeakMap,R=new WeakMap,L=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)},U=new WeakSet,Z=async function(t,r){var n,i;if(a(this,R).running>0&&((n=t.headers)==null?void 0:n["x-request-issuer"])==="php")return console.warn("Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."),new PHPResponse(502,{},new TextEncoder().encode("502 Bad Gateway"));const s=await a(this,R).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",a(this,P)),this.php.addServerGlobalEntry("HTTPS",a(this,F).startsWith("https://")?"on":"");let o="GET";const l={host:a(this,H),...normalizeHeaders(t.headers||{})};let d=t.body;if(typeof d=="object"&&!(d instanceof Uint8Array)){o="POST";const{bytes:f,contentType:B}=await encodeAsMultipart(d);d=f,l["content-type"]=B}let u;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{}u=p(this,I,K).call(this,f)}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),a(this,_)),protocol:a(this,x),method:t.method||o,body:d,scriptPath:u,headers:l})}finally{s()}},I=new WeakSet,K=function(t){let r=removePathPrefix(t,a(this,_));r.includes(".php")?r=r.split(".php")[0]+".php":(r.endsWith("/")||(r+="/"),r.endsWith("index.php")||(r+="index.php"));const s=`${a(this,P)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};function inferMimeType(e){switch(e.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}function seemsLikeAPHPRequestHandlerPath(e){return seemsLikeAPHPFile(e)||seemsLikeADirectoryRoot(e)}function seemsLikeAPHPFile(e){return e.endsWith(".php")||e.includes(".php/")}function seemsLikeADirectoryRoot(e){return!e.split("/").pop().includes(".")}const FileErrorCodes={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function getEmscriptenFsError(e){const t=typeof e=="object"?e==null?void 0:e.errno:null;if(t in FileErrorCodes)return FileErrorCodes[t]}function rethrowFileSystemError(e=""){return function(r,s,n){const i=n.value;n.value=function(...o){try{return i.apply(this,o)}catch(l){const d=typeof l=="object"?l==null?void 0:l.errno:null;if(d in FileErrorCodes){const u=FileErrorCodes[d],f=typeof o[0]=="string"?o[0]:null,B=f!==null?e.replaceAll("{path}",f):e;throw new Error(`${B}: ${u}`,{cause:l})}throw l}}}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(e,t={}){const[r,s,n]=makePromise(),i=e.init(currentJsRuntime,{onAbort(l){n(l),console.error(l)},ENV:{},locateFile:l=>l,...t,noInitialRun:!0,onRuntimeInitialized(){t.onRuntimeInitialized&&t.onRuntimeInitialized(),s()}});await r;const o=++lastRuntimeId;return i.id=o,i.originalExit=i._exit,i._exit=function(l){return loadedRuntimes.delete(o),i.originalExit(l)},i[RuntimeId]=o,loadedRuntimes.set(o,i),o}function getLoadedRuntime(e){return loadedRuntimes.get(e)}const currentJsRuntime=function(){var e;return typeof process<"u"&&((e=process.release)==null?void 0:e.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),makePromise=()=>{const e=[],t=new Promise((r,s)=>{e.push(r,s)});return e.unshift(t),e};var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__decorateClass=(e,t,r,s)=>{for(var n=s>1?void 0:s?__getOwnPropDesc(t,r):t,i=e.length-1,o;i>=0;i--)(o=e[i])&&(n=(s?o(t,r,n):o(n))||n);return s&&n&&__defProp(t,r,n),n};const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");var b,T,A,m,w,g,y,C,q,Q,N,X,M,ee,$,te,O,re,D,se,j,ne,z,ie,W,oe,G,ae,V,le;class BasePHP{constructor(e,t){c(this,q);c(this,N);c(this,M);c(this,$);c(this,O);c(this,D);c(this,j);c(this,z);c(this,W);c(this,G);c(this,V);c(this,b,void 0);c(this,T,void 0);c(this,A,void 0);c(this,m,void 0);c(this,w,void 0);c(this,g,void 0);c(this,y,void 0);c(this,C,void 0);h(this,b,[]),h(this,m,!1),h(this,w,null),h(this,g,{}),h(this,y,new Map),h(this,C,[]),this.semaphore=new Semaphore({concurrency:1}),e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new PHPBrowser(new PHPRequestHandler(this,t)))}addEventListener(e,t){a(this,y).has(e)||a(this,y).set(e,new Set),a(this,y).get(e).add(t)}removeEventListener(e,t){var r;(r=a(this,y).get(e))==null||r.delete(t)}dispatchEvent(e){const t=a(this,y).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){a(this,C).push(e)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const t=getLoadedRuntime(e);if(!t)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=t,t.onMessage=async r=>{for(const s of a(this,C)){const n=await s(r);if(n)return n}return""},h(this,w,improveWASMErrorReporting(t)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(e){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[e])!==0)throw new Error("Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?");h(this,A,e)}setPhpIniPath(e){if(a(this,m))throw new Error("Cannot set PHP ini path after calling run().");h(this,T,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(a(this,m))throw new Error("Cannot set PHP ini entries after calling run().");a(this,b).push([e,t])}chdir(e){this[__private__dont__use].FS.chdir(e)}async request(e,t){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,t)}async run(e){const t=await this.semaphore.acquire();let r;try{a(this,m)||(p(this,q,Q).call(this),h(this,m,!0)),p(this,z,ie).call(this,e.scriptPath||""),p(this,M,ee).call(this,e.relativeUri||""),p(this,O,re).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";p(this,$,te).call(this,n,e.protocol||"http"),p(this,D,se).call(this,s),e.body&&(r=p(this,j,ne).call(this,e.body)),typeof e.code=="string"&&p(this,G,ae).call(this," ?>"+e.code),p(this,W,oe).call(this);const i=await p(this,V,le).call(this);if(e.throwOnError&&i.exitCode!==0){const o={stdout:i.text,stderr:i.errors};console.warn("PHP.run() output was:",o);const l=new Error(`PHP.run() failed with exit code ${i.exitCode} and the following output`);throw l.output=o,l}return i}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){a(this,g)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/tmp/consts.json")&&this.readFileAsText("/tmp/consts.json")||"{}")}catch{}this.writeFile("/tmp/consts.json",JSON.stringify({...r,[e]:t}))}mkdir(e){this[__private__dont__use].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[__private__dont__use].FS.readFile(e)}writeFile(e,t){this[__private__dont__use].FS.writeFile(e,t)}unlink(e){this[__private__dont__use].FS.unlink(e)}mv(e,t){try{this[__private__dont__use].FS.rename(e,t)}catch(r){const s=getEmscriptenFsError(r);throw s?new Error(`Could not move ${e} to ${t}: ${s}`,{cause:r}):r}}rmdir(e,t={recursive:!0}){t!=null&&t.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[__private__dont__use].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[__private__dont__use].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(n=>`${s}/${n}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[__private__dont__use].FS.isDir(this[__private__dont__use].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[__private__dont__use].FS.lookupPath(e),!0}catch{return!1}}hotSwapPHPRuntime(e){const t=this[__private__dont__use].FS;try{this.exit()}catch{}if(this.initializeRuntime(e),a(this,T)&&this.setPhpIniPath(a(this,T)),a(this,A)&&this.setSapiName(a(this,A)),this.requestHandler){const r=this.documentRoot;recreateMemFS(this[__private__dont__use].FS,t,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}h(this,m,!1),h(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}b=new WeakMap,T=new WeakMap,A=new WeakMap,m=new WeakMap,w=new WeakMap,g=new WeakMap,y=new WeakMap,C=new WeakMap,q=new WeakSet,Q=function(){if(this.setPhpIniEntry("auto_prepend_file","/tmp/consts.php"),this.fileExists("/tmp/consts.php")||this.writeFile("/tmp/consts.php",`<?php
42
- if(file_exists('/tmp/consts.json')) {
43
- $consts = json_decode(file_get_contents('/tmp/consts.json'), true);
41
+ `);const i=n.reduce((c,d)=>c+d.length,0),o=new Uint8Array(i);let l=0;for(const c of n)o.set(typeof c=="string"?s.encode(c):c,l),l+=c.length;return{bytes:o,contentType:r}}function fileToUint8Array(e){return new Promise(t=>{const r=new FileReader;r.onload=()=>{t(new Uint8Array(r.result))},r.readAsArrayBuffer(e)})}var m,x,U,v,H,_,F,R,B,Y,I,Z,L,K;class PHPRequestHandler{constructor(t,r={}){u(this,B);u(this,I);u(this,L);u(this,m,void 0);u(this,x,void 0);u(this,U,void 0);u(this,v,void 0);u(this,H,void 0);u(this,_,void 0);u(this,F,void 0);u(this,R,void 0);h(this,R,new Semaphore({concurrency:1}));const{documentRoot:s="/www/",absoluteUrl:n=typeof location=="object"?location==null?void 0:location.href:""}=r;this.php=t,h(this,m,s);const i=new URL(n);h(this,U,i.hostname),h(this,v,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,x,(i.protocol||"").replace(":",""));const o=a(this,v)!==443&&a(this,v)!==80;h(this,H,[a(this,U),o?`:${a(this,v)}`:""].join("")),h(this,_,i.pathname.replace(/\/+$/,"")),h(this,F,[`${a(this,x)}://`,a(this,H),a(this,_)].join(""))}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(a(this,_))&&(r.pathname=r.pathname.slice(a(this,_).length)),toRelativeUrl(r)}get isRequestRunning(){return a(this,R).running>0}get absoluteUrl(){return a(this,F)}get documentRoot(){return a(this,m)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url,r?void 0:DEFAULT_BASE_URL),n=removePathPrefix(s.pathname,a(this,_)),i=`${a(this,m)}${n}`;return seemsLikeAPHPRequestHandlerPath(i)?await p(this,I,Z).call(this,t,s):p(this,B,Y).call(this,i)}}m=new WeakMap,x=new WeakMap,U=new WeakMap,v=new WeakMap,H=new WeakMap,_=new WeakMap,F=new WeakMap,R=new WeakMap,B=new WeakSet,Y=function(t){if(!this.php.fileExists(t))return new PHPResponse(404,{"x-file-type":["static"]},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new PHPResponse(200,{"content-length":[`${r.byteLength}`],"content-type":[inferMimeType(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)},I=new WeakSet,Z=async function(t,r){var n,i;if(a(this,R).running>0&&((n=t.headers)==null?void 0:n["x-request-issuer"])==="php")return console.warn("Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."),new PHPResponse(502,{},new TextEncoder().encode("502 Bad Gateway"));const s=await a(this,R).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",a(this,m)),this.php.addServerGlobalEntry("HTTPS",a(this,F).startsWith("https://")?"on":"");let o="GET";const l={host:a(this,H),...normalizeHeaders(t.headers||{})};let c=t.body;if(typeof c=="object"&&!(c instanceof Uint8Array)){o="POST";const{bytes:f,contentType:k}=await encodeAsMultipart(c);c=f,l["content-type"]=k}let d;try{let f=r.pathname;if((i=t.headers)!=null&&i["x-rewrite-url"])try{f=new URL(t.headers["x-rewrite-url"]).pathname}catch{}d=p(this,L,K).call(this,f)}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),a(this,_)),protocol:a(this,x),method:t.method||o,body:c,scriptPath:d,headers:l})}finally{s()}},L=new WeakSet,K=function(t){let r=removePathPrefix(t,a(this,_));r.includes(".php")?r=r.split(".php")[0]+".php":this.php.isDir(`${a(this,m)}${r}`)?(r.endsWith("/")||(r=`${r}/`),r=`${r}index.php`):r="/index.php";const s=`${a(this,m)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};function inferMimeType(e){switch(e.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}function seemsLikeAPHPRequestHandlerPath(e){return seemsLikeAPHPFile(e)||seemsLikeADirectoryRoot(e)}function seemsLikeAPHPFile(e){return e.endsWith(".php")||e.includes(".php/")}function seemsLikeADirectoryRoot(e){return!e.split("/").pop().includes(".")}const FileErrorCodes={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function getEmscriptenFsError(e){const t=typeof e=="object"?e==null?void 0:e.errno:null;if(t in FileErrorCodes)return FileErrorCodes[t]}function rethrowFileSystemError(e=""){return function(r,s,n){const i=n.value;n.value=function(...o){try{return i.apply(this,o)}catch(l){const c=typeof l=="object"?l==null?void 0:l.errno:null;if(c in FileErrorCodes){const d=FileErrorCodes[c],f=typeof o[0]=="string"?o[0]:null,k=f!==null?e.replaceAll("{path}",f):e;throw new Error(`${k}: ${d}`,{cause:l})}throw l}}}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(e,t={}){const[r,s,n]=makePromise(),i=e.init(currentJsRuntime,{onAbort(l){n(l),console.error(l)},ENV:{},locateFile:l=>l,...t,noInitialRun:!0,onRuntimeInitialized(){t.onRuntimeInitialized&&t.onRuntimeInitialized(),s()}});await r;const o=++lastRuntimeId;return i.id=o,i.originalExit=i._exit,i._exit=function(l){return loadedRuntimes.delete(o),i.originalExit(l)},i[RuntimeId]=o,loadedRuntimes.set(o,i),o}function getLoadedRuntime(e){return loadedRuntimes.get(e)}const currentJsRuntime=function(){var e;return typeof process<"u"&&((e=process.release)==null?void 0:e.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),makePromise=()=>{const e=[],t=new Promise((r,s)=>{e.push(r,s)});return e.unshift(t),e};var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__decorateClass=(e,t,r,s)=>{for(var n=s>1?void 0:s?__getOwnPropDesc(t,r):t,i=e.length-1,o;i>=0;i--)(o=e[i])&&(n=(s?o(t,r,n):o(n))||n);return s&&n&&__defProp(t,r,n),n};const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");var S,T,A,y,w,g,P,C,N,X,M,ee,q,te,O,re,D,se,$,ne,j,ie,z,oe,W,ae,G,le,V,ce,Q,ue;class BasePHP{constructor(e,t){u(this,N);u(this,M);u(this,q);u(this,O);u(this,D);u(this,$);u(this,j);u(this,z);u(this,W);u(this,G);u(this,V);u(this,Q);u(this,S,void 0);u(this,T,void 0);u(this,A,void 0);u(this,y,void 0);u(this,w,void 0);u(this,g,void 0);u(this,P,void 0);u(this,C,void 0);h(this,S,[]),h(this,y,!1),h(this,w,null),h(this,g,{}),h(this,P,new Map),h(this,C,[]),this.semaphore=new Semaphore({concurrency:1}),e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new PHPBrowser(new PHPRequestHandler(this,t)))}addEventListener(e,t){a(this,P).has(e)||a(this,P).set(e,new Set),a(this,P).get(e).add(t)}removeEventListener(e,t){var r;(r=a(this,P).get(e))==null||r.delete(t)}dispatchEvent(e){const t=a(this,P).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){a(this,C).push(e)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const t=getLoadedRuntime(e);if(!t)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=t,t.onMessage=async r=>{for(const s of a(this,C)){const n=await s(r);if(n)return n}return""},h(this,w,improveWASMErrorReporting(t)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(e){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[e])!==0)throw new Error("Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?");h(this,A,e)}setPhpIniPath(e){if(a(this,y))throw new Error("Cannot set PHP ini path after calling run().");h(this,T,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(a(this,y))throw new Error("Cannot set PHP ini entries after calling run().");a(this,S).push([e,t])}chdir(e){this[__private__dont__use].FS.chdir(e)}async request(e,t){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,t)}async run(e){const t=await this.semaphore.acquire();let r;try{if(a(this,y)||(p(this,N,X).call(this),h(this,y,!0)),e.scriptPath&&!this.fileExists(e.scriptPath))throw new Error(`The script path "${e.scriptPath}" does not exist.`);p(this,z,oe).call(this,e.scriptPath||""),p(this,q,te).call(this,e.relativeUri||""),p(this,D,se).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";p(this,O,re).call(this,n,e.protocol||"http"),p(this,$,ne).call(this,s),e.body&&(r=p(this,j,ie).call(this,e.body)),typeof e.code=="string"&&p(this,V,ce).call(this," ?>"+e.code),p(this,W,ae).call(this);const i=e.env||{};for(const l in i)p(this,G,le).call(this,l,i[l]);const o=await p(this,Q,ue).call(this);if(e.throwOnError&&o.exitCode!==0){const l={stdout:o.text,stderr:o.errors};console.warn("PHP.run() output was:",l);const c=new Error(`PHP.run() failed with exit code ${o.exitCode} and the following output: `+o.errors);throw c.output=l,console.error(c),c}return o}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){a(this,g)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/internal/consts.json")&&this.readFileAsText("/internal/consts.json")||"{}")}catch{}this.writeFile("/internal/consts.json",JSON.stringify({...r,[e]:t}))}mkdir(e){this[__private__dont__use].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[__private__dont__use].FS.readFile(e)}writeFile(e,t){this[__private__dont__use].FS.writeFile(e,t)}unlink(e){this[__private__dont__use].FS.unlink(e)}mv(e,t){try{this[__private__dont__use].FS.rename(e,t)}catch(r){const s=getEmscriptenFsError(r);throw s?new Error(`Could not move ${e} to ${t}: ${s}`,{cause:r}):r}}rmdir(e,t={recursive:!0}){t!=null&&t.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[__private__dont__use].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[__private__dont__use].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(n=>`${s}/${n}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[__private__dont__use].FS.isDir(this[__private__dont__use].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[__private__dont__use].FS.lookupPath(e),!0}catch{return!1}}hotSwapPHPRuntime(e){const t=this[__private__dont__use].FS;try{this.exit()}catch{}if(this.initializeRuntime(e),a(this,T)&&this.setPhpIniPath(a(this,T)),a(this,A)&&this.setSapiName(a(this,A)),this.requestHandler){const r=this.documentRoot;copyFS(t,this[__private__dont__use].FS,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}h(this,y,!1),h(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,T=new WeakMap,A=new WeakMap,y=new WeakMap,w=new WeakMap,g=new WeakMap,P=new WeakMap,C=new WeakMap,N=new WeakSet,X=function(){if(this.setPhpIniEntry("auto_prepend_file","/internal/consts.php"),this.fileExists("/internal/consts.php")||this.writeFile("/internal/consts.php",`<?php
42
+ if(file_exists('/internal/consts.json')) {
43
+ $consts = json_decode(file_get_contents('/internal/consts.json'), true);
44
44
  foreach ($consts as $const => $value) {
45
45
  if (!defined($const) && is_scalar($value)) {
46
46
  define($const, $value);
47
47
  }
48
48
  }
49
- }`),a(this,b).length>0){const e=a(this,b).map(([t,r])=>`${t}=${r}`).join(`
49
+ }`),a(this,S).length>0){const e=a(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,[],[])},N=new WeakSet,X=function(){const e="/tmp/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const t=JSON.parse(this.readFileAsText(e)),r={};for(const s of t.headers){if(!s.includes(": "))continue;const 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,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])}},$=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")},O=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])}},j=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},z=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 a(this,g))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,a(this,g)[e]])},G=new WeakSet,ae=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},V=new WeakSet,le=async function(){var n;let e,t;try{e=await new Promise((i,o)=>{var d;t=u=>{const f=new Error("Rethrown");f.cause=u.error,f.betterMessage=u.message,o(f)},(d=a(this,w))==null||d.addEventListener("error",t);const l=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return l instanceof Promise?l.then(i,o):i(l)})}catch(i){for(const u in this)typeof this[u]=="function"&&(this[u]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=getFunctionsMaybeMissingFromAsyncify();const o=i,l="betterMessage"in o?o.betterMessage:o.message,d=new Error(l);throw d.cause=o,d}finally{(n=a(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("/tmp/stdout"),this.readFileAsText("/tmp/stderr"),e)};__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdir",1);__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdirTree",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsText",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsBuffer",1);__decorateClass([rethrowFileSystemError('Could not write to "{path}"')],BasePHP.prototype,"writeFile",1);__decorateClass([rethrowFileSystemError('Could not unlink "{path}"')],BasePHP.prototype,"unlink",1);__decorateClass([rethrowFileSystemError('Could not remove directory "{path}"')],BasePHP.prototype,"rmdir",1);__decorateClass([rethrowFileSystemError('Could not list files in "{path}"')],BasePHP.prototype,"listFiles",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"isDir",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"fileExists",1);function normalizeHeaders(e){const t={};for(const r in e)t[r.toLowerCase()]=e[r];return t}function recreateMemFS(e,t,r){let s;try{s=t.lookupPath(r)}catch{return}if(!("contents"in s.node))return;try{e=e.lookupPath(r);return}catch{}if(!t.isDir(s.node.mode)){e.writeFile(r,t.readFile(r));return}e.mkdirTree(r);const n=t.readdir(r).filter(i=>i!=="."&&i!=="..");for(const i of n)recreateMemFS(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,[],[])},M=new WeakSet,ee=function(){const e="/internal/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const t=JSON.parse(this.readFileAsText(e)),r={};for(const s of t.headers){if(!s.includes(": "))continue;const n=s.indexOf(": "),i=s.substring(0,n).toLowerCase(),o=s.substring(n+2);i in r||(r[i]=[]),r[i].push(o)}return{headers:r,httpStatusCode:t.status}},q=new WeakSet,te=function(e){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[t])}},O=new WeakSet,re=function(e,t){this[__private__dont__use].ccall("wasm_set_request_host",null,[STRING],[e]);let r;try{r=parseInt(new URL(e).port,10)}catch{}(!r||isNaN(r)||r===80)&&(r=t==="https"?443:80),this[__private__dont__use].ccall("wasm_set_request_port",null,[NUMBER],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")},D=new WeakSet,se=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},$=new WeakSet,ne=function(e){e.cookie&&this[__private__dont__use].ccall("wasm_set_cookies",null,[STRING],[e.cookie]),e["content-type"]&&this[__private__dont__use].ccall("wasm_set_content_type",null,[STRING],[e["content-type"]]),e["content-length"]&&this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[parseInt(e["content-length"],10)]);for(const t in e){let r="HTTP_";["content-type","content-length"].includes(t.toLowerCase())&&(r=""),this.addServerGlobalEntry(`${r}${t.toUpperCase().replace(/-/g,"_")}`,e[t])}},j=new WeakSet,ie=function(e){let t,r;typeof e=="string"?(console.warn("Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"),r=this[__private__dont__use].lengthBytesUTF8(e),t=r+1):(r=e.byteLength,t=e.byteLength);const s=this[__private__dont__use].malloc(t);if(!s)throw new Error("Could not allocate memory for the request body.");return typeof e=="string"?this[__private__dont__use].stringToUTF8(e,s,t+1):this[__private__dont__use].HEAPU8.set(e,s),this[__private__dont__use].ccall("wasm_set_request_body",null,[NUMBER],[s]),this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[r]),s},z=new WeakSet,oe=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},W=new WeakSet,ae=function(){for(const e in a(this,g))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,a(this,g)[e]])},G=new WeakSet,le=function(e,t){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[e,t])},V=new WeakSet,ce=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},Q=new WeakSet,ue=async function(){var n;let e,t;try{e=await new Promise((i,o)=>{var c;t=d=>{console.error(d),console.error(d.error);const f=new Error("Rethrown");f.cause=d.error,f.betterMessage=d.message,o(f)},(c=a(this,w))==null||c.addEventListener("error",t);const l=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return l instanceof Promise?l.then(i,o):i(l)})}catch(i){for(const d in this)typeof this[d]=="function"&&(this[d]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=getFunctionsMaybeMissingFromAsyncify();const o=i,l="betterMessage"in o?o.betterMessage:o.message,c=new Error(l);throw c.cause=o,console.error(c),c}finally{(n=a(this,w))==null||n.removeEventListener("error",t),h(this,g,{})}const{headers:r,httpStatusCode:s}=p(this,M,ee).call(this);return new PHPResponse(s,r,this.readFileAsBuffer("/internal/stdout"),this.readFileAsText("/internal/stderr"),e)};__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdir",1);__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdirTree",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsText",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsBuffer",1);__decorateClass([rethrowFileSystemError('Could not write to "{path}"')],BasePHP.prototype,"writeFile",1);__decorateClass([rethrowFileSystemError('Could not unlink "{path}"')],BasePHP.prototype,"unlink",1);__decorateClass([rethrowFileSystemError('Could not remove directory "{path}"')],BasePHP.prototype,"rmdir",1);__decorateClass([rethrowFileSystemError('Could not list files in "{path}"')],BasePHP.prototype,"listFiles",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"isDir",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"fileExists",1);function normalizeHeaders(e){const t={};for(const r in e)t[r.toLowerCase()]=e[r];return t}function copyFS(e,t,r){let s;try{s=e.lookupPath(r)}catch{return}if(!("contents"in s.node))return;if(!e.isDir(s.node.mode)){t.writeFile(r,e.readFile(r));return}t.mkdirTree(r);const n=e.readdir(r).filter(i=>i!=="."&&i!=="..");for(const i of n)copyFS(e,t,joinPaths(r,i))}function isLocalPHP(e){return!(e instanceof BasePHP)}function isRemotePHP(e){return!isLocalPHP(e)}function rotatePHPRuntime({php:e,recreateRuntime:t,maxRequests:r}){let s=0;async function n(){if(++s<r)return;s=0;const i=await e.semaphore.acquire();try{e.hotSwapPHPRuntime(await t())}finally{i()}}return e.addEventListener("request.end",n),function(){e.removeEventListener("request.end",n)}}async function writeFiles(e,t,r,{rmRoot:s=!1}={}){s&&await e.isDir(t)&&await e.rmdir(t,{recursive:!0});for(const[n,i]of Object.entries(r)){const o=joinPaths(t,n);await e.fileExists(dirname(o))||await e.mkdir(dirname(o)),await e.writeFile(o,i)}}exports.BasePHP=BasePHP;exports.DEFAULT_BASE_URL=DEFAULT_BASE_URL;exports.LatestSupportedPHPVersion=LatestSupportedPHPVersion;exports.PHPBrowser=PHPBrowser;exports.PHPRequestHandler=PHPRequestHandler;exports.PHPResponse=PHPResponse;exports.SupportedPHPExtensionBundles=SupportedPHPExtensionBundles;exports.SupportedPHPExtensionsList=SupportedPHPExtensionsList;exports.SupportedPHPVersions=SupportedPHPVersions;exports.SupportedPHPVersionsList=SupportedPHPVersionsList;exports.UnhandledRejectionsTarget=UnhandledRejectionsTarget;exports.__private__dont__use=__private__dont__use;exports.ensurePathPrefix=ensurePathPrefix;exports.isExitCodeZero=isExitCodeZero;exports.isLocalPHP=isLocalPHP;exports.isRemotePHP=isRemotePHP;exports.iterateFiles=iteratePhpFiles;exports.loadPHPRuntime=loadPHPRuntime;exports.removePathPrefix=removePathPrefix;exports.rethrowFileSystemError=rethrowFileSystemError;exports.rotatePHPRuntime=rotatePHPRuntime;exports.toRelativeUrl=toRelativeUrl;exports.writeFiles=writeFiles;exports.writeFilesStreamToPhp=writeFilesStreamToPhp;
package/index.js CHANGED
@@ -2,7 +2,7 @@ var J = (e, t, r) => {
2
2
  if (!t.has(e))
3
3
  throw TypeError("Cannot " + r);
4
4
  };
5
- var a = (e, t, r) => (J(e, t, "read from private field"), r ? r.call(e) : t.get(e)), c = (e, t, r) => {
5
+ var a = (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);
@@ -274,12 +274,31 @@ function normalizePathsArray(e, t) {
274
274
  e.unshift("..");
275
275
  return e;
276
276
  }
277
+ function splitShellCommand(e) {
278
+ let s = 0, n = "";
279
+ const i = [];
280
+ let o = "";
281
+ for (let l = 0; l < e.length; l++) {
282
+ const c = e[l];
283
+ c === "\\" ? ((e[l + 1] === '"' || e[l + 1] === "'") && l++, o += e[l]) : s === 0 ? c === '"' || c === "'" ? (s = 1, n = c) : c.match(/\s/) ? (o.trim().length && i.push(o.trim()), o = c) : i.length && !o ? o = i.pop() + c : o += c : s === 1 && (c === n ? (s = 0, n = "") : o += c);
284
+ }
285
+ return o && i.push(o.trim()), i;
286
+ }
277
287
  function createSpawnHandler(e) {
278
- return function(t) {
279
- const r = new ChildProcess(), s = new ProcessApi(r);
288
+ return function(t, r = [], s = {}) {
289
+ const n = new ChildProcess(), i = new ProcessApi(n);
280
290
  return setTimeout(async () => {
281
- await e(t, s), r.emit("spawn", !0);
282
- }), r;
291
+ let o = [];
292
+ if (r.length)
293
+ o = [t, ...r];
294
+ else if (typeof t == "string")
295
+ o = splitShellCommand(t);
296
+ else if (Array.isArray(t))
297
+ o = t;
298
+ else
299
+ throw new Error("Invalid command ", t);
300
+ await e(o, i, s), n.emit("spawn", !0);
301
+ }), n;
283
302
  };
284
303
  }
285
304
  class EventEmitter {
@@ -304,9 +323,15 @@ class ProcessApi extends EventEmitter {
304
323
  stdout(t) {
305
324
  typeof t == "string" && (t = new TextEncoder().encode(t)), this.childProcess.stdout.emit("data", t);
306
325
  }
326
+ stdoutEnd() {
327
+ this.childProcess.stdout.emit("end", {});
328
+ }
307
329
  stderr(t) {
308
330
  typeof t == "string" && (t = new TextEncoder().encode(t)), this.childProcess.stderr.emit("data", t);
309
331
  }
332
+ stderrEnd() {
333
+ this.childProcess.stderr.emit("end", {});
334
+ }
310
335
  exit(t) {
311
336
  this.exited || (this.exited = !0, this.childProcess.emit("exit", t));
312
337
  }
@@ -468,16 +493,16 @@ async function* iteratePhpFiles(e, t, {
468
493
  if (!o)
469
494
  return;
470
495
  const l = await e.listFiles(o);
471
- for (const d of l) {
472
- const u = `${o}/${d}`;
473
- if (n.includes(u.substring(t.length + 1)))
496
+ for (const c of l) {
497
+ const d = `${o}/${c}`;
498
+ if (n.includes(d.substring(t.length + 1)))
474
499
  continue;
475
- await e.isDir(u) ? i.push(u) : yield new StreamedFile(
476
- streamReadFileFromPHP(e, u),
500
+ await e.isDir(d) ? i.push(d) : yield new StreamedFile(
501
+ streamReadFileFromPHP(e, d),
477
502
  r ? joinPaths(
478
503
  s || "",
479
- u.substring(t.length + 1)
480
- ) : u
504
+ d.substring(t.length + 1)
505
+ ) : d
481
506
  );
482
507
  }
483
508
  }
@@ -546,16 +571,16 @@ const SupportedPHPVersions = [
546
571
  ], SupportedPHPExtensionBundles = {
547
572
  "kitchen-sink": SupportedPHPExtensionsList
548
573
  };
549
- var E, S;
574
+ var E, b;
550
575
  class PHPBrowser {
551
576
  /**
552
577
  * @param server - The PHP server to browse.
553
578
  * @param config - The browser configuration.
554
579
  */
555
580
  constructor(t, r = {}) {
556
- c(this, E, void 0);
557
- c(this, S, void 0);
558
- this.requestHandler = t, h(this, E, {}), h(this, S, {
581
+ u(this, E, void 0);
582
+ u(this, b, void 0);
583
+ this.requestHandler = t, h(this, E, {}), h(this, b, {
559
584
  handleRedirects: !1,
560
585
  maxRedirects: 4,
561
586
  ...r
@@ -583,7 +608,7 @@ class PHPBrowser {
583
608
  cookie: this.serializeCookies()
584
609
  }
585
610
  });
586
- if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), a(this, S).handleRedirects && s.headers.location && r < a(this, S).maxRedirects) {
611
+ if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), a(this, b).handleRedirects && s.headers.location && r < a(this, b).maxRedirects) {
587
612
  const n = new URL(
588
613
  s.headers.location[0],
589
614
  this.requestHandler.absoluteUrl
@@ -633,7 +658,7 @@ class PHPBrowser {
633
658
  return t.join("; ");
634
659
  }
635
660
  }
636
- E = new WeakMap(), S = new WeakMap();
661
+ E = new WeakMap(), b = new WeakMap();
637
662
  const DEFAULT_BASE_URL = "http://example.com";
638
663
  function toRelativeUrl(e) {
639
664
  return e.toString().substring(e.origin.length);
@@ -646,22 +671,22 @@ function ensurePathPrefix(e, t) {
646
671
  }
647
672
  async function encodeAsMultipart(e) {
648
673
  const t = `----${Math.random().toString(36).slice(2)}`, r = `multipart/form-data; boundary=${t}`, s = new TextEncoder(), n = [];
649
- for (const [d, u] of Object.entries(e))
674
+ for (const [c, d] of Object.entries(e))
650
675
  n.push(`--${t}\r
651
- `), n.push(`Content-Disposition: form-data; name="${d}"`), u instanceof File && n.push(`; filename="${u.name}"`), n.push(`\r
652
- `), u instanceof File && n.push("Content-Type: application/octet-stream"), n.push(`\r
653
- \r
654
- `), u instanceof File ? n.push(await fileToUint8Array(u)) : n.push(u), n.push(`\r
676
+ `), n.push(`Content-Disposition: form-data; name="${c}"`), d instanceof File && n.push(`; filename="${d.name}"`), n.push(`\r
677
+ `), d instanceof File && (n.push("Content-Type: application/octet-stream"), n.push(`\r
678
+ `)), n.push(`\r
679
+ `), d instanceof File ? n.push(await fileToUint8Array(d)) : n.push(d), n.push(`\r
655
680
  `);
656
681
  n.push(`--${t}--\r
657
682
  `);
658
- const i = n.reduce((d, u) => d + u.length, 0), o = new Uint8Array(i);
683
+ const i = n.reduce((c, d) => c + d.length, 0), o = new Uint8Array(i);
659
684
  let l = 0;
660
- for (const d of n)
685
+ for (const c of n)
661
686
  o.set(
662
- typeof d == "string" ? s.encode(d) : d,
687
+ typeof c == "string" ? s.encode(c) : c,
663
688
  l
664
- ), l += d.length;
689
+ ), l += c.length;
665
690
  return { bytes: o, contentType: r };
666
691
  }
667
692
  function fileToUint8Array(e) {
@@ -672,7 +697,7 @@ function fileToUint8Array(e) {
672
697
  }, r.readAsArrayBuffer(e);
673
698
  });
674
699
  }
675
- var P, H, k, v, x, _, F, R, U, Y, I, Z, L, K;
700
+ var m, H, k, v, x, _, F, R, B, Y, I, Z, L, K;
676
701
  class PHPRequestHandler {
677
702
  /**
678
703
  * @param php - The PHP instance.
@@ -685,7 +710,7 @@ class PHPRequestHandler {
685
710
  * @param fsPath - Absolute path of the static file to serve.
686
711
  * @returns The response.
687
712
  */
688
- c(this, U);
713
+ u(this, B);
689
714
  /**
690
715
  * Runs the requested PHP file with all the request and $_SERVER
691
716
  * superglobals populated.
@@ -693,7 +718,7 @@ class PHPRequestHandler {
693
718
  * @param request - The request.
694
719
  * @returns The response.
695
720
  */
696
- c(this, I);
721
+ u(this, I);
697
722
  /**
698
723
  * Resolve the requested path to the filesystem path of the requested PHP file.
699
724
  *
@@ -703,21 +728,21 @@ class PHPRequestHandler {
703
728
  * @throws {Error} If the requested path doesn't exist.
704
729
  * @returns The resolved filesystem path.
705
730
  */
706
- c(this, L);
707
- c(this, P, void 0);
708
- c(this, H, void 0);
709
- c(this, k, void 0);
710
- c(this, v, void 0);
711
- c(this, x, void 0);
712
- c(this, _, void 0);
713
- c(this, F, void 0);
714
- c(this, R, void 0);
731
+ u(this, L);
732
+ u(this, m, void 0);
733
+ u(this, H, void 0);
734
+ u(this, k, void 0);
735
+ u(this, v, void 0);
736
+ u(this, x, void 0);
737
+ u(this, _, void 0);
738
+ u(this, F, void 0);
739
+ u(this, R, void 0);
715
740
  h(this, R, new Semaphore({ concurrency: 1 }));
716
741
  const {
717
742
  documentRoot: s = "/www/",
718
743
  absoluteUrl: n = typeof location == "object" ? location == null ? void 0 : location.href : ""
719
744
  } = r;
720
- this.php = t, h(this, P, s);
745
+ this.php = t, h(this, m, s);
721
746
  const i = new URL(n);
722
747
  h(this, k, i.hostname), h(this, v, i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80), h(this, H, (i.protocol || "").replace(":", ""));
723
748
  const o = a(this, v) !== 443 && a(this, v) !== 80;
@@ -748,7 +773,7 @@ class PHPRequestHandler {
748
773
  }
749
774
  /** @inheritDoc */
750
775
  get documentRoot() {
751
- return a(this, P);
776
+ return a(this, m);
752
777
  }
753
778
  /** @inheritDoc */
754
779
  async request(t) {
@@ -758,11 +783,11 @@ class PHPRequestHandler {
758
783
  ), n = removePathPrefix(
759
784
  s.pathname,
760
785
  a(this, _)
761
- ), i = `${a(this, P)}${n}`;
762
- return seemsLikeAPHPRequestHandlerPath(i) ? await f(this, I, Z).call(this, t, s) : f(this, U, Y).call(this, i);
786
+ ), i = `${a(this, m)}${n}`;
787
+ return seemsLikeAPHPRequestHandlerPath(i) ? await f(this, I, Z).call(this, t, s) : f(this, B, Y).call(this, i);
763
788
  }
764
789
  }
765
- P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x = new WeakMap(), _ = new WeakMap(), F = new WeakMap(), R = new WeakMap(), U = new WeakSet(), Y = function(t) {
790
+ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x = new WeakMap(), _ = new WeakMap(), F = new WeakMap(), R = new WeakMap(), B = new WeakSet(), Y = function(t) {
766
791
  if (!this.php.fileExists(t))
767
792
  return new PHPResponse(
768
793
  404,
@@ -799,7 +824,7 @@ P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
799
824
  );
800
825
  const s = await a(this, R).acquire();
801
826
  try {
802
- this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", a(this, P)), this.php.addServerGlobalEntry(
827
+ this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", a(this, m)), this.php.addServerGlobalEntry(
803
828
  "HTTPS",
804
829
  a(this, F).startsWith("https://") ? "on" : ""
805
830
  );
@@ -808,13 +833,13 @@ P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
808
833
  host: a(this, x),
809
834
  ...normalizeHeaders(t.headers || {})
810
835
  };
811
- let d = t.body;
812
- if (typeof d == "object" && !(d instanceof Uint8Array)) {
836
+ let c = t.body;
837
+ if (typeof c == "object" && !(c instanceof Uint8Array)) {
813
838
  o = "POST";
814
- const { bytes: p, contentType: B } = await encodeAsMultipart(d);
815
- d = p, l["content-type"] = B;
839
+ const { bytes: p, contentType: U } = await encodeAsMultipart(c);
840
+ c = p, l["content-type"] = U;
816
841
  }
817
- let u;
842
+ let d;
818
843
  try {
819
844
  let p = r.pathname;
820
845
  if ((i = t.headers) != null && i["x-rewrite-url"])
@@ -824,7 +849,7 @@ P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
824
849
  ).pathname;
825
850
  } catch {
826
851
  }
827
- u = f(this, L, K).call(this, p);
852
+ d = f(this, L, K).call(this, p);
828
853
  } catch {
829
854
  return new PHPResponse(
830
855
  404,
@@ -839,8 +864,8 @@ P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
839
864
  ),
840
865
  protocol: a(this, H),
841
866
  method: t.method || o,
842
- body: d,
843
- scriptPath: u,
867
+ body: c,
868
+ scriptPath: d,
844
869
  headers: l
845
870
  });
846
871
  } finally {
@@ -848,8 +873,8 @@ P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
848
873
  }
849
874
  }, L = new WeakSet(), K = function(t) {
850
875
  let r = removePathPrefix(t, a(this, _));
851
- r.includes(".php") ? r = r.split(".php")[0] + ".php" : (r.endsWith("/") || (r += "/"), r.endsWith("index.php") || (r += "index.php"));
852
- const s = `${a(this, P)}${r}`;
876
+ r.includes(".php") ? r = r.split(".php")[0] + ".php" : this.php.isDir(`${a(this, m)}${r}`) ? (r.endsWith("/") || (r = `${r}/`), r = `${r}index.php`) : r = "/index.php";
877
+ const s = `${a(this, m)}${r}`;
853
878
  if (this.php.fileExists(s))
854
879
  return s;
855
880
  throw new Error(`File not found: ${s}`);
@@ -994,10 +1019,10 @@ function rethrowFileSystemError(e = "") {
994
1019
  try {
995
1020
  return i.apply(this, o);
996
1021
  } catch (l) {
997
- const d = typeof l == "object" ? l == null ? void 0 : l.errno : null;
998
- if (d in FileErrorCodes) {
999
- const u = FileErrorCodes[d], p = typeof o[0] == "string" ? o[0] : null, B = p !== null ? e.replaceAll("{path}", p) : e;
1000
- throw new Error(`${B}: ${u}`, {
1022
+ const c = typeof l == "object" ? l == null ? void 0 : l.errno : null;
1023
+ if (c in FileErrorCodes) {
1024
+ const d = FileErrorCodes[c], p = typeof o[0] == "string" ? o[0] : null, U = p !== null ? e.replaceAll("{path}", p) : e;
1025
+ throw new Error(`${U}: ${d}`, {
1001
1026
  cause: l
1002
1027
  });
1003
1028
  }
@@ -1048,7 +1073,7 @@ var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyD
1048
1073
  return s && n && __defProp(t, r, n), n;
1049
1074
  };
1050
1075
  const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
1051
- var b, T, A, m, w, g, y, C, q, Q, N, X, M, ee, $, te, O, re, D, se, j, ne, z, ie, W, oe, G, ae, V, le;
1076
+ var S, T, A, y, w, g, P, C, N, X, M, ee, q, te, O, re, $, se, D, ne, j, ie, z, oe, W, ae, G, le, V, ce, Q, ue;
1052
1077
  class BasePHP {
1053
1078
  /**
1054
1079
  * Initializes a PHP runtime.
@@ -1058,38 +1083,39 @@ class BasePHP {
1058
1083
  * @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
1059
1084
  */
1060
1085
  constructor(e, t) {
1061
- c(this, q);
1062
- c(this, N);
1063
- c(this, M);
1064
- c(this, $);
1065
- c(this, O);
1066
- c(this, D);
1067
- c(this, j);
1068
- c(this, z);
1069
- c(this, W);
1070
- c(this, G);
1071
- c(this, V);
1072
- c(this, b, void 0);
1073
- c(this, T, void 0);
1074
- c(this, A, void 0);
1075
- c(this, m, void 0);
1076
- c(this, w, void 0);
1077
- c(this, g, void 0);
1078
- c(this, y, void 0);
1079
- c(this, C, void 0);
1080
- h(this, b, []), h(this, m, !1), h(this, w, null), h(this, g, {}), h(this, y, /* @__PURE__ */ new Map()), h(this, C, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new PHPBrowser(
1086
+ u(this, N);
1087
+ u(this, M);
1088
+ u(this, q);
1089
+ u(this, O);
1090
+ u(this, $);
1091
+ u(this, D);
1092
+ u(this, j);
1093
+ u(this, z);
1094
+ u(this, W);
1095
+ u(this, G);
1096
+ u(this, V);
1097
+ u(this, Q);
1098
+ u(this, S, void 0);
1099
+ u(this, T, void 0);
1100
+ u(this, A, void 0);
1101
+ u(this, y, void 0);
1102
+ u(this, w, void 0);
1103
+ u(this, g, void 0);
1104
+ u(this, P, void 0);
1105
+ u(this, C, void 0);
1106
+ h(this, S, []), h(this, y, !1), h(this, w, null), h(this, g, {}), h(this, P, /* @__PURE__ */ new Map()), h(this, C, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new PHPBrowser(
1081
1107
  new PHPRequestHandler(this, t)
1082
1108
  ));
1083
1109
  }
1084
1110
  addEventListener(e, t) {
1085
- a(this, y).has(e) || a(this, y).set(e, /* @__PURE__ */ new Set()), a(this, y).get(e).add(t);
1111
+ a(this, P).has(e) || a(this, P).set(e, /* @__PURE__ */ new Set()), a(this, P).get(e).add(t);
1086
1112
  }
1087
1113
  removeEventListener(e, t) {
1088
1114
  var r;
1089
- (r = a(this, y).get(e)) == null || r.delete(t);
1115
+ (r = a(this, P).get(e)) == null || r.delete(t);
1090
1116
  }
1091
1117
  dispatchEvent(e) {
1092
- const t = a(this, y).get(e.type);
1118
+ const t = a(this, P).get(e.type);
1093
1119
  if (t)
1094
1120
  for (const r of t)
1095
1121
  r(e);
@@ -1152,7 +1178,7 @@ class BasePHP {
1152
1178
  }
1153
1179
  /** @inheritDoc */
1154
1180
  setPhpIniPath(e) {
1155
- if (a(this, m))
1181
+ if (a(this, y))
1156
1182
  throw new Error("Cannot set PHP ini path after calling run().");
1157
1183
  h(this, T, e), this[__private__dont__use].ccall(
1158
1184
  "wasm_set_phpini_path",
@@ -1163,9 +1189,9 @@ class BasePHP {
1163
1189
  }
1164
1190
  /** @inheritDoc */
1165
1191
  setPhpIniEntry(e, t) {
1166
- if (a(this, m))
1192
+ if (a(this, y))
1167
1193
  throw new Error("Cannot set PHP ini entries after calling run().");
1168
- a(this, b).push([e, t]);
1194
+ a(this, S).push([e, t]);
1169
1195
  }
1170
1196
  /** @inheritDoc */
1171
1197
  chdir(e) {
@@ -1182,22 +1208,29 @@ class BasePHP {
1182
1208
  const t = await this.semaphore.acquire();
1183
1209
  let r;
1184
1210
  try {
1185
- a(this, m) || (f(this, q, Q).call(this), h(this, m, !0)), f(this, z, ie).call(this, e.scriptPath || ""), f(this, M, ee).call(this, e.relativeUri || ""), f(this, O, re).call(this, e.method || "GET");
1211
+ if (a(this, y) || (f(this, N, X).call(this), h(this, y, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
1212
+ throw new Error(
1213
+ `The script path "${e.scriptPath}" does not exist.`
1214
+ );
1215
+ f(this, z, oe).call(this, e.scriptPath || ""), f(this, q, te).call(this, e.relativeUri || ""), f(this, $, se).call(this, e.method || "GET");
1186
1216
  const s = normalizeHeaders(e.headers || {}), n = s.host || "example.com:443";
1187
- f(this, $, te).call(this, n, e.protocol || "http"), f(this, D, se).call(this, s), e.body && (r = f(this, j, ne).call(this, e.body)), typeof e.code == "string" && f(this, G, ae).call(this, " ?>" + e.code), f(this, W, oe).call(this);
1188
- const i = await f(this, V, le).call(this);
1189
- if (e.throwOnError && i.exitCode !== 0) {
1190
- const o = {
1191
- stdout: i.text,
1192
- stderr: i.errors
1217
+ f(this, O, re).call(this, n, e.protocol || "http"), f(this, D, ne).call(this, s), e.body && (r = f(this, j, ie).call(this, e.body)), typeof e.code == "string" && f(this, V, ce).call(this, " ?>" + e.code), f(this, W, ae).call(this);
1218
+ const i = e.env || {};
1219
+ for (const l in i)
1220
+ f(this, G, le).call(this, l, i[l]);
1221
+ const o = await f(this, Q, ue).call(this);
1222
+ if (e.throwOnError && o.exitCode !== 0) {
1223
+ const l = {
1224
+ stdout: o.text,
1225
+ stderr: o.errors
1193
1226
  };
1194
- console.warn("PHP.run() output was:", o);
1195
- const l = new Error(
1196
- `PHP.run() failed with exit code ${i.exitCode} and the following output`
1227
+ console.warn("PHP.run() output was:", l);
1228
+ const c = new Error(
1229
+ `PHP.run() failed with exit code ${o.exitCode} and the following output: ` + o.errors
1197
1230
  );
1198
- throw l.output = o, l;
1231
+ throw c.output = l, console.error(c), c;
1199
1232
  }
1200
- return i;
1233
+ return o;
1201
1234
  } finally {
1202
1235
  try {
1203
1236
  r && this[__private__dont__use].free(r);
@@ -1215,12 +1248,12 @@ class BasePHP {
1215
1248
  let r = {};
1216
1249
  try {
1217
1250
  r = JSON.parse(
1218
- this.fileExists("/tmp/consts.json") && this.readFileAsText("/tmp/consts.json") || "{}"
1251
+ this.fileExists("/internal/consts.json") && this.readFileAsText("/internal/consts.json") || "{}"
1219
1252
  );
1220
1253
  } catch {
1221
1254
  }
1222
1255
  this.writeFile(
1223
- "/tmp/consts.json",
1256
+ "/internal/consts.json",
1224
1257
  JSON.stringify({
1225
1258
  ...r,
1226
1259
  [e]: t
@@ -1307,7 +1340,7 @@ class BasePHP {
1307
1340
  }
1308
1341
  if (this.initializeRuntime(e), a(this, T) && this.setPhpIniPath(a(this, T)), a(this, A) && this.setSapiName(a(this, A)), this.requestHandler) {
1309
1342
  const r = this.documentRoot;
1310
- recreateMemFS(this[__private__dont__use].FS, t, r);
1343
+ copyFS(t, this[__private__dont__use].FS, r);
1311
1344
  }
1312
1345
  }
1313
1346
  exit(e = 0) {
@@ -1318,23 +1351,23 @@ class BasePHP {
1318
1351
  this[__private__dont__use]._exit(e);
1319
1352
  } catch {
1320
1353
  }
1321
- h(this, m, !1), h(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1354
+ h(this, y, !1), h(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1322
1355
  }
1323
1356
  }
1324
- b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w = new WeakMap(), g = new WeakMap(), y = new WeakMap(), C = new WeakMap(), q = new WeakSet(), Q = function() {
1325
- if (this.setPhpIniEntry("auto_prepend_file", "/tmp/consts.php"), this.fileExists("/tmp/consts.php") || this.writeFile(
1326
- "/tmp/consts.php",
1357
+ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w = new WeakMap(), g = new WeakMap(), P = new WeakMap(), C = new WeakMap(), N = new WeakSet(), X = function() {
1358
+ if (this.setPhpIniEntry("auto_prepend_file", "/internal/consts.php"), this.fileExists("/internal/consts.php") || this.writeFile(
1359
+ "/internal/consts.php",
1327
1360
  `<?php
1328
- if(file_exists('/tmp/consts.json')) {
1329
- $consts = json_decode(file_get_contents('/tmp/consts.json'), true);
1361
+ if(file_exists('/internal/consts.json')) {
1362
+ $consts = json_decode(file_get_contents('/internal/consts.json'), true);
1330
1363
  foreach ($consts as $const => $value) {
1331
1364
  if (!defined($const) && is_scalar($value)) {
1332
1365
  define($const, $value);
1333
1366
  }
1334
1367
  }
1335
1368
  }`
1336
- ), a(this, b).length > 0) {
1337
- const e = a(this, b).map(([t, r]) => `${t}=${r}`).join(`
1369
+ ), a(this, S).length > 0) {
1370
+ const e = a(this, S).map(([t, r]) => `${t}=${r}`).join(`
1338
1371
  `) + `
1339
1372
 
1340
1373
  `;
@@ -1346,8 +1379,8 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
1346
1379
  );
1347
1380
  }
1348
1381
  this[__private__dont__use].ccall("php_wasm_init", null, [], []);
1349
- }, N = new WeakSet(), X = function() {
1350
- const e = "/tmp/headers.json";
1382
+ }, M = new WeakSet(), ee = function() {
1383
+ const e = "/internal/headers.json";
1351
1384
  if (!this.fileExists(e))
1352
1385
  throw new Error(
1353
1386
  "SAPI Error: Could not find response headers file."
@@ -1363,7 +1396,7 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
1363
1396
  headers: r,
1364
1397
  httpStatusCode: t.status
1365
1398
  };
1366
- }, M = new WeakSet(), ee = function(e) {
1399
+ }, q = new WeakSet(), te = function(e) {
1367
1400
  if (this[__private__dont__use].ccall(
1368
1401
  "wasm_set_request_uri",
1369
1402
  null,
@@ -1378,7 +1411,7 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
1378
1411
  [t]
1379
1412
  );
1380
1413
  }
1381
- }, $ = new WeakSet(), te = function(e, t) {
1414
+ }, O = new WeakSet(), re = function(e, t) {
1382
1415
  this[__private__dont__use].ccall(
1383
1416
  "wasm_set_request_host",
1384
1417
  null,
@@ -1396,14 +1429,14 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
1396
1429
  [NUMBER],
1397
1430
  [r]
1398
1431
  ), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
1399
- }, O = new WeakSet(), re = function(e) {
1432
+ }, $ = new WeakSet(), se = function(e) {
1400
1433
  this[__private__dont__use].ccall(
1401
1434
  "wasm_set_request_method",
1402
1435
  null,
1403
1436
  [STRING],
1404
1437
  [e]
1405
1438
  );
1406
- }, D = new WeakSet(), se = function(e) {
1439
+ }, D = new WeakSet(), ne = function(e) {
1407
1440
  e.cookie && this[__private__dont__use].ccall(
1408
1441
  "wasm_set_cookies",
1409
1442
  null,
@@ -1427,7 +1460,7 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
1427
1460
  e[t]
1428
1461
  );
1429
1462
  }
1430
- }, j = new WeakSet(), ne = function(e) {
1463
+ }, j = new WeakSet(), ie = function(e) {
1431
1464
  let t, r;
1432
1465
  typeof e == "string" ? (console.warn(
1433
1466
  "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"
@@ -1450,14 +1483,14 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
1450
1483
  [NUMBER],
1451
1484
  [r]
1452
1485
  ), s;
1453
- }, z = new WeakSet(), ie = function(e) {
1486
+ }, z = new WeakSet(), oe = function(e) {
1454
1487
  this[__private__dont__use].ccall(
1455
1488
  "wasm_set_path_translated",
1456
1489
  null,
1457
1490
  [STRING],
1458
1491
  [e]
1459
1492
  );
1460
- }, W = new WeakSet(), oe = function() {
1493
+ }, W = new WeakSet(), ae = function() {
1461
1494
  for (const e in a(this, g))
1462
1495
  this[__private__dont__use].ccall(
1463
1496
  "wasm_add_SERVER_entry",
@@ -1465,23 +1498,31 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
1465
1498
  [STRING, STRING],
1466
1499
  [e, a(this, g)[e]]
1467
1500
  );
1468
- }, G = new WeakSet(), ae = function(e) {
1501
+ }, G = new WeakSet(), le = function(e, t) {
1502
+ this[__private__dont__use].ccall(
1503
+ "wasm_add_ENV_entry",
1504
+ null,
1505
+ [STRING, STRING],
1506
+ [e, t]
1507
+ );
1508
+ }, V = new WeakSet(), ce = function(e) {
1469
1509
  this[__private__dont__use].ccall(
1470
1510
  "wasm_set_php_code",
1471
1511
  null,
1472
1512
  [STRING],
1473
1513
  [e]
1474
1514
  );
1475
- }, V = new WeakSet(), le = async function() {
1515
+ }, Q = new WeakSet(), ue = async function() {
1476
1516
  var n;
1477
1517
  let e, t;
1478
1518
  try {
1479
1519
  e = await new Promise((i, o) => {
1480
- var d;
1481
- t = (u) => {
1520
+ var c;
1521
+ t = (d) => {
1522
+ console.error(d), console.error(d.error);
1482
1523
  const p = new Error("Rethrown");
1483
- p.cause = u.error, p.betterMessage = u.message, o(p);
1484
- }, (d = a(this, w)) == null || d.addEventListener(
1524
+ p.cause = d.error, p.betterMessage = d.message, o(p);
1525
+ }, (c = a(this, w)) == null || c.addEventListener(
1485
1526
  "error",
1486
1527
  t
1487
1528
  );
@@ -1495,24 +1536,24 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
1495
1536
  return l instanceof Promise ? l.then(i, o) : i(l);
1496
1537
  });
1497
1538
  } catch (i) {
1498
- for (const u in this)
1499
- typeof this[u] == "function" && (this[u] = () => {
1539
+ for (const d in this)
1540
+ typeof this[d] == "function" && (this[d] = () => {
1500
1541
  throw new Error(
1501
1542
  "PHP runtime has crashed – see the earlier error for details."
1502
1543
  );
1503
1544
  });
1504
1545
  this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
1505
- const o = i, l = "betterMessage" in o ? o.betterMessage : o.message, d = new Error(l);
1506
- throw d.cause = o, d;
1546
+ const o = i, l = "betterMessage" in o ? o.betterMessage : o.message, c = new Error(l);
1547
+ throw c.cause = o, console.error(c), c;
1507
1548
  } finally {
1508
1549
  (n = a(this, w)) == null || n.removeEventListener("error", t), h(this, g, {});
1509
1550
  }
1510
- const { headers: r, httpStatusCode: s } = f(this, N, X).call(this);
1551
+ const { headers: r, httpStatusCode: s } = f(this, M, ee).call(this);
1511
1552
  return new PHPResponse(
1512
1553
  s,
1513
1554
  r,
1514
- this.readFileAsBuffer("/tmp/stdout"),
1515
- this.readFileAsText("/tmp/stderr"),
1555
+ this.readFileAsBuffer("/internal/stdout"),
1556
+ this.readFileAsText("/internal/stderr"),
1516
1557
  e
1517
1558
  );
1518
1559
  };
@@ -1552,28 +1593,23 @@ function normalizeHeaders(e) {
1552
1593
  t[r.toLowerCase()] = e[r];
1553
1594
  return t;
1554
1595
  }
1555
- function recreateMemFS(e, t, r) {
1596
+ function copyFS(e, t, r) {
1556
1597
  let s;
1557
1598
  try {
1558
- s = t.lookupPath(r);
1599
+ s = e.lookupPath(r);
1559
1600
  } catch {
1560
1601
  return;
1561
1602
  }
1562
1603
  if (!("contents" in s.node))
1563
1604
  return;
1564
- try {
1565
- e = e.lookupPath(r);
1566
- return;
1567
- } catch {
1568
- }
1569
- if (!t.isDir(s.node.mode)) {
1570
- e.writeFile(r, t.readFile(r));
1605
+ if (!e.isDir(s.node.mode)) {
1606
+ t.writeFile(r, e.readFile(r));
1571
1607
  return;
1572
1608
  }
1573
- e.mkdirTree(r);
1574
- const n = t.readdir(r).filter((i) => i !== "." && i !== "..");
1609
+ t.mkdirTree(r);
1610
+ const n = e.readdir(r).filter((i) => i !== "." && i !== "..");
1575
1611
  for (const i of n)
1576
- recreateMemFS(e, t, joinPaths(r, i));
1612
+ copyFS(e, t, joinPaths(r, i));
1577
1613
  }
1578
1614
  function isLocalPHP(e) {
1579
1615
  return !(e instanceof BasePHP);
package/lib/base-php.d.ts CHANGED
@@ -92,3 +92,11 @@ export declare abstract class BasePHP implements IsomorphicLocalPHP {
92
92
  exit(code?: number): void;
93
93
  }
94
94
  export declare function normalizeHeaders(headers: PHPRequestHeaders): PHPRequestHeaders;
95
+ type EmscriptenFS = any;
96
+ export declare function syncFSTo(source: BasePHP, target: BasePHP, path?: string | null): void;
97
+ /**
98
+ * Copies the MEMFS directory structure from one FS in another FS.
99
+ * Non-MEMFS nodes are ignored.
100
+ */
101
+ export declare function copyFS(source: EmscriptenFS, target: EmscriptenFS, path: string): void;
102
+ export {};
@@ -462,6 +462,10 @@ export interface PHPRunOptions {
462
462
  * Request body.
463
463
  */
464
464
  body?: string | Uint8Array;
465
+ /**
466
+ * Environment variables to set for this run.
467
+ */
468
+ env?: Record<string, string>;
465
469
  /**
466
470
  * The code snippet to eval instead of a php file.
467
471
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/universal",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
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": "0a8916ec08aa5f02de5fea308b287171e7948e4b",
39
+ "gitHead": "eb45486a61d06a8a9e62cbd65348bfb274ff9e7c",
40
40
  "engines": {
41
41
  "node": ">=18.18.2",
42
42
  "npm": ">=8.11.0"