@php-wasm/fs-journal 0.6.6 → 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.cjs +8 -8
  2. package/index.js +216 -202
  3. package/package.json +2 -2
package/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var Y=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var a=(e,t,r)=>(Y(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)=>(Y(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var f=(e,t,r)=>(Y(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 Y=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var l=(e,t,r)=>(Y(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)=>(Y(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var f=(e,t,r)=>(Y(e,t,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});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"}();if(currentJsRuntime==="NODE"){let e=function(r){return new Promise(function(s,n){r.onload=r.onerror=function(i){r.onload=r.onerror=null,i.type==="load"?s(r.result):n(new Error("Failed to read the blob/file"))}})},t=function(){const r=new Uint8Array([1,2,3,4]),n=new File([r],"test").stream();try{return n.getReader({mode:"byob"}),!0}catch{return!1}};if(typeof File>"u"){class r extends Blob{constructor(n,i,o){super(n);let a;o!=null&&o.lastModified&&(a=new Date),(!a||isNaN(a.getFullYear()))&&(a=new Date),this.lastModifiedDate=a,this.lastModified=a.getMilliseconds(),this.name=i||""}}global.File=r}typeof Blob.prototype.arrayBuffer>"u"&&(Blob.prototype.arrayBuffer=function(){const s=new FileReader;return s.readAsArrayBuffer(this),e(s)}),typeof Blob.prototype.text>"u"&&(Blob.prototype.text=function(){const s=new FileReader;return s.readAsText(this),e(s)}),(typeof Blob.prototype.stream>"u"||!t())&&(Blob.prototype.stream=function(){let r=0;const s=this;return new ReadableStream({type:"bytes",autoAllocateChunkSize:512*1024,async pull(n){const i=n.byobRequest.view,a=await s.slice(r,r+i.byteLength).arrayBuffer(),c=new Uint8Array(a);new Uint8Array(i.buffer).set(c);const d=c.byteLength;n.byobRequest.respond(d),r+=d,r>=s.size&&n.close()}})})}if(currentJsRuntime==="NODE"&&typeof CustomEvent>"u"){class e extends Event{constructor(r,s={}){super(r,s),this.detail=s.detail}initCustomEvent(){}}globalThis.CustomEvent=e}const kError=Symbol("error"),kMessage=Symbol("message");class ErrorEvent2 extends Event{constructor(t,r={}){super(t),this[kError]=r.error===void 0?null:r.error,this[kMessage]=r.message===void 0?"":r.message}get error(){return this[kError]}get message(){return this[kMessage]}}Object.defineProperty(ErrorEvent2.prototype,"error",{enumerable:!0});Object.defineProperty(ErrorEvent2.prototype,"message",{enumerable:!0});const ErrorEvent=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:ErrorEvent2;function isExitCodeZero(e){return e instanceof Error?"exitCode"in e&&(e==null?void 0:e.exitCode)===0||(e==null?void 0:e.name)==="ExitStatus"&&"status"in e&&e.status===0:!1}class UnhandledRejectionsTarget extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(t,r){++this.listenersCount,super.addEventListener(t,r)}removeEventListener(t,r){--this.listenersCount,super.removeEventListener(t,r)}hasListeners(){return this.listenersCount>0}}function improveWASMErrorReporting(e){e.asm={...e.asm};const t=new UnhandledRejectionsTarget;for(const r in e.asm)if(typeof e.asm[r]=="function"){const s=e.asm[r];e.asm[r]=function(...n){var i;try{return s(...n)}catch(o){if(!(o instanceof Error))throw o;const a=clarifyErrorMessage(o,(i=e.lastAsyncifyStackSource)==null?void 0:i.stack);if(e.lastAsyncifyStackSource&&(o.cause=e.lastAsyncifyStackSource),t.hasListeners()){t.dispatchEvent(new ErrorEvent("error",{error:o,message:a}));return}throw isExitCodeZero(o)||showCriticalErrorBox(a),o}}}return t}let functionsMaybeMissingFromAsyncify=[];function getFunctionsMaybeMissingFromAsyncify(){return functionsMaybeMissingFromAsyncify}function clarifyErrorMessage(e,t){if(e.message==="unreachable"){let r=UNREACHABLE_ERROR;t||(r+=`
2
2
 
3
3
  This stack trace is lacking. For a better one initialize
4
4
  the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
@@ -32,13 +32,13 @@ CLI option:
32
32
  ${eol}
33
33
  ${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
34
34
  `))console.log(`${eol} ${t} `);console.log(`${reset}`)}}function extractPHPFunctionsFromStack(e){try{const t=e.split(`
35
- `).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(t))}catch{return[]}}class Semaphore{constructor({concurrency:t}){this._running=0,this.concurrency=t,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(t=>this.queue.push(t));else{this._running++;let t=!1;return()=>{t||(t=!0,this._running--,this.queue.length>0&&this.queue.shift()())}}}async run(t){const r=await this.acquire();try{return await t()}finally{r()}}}function joinPaths(...e){let t=e.join("/");const r=t[0]==="/",s=t.substring(t.length-1)==="/";return t=normalizePath$1(t),!t&&!r&&(t="."),t&&s&&(t+="/"),t}function basename(e){if(e==="/")return"/";e=normalizePath$1(e);const t=e.lastIndexOf("/");return t===-1?e:e.substr(t+1)}function normalizePath$1(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)}}}}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]);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)}}var v,T;class PHPBrowser{constructor(t,r={}){u(this,v,void 0);u(this,T,void 0);this.requestHandler=t,h(this,v,{}),h(this,T,{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,T).handleRedirects&&s.headers.location&&r<a(this,T).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,v)[n]=i}catch(s){console.error(s)}}serializeCookies(){const t=[];for(const r in a(this,v))t.push(`${r}=${a(this,v)[r]}`);return t.join("; ")}}v=new WeakMap,T=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,p]of Object.entries(e))n.push(`--${t}\r
36
- `),n.push(`Content-Disposition: form-data; name="${c}"`),p instanceof File&&n.push(`; filename="${p.name}"`),n.push(`\r
37
- `),p instanceof File&&(n.push("Content-Type: application/octet-stream"),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$1(t),!t&&!r&&(t="."),t&&s&&(t+="/"),t}function basename(e){if(e==="/")return"/";e=normalizePath$1(e);const t=e.lastIndexOf("/");return t===-1?e:e.substr(t+1)}function normalizePath$1(e){const t=e[0]==="/";return e=normalizePathsArray(e.split("/").filter(r=>!!r),!t).join("/"),(t?"/":"")+e.replace(/\/$/,"")}function normalizePathsArray(e,t){let r=0;for(let s=e.length-1;s>=0;s--){const n=e[s];n==="."?e.splice(s,1):n===".."?(e.splice(s,1),r++):r&&(e.splice(s,1),r--)}if(t)for(;r;r--)e.unshift("..");return e}function splitShellCommand(e){let s=0,n="";const i=[];let o="";for(let a=0;a<e.length;a++){const c=e[a];c==="\\"?((e[a+1]==='"'||e[a+1]==="'")&&a++,o+=e[a]):s===0?c==='"'||c==="'"?(s=1,n=c):c.match(/\s/)?(o.trim().length&&i.push(o.trim()),o=c):i.length&&!o?o=i.pop()+c:o+=c:s===1&&(c===n?(s=0,n=""):o+=c)}return o&&i.push(o.trim()),i}function createSpawnHandler(e){return function(t,r=[],s={}){const n=new ChildProcess,i=new ProcessApi(n);return setTimeout(async()=>{let o=[];if(r.length)o=[t,...r];else if(typeof t=="string")o=splitShellCommand(t);else if(Array.isArray(t))o=t;else throw new Error("Invalid command ",t);await e(o,i,s),n.emit("spawn",!0)}),n}}class EventEmitter{constructor(){this.listeners={}}emit(t,r){this.listeners[t]&&this.listeners[t].forEach(function(s){s(r)})}on(t,r){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(r)}}class ProcessApi extends EventEmitter{constructor(t){super(),this.childProcess=t,this.exited=!1,this.stdinData=[],t.on("stdin",r=>{this.stdinData?this.stdinData.push(r.slice()):this.emit("stdin",r)})}stdout(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stdout.emit("data",t)}stdoutEnd(){this.childProcess.stdout.emit("end",{})}stderr(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stderr.emit("data",t)}stderrEnd(){this.childProcess.stderr.emit("end",{})}exit(t){this.exited||(this.exited=!0,this.childProcess.emit("exit",t))}flushStdin(){if(this.stdinData)for(let t=0;t<this.stdinData.length;t++)this.emit("stdin",this.stdinData[t]);this.stdinData=null}}let lastPid=9743;class ChildProcess extends EventEmitter{constructor(t=lastPid++){super(),this.pid=t,this.stdout=new EventEmitter,this.stderr=new EventEmitter;const r=this;this.stdin={write:s=>{r.emit("stdin",s)}}}}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]);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)}}var v,T;class PHPBrowser{constructor(t,r={}){u(this,v,void 0);u(this,T,void 0);this.requestHandler=t,h(this,v,{}),h(this,T,{handleRedirects:!1,maxRedirects:4,...r})}async request(t,r=0){const s=await this.requestHandler.request({...t,headers:{...t.headers,cookie:this.serializeCookies()}});if(s.headers["set-cookie"]&&this.setCookies(s.headers["set-cookie"]),l(this,T).handleRedirects&&s.headers.location&&r<l(this,T).maxRedirects){const n=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:n.toString(),method:"GET",headers:{}},r+1)}return s}pathToInternalUrl(t){return this.requestHandler.pathToInternalUrl(t)}internalUrlToPath(t){return this.requestHandler.internalUrlToPath(t)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}setCookies(t){for(const r of t)try{if(!r.includes("="))continue;const s=r.indexOf("="),n=r.substring(0,s),i=r.substring(s+1).split(";")[0];l(this,v)[n]=i}catch(s){console.error(s)}}serializeCookies(){const t=[];for(const r in l(this,v))t.push(`${r}=${l(this,v)[r]}`);return t.join("; ")}}v=new WeakMap,T=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
38
  `)),n.push(`\r
39
- `),p instanceof File?n.push(await fileToUint8Array(p)):n.push(p),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((c,p)=>c+p.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 y,F,I,b,x,m,C,R,N,K,O,Z,U,X;class PHPRequestHandler{constructor(t,r={}){u(this,N);u(this,O);u(this,U);u(this,y,void 0);u(this,F,void 0);u(this,I,void 0);u(this,b,void 0);u(this,x,void 0);u(this,m,void 0);u(this,C,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,y,s);const i=new URL(n);h(this,I,i.hostname),h(this,b,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,F,(i.protocol||"").replace(":",""));const o=a(this,b)!==443&&a(this,b)!==80;h(this,x,[a(this,I),o?`:${a(this,b)}`:""].join("")),h(this,m,i.pathname.replace(/\/+$/,"")),h(this,C,[`${a(this,F)}://`,a(this,x),a(this,m)].join(""))}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(a(this,m))&&(r.pathname=r.pathname.slice(a(this,m).length)),toRelativeUrl(r)}get isRequestRunning(){return a(this,R).running>0}get absoluteUrl(){return a(this,C)}get documentRoot(){return a(this,y)}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,m)),i=`${a(this,y)}${n}`;return seemsLikeAPHPRequestHandlerPath(i)?await f(this,O,Z).call(this,t,s):f(this,N,K).call(this,i)}}y=new WeakMap,F=new WeakMap,I=new WeakMap,b=new WeakMap,x=new WeakMap,m=new WeakMap,C=new WeakMap,R=new WeakMap,N=new WeakSet,K=function(t){if(!this.php.fileExists(t))return new PHPResponse(404,{"x-file-type":["static"]},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new PHPResponse(200,{"content-length":[`${r.byteLength}`],"content-type":[inferMimeType(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)},O=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,y)),this.php.addServerGlobalEntry("HTTPS",a(this,C).startsWith("https://")?"on":"");let o="GET";const l={host:a(this,x),...normalizeHeaders(t.headers||{})};let c=t.body;if(typeof c=="object"&&!(c instanceof Uint8Array)){o="POST";const{bytes:d,contentType:_}=await encodeAsMultipart(c);c=d,l["content-type"]=_}let p;try{let d=r.pathname;if((i=t.headers)!=null&&i["x-rewrite-url"])try{d=new URL(t.headers["x-rewrite-url"]).pathname}catch{}p=f(this,U,X).call(this,d)}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),a(this,m)),protocol:a(this,F),method:t.method||o,body:c,scriptPath:p,headers:l})}finally{s()}},U=new WeakSet,X=function(t){let r=removePathPrefix(t,a(this,m));r.includes(".php")?r=r.split(".php")[0]+".php":this.php.isDir(`${a(this,y)}${r}`)?(r.endsWith("/")||(r=`${r}/`),r=`${r}index.php`):r="/index.php";const s=`${a(this,y)}${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 p=FileErrorCodes[c],d=typeof o[0]=="string"?o[0]:null,_=d!==null?e.replaceAll("{path}",d):e;throw new Error(`${_}: ${p}`,{cause:l})}throw l}}}}const loadedRuntimes=new Map;function getLoadedRuntime(e){return loadedRuntimes.get(e)}(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"})();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,A,k,E,g,P,w,H,M,ee,B,te,L,re,$,se,D,ne,q,ie,j,oe,W,ae,z,le,G,ce,J,ue,Q,de;class BasePHP{constructor(e,t){u(this,M);u(this,B);u(this,L);u(this,$);u(this,D);u(this,q);u(this,j);u(this,W);u(this,z);u(this,G);u(this,J);u(this,Q);u(this,S,void 0);u(this,A,void 0);u(this,k,void 0);u(this,E,void 0);u(this,g,void 0);u(this,P,void 0);u(this,w,void 0);u(this,H,void 0);h(this,S,[]),h(this,E,!1),h(this,g,null),h(this,P,{}),h(this,w,new Map),h(this,H,[]),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,w).has(e)||a(this,w).set(e,new Set),a(this,w).get(e).add(t)}removeEventListener(e,t){var r;(r=a(this,w).get(e))==null||r.delete(t)}dispatchEvent(e){const t=a(this,w).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){a(this,H).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,H)){const n=await s(r);if(n)return n}return""},h(this,g,improveWASMErrorReporting(t)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(e){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[e])!==0)throw new Error("Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?");h(this,k,e)}setPhpIniPath(e){if(a(this,E))throw new Error("Cannot set PHP ini path after calling run().");h(this,A,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(a(this,E))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,E)||(f(this,M,ee).call(this),h(this,E,!0)),e.scriptPath&&!this.fileExists(e.scriptPath))throw new Error(`The script path "${e.scriptPath}" does not exist.`);f(this,W,ae).call(this,e.scriptPath||""),f(this,L,re).call(this,e.relativeUri||""),f(this,D,ne).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";f(this,$,se).call(this,n,e.protocol||"http"),f(this,q,ie).call(this,s),e.body&&(r=f(this,j,oe).call(this,e.body)),typeof e.code=="string"&&f(this,J,ue).call(this," ?>"+e.code),f(this,z,le).call(this);const i=e.env||{};for(const l in i)f(this,G,ce).call(this,l,i[l]);const o=await f(this,Q,de).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,P)[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,A)&&this.setPhpIniPath(a(this,A)),a(this,k)&&this.setSapiName(a(this,k)),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,E,!1),h(this,g,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,A=new WeakMap,k=new WeakMap,E=new WeakMap,g=new WeakMap,P=new WeakMap,w=new WeakMap,H=new WeakMap,M=new WeakSet,ee=function(){if(this.setPhpIniEntry("auto_prepend_file","/internal/consts.php"),this.fileExists("/internal/consts.php")||this.writeFile("/internal/consts.php",`<?php
41
+ `);const i=n.reduce((c,d)=>c+d.length,0),o=new Uint8Array(i);let a=0;for(const c of n)o.set(typeof c=="string"?s.encode(c):c,a),a+=c.length;return{bytes:o,contentType:r}}function fileToUint8Array(e){return new Promise(t=>{const r=new FileReader;r.onload=()=>{t(new Uint8Array(r.result))},r.readAsArrayBuffer(e)})}var y,F,N,R,x,_,C,b,O,K,I,Z,M,X;class PHPRequestHandler{constructor(t,r={}){u(this,O);u(this,I);u(this,M);u(this,y,void 0);u(this,F,void 0);u(this,N,void 0);u(this,R,void 0);u(this,x,void 0);u(this,_,void 0);u(this,C,void 0);u(this,b,void 0);h(this,b,new Semaphore({concurrency:1}));const{documentRoot:s="/www/",absoluteUrl:n=typeof location=="object"?location==null?void 0:location.href:"",rewriteRules:i=[]}=r;this.php=t,h(this,y,s);const o=new URL(n);h(this,N,o.hostname),h(this,R,o.port?Number(o.port):o.protocol==="https:"?443:80),h(this,F,(o.protocol||"").replace(":",""));const a=l(this,R)!==443&&l(this,R)!==80;h(this,x,[l(this,N),a?`:${l(this,R)}`:""].join("")),h(this,_,o.pathname.replace(/\/+$/,"")),h(this,C,[`${l(this,F)}://`,l(this,x),l(this,_)].join("")),this.rewriteRules=i}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(l(this,_))&&(r.pathname=r.pathname.slice(l(this,_).length)),toRelativeUrl(r)}get isRequestRunning(){return l(this,b).running>0}get absoluteUrl(){return l(this,C)}get documentRoot(){return l(this,y)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url,r?void 0:DEFAULT_BASE_URL),n=applyRewriteRules(removePathPrefix(s.pathname,l(this,_)),this.rewriteRules),i=`${l(this,y)}${n}`;return seemsLikeAPHPRequestHandlerPath(i)?await f(this,I,Z).call(this,t,s):f(this,O,K).call(this,i)}}y=new WeakMap,F=new WeakMap,N=new WeakMap,R=new WeakMap,x=new WeakMap,_=new WeakMap,C=new WeakMap,b=new WeakMap,O=new WeakSet,K=function(t){if(!this.php.fileExists(t))return new PHPResponse(404,{"x-file-type":["static"]},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new PHPResponse(200,{"content-length":[`${r.byteLength}`],"content-type":[inferMimeType(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)},I=new WeakSet,Z=async function(t,r){var n;if(l(this,b).running>0&&((n=t.headers)==null?void 0:n["x-request-issuer"])==="php")return console.warn("Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."),new PHPResponse(502,{},new TextEncoder().encode("502 Bad Gateway"));const s=await l(this,b).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",l(this,y)),this.php.addServerGlobalEntry("HTTPS",l(this,C).startsWith("https://")?"on":"");let i="GET";const o={host:l(this,x),...normalizeHeaders(t.headers||{})};let a=t.body;if(typeof a=="object"&&!(a instanceof Uint8Array)){i="POST";const{bytes:d,contentType:p}=await encodeAsMultipart(a);a=d,o["content-type"]=p}let c;try{c=f(this,M,X).call(this,r.pathname)}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),l(this,_)),protocol:l(this,F),method:t.method||i,body:a,scriptPath:c,headers:o})}finally{s()}},M=new WeakSet,X=function(t){let r=removePathPrefix(t,l(this,_));r=applyRewriteRules(r,this.rewriteRules),r.includes(".php")?r=r.split(".php")[0]+".php":this.php.isDir(`${l(this,y)}${r}`)?(r.endsWith("/")||(r=`${r}/`),r=`${r}index.php`):r="/index.php";const s=`${l(this,y)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};function inferMimeType(e){switch(e.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}function seemsLikeAPHPRequestHandlerPath(e){return seemsLikeAPHPFile(e)||seemsLikeADirectoryRoot(e)}function seemsLikeAPHPFile(e){return e.endsWith(".php")||e.includes(".php/")}function seemsLikeADirectoryRoot(e){return!e.split("/").pop().includes(".")}function applyRewriteRules(e,t){for(const r of t)if(new RegExp(r.match).test(e))return e.replace(r.match,r.replacement);return e}const FileErrorCodes={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function getEmscriptenFsError(e){const t=typeof e=="object"?e==null?void 0:e.errno:null;if(t in FileErrorCodes)return FileErrorCodes[t]}function rethrowFileSystemError(e=""){return function(r,s,n){const i=n.value;n.value=function(...o){try{return i.apply(this,o)}catch(a){const c=typeof a=="object"?a==null?void 0:a.errno:null;if(c in FileErrorCodes){const d=FileErrorCodes[c],p=typeof o[0]=="string"?o[0]:null,P=p!==null?e.replaceAll("{path}",p):e;throw new Error(`${P}: ${d}`,{cause:a})}throw a}}}}const loadedRuntimes=new Map;function getLoadedRuntime(e){return loadedRuntimes.get(e)}(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"})();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,k,A,m,w,g,E,H,U,ee,B,te,L,re,D,se,$,ne,q,ie,W,oe,j,ae,z,le,G,ce,J,ue,Q,de;class BasePHP{constructor(e,t){u(this,U);u(this,B);u(this,L);u(this,D);u(this,$);u(this,q);u(this,W);u(this,j);u(this,z);u(this,G);u(this,J);u(this,Q);u(this,S,void 0);u(this,k,void 0);u(this,A,void 0);u(this,m,void 0);u(this,w,void 0);u(this,g,void 0);u(this,E,void 0);u(this,H,void 0);h(this,S,[]),h(this,m,!1),h(this,w,null),h(this,g,{}),h(this,E,new Map),h(this,H,[]),this.semaphore=new Semaphore({concurrency:1}),e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new PHPBrowser(new PHPRequestHandler(this,t)))}addEventListener(e,t){l(this,E).has(e)||l(this,E).set(e,new Set),l(this,E).get(e).add(t)}removeEventListener(e,t){var r;(r=l(this,E).get(e))==null||r.delete(t)}dispatchEvent(e){const t=l(this,E).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){l(this,H).push(e)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const t=getLoadedRuntime(e);if(!t)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=t,t.onMessage=async r=>{for(const s of l(this,H)){const n=await s(r);if(n)return n}return""},h(this,w,improveWASMErrorReporting(t)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(e){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[e])!==0)throw new Error("Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?");h(this,A,e)}setPhpIniPath(e){if(l(this,m))throw new Error("Cannot set PHP ini path after calling run().");h(this,k,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(l(this,m))throw new Error("Cannot set PHP ini entries after calling run().");l(this,S).push([e,t])}chdir(e){this[__private__dont__use].FS.chdir(e)}async request(e,t){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,t)}async run(e){const t=await this.semaphore.acquire();let r;try{if(l(this,m)||(f(this,U,ee).call(this),h(this,m,!0)),e.scriptPath&&!this.fileExists(e.scriptPath))throw new Error(`The script path "${e.scriptPath}" does not exist.`);f(this,j,ae).call(this,e.scriptPath||""),f(this,L,re).call(this,e.relativeUri||""),f(this,$,ne).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";f(this,D,se).call(this,n,e.protocol||"http"),f(this,q,ie).call(this,s),e.body&&(r=f(this,W,oe).call(this,e.body)),typeof e.code=="string"&&f(this,J,ue).call(this," ?>"+e.code),f(this,z,le).call(this);const i=e.env||{};for(const a in i)f(this,G,ce).call(this,a,i[a]);const o=await f(this,Q,de).call(this);if(e.throwOnError&&o.exitCode!==0){const a={stdout:o.text,stderr:o.errors};console.warn("PHP.run() output was:",a);const c=new Error(`PHP.run() failed with exit code ${o.exitCode} and the following output: `+o.errors);throw c.output=a,console.error(c),c}return o}catch(s){throw this.dispatchEvent({type:"request.error",error:s}),s}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){l(this,g)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/internal/consts.json")&&this.readFileAsText("/internal/consts.json")||"{}")}catch{}this.writeFile("/internal/consts.json",JSON.stringify({...r,[e]:t}))}mkdir(e){this[__private__dont__use].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[__private__dont__use].FS.readFile(e)}writeFile(e,t){this[__private__dont__use].FS.writeFile(e,t)}unlink(e){this[__private__dont__use].FS.unlink(e)}mv(e,t){try{this[__private__dont__use].FS.rename(e,t)}catch(r){const s=getEmscriptenFsError(r);throw s?new Error(`Could not move ${e} to ${t}: ${s}`,{cause:r}):r}}rmdir(e,t={recursive:!0}){t!=null&&t.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[__private__dont__use].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[__private__dont__use].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(n=>`${s}/${n}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[__private__dont__use].FS.isDir(this[__private__dont__use].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[__private__dont__use].FS.lookupPath(e),!0}catch{return!1}}hotSwapPHPRuntime(e){const t=this[__private__dont__use].FS;try{this.exit()}catch{}if(this.initializeRuntime(e),l(this,k)&&this.setPhpIniPath(l(this,k)),l(this,A)&&this.setSapiName(l(this,A)),this.requestHandler){const r=this.documentRoot;copyFS(t,this[__private__dont__use].FS,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}h(this,m,!1),h(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,k=new WeakMap,A=new WeakMap,m=new WeakMap,w=new WeakMap,g=new WeakMap,E=new WeakMap,H=new WeakMap,U=new WeakSet,ee=function(){if(this.setPhpIniEntry("auto_prepend_file","/internal/consts.php"),this.fileExists("/internal/consts.php")||this.writeFile("/internal/consts.php",`<?php
42
42
  if(file_exists('/internal/consts.json')) {
43
43
  $consts = json_decode(file_get_contents('/internal/consts.json'), true);
44
44
  foreach ($consts as $const => $value) {
@@ -46,7 +46,7 @@ ${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
46
46
  define($const, $value);
47
47
  }
48
48
  }
49
- }`),a(this,S).length>0){const e=a(this,S).map(([t,r])=>`${t}=${r}`).join(`
49
+ }`),l(this,S).length>0){const e=l(this,S).map(([t,r])=>`${t}=${r}`).join(`
50
50
  `)+`
51
51
 
52
- `;this[__private__dont__use].ccall("wasm_set_phpini_entries",null,[STRING],[e])}this[__private__dont__use].ccall("php_wasm_init",null,[],[])},B=new WeakSet,te=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}},L=new WeakSet,re=function(e){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[t])}},$=new WeakSet,se=function(e,t){this[__private__dont__use].ccall("wasm_set_request_host",null,[STRING],[e]);let r;try{r=parseInt(new URL(e).port,10)}catch{}(!r||isNaN(r)||r===80)&&(r=t==="https"?443:80),this[__private__dont__use].ccall("wasm_set_request_port",null,[NUMBER],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")},D=new WeakSet,ne=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},q=new WeakSet,ie=function(e){e.cookie&&this[__private__dont__use].ccall("wasm_set_cookies",null,[STRING],[e.cookie]),e["content-type"]&&this[__private__dont__use].ccall("wasm_set_content_type",null,[STRING],[e["content-type"]]),e["content-length"]&&this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[parseInt(e["content-length"],10)]);for(const t in e){let r="HTTP_";["content-type","content-length"].includes(t.toLowerCase())&&(r=""),this.addServerGlobalEntry(`${r}${t.toUpperCase().replace(/-/g,"_")}`,e[t])}},j=new WeakSet,oe=function(e){let t,r;typeof e=="string"?(console.warn("Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"),r=this[__private__dont__use].lengthBytesUTF8(e),t=r+1):(r=e.byteLength,t=e.byteLength);const s=this[__private__dont__use].malloc(t);if(!s)throw new Error("Could not allocate memory for the request body.");return typeof e=="string"?this[__private__dont__use].stringToUTF8(e,s,t+1):this[__private__dont__use].HEAPU8.set(e,s),this[__private__dont__use].ccall("wasm_set_request_body",null,[NUMBER],[s]),this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[r]),s},W=new WeakSet,ae=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},z=new WeakSet,le=function(){for(const e in a(this,P))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,a(this,P)[e]])},G=new WeakSet,ce=function(e,t){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[e,t])},J=new WeakSet,ue=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},Q=new WeakSet,de=async function(){var n;let e,t;try{e=await new Promise((i,o)=>{var c;t=p=>{console.error(p),console.error(p.error);const d=new Error("Rethrown");d.cause=p.error,d.betterMessage=p.message,o(d)},(c=a(this,g))==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 p in this)typeof this[p]=="function"&&(this[p]=()=>{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,g))==null||n.removeEventListener("error",t),h(this,P,{})}const{headers:r,httpStatusCode:s}=f(this,B,te).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 journalFSEvents(e,t,r=()=>{}){function s(){t=normalizePath(t);const i=e[__private__dont__use].FS,o=createFSHooks(i,d=>{if(d.path.startsWith(t))r(d);else if(d.operation==="RENAME"&&d.toPath.startsWith(t))for(const _ of recordExistingPath(e,d.path,d.toPath))r(_)}),l={};for(const[d]of Object.entries(o))l[d]=i[d];function c(){for(const[d,_]of Object.entries(o))i[d]=function(...V){return _(...V),l[d].apply(this,V)}}function p(){for(const[d,_]of Object.entries(l))e[__private__dont__use].FS[d]=_}e[__private__dont__use].journal={bind:c,unbind:p},c()}e.addEventListener("runtime.initialized",s),e[__private__dont__use]&&s();function n(){e[__private__dont__use].journal.unbind(),delete e[__private__dont__use].journal}return e.addEventListener("runtime.beforedestroy",n),function(){return e.removeEventListener("runtime.initialized",s),e.removeEventListener("runtime.beforedestroy",n),e[__private__dont__use].journal.unbind()}}const createFSHooks=(e,t=()=>{})=>({write(r){t({operation:"WRITE",path:r.path,nodeType:"file"})},truncate(r){let s;typeof r=="string"?s=e.lookupPath(r,{follow:!0}).node:s=r,t({operation:"WRITE",path:e.getPath(s),nodeType:"file"})},unlink(r){t({operation:"DELETE",path:r,nodeType:"file"})},mknod(r,s){e.isFile(s)&&t({operation:"CREATE",path:r,nodeType:"file"})},mkdir(r){t({operation:"CREATE",path:r,nodeType:"directory"})},rmdir(r){t({operation:"DELETE",path:r,nodeType:"directory"})},rename(r,s){try{const n=e.lookupPath(r,{follow:!0}),i=e.lookupPath(s,{parent:!0}).path;t({operation:"RENAME",nodeType:e.isDir(n.node.mode)?"directory":"file",path:n.path,toPath:joinPaths(i,basename(s))})}catch{}}});function replayFSJournal(e,t){e[__private__dont__use].journal.unbind();try{for(const r of t)r.operation==="CREATE"?r.nodeType==="file"?e.writeFile(r.path," "):e.mkdir(r.path):r.operation==="DELETE"?r.nodeType==="file"?e.unlink(r.path):e.rmdir(r.path):r.operation==="WRITE"?e.writeFile(r.path,r.data):r.operation==="RENAME"&&e.mv(r.path,r.toPath)}finally{e[__private__dont__use].journal.bind()}}function*recordExistingPath(e,t,r){if(e.isDir(t)){yield{operation:"CREATE",path:r,nodeType:"directory"};for(const s of e.listFiles(t))yield*recordExistingPath(e,joinPaths(t,s),joinPaths(r,s))}else yield{operation:"CREATE",path:r,nodeType:"file"},yield{operation:"WRITE",nodeType:"file",path:r}}function normalizePath(e){return e.replace(/\/$/,"").replace(/\/\/+/g,"/")}function normalizeFilesystemOperations(e){const t={};for(let r=e.length-1;r>=0;r--){for(let s=r-1;s>=0;s--){const n=checkRelationship(e[r],e[s]);if(n==="none")continue;const i=e[r],o=e[s];if(i.operation==="RENAME"&&o.operation==="RENAME"){console.warn("[FS Journal] Normalizing a double rename is not yet supported:",{current:i,last:o});continue}(o.operation==="CREATE"||o.operation==="WRITE")&&(i.operation==="RENAME"?n==="same_node"?(t[s]=[],t[r]=[{...o,path:i.toPath},...t[r]||[]]):n==="descendant"&&(t[s]=[],t[r]=[{...o,path:joinPaths(i.toPath,o.path.substring(i.path.length))},...t[r]||[]]):i.operation==="WRITE"&&n==="same_node"?t[s]=[]:i.operation==="DELETE"&&n==="same_node"&&(t[s]=[],t[r]=[]))}if(Object.entries(t).length>0){const s=e.flatMap((n,i)=>i in t?t[i]:[n]);return normalizeFilesystemOperations(s)}}return e}function checkRelationship(e,t){const r=e.path,s=e.operation!=="WRITE"&&e.nodeType==="directory",n=t.operation!=="WRITE"&&t.nodeType==="directory",i=t.operation==="RENAME"?t.toPath:t.path;return i===r?"same_node":n&&r.startsWith(i+"/")?"ancestor":s&&i.startsWith(r+"/")?"descendant":"none"}async function hydrateUpdateFileOps(e,t){const s=t.filter(n=>n.operation==="WRITE").map(n=>hydrateOp(e,n));return await Promise.all(s),t}const hydrateLock=new Semaphore({concurrency:15});async function hydrateOp(e,t){const r=await hydrateLock.acquire();try{t.data=await e.readFileAsBuffer(t.path)}catch(s){console.warn(`Journal failed to hydrate a file on flush: the path ${t.path} no longer exists`),console.error(s)}r()}exports.hydrateUpdateFileOps=hydrateUpdateFileOps;exports.journalFSEvents=journalFSEvents;exports.normalizeFilesystemOperations=normalizeFilesystemOperations;exports.replayFSJournal=replayFSJournal;
52
+ `;this[__private__dont__use].ccall("wasm_set_phpini_entries",null,[STRING],[e])}this[__private__dont__use].ccall("php_wasm_init",null,[],[])},B=new WeakSet,te=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}},L=new WeakSet,re=function(e){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[t])}},D=new WeakSet,se=function(e,t){this[__private__dont__use].ccall("wasm_set_request_host",null,[STRING],[e]);let r;try{r=parseInt(new URL(e).port,10)}catch{}(!r||isNaN(r)||r===80)&&(r=t==="https"?443:80),this[__private__dont__use].ccall("wasm_set_request_port",null,[NUMBER],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")},$=new WeakSet,ne=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},q=new WeakSet,ie=function(e){e.cookie&&this[__private__dont__use].ccall("wasm_set_cookies",null,[STRING],[e.cookie]),e["content-type"]&&this[__private__dont__use].ccall("wasm_set_content_type",null,[STRING],[e["content-type"]]),e["content-length"]&&this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[parseInt(e["content-length"],10)]);for(const t in e){let r="HTTP_";["content-type","content-length"].includes(t.toLowerCase())&&(r=""),this.addServerGlobalEntry(`${r}${t.toUpperCase().replace(/-/g,"_")}`,e[t])}},W=new WeakSet,oe=function(e){let t,r;typeof e=="string"?(console.warn("Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"),r=this[__private__dont__use].lengthBytesUTF8(e),t=r+1):(r=e.byteLength,t=e.byteLength);const s=this[__private__dont__use].malloc(t);if(!s)throw new Error("Could not allocate memory for the request body.");return typeof e=="string"?this[__private__dont__use].stringToUTF8(e,s,t+1):this[__private__dont__use].HEAPU8.set(e,s),this[__private__dont__use].ccall("wasm_set_request_body",null,[NUMBER],[s]),this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[r]),s},j=new WeakSet,ae=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},z=new WeakSet,le=function(){for(const e in l(this,g))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,l(this,g)[e]])},G=new WeakSet,ce=function(e,t){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[e,t])},J=new WeakSet,ue=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},Q=new WeakSet,de=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 p=new Error("Rethrown");p.cause=d.error,p.betterMessage=d.message,o(p)},(c=l(this,w))==null||c.addEventListener("error",t);const a=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return a instanceof Promise?a.then(i,o):i(a)})}catch(i){for(const d in this)typeof this[d]=="function"&&(this[d]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=getFunctionsMaybeMissingFromAsyncify();const o=i,a="betterMessage"in o?o.betterMessage:o.message,c=new Error(a);throw c.cause=o,console.error(c),c}finally{(n=l(this,w))==null||n.removeEventListener("error",t),h(this,g,{})}const{headers:r,httpStatusCode:s}=f(this,B,te).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 journalFSEvents(e,t,r=()=>{}){function s(){t=normalizePath(t);const i=e[__private__dont__use].FS,o=createFSHooks(i,p=>{if(p.path.startsWith(t))r(p);else if(p.operation==="RENAME"&&p.toPath.startsWith(t))for(const P of recordExistingPath(e,p.path,p.toPath))r(P)}),a={};for(const[p]of Object.entries(o))a[p]=i[p];function c(){for(const[p,P]of Object.entries(o))i[p]=function(...V){return P(...V),a[p].apply(this,V)}}function d(){for(const[p,P]of Object.entries(a))e[__private__dont__use].FS[p]=P}e[__private__dont__use].journal={bind:c,unbind:d},c()}e.addEventListener("runtime.initialized",s),e[__private__dont__use]&&s();function n(){e[__private__dont__use].journal.unbind(),delete e[__private__dont__use].journal}return e.addEventListener("runtime.beforedestroy",n),function(){return e.removeEventListener("runtime.initialized",s),e.removeEventListener("runtime.beforedestroy",n),e[__private__dont__use].journal.unbind()}}const createFSHooks=(e,t=()=>{})=>({write(r){t({operation:"WRITE",path:r.path,nodeType:"file"})},truncate(r){let s;typeof r=="string"?s=e.lookupPath(r,{follow:!0}).node:s=r,t({operation:"WRITE",path:e.getPath(s),nodeType:"file"})},unlink(r){t({operation:"DELETE",path:r,nodeType:"file"})},mknod(r,s){e.isFile(s)&&t({operation:"CREATE",path:r,nodeType:"file"})},mkdir(r){t({operation:"CREATE",path:r,nodeType:"directory"})},rmdir(r){t({operation:"DELETE",path:r,nodeType:"directory"})},rename(r,s){try{const n=e.lookupPath(r,{follow:!0}),i=e.lookupPath(s,{parent:!0}).path;t({operation:"RENAME",nodeType:e.isDir(n.node.mode)?"directory":"file",path:n.path,toPath:joinPaths(i,basename(s))})}catch{}}});function replayFSJournal(e,t){e[__private__dont__use].journal.unbind();try{for(const r of t)r.operation==="CREATE"?r.nodeType==="file"?e.writeFile(r.path," "):e.mkdir(r.path):r.operation==="DELETE"?r.nodeType==="file"?e.unlink(r.path):e.rmdir(r.path):r.operation==="WRITE"?e.writeFile(r.path,r.data):r.operation==="RENAME"&&e.mv(r.path,r.toPath)}finally{e[__private__dont__use].journal.bind()}}function*recordExistingPath(e,t,r){if(e.isDir(t)){yield{operation:"CREATE",path:r,nodeType:"directory"};for(const s of e.listFiles(t))yield*recordExistingPath(e,joinPaths(t,s),joinPaths(r,s))}else yield{operation:"CREATE",path:r,nodeType:"file"},yield{operation:"WRITE",nodeType:"file",path:r}}function normalizePath(e){return e.replace(/\/$/,"").replace(/\/\/+/g,"/")}function normalizeFilesystemOperations(e){const t={};for(let r=e.length-1;r>=0;r--){for(let s=r-1;s>=0;s--){const n=checkRelationship(e[r],e[s]);if(n==="none")continue;const i=e[r],o=e[s];if(i.operation==="RENAME"&&o.operation==="RENAME"){console.warn("[FS Journal] Normalizing a double rename is not yet supported:",{current:i,last:o});continue}(o.operation==="CREATE"||o.operation==="WRITE")&&(i.operation==="RENAME"?n==="same_node"?(t[s]=[],t[r]=[{...o,path:i.toPath},...t[r]||[]]):n==="descendant"&&(t[s]=[],t[r]=[{...o,path:joinPaths(i.toPath,o.path.substring(i.path.length))},...t[r]||[]]):i.operation==="WRITE"&&n==="same_node"?t[s]=[]:i.operation==="DELETE"&&n==="same_node"&&(t[s]=[],t[r]=[]))}if(Object.entries(t).length>0){const s=e.flatMap((n,i)=>i in t?t[i]:[n]);return normalizeFilesystemOperations(s)}}return e}function checkRelationship(e,t){const r=e.path,s=e.operation!=="WRITE"&&e.nodeType==="directory",n=t.operation!=="WRITE"&&t.nodeType==="directory",i=t.operation==="RENAME"?t.toPath:t.path;return i===r?"same_node":n&&r.startsWith(i+"/")?"ancestor":s&&i.startsWith(r+"/")?"descendant":"none"}async function hydrateUpdateFileOps(e,t){const s=t.filter(n=>n.operation==="WRITE").map(n=>hydrateOp(e,n));return await Promise.all(s),t}const hydrateLock=new Semaphore({concurrency:15});async function hydrateOp(e,t){const r=await hydrateLock.acquire();try{t.data=await e.readFileAsBuffer(t.path)}catch(s){console.warn(`Journal failed to hydrate a file on flush: the path ${t.path} no longer exists`),console.error(s)}r()}exports.hydrateUpdateFileOps=hydrateUpdateFileOps;exports.journalFSEvents=journalFSEvents;exports.normalizeFilesystemOperations=normalizeFilesystemOperations;exports.replayFSJournal=replayFSJournal;
package/index.js CHANGED
@@ -2,62 +2,72 @@ var Y = (e, t, r) => {
2
2
  if (!t.has(e))
3
3
  throw TypeError("Cannot " + r);
4
4
  };
5
- var a = (e, t, r) => (Y(e, t, "read from private field"), r ? r.call(e) : t.get(e)), u = (e, t, r) => {
5
+ var l = (e, t, r) => (Y(e, t, "read from private field"), r ? r.call(e) : t.get(e)), u = (e, t, r) => {
6
6
  if (t.has(e))
7
7
  throw TypeError("Cannot add the same private member more than once");
8
8
  t instanceof WeakSet ? t.add(e) : t.set(e, r);
9
9
  }, h = (e, t, r, s) => (Y(e, t, "write to private field"), s ? s.call(e, r) : t.set(e, r), r);
10
10
  var f = (e, t, r) => (Y(e, t, "access private method"), r);
11
- if (typeof File > "u") {
12
- class e extends Blob {
13
- constructor(r, s, n) {
14
- super(r);
15
- let i;
16
- n != null && n.lastModified && (i = /* @__PURE__ */ new Date()), (!i || isNaN(i.getFullYear())) && (i = /* @__PURE__ */ new Date()), this.lastModifiedDate = i, this.lastModified = i.getMilliseconds(), this.name = s || "";
11
+ const currentJsRuntime = function() {
12
+ var e;
13
+ return typeof process < "u" && ((e = process.release) == null ? void 0 : e.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : (
14
+ // @ts-ignore
15
+ typeof WorkerGlobalScope < "u" && // @ts-ignore
16
+ self instanceof WorkerGlobalScope ? "WORKER" : "NODE"
17
+ );
18
+ }();
19
+ if (currentJsRuntime === "NODE") {
20
+ let e = function(r) {
21
+ return new Promise(function(s, n) {
22
+ r.onload = r.onerror = function(i) {
23
+ r.onload = r.onerror = null, i.type === "load" ? s(r.result) : n(new Error("Failed to read the blob/file"));
24
+ };
25
+ });
26
+ }, t = function() {
27
+ const r = new Uint8Array([1, 2, 3, 4]), n = new File([r], "test").stream();
28
+ try {
29
+ return n.getReader({ mode: "byob" }), !0;
30
+ } catch {
31
+ return !1;
17
32
  }
18
- }
19
- global.File = e;
20
- }
21
- function asPromise(e) {
22
- return new Promise(function(t, r) {
23
- e.onload = e.onerror = function(s) {
24
- e.onload = e.onerror = null, s.type === "load" ? t(e.result) : r(new Error("Failed to read the blob/file"));
25
- };
26
- });
27
- }
28
- typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
29
- const t = new FileReader();
30
- return t.readAsArrayBuffer(this), asPromise(t);
31
- });
32
- typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
33
- const t = new FileReader();
34
- return t.readAsText(this), asPromise(t);
35
- });
36
- function isByobSupported() {
37
- const e = new Uint8Array([1, 2, 3, 4]), r = new File([e], "test").stream();
38
- try {
39
- return r.getReader({ mode: "byob" }), !0;
40
- } catch {
41
- return !1;
42
- }
43
- }
44
- (typeof Blob.prototype.stream > "u" || !isByobSupported()) && (Blob.prototype.stream = function() {
45
- let e = 0;
46
- const t = this;
47
- return new ReadableStream({
48
- type: "bytes",
49
- // 0.5 MB seems like a reasonable chunk size, let's adjust
50
- // this if needed.
51
- autoAllocateChunkSize: 512 * 1024,
52
- async pull(r) {
53
- const s = r.byobRequest.view, i = await t.slice(e, e + s.byteLength).arrayBuffer(), o = new Uint8Array(i);
54
- new Uint8Array(s.buffer).set(o);
55
- const l = o.byteLength;
56
- r.byobRequest.respond(l), e += l, e >= t.size && r.close();
33
+ };
34
+ if (typeof File > "u") {
35
+ class r extends Blob {
36
+ constructor(n, i, o) {
37
+ super(n);
38
+ let a;
39
+ o != null && o.lastModified && (a = /* @__PURE__ */ new Date()), (!a || isNaN(a.getFullYear())) && (a = /* @__PURE__ */ new Date()), this.lastModifiedDate = a, this.lastModified = a.getMilliseconds(), this.name = i || "";
40
+ }
57
41
  }
42
+ global.File = r;
43
+ }
44
+ typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
45
+ const s = new FileReader();
46
+ return s.readAsArrayBuffer(this), e(s);
47
+ }), typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
48
+ const s = new FileReader();
49
+ return s.readAsText(this), e(s);
50
+ }), (typeof Blob.prototype.stream > "u" || !t()) && (Blob.prototype.stream = function() {
51
+ let r = 0;
52
+ const s = this;
53
+ return new ReadableStream({
54
+ type: "bytes",
55
+ // 0.5 MB seems like a reasonable chunk size, let's adjust
56
+ // this if needed.
57
+ autoAllocateChunkSize: 512 * 1024,
58
+ async pull(n) {
59
+ const i = n.byobRequest.view, a = await s.slice(
60
+ r,
61
+ r + i.byteLength
62
+ ).arrayBuffer(), c = new Uint8Array(a);
63
+ new Uint8Array(i.buffer).set(c);
64
+ const d = c.byteLength;
65
+ n.byobRequest.respond(d), r += d, r >= s.size && n.close();
66
+ }
67
+ });
58
68
  });
59
- });
60
- if (typeof CustomEvent > "u") {
69
+ }
70
+ if (currentJsRuntime === "NODE" && typeof CustomEvent > "u") {
61
71
  class e extends Event {
62
72
  constructor(r, s = {}) {
63
73
  super(r, s), this.detail = s.detail;
@@ -121,7 +131,7 @@ function improveWASMErrorReporting(e) {
121
131
  } catch (o) {
122
132
  if (!(o instanceof Error))
123
133
  throw o;
124
- const l = clarifyErrorMessage(
134
+ const a = clarifyErrorMessage(
125
135
  o,
126
136
  (i = e.lastAsyncifyStackSource) == null ? void 0 : i.stack
127
137
  );
@@ -129,12 +139,12 @@ function improveWASMErrorReporting(e) {
129
139
  t.dispatchEvent(
130
140
  new ErrorEvent("error", {
131
141
  error: o,
132
- message: l
142
+ message: a
133
143
  })
134
144
  );
135
145
  return;
136
146
  }
137
- throw isExitCodeZero(o) || showCriticalErrorBox(l), o;
147
+ throw isExitCodeZero(o) || showCriticalErrorBox(a), o;
138
148
  }
139
149
  };
140
150
  }
@@ -278,9 +288,9 @@ function splitShellCommand(e) {
278
288
  let s = 0, n = "";
279
289
  const i = [];
280
290
  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);
291
+ for (let a = 0; a < e.length; a++) {
292
+ const c = e[a];
293
+ c === "\\" ? ((e[a + 1] === '"' || e[a + 1] === "'") && a++, o += e[a]) : s === 0 ? c === '"' || c === "'" ? (s = 1, n = c) : c.match(/\s/) ? (o.trim().length && i.push(o.trim()), o = c) : i.length && !o ? o = i.pop() + c : o += c : s === 1 && (c === n ? (s = 0, n = "") : o += c);
284
294
  }
285
295
  return o && i.push(o.trim()), i;
286
296
  }
@@ -440,7 +450,7 @@ class PHPBrowser {
440
450
  cookie: this.serializeCookies()
441
451
  }
442
452
  });
443
- if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), a(this, T).handleRedirects && s.headers.location && r < a(this, T).maxRedirects) {
453
+ if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), l(this, T).handleRedirects && s.headers.location && r < l(this, T).maxRedirects) {
444
454
  const n = new URL(
445
455
  s.headers.location[0],
446
456
  this.requestHandler.absoluteUrl
@@ -478,15 +488,15 @@ class PHPBrowser {
478
488
  if (!r.includes("="))
479
489
  continue;
480
490
  const s = r.indexOf("="), n = r.substring(0, s), i = r.substring(s + 1).split(";")[0];
481
- a(this, v)[n] = i;
491
+ l(this, v)[n] = i;
482
492
  } catch (s) {
483
493
  console.error(s);
484
494
  }
485
495
  }
486
496
  serializeCookies() {
487
497
  const t = [];
488
- for (const r in a(this, v))
489
- t.push(`${r}=${a(this, v)[r]}`);
498
+ for (const r in l(this, v))
499
+ t.push(`${r}=${l(this, v)[r]}`);
490
500
  return t.join("; ");
491
501
  }
492
502
  }
@@ -503,22 +513,22 @@ function ensurePathPrefix(e, t) {
503
513
  }
504
514
  async function encodeAsMultipart(e) {
505
515
  const t = `----${Math.random().toString(36).slice(2)}`, r = `multipart/form-data; boundary=${t}`, s = new TextEncoder(), n = [];
506
- for (const [c, p] of Object.entries(e))
516
+ for (const [c, d] of Object.entries(e))
507
517
  n.push(`--${t}\r
508
- `), n.push(`Content-Disposition: form-data; name="${c}"`), p instanceof File && n.push(`; filename="${p.name}"`), n.push(`\r
509
- `), p instanceof File && (n.push("Content-Type: application/octet-stream"), n.push(`\r
518
+ `), n.push(`Content-Disposition: form-data; name="${c}"`), d instanceof File && n.push(`; filename="${d.name}"`), n.push(`\r
519
+ `), d instanceof File && (n.push("Content-Type: application/octet-stream"), n.push(`\r
510
520
  `)), n.push(`\r
511
- `), p instanceof File ? n.push(await fileToUint8Array(p)) : n.push(p), n.push(`\r
521
+ `), d instanceof File ? n.push(await fileToUint8Array(d)) : n.push(d), n.push(`\r
512
522
  `);
513
523
  n.push(`--${t}--\r
514
524
  `);
515
- const i = n.reduce((c, p) => c + p.length, 0), o = new Uint8Array(i);
516
- let l = 0;
525
+ const i = n.reduce((c, d) => c + d.length, 0), o = new Uint8Array(i);
526
+ let a = 0;
517
527
  for (const c of n)
518
528
  o.set(
519
529
  typeof c == "string" ? s.encode(c) : c,
520
- l
521
- ), l += c.length;
530
+ a
531
+ ), a += c.length;
522
532
  return { bytes: o, contentType: r };
523
533
  }
524
534
  function fileToUint8Array(e) {
@@ -529,7 +539,7 @@ function fileToUint8Array(e) {
529
539
  }, r.readAsArrayBuffer(e);
530
540
  });
531
541
  }
532
- var y, F, I, b, x, m, C, R, N, K, O, Z, U, X;
542
+ var m, F, N, R, x, _, C, b, I, K, O, Z, M, X;
533
543
  class PHPRequestHandler {
534
544
  /**
535
545
  * @param php - The PHP instance.
@@ -542,7 +552,7 @@ class PHPRequestHandler {
542
552
  * @param fsPath - Absolute path of the static file to serve.
543
553
  * @returns The response.
544
554
  */
545
- u(this, N);
555
+ u(this, I);
546
556
  /**
547
557
  * Runs the requested PHP file with all the request and $_SERVER
548
558
  * superglobals populated.
@@ -560,32 +570,33 @@ class PHPRequestHandler {
560
570
  * @throws {Error} If the requested path doesn't exist.
561
571
  * @returns The resolved filesystem path.
562
572
  */
563
- u(this, U);
564
- u(this, y, void 0);
573
+ u(this, M);
574
+ u(this, m, void 0);
565
575
  u(this, F, void 0);
566
- u(this, I, void 0);
567
- u(this, b, void 0);
576
+ u(this, N, void 0);
577
+ u(this, R, void 0);
568
578
  u(this, x, void 0);
569
- u(this, m, void 0);
579
+ u(this, _, void 0);
570
580
  u(this, C, void 0);
571
- u(this, R, void 0);
572
- h(this, R, new Semaphore({ concurrency: 1 }));
581
+ u(this, b, void 0);
582
+ h(this, b, new Semaphore({ concurrency: 1 }));
573
583
  const {
574
584
  documentRoot: s = "/www/",
575
- absoluteUrl: n = typeof location == "object" ? location == null ? void 0 : location.href : ""
585
+ absoluteUrl: n = typeof location == "object" ? location == null ? void 0 : location.href : "",
586
+ rewriteRules: i = []
576
587
  } = r;
577
- this.php = t, h(this, y, s);
578
- const i = new URL(n);
579
- h(this, I, i.hostname), h(this, b, i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80), h(this, F, (i.protocol || "").replace(":", ""));
580
- const o = a(this, b) !== 443 && a(this, b) !== 80;
588
+ this.php = t, h(this, m, s);
589
+ const o = new URL(n);
590
+ h(this, N, o.hostname), h(this, R, o.port ? Number(o.port) : o.protocol === "https:" ? 443 : 80), h(this, F, (o.protocol || "").replace(":", ""));
591
+ const a = l(this, R) !== 443 && l(this, R) !== 80;
581
592
  h(this, x, [
582
- a(this, I),
583
- o ? `:${a(this, b)}` : ""
584
- ].join("")), h(this, m, i.pathname.replace(/\/+$/, "")), h(this, C, [
585
- `${a(this, F)}://`,
586
- a(this, x),
587
- a(this, m)
588
- ].join(""));
593
+ l(this, N),
594
+ a ? `:${l(this, R)}` : ""
595
+ ].join("")), h(this, _, o.pathname.replace(/\/+$/, "")), h(this, C, [
596
+ `${l(this, F)}://`,
597
+ l(this, x),
598
+ l(this, _)
599
+ ].join("")), this.rewriteRules = i;
589
600
  }
590
601
  /** @inheritDoc */
591
602
  pathToInternalUrl(t) {
@@ -594,32 +605,32 @@ class PHPRequestHandler {
594
605
  /** @inheritDoc */
595
606
  internalUrlToPath(t) {
596
607
  const r = new URL(t);
597
- return r.pathname.startsWith(a(this, m)) && (r.pathname = r.pathname.slice(a(this, m).length)), toRelativeUrl(r);
608
+ return r.pathname.startsWith(l(this, _)) && (r.pathname = r.pathname.slice(l(this, _).length)), toRelativeUrl(r);
598
609
  }
599
610
  get isRequestRunning() {
600
- return a(this, R).running > 0;
611
+ return l(this, b).running > 0;
601
612
  }
602
613
  /** @inheritDoc */
603
614
  get absoluteUrl() {
604
- return a(this, C);
615
+ return l(this, C);
605
616
  }
606
617
  /** @inheritDoc */
607
618
  get documentRoot() {
608
- return a(this, y);
619
+ return l(this, m);
609
620
  }
610
621
  /** @inheritDoc */
611
622
  async request(t) {
612
623
  const r = t.url.startsWith("http://") || t.url.startsWith("https://"), s = new URL(
613
624
  t.url,
614
625
  r ? void 0 : DEFAULT_BASE_URL
615
- ), n = removePathPrefix(
616
- s.pathname,
617
- a(this, m)
618
- ), i = `${a(this, y)}${n}`;
619
- return seemsLikeAPHPRequestHandlerPath(i) ? await f(this, O, Z).call(this, t, s) : f(this, N, K).call(this, i);
626
+ ), n = applyRewriteRules(
627
+ removePathPrefix(s.pathname, l(this, _)),
628
+ this.rewriteRules
629
+ ), i = `${l(this, m)}${n}`;
630
+ return seemsLikeAPHPRequestHandlerPath(i) ? await f(this, O, Z).call(this, t, s) : f(this, I, K).call(this, i);
620
631
  }
621
632
  }
622
- y = new WeakMap(), F = new WeakMap(), I = new WeakMap(), b = new WeakMap(), x = new WeakMap(), m = new WeakMap(), C = new WeakMap(), R = new WeakMap(), N = new WeakSet(), K = function(t) {
633
+ m = new WeakMap(), F = new WeakMap(), N = new WeakMap(), R = new WeakMap(), x = new WeakMap(), _ = new WeakMap(), C = new WeakMap(), b = new WeakMap(), I = new WeakSet(), K = function(t) {
623
634
  if (!this.php.fileExists(t))
624
635
  return new PHPResponse(
625
636
  404,
@@ -645,8 +656,8 @@ y = new WeakMap(), F = new WeakMap(), I = new WeakMap(), b = new WeakMap(), x =
645
656
  r
646
657
  );
647
658
  }, O = new WeakSet(), Z = async function(t, r) {
648
- var n, i;
649
- if (a(this, R).running > 0 && ((n = t.headers) == null ? void 0 : n["x-request-issuer"]) === "php")
659
+ var n;
660
+ if (l(this, b).running > 0 && ((n = t.headers) == null ? void 0 : n["x-request-issuer"]) === "php")
650
661
  return console.warn(
651
662
  "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."
652
663
  ), new PHPResponse(
@@ -654,34 +665,26 @@ y = new WeakMap(), F = new WeakMap(), I = new WeakMap(), b = new WeakMap(), x =
654
665
  {},
655
666
  new TextEncoder().encode("502 Bad Gateway")
656
667
  );
657
- const s = await a(this, R).acquire();
668
+ const s = await l(this, b).acquire();
658
669
  try {
659
- this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", a(this, y)), this.php.addServerGlobalEntry(
670
+ this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", l(this, m)), this.php.addServerGlobalEntry(
660
671
  "HTTPS",
661
- a(this, C).startsWith("https://") ? "on" : ""
672
+ l(this, C).startsWith("https://") ? "on" : ""
662
673
  );
663
- let o = "GET";
664
- const l = {
665
- host: a(this, x),
674
+ let i = "GET";
675
+ const o = {
676
+ host: l(this, x),
666
677
  ...normalizeHeaders(t.headers || {})
667
678
  };
668
- let c = t.body;
669
- if (typeof c == "object" && !(c instanceof Uint8Array)) {
670
- o = "POST";
671
- const { bytes: d, contentType: _ } = await encodeAsMultipart(c);
672
- c = d, l["content-type"] = _;
679
+ let a = t.body;
680
+ if (typeof a == "object" && !(a instanceof Uint8Array)) {
681
+ i = "POST";
682
+ const { bytes: d, contentType: p } = await encodeAsMultipart(a);
683
+ a = d, o["content-type"] = p;
673
684
  }
674
- let p;
685
+ let c;
675
686
  try {
676
- let d = r.pathname;
677
- if ((i = t.headers) != null && i["x-rewrite-url"])
678
- try {
679
- d = new URL(
680
- t.headers["x-rewrite-url"]
681
- ).pathname;
682
- } catch {
683
- }
684
- p = f(this, U, X).call(this, d);
687
+ c = f(this, M, X).call(this, r.pathname);
685
688
  } catch {
686
689
  return new PHPResponse(
687
690
  404,
@@ -692,21 +695,21 @@ y = new WeakMap(), F = new WeakMap(), I = new WeakMap(), b = new WeakMap(), x =
692
695
  return await this.php.run({
693
696
  relativeUri: ensurePathPrefix(
694
697
  toRelativeUrl(r),
695
- a(this, m)
698
+ l(this, _)
696
699
  ),
697
- protocol: a(this, F),
698
- method: t.method || o,
699
- body: c,
700
- scriptPath: p,
701
- headers: l
700
+ protocol: l(this, F),
701
+ method: t.method || i,
702
+ body: a,
703
+ scriptPath: c,
704
+ headers: o
702
705
  });
703
706
  } finally {
704
707
  s();
705
708
  }
706
- }, U = new WeakSet(), X = function(t) {
707
- let r = removePathPrefix(t, a(this, m));
708
- r.includes(".php") ? r = r.split(".php")[0] + ".php" : this.php.isDir(`${a(this, y)}${r}`) ? (r.endsWith("/") || (r = `${r}/`), r = `${r}index.php`) : r = "/index.php";
709
- const s = `${a(this, y)}${r}`;
709
+ }, M = new WeakSet(), X = function(t) {
710
+ let r = removePathPrefix(t, l(this, _));
711
+ r = applyRewriteRules(r, this.rewriteRules), r.includes(".php") ? r = r.split(".php")[0] + ".php" : this.php.isDir(`${l(this, m)}${r}`) ? (r.endsWith("/") || (r = `${r}/`), r = `${r}index.php`) : r = "/index.php";
712
+ const s = `${l(this, m)}${r}`;
710
713
  if (this.php.fileExists(s))
711
714
  return s;
712
715
  throw new Error(`File not found: ${s}`);
@@ -760,6 +763,12 @@ function seemsLikeAPHPFile(e) {
760
763
  function seemsLikeADirectoryRoot(e) {
761
764
  return !e.split("/").pop().includes(".");
762
765
  }
766
+ function applyRewriteRules(e, t) {
767
+ for (const r of t)
768
+ if (new RegExp(r.match).test(e))
769
+ return e.replace(r.match, r.replacement);
770
+ return e;
771
+ }
763
772
  const FileErrorCodes = {
764
773
  0: "No error occurred. System call completed successfully.",
765
774
  1: "Argument list too long.",
@@ -850,15 +859,15 @@ function rethrowFileSystemError(e = "") {
850
859
  n.value = function(...o) {
851
860
  try {
852
861
  return i.apply(this, o);
853
- } catch (l) {
854
- const c = typeof l == "object" ? l == null ? void 0 : l.errno : null;
862
+ } catch (a) {
863
+ const c = typeof a == "object" ? a == null ? void 0 : a.errno : null;
855
864
  if (c in FileErrorCodes) {
856
- const p = FileErrorCodes[c], d = typeof o[0] == "string" ? o[0] : null, _ = d !== null ? e.replaceAll("{path}", d) : e;
857
- throw new Error(`${_}: ${p}`, {
858
- cause: l
865
+ const d = FileErrorCodes[c], p = typeof o[0] == "string" ? o[0] : null, P = p !== null ? e.replaceAll("{path}", p) : e;
866
+ throw new Error(`${P}: ${d}`, {
867
+ cause: a
859
868
  });
860
869
  }
861
- throw l;
870
+ throw a;
862
871
  }
863
872
  };
864
873
  };
@@ -877,7 +886,7 @@ var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyD
877
886
  return s && n && __defProp(t, r, n), n;
878
887
  };
879
888
  const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
880
- var S, A, k, E, g, P, w, H, M, ee, B, te, L, re, $, se, D, ne, q, ie, W, oe, j, ae, z, le, G, ce, J, ue, Q, de;
889
+ var S, k, A, y, w, g, E, H, U, ee, B, te, L, re, D, se, $, ne, q, ie, W, oe, j, ae, z, le, G, ce, J, ue, Q, de;
881
890
  class BasePHP {
882
891
  /**
883
892
  * Initializes a PHP runtime.
@@ -887,11 +896,11 @@ class BasePHP {
887
896
  * @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
888
897
  */
889
898
  constructor(e, t) {
890
- u(this, M);
899
+ u(this, U);
891
900
  u(this, B);
892
901
  u(this, L);
893
- u(this, $);
894
902
  u(this, D);
903
+ u(this, $);
895
904
  u(this, q);
896
905
  u(this, W);
897
906
  u(this, j);
@@ -900,33 +909,33 @@ class BasePHP {
900
909
  u(this, J);
901
910
  u(this, Q);
902
911
  u(this, S, void 0);
903
- u(this, A, void 0);
904
912
  u(this, k, void 0);
905
- u(this, E, void 0);
906
- u(this, g, void 0);
907
- u(this, P, void 0);
913
+ u(this, A, void 0);
914
+ u(this, y, void 0);
908
915
  u(this, w, void 0);
916
+ u(this, g, void 0);
917
+ u(this, E, void 0);
909
918
  u(this, H, void 0);
910
- h(this, S, []), h(this, E, !1), h(this, g, null), h(this, P, {}), h(this, w, /* @__PURE__ */ new Map()), h(this, H, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new PHPBrowser(
919
+ h(this, S, []), h(this, y, !1), h(this, w, null), h(this, g, {}), h(this, E, /* @__PURE__ */ new Map()), h(this, H, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new PHPBrowser(
911
920
  new PHPRequestHandler(this, t)
912
921
  ));
913
922
  }
914
923
  addEventListener(e, t) {
915
- a(this, w).has(e) || a(this, w).set(e, /* @__PURE__ */ new Set()), a(this, w).get(e).add(t);
924
+ l(this, E).has(e) || l(this, E).set(e, /* @__PURE__ */ new Set()), l(this, E).get(e).add(t);
916
925
  }
917
926
  removeEventListener(e, t) {
918
927
  var r;
919
- (r = a(this, w).get(e)) == null || r.delete(t);
928
+ (r = l(this, E).get(e)) == null || r.delete(t);
920
929
  }
921
930
  dispatchEvent(e) {
922
- const t = a(this, w).get(e.type);
931
+ const t = l(this, E).get(e.type);
923
932
  if (t)
924
933
  for (const r of t)
925
934
  r(e);
926
935
  }
927
936
  /** @inheritDoc */
928
937
  async onMessage(e) {
929
- a(this, H).push(e);
938
+ l(this, H).push(e);
930
939
  }
931
940
  /** @inheritDoc */
932
941
  async setSpawnHandler(handler) {
@@ -957,13 +966,13 @@ class BasePHP {
957
966
  if (!t)
958
967
  throw new Error("Invalid PHP runtime id.");
959
968
  this[__private__dont__use] = t, t.onMessage = async (r) => {
960
- for (const s of a(this, H)) {
969
+ for (const s of l(this, H)) {
961
970
  const n = await s(r);
962
971
  if (n)
963
972
  return n;
964
973
  }
965
974
  return "";
966
- }, h(this, g, improveWASMErrorReporting(t)), this.dispatchEvent({
975
+ }, h(this, w, improveWASMErrorReporting(t)), this.dispatchEvent({
967
976
  type: "runtime.initialized"
968
977
  });
969
978
  }
@@ -978,13 +987,13 @@ class BasePHP {
978
987
  throw new Error(
979
988
  "Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?"
980
989
  );
981
- h(this, k, e);
990
+ h(this, A, e);
982
991
  }
983
992
  /** @inheritDoc */
984
993
  setPhpIniPath(e) {
985
- if (a(this, E))
994
+ if (l(this, y))
986
995
  throw new Error("Cannot set PHP ini path after calling run().");
987
- h(this, A, e), this[__private__dont__use].ccall(
996
+ h(this, k, e), this[__private__dont__use].ccall(
988
997
  "wasm_set_phpini_path",
989
998
  null,
990
999
  ["string"],
@@ -993,9 +1002,9 @@ class BasePHP {
993
1002
  }
994
1003
  /** @inheritDoc */
995
1004
  setPhpIniEntry(e, t) {
996
- if (a(this, E))
1005
+ if (l(this, y))
997
1006
  throw new Error("Cannot set PHP ini entries after calling run().");
998
- a(this, S).push([e, t]);
1007
+ l(this, S).push([e, t]);
999
1008
  }
1000
1009
  /** @inheritDoc */
1001
1010
  chdir(e) {
@@ -1012,29 +1021,34 @@ class BasePHP {
1012
1021
  const t = await this.semaphore.acquire();
1013
1022
  let r;
1014
1023
  try {
1015
- if (a(this, E) || (f(this, M, ee).call(this), h(this, E, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
1024
+ if (l(this, y) || (f(this, U, ee).call(this), h(this, y, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
1016
1025
  throw new Error(
1017
1026
  `The script path "${e.scriptPath}" does not exist.`
1018
1027
  );
1019
- f(this, j, ae).call(this, e.scriptPath || ""), f(this, L, re).call(this, e.relativeUri || ""), f(this, D, ne).call(this, e.method || "GET");
1028
+ f(this, j, ae).call(this, e.scriptPath || ""), f(this, L, re).call(this, e.relativeUri || ""), f(this, $, ne).call(this, e.method || "GET");
1020
1029
  const s = normalizeHeaders(e.headers || {}), n = s.host || "example.com:443";
1021
- f(this, $, se).call(this, n, e.protocol || "http"), f(this, q, ie).call(this, s), e.body && (r = f(this, W, oe).call(this, e.body)), typeof e.code == "string" && f(this, J, ue).call(this, " ?>" + e.code), f(this, z, le).call(this);
1030
+ f(this, D, se).call(this, n, e.protocol || "http"), f(this, q, ie).call(this, s), e.body && (r = f(this, W, oe).call(this, e.body)), typeof e.code == "string" && f(this, J, ue).call(this, " ?>" + e.code), f(this, z, le).call(this);
1022
1031
  const i = e.env || {};
1023
- for (const l in i)
1024
- f(this, G, ce).call(this, l, i[l]);
1032
+ for (const a in i)
1033
+ f(this, G, ce).call(this, a, i[a]);
1025
1034
  const o = await f(this, Q, de).call(this);
1026
1035
  if (e.throwOnError && o.exitCode !== 0) {
1027
- const l = {
1036
+ const a = {
1028
1037
  stdout: o.text,
1029
1038
  stderr: o.errors
1030
1039
  };
1031
- console.warn("PHP.run() output was:", l);
1040
+ console.warn("PHP.run() output was:", a);
1032
1041
  const c = new Error(
1033
1042
  `PHP.run() failed with exit code ${o.exitCode} and the following output: ` + o.errors
1034
1043
  );
1035
- throw c.output = l, console.error(c), c;
1044
+ throw c.output = a, console.error(c), c;
1036
1045
  }
1037
1046
  return o;
1047
+ } catch (s) {
1048
+ throw this.dispatchEvent({
1049
+ type: "request.error",
1050
+ error: s
1051
+ }), s;
1038
1052
  } finally {
1039
1053
  try {
1040
1054
  r && this[__private__dont__use].free(r);
@@ -1046,7 +1060,7 @@ class BasePHP {
1046
1060
  }
1047
1061
  }
1048
1062
  addServerGlobalEntry(e, t) {
1049
- a(this, P)[e] = t;
1063
+ l(this, g)[e] = t;
1050
1064
  }
1051
1065
  defineConstant(e, t) {
1052
1066
  let r = {};
@@ -1142,7 +1156,7 @@ class BasePHP {
1142
1156
  this.exit();
1143
1157
  } catch {
1144
1158
  }
1145
- if (this.initializeRuntime(e), a(this, A) && this.setPhpIniPath(a(this, A)), a(this, k) && this.setSapiName(a(this, k)), this.requestHandler) {
1159
+ if (this.initializeRuntime(e), l(this, k) && this.setPhpIniPath(l(this, k)), l(this, A) && this.setSapiName(l(this, A)), this.requestHandler) {
1146
1160
  const r = this.documentRoot;
1147
1161
  copyFS(t, this[__private__dont__use].FS, r);
1148
1162
  }
@@ -1155,10 +1169,10 @@ class BasePHP {
1155
1169
  this[__private__dont__use]._exit(e);
1156
1170
  } catch {
1157
1171
  }
1158
- h(this, E, !1), h(this, g, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1172
+ h(this, y, !1), h(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1159
1173
  }
1160
1174
  }
1161
- S = new WeakMap(), A = new WeakMap(), k = new WeakMap(), E = new WeakMap(), g = new WeakMap(), P = new WeakMap(), w = new WeakMap(), H = new WeakMap(), M = new WeakSet(), ee = function() {
1175
+ S = new WeakMap(), k = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w = new WeakMap(), g = new WeakMap(), E = new WeakMap(), H = new WeakMap(), U = new WeakSet(), ee = function() {
1162
1176
  if (this.setPhpIniEntry("auto_prepend_file", "/internal/consts.php"), this.fileExists("/internal/consts.php") || this.writeFile(
1163
1177
  "/internal/consts.php",
1164
1178
  `<?php
@@ -1170,8 +1184,8 @@ S = new WeakMap(), A = new WeakMap(), k = new WeakMap(), E = new WeakMap(), g =
1170
1184
  }
1171
1185
  }
1172
1186
  }`
1173
- ), a(this, S).length > 0) {
1174
- const e = a(this, S).map(([t, r]) => `${t}=${r}`).join(`
1187
+ ), l(this, S).length > 0) {
1188
+ const e = l(this, S).map(([t, r]) => `${t}=${r}`).join(`
1175
1189
  `) + `
1176
1190
 
1177
1191
  `;
@@ -1215,7 +1229,7 @@ S = new WeakMap(), A = new WeakMap(), k = new WeakMap(), E = new WeakMap(), g =
1215
1229
  [t]
1216
1230
  );
1217
1231
  }
1218
- }, $ = new WeakSet(), se = function(e, t) {
1232
+ }, D = new WeakSet(), se = function(e, t) {
1219
1233
  this[__private__dont__use].ccall(
1220
1234
  "wasm_set_request_host",
1221
1235
  null,
@@ -1233,7 +1247,7 @@ S = new WeakMap(), A = new WeakMap(), k = new WeakMap(), E = new WeakMap(), g =
1233
1247
  [NUMBER],
1234
1248
  [r]
1235
1249
  ), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
1236
- }, D = new WeakSet(), ne = function(e) {
1250
+ }, $ = new WeakSet(), ne = function(e) {
1237
1251
  this[__private__dont__use].ccall(
1238
1252
  "wasm_set_request_method",
1239
1253
  null,
@@ -1295,12 +1309,12 @@ S = new WeakMap(), A = new WeakMap(), k = new WeakMap(), E = new WeakMap(), g =
1295
1309
  [e]
1296
1310
  );
1297
1311
  }, z = new WeakSet(), le = function() {
1298
- for (const e in a(this, P))
1312
+ for (const e in l(this, g))
1299
1313
  this[__private__dont__use].ccall(
1300
1314
  "wasm_add_SERVER_entry",
1301
1315
  null,
1302
1316
  [STRING, STRING],
1303
- [e, a(this, P)[e]]
1317
+ [e, l(this, g)[e]]
1304
1318
  );
1305
1319
  }, G = new WeakSet(), ce = function(e, t) {
1306
1320
  this[__private__dont__use].ccall(
@@ -1322,35 +1336,35 @@ S = new WeakMap(), A = new WeakMap(), k = new WeakMap(), E = new WeakMap(), g =
1322
1336
  try {
1323
1337
  e = await new Promise((i, o) => {
1324
1338
  var c;
1325
- t = (p) => {
1326
- console.error(p), console.error(p.error);
1327
- const d = new Error("Rethrown");
1328
- d.cause = p.error, d.betterMessage = p.message, o(d);
1329
- }, (c = a(this, g)) == null || c.addEventListener(
1339
+ t = (d) => {
1340
+ console.error(d), console.error(d.error);
1341
+ const p = new Error("Rethrown");
1342
+ p.cause = d.error, p.betterMessage = d.message, o(p);
1343
+ }, (c = l(this, w)) == null || c.addEventListener(
1330
1344
  "error",
1331
1345
  t
1332
1346
  );
1333
- const l = this[__private__dont__use].ccall(
1347
+ const a = this[__private__dont__use].ccall(
1334
1348
  "wasm_sapi_handle_request",
1335
1349
  NUMBER,
1336
1350
  [],
1337
1351
  [],
1338
1352
  { async: !0 }
1339
1353
  );
1340
- return l instanceof Promise ? l.then(i, o) : i(l);
1354
+ return a instanceof Promise ? a.then(i, o) : i(a);
1341
1355
  });
1342
1356
  } catch (i) {
1343
- for (const p in this)
1344
- typeof this[p] == "function" && (this[p] = () => {
1357
+ for (const d in this)
1358
+ typeof this[d] == "function" && (this[d] = () => {
1345
1359
  throw new Error(
1346
1360
  "PHP runtime has crashed – see the earlier error for details."
1347
1361
  );
1348
1362
  });
1349
1363
  this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
1350
- const o = i, l = "betterMessage" in o ? o.betterMessage : o.message, c = new Error(l);
1364
+ const o = i, a = "betterMessage" in o ? o.betterMessage : o.message, c = new Error(a);
1351
1365
  throw c.cause = o, console.error(c), c;
1352
1366
  } finally {
1353
- (n = a(this, g)) == null || n.removeEventListener("error", t), h(this, P, {});
1367
+ (n = l(this, w)) == null || n.removeEventListener("error", t), h(this, g, {});
1354
1368
  }
1355
1369
  const { headers: r, httpStatusCode: s } = f(this, B, te).call(this);
1356
1370
  return new PHPResponse(
@@ -1419,32 +1433,32 @@ function journalFSEvents(e, t, r = () => {
1419
1433
  }) {
1420
1434
  function s() {
1421
1435
  t = normalizePath(t);
1422
- const i = e[__private__dont__use].FS, o = createFSHooks(i, (d) => {
1423
- if (d.path.startsWith(t))
1424
- r(d);
1425
- else if (d.operation === "RENAME" && d.toPath.startsWith(t))
1426
- for (const _ of recordExistingPath(
1436
+ const i = e[__private__dont__use].FS, o = createFSHooks(i, (p) => {
1437
+ if (p.path.startsWith(t))
1438
+ r(p);
1439
+ else if (p.operation === "RENAME" && p.toPath.startsWith(t))
1440
+ for (const P of recordExistingPath(
1427
1441
  e,
1428
- d.path,
1429
- d.toPath
1442
+ p.path,
1443
+ p.toPath
1430
1444
  ))
1431
- r(_);
1432
- }), l = {};
1433
- for (const [d] of Object.entries(o))
1434
- l[d] = i[d];
1445
+ r(P);
1446
+ }), a = {};
1447
+ for (const [p] of Object.entries(o))
1448
+ a[p] = i[p];
1435
1449
  function c() {
1436
- for (const [d, _] of Object.entries(o))
1437
- i[d] = function(...V) {
1438
- return _(...V), l[d].apply(this, V);
1450
+ for (const [p, P] of Object.entries(o))
1451
+ i[p] = function(...V) {
1452
+ return P(...V), a[p].apply(this, V);
1439
1453
  };
1440
1454
  }
1441
- function p() {
1442
- for (const [d, _] of Object.entries(l))
1443
- e[__private__dont__use].FS[d] = _;
1455
+ function d() {
1456
+ for (const [p, P] of Object.entries(a))
1457
+ e[__private__dont__use].FS[p] = P;
1444
1458
  }
1445
1459
  e[__private__dont__use].journal = {
1446
1460
  bind: c,
1447
- unbind: p
1461
+ unbind: d
1448
1462
  }, c();
1449
1463
  }
1450
1464
  e.addEventListener("runtime.initialized", s), e[__private__dont__use] && s();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/fs-journal",
3
- "version": "0.6.6",
3
+ "version": "0.6.8",
4
4
  "description": "Bindings to journal the PHP filesystem",
5
5
  "repository": {
6
6
  "type": "git",
@@ -36,7 +36,7 @@
36
36
  "main": "./index.cjs",
37
37
  "module": "./index.js",
38
38
  "license": "GPL-2.0-or-later",
39
- "gitHead": "90f82ca946f8573b358c1320be0b6b8674f67cfc",
39
+ "gitHead": "cb7b1af260489022238495a2fc0d96f767a1294a",
40
40
  "engines": {
41
41
  "node": ">=18.18.2",
42
42
  "npm": ">=8.11.0"