@php-wasm/universal 0.9.37 → 0.9.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var V=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)};var p=(t,e,r)=>(V(t,e,"read from private field"),r?r.call(t):e.get(t)),u=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},h=(t,e,r,s)=>(V(t,e,"write to private field"),s?s.call(t,r):e.set(t,r),r);var d=(t,e,r)=>(V(t,e,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("@php-wasm/node-polyfills");const logger=require("@php-wasm/logger"),util=require("@php-wasm/util"),ini=require("ini"),streamCompression=require("@php-wasm/stream-compression"),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(t){const e=typeof t=="object"?t==null?void 0:t.errno:null;if(e in FileErrorCodes)return FileErrorCodes[e]}function rethrowFileSystemError(t=""){return function(r,s,i){const n=i.value;i.value=function(...o){try{return n.apply(this,o)}catch(a){const l=typeof a=="object"?a==null?void 0:a.errno:null;if(l in FileErrorCodes){const c=FileErrorCodes[l],y=typeof o[1]=="string"?o[1]:null,pe=y!==null?t.replaceAll("{path}",y):t;throw new Error(`${pe}: ${c}`,{cause:a})}throw a}}}}var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__decorateClass=(t,e,r,s)=>{for(var i=s>1?void 0:s?__getOwnPropDesc(e,r):e,n=t.length-1,o;n>=0;n--)(o=t[n])&&(i=(s?o(e,r,i):o(i))||i);return s&&i&&__defProp(e,r,i),i};const _FSHelpers=class m{static readFileAsText(e,r){return new TextDecoder().decode(m.readFileAsBuffer(e,r))}static readFileAsBuffer(e,r){return e.readFile(r)}static writeFile(e,r,s){e.writeFile(r,s)}static unlink(e,r){e.unlink(r)}static mv(e,r,s){try{const i=e.lookupPath(r).node.mount,n=m.fileExists(e,s)?e.lookupPath(s).node.mount:e.lookupPath(util.dirname(s)).node.mount;i.mountpoint!==n.mountpoint?(m.copyRecursive(e,r,s),m.rmdir(e,r,{recursive:!0})):e.rename(r,s)}catch(i){const n=getEmscriptenFsError(i);throw n?new Error(`Could not move ${r} to ${s}: ${n}`,{cause:i}):i}}static rmdir(e,r,s={recursive:!0}){s!=null&&s.recursive&&m.listFiles(e,r).forEach(i=>{const n=`${r}/${i}`;m.isDir(e,n)?m.rmdir(e,n,s):m.unlink(e,n)}),e.rmdir(r)}static listFiles(e,r,s={prependPath:!1}){if(!m.fileExists(e,r))return[];try{const i=e.readdir(r).filter(n=>n!=="."&&n!=="..");if(s.prependPath){const n=r.replace(/\/$/,"");return i.map(o=>`${n}/${o}`)}return i}catch(i){return logger.logger.error(i,{path:r}),[]}}static isDir(e,r){return m.fileExists(e,r)?e.isDir(e.lookupPath(r).node.mode):!1}static isFile(e,r){return m.fileExists(e,r)?e.isFile(e.lookupPath(r).node.mode):!1}static fileExists(e,r){try{return e.lookupPath(r),!0}catch{return!1}}static mkdir(e,r){e.mkdirTree(r)}static copyRecursive(e,r,s){const i=e.lookupPath(r).node;if(e.isDir(i.mode)){e.mkdirTree(s);const n=e.readdir(r).filter(o=>o!=="."&&o!=="..");for(const o of n)m.copyRecursive(e,util.joinPaths(r,o),util.joinPaths(s,o))}else e.writeFile(s,e.readFile(r))}};__decorateClass([rethrowFileSystemError('Could not read "{path}"')],_FSHelpers,"readFileAsText",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],_FSHelpers,"readFileAsBuffer",1);__decorateClass([rethrowFileSystemError('Could not write to "{path}"')],_FSHelpers,"writeFile",1);__decorateClass([rethrowFileSystemError('Could not unlink "{path}"')],_FSHelpers,"unlink",1);__decorateClass([rethrowFileSystemError('Could not remove directory "{path}"')],_FSHelpers,"rmdir",1);__decorateClass([rethrowFileSystemError('Could not list files in "{path}"')],_FSHelpers,"listFiles",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],_FSHelpers,"isDir",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],_FSHelpers,"fileExists",1);__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],_FSHelpers,"mkdir",1);__decorateClass([rethrowFileSystemError('Could not copy files from "{path}"')],_FSHelpers,"copyRecursive",1);let FSHelpers=_FSHelpers;const _private=new WeakMap;class PHPWorker{constructor(e,r){this.absoluteUrl="",this.documentRoot="",_private.set(this,{monitor:r}),e&&this.__internal_setRequestHandler(e)}__internal_setRequestHandler(e){this.absoluteUrl=e.absoluteUrl,this.documentRoot=e.documentRoot,_private.set(this,{..._private.get(this),requestHandler:e})}__internal_getPHP(){return _private.get(this).php}async setPrimaryPHP(e){_private.set(this,{..._private.get(this),php:e})}pathToInternalUrl(e){return _private.get(this).requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return _private.get(this).requestHandler.internalUrlToPath(e)}async onDownloadProgress(e){var r;return(r=_private.get(this).monitor)==null?void 0:r.addEventListener("progress",e)}async mv(e,r){return _private.get(this).php.mv(e,r)}async rmdir(e,r){return _private.get(this).php.rmdir(e,r)}async request(e){return await _private.get(this).requestHandler.request(e)}async run(e){const{php:r,reap:s}=await _private.get(this).requestHandler.processManager.acquirePHPInstance();try{return await r.run(e)}finally{s()}}chdir(e){return _private.get(this).php.chdir(e)}setSapiName(e){_private.get(this).php.setSapiName(e)}mkdir(e){return _private.get(this).php.mkdir(e)}mkdirTree(e){return _private.get(this).php.mkdirTree(e)}readFileAsText(e){return _private.get(this).php.readFileAsText(e)}readFileAsBuffer(e){return _private.get(this).php.readFileAsBuffer(e)}writeFile(e,r){return _private.get(this).php.writeFile(e,r)}unlink(e){return _private.get(this).php.unlink(e)}listFiles(e,r){return _private.get(this).php.listFiles(e,r)}isDir(e){return _private.get(this).php.isDir(e)}isFile(e){return _private.get(this).php.isFile(e)}fileExists(e){return _private.get(this).php.fileExists(e)}onMessage(e){_private.get(this).php.onMessage(e)}defineConstant(e,r){_private.get(this).php.defineConstant(e,r)}addEventListener(e,r){_private.get(this).php.addEventListener(e,r)}removeEventListener(e,r){_private.get(this).php.removeEventListener(e,r)}}const responseTexts={500:"Internal Server Error",502:"Bad Gateway",404:"Not Found",403:"Forbidden",401:"Unauthorized",400:"Bad Request",301:"Moved Permanently",302:"Found",307:"Temporary Redirect",308:"Permanent Redirect",204:"No Content",201:"Created",200:"OK"};class PHPResponse{constructor(e,r,s,i="",n=0){this.httpStatusCode=e,this.headers=r,this.bytes=s,this.exitCode=n,this.errors=i}static forHttpCode(e,r=""){return new PHPResponse(e,{},new TextEncoder().encode(r||responseTexts[e]||""))}static fromRawData(e){return new PHPResponse(e.httpStatusCode,e.headers,e.bytes,e.errors,e.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(t,e={}){const[r,s,i]=makePromise(),n=t.init(currentJsRuntime,{onAbort(a){i(a),logger.logger.error(a)},ENV:{},locateFile:a=>a,...e,noInitialRun:!0,onRuntimeInitialized(){e.onRuntimeInitialized&&e.onRuntimeInitialized(),s()}});await r;const o=++lastRuntimeId;return n.id=o,n.originalExit=n._exit,n._exit=function(a){return n.outboundNetworkProxyServer&&(n.outboundNetworkProxyServer.close(),n.outboundNetworkProxyServer.closeAllConnections()),loadedRuntimes.delete(o),n.originalExit(a)},n[RuntimeId]=o,loadedRuntimes.set(o,n),o}function getLoadedRuntime(t){return loadedRuntimes.get(t)}const currentJsRuntime=function(){var t;return typeof process<"u"&&((t=process.release)==null?void 0:t.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),makePromise=()=>{const t=[],e=new Promise((r,s)=>{t.push(r,s)});return t.unshift(e),t},kError=Symbol("error"),kMessage=Symbol("message");class ErrorEvent2 extends Event{constructor(e,r={}){super(e),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(t){return t instanceof Error?"exitCode"in t&&(t==null?void 0:t.exitCode)===0||(t==null?void 0:t.name)==="ExitStatus"&&"status"in t&&t.status===0:!1}class UnhandledRejectionsTarget extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(e,r){++this.listenersCount,super.addEventListener(e,r)}removeEventListener(e,r){--this.listenersCount,super.removeEventListener(e,r)}hasListeners(){return this.listenersCount>0}}function improveWASMErrorReporting(t){const e=new UnhandledRejectionsTarget;for(const r in t.wasmExports)if(typeof t.wasmExports[r]=="function"){const s=t.wasmExports[r];t.wasmExports[r]=function(...i){var n;try{return s(...i)}catch(o){if(!(o instanceof Error))throw o;const a=clarifyErrorMessage(o,(n=t.lastAsyncifyStackSource)==null?void 0:n.stack);if(t.lastAsyncifyStackSource&&(o.cause=t.lastAsyncifyStackSource),e.hasListeners()){e.dispatchEvent(new ErrorEvent("error",{error:o,message:a}));return}throw isExitCodeZero(o)||showCriticalErrorBox(a),o}}}return e}let functionsMaybeMissingFromAsyncify=[];function getFunctionsMaybeMissingFromAsyncify(){return functionsMaybeMissingFromAsyncify}function clarifyErrorMessage(t,e){if(t.message==="unreachable"){let r=UNREACHABLE_ERROR;e||(r+=`
1
+ "use strict";var V=(t,e,r)=>{if(!e.has(t))throw TypeError("Cannot "+r)};var p=(t,e,r)=>(V(t,e,"read from private field"),r?r.call(t):e.get(t)),u=(t,e,r)=>{if(e.has(t))throw TypeError("Cannot add the same private member more than once");e instanceof WeakSet?e.add(t):e.set(t,r)},h=(t,e,r,s)=>(V(t,e,"write to private field"),s?s.call(t,r):e.set(t,r),r);var d=(t,e,r)=>(V(t,e,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("@php-wasm/node-polyfills");const logger=require("@php-wasm/logger"),util=require("@php-wasm/util"),ini=require("ini"),streamCompression=require("@php-wasm/stream-compression"),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(t){const e=typeof t=="object"?t==null?void 0:t.errno:null;if(e in FileErrorCodes)return FileErrorCodes[e]}function rethrowFileSystemError(t=""){return function(r,s,i){const n=i.value;i.value=function(...o){try{return n.apply(this,o)}catch(a){const l=typeof a=="object"?a==null?void 0:a.errno:null;if(l in FileErrorCodes){const c=FileErrorCodes[l],y=typeof o[1]=="string"?o[1]:null,pe=y!==null?t.replaceAll("{path}",y):t;throw new Error(`${pe}: ${c}`,{cause:a})}throw a}}}}var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__decorateClass=(t,e,r,s)=>{for(var i=s>1?void 0:s?__getOwnPropDesc(e,r):e,n=t.length-1,o;n>=0;n--)(o=t[n])&&(i=(s?o(e,r,i):o(i))||i);return s&&i&&__defProp(e,r,i),i};const _FSHelpers=class m{static readFileAsText(e,r){return new TextDecoder().decode(m.readFileAsBuffer(e,r))}static readFileAsBuffer(e,r){return e.readFile(r)}static writeFile(e,r,s){e.writeFile(r,s)}static unlink(e,r){e.unlink(r)}static mv(e,r,s){try{const i=e.lookupPath(r).node.mount,n=m.fileExists(e,s)?e.lookupPath(s).node.mount:e.lookupPath(util.dirname(s)).node.mount;i.mountpoint!==n.mountpoint?(m.copyRecursive(e,r,s),m.rmdir(e,r,{recursive:!0})):e.rename(r,s)}catch(i){const n=getEmscriptenFsError(i);throw n?new Error(`Could not move ${r} to ${s}: ${n}`,{cause:i}):i}}static rmdir(e,r,s={recursive:!0}){s!=null&&s.recursive&&m.listFiles(e,r).forEach(i=>{const n=`${r}/${i}`;m.isDir(e,n)?m.rmdir(e,n,s):m.unlink(e,n)}),e.rmdir(r)}static listFiles(e,r,s={prependPath:!1}){if(!m.fileExists(e,r))return[];try{const i=e.readdir(r).filter(n=>n!=="."&&n!=="..");if(s.prependPath){const n=r.replace(/\/$/,"");return i.map(o=>`${n}/${o}`)}return i}catch(i){return logger.logger.error(i,{path:r}),[]}}static isDir(e,r){return m.fileExists(e,r)?e.isDir(e.lookupPath(r,{follow:!0}).node.mode):!1}static isFile(e,r){return m.fileExists(e,r)?e.isFile(e.lookupPath(r,{follow:!0}).node.mode):!1}static symlink(e,r,s){return e.symlink(r,s)}static isSymlink(e,r){return m.fileExists(e,r)?e.isLink(e.lookupPath(r).node.mode):!1}static readlink(e,r){return e.readlink(r)}static realpath(e,r){return e.lookupPath(r,{follow:!0}).path}static fileExists(e,r){try{return e.lookupPath(r),!0}catch{return!1}}static mkdir(e,r){e.mkdirTree(r)}static copyRecursive(e,r,s){const i=e.lookupPath(r).node;if(e.isDir(i.mode)){e.mkdirTree(s);const n=e.readdir(r).filter(o=>o!=="."&&o!=="..");for(const o of n)m.copyRecursive(e,util.joinPaths(r,o),util.joinPaths(s,o))}else e.writeFile(s,e.readFile(r))}};__decorateClass([rethrowFileSystemError('Could not read "{path}"')],_FSHelpers,"readFileAsText",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],_FSHelpers,"readFileAsBuffer",1);__decorateClass([rethrowFileSystemError('Could not write to "{path}"')],_FSHelpers,"writeFile",1);__decorateClass([rethrowFileSystemError('Could not unlink "{path}"')],_FSHelpers,"unlink",1);__decorateClass([rethrowFileSystemError('Could not remove directory "{path}"')],_FSHelpers,"rmdir",1);__decorateClass([rethrowFileSystemError('Could not list files in "{path}"')],_FSHelpers,"listFiles",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],_FSHelpers,"isDir",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],_FSHelpers,"isFile",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],_FSHelpers,"realpath",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],_FSHelpers,"fileExists",1);__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],_FSHelpers,"mkdir",1);__decorateClass([rethrowFileSystemError('Could not copy files from "{path}"')],_FSHelpers,"copyRecursive",1);let FSHelpers=_FSHelpers;const _private=new WeakMap;class PHPWorker{constructor(e,r){this.absoluteUrl="",this.documentRoot="",_private.set(this,{monitor:r}),e&&this.__internal_setRequestHandler(e)}__internal_setRequestHandler(e){this.absoluteUrl=e.absoluteUrl,this.documentRoot=e.documentRoot,_private.set(this,{..._private.get(this),requestHandler:e})}__internal_getPHP(){return _private.get(this).php}async setPrimaryPHP(e){_private.set(this,{..._private.get(this),php:e})}pathToInternalUrl(e){return _private.get(this).requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return _private.get(this).requestHandler.internalUrlToPath(e)}async onDownloadProgress(e){var r;return(r=_private.get(this).monitor)==null?void 0:r.addEventListener("progress",e)}async mv(e,r){return _private.get(this).php.mv(e,r)}async rmdir(e,r){return _private.get(this).php.rmdir(e,r)}async request(e){return await _private.get(this).requestHandler.request(e)}async run(e){const{php:r,reap:s}=await _private.get(this).requestHandler.processManager.acquirePHPInstance();try{return await r.run(e)}finally{s()}}chdir(e){return _private.get(this).php.chdir(e)}setSapiName(e){_private.get(this).php.setSapiName(e)}mkdir(e){return _private.get(this).php.mkdir(e)}mkdirTree(e){return _private.get(this).php.mkdirTree(e)}readFileAsText(e){return _private.get(this).php.readFileAsText(e)}readFileAsBuffer(e){return _private.get(this).php.readFileAsBuffer(e)}writeFile(e,r){return _private.get(this).php.writeFile(e,r)}unlink(e){return _private.get(this).php.unlink(e)}listFiles(e,r){return _private.get(this).php.listFiles(e,r)}isDir(e){return _private.get(this).php.isDir(e)}isFile(e){return _private.get(this).php.isFile(e)}fileExists(e){return _private.get(this).php.fileExists(e)}onMessage(e){_private.get(this).php.onMessage(e)}defineConstant(e,r){_private.get(this).php.defineConstant(e,r)}addEventListener(e,r){_private.get(this).php.addEventListener(e,r)}removeEventListener(e,r){_private.get(this).php.removeEventListener(e,r)}}const responseTexts={500:"Internal Server Error",502:"Bad Gateway",404:"Not Found",403:"Forbidden",401:"Unauthorized",400:"Bad Request",301:"Moved Permanently",302:"Found",307:"Temporary Redirect",308:"Permanent Redirect",204:"No Content",201:"Created",200:"OK"};class PHPResponse{constructor(e,r,s,i="",n=0){this.httpStatusCode=e,this.headers=r,this.bytes=s,this.exitCode=n,this.errors=i}static forHttpCode(e,r=""){return new PHPResponse(e,{},new TextEncoder().encode(r||responseTexts[e]||""))}static fromRawData(e){return new PHPResponse(e.httpStatusCode,e.headers,e.bytes,e.errors,e.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(t,e={}){const[r,s,i]=makePromise(),n=t.init(currentJsRuntime,{onAbort(a){i(a),logger.logger.error(a)},ENV:{},locateFile:a=>a,...e,noInitialRun:!0,onRuntimeInitialized(){e.onRuntimeInitialized&&e.onRuntimeInitialized(),s()}});await r;const o=++lastRuntimeId;return n.id=o,n.originalExit=n._exit,n._exit=function(a){return n.outboundNetworkProxyServer&&(n.outboundNetworkProxyServer.close(),n.outboundNetworkProxyServer.closeAllConnections()),loadedRuntimes.delete(o),n.originalExit(a)},n[RuntimeId]=o,loadedRuntimes.set(o,n),o}function getLoadedRuntime(t){return loadedRuntimes.get(t)}const currentJsRuntime=function(){var t;return typeof process<"u"&&((t=process.release)==null?void 0:t.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),makePromise=()=>{const t=[],e=new Promise((r,s)=>{t.push(r,s)});return t.unshift(e),t},kError=Symbol("error"),kMessage=Symbol("message");class ErrorEvent2 extends Event{constructor(e,r={}){super(e),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(t){return t instanceof Error?"exitCode"in t&&(t==null?void 0:t.exitCode)===0||(t==null?void 0:t.name)==="ExitStatus"&&"status"in t&&t.status===0:!1}class UnhandledRejectionsTarget extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(e,r){++this.listenersCount,super.addEventListener(e,r)}removeEventListener(e,r){--this.listenersCount,super.removeEventListener(e,r)}hasListeners(){return this.listenersCount>0}}function improveWASMErrorReporting(t){const e=new UnhandledRejectionsTarget;for(const r in t.wasmExports)if(typeof t.wasmExports[r]=="function"){const s=t.wasmExports[r];t.wasmExports[r]=function(...i){var n;try{return s(...i)}catch(o){if(!(o instanceof Error))throw o;const a=clarifyErrorMessage(o,(n=t.lastAsyncifyStackSource)==null?void 0:n.stack);if(t.lastAsyncifyStackSource&&(o.cause=t.lastAsyncifyStackSource),e.hasListeners()){e.dispatchEvent(new ErrorEvent("error",{error:o,message:a}));return}throw isExitCodeZero(o)||showCriticalErrorBox(a),o}}}return e}let functionsMaybeMissingFromAsyncify=[];function getFunctionsMaybeMissingFromAsyncify(){return functionsMaybeMissingFromAsyncify}function clarifyErrorMessage(t,e){if(t.message==="unreachable"){let r=UNREACHABLE_ERROR;e||(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,7 +32,7 @@ CLI option:
32
32
  ${eol}
33
33
  ${bold} WASM ERROR${reset}${redBg}`);for(const e of t.split(`
34
34
  `))logger.logger.log(`${eol} ${e} `);logger.logger.log(`${reset}`)}}function extractPHPFunctionsFromStack(t){try{const e=t.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(e))}catch{return[]}}const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");class PHPExecutionFailureError extends Error{constructor(e,r,s){super(e),this.response=r,this.source=s}}const PHP_INI_PATH="/internal/shared/php.ini",AUTO_PREPEND_SCRIPT="/internal/shared/auto_prepend_file.php";var x,g,P,_,E,k,J,I,Y,C,Z,A,K,N,X,M,Q,j,ee,U,te,L,re,q,se,b,G,$,ie,B,ne,O,oe;class PHP{constructor(t){u(this,k);u(this,I);u(this,C);u(this,A);u(this,N);u(this,M);u(this,j);u(this,U);u(this,L);u(this,q);u(this,b);u(this,$);u(this,B);u(this,O);u(this,x,void 0);u(this,g,void 0);u(this,P,void 0);u(this,_,void 0);u(this,E,void 0);h(this,g,!1),h(this,P,null),h(this,_,new Map),h(this,E,[]),this.semaphore=new util.Semaphore({concurrency:1}),t!==void 0&&this.initializeRuntime(t)}addEventListener(t,e){p(this,_).has(t)||p(this,_).set(t,new Set),p(this,_).get(t).add(e)}removeEventListener(t,e){var r;(r=p(this,_).get(t))==null||r.delete(e)}dispatchEvent(t){const e=p(this,_).get(t.type);if(e)for(const r of e)r(t)}onMessage(t){p(this,E).push(t)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=util.createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}pathToInternalUrl(t){return this.requestHandler.pathToInternalUrl(t)}internalUrlToPath(t){return this.requestHandler.internalUrlToPath(t)}initializeRuntime(t){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const e=getLoadedRuntime(t);if(!e)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=e,this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[PHP_INI_PATH]),this.fileExists(PHP_INI_PATH)||this.writeFile(PHP_INI_PATH,["auto_prepend_file="+AUTO_PREPEND_SCRIPT,"memory_limit=256M","ignore_repeated_errors = 1","error_reporting = E_ALL","display_errors = 1","html_errors = 1","display_startup_errors = On","log_errors = 1","always_populate_raw_post_data = -1","upload_max_filesize = 2000M","post_max_size = 2000M","disable_functions = curl_exec,curl_multi_exec","allow_url_fopen = Off","allow_url_include = Off","session.save_path = /home/web_user","implicit_flush = 1","output_buffering = 0","max_execution_time = 0","max_input_time = -1"].join(`
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(e))}catch{return[]}}const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");class PHPExecutionFailureError extends Error{constructor(e,r,s){super(e),this.response=r,this.source=s}}const PHP_INI_PATH="/internal/shared/php.ini",AUTO_PREPEND_SCRIPT="/internal/shared/auto_prepend_file.php";var x,g,P,_,E,T,J,I,Y,C,Z,A,K,N,X,M,Q,j,ee,U,te,L,re,q,se,b,G,$,ie,B,ne,O,oe;class PHP{constructor(t){u(this,T);u(this,I);u(this,C);u(this,A);u(this,N);u(this,M);u(this,j);u(this,U);u(this,L);u(this,q);u(this,b);u(this,$);u(this,B);u(this,O);u(this,x,void 0);u(this,g,void 0);u(this,P,void 0);u(this,_,void 0);u(this,E,void 0);h(this,g,!1),h(this,P,null),h(this,_,new Map),h(this,E,[]),this.semaphore=new util.Semaphore({concurrency:1}),t!==void 0&&this.initializeRuntime(t)}addEventListener(t,e){p(this,_).has(t)||p(this,_).set(t,new Set),p(this,_).get(t).add(e)}removeEventListener(t,e){var r;(r=p(this,_).get(t))==null||r.delete(e)}dispatchEvent(t){const e=p(this,_).get(t.type);if(e)for(const r of e)r(t)}onMessage(t){p(this,E).push(t)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=util.createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}pathToInternalUrl(t){return this.requestHandler.pathToInternalUrl(t)}internalUrlToPath(t){return this.requestHandler.internalUrlToPath(t)}initializeRuntime(t){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const e=getLoadedRuntime(t);if(!e)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=e,this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[PHP_INI_PATH]),this.fileExists(PHP_INI_PATH)||this.writeFile(PHP_INI_PATH,["auto_prepend_file="+AUTO_PREPEND_SCRIPT,"memory_limit=256M","ignore_repeated_errors = 1","error_reporting = E_ALL","display_errors = 1","html_errors = 1","display_startup_errors = On","log_errors = 1","always_populate_raw_post_data = -1","upload_max_filesize = 2000M","post_max_size = 2000M","disable_functions = curl_exec,curl_multi_exec","allow_url_fopen = Off","allow_url_include = Off","session.save_path = /home/web_user","implicit_flush = 1","output_buffering = 0","max_execution_time = 0","max_input_time = -1"].join(`
36
36
  `)),this.fileExists(AUTO_PREPEND_SCRIPT)||this.writeFile(AUTO_PREPEND_SCRIPT,`<?php
37
37
  // Define constants set via defineConstant() calls
38
38
  if(file_exists('/internal/shared/consts.json')) {
@@ -47,10 +47,10 @@ ${bold} WASM ERROR${reset}${redBg}`);for(const e of t.split(`
47
47
  foreach (glob('/internal/shared/preload/*.php') as $file) {
48
48
  require_once $file;
49
49
  }
50
- `),e.onMessage=async r=>{for(const s of p(this,E)){const i=await s(r);if(i)return i}return""},h(this,P,improveWASMErrorReporting(e)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(t){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[t])!==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,x,t)}chdir(t){this[__private__dont__use].FS.chdir(t)}async request(t){if(logger.logger.warn("PHP.request() is deprecated. Please use new PHPRequestHandler() instead."),!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(t)}async run(t){const e=await this.semaphore.acquire();let r;try{if(p(this,g)||(d(this,I,Y).call(this),h(this,g,!0)),t.scriptPath&&!this.fileExists(t.scriptPath))throw new Error(`The script path "${t.scriptPath}" does not exist.`);d(this,A,K).call(this,t.relativeUri||""),d(this,U,te).call(this,t.method||"GET");const s=normalizeHeaders(t.headers||{}),i=s.host||"example.com:443",n=d(this,j,ee).call(this,i,t.protocol||"http");if(d(this,N,X).call(this,i),d(this,M,Q).call(this,n),d(this,L,re).call(this,s),t.body&&(r=d(this,q,se).call(this,t.body)),typeof t.code=="string")this.writeFile("/internal/eval.php",t.code),d(this,b,G).call(this,"/internal/eval.php");else if(typeof t.scriptPath=="string")d(this,b,G).call(this,t.scriptPath||"");else throw new TypeError("The request object must have either a `code` or a `scriptPath` property.");const o=d(this,k,J).call(this,t.$_SERVER,s,n);for(const c in o)d(this,$,ie).call(this,c,o[c]);const a=t.env||{};for(const c in a)d(this,B,ne).call(this,c,a[c]);const l=await d(this,O,oe).call(this);if(l.exitCode!==0){logger.logger.warn("PHP.run() output was:",l.text);const c=new PHPExecutionFailureError(`PHP.run() failed with exit code ${l.exitCode} and the following output: `+l.errors,l,"request");throw logger.logger.error(c),c}return l}catch(s){throw this.dispatchEvent({type:"request.error",error:s,source:s.source??"php-wasm"}),s}finally{try{r&&this[__private__dont__use].free(r)}finally{e(),this.dispatchEvent({type:"request.end"})}}}defineConstant(t,e){let r={};try{r=JSON.parse(this.fileExists("/internal/shared/consts.json")&&this.readFileAsText("/internal/shared/consts.json")||"{}")}catch{}this.writeFile("/internal/shared/consts.json",JSON.stringify({...r,[t]:e}))}mkdir(t){return FSHelpers.mkdir(this[__private__dont__use].FS,t)}mkdirTree(t){return FSHelpers.mkdir(this[__private__dont__use].FS,t)}readFileAsText(t){return FSHelpers.readFileAsText(this[__private__dont__use].FS,t)}readFileAsBuffer(t){return FSHelpers.readFileAsBuffer(this[__private__dont__use].FS,t)}writeFile(t,e){return FSHelpers.writeFile(this[__private__dont__use].FS,t,e)}unlink(t){return FSHelpers.unlink(this[__private__dont__use].FS,t)}mv(t,e){return FSHelpers.mv(this[__private__dont__use].FS,t,e)}rmdir(t,e={recursive:!0}){return FSHelpers.rmdir(this[__private__dont__use].FS,t,e)}listFiles(t,e={prependPath:!1}){return FSHelpers.listFiles(this[__private__dont__use].FS,t,e)}isDir(t){return FSHelpers.isDir(this[__private__dont__use].FS,t)}isFile(t){return FSHelpers.isFile(this[__private__dont__use].FS,t)}fileExists(t){return FSHelpers.fileExists(this[__private__dont__use].FS,t)}hotSwapPHPRuntime(t,e){const r=this[__private__dont__use].FS;try{this.exit()}catch{}this.initializeRuntime(t),p(this,x)&&this.setSapiName(p(this,x)),e&&copyFS(r,this[__private__dont__use].FS,e)}async mount(t,e){return await e(this,this[__private__dont__use].FS,t)}async cli(t){for(const e of t)this[__private__dont__use].ccall("wasm_add_cli_arg",null,[STRING],[e]);try{return await this[__private__dont__use].ccall("run_cli",null,[],[],{async:!0})}catch(e){if(isExitCodeZero(e))return 0;throw e}}setSkipShebang(t){this[__private__dont__use].ccall("wasm_set_skip_shebang",null,[NUMBER],[t?1:0])}exit(t=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(t)}catch{}h(this,g,!1),h(this,P,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}[Symbol.dispose](){p(this,g)&&this.exit(0)}}x=new WeakMap,g=new WeakMap,P=new WeakMap,_=new WeakMap,E=new WeakMap,k=new WeakSet,J=function(t,e,r){const s={...t||{}};s.HTTPS=s.HTTPS||r===443?"on":"off";for(const i in e){let n="HTTP_";["content-type","content-length"].includes(i.toLowerCase())&&(n=""),s[`${n}${i.toUpperCase().replace(/-/g,"_")}`]=e[i]}return s},I=new WeakSet,Y=function(){this[__private__dont__use].ccall("php_wasm_init",null,[],[])},C=new WeakSet,Z=function(){const t="/internal/headers.json";if(!this.fileExists(t))throw new Error("SAPI Error: Could not find response headers file.");const e=JSON.parse(this.readFileAsText(t)),r={};for(const s of e.headers){if(!s.includes(": "))continue;const i=s.indexOf(": "),n=s.substring(0,i).toLowerCase(),o=s.substring(i+2);n in r||(r[n]=[]),r[n].push(o)}return{headers:r,httpStatusCode:e.status}},A=new WeakSet,K=function(t){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[t]),t.includes("?")){const e=t.substring(t.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[e])}},N=new WeakSet,X=function(t){this[__private__dont__use].ccall("wasm_set_request_host",null,[STRING],[t])},M=new WeakSet,Q=function(t){this[__private__dont__use].ccall("wasm_set_request_port",null,[NUMBER],[t])},j=new WeakSet,ee=function(t,e){let r;try{r=parseInt(new URL(t).port,10)}catch{}return(!r||isNaN(r)||r===80)&&(r=e==="https"?443:80),r},U=new WeakSet,te=function(t){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[t])},L=new WeakSet,re=function(t){t.cookie&&this[__private__dont__use].ccall("wasm_set_cookies",null,[STRING],[t.cookie]),t["content-type"]&&this[__private__dont__use].ccall("wasm_set_content_type",null,[STRING],[t["content-type"]]),t["content-length"]&&this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[parseInt(t["content-length"],10)])},q=new WeakSet,se=function(t){let e,r;typeof t=="string"?(logger.logger.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(t),e=r+1):(r=t.byteLength,e=t.byteLength);const s=this[__private__dont__use].malloc(e);if(!s)throw new Error("Could not allocate memory for the request body.");return typeof t=="string"?this[__private__dont__use].stringToUTF8(t,s,e+1):this[__private__dont__use].HEAPU8.set(t,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},b=new WeakSet,G=function(t){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[t])},$=new WeakSet,ie=function(t,e){this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[t,e])},B=new WeakSet,ne=function(t,e){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[t,e])},O=new WeakSet,oe=async function(){var i;let t,e;try{t=await new Promise((n,o)=>{var l;e=c=>{logger.logger.error(c),logger.logger.error(c.error);const y=new Error("Rethrown");y.cause=c.error,y.betterMessage=c.message,o(y)},(l=p(this,P))==null||l.addEventListener("error",e);const a=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return a instanceof Promise?a.then(n,o):n(a)})}catch(n){for(const c in this)typeof this[c]=="function"&&(this[c]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=getFunctionsMaybeMissingFromAsyncify();const o=n,a="betterMessage"in o?o.betterMessage:o.message,l=new Error(a);throw l.cause=o,logger.logger.error(l),l}finally{(i=p(this,P))==null||i.removeEventListener("error",e)}const{headers:r,httpStatusCode:s}=d(this,C,Z).call(this);return new PHPResponse(t===0?s:500,r,this.readFileAsBuffer("/internal/stdout"),this.readFileAsText("/internal/stderr"),t)};function normalizeHeaders(t){const e={};for(const r in t)e[r.toLowerCase()]=t[r];return e}function copyFS(t,e,r){let s;try{s=t.lookupPath(r)}catch{return}if(!("contents"in s.node))return;if(!t.isDir(s.node.mode)){e.writeFile(r,t.readFile(r));return}e.mkdirTree(r);const i=t.readdir(r).filter(n=>n!=="."&&n!=="..");for(const n of i)copyFS(t,e,util.joinPaths(r,n))}async function getPhpIniEntries(t,e){const r=ini.parse(await t.readFileAsText(PHP_INI_PATH));if(e===void 0)return r;const s={};for(const i of e)s[i]=r[i];return s}async function setPhpIniEntries(t,e){const r=ini.parse(await t.readFileAsText(PHP_INI_PATH));for(const[s,i]of Object.entries(e))i==null?delete r[s]:r[s]=i;await t.writeFile(PHP_INI_PATH,ini.stringify(r))}async function withPHPIniValues(t,e,r){const s=await t.readFileAsText(PHP_INI_PATH);try{return await setPhpIniEntries(t,e),await r()}finally{await t.writeFile(PHP_INI_PATH,s)}}class HttpCookieStore{constructor(){this.cookies={}}rememberCookiesFromResponseHeaders(e){if(e!=null&&e["set-cookie"])for(const r of e["set-cookie"])try{if(!r.includes("="))continue;const s=r.indexOf("="),i=r.substring(0,s),n=r.substring(s+1).split(";")[0];this.cookies[i]=n}catch(s){logger.logger.error(s)}}getCookieRequestHeader(){const e=[];for(const r in this.cookies)e.push(`${r}=${this.cookies[r]}`);return e.join("; ")}}function streamReadFileFromPHP(t,e){return new ReadableStream({async pull(r){const s=await t.readFileAsBuffer(e);r.enqueue(s),r.close()}})}async function*iteratePhpFiles(t,e,{relativePaths:r=!0,pathPrefix:s,exceptPaths:i=[]}={}){e=util.normalizePath(e);const n=[e];for(;n.length;){const o=n.pop();if(!o)return;const a=await t.listFiles(o);for(const l of a){const c=`${o}/${l}`;if(i.includes(c.substring(e.length+1)))continue;await t.isDir(c)?n.push(c):yield new streamCompression.StreamedFile(streamReadFileFromPHP(t,c),r?util.joinPaths(s||"",c.substring(e.length+1)):c)}}}function writeFilesStreamToPhp(t,e){return new WritableStream({async write(r){const s=util.joinPaths(e,r.name);r.type==="directory"?await t.mkdir(s):(await t.mkdir(util.dirname(s)),await t.writeFile(s,new Uint8Array(await r.arrayBuffer())))}})}class MaxPhpInstancesError extends Error{constructor(e){super(`Requested more concurrent PHP instances than the limit (${e}).`),this.name=this.constructor.name}}class PHPProcessManager{constructor(e){this.primaryIdle=!0,this.nextInstance=null,this.allInstances=[],this.maxPhpInstances=(e==null?void 0:e.maxPhpInstances)??5,this.phpFactory=e==null?void 0:e.phpFactory,this.primaryPhp=e==null?void 0:e.primaryPhp,this.semaphore=new util.Semaphore({concurrency:this.maxPhpInstances,timeout:(e==null?void 0:e.timeout)||5e3})}async getPrimaryPhp(){if(!this.phpFactory&&!this.primaryPhp)throw new Error("phpFactory or primaryPhp must be set before calling getPrimaryPhp().");if(!this.primaryPhp){const e=await this.spawn({isPrimary:!0});this.primaryPhp=e.php}return this.primaryPhp}async acquirePHPInstance(){if(this.primaryIdle)return this.primaryIdle=!1,{php:await this.getPrimaryPhp(),reap:()=>this.primaryIdle=!0};const e=this.nextInstance||this.spawn({isPrimary:!1});return this.semaphore.remaining>0?this.nextInstance=this.spawn({isPrimary:!1}):this.nextInstance=null,await e}spawn(e){if(e.isPrimary&&this.allInstances.length>0)throw new Error("Requested spawning a primary PHP instance when another primary instance already started spawning.");const r=this.doSpawn(e);this.allInstances.push(r);const s=()=>{this.allInstances=this.allInstances.filter(i=>i!==r)};return r.catch(i=>{throw s(),i}).then(i=>({...i,reap:()=>{s(),i.reap()}}))}async doSpawn(e){let r;try{r=await this.semaphore.acquire()}catch(s){throw s instanceof util.AcquireTimeoutError?new MaxPhpInstancesError(this.maxPhpInstances):s}try{const s=await this.phpFactory(e);return{php:s,reap(){s.exit(),r()}}}catch(s){throw r(),s}}async[Symbol.asyncDispose](){this.primaryPhp&&this.primaryPhp.exit(),await Promise.all(this.allInstances.map(e=>e.then(({reap:r})=>r())))}}const SupportedPHPVersions=["8.3","8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0"],LatestSupportedPHPVersion=SupportedPHPVersions[0],SupportedPHPVersionsList=SupportedPHPVersions,SupportedPHPExtensionsList=["iconv","mbstring","xml-bundle","gd"],SupportedPHPExtensionBundles={"kitchen-sink":SupportedPHPExtensionsList,light:[]},DEFAULT_BASE_URL="http://example.com";function toRelativeUrl(t){return t.toString().substring(t.origin.length)}function removePathPrefix(t,e){return!e||!t.startsWith(e)?t:t.substring(e.length)}function ensurePathPrefix(t,e){return!e||t.startsWith(e)?t:e+t}async function encodeAsMultipart(t){const e=`----${Math.random().toString(36).slice(2)}`,r=`multipart/form-data; boundary=${e}`,s=new TextEncoder,i=[];for(const[l,c]of Object.entries(t))i.push(`--${e}\r
50
+ `),e.onMessage=async r=>{for(const s of p(this,E)){const i=await s(r);if(i)return i}return""},h(this,P,improveWASMErrorReporting(e)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(t){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[t])!==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,x,t)}chdir(t){this[__private__dont__use].FS.chdir(t)}async request(t){if(logger.logger.warn("PHP.request() is deprecated. Please use new PHPRequestHandler() instead."),!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(t)}async run(t){const e=await this.semaphore.acquire();let r;try{if(p(this,g)||(d(this,I,Y).call(this),h(this,g,!0)),t.scriptPath&&!this.fileExists(t.scriptPath))throw new Error(`The script path "${t.scriptPath}" does not exist.`);d(this,A,K).call(this,t.relativeUri||""),d(this,U,te).call(this,t.method||"GET");const s=normalizeHeaders(t.headers||{}),i=s.host||"example.com:443",n=d(this,j,ee).call(this,i,t.protocol||"http");if(d(this,N,X).call(this,i),d(this,M,Q).call(this,n),d(this,L,re).call(this,s),t.body&&(r=d(this,q,se).call(this,t.body)),typeof t.code=="string")this.writeFile("/internal/eval.php",t.code),d(this,b,G).call(this,"/internal/eval.php");else if(typeof t.scriptPath=="string")d(this,b,G).call(this,t.scriptPath||"");else throw new TypeError("The request object must have either a `code` or a `scriptPath` property.");const o=d(this,T,J).call(this,t.$_SERVER,s,n);for(const c in o)d(this,$,ie).call(this,c,o[c]);const a=t.env||{};for(const c in a)d(this,B,ne).call(this,c,a[c]);const l=await d(this,O,oe).call(this);if(l.exitCode!==0){logger.logger.warn("PHP.run() output was:",l.text);const c=new PHPExecutionFailureError(`PHP.run() failed with exit code ${l.exitCode} and the following output: `+l.errors,l,"request");throw logger.logger.error(c),c}return l}catch(s){throw this.dispatchEvent({type:"request.error",error:s,source:s.source??"php-wasm"}),s}finally{try{r&&this[__private__dont__use].free(r)}finally{e(),this.dispatchEvent({type:"request.end"})}}}defineConstant(t,e){let r={};try{r=JSON.parse(this.fileExists("/internal/shared/consts.json")&&this.readFileAsText("/internal/shared/consts.json")||"{}")}catch{}this.writeFile("/internal/shared/consts.json",JSON.stringify({...r,[t]:e}))}mkdir(t){return FSHelpers.mkdir(this[__private__dont__use].FS,t)}mkdirTree(t){return FSHelpers.mkdir(this[__private__dont__use].FS,t)}readFileAsText(t){return FSHelpers.readFileAsText(this[__private__dont__use].FS,t)}readFileAsBuffer(t){return FSHelpers.readFileAsBuffer(this[__private__dont__use].FS,t)}writeFile(t,e){return FSHelpers.writeFile(this[__private__dont__use].FS,t,e)}unlink(t){return FSHelpers.unlink(this[__private__dont__use].FS,t)}mv(t,e){return FSHelpers.mv(this[__private__dont__use].FS,t,e)}rmdir(t,e={recursive:!0}){return FSHelpers.rmdir(this[__private__dont__use].FS,t,e)}listFiles(t,e={prependPath:!1}){return FSHelpers.listFiles(this[__private__dont__use].FS,t,e)}isDir(t){return FSHelpers.isDir(this[__private__dont__use].FS,t)}isFile(t){return FSHelpers.isFile(this[__private__dont__use].FS,t)}symlink(t,e){return FSHelpers.symlink(this[__private__dont__use].FS,t,e)}isSymlink(t){return FSHelpers.isSymlink(this[__private__dont__use].FS,t)}readlink(t){return FSHelpers.readlink(this[__private__dont__use].FS,t)}realpath(t){return FSHelpers.realpath(this[__private__dont__use].FS,t)}fileExists(t){return FSHelpers.fileExists(this[__private__dont__use].FS,t)}hotSwapPHPRuntime(t,e){const r=this[__private__dont__use].FS;try{this.exit()}catch{}this.initializeRuntime(t),p(this,x)&&this.setSapiName(p(this,x)),e&&copyFS(r,this[__private__dont__use].FS,e)}async mount(t,e){return await e(this,this[__private__dont__use].FS,t)}async cli(t){for(const e of t)this[__private__dont__use].ccall("wasm_add_cli_arg",null,[STRING],[e]);try{return await this[__private__dont__use].ccall("run_cli",null,[],[],{async:!0})}catch(e){if(isExitCodeZero(e))return 0;throw e}}setSkipShebang(t){this[__private__dont__use].ccall("wasm_set_skip_shebang",null,[NUMBER],[t?1:0])}exit(t=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(t)}catch{}h(this,g,!1),h(this,P,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}[Symbol.dispose](){p(this,g)&&this.exit(0)}}x=new WeakMap,g=new WeakMap,P=new WeakMap,_=new WeakMap,E=new WeakMap,T=new WeakSet,J=function(t,e,r){const s={...t||{}};s.HTTPS=s.HTTPS||r===443?"on":"off";for(const i in e){let n="HTTP_";["content-type","content-length"].includes(i.toLowerCase())&&(n=""),s[`${n}${i.toUpperCase().replace(/-/g,"_")}`]=e[i]}return s},I=new WeakSet,Y=function(){this[__private__dont__use].ccall("php_wasm_init",null,[],[])},C=new WeakSet,Z=function(){const t="/internal/headers.json";if(!this.fileExists(t))throw new Error("SAPI Error: Could not find response headers file.");const e=JSON.parse(this.readFileAsText(t)),r={};for(const s of e.headers){if(!s.includes(": "))continue;const i=s.indexOf(": "),n=s.substring(0,i).toLowerCase(),o=s.substring(i+2);n in r||(r[n]=[]),r[n].push(o)}return{headers:r,httpStatusCode:e.status}},A=new WeakSet,K=function(t){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[t]),t.includes("?")){const e=t.substring(t.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[e])}},N=new WeakSet,X=function(t){this[__private__dont__use].ccall("wasm_set_request_host",null,[STRING],[t])},M=new WeakSet,Q=function(t){this[__private__dont__use].ccall("wasm_set_request_port",null,[NUMBER],[t])},j=new WeakSet,ee=function(t,e){let r;try{r=parseInt(new URL(t).port,10)}catch{}return(!r||isNaN(r)||r===80)&&(r=e==="https"?443:80),r},U=new WeakSet,te=function(t){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[t])},L=new WeakSet,re=function(t){t.cookie&&this[__private__dont__use].ccall("wasm_set_cookies",null,[STRING],[t.cookie]),t["content-type"]&&this[__private__dont__use].ccall("wasm_set_content_type",null,[STRING],[t["content-type"]]),t["content-length"]&&this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[parseInt(t["content-length"],10)])},q=new WeakSet,se=function(t){let e,r;typeof t=="string"?(logger.logger.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(t),e=r+1):(r=t.byteLength,e=t.byteLength);const s=this[__private__dont__use].malloc(e);if(!s)throw new Error("Could not allocate memory for the request body.");return typeof t=="string"?this[__private__dont__use].stringToUTF8(t,s,e+1):this[__private__dont__use].HEAPU8.set(t,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},b=new WeakSet,G=function(t){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[t])},$=new WeakSet,ie=function(t,e){this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[t,e])},B=new WeakSet,ne=function(t,e){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[t,e])},O=new WeakSet,oe=async function(){var i;let t,e;try{t=await new Promise((n,o)=>{var l;e=c=>{logger.logger.error(c),logger.logger.error(c.error);const y=new Error("Rethrown");y.cause=c.error,y.betterMessage=c.message,o(y)},(l=p(this,P))==null||l.addEventListener("error",e);const a=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return a instanceof Promise?a.then(n,o):n(a)})}catch(n){for(const c in this)typeof this[c]=="function"&&(this[c]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=getFunctionsMaybeMissingFromAsyncify();const o=n,a="betterMessage"in o?o.betterMessage:o.message,l=new Error(a);throw l.cause=o,logger.logger.error(l),l}finally{(i=p(this,P))==null||i.removeEventListener("error",e)}const{headers:r,httpStatusCode:s}=d(this,C,Z).call(this);return new PHPResponse(t===0?s:500,r,this.readFileAsBuffer("/internal/stdout"),this.readFileAsText("/internal/stderr"),t)};function normalizeHeaders(t){const e={};for(const r in t)e[r.toLowerCase()]=t[r];return e}function copyFS(t,e,r){let s;try{s=t.lookupPath(r)}catch{return}if(!("contents"in s.node))return;if(!t.isDir(s.node.mode)){e.writeFile(r,t.readFile(r));return}e.mkdirTree(r);const i=t.readdir(r).filter(n=>n!=="."&&n!=="..");for(const n of i)copyFS(t,e,util.joinPaths(r,n))}async function getPhpIniEntries(t,e){const r=ini.parse(await t.readFileAsText(PHP_INI_PATH));if(e===void 0)return r;const s={};for(const i of e)s[i]=r[i];return s}async function setPhpIniEntries(t,e){const r=ini.parse(await t.readFileAsText(PHP_INI_PATH));for(const[s,i]of Object.entries(e))i==null?delete r[s]:r[s]=i;await t.writeFile(PHP_INI_PATH,ini.stringify(r))}async function withPHPIniValues(t,e,r){const s=await t.readFileAsText(PHP_INI_PATH);try{return await setPhpIniEntries(t,e),await r()}finally{await t.writeFile(PHP_INI_PATH,s)}}class HttpCookieStore{constructor(){this.cookies={}}rememberCookiesFromResponseHeaders(e){if(e!=null&&e["set-cookie"])for(const r of e["set-cookie"])try{if(!r.includes("="))continue;const s=r.indexOf("="),i=r.substring(0,s),n=r.substring(s+1).split(";")[0];this.cookies[i]=n}catch(s){logger.logger.error(s)}}getCookieRequestHeader(){const e=[];for(const r in this.cookies)e.push(`${r}=${this.cookies[r]}`);return e.join("; ")}}function streamReadFileFromPHP(t,e){return new ReadableStream({async pull(r){const s=await t.readFileAsBuffer(e);r.enqueue(s),r.close()}})}async function*iteratePhpFiles(t,e,{relativePaths:r=!0,pathPrefix:s,exceptPaths:i=[]}={}){e=util.normalizePath(e);const n=[e];for(;n.length;){const o=n.pop();if(!o)return;const a=await t.listFiles(o);for(const l of a){const c=`${o}/${l}`;if(i.includes(c.substring(e.length+1)))continue;await t.isDir(c)?n.push(c):yield new streamCompression.StreamedFile(streamReadFileFromPHP(t,c),r?util.joinPaths(s||"",c.substring(e.length+1)):c)}}}function writeFilesStreamToPhp(t,e){return new WritableStream({async write(r){const s=util.joinPaths(e,r.name);r.type==="directory"?await t.mkdir(s):(await t.mkdir(util.dirname(s)),await t.writeFile(s,new Uint8Array(await r.arrayBuffer())))}})}class MaxPhpInstancesError extends Error{constructor(e){super(`Requested more concurrent PHP instances than the limit (${e}).`),this.name=this.constructor.name}}class PHPProcessManager{constructor(e){this.primaryIdle=!0,this.nextInstance=null,this.allInstances=[],this.maxPhpInstances=(e==null?void 0:e.maxPhpInstances)??5,this.phpFactory=e==null?void 0:e.phpFactory,this.primaryPhp=e==null?void 0:e.primaryPhp,this.semaphore=new util.Semaphore({concurrency:this.maxPhpInstances,timeout:(e==null?void 0:e.timeout)||5e3})}async getPrimaryPhp(){if(!this.phpFactory&&!this.primaryPhp)throw new Error("phpFactory or primaryPhp must be set before calling getPrimaryPhp().");if(!this.primaryPhp){const e=await this.spawn({isPrimary:!0});this.primaryPhp=e.php}return this.primaryPhp}async acquirePHPInstance(){if(this.primaryIdle)return this.primaryIdle=!1,{php:await this.getPrimaryPhp(),reap:()=>this.primaryIdle=!0};const e=this.nextInstance||this.spawn({isPrimary:!1});return this.semaphore.remaining>0?this.nextInstance=this.spawn({isPrimary:!1}):this.nextInstance=null,await e}spawn(e){if(e.isPrimary&&this.allInstances.length>0)throw new Error("Requested spawning a primary PHP instance when another primary instance already started spawning.");const r=this.doSpawn(e);this.allInstances.push(r);const s=()=>{this.allInstances=this.allInstances.filter(i=>i!==r)};return r.catch(i=>{throw s(),i}).then(i=>({...i,reap:()=>{s(),i.reap()}}))}async doSpawn(e){let r;try{r=await this.semaphore.acquire()}catch(s){throw s instanceof util.AcquireTimeoutError?new MaxPhpInstancesError(this.maxPhpInstances):s}try{const s=await this.phpFactory(e);return{php:s,reap(){s.exit(),r()}}}catch(s){throw r(),s}}async[Symbol.asyncDispose](){this.primaryPhp&&this.primaryPhp.exit(),await Promise.all(this.allInstances.map(e=>e.then(({reap:r})=>r())))}}const SupportedPHPVersions=["8.3","8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0"],LatestSupportedPHPVersion=SupportedPHPVersions[0],SupportedPHPVersionsList=SupportedPHPVersions,SupportedPHPExtensionsList=["iconv","mbstring","xml-bundle","gd"],SupportedPHPExtensionBundles={"kitchen-sink":SupportedPHPExtensionsList,light:[]},DEFAULT_BASE_URL="http://example.com";function toRelativeUrl(t){return t.toString().substring(t.origin.length)}function removePathPrefix(t,e){return!e||!t.startsWith(e)?t:t.substring(e.length)}function ensurePathPrefix(t,e){return!e||t.startsWith(e)?t:e+t}async function encodeAsMultipart(t){const e=`----${Math.random().toString(36).slice(2)}`,r=`multipart/form-data; boundary=${e}`,s=new TextEncoder,i=[];for(const[l,c]of Object.entries(t))i.push(`--${e}\r
51
51
  `),i.push(`Content-Disposition: form-data; name="${l}"`),c instanceof File&&i.push(`; filename="${c.name}"`),i.push(`\r
52
52
  `),c instanceof File&&(i.push("Content-Type: application/octet-stream"),i.push(`\r
53
53
  `)),i.push(`\r
54
54
  `),c instanceof File?i.push(await fileToUint8Array(c)):i.push(c),i.push(`\r
55
55
  `);i.push(`--${e}--\r
56
- `);const n=i.reduce((l,c)=>l+c.length,0),o=new Uint8Array(n);let a=0;for(const l of i)o.set(typeof l=="string"?s.encode(l):l,a),a+=l.length;return{bytes:o,contentType:r}}function fileToUint8Array(t){return new Promise(e=>{const r=new FileReader;r.onload=()=>{e(new Uint8Array(r.result))},r.readAsArrayBuffer(t)})}const _default="application/octet-stream",asx="video/x-ms-asf",atom="application/atom+xml",avi="video/x-msvideo",avif="image/avif",bin="application/octet-stream",bmp="image/x-ms-bmp",cco="application/x-cocoa",css="text/css",data="application/octet-stream",deb="application/octet-stream",der="application/x-x509-ca-cert",dmg="application/octet-stream",doc="application/msword",docx="application/vnd.openxmlformats-officedocument.wordprocessingml.document",eot="application/vnd.ms-fontobject",flv="video/x-flv",gif="image/gif",gz="application/gzip",hqx="application/mac-binhex40",htc="text/x-component",html="text/html",ico="image/x-icon",iso="application/octet-stream",jad="text/vnd.sun.j2me.app-descriptor",jar="application/java-archive",jardiff="application/x-java-archive-diff",jng="image/x-jng",jnlp="application/x-java-jnlp-file",jpg="image/jpeg",jpeg="image/jpeg",js="application/javascript",json="application/json",kml="application/vnd.google-earth.kml+xml",kmz="application/vnd.google-earth.kmz",m3u8="application/vnd.apple.mpegurl",m4a="audio/x-m4a",m4v="video/x-m4v",md="text/plain",mid="audio/midi",mml="text/mathml",mng="video/x-mng",mov="video/quicktime",mp3="audio/mpeg",mp4="video/mp4",mpeg="video/mpeg",msi="application/octet-stream",odg="application/vnd.oasis.opendocument.graphics",odp="application/vnd.oasis.opendocument.presentation",ods="application/vnd.oasis.opendocument.spreadsheet",odt="application/vnd.oasis.opendocument.text",ogg="audio/ogg",otf="font/otf",pdf="application/pdf",pl="application/x-perl",png="image/png",ppt="application/vnd.ms-powerpoint",pptx="application/vnd.openxmlformats-officedocument.presentationml.presentation",prc="application/x-pilot",ps="application/postscript",ra="audio/x-realaudio",rar="application/x-rar-compressed",rpm="application/x-redhat-package-manager",rss="application/rss+xml",rtf="application/rtf",run="application/x-makeself",sea="application/x-sea",sit="application/x-stuffit",svg="image/svg+xml",swf="application/x-shockwave-flash",tcl="application/x-tcl",tar="application/x-tar",tif="image/tiff",ts="video/mp2t",ttf="font/ttf",txt="text/plain",wasm="application/wasm",wbmp="image/vnd.wap.wbmp",webm="video/webm",webp="image/webp",wml="text/vnd.wap.wml",wmlc="application/vnd.wap.wmlc",wmv="video/x-ms-wmv",woff="font/woff",woff2="font/woff2",xhtml="application/xhtml+xml",xls="application/vnd.ms-excel",xlsx="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",xml="text/xml",xpi="application/x-xpinstall",xspf="application/xspf+xml",zip="application/zip",mimeTypes={_default,"3gpp":"video/3gpp","7z":"application/x-7z-compressed",asx,atom,avi,avif,bin,bmp,cco,css,data,deb,der,dmg,doc,docx,eot,flv,gif,gz,hqx,htc,html,ico,iso,jad,jar,jardiff,jng,jnlp,jpg,jpeg,js,json,kml,kmz,m3u8,m4a,m4v,md,mid,mml,mng,mov,mp3,mp4,mpeg,msi,odg,odp,ods,odt,ogg,otf,pdf,pl,png,ppt,pptx,prc,ps,ra,rar,rpm,rss,rtf,run,sea,sit,svg,swf,tcl,tar,tif,ts,ttf,txt,wasm,wbmp,webm,webp,wml,wmlc,wmv,woff,woff2,xhtml,xls,xlsx,xml,xpi,xspf,zip};var w,R,T,v,S,f,F,H,D,ae,z,le,W,ce;class PHPRequestHandler{constructor(e){u(this,D);u(this,z);u(this,W);u(this,w,void 0);u(this,R,void 0);u(this,T,void 0);u(this,v,void 0);u(this,S,void 0);u(this,f,void 0);u(this,F,void 0);u(this,H,void 0);const{documentRoot:r="/www/",absoluteUrl:s=typeof location=="object"?location==null?void 0:location.href:"",rewriteRules:i=[],getFileNotFoundAction:n=()=>({type:"404"})}=e;"processManager"in e?this.processManager=e.processManager:this.processManager=new PHPProcessManager({phpFactory:async l=>{const c=await e.phpFactory({...l,requestHandler:this});return c.requestHandler=this,c},maxPhpInstances:e.maxPhpInstances}),h(this,H,new HttpCookieStore),h(this,w,r);const o=new URL(s);h(this,T,o.hostname),h(this,v,o.port?Number(o.port):o.protocol==="https:"?443:80),h(this,R,(o.protocol||"").replace(":",""));const a=p(this,v)!==443&&p(this,v)!==80;h(this,S,[p(this,T),a?`:${p(this,v)}`:""].join("")),h(this,f,o.pathname.replace(/\/+$/,"")),h(this,F,[`${p(this,R)}://`,p(this,S),p(this,f)].join("")),this.rewriteRules=i,this.getFileNotFoundAction=n}async getPrimaryPhp(){return await this.processManager.getPrimaryPhp()}pathToInternalUrl(e){return`${this.absoluteUrl}${e}`}internalUrlToPath(e){const r=new URL(e);return r.pathname.startsWith(p(this,f))&&(r.pathname=r.pathname.slice(p(this,f).length)),toRelativeUrl(r)}get absoluteUrl(){return p(this,F)}get documentRoot(){return p(this,w)}async request(e){const r=e.url.startsWith("http://")||e.url.startsWith("https://"),s=new URL(e.url.split("#")[0],r?void 0:DEFAULT_BASE_URL),i=applyRewriteRules(removePathPrefix(decodeURIComponent(s.pathname),p(this,f)),this.rewriteRules),n=await this.getPrimaryPhp();let o=util.joinPaths(p(this,w),i);if(n.isDir(o)){if(!o.endsWith("/"))return new PHPResponse(301,{Location:[`${s.pathname}/`]},new Uint8Array(0));for(const a of["index.php","index.html"]){const l=util.joinPaths(o,a);if(n.isFile(l)){o=l;break}}}if(!n.isFile(o)){const a=this.getFileNotFoundAction(i);switch(a.type){case"response":return a.response;case"internal-redirect":o=util.joinPaths(p(this,w),a.uri);break;case"404":return PHPResponse.forHttpCode(404);default:throw new Error(`Unsupported file-not-found action type: '${a.type}'`)}}if(n.isFile(o))if(o.endsWith(".php")){const a={...e,url:s.toString()};return d(this,z,le).call(this,a,o)}else return d(this,D,ae).call(this,n,o);else return PHPResponse.forHttpCode(404)}}w=new WeakMap,R=new WeakMap,T=new WeakMap,v=new WeakMap,S=new WeakMap,f=new WeakMap,F=new WeakMap,H=new WeakMap,D=new WeakSet,ae=function(e,r){const s=e.readFileAsBuffer(r);return new PHPResponse(200,{"content-length":[`${s.byteLength}`],"content-type":[inferMimeType(r)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},s)},z=new WeakSet,le=async function(e,r){let s;try{s=await this.processManager.acquirePHPInstance()}catch(i){return i instanceof MaxPhpInstancesError?PHPResponse.forHttpCode(502):PHPResponse.forHttpCode(500)}try{return await d(this,W,ce).call(this,s.php,e,r)}finally{s.reap()}},W=new WeakSet,ce=async function(e,r,s){let i="GET";const n={host:p(this,S),...normalizeHeaders(r.headers||{}),cookie:p(this,H).getCookieRequestHeader()};let o=r.body;if(typeof o=="object"&&!(o instanceof Uint8Array)){i="POST";const{bytes:a,contentType:l}=await encodeAsMultipart(o);o=a,n["content-type"]=l}try{const a=await e.run({relativeUri:ensurePathPrefix(toRelativeUrl(new URL(r.url)),p(this,f)),protocol:p(this,R),method:r.method||i,$_SERVER:{REMOTE_ADDR:"127.0.0.1",DOCUMENT_ROOT:p(this,w),HTTPS:p(this,F).startsWith("https://")?"on":""},body:o,scriptPath:s,headers:n});return p(this,H).rememberCookiesFromResponseHeaders(a.headers),a}catch(a){const l=a;if(l!=null&&l.response)return l.response;throw a}};function inferMimeType(t){const e=t.split(".").pop();return mimeTypes[e]||mimeTypes._default}function applyRewriteRules(t,e){for(const r of e)if(new RegExp(r.match).test(t))return t.replace(r.match,r.replacement);return t}function rotatePHPRuntime({php:t,cwd:e,recreateRuntime:r,maxRequests:s=400}){let i=0;async function n(){const l=await t.semaphore.acquire();try{t.hotSwapPHPRuntime(await r(),e),i=0}finally{l()}}async function o(){++i<s||await n()}async function a(l){l.type==="request.error"&&l.source==="php-wasm"&&await n()}return t.addEventListener("request.error",a),t.addEventListener("request.end",o),function(){t.removeEventListener("request.error",a),t.removeEventListener("request.end",o)}}async function writeFiles(t,e,r,{rmRoot:s=!1}={}){s&&await t.isDir(e)&&await t.rmdir(e,{recursive:!0});for(const[i,n]of Object.entries(r)){const o=util.joinPaths(e,i);await t.fileExists(util.dirname(o))||await t.mkdir(util.dirname(o)),n instanceof Uint8Array||typeof n=="string"?await t.writeFile(o,n):await writeFiles(t,o,n)}}function proxyFileSystem(t,e,r){const s=Object.getOwnPropertySymbols(t)[0];for(const i of r)e.fileExists(i)||e.mkdir(i),t.fileExists(i)||t.mkdir(i),e[s].FS.mount(e[s].PROXYFS,{root:i,fs:t[s].FS},i)}exports.DEFAULT_BASE_URL=DEFAULT_BASE_URL;exports.FSHelpers=FSHelpers;exports.HttpCookieStore=HttpCookieStore;exports.LatestSupportedPHPVersion=LatestSupportedPHPVersion;exports.PHP=PHP;exports.PHPProcessManager=PHPProcessManager;exports.PHPRequestHandler=PHPRequestHandler;exports.PHPResponse=PHPResponse;exports.PHPWorker=PHPWorker;exports.SupportedPHPExtensionBundles=SupportedPHPExtensionBundles;exports.SupportedPHPExtensionsList=SupportedPHPExtensionsList;exports.SupportedPHPVersions=SupportedPHPVersions;exports.SupportedPHPVersionsList=SupportedPHPVersionsList;exports.UnhandledRejectionsTarget=UnhandledRejectionsTarget;exports.__private__dont__use=__private__dont__use;exports.applyRewriteRules=applyRewriteRules;exports.ensurePathPrefix=ensurePathPrefix;exports.getLoadedRuntime=getLoadedRuntime;exports.getPhpIniEntries=getPhpIniEntries;exports.isExitCodeZero=isExitCodeZero;exports.iterateFiles=iteratePhpFiles;exports.loadPHPRuntime=loadPHPRuntime;exports.proxyFileSystem=proxyFileSystem;exports.removePathPrefix=removePathPrefix;exports.rotatePHPRuntime=rotatePHPRuntime;exports.setPhpIniEntries=setPhpIniEntries;exports.toRelativeUrl=toRelativeUrl;exports.withPHPIniValues=withPHPIniValues;exports.writeFiles=writeFiles;exports.writeFilesStreamToPhp=writeFilesStreamToPhp;
56
+ `);const n=i.reduce((l,c)=>l+c.length,0),o=new Uint8Array(n);let a=0;for(const l of i)o.set(typeof l=="string"?s.encode(l):l,a),a+=l.length;return{bytes:o,contentType:r}}function fileToUint8Array(t){return new Promise(e=>{const r=new FileReader;r.onload=()=>{e(new Uint8Array(r.result))},r.readAsArrayBuffer(t)})}const _default="application/octet-stream",asx="video/x-ms-asf",atom="application/atom+xml",avi="video/x-msvideo",avif="image/avif",bin="application/octet-stream",bmp="image/x-ms-bmp",cco="application/x-cocoa",css="text/css",data="application/octet-stream",deb="application/octet-stream",der="application/x-x509-ca-cert",dmg="application/octet-stream",doc="application/msword",docx="application/vnd.openxmlformats-officedocument.wordprocessingml.document",eot="application/vnd.ms-fontobject",flv="video/x-flv",gif="image/gif",gz="application/gzip",hqx="application/mac-binhex40",htc="text/x-component",html="text/html",ico="image/x-icon",iso="application/octet-stream",jad="text/vnd.sun.j2me.app-descriptor",jar="application/java-archive",jardiff="application/x-java-archive-diff",jng="image/x-jng",jnlp="application/x-java-jnlp-file",jpg="image/jpeg",jpeg="image/jpeg",js="application/javascript",json="application/json",kml="application/vnd.google-earth.kml+xml",kmz="application/vnd.google-earth.kmz",m3u8="application/vnd.apple.mpegurl",m4a="audio/x-m4a",m4v="video/x-m4v",md="text/plain",mid="audio/midi",mml="text/mathml",mng="video/x-mng",mov="video/quicktime",mp3="audio/mpeg",mp4="video/mp4",mpeg="video/mpeg",msi="application/octet-stream",odg="application/vnd.oasis.opendocument.graphics",odp="application/vnd.oasis.opendocument.presentation",ods="application/vnd.oasis.opendocument.spreadsheet",odt="application/vnd.oasis.opendocument.text",ogg="audio/ogg",otf="font/otf",pdf="application/pdf",pl="application/x-perl",png="image/png",ppt="application/vnd.ms-powerpoint",pptx="application/vnd.openxmlformats-officedocument.presentationml.presentation",prc="application/x-pilot",ps="application/postscript",ra="audio/x-realaudio",rar="application/x-rar-compressed",rpm="application/x-redhat-package-manager",rss="application/rss+xml",rtf="application/rtf",run="application/x-makeself",sea="application/x-sea",sit="application/x-stuffit",svg="image/svg+xml",swf="application/x-shockwave-flash",tcl="application/x-tcl",tar="application/x-tar",tif="image/tiff",ts="video/mp2t",ttf="font/ttf",txt="text/plain",wasm="application/wasm",wbmp="image/vnd.wap.wbmp",webm="video/webm",webp="image/webp",wml="text/vnd.wap.wml",wmlc="application/vnd.wap.wmlc",wmv="video/x-ms-wmv",woff="font/woff",woff2="font/woff2",xhtml="application/xhtml+xml",xls="application/vnd.ms-excel",xlsx="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",xml="text/xml",xpi="application/x-xpinstall",xspf="application/xspf+xml",zip="application/zip",mimeTypes={_default,"3gpp":"video/3gpp","7z":"application/x-7z-compressed",asx,atom,avi,avif,bin,bmp,cco,css,data,deb,der,dmg,doc,docx,eot,flv,gif,gz,hqx,htc,html,ico,iso,jad,jar,jardiff,jng,jnlp,jpg,jpeg,js,json,kml,kmz,m3u8,m4a,m4v,md,mid,mml,mng,mov,mp3,mp4,mpeg,msi,odg,odp,ods,odt,ogg,otf,pdf,pl,png,ppt,pptx,prc,ps,ra,rar,rpm,rss,rtf,run,sea,sit,svg,swf,tcl,tar,tif,ts,ttf,txt,wasm,wbmp,webm,webp,wml,wmlc,wmv,woff,woff2,xhtml,xls,xlsx,xml,xpi,xspf,zip};var w,R,k,v,S,f,F,H,D,ae,z,le,W,ce;class PHPRequestHandler{constructor(e){u(this,D);u(this,z);u(this,W);u(this,w,void 0);u(this,R,void 0);u(this,k,void 0);u(this,v,void 0);u(this,S,void 0);u(this,f,void 0);u(this,F,void 0);u(this,H,void 0);const{documentRoot:r="/www/",absoluteUrl:s=typeof location=="object"?location==null?void 0:location.href:"",rewriteRules:i=[],getFileNotFoundAction:n=()=>({type:"404"})}=e;"processManager"in e?this.processManager=e.processManager:this.processManager=new PHPProcessManager({phpFactory:async l=>{const c=await e.phpFactory({...l,requestHandler:this});return c.requestHandler=this,c},maxPhpInstances:e.maxPhpInstances}),h(this,H,new HttpCookieStore),h(this,w,r);const o=new URL(s);h(this,k,o.hostname),h(this,v,o.port?Number(o.port):o.protocol==="https:"?443:80),h(this,R,(o.protocol||"").replace(":",""));const a=p(this,v)!==443&&p(this,v)!==80;h(this,S,[p(this,k),a?`:${p(this,v)}`:""].join("")),h(this,f,o.pathname.replace(/\/+$/,"")),h(this,F,[`${p(this,R)}://`,p(this,S),p(this,f)].join("")),this.rewriteRules=i,this.getFileNotFoundAction=n}async getPrimaryPhp(){return await this.processManager.getPrimaryPhp()}pathToInternalUrl(e){return`${this.absoluteUrl}${e}`}internalUrlToPath(e){const r=new URL(e);return r.pathname.startsWith(p(this,f))&&(r.pathname=r.pathname.slice(p(this,f).length)),toRelativeUrl(r)}get absoluteUrl(){return p(this,F)}get documentRoot(){return p(this,w)}async request(e){const r=e.url.startsWith("http://")||e.url.startsWith("https://"),s=new URL(e.url.split("#")[0],r?void 0:DEFAULT_BASE_URL),i=applyRewriteRules(removePathPrefix(decodeURIComponent(s.pathname),p(this,f)),this.rewriteRules),n=await this.getPrimaryPhp();let o=util.joinPaths(p(this,w),i);if(n.isDir(o)){if(!o.endsWith("/"))return new PHPResponse(301,{Location:[`${s.pathname}/`]},new Uint8Array(0));for(const a of["index.php","index.html"]){const l=util.joinPaths(o,a);if(n.isFile(l)){o=l;break}}}if(!n.isFile(o)){const a=this.getFileNotFoundAction(i);switch(a.type){case"response":return a.response;case"internal-redirect":o=util.joinPaths(p(this,w),a.uri);break;case"404":return PHPResponse.forHttpCode(404);default:throw new Error(`Unsupported file-not-found action type: '${a.type}'`)}}if(n.isFile(o))if(o.endsWith(".php")){const a={...e,url:s.toString()};return d(this,z,le).call(this,a,o)}else return d(this,D,ae).call(this,n,o);else return PHPResponse.forHttpCode(404)}}w=new WeakMap,R=new WeakMap,k=new WeakMap,v=new WeakMap,S=new WeakMap,f=new WeakMap,F=new WeakMap,H=new WeakMap,D=new WeakSet,ae=function(e,r){const s=e.readFileAsBuffer(r);return new PHPResponse(200,{"content-length":[`${s.byteLength}`],"content-type":[inferMimeType(r)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},s)},z=new WeakSet,le=async function(e,r){let s;try{s=await this.processManager.acquirePHPInstance()}catch(i){return i instanceof MaxPhpInstancesError?PHPResponse.forHttpCode(502):PHPResponse.forHttpCode(500)}try{return await d(this,W,ce).call(this,s.php,e,r)}finally{s.reap()}},W=new WeakSet,ce=async function(e,r,s){let i="GET";const n={host:p(this,S),...normalizeHeaders(r.headers||{}),cookie:p(this,H).getCookieRequestHeader()};let o=r.body;if(typeof o=="object"&&!(o instanceof Uint8Array)){i="POST";const{bytes:a,contentType:l}=await encodeAsMultipart(o);o=a,n["content-type"]=l}try{const a=await e.run({relativeUri:ensurePathPrefix(toRelativeUrl(new URL(r.url)),p(this,f)),protocol:p(this,R),method:r.method||i,$_SERVER:{REMOTE_ADDR:"127.0.0.1",DOCUMENT_ROOT:p(this,w),HTTPS:p(this,F).startsWith("https://")?"on":""},body:o,scriptPath:s,headers:n});return p(this,H).rememberCookiesFromResponseHeaders(a.headers),a}catch(a){const l=a;if(l!=null&&l.response)return l.response;throw a}};function inferMimeType(t){const e=t.split(".").pop();return mimeTypes[e]||mimeTypes._default}function applyRewriteRules(t,e){for(const r of e)if(new RegExp(r.match).test(t))return t.replace(r.match,r.replacement);return t}function rotatePHPRuntime({php:t,cwd:e,recreateRuntime:r,maxRequests:s=400}){let i=0;async function n(){const l=await t.semaphore.acquire();try{t.hotSwapPHPRuntime(await r(),e),i=0}finally{l()}}async function o(){++i<s||await n()}async function a(l){l.type==="request.error"&&l.source==="php-wasm"&&await n()}return t.addEventListener("request.error",a),t.addEventListener("request.end",o),function(){t.removeEventListener("request.error",a),t.removeEventListener("request.end",o)}}async function writeFiles(t,e,r,{rmRoot:s=!1}={}){s&&await t.isDir(e)&&await t.rmdir(e,{recursive:!0});for(const[i,n]of Object.entries(r)){const o=util.joinPaths(e,i);await t.fileExists(util.dirname(o))||await t.mkdir(util.dirname(o)),n instanceof Uint8Array||typeof n=="string"?await t.writeFile(o,n):await writeFiles(t,o,n)}}function proxyFileSystem(t,e,r){const s=Object.getOwnPropertySymbols(t)[0];for(const i of r)e.fileExists(i)||e.mkdir(i),t.fileExists(i)||t.mkdir(i),e[s].FS.mount(e[s].PROXYFS,{root:i,fs:t[s].FS},i)}exports.DEFAULT_BASE_URL=DEFAULT_BASE_URL;exports.FSHelpers=FSHelpers;exports.HttpCookieStore=HttpCookieStore;exports.LatestSupportedPHPVersion=LatestSupportedPHPVersion;exports.PHP=PHP;exports.PHPProcessManager=PHPProcessManager;exports.PHPRequestHandler=PHPRequestHandler;exports.PHPResponse=PHPResponse;exports.PHPWorker=PHPWorker;exports.SupportedPHPExtensionBundles=SupportedPHPExtensionBundles;exports.SupportedPHPExtensionsList=SupportedPHPExtensionsList;exports.SupportedPHPVersions=SupportedPHPVersions;exports.SupportedPHPVersionsList=SupportedPHPVersionsList;exports.UnhandledRejectionsTarget=UnhandledRejectionsTarget;exports.__private__dont__use=__private__dont__use;exports.applyRewriteRules=applyRewriteRules;exports.ensurePathPrefix=ensurePathPrefix;exports.getLoadedRuntime=getLoadedRuntime;exports.getPhpIniEntries=getPhpIniEntries;exports.isExitCodeZero=isExitCodeZero;exports.iterateFiles=iteratePhpFiles;exports.loadPHPRuntime=loadPHPRuntime;exports.proxyFileSystem=proxyFileSystem;exports.removePathPrefix=removePathPrefix;exports.rotatePHPRuntime=rotatePHPRuntime;exports.setPhpIniEntries=setPhpIniEntries;exports.toRelativeUrl=toRelativeUrl;exports.withPHPIniValues=withPHPIniValues;exports.writeFiles=writeFiles;exports.writeFilesStreamToPhp=writeFilesStreamToPhp;
package/index.js CHANGED
@@ -106,7 +106,7 @@ function rethrowFileSystemError(t = "") {
106
106
  } catch (a) {
107
107
  const l = typeof a == "object" ? a == null ? void 0 : a.errno : null;
108
108
  if (l in FileErrorCodes) {
109
- const c = FileErrorCodes[l], y = typeof o[1] == "string" ? o[1] : null, pe = y !== null ? t.replaceAll("{path}", y) : t;
109
+ const c = FileErrorCodes[l], P = typeof o[1] == "string" ? o[1] : null, pe = P !== null ? t.replaceAll("{path}", P) : t;
110
110
  throw new Error(`${pe}: ${c}`, {
111
111
  cause: a
112
112
  });
@@ -138,8 +138,9 @@ const _FSHelpers = class m {
138
138
  * Moves a file or directory in the PHP filesystem to a
139
139
  * new location.
140
140
  *
141
- * @param oldPath The path to rename.
142
- * @param newPath The new path.
141
+ * @param FS
142
+ * @param fromPath The path to rename.
143
+ * @param toPath The new path.
143
144
  */
144
145
  static mv(e, r, s) {
145
146
  try {
@@ -178,16 +179,43 @@ const _FSHelpers = class m {
178
179
  }
179
180
  }
180
181
  static isDir(e, r) {
181
- return m.fileExists(e, r) ? e.isDir(e.lookupPath(r).node.mode) : !1;
182
+ return m.fileExists(e, r) ? e.isDir(e.lookupPath(r, { follow: !0 }).node.mode) : !1;
183
+ }
184
+ static isFile(e, r) {
185
+ return m.fileExists(e, r) ? e.isFile(e.lookupPath(r, { follow: !0 }).node.mode) : !1;
182
186
  }
183
187
  /**
184
- * Checks if a file exists in the PHP filesystem.
188
+ * Creates a symlink in the PHP filesystem.
185
189
  *
186
- * @param path – The path to check.
187
- * @returns True if the path is a file, false otherwise.
190
+ * @param FS
191
+ * @param target
192
+ * @param link
188
193
  */
189
- static isFile(e, r) {
190
- return m.fileExists(e, r) ? e.isFile(e.lookupPath(r).node.mode) : !1;
194
+ static symlink(e, r, s) {
195
+ return e.symlink(r, s);
196
+ }
197
+ /**
198
+ * Checks if a path is a symlink in the PHP filesystem.
199
+ *
200
+ * @param FS
201
+ * @param path
202
+ * @returns True if the path is a symlink, false otherwise.
203
+ */
204
+ static isSymlink(e, r) {
205
+ return m.fileExists(e, r) ? e.isLink(e.lookupPath(r).node.mode) : !1;
206
+ }
207
+ /**
208
+ * Reads the target of a symlink in the PHP filesystem.
209
+ * @param FS
210
+ * @param path
211
+ * @returns The target of the symlink.
212
+ * @throws {@link @php-wasm/universal:ErrnoError} – If the path is not a symlink.
213
+ */
214
+ static readlink(e, r) {
215
+ return e.readlink(r);
216
+ }
217
+ static realpath(e, r) {
218
+ return e.lookupPath(r, { follow: !0 }).path;
191
219
  }
192
220
  static fileExists(e, r) {
193
221
  try {
@@ -237,6 +265,12 @@ __decorateClass([
237
265
  __decorateClass([
238
266
  rethrowFileSystemError('Could not stat "{path}"')
239
267
  ], _FSHelpers, "isDir", 1);
268
+ __decorateClass([
269
+ rethrowFileSystemError('Could not stat "{path}"')
270
+ ], _FSHelpers, "isFile", 1);
271
+ __decorateClass([
272
+ rethrowFileSystemError('Could not stat "{path}"')
273
+ ], _FSHelpers, "realpath", 1);
240
274
  __decorateClass([
241
275
  rethrowFileSystemError('Could not stat "{path}"')
242
276
  ], _FSHelpers, "fileExists", 1);
@@ -625,7 +659,7 @@ class PHPExecutionFailureError extends Error {
625
659
  }
626
660
  }
627
661
  const PHP_INI_PATH = "/internal/shared/php.ini", AUTO_PREPEND_SCRIPT = "/internal/shared/auto_prepend_file.php";
628
- var x, g, w, f, E, k, J, I, Y, C, Z, A, K, N, X, M, Q, j, ee, U, te, L, re, q, se, H, V, $, ie, B, ne, O, oe;
662
+ var x, g, w, _, E, T, J, I, Y, C, Z, A, K, N, X, M, Q, j, ee, U, te, L, re, q, se, b, V, $, ie, B, ne, O, oe;
629
663
  class PHP {
630
664
  /**
631
665
  * Initializes a PHP runtime.
@@ -644,7 +678,7 @@ class PHP {
644
678
  * was provided.
645
679
  * @returns Computed $_SERVER entries.
646
680
  */
647
- u(this, k);
681
+ u(this, T);
648
682
  u(this, I);
649
683
  u(this, C);
650
684
  u(this, A);
@@ -654,16 +688,16 @@ class PHP {
654
688
  u(this, U);
655
689
  u(this, L);
656
690
  u(this, q);
657
- u(this, H);
691
+ u(this, b);
658
692
  u(this, $);
659
693
  u(this, B);
660
694
  u(this, O);
661
695
  u(this, x, void 0);
662
696
  u(this, g, void 0);
663
697
  u(this, w, void 0);
664
- u(this, f, void 0);
698
+ u(this, _, void 0);
665
699
  u(this, E, void 0);
666
- h(this, g, !1), h(this, w, null), h(this, f, /* @__PURE__ */ new Map()), h(this, E, []), this.semaphore = new Semaphore({ concurrency: 1 }), t !== void 0 && this.initializeRuntime(t);
700
+ h(this, g, !1), h(this, w, null), h(this, _, /* @__PURE__ */ new Map()), h(this, E, []), this.semaphore = new Semaphore({ concurrency: 1 }), t !== void 0 && this.initializeRuntime(t);
667
701
  }
668
702
  /**
669
703
  * Adds an event listener for a PHP event.
@@ -671,7 +705,7 @@ class PHP {
671
705
  * @param listener - The listener function to be called when the event is triggered.
672
706
  */
673
707
  addEventListener(t, e) {
674
- p(this, f).has(t) || p(this, f).set(t, /* @__PURE__ */ new Set()), p(this, f).get(t).add(e);
708
+ p(this, _).has(t) || p(this, _).set(t, /* @__PURE__ */ new Set()), p(this, _).get(t).add(e);
675
709
  }
676
710
  /**
677
711
  * Removes an event listener for a PHP event.
@@ -680,10 +714,10 @@ class PHP {
680
714
  */
681
715
  removeEventListener(t, e) {
682
716
  var r;
683
- (r = p(this, f).get(t)) == null || r.delete(e);
717
+ (r = p(this, _).get(t)) == null || r.delete(e);
684
718
  }
685
719
  dispatchEvent(t) {
686
- const e = p(this, f).get(t.type);
720
+ const e = p(this, _).get(t.type);
687
721
  if (e)
688
722
  for (const r of e)
689
723
  r(t);
@@ -927,14 +961,14 @@ class PHP {
927
961
  d(this, A, K).call(this, t.relativeUri || ""), d(this, U, te).call(this, t.method || "GET");
928
962
  const s = normalizeHeaders(t.headers || {}), i = s.host || "example.com:443", n = d(this, j, ee).call(this, i, t.protocol || "http");
929
963
  if (d(this, N, X).call(this, i), d(this, M, Q).call(this, n), d(this, L, re).call(this, s), t.body && (r = d(this, q, se).call(this, t.body)), typeof t.code == "string")
930
- this.writeFile("/internal/eval.php", t.code), d(this, H, V).call(this, "/internal/eval.php");
964
+ this.writeFile("/internal/eval.php", t.code), d(this, b, V).call(this, "/internal/eval.php");
931
965
  else if (typeof t.scriptPath == "string")
932
- d(this, H, V).call(this, t.scriptPath || "");
966
+ d(this, b, V).call(this, t.scriptPath || "");
933
967
  else
934
968
  throw new TypeError(
935
969
  "The request object must have either a `code` or a `scriptPath` property."
936
970
  );
937
- const o = d(this, k, J).call(this, t.$_SERVER, s, n);
971
+ const o = d(this, T, J).call(this, t.$_SERVER, s, n);
938
972
  for (const c in o)
939
973
  d(this, $, ie).call(this, c, o[c]);
940
974
  const a = t.env || {};
@@ -1095,6 +1129,40 @@ class PHP {
1095
1129
  isFile(t) {
1096
1130
  return FSHelpers.isFile(this[__private__dont__use].FS, t);
1097
1131
  }
1132
+ /**
1133
+ * Creates a symlink in the PHP filesystem.
1134
+ * @param target
1135
+ * @param path
1136
+ */
1137
+ symlink(t, e) {
1138
+ return FSHelpers.symlink(this[__private__dont__use].FS, t, e);
1139
+ }
1140
+ /**
1141
+ * Checks if a path is a symlink in the PHP filesystem.
1142
+ *
1143
+ * @param path
1144
+ * @returns True if the path is a symlink, false otherwise.
1145
+ */
1146
+ isSymlink(t) {
1147
+ return FSHelpers.isSymlink(this[__private__dont__use].FS, t);
1148
+ }
1149
+ /**
1150
+ * Reads the target of a symlink in the PHP filesystem.
1151
+ *
1152
+ * @param path
1153
+ * @returns The target of the symlink.
1154
+ */
1155
+ readlink(t) {
1156
+ return FSHelpers.readlink(this[__private__dont__use].FS, t);
1157
+ }
1158
+ /**
1159
+ * Resolves the real path of a file in the PHP filesystem.
1160
+ * @param path
1161
+ * @returns The real path of the file.
1162
+ */
1163
+ realpath(t) {
1164
+ return FSHelpers.realpath(this[__private__dont__use].FS, t);
1165
+ }
1098
1166
  /**
1099
1167
  * Checks if a file (or a directory) exists in the PHP filesystem.
1100
1168
  *
@@ -1195,7 +1263,7 @@ class PHP {
1195
1263
  p(this, g) && this.exit(0);
1196
1264
  }
1197
1265
  }
1198
- x = new WeakMap(), g = new WeakMap(), w = new WeakMap(), f = new WeakMap(), E = new WeakMap(), k = new WeakSet(), J = function(t, e, r) {
1266
+ x = new WeakMap(), g = new WeakMap(), w = new WeakMap(), _ = new WeakMap(), E = new WeakMap(), T = new WeakSet(), J = function(t, e, r) {
1199
1267
  const s = {
1200
1268
  ...t || {}
1201
1269
  };
@@ -1307,7 +1375,7 @@ x = new WeakMap(), g = new WeakMap(), w = new WeakMap(), f = new WeakMap(), E =
1307
1375
  [NUMBER],
1308
1376
  [r]
1309
1377
  ), s;
1310
- }, H = new WeakSet(), V = function(t) {
1378
+ }, b = new WeakSet(), V = function(t) {
1311
1379
  this[__private__dont__use].ccall(
1312
1380
  "wasm_set_path_translated",
1313
1381
  null,
@@ -1336,8 +1404,8 @@ x = new WeakMap(), g = new WeakMap(), w = new WeakMap(), f = new WeakMap(), E =
1336
1404
  var l;
1337
1405
  e = (c) => {
1338
1406
  logger.error(c), logger.error(c.error);
1339
- const y = new Error("Rethrown");
1340
- y.cause = c.error, y.betterMessage = c.message, o(y);
1407
+ const P = new Error("Rethrown");
1408
+ P.cause = c.error, P.betterMessage = c.message, o(P);
1341
1409
  }, (l = p(this, w)) == null || l.addEventListener(
1342
1410
  "error",
1343
1411
  e
@@ -1753,7 +1821,7 @@ const _default = "application/octet-stream", asx = "video/x-ms-asf", atom = "app
1753
1821
  xspf,
1754
1822
  zip
1755
1823
  };
1756
- var P, R, T, v, F, _, S, b, D, ae, z, le, W, ce;
1824
+ var y, R, k, v, F, f, S, H, D, ae, z, le, W, ce;
1757
1825
  class PHPRequestHandler {
1758
1826
  /**
1759
1827
  * The request handler needs to decide whether to serve a static asset or
@@ -1786,14 +1854,14 @@ class PHPRequestHandler {
1786
1854
  * @returns The response.
1787
1855
  */
1788
1856
  u(this, W);
1789
- u(this, P, void 0);
1857
+ u(this, y, void 0);
1790
1858
  u(this, R, void 0);
1791
- u(this, T, void 0);
1859
+ u(this, k, void 0);
1792
1860
  u(this, v, void 0);
1793
1861
  u(this, F, void 0);
1794
- u(this, _, void 0);
1862
+ u(this, f, void 0);
1795
1863
  u(this, S, void 0);
1796
- u(this, b, void 0);
1864
+ u(this, H, void 0);
1797
1865
  const {
1798
1866
  documentRoot: r = "/www/",
1799
1867
  absoluteUrl: s = typeof location == "object" ? location == null ? void 0 : location.href : "",
@@ -1809,17 +1877,17 @@ class PHPRequestHandler {
1809
1877
  return c.requestHandler = this, c;
1810
1878
  },
1811
1879
  maxPhpInstances: e.maxPhpInstances
1812
- }), h(this, b, new HttpCookieStore()), h(this, P, r);
1880
+ }), h(this, H, new HttpCookieStore()), h(this, y, r);
1813
1881
  const o = new URL(s);
1814
- h(this, T, o.hostname), h(this, v, o.port ? Number(o.port) : o.protocol === "https:" ? 443 : 80), h(this, R, (o.protocol || "").replace(":", ""));
1882
+ h(this, k, o.hostname), h(this, v, o.port ? Number(o.port) : o.protocol === "https:" ? 443 : 80), h(this, R, (o.protocol || "").replace(":", ""));
1815
1883
  const a = p(this, v) !== 443 && p(this, v) !== 80;
1816
1884
  h(this, F, [
1817
- p(this, T),
1885
+ p(this, k),
1818
1886
  a ? `:${p(this, v)}` : ""
1819
- ].join("")), h(this, _, o.pathname.replace(/\/+$/, "")), h(this, S, [
1887
+ ].join("")), h(this, f, o.pathname.replace(/\/+$/, "")), h(this, S, [
1820
1888
  `${p(this, R)}://`,
1821
1889
  p(this, F),
1822
- p(this, _)
1890
+ p(this, f)
1823
1891
  ].join("")), this.rewriteRules = i, this.getFileNotFoundAction = n;
1824
1892
  }
1825
1893
  async getPrimaryPhp() {
@@ -1844,7 +1912,7 @@ class PHPRequestHandler {
1844
1912
  */
1845
1913
  internalUrlToPath(e) {
1846
1914
  const r = new URL(e);
1847
- return r.pathname.startsWith(p(this, _)) && (r.pathname = r.pathname.slice(p(this, _).length)), toRelativeUrl(r);
1915
+ return r.pathname.startsWith(p(this, f)) && (r.pathname = r.pathname.slice(p(this, f).length)), toRelativeUrl(r);
1848
1916
  }
1849
1917
  /**
1850
1918
  * The absolute URL of this PHPRequestHandler instance.
@@ -1857,7 +1925,7 @@ class PHPRequestHandler {
1857
1925
  * for the files to serve. Default: `/var/www`.
1858
1926
  */
1859
1927
  get documentRoot() {
1860
- return p(this, P);
1928
+ return p(this, y);
1861
1929
  }
1862
1930
  /**
1863
1931
  * Serves the request – either by serving a static file, or by
@@ -1915,11 +1983,11 @@ class PHPRequestHandler {
1915
1983
  ), i = applyRewriteRules(
1916
1984
  removePathPrefix(
1917
1985
  decodeURIComponent(s.pathname),
1918
- p(this, _)
1986
+ p(this, f)
1919
1987
  ),
1920
1988
  this.rewriteRules
1921
1989
  ), n = await this.getPrimaryPhp();
1922
- let o = joinPaths(p(this, P), i);
1990
+ let o = joinPaths(p(this, y), i);
1923
1991
  if (n.isDir(o)) {
1924
1992
  if (!o.endsWith("/"))
1925
1993
  return new PHPResponse(
@@ -1943,7 +2011,7 @@ class PHPRequestHandler {
1943
2011
  case "response":
1944
2012
  return a.response;
1945
2013
  case "internal-redirect":
1946
- o = joinPaths(p(this, P), a.uri);
2014
+ o = joinPaths(p(this, y), a.uri);
1947
2015
  break;
1948
2016
  case "404":
1949
2017
  return PHPResponse.forHttpCode(404);
@@ -1967,7 +2035,7 @@ class PHPRequestHandler {
1967
2035
  return PHPResponse.forHttpCode(404);
1968
2036
  }
1969
2037
  }
1970
- P = new WeakMap(), R = new WeakMap(), T = new WeakMap(), v = new WeakMap(), F = new WeakMap(), _ = new WeakMap(), S = new WeakMap(), b = new WeakMap(), D = new WeakSet(), ae = function(e, r) {
2038
+ y = new WeakMap(), R = new WeakMap(), k = new WeakMap(), v = new WeakMap(), F = new WeakMap(), f = new WeakMap(), S = new WeakMap(), H = new WeakMap(), D = new WeakSet(), ae = function(e, r) {
1971
2039
  const s = e.readFileAsBuffer(r);
1972
2040
  return new PHPResponse(
1973
2041
  200,
@@ -1999,7 +2067,7 @@ P = new WeakMap(), R = new WeakMap(), T = new WeakMap(), v = new WeakMap(), F =
1999
2067
  const n = {
2000
2068
  host: p(this, F),
2001
2069
  ...normalizeHeaders(r.headers || {}),
2002
- cookie: p(this, b).getCookieRequestHeader()
2070
+ cookie: p(this, H).getCookieRequestHeader()
2003
2071
  };
2004
2072
  let o = r.body;
2005
2073
  if (typeof o == "object" && !(o instanceof Uint8Array)) {
@@ -2011,20 +2079,20 @@ P = new WeakMap(), R = new WeakMap(), T = new WeakMap(), v = new WeakMap(), F =
2011
2079
  const a = await e.run({
2012
2080
  relativeUri: ensurePathPrefix(
2013
2081
  toRelativeUrl(new URL(r.url)),
2014
- p(this, _)
2082
+ p(this, f)
2015
2083
  ),
2016
2084
  protocol: p(this, R),
2017
2085
  method: r.method || i,
2018
2086
  $_SERVER: {
2019
2087
  REMOTE_ADDR: "127.0.0.1",
2020
- DOCUMENT_ROOT: p(this, P),
2088
+ DOCUMENT_ROOT: p(this, y),
2021
2089
  HTTPS: p(this, S).startsWith("https://") ? "on" : ""
2022
2090
  },
2023
2091
  body: o,
2024
2092
  scriptPath: s,
2025
2093
  headers: n
2026
2094
  });
2027
- return p(this, b).rememberCookiesFromResponseHeaders(
2095
+ return p(this, H).rememberCookiesFromResponseHeaders(
2028
2096
  a.headers
2029
2097
  ), a;
2030
2098
  } catch (a) {
@@ -18,6 +18,7 @@ export declare class FSHelpers {
18
18
  * Reads a file from the PHP filesystem and returns it as a string.
19
19
  *
20
20
  * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist.
21
+ * @param FS
21
22
  * @param path - The file path to read.
22
23
  * @returns The file contents.
23
24
  */
@@ -26,6 +27,7 @@ export declare class FSHelpers {
26
27
  * Reads a file from the PHP filesystem and returns it as an array buffer.
27
28
  *
28
29
  * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist.
30
+ * @param FS
29
31
  * @param path - The file path to read.
30
32
  * @returns The file contents.
31
33
  */
@@ -34,6 +36,7 @@ export declare class FSHelpers {
34
36
  * Overwrites data in a file in the PHP filesystem.
35
37
  * Creates a new file if one doesn't exist yet.
36
38
  *
39
+ * @param FS
37
40
  * @param path - The file path to write to.
38
41
  * @param data - The data to write to the file.
39
42
  */
@@ -42,6 +45,7 @@ export declare class FSHelpers {
42
45
  * Removes a file from the PHP filesystem.
43
46
  *
44
47
  * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist.
48
+ * @param FS
45
49
  * @param path - The file path to remove.
46
50
  */
47
51
  static unlink(FS: Emscripten.RootFS, path: string): void;
@@ -49,13 +53,15 @@ export declare class FSHelpers {
49
53
  * Moves a file or directory in the PHP filesystem to a
50
54
  * new location.
51
55
  *
52
- * @param oldPath The path to rename.
53
- * @param newPath The new path.
56
+ * @param FS
57
+ * @param fromPath The path to rename.
58
+ * @param toPath The new path.
54
59
  */
55
60
  static mv(FS: Emscripten.RootFS, fromPath: string, toPath: string): void;
56
61
  /**
57
62
  * Removes a directory from the PHP filesystem.
58
63
  *
64
+ * @param FS
59
65
  * @param path The directory path to remove.
60
66
  * @param options Options for the removal.
61
67
  */
@@ -63,6 +69,7 @@ export declare class FSHelpers {
63
69
  /**
64
70
  * Lists the files and directories in the given directory.
65
71
  *
72
+ * @param FS
66
73
  * @param path - The directory path to list.
67
74
  * @param options - Options for the listing.
68
75
  * @returns The list of files and directories in the given directory.
@@ -71,6 +78,7 @@ export declare class FSHelpers {
71
78
  /**
72
79
  * Checks if a directory exists in the PHP filesystem.
73
80
  *
81
+ * @param FS
74
82
  * @param path – The path to check.
75
83
  * @returns True if the path is a directory, false otherwise.
76
84
  */
@@ -78,13 +86,47 @@ export declare class FSHelpers {
78
86
  /**
79
87
  * Checks if a file exists in the PHP filesystem.
80
88
  *
89
+ * @param FS
81
90
  * @param path – The path to check.
82
91
  * @returns True if the path is a file, false otherwise.
83
92
  */
84
93
  static isFile(FS: Emscripten.RootFS, path: string): boolean;
94
+ /**
95
+ * Creates a symlink in the PHP filesystem.
96
+ *
97
+ * @param FS
98
+ * @param target
99
+ * @param link
100
+ */
101
+ static symlink(FS: Emscripten.RootFS, target: string, link: string): any;
102
+ /**
103
+ * Checks if a path is a symlink in the PHP filesystem.
104
+ *
105
+ * @param FS
106
+ * @param path
107
+ * @returns True if the path is a symlink, false otherwise.
108
+ */
109
+ static isSymlink(FS: Emscripten.RootFS, path: string): boolean;
110
+ /**
111
+ * Reads the target of a symlink in the PHP filesystem.
112
+ * @param FS
113
+ * @param path
114
+ * @returns The target of the symlink.
115
+ * @throws {@link @php-wasm/universal:ErrnoError} – If the path is not a symlink.
116
+ */
117
+ static readlink(FS: Emscripten.RootFS, path: string): string;
118
+ /**
119
+ * Gets the real path of a file in the PHP filesystem.
120
+ * @param FS
121
+ * @param path
122
+ *
123
+ * @returns The real path of the file.
124
+ */
125
+ static realpath(FS: Emscripten.RootFS, path: string): string;
85
126
  /**
86
127
  * Checks if a file (or a directory) exists in the PHP filesystem.
87
128
  *
129
+ * @param FS
88
130
  * @param path - The file path to check.
89
131
  * @returns True if the file exists, false otherwise.
90
132
  */
@@ -94,6 +136,7 @@ export declare class FSHelpers {
94
136
  * For example, if the path is `/root/php/data`, and `/root` already exists,
95
137
  * it will create the directories `/root/php` and `/root/php/data`.
96
138
  *
139
+ * @param FS
97
140
  * @param path - The directory path to create.
98
141
  */
99
142
  static mkdir(FS: Emscripten.RootFS, path: string): void;
@@ -69,7 +69,7 @@ export type PHPRequestHandlerConfiguration = BaseConfiguration & ({
69
69
  * @public
70
70
  * @example Use PHPRequestHandler implicitly with a new PHP instance:
71
71
  * ```js
72
- * import { PHP } from '../../../web/src/index.ts';
72
+ * import { PHP } from '@php-wasm/web';
73
73
  *
74
74
  * const php = await PHP.load( '7.4', {
75
75
  * requestHandler: {
@@ -1,4 +1,4 @@
1
- import { EmscriptenDownloadMonitor } from '../../../progress/src/index.ts';
1
+ import { EmscriptenDownloadMonitor } from '@php-wasm/progress';
2
2
  import { PHP } from './php';
3
3
  import { PHPRequestHandler } from './php-request-handler';
4
4
  import { PHPResponse } from './php-response';
package/lib/php.d.ts CHANGED
@@ -2,7 +2,7 @@ import { PHPResponse } from './php-response';
2
2
  import type { PHPRuntimeId } from './load-php-runtime';
3
3
  import { MessageListener, PHPRequest, PHPRequestHeaders, PHPRunOptions, SpawnHandler, PHPEventListener, PHPEvent } from './universal-php';
4
4
  import { RmDirOptions, ListFilesOptions } from './fs-helpers';
5
- import { Semaphore } from '../../../util/src/index.ts';
5
+ import { Semaphore } from '@php-wasm/util';
6
6
  import { PHPRequestHandler } from './php-request-handler';
7
7
  import { Emscripten } from './emscripten-types';
8
8
  export declare const __private__dont__use: unique symbol;
@@ -274,6 +274,32 @@ export declare class PHP implements Disposable {
274
274
  * @returns True if the path is a file, false otherwise.
275
275
  */
276
276
  isFile(path: string): boolean;
277
+ /**
278
+ * Creates a symlink in the PHP filesystem.
279
+ * @param target
280
+ * @param path
281
+ */
282
+ symlink(target: string, path: string): any;
283
+ /**
284
+ * Checks if a path is a symlink in the PHP filesystem.
285
+ *
286
+ * @param path
287
+ * @returns True if the path is a symlink, false otherwise.
288
+ */
289
+ isSymlink(path: string): boolean;
290
+ /**
291
+ * Reads the target of a symlink in the PHP filesystem.
292
+ *
293
+ * @param path
294
+ * @returns The target of the symlink.
295
+ */
296
+ readlink(path: string): string;
297
+ /**
298
+ * Resolves the real path of a file in the PHP filesystem.
299
+ * @param path
300
+ * @returns The real path of the file.
301
+ */
302
+ realpath(path: string): string;
277
303
  /**
278
304
  * Checks if a file (or a directory) exists in the PHP filesystem.
279
305
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/universal",
3
- "version": "0.9.37",
3
+ "version": "0.9.39",
4
4
  "description": "PHP.wasm – emscripten bindings for PHP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,7 +37,7 @@
37
37
  "module": "./index.js",
38
38
  "types": "index.d.ts",
39
39
  "license": "GPL-2.0-or-later",
40
- "gitHead": "7bb24a2519a65bc8265b2c73f2f01dd67bf13204",
40
+ "gitHead": "cbb5ec6aeed54bebf0fd6503f207c93261b3e4ba",
41
41
  "engines": {
42
42
  "node": ">=18.18.0",
43
43
  "npm": ">=8.11.0"
@@ -45,10 +45,10 @@
45
45
  "dependencies": {
46
46
  "comlink": "^4.4.1",
47
47
  "ini": "4.1.2",
48
- "@php-wasm/node-polyfills": "0.9.37",
49
- "@php-wasm/logger": "0.9.37",
50
- "@php-wasm/util": "0.9.37",
51
- "@php-wasm/stream-compression": "0.9.37",
52
- "@php-wasm/progress": "0.9.37"
48
+ "@php-wasm/node-polyfills": "0.9.39",
49
+ "@php-wasm/logger": "0.9.39",
50
+ "@php-wasm/util": "0.9.39",
51
+ "@php-wasm/stream-compression": "0.9.39",
52
+ "@php-wasm/progress": "0.9.39"
53
53
  }
54
54
  }