@php-wasm/universal 0.9.37 → 0.9.38
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 +4 -4
- package/index.js +112 -44
- package/lib/fs-helpers.d.ts +45 -2
- package/lib/php.d.ts +26 -0
- package/package.json +7 -7
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,
|
|
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&©FS(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&©FS(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,
|
|
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],
|
|
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
|
|
142
|
-
* @param
|
|
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
|
-
*
|
|
188
|
+
* Creates a symlink in the PHP filesystem.
|
|
185
189
|
*
|
|
186
|
-
* @param
|
|
187
|
-
* @
|
|
190
|
+
* @param FS
|
|
191
|
+
* @param target
|
|
192
|
+
* @param link
|
|
188
193
|
*/
|
|
189
|
-
static
|
|
190
|
-
return
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
698
|
+
u(this, _, void 0);
|
|
665
699
|
u(this, E, void 0);
|
|
666
|
-
h(this, g, !1), h(this, w, null), h(this,
|
|
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,
|
|
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,
|
|
717
|
+
(r = p(this, _).get(t)) == null || r.delete(e);
|
|
684
718
|
}
|
|
685
719
|
dispatchEvent(t) {
|
|
686
|
-
const e = p(this,
|
|
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,
|
|
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,
|
|
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,
|
|
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(),
|
|
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
|
-
},
|
|
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
|
|
1340
|
-
|
|
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
|
|
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,
|
|
1857
|
+
u(this, y, void 0);
|
|
1790
1858
|
u(this, R, void 0);
|
|
1791
|
-
u(this,
|
|
1859
|
+
u(this, k, void 0);
|
|
1792
1860
|
u(this, v, void 0);
|
|
1793
1861
|
u(this, F, void 0);
|
|
1794
|
-
u(this,
|
|
1862
|
+
u(this, f, void 0);
|
|
1795
1863
|
u(this, S, void 0);
|
|
1796
|
-
u(this,
|
|
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,
|
|
1880
|
+
}), h(this, H, new HttpCookieStore()), h(this, y, r);
|
|
1813
1881
|
const o = new URL(s);
|
|
1814
|
-
h(this,
|
|
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,
|
|
1885
|
+
p(this, k),
|
|
1818
1886
|
a ? `:${p(this, v)}` : ""
|
|
1819
|
-
].join("")), h(this,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
2095
|
+
return p(this, H).rememberCookiesFromResponseHeaders(
|
|
2028
2096
|
a.headers
|
|
2029
2097
|
), a;
|
|
2030
2098
|
} catch (a) {
|
package/lib/fs-helpers.d.ts
CHANGED
|
@@ -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
|
|
53
|
-
* @param
|
|
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;
|
package/lib/php.d.ts
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "0.9.38",
|
|
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": "
|
|
40
|
+
"gitHead": "f07ef4e59813c2d43d71d639237457b029dea995",
|
|
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.
|
|
49
|
-
"@php-wasm/logger": "0.9.
|
|
50
|
-
"@php-wasm/util": "0.9.
|
|
51
|
-
"@php-wasm/stream-compression": "0.9.
|
|
52
|
-
"@php-wasm/progress": "0.9.
|
|
48
|
+
"@php-wasm/node-polyfills": "0.9.38",
|
|
49
|
+
"@php-wasm/logger": "0.9.38",
|
|
50
|
+
"@php-wasm/util": "0.9.38",
|
|
51
|
+
"@php-wasm/stream-compression": "0.9.38",
|
|
52
|
+
"@php-wasm/progress": "0.9.38"
|
|
53
53
|
}
|
|
54
54
|
}
|