@php-wasm/universal 0.6.7 → 0.6.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +4 -4
- package/index.js +162 -154
- package/lib/index.d.ts +2 -2
- package/lib/php-request-handler.d.ts +17 -0
- package/lib/universal-php.d.ts +9 -6
- package/package.json +2 -2
package/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var J=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var l=(e,t,r)=>(J(e,t,"read from private field"),r?r.call(e):t.get(e)),u=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r)},h=(e,t,r,s)=>(J(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var p=(e,t,r)=>(J(e,t,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const currentJsRuntime$1=function(){var e;return typeof process<"u"&&((e=process.release)==null?void 0:e.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}();if(currentJsRuntime$1==="NODE"){let e=function(r){return new Promise(function(s,n){r.onload=r.onerror=function(o){r.onload=r.onerror=null,o.type==="load"?s(r.result):n(new Error("Failed to read the blob/file"))}})},t=function(){const r=new Uint8Array([1,2,3,4]),n=new File([r],"test").stream();try{return n.getReader({mode:"byob"}),!0}catch{return!1}};if(typeof File>"u"){class r extends Blob{constructor(n,o,i){super(n);let a;i!=null&&i.lastModified&&(a=new Date),(!a||isNaN(a.getFullYear()))&&(a=new Date),this.lastModifiedDate=a,this.lastModified=a.getMilliseconds(),this.name=o||""}}global.File=r}typeof Blob.prototype.arrayBuffer>"u"&&(Blob.prototype.arrayBuffer=function(){const s=new FileReader;return s.readAsArrayBuffer(this),e(s)}),typeof Blob.prototype.text>"u"&&(Blob.prototype.text=function(){const s=new FileReader;return s.readAsText(this),e(s)}),(typeof Blob.prototype.stream>"u"||!t())&&(Blob.prototype.stream=function(){let r=0;const s=this;return new ReadableStream({type:"bytes",autoAllocateChunkSize:512*1024,async pull(n){const o=n.byobRequest.view,a=await s.slice(r,r+o.byteLength).arrayBuffer(),c=new Uint8Array(a);new Uint8Array(o.buffer).set(c);const d=c.byteLength;n.byobRequest.respond(d),r+=d,r>=s.size&&n.close()}})})}if(currentJsRuntime$1==="NODE"&&typeof CustomEvent>"u"){class e extends Event{constructor(r,s={}){super(r,s),this.detail=s.detail}initCustomEvent(){}}globalThis.CustomEvent=e}const kError=Symbol("error"),kMessage=Symbol("message");class ErrorEvent2 extends Event{constructor(t,r={}){super(t),this[kError]=r.error===void 0?null:r.error,this[kMessage]=r.message===void 0?"":r.message}get error(){return this[kError]}get message(){return this[kMessage]}}Object.defineProperty(ErrorEvent2.prototype,"error",{enumerable:!0});Object.defineProperty(ErrorEvent2.prototype,"message",{enumerable:!0});const ErrorEvent=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:ErrorEvent2;function isExitCodeZero(e){return e instanceof Error?"exitCode"in e&&(e==null?void 0:e.exitCode)===0||(e==null?void 0:e.name)==="ExitStatus"&&"status"in e&&e.status===0:!1}class UnhandledRejectionsTarget extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(t,r){++this.listenersCount,super.addEventListener(t,r)}removeEventListener(t,r){--this.listenersCount,super.removeEventListener(t,r)}hasListeners(){return this.listenersCount>0}}function improveWASMErrorReporting(e){e.asm={...e.asm};const t=new UnhandledRejectionsTarget;for(const r in e.asm)if(typeof e.asm[r]=="function"){const s=e.asm[r];e.asm[r]=function(...n){var o;try{return s(...n)}catch(i){if(!(i instanceof Error))throw i;const a=clarifyErrorMessage(i,(o=e.lastAsyncifyStackSource)==null?void 0:o.stack);if(e.lastAsyncifyStackSource&&(i.cause=e.lastAsyncifyStackSource),t.hasListeners()){t.dispatchEvent(new ErrorEvent("error",{error:i,message:a}));return}throw isExitCodeZero(i)||showCriticalErrorBox(a),i}}}return t}let functionsMaybeMissingFromAsyncify=[];function getFunctionsMaybeMissingFromAsyncify(){return functionsMaybeMissingFromAsyncify}function clarifyErrorMessage(e,t){if(e.message==="unreachable"){let r=UNREACHABLE_ERROR;t||(r+=`
|
|
2
2
|
|
|
3
3
|
This stack trace is lacking. For a better one initialize
|
|
4
4
|
the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
|
|
@@ -32,13 +32,13 @@ CLI option:
|
|
|
32
32
|
${eol}
|
|
33
33
|
${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
|
|
34
34
|
`))console.log(`${eol} ${t} `);console.log(`${reset}`)}}function extractPHPFunctionsFromStack(e){try{const t=e.split(`
|
|
35
|
-
`).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(t))}catch{return[]}}class Semaphore{constructor({concurrency:t}){this._running=0,this.concurrency=t,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(t=>this.queue.push(t));else{this._running++;let t=!1;return()=>{t||(t=!0,this._running--,this.queue.length>0&&this.queue.shift()())}}}async run(t){const r=await this.acquire();try{return await t()}finally{r()}}}function joinPaths(...e){let t=e.join("/");const r=t[0]==="/",s=t.substring(t.length-1)==="/";return t=normalizePath(t),!t&&!r&&(t="."),t&&s&&(t+="/"),t}function dirname(e){if(e==="/")return"/";e=normalizePath(e);const t=e.lastIndexOf("/");return t===-1?"":t===0?"/":e.substr(0,t)}function normalizePath(e){const t=e[0]==="/";return e=normalizePathsArray(e.split("/").filter(r=>!!r),!t).join("/"),(t?"/":"")+e.replace(/\/$/,"")}function normalizePathsArray(e,t){let r=0;for(let s=e.length-1;s>=0;s--){const n=e[s];n==="."?e.splice(s,1):n===".."?(e.splice(s,1),r++):r&&(e.splice(s,1),r--)}if(t)for(;r;r--)e.unshift("..");return e}function splitShellCommand(e){let s=0,n="";const
|
|
35
|
+
`).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(t))}catch{return[]}}class Semaphore{constructor({concurrency:t}){this._running=0,this.concurrency=t,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(t=>this.queue.push(t));else{this._running++;let t=!1;return()=>{t||(t=!0,this._running--,this.queue.length>0&&this.queue.shift()())}}}async run(t){const r=await this.acquire();try{return await t()}finally{r()}}}function joinPaths(...e){let t=e.join("/");const r=t[0]==="/",s=t.substring(t.length-1)==="/";return t=normalizePath(t),!t&&!r&&(t="."),t&&s&&(t+="/"),t}function dirname(e){if(e==="/")return"/";e=normalizePath(e);const t=e.lastIndexOf("/");return t===-1?"":t===0?"/":e.substr(0,t)}function normalizePath(e){const t=e[0]==="/";return e=normalizePathsArray(e.split("/").filter(r=>!!r),!t).join("/"),(t?"/":"")+e.replace(/\/$/,"")}function normalizePathsArray(e,t){let r=0;for(let s=e.length-1;s>=0;s--){const n=e[s];n==="."?e.splice(s,1):n===".."?(e.splice(s,1),r++):r&&(e.splice(s,1),r--)}if(t)for(;r;r--)e.unshift("..");return e}function splitShellCommand(e){let s=0,n="";const o=[];let i="";for(let a=0;a<e.length;a++){const c=e[a];c==="\\"?((e[a+1]==='"'||e[a+1]==="'")&&a++,i+=e[a]):s===0?c==='"'||c==="'"?(s=1,n=c):c.match(/\s/)?(i.trim().length&&o.push(i.trim()),i=c):o.length&&!i?i=o.pop()+c:i+=c:s===1&&(c===n?(s=0,n=""):i+=c)}return i&&o.push(i.trim()),o}function createSpawnHandler(e){return function(t,r=[],s={}){const n=new ChildProcess,o=new ProcessApi(n);return setTimeout(async()=>{let i=[];if(r.length)i=[t,...r];else if(typeof t=="string")i=splitShellCommand(t);else if(Array.isArray(t))i=t;else throw new Error("Invalid command ",t);await e(i,o,s),n.emit("spawn",!0)}),n}}class EventEmitter{constructor(){this.listeners={}}emit(t,r){this.listeners[t]&&this.listeners[t].forEach(function(s){s(r)})}on(t,r){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(r)}}class ProcessApi extends EventEmitter{constructor(t){super(),this.childProcess=t,this.exited=!1,this.stdinData=[],t.on("stdin",r=>{this.stdinData?this.stdinData.push(r.slice()):this.emit("stdin",r)})}stdout(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stdout.emit("data",t)}stdoutEnd(){this.childProcess.stdout.emit("end",{})}stderr(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stderr.emit("data",t)}stderrEnd(){this.childProcess.stderr.emit("end",{})}exit(t){this.exited||(this.exited=!0,this.childProcess.emit("exit",t))}flushStdin(){if(this.stdinData)for(let t=0;t<this.stdinData.length;t++)this.emit("stdin",this.stdinData[t]);this.stdinData=null}}let lastPid=9743;class ChildProcess extends EventEmitter{constructor(t=lastPid++){super(),this.pid=t,this.stdout=new EventEmitter,this.stderr=new EventEmitter;const r=this;this.stdin={write:s=>{r.emit("stdin",s)}}}}function concatUint8Array(...e){const t=new Uint8Array(e.reduce((s,n)=>s+n.length,0));let r=0;for(const s of e)t.set(s,r),r+=s.length;return t}function concatBytes(e){if(e===void 0){let t=new Uint8Array;return new TransformStream({transform(r){t=concatUint8Array(t,r)},flush(r){r.enqueue(t)}})}else{const t=new ArrayBuffer(e||0);let r=0;return new TransformStream({transform(s){new Uint8Array(t).set(s,r),r+=s.byteLength},flush(s){s.enqueue(new Uint8Array(t))}})}}function limitBytes(e,t){if(t===0)return new ReadableStream({start(n){n.close()}});const r=e.getReader({mode:"byob"});let s=0;return new ReadableStream({async pull(n){const{value:o,done:i}=await r.read(new Uint8Array(t-s));if(i){r.releaseLock(),n.close();return}s+=o.length,n.enqueue(o),s>=t&&(r.releaseLock(),n.close())},cancel(){r.cancel()}})}async function collectBytes(e,t){return t!==void 0&&(e=limitBytes(e,t)),await e.pipeThrough(concatBytes(t)).getReader().read().then(({value:r})=>r)}class StreamedFile extends File{constructor(t,r,s){super([],r,{type:s}),this.readableStream=t}slice(){throw new Error("slice() is not possible on a StreamedFile")}stream(){return this.readableStream}async text(){return new TextDecoder().decode(await this.arrayBuffer())}async arrayBuffer(){return await collectBytes(this.stream())}}ReadableStream.prototype[Symbol.asyncIterator]||(ReadableStream.prototype[Symbol.asyncIterator]=async function*(){const e=this.getReader();try{for(;;){const{done:t,value:r}=await e.read();if(t)return;yield r}}finally{e.releaseLock()}},ReadableStream.prototype.iterate=ReadableStream.prototype[Symbol.asyncIterator]);function streamReadFileFromPHP(e,t){return new ReadableStream({async pull(r){const s=await e.readFileAsBuffer(t);r.enqueue(s),r.close()}})}async function*iteratePhpFiles(e,t,{relativePaths:r=!0,pathPrefix:s,exceptPaths:n=[]}={}){t=normalizePath(t);const o=[t];for(;o.length;){const i=o.pop();if(!i)return;const a=await e.listFiles(i);for(const c of a){const d=`${i}/${c}`;if(n.includes(d.substring(t.length+1)))continue;await e.isDir(d)?o.push(d):yield new StreamedFile(streamReadFileFromPHP(e,d),r?joinPaths(s||"",d.substring(t.length+1)):d)}}}function writeFilesStreamToPhp(e,t){return new WritableStream({async write(r){const s=joinPaths(t,r.name);r.type==="directory"?await e.mkdir(s):(await e.mkdir(dirname(s)),await e.writeFile(s,new Uint8Array(await r.arrayBuffer())))}})}class PHPResponse{constructor(t,r,s,n="",o=0){this.httpStatusCode=t,this.headers=r,this.bytes=s,this.exitCode=o,this.errors=n}static fromRawData(t){return new PHPResponse(t.httpStatusCode,t.headers,t.bytes,t.errors,t.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const SupportedPHPVersions=["8.3","8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0"],LatestSupportedPHPVersion=SupportedPHPVersions[0],SupportedPHPVersionsList=SupportedPHPVersions,SupportedPHPExtensionsList=["iconv","mbstring","xml-bundle","gd"],SupportedPHPExtensionBundles={"kitchen-sink":SupportedPHPExtensionsList};var E,b;class PHPBrowser{constructor(t,r={}){u(this,E,void 0);u(this,b,void 0);this.requestHandler=t,h(this,E,{}),h(this,b,{handleRedirects:!1,maxRedirects:4,...r})}async request(t,r=0){const s=await this.requestHandler.request({...t,headers:{...t.headers,cookie:this.serializeCookies()}});if(s.headers["set-cookie"]&&this.setCookies(s.headers["set-cookie"]),l(this,b).handleRedirects&&s.headers.location&&r<l(this,b).maxRedirects){const n=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:n.toString(),method:"GET",headers:{}},r+1)}return s}pathToInternalUrl(t){return this.requestHandler.pathToInternalUrl(t)}internalUrlToPath(t){return this.requestHandler.internalUrlToPath(t)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}setCookies(t){for(const r of t)try{if(!r.includes("="))continue;const s=r.indexOf("="),n=r.substring(0,s),o=r.substring(s+1).split(";")[0];l(this,E)[n]=o}catch(s){console.error(s)}}serializeCookies(){const t=[];for(const r in l(this,E))t.push(`${r}=${l(this,E)[r]}`);return t.join("; ")}}E=new WeakMap,b=new WeakMap;const DEFAULT_BASE_URL="http://example.com";function toRelativeUrl(e){return e.toString().substring(e.origin.length)}function removePathPrefix(e,t){return!t||!e.startsWith(t)?e:e.substring(t.length)}function ensurePathPrefix(e,t){return!t||e.startsWith(t)?e:t+e}async function encodeAsMultipart(e){const t=`----${Math.random().toString(36).slice(2)}`,r=`multipart/form-data; boundary=${t}`,s=new TextEncoder,n=[];for(const[c,d]of Object.entries(e))n.push(`--${t}\r
|
|
36
36
|
`),n.push(`Content-Disposition: form-data; name="${c}"`),d instanceof File&&n.push(`; filename="${d.name}"`),n.push(`\r
|
|
37
37
|
`),d instanceof File&&(n.push("Content-Type: application/octet-stream"),n.push(`\r
|
|
38
38
|
`)),n.push(`\r
|
|
39
39
|
`),d instanceof File?n.push(await fileToUint8Array(d)):n.push(d),n.push(`\r
|
|
40
40
|
`);n.push(`--${t}--\r
|
|
41
|
-
`);const i=n.reduce((c,d)=>c+d.length,0),o=new Uint8Array(i);let a=0;for(const c of n)o.set(typeof c=="string"?s.encode(c):c,a),a+=c.length;return{bytes:o,contentType:r}}function fileToUint8Array(e){return new Promise(t=>{const r=new FileReader;r.onload=()=>{t(new Uint8Array(r.result))},r.readAsArrayBuffer(e)})}var m,x,k,v,H,_,F,R,B,Y,I,Z,L,K;class PHPRequestHandler{constructor(t,r={}){u(this,B);u(this,I);u(this,L);u(this,m,void 0);u(this,x,void 0);u(this,k,void 0);u(this,v,void 0);u(this,H,void 0);u(this,_,void 0);u(this,F,void 0);u(this,R,void 0);h(this,R,new Semaphore({concurrency:1}));const{documentRoot:s="/www/",absoluteUrl:n=typeof location=="object"?location==null?void 0:location.href:""}=r;this.php=t,h(this,m,s);const i=new URL(n);h(this,k,i.hostname),h(this,v,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,x,(i.protocol||"").replace(":",""));const o=l(this,v)!==443&&l(this,v)!==80;h(this,H,[l(this,k),o?`:${l(this,v)}`:""].join("")),h(this,_,i.pathname.replace(/\/+$/,"")),h(this,F,[`${l(this,x)}://`,l(this,H),l(this,_)].join(""))}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(l(this,_))&&(r.pathname=r.pathname.slice(l(this,_).length)),toRelativeUrl(r)}get isRequestRunning(){return l(this,R).running>0}get absoluteUrl(){return l(this,F)}get documentRoot(){return l(this,m)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url,r?void 0:DEFAULT_BASE_URL),n=removePathPrefix(s.pathname,l(this,_)),i=`${l(this,m)}${n}`;return seemsLikeAPHPRequestHandlerPath(i)?await p(this,I,Z).call(this,t,s):p(this,B,Y).call(this,i)}}m=new WeakMap,x=new WeakMap,k=new WeakMap,v=new WeakMap,H=new WeakMap,_=new WeakMap,F=new WeakMap,R=new WeakMap,B=new WeakSet,Y=function(t){if(!this.php.fileExists(t))return new PHPResponse(404,{"x-file-type":["static"]},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new PHPResponse(200,{"content-length":[`${r.byteLength}`],"content-type":[inferMimeType(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)},I=new WeakSet,Z=async function(t,r){var n,i;if(l(this,R).running>0&&((n=t.headers)==null?void 0:n["x-request-issuer"])==="php")return console.warn("Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."),new PHPResponse(502,{},new TextEncoder().encode("502 Bad Gateway"));const s=await l(this,R).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",l(this,m)),this.php.addServerGlobalEntry("HTTPS",l(this,F).startsWith("https://")?"on":"");let o="GET";const a={host:l(this,H),...normalizeHeaders(t.headers||{})};let c=t.body;if(typeof c=="object"&&!(c instanceof Uint8Array)){o="POST";const{bytes:f,contentType:U}=await encodeAsMultipart(c);c=f,a["content-type"]=U}let d;try{let f=r.pathname;if((i=t.headers)!=null&&i["x-rewrite-url"])try{f=new URL(t.headers["x-rewrite-url"]).pathname}catch{}d=p(this,L,K).call(this,f)}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),l(this,_)),protocol:l(this,x),method:t.method||o,body:c,scriptPath:d,headers:a})}finally{s()}},L=new WeakSet,K=function(t){let r=removePathPrefix(t,l(this,_));r.includes(".php")?r=r.split(".php")[0]+".php":this.php.isDir(`${l(this,m)}${r}`)?(r.endsWith("/")||(r=`${r}/`),r=`${r}index.php`):r="/index.php";const s=`${l(this,m)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};function inferMimeType(e){switch(e.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}function seemsLikeAPHPRequestHandlerPath(e){return seemsLikeAPHPFile(e)||seemsLikeADirectoryRoot(e)}function seemsLikeAPHPFile(e){return e.endsWith(".php")||e.includes(".php/")}function seemsLikeADirectoryRoot(e){return!e.split("/").pop().includes(".")}const FileErrorCodes={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function getEmscriptenFsError(e){const t=typeof e=="object"?e==null?void 0:e.errno:null;if(t in FileErrorCodes)return FileErrorCodes[t]}function rethrowFileSystemError(e=""){return function(r,s,n){const i=n.value;n.value=function(...o){try{return i.apply(this,o)}catch(a){const c=typeof a=="object"?a==null?void 0:a.errno:null;if(c in FileErrorCodes){const d=FileErrorCodes[c],f=typeof o[0]=="string"?o[0]:null,U=f!==null?e.replaceAll("{path}",f):e;throw new Error(`${U}: ${d}`,{cause:a})}throw a}}}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(e,t={}){const[r,s,n]=makePromise(),i=e.init(currentJsRuntime,{onAbort(a){n(a),console.error(a)},ENV:{},locateFile:a=>a,...t,noInitialRun:!0,onRuntimeInitialized(){t.onRuntimeInitialized&&t.onRuntimeInitialized(),s()}});await r;const o=++lastRuntimeId;return i.id=o,i.originalExit=i._exit,i._exit=function(a){return loadedRuntimes.delete(o),i.originalExit(a)},i[RuntimeId]=o,loadedRuntimes.set(o,i),o}function getLoadedRuntime(e){return loadedRuntimes.get(e)}const currentJsRuntime=function(){var e;return typeof process<"u"&&((e=process.release)==null?void 0:e.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),makePromise=()=>{const e=[],t=new Promise((r,s)=>{e.push(r,s)});return e.unshift(t),e};var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__decorateClass=(e,t,r,s)=>{for(var n=s>1?void 0:s?__getOwnPropDesc(t,r):t,i=e.length-1,o;i>=0;i--)(o=e[i])&&(n=(s?o(t,r,n):o(n))||n);return s&&n&&__defProp(t,r,n),n};const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");var S,T,A,y,w,g,P,C,N,X,O,ee,M,te,q,re,D,se,$,ne,j,ie,W,oe,z,ae,G,le,V,ce,J,ue;class BasePHP{constructor(e,t){u(this,N);u(this,O);u(this,M);u(this,q);u(this,D);u(this,$);u(this,j);u(this,W);u(this,z);u(this,G);u(this,V);u(this,J);u(this,S,void 0);u(this,T,void 0);u(this,A,void 0);u(this,y,void 0);u(this,w,void 0);u(this,g,void 0);u(this,P,void 0);u(this,C,void 0);h(this,S,[]),h(this,y,!1),h(this,w,null),h(this,g,{}),h(this,P,new Map),h(this,C,[]),this.semaphore=new Semaphore({concurrency:1}),e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new PHPBrowser(new PHPRequestHandler(this,t)))}addEventListener(e,t){l(this,P).has(e)||l(this,P).set(e,new Set),l(this,P).get(e).add(t)}removeEventListener(e,t){var r;(r=l(this,P).get(e))==null||r.delete(t)}dispatchEvent(e){const t=l(this,P).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){l(this,C).push(e)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const t=getLoadedRuntime(e);if(!t)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=t,t.onMessage=async r=>{for(const s of l(this,C)){const n=await s(r);if(n)return n}return""},h(this,w,improveWASMErrorReporting(t)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(e){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[e])!==0)throw new Error("Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?");h(this,A,e)}setPhpIniPath(e){if(l(this,y))throw new Error("Cannot set PHP ini path after calling run().");h(this,T,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(l(this,y))throw new Error("Cannot set PHP ini entries after calling run().");l(this,S).push([e,t])}chdir(e){this[__private__dont__use].FS.chdir(e)}async request(e,t){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,t)}async run(e){const t=await this.semaphore.acquire();let r;try{if(l(this,y)||(p(this,N,X).call(this),h(this,y,!0)),e.scriptPath&&!this.fileExists(e.scriptPath))throw new Error(`The script path "${e.scriptPath}" does not exist.`);p(this,W,oe).call(this,e.scriptPath||""),p(this,M,te).call(this,e.relativeUri||""),p(this,D,se).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";p(this,q,re).call(this,n,e.protocol||"http"),p(this,$,ne).call(this,s),e.body&&(r=p(this,j,ie).call(this,e.body)),typeof e.code=="string"&&p(this,V,ce).call(this," ?>"+e.code),p(this,z,ae).call(this);const i=e.env||{};for(const a in i)p(this,G,le).call(this,a,i[a]);const o=await p(this,J,ue).call(this);if(e.throwOnError&&o.exitCode!==0){const a={stdout:o.text,stderr:o.errors};console.warn("PHP.run() output was:",a);const c=new Error(`PHP.run() failed with exit code ${o.exitCode} and the following output: `+o.errors);throw c.output=a,console.error(c),c}return o}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){l(this,g)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/internal/consts.json")&&this.readFileAsText("/internal/consts.json")||"{}")}catch{}this.writeFile("/internal/consts.json",JSON.stringify({...r,[e]:t}))}mkdir(e){this[__private__dont__use].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[__private__dont__use].FS.readFile(e)}writeFile(e,t){this[__private__dont__use].FS.writeFile(e,t)}unlink(e){this[__private__dont__use].FS.unlink(e)}mv(e,t){try{this[__private__dont__use].FS.rename(e,t)}catch(r){const s=getEmscriptenFsError(r);throw s?new Error(`Could not move ${e} to ${t}: ${s}`,{cause:r}):r}}rmdir(e,t={recursive:!0}){t!=null&&t.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[__private__dont__use].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[__private__dont__use].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(n=>`${s}/${n}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[__private__dont__use].FS.isDir(this[__private__dont__use].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[__private__dont__use].FS.lookupPath(e),!0}catch{return!1}}hotSwapPHPRuntime(e){const t=this[__private__dont__use].FS;try{this.exit()}catch{}if(this.initializeRuntime(e),l(this,T)&&this.setPhpIniPath(l(this,T)),l(this,A)&&this.setSapiName(l(this,A)),this.requestHandler){const r=this.documentRoot;copyFS(t,this[__private__dont__use].FS,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}h(this,y,!1),h(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,T=new WeakMap,A=new WeakMap,y=new WeakMap,w=new WeakMap,g=new WeakMap,P=new WeakMap,C=new WeakMap,N=new WeakSet,X=function(){if(this.setPhpIniEntry("auto_prepend_file","/internal/consts.php"),this.fileExists("/internal/consts.php")||this.writeFile("/internal/consts.php",`<?php
|
|
41
|
+
`);const o=n.reduce((c,d)=>c+d.length,0),i=new Uint8Array(o);let a=0;for(const c of n)i.set(typeof c=="string"?s.encode(c):c,a),a+=c.length;return{bytes:i,contentType:r}}function fileToUint8Array(e){return new Promise(t=>{const r=new FileReader;r.onload=()=>{t(new Uint8Array(r.result))},r.readAsArrayBuffer(e)})}var m,x,k,R,H,f,F,v,U,Q,B,Y,I,Z;class PHPRequestHandler{constructor(t,r={}){u(this,U);u(this,B);u(this,I);u(this,m,void 0);u(this,x,void 0);u(this,k,void 0);u(this,R,void 0);u(this,H,void 0);u(this,f,void 0);u(this,F,void 0);u(this,v,void 0);h(this,v,new Semaphore({concurrency:1}));const{documentRoot:s="/www/",absoluteUrl:n=typeof location=="object"?location==null?void 0:location.href:"",rewriteRules:o=[]}=r;this.php=t,h(this,m,s);const i=new URL(n);h(this,k,i.hostname),h(this,R,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,x,(i.protocol||"").replace(":",""));const a=l(this,R)!==443&&l(this,R)!==80;h(this,H,[l(this,k),a?`:${l(this,R)}`:""].join("")),h(this,f,i.pathname.replace(/\/+$/,"")),h(this,F,[`${l(this,x)}://`,l(this,H),l(this,f)].join("")),this.rewriteRules=o}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(l(this,f))&&(r.pathname=r.pathname.slice(l(this,f).length)),toRelativeUrl(r)}get isRequestRunning(){return l(this,v).running>0}get absoluteUrl(){return l(this,F)}get documentRoot(){return l(this,m)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url.split("#")[0],r?void 0:DEFAULT_BASE_URL),n=applyRewriteRules(removePathPrefix(s.pathname,l(this,f)),this.rewriteRules),o=`${l(this,m)}${n}`;return seemsLikeAPHPRequestHandlerPath(o)?await p(this,B,Y).call(this,t,s):p(this,U,Q).call(this,o)}}m=new WeakMap,x=new WeakMap,k=new WeakMap,R=new WeakMap,H=new WeakMap,f=new WeakMap,F=new WeakMap,v=new WeakMap,U=new WeakSet,Q=function(t){if(!this.php.fileExists(t))return new PHPResponse(404,{"x-file-type":["static"]},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new PHPResponse(200,{"content-length":[`${r.byteLength}`],"content-type":[inferMimeType(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)},B=new WeakSet,Y=async function(t,r){var n;if(l(this,v).running>0&&((n=t.headers)==null?void 0:n["x-request-issuer"])==="php")return console.warn("Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."),new PHPResponse(502,{},new TextEncoder().encode("502 Bad Gateway"));const s=await l(this,v).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",l(this,m)),this.php.addServerGlobalEntry("HTTPS",l(this,F).startsWith("https://")?"on":"");let o="GET";const i={host:l(this,H),...normalizeHeaders(t.headers||{})};let a=t.body;if(typeof a=="object"&&!(a instanceof Uint8Array)){o="POST";const{bytes:d,contentType:_}=await encodeAsMultipart(a);a=d,i["content-type"]=_}let c;try{c=p(this,I,Z).call(this,r.pathname)}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),l(this,f)),protocol:l(this,x),method:t.method||o,body:a,scriptPath:c,headers:i})}finally{s()}},I=new WeakSet,Z=function(t){let r=removePathPrefix(t,l(this,f));r=applyRewriteRules(r,this.rewriteRules),r.includes(".php")?r=r.split(".php")[0]+".php":this.php.isDir(`${l(this,m)}${r}`)?(r.endsWith("/")||(r=`${r}/`),r=`${r}index.php`):r="/index.php";const s=`${l(this,m)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};function inferMimeType(e){switch(e.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}function seemsLikeAPHPRequestHandlerPath(e){return seemsLikeAPHPFile(e)||seemsLikeADirectoryRoot(e)}function seemsLikeAPHPFile(e){return e.endsWith(".php")||e.includes(".php/")}function seemsLikeADirectoryRoot(e){return!e.split("/").pop().includes(".")}function applyRewriteRules(e,t){for(const r of t)if(new RegExp(r.match).test(e))return e.replace(r.match,r.replacement);return e}const FileErrorCodes={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function getEmscriptenFsError(e){const t=typeof e=="object"?e==null?void 0:e.errno:null;if(t in FileErrorCodes)return FileErrorCodes[t]}function rethrowFileSystemError(e=""){return function(r,s,n){const o=n.value;n.value=function(...i){try{return o.apply(this,i)}catch(a){const c=typeof a=="object"?a==null?void 0:a.errno:null;if(c in FileErrorCodes){const d=FileErrorCodes[c],_=typeof i[0]=="string"?i[0]:null,ue=_!==null?e.replaceAll("{path}",_):e;throw new Error(`${ue}: ${d}`,{cause:a})}throw a}}}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(e,t={}){const[r,s,n]=makePromise(),o=e.init(currentJsRuntime,{onAbort(a){n(a),console.error(a)},ENV:{},locateFile:a=>a,...t,noInitialRun:!0,onRuntimeInitialized(){t.onRuntimeInitialized&&t.onRuntimeInitialized(),s()}});await r;const i=++lastRuntimeId;return o.id=i,o.originalExit=o._exit,o._exit=function(a){return loadedRuntimes.delete(i),o.originalExit(a)},o[RuntimeId]=i,loadedRuntimes.set(i,o),i}function getLoadedRuntime(e){return loadedRuntimes.get(e)}const currentJsRuntime=function(){var e;return typeof process<"u"&&((e=process.release)==null?void 0:e.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),makePromise=()=>{const e=[],t=new Promise((r,s)=>{e.push(r,s)});return e.unshift(t),e};var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__decorateClass=(e,t,r,s)=>{for(var n=s>1?void 0:s?__getOwnPropDesc(t,r):t,o=e.length-1,i;o>=0;o--)(i=e[o])&&(n=(s?i(t,r,n):i(n))||n);return s&&n&&__defProp(t,r,n),n};const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");var S,T,A,y,w,g,P,C,L,K,N,X,q,ee,O,te,M,re,D,se,$,ne,j,ie,W,oe,z,ae,G,le,V,ce;class BasePHP{constructor(e,t){u(this,L);u(this,N);u(this,q);u(this,O);u(this,M);u(this,D);u(this,$);u(this,j);u(this,W);u(this,z);u(this,G);u(this,V);u(this,S,void 0);u(this,T,void 0);u(this,A,void 0);u(this,y,void 0);u(this,w,void 0);u(this,g,void 0);u(this,P,void 0);u(this,C,void 0);h(this,S,[]),h(this,y,!1),h(this,w,null),h(this,g,{}),h(this,P,new Map),h(this,C,[]),this.semaphore=new Semaphore({concurrency:1}),e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new PHPBrowser(new PHPRequestHandler(this,t)))}addEventListener(e,t){l(this,P).has(e)||l(this,P).set(e,new Set),l(this,P).get(e).add(t)}removeEventListener(e,t){var r;(r=l(this,P).get(e))==null||r.delete(t)}dispatchEvent(e){const t=l(this,P).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){l(this,C).push(e)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const t=getLoadedRuntime(e);if(!t)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=t,t.onMessage=async r=>{for(const s of l(this,C)){const n=await s(r);if(n)return n}return""},h(this,w,improveWASMErrorReporting(t)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(e){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[e])!==0)throw new Error("Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?");h(this,A,e)}setPhpIniPath(e){if(l(this,y))throw new Error("Cannot set PHP ini path after calling run().");h(this,T,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(l(this,y))throw new Error("Cannot set PHP ini entries after calling run().");l(this,S).push([e,t])}chdir(e){this[__private__dont__use].FS.chdir(e)}async request(e,t){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,t)}async run(e){const t=await this.semaphore.acquire();let r;try{if(l(this,y)||(p(this,L,K).call(this),h(this,y,!0)),e.scriptPath&&!this.fileExists(e.scriptPath))throw new Error(`The script path "${e.scriptPath}" does not exist.`);p(this,j,ie).call(this,e.scriptPath||""),p(this,q,ee).call(this,e.relativeUri||""),p(this,M,re).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";p(this,O,te).call(this,n,e.protocol||"http"),p(this,D,se).call(this,s),e.body&&(r=p(this,$,ne).call(this,e.body)),typeof e.code=="string"&&p(this,G,le).call(this," ?>"+e.code),p(this,W,oe).call(this);const o=e.env||{};for(const a in o)p(this,z,ae).call(this,a,o[a]);const i=await p(this,V,ce).call(this);if(i.exitCode!==0){const a={stdout:i.text,stderr:i.errors};console.warn("PHP.run() output was:",a);const c=new Error(`PHP.run() failed with exit code ${i.exitCode} and the following output: `+i.errors);throw c.output=a,c.source="request",console.error(c),c}return i}catch(s){throw this.dispatchEvent({type:"request.error",error:s,source:s.source??"php-wasm"}),s}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){l(this,g)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/internal/consts.json")&&this.readFileAsText("/internal/consts.json")||"{}")}catch{}this.writeFile("/internal/consts.json",JSON.stringify({...r,[e]:t}))}mkdir(e){this[__private__dont__use].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[__private__dont__use].FS.readFile(e)}writeFile(e,t){this[__private__dont__use].FS.writeFile(e,t)}unlink(e){this[__private__dont__use].FS.unlink(e)}mv(e,t){try{this[__private__dont__use].FS.rename(e,t)}catch(r){const s=getEmscriptenFsError(r);throw s?new Error(`Could not move ${e} to ${t}: ${s}`,{cause:r}):r}}rmdir(e,t={recursive:!0}){t!=null&&t.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[__private__dont__use].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[__private__dont__use].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(n=>`${s}/${n}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[__private__dont__use].FS.isDir(this[__private__dont__use].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[__private__dont__use].FS.lookupPath(e),!0}catch{return!1}}hotSwapPHPRuntime(e){const t=this[__private__dont__use].FS;try{this.exit()}catch{}if(this.initializeRuntime(e),l(this,T)&&this.setPhpIniPath(l(this,T)),l(this,A)&&this.setSapiName(l(this,A)),this.requestHandler){const r=this.documentRoot;copyFS(t,this[__private__dont__use].FS,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}h(this,y,!1),h(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,T=new WeakMap,A=new WeakMap,y=new WeakMap,w=new WeakMap,g=new WeakMap,P=new WeakMap,C=new WeakMap,L=new WeakSet,K=function(){if(this.setPhpIniEntry("auto_prepend_file","/internal/consts.php"),this.fileExists("/internal/consts.php")||this.writeFile("/internal/consts.php",`<?php
|
|
42
42
|
if(file_exists('/internal/consts.json')) {
|
|
43
43
|
$consts = json_decode(file_get_contents('/internal/consts.json'), true);
|
|
44
44
|
foreach ($consts as $const => $value) {
|
|
@@ -49,4 +49,4 @@ ${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
|
|
|
49
49
|
}`),l(this,S).length>0){const e=l(this,S).map(([t,r])=>`${t}=${r}`).join(`
|
|
50
50
|
`)+`
|
|
51
51
|
|
|
52
|
-
`;this[__private__dont__use].ccall("wasm_set_phpini_entries",null,[STRING],[e])}this[__private__dont__use].ccall("php_wasm_init",null,[],[])},
|
|
52
|
+
`;this[__private__dont__use].ccall("wasm_set_phpini_entries",null,[STRING],[e])}this[__private__dont__use].ccall("php_wasm_init",null,[],[])},N=new WeakSet,X=function(){const e="/internal/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const t=JSON.parse(this.readFileAsText(e)),r={};for(const s of t.headers){if(!s.includes(": "))continue;const n=s.indexOf(": "),o=s.substring(0,n).toLowerCase(),i=s.substring(n+2);o in r||(r[o]=[]),r[o].push(i)}return{headers:r,httpStatusCode:t.status}},q=new WeakSet,ee=function(e){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[t])}},O=new WeakSet,te=function(e,t){this[__private__dont__use].ccall("wasm_set_request_host",null,[STRING],[e]);let r;try{r=parseInt(new URL(e).port,10)}catch{}(!r||isNaN(r)||r===80)&&(r=t==="https"?443:80),this[__private__dont__use].ccall("wasm_set_request_port",null,[NUMBER],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")},M=new WeakSet,re=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},D=new WeakSet,se=function(e){e.cookie&&this[__private__dont__use].ccall("wasm_set_cookies",null,[STRING],[e.cookie]),e["content-type"]&&this[__private__dont__use].ccall("wasm_set_content_type",null,[STRING],[e["content-type"]]),e["content-length"]&&this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[parseInt(e["content-length"],10)]);for(const t in e){let r="HTTP_";["content-type","content-length"].includes(t.toLowerCase())&&(r=""),this.addServerGlobalEntry(`${r}${t.toUpperCase().replace(/-/g,"_")}`,e[t])}},$=new WeakSet,ne=function(e){let t,r;typeof e=="string"?(console.warn("Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"),r=this[__private__dont__use].lengthBytesUTF8(e),t=r+1):(r=e.byteLength,t=e.byteLength);const s=this[__private__dont__use].malloc(t);if(!s)throw new Error("Could not allocate memory for the request body.");return typeof e=="string"?this[__private__dont__use].stringToUTF8(e,s,t+1):this[__private__dont__use].HEAPU8.set(e,s),this[__private__dont__use].ccall("wasm_set_request_body",null,[NUMBER],[s]),this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[r]),s},j=new WeakSet,ie=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},W=new WeakSet,oe=function(){for(const e in l(this,g))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,l(this,g)[e]])},z=new WeakSet,ae=function(e,t){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[e,t])},G=new WeakSet,le=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},V=new WeakSet,ce=async function(){var n;let e,t;try{e=await new Promise((o,i)=>{var c;t=d=>{console.error(d),console.error(d.error);const _=new Error("Rethrown");_.cause=d.error,_.betterMessage=d.message,i(_)},(c=l(this,w))==null||c.addEventListener("error",t);const a=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return a instanceof Promise?a.then(o,i):o(a)})}catch(o){for(const d in this)typeof this[d]=="function"&&(this[d]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=getFunctionsMaybeMissingFromAsyncify();const i=o,a="betterMessage"in i?i.betterMessage:i.message,c=new Error(a);throw c.cause=i,console.error(c),c}finally{(n=l(this,w))==null||n.removeEventListener("error",t),h(this,g,{})}const{headers:r,httpStatusCode:s}=p(this,N,X).call(this);return new PHPResponse(s,r,this.readFileAsBuffer("/internal/stdout"),this.readFileAsText("/internal/stderr"),e)};__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdir",1);__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdirTree",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsText",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsBuffer",1);__decorateClass([rethrowFileSystemError('Could not write to "{path}"')],BasePHP.prototype,"writeFile",1);__decorateClass([rethrowFileSystemError('Could not unlink "{path}"')],BasePHP.prototype,"unlink",1);__decorateClass([rethrowFileSystemError('Could not remove directory "{path}"')],BasePHP.prototype,"rmdir",1);__decorateClass([rethrowFileSystemError('Could not list files in "{path}"')],BasePHP.prototype,"listFiles",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"isDir",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"fileExists",1);function normalizeHeaders(e){const t={};for(const r in e)t[r.toLowerCase()]=e[r];return t}function copyFS(e,t,r){let s;try{s=e.lookupPath(r)}catch{return}if(!("contents"in s.node))return;if(!e.isDir(s.node.mode)){t.writeFile(r,e.readFile(r));return}t.mkdirTree(r);const n=e.readdir(r).filter(o=>o!=="."&&o!=="..");for(const o of n)copyFS(e,t,joinPaths(r,o))}function isLocalPHP(e){return!(e instanceof BasePHP)}function isRemotePHP(e){return!isLocalPHP(e)}function rotatePHPRuntime({php:e,recreateRuntime:t,maxRequests:r}){let s=0;async function n(){if(++s<r)return;s=0;const o=await e.semaphore.acquire();try{e.hotSwapPHPRuntime(await t())}finally{o()}}return e.addEventListener("request.end",n),function(){e.removeEventListener("request.end",n)}}async function writeFiles(e,t,r,{rmRoot:s=!1}={}){s&&await e.isDir(t)&&await e.rmdir(t,{recursive:!0});for(const[n,o]of Object.entries(r)){const i=joinPaths(t,n);await e.fileExists(dirname(i))||await e.mkdir(dirname(i)),await e.writeFile(i,o)}}exports.BasePHP=BasePHP;exports.DEFAULT_BASE_URL=DEFAULT_BASE_URL;exports.LatestSupportedPHPVersion=LatestSupportedPHPVersion;exports.PHPBrowser=PHPBrowser;exports.PHPRequestHandler=PHPRequestHandler;exports.PHPResponse=PHPResponse;exports.SupportedPHPExtensionBundles=SupportedPHPExtensionBundles;exports.SupportedPHPExtensionsList=SupportedPHPExtensionsList;exports.SupportedPHPVersions=SupportedPHPVersions;exports.SupportedPHPVersionsList=SupportedPHPVersionsList;exports.UnhandledRejectionsTarget=UnhandledRejectionsTarget;exports.__private__dont__use=__private__dont__use;exports.applyRewriteRules=applyRewriteRules;exports.ensurePathPrefix=ensurePathPrefix;exports.isExitCodeZero=isExitCodeZero;exports.isLocalPHP=isLocalPHP;exports.isRemotePHP=isRemotePHP;exports.iterateFiles=iteratePhpFiles;exports.loadPHPRuntime=loadPHPRuntime;exports.removePathPrefix=removePathPrefix;exports.rethrowFileSystemError=rethrowFileSystemError;exports.rotatePHPRuntime=rotatePHPRuntime;exports.toRelativeUrl=toRelativeUrl;exports.writeFiles=writeFiles;exports.writeFilesStreamToPhp=writeFilesStreamToPhp;
|
package/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
var
|
|
1
|
+
var J = (e, t, r) => {
|
|
2
2
|
if (!t.has(e))
|
|
3
3
|
throw TypeError("Cannot " + r);
|
|
4
4
|
};
|
|
5
|
-
var l = (e, t, r) => (
|
|
5
|
+
var l = (e, t, r) => (J(e, t, "read from private field"), r ? r.call(e) : t.get(e)), u = (e, t, r) => {
|
|
6
6
|
if (t.has(e))
|
|
7
7
|
throw TypeError("Cannot add the same private member more than once");
|
|
8
8
|
t instanceof WeakSet ? t.add(e) : t.set(e, r);
|
|
9
|
-
}, h = (e, t, r, s) => (
|
|
10
|
-
var f = (e, t, r) => (
|
|
9
|
+
}, h = (e, t, r, s) => (J(e, t, "write to private field"), s ? s.call(e, r) : t.set(e, r), r);
|
|
10
|
+
var f = (e, t, r) => (J(e, t, "access private method"), r);
|
|
11
11
|
const currentJsRuntime$1 = function() {
|
|
12
12
|
var e;
|
|
13
13
|
return typeof process < "u" && ((e = process.release) == null ? void 0 : e.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : (
|
|
@@ -19,8 +19,8 @@ const currentJsRuntime$1 = function() {
|
|
|
19
19
|
if (currentJsRuntime$1 === "NODE") {
|
|
20
20
|
let e = function(r) {
|
|
21
21
|
return new Promise(function(s, n) {
|
|
22
|
-
r.onload = r.onerror = function(
|
|
23
|
-
r.onload = r.onerror = null,
|
|
22
|
+
r.onload = r.onerror = function(o) {
|
|
23
|
+
r.onload = r.onerror = null, o.type === "load" ? s(r.result) : n(new Error("Failed to read the blob/file"));
|
|
24
24
|
};
|
|
25
25
|
});
|
|
26
26
|
}, t = function() {
|
|
@@ -33,10 +33,10 @@ if (currentJsRuntime$1 === "NODE") {
|
|
|
33
33
|
};
|
|
34
34
|
if (typeof File > "u") {
|
|
35
35
|
class r extends Blob {
|
|
36
|
-
constructor(n,
|
|
36
|
+
constructor(n, o, i) {
|
|
37
37
|
super(n);
|
|
38
38
|
let a;
|
|
39
|
-
|
|
39
|
+
i != null && i.lastModified && (a = /* @__PURE__ */ new Date()), (!a || isNaN(a.getFullYear())) && (a = /* @__PURE__ */ new Date()), this.lastModifiedDate = a, this.lastModified = a.getMilliseconds(), this.name = o || "";
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
global.File = r;
|
|
@@ -56,11 +56,11 @@ if (currentJsRuntime$1 === "NODE") {
|
|
|
56
56
|
// this if needed.
|
|
57
57
|
autoAllocateChunkSize: 512 * 1024,
|
|
58
58
|
async pull(n) {
|
|
59
|
-
const
|
|
59
|
+
const o = n.byobRequest.view, a = await s.slice(
|
|
60
60
|
r,
|
|
61
|
-
r +
|
|
61
|
+
r + o.byteLength
|
|
62
62
|
).arrayBuffer(), c = new Uint8Array(a);
|
|
63
|
-
new Uint8Array(
|
|
63
|
+
new Uint8Array(o.buffer).set(c);
|
|
64
64
|
const d = c.byteLength;
|
|
65
65
|
n.byobRequest.respond(d), r += d, r >= s.size && n.close();
|
|
66
66
|
}
|
|
@@ -125,26 +125,26 @@ function improveWASMErrorReporting(e) {
|
|
|
125
125
|
if (typeof e.asm[r] == "function") {
|
|
126
126
|
const s = e.asm[r];
|
|
127
127
|
e.asm[r] = function(...n) {
|
|
128
|
-
var
|
|
128
|
+
var o;
|
|
129
129
|
try {
|
|
130
130
|
return s(...n);
|
|
131
|
-
} catch (
|
|
132
|
-
if (!(
|
|
133
|
-
throw
|
|
131
|
+
} catch (i) {
|
|
132
|
+
if (!(i instanceof Error))
|
|
133
|
+
throw i;
|
|
134
134
|
const a = clarifyErrorMessage(
|
|
135
|
-
|
|
136
|
-
(
|
|
135
|
+
i,
|
|
136
|
+
(o = e.lastAsyncifyStackSource) == null ? void 0 : o.stack
|
|
137
137
|
);
|
|
138
|
-
if (e.lastAsyncifyStackSource && (
|
|
138
|
+
if (e.lastAsyncifyStackSource && (i.cause = e.lastAsyncifyStackSource), t.hasListeners()) {
|
|
139
139
|
t.dispatchEvent(
|
|
140
140
|
new ErrorEvent("error", {
|
|
141
|
-
error:
|
|
141
|
+
error: i,
|
|
142
142
|
message: a
|
|
143
143
|
})
|
|
144
144
|
);
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
|
-
throw isExitCodeZero(
|
|
147
|
+
throw isExitCodeZero(i) || showCriticalErrorBox(a), i;
|
|
148
148
|
}
|
|
149
149
|
};
|
|
150
150
|
}
|
|
@@ -286,28 +286,28 @@ function normalizePathsArray(e, t) {
|
|
|
286
286
|
}
|
|
287
287
|
function splitShellCommand(e) {
|
|
288
288
|
let s = 0, n = "";
|
|
289
|
-
const
|
|
290
|
-
let
|
|
289
|
+
const o = [];
|
|
290
|
+
let i = "";
|
|
291
291
|
for (let a = 0; a < e.length; a++) {
|
|
292
292
|
const c = e[a];
|
|
293
|
-
c === "\\" ? ((e[a + 1] === '"' || e[a + 1] === "'") && a++,
|
|
293
|
+
c === "\\" ? ((e[a + 1] === '"' || e[a + 1] === "'") && a++, i += e[a]) : s === 0 ? c === '"' || c === "'" ? (s = 1, n = c) : c.match(/\s/) ? (i.trim().length && o.push(i.trim()), i = c) : o.length && !i ? i = o.pop() + c : i += c : s === 1 && (c === n ? (s = 0, n = "") : i += c);
|
|
294
294
|
}
|
|
295
|
-
return
|
|
295
|
+
return i && o.push(i.trim()), o;
|
|
296
296
|
}
|
|
297
297
|
function createSpawnHandler(e) {
|
|
298
298
|
return function(t, r = [], s = {}) {
|
|
299
|
-
const n = new ChildProcess(),
|
|
299
|
+
const n = new ChildProcess(), o = new ProcessApi(n);
|
|
300
300
|
return setTimeout(async () => {
|
|
301
|
-
let
|
|
301
|
+
let i = [];
|
|
302
302
|
if (r.length)
|
|
303
|
-
|
|
303
|
+
i = [t, ...r];
|
|
304
304
|
else if (typeof t == "string")
|
|
305
|
-
|
|
305
|
+
i = splitShellCommand(t);
|
|
306
306
|
else if (Array.isArray(t))
|
|
307
|
-
|
|
307
|
+
i = t;
|
|
308
308
|
else
|
|
309
309
|
throw new Error("Invalid command ", t);
|
|
310
|
-
await e(
|
|
310
|
+
await e(i, o, s), n.emit("spawn", !0);
|
|
311
311
|
}), n;
|
|
312
312
|
};
|
|
313
313
|
}
|
|
@@ -408,14 +408,14 @@ function limitBytes(e, t) {
|
|
|
408
408
|
let s = 0;
|
|
409
409
|
return new ReadableStream({
|
|
410
410
|
async pull(n) {
|
|
411
|
-
const { value:
|
|
411
|
+
const { value: o, done: i } = await r.read(
|
|
412
412
|
new Uint8Array(t - s)
|
|
413
413
|
);
|
|
414
|
-
if (
|
|
414
|
+
if (i) {
|
|
415
415
|
r.releaseLock(), n.close();
|
|
416
416
|
return;
|
|
417
417
|
}
|
|
418
|
-
s +=
|
|
418
|
+
s += o.length, n.enqueue(o), s >= t && (r.releaseLock(), n.close());
|
|
419
419
|
},
|
|
420
420
|
cancel() {
|
|
421
421
|
r.cancel();
|
|
@@ -497,17 +497,17 @@ async function* iteratePhpFiles(e, t, {
|
|
|
497
497
|
exceptPaths: n = []
|
|
498
498
|
} = {}) {
|
|
499
499
|
t = normalizePath(t);
|
|
500
|
-
const
|
|
501
|
-
for (;
|
|
502
|
-
const
|
|
503
|
-
if (!
|
|
500
|
+
const o = [t];
|
|
501
|
+
for (; o.length; ) {
|
|
502
|
+
const i = o.pop();
|
|
503
|
+
if (!i)
|
|
504
504
|
return;
|
|
505
|
-
const a = await e.listFiles(
|
|
505
|
+
const a = await e.listFiles(i);
|
|
506
506
|
for (const c of a) {
|
|
507
|
-
const d = `${
|
|
507
|
+
const d = `${i}/${c}`;
|
|
508
508
|
if (n.includes(d.substring(t.length + 1)))
|
|
509
509
|
continue;
|
|
510
|
-
await e.isDir(d) ?
|
|
510
|
+
await e.isDir(d) ? o.push(d) : yield new StreamedFile(
|
|
511
511
|
streamReadFileFromPHP(e, d),
|
|
512
512
|
r ? joinPaths(
|
|
513
513
|
s || "",
|
|
@@ -529,8 +529,8 @@ function writeFilesStreamToPhp(e, t) {
|
|
|
529
529
|
});
|
|
530
530
|
}
|
|
531
531
|
class PHPResponse {
|
|
532
|
-
constructor(t, r, s, n = "",
|
|
533
|
-
this.httpStatusCode = t, this.headers = r, this.bytes = s, this.exitCode =
|
|
532
|
+
constructor(t, r, s, n = "", o = 0) {
|
|
533
|
+
this.httpStatusCode = t, this.headers = r, this.bytes = s, this.exitCode = o, this.errors = n;
|
|
534
534
|
}
|
|
535
535
|
static fromRawData(t) {
|
|
536
536
|
return new PHPResponse(
|
|
@@ -655,8 +655,8 @@ class PHPBrowser {
|
|
|
655
655
|
try {
|
|
656
656
|
if (!r.includes("="))
|
|
657
657
|
continue;
|
|
658
|
-
const s = r.indexOf("="), n = r.substring(0, s),
|
|
659
|
-
l(this, E)[n] =
|
|
658
|
+
const s = r.indexOf("="), n = r.substring(0, s), o = r.substring(s + 1).split(";")[0];
|
|
659
|
+
l(this, E)[n] = o;
|
|
660
660
|
} catch (s) {
|
|
661
661
|
console.error(s);
|
|
662
662
|
}
|
|
@@ -690,14 +690,14 @@ async function encodeAsMultipart(e) {
|
|
|
690
690
|
`);
|
|
691
691
|
n.push(`--${t}--\r
|
|
692
692
|
`);
|
|
693
|
-
const
|
|
693
|
+
const o = n.reduce((c, d) => c + d.length, 0), i = new Uint8Array(o);
|
|
694
694
|
let a = 0;
|
|
695
695
|
for (const c of n)
|
|
696
|
-
|
|
696
|
+
i.set(
|
|
697
697
|
typeof c == "string" ? s.encode(c) : c,
|
|
698
698
|
a
|
|
699
699
|
), a += c.length;
|
|
700
|
-
return { bytes:
|
|
700
|
+
return { bytes: i, contentType: r };
|
|
701
701
|
}
|
|
702
702
|
function fileToUint8Array(e) {
|
|
703
703
|
return new Promise((t) => {
|
|
@@ -707,7 +707,7 @@ function fileToUint8Array(e) {
|
|
|
707
707
|
}, r.readAsArrayBuffer(e);
|
|
708
708
|
});
|
|
709
709
|
}
|
|
710
|
-
var m, H, k, v,
|
|
710
|
+
var m, H, k, v, F, p, x, R, U, Q, B, Y, I, K;
|
|
711
711
|
class PHPRequestHandler {
|
|
712
712
|
/**
|
|
713
713
|
* @param php - The PHP instance.
|
|
@@ -720,7 +720,7 @@ class PHPRequestHandler {
|
|
|
720
720
|
* @param fsPath - Absolute path of the static file to serve.
|
|
721
721
|
* @returns The response.
|
|
722
722
|
*/
|
|
723
|
-
u(this,
|
|
723
|
+
u(this, U);
|
|
724
724
|
/**
|
|
725
725
|
* Runs the requested PHP file with all the request and $_SERVER
|
|
726
726
|
* superglobals populated.
|
|
@@ -728,7 +728,7 @@ class PHPRequestHandler {
|
|
|
728
728
|
* @param request - The request.
|
|
729
729
|
* @returns The response.
|
|
730
730
|
*/
|
|
731
|
-
u(this,
|
|
731
|
+
u(this, B);
|
|
732
732
|
/**
|
|
733
733
|
* Resolve the requested path to the filesystem path of the requested PHP file.
|
|
734
734
|
*
|
|
@@ -738,32 +738,33 @@ class PHPRequestHandler {
|
|
|
738
738
|
* @throws {Error} If the requested path doesn't exist.
|
|
739
739
|
* @returns The resolved filesystem path.
|
|
740
740
|
*/
|
|
741
|
-
u(this,
|
|
741
|
+
u(this, I);
|
|
742
742
|
u(this, m, void 0);
|
|
743
743
|
u(this, H, void 0);
|
|
744
744
|
u(this, k, void 0);
|
|
745
745
|
u(this, v, void 0);
|
|
746
|
-
u(this, x, void 0);
|
|
747
|
-
u(this, _, void 0);
|
|
748
746
|
u(this, F, void 0);
|
|
747
|
+
u(this, p, void 0);
|
|
748
|
+
u(this, x, void 0);
|
|
749
749
|
u(this, R, void 0);
|
|
750
750
|
h(this, R, new Semaphore({ concurrency: 1 }));
|
|
751
751
|
const {
|
|
752
752
|
documentRoot: s = "/www/",
|
|
753
|
-
absoluteUrl: n = typeof location == "object" ? location == null ? void 0 : location.href : ""
|
|
753
|
+
absoluteUrl: n = typeof location == "object" ? location == null ? void 0 : location.href : "",
|
|
754
|
+
rewriteRules: o = []
|
|
754
755
|
} = r;
|
|
755
756
|
this.php = t, h(this, m, s);
|
|
756
757
|
const i = new URL(n);
|
|
757
758
|
h(this, k, i.hostname), h(this, v, i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80), h(this, H, (i.protocol || "").replace(":", ""));
|
|
758
|
-
const
|
|
759
|
-
h(this,
|
|
759
|
+
const a = l(this, v) !== 443 && l(this, v) !== 80;
|
|
760
|
+
h(this, F, [
|
|
760
761
|
l(this, k),
|
|
761
|
-
|
|
762
|
-
].join("")), h(this,
|
|
762
|
+
a ? `:${l(this, v)}` : ""
|
|
763
|
+
].join("")), h(this, p, i.pathname.replace(/\/+$/, "")), h(this, x, [
|
|
763
764
|
`${l(this, H)}://`,
|
|
764
|
-
l(this,
|
|
765
|
-
l(this,
|
|
766
|
-
].join(""));
|
|
765
|
+
l(this, F),
|
|
766
|
+
l(this, p)
|
|
767
|
+
].join("")), this.rewriteRules = o;
|
|
767
768
|
}
|
|
768
769
|
/** @inheritDoc */
|
|
769
770
|
pathToInternalUrl(t) {
|
|
@@ -772,14 +773,14 @@ class PHPRequestHandler {
|
|
|
772
773
|
/** @inheritDoc */
|
|
773
774
|
internalUrlToPath(t) {
|
|
774
775
|
const r = new URL(t);
|
|
775
|
-
return r.pathname.startsWith(l(this,
|
|
776
|
+
return r.pathname.startsWith(l(this, p)) && (r.pathname = r.pathname.slice(l(this, p).length)), toRelativeUrl(r);
|
|
776
777
|
}
|
|
777
778
|
get isRequestRunning() {
|
|
778
779
|
return l(this, R).running > 0;
|
|
779
780
|
}
|
|
780
781
|
/** @inheritDoc */
|
|
781
782
|
get absoluteUrl() {
|
|
782
|
-
return l(this,
|
|
783
|
+
return l(this, x);
|
|
783
784
|
}
|
|
784
785
|
/** @inheritDoc */
|
|
785
786
|
get documentRoot() {
|
|
@@ -788,16 +789,17 @@ class PHPRequestHandler {
|
|
|
788
789
|
/** @inheritDoc */
|
|
789
790
|
async request(t) {
|
|
790
791
|
const r = t.url.startsWith("http://") || t.url.startsWith("https://"), s = new URL(
|
|
791
|
-
|
|
792
|
+
// Remove the hash part of the URL as it's not meant for the server.
|
|
793
|
+
t.url.split("#")[0],
|
|
792
794
|
r ? void 0 : DEFAULT_BASE_URL
|
|
793
|
-
), n =
|
|
794
|
-
s.pathname,
|
|
795
|
-
|
|
796
|
-
),
|
|
797
|
-
return seemsLikeAPHPRequestHandlerPath(
|
|
795
|
+
), n = applyRewriteRules(
|
|
796
|
+
removePathPrefix(s.pathname, l(this, p)),
|
|
797
|
+
this.rewriteRules
|
|
798
|
+
), o = `${l(this, m)}${n}`;
|
|
799
|
+
return seemsLikeAPHPRequestHandlerPath(o) ? await f(this, B, Y).call(this, t, s) : f(this, U, Q).call(this, o);
|
|
798
800
|
}
|
|
799
801
|
}
|
|
800
|
-
m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(),
|
|
802
|
+
m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), F = new WeakMap(), p = new WeakMap(), x = new WeakMap(), R = new WeakMap(), U = new WeakSet(), Q = function(t) {
|
|
801
803
|
if (!this.php.fileExists(t))
|
|
802
804
|
return new PHPResponse(
|
|
803
805
|
404,
|
|
@@ -822,8 +824,8 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
822
824
|
},
|
|
823
825
|
r
|
|
824
826
|
);
|
|
825
|
-
},
|
|
826
|
-
var n
|
|
827
|
+
}, B = new WeakSet(), Y = async function(t, r) {
|
|
828
|
+
var n;
|
|
827
829
|
if (l(this, R).running > 0 && ((n = t.headers) == null ? void 0 : n["x-request-issuer"]) === "php")
|
|
828
830
|
return console.warn(
|
|
829
831
|
"Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."
|
|
@@ -836,30 +838,22 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
836
838
|
try {
|
|
837
839
|
this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", l(this, m)), this.php.addServerGlobalEntry(
|
|
838
840
|
"HTTPS",
|
|
839
|
-
l(this,
|
|
841
|
+
l(this, x).startsWith("https://") ? "on" : ""
|
|
840
842
|
);
|
|
841
843
|
let o = "GET";
|
|
842
|
-
const
|
|
843
|
-
host: l(this,
|
|
844
|
+
const i = {
|
|
845
|
+
host: l(this, F),
|
|
844
846
|
...normalizeHeaders(t.headers || {})
|
|
845
847
|
};
|
|
846
|
-
let
|
|
847
|
-
if (typeof
|
|
848
|
+
let a = t.body;
|
|
849
|
+
if (typeof a == "object" && !(a instanceof Uint8Array)) {
|
|
848
850
|
o = "POST";
|
|
849
|
-
const { bytes:
|
|
850
|
-
|
|
851
|
+
const { bytes: d, contentType: _ } = await encodeAsMultipart(a);
|
|
852
|
+
a = d, i["content-type"] = _;
|
|
851
853
|
}
|
|
852
|
-
let
|
|
854
|
+
let c;
|
|
853
855
|
try {
|
|
854
|
-
|
|
855
|
-
if ((i = t.headers) != null && i["x-rewrite-url"])
|
|
856
|
-
try {
|
|
857
|
-
p = new URL(
|
|
858
|
-
t.headers["x-rewrite-url"]
|
|
859
|
-
).pathname;
|
|
860
|
-
} catch {
|
|
861
|
-
}
|
|
862
|
-
d = f(this, N, Z).call(this, p);
|
|
856
|
+
c = f(this, I, K).call(this, r.pathname);
|
|
863
857
|
} catch {
|
|
864
858
|
return new PHPResponse(
|
|
865
859
|
404,
|
|
@@ -870,20 +864,20 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
870
864
|
return await this.php.run({
|
|
871
865
|
relativeUri: ensurePathPrefix(
|
|
872
866
|
toRelativeUrl(r),
|
|
873
|
-
l(this,
|
|
867
|
+
l(this, p)
|
|
874
868
|
),
|
|
875
869
|
protocol: l(this, H),
|
|
876
870
|
method: t.method || o,
|
|
877
|
-
body:
|
|
878
|
-
scriptPath:
|
|
879
|
-
headers:
|
|
871
|
+
body: a,
|
|
872
|
+
scriptPath: c,
|
|
873
|
+
headers: i
|
|
880
874
|
});
|
|
881
875
|
} finally {
|
|
882
876
|
s();
|
|
883
877
|
}
|
|
884
|
-
},
|
|
885
|
-
let r = removePathPrefix(t, l(this,
|
|
886
|
-
r.includes(".php") ? r = r.split(".php")[0] + ".php" : this.php.isDir(`${l(this, m)}${r}`) ? (r.endsWith("/") || (r = `${r}/`), r = `${r}index.php`) : r = "/index.php";
|
|
878
|
+
}, I = new WeakSet(), K = function(t) {
|
|
879
|
+
let r = removePathPrefix(t, l(this, p));
|
|
880
|
+
r = applyRewriteRules(r, this.rewriteRules), r.includes(".php") ? r = r.split(".php")[0] + ".php" : this.php.isDir(`${l(this, m)}${r}`) ? (r.endsWith("/") || (r = `${r}/`), r = `${r}index.php`) : r = "/index.php";
|
|
887
881
|
const s = `${l(this, m)}${r}`;
|
|
888
882
|
if (this.php.fileExists(s))
|
|
889
883
|
return s;
|
|
@@ -938,6 +932,12 @@ function seemsLikeAPHPFile(e) {
|
|
|
938
932
|
function seemsLikeADirectoryRoot(e) {
|
|
939
933
|
return !e.split("/").pop().includes(".");
|
|
940
934
|
}
|
|
935
|
+
function applyRewriteRules(e, t) {
|
|
936
|
+
for (const r of t)
|
|
937
|
+
if (new RegExp(r.match).test(e))
|
|
938
|
+
return e.replace(r.match, r.replacement);
|
|
939
|
+
return e;
|
|
940
|
+
}
|
|
941
941
|
const FileErrorCodes = {
|
|
942
942
|
0: "No error occurred. System call completed successfully.",
|
|
943
943
|
1: "Argument list too long.",
|
|
@@ -1024,15 +1024,15 @@ function getEmscriptenFsError(e) {
|
|
|
1024
1024
|
}
|
|
1025
1025
|
function rethrowFileSystemError(e = "") {
|
|
1026
1026
|
return function(r, s, n) {
|
|
1027
|
-
const
|
|
1028
|
-
n.value = function(...
|
|
1027
|
+
const o = n.value;
|
|
1028
|
+
n.value = function(...i) {
|
|
1029
1029
|
try {
|
|
1030
|
-
return
|
|
1030
|
+
return o.apply(this, i);
|
|
1031
1031
|
} catch (a) {
|
|
1032
1032
|
const c = typeof a == "object" ? a == null ? void 0 : a.errno : null;
|
|
1033
1033
|
if (c in FileErrorCodes) {
|
|
1034
|
-
const d = FileErrorCodes[c],
|
|
1035
|
-
throw new Error(`${
|
|
1034
|
+
const d = FileErrorCodes[c], _ = typeof i[0] == "string" ? i[0] : null, ue = _ !== null ? e.replaceAll("{path}", _) : e;
|
|
1035
|
+
throw new Error(`${ue}: ${d}`, {
|
|
1036
1036
|
cause: a
|
|
1037
1037
|
});
|
|
1038
1038
|
}
|
|
@@ -1044,7 +1044,7 @@ function rethrowFileSystemError(e = "") {
|
|
|
1044
1044
|
const RuntimeId = Symbol("RuntimeId"), loadedRuntimes = /* @__PURE__ */ new Map();
|
|
1045
1045
|
let lastRuntimeId = 0;
|
|
1046
1046
|
async function loadPHPRuntime(e, t = {}) {
|
|
1047
|
-
const [r, s, n] = makePromise(),
|
|
1047
|
+
const [r, s, n] = makePromise(), o = e.init(currentJsRuntime, {
|
|
1048
1048
|
onAbort(a) {
|
|
1049
1049
|
n(a), console.error(a);
|
|
1050
1050
|
},
|
|
@@ -1060,10 +1060,10 @@ async function loadPHPRuntime(e, t = {}) {
|
|
|
1060
1060
|
}
|
|
1061
1061
|
});
|
|
1062
1062
|
await r;
|
|
1063
|
-
const
|
|
1064
|
-
return
|
|
1065
|
-
return loadedRuntimes.delete(
|
|
1066
|
-
},
|
|
1063
|
+
const i = ++lastRuntimeId;
|
|
1064
|
+
return o.id = i, o.originalExit = o._exit, o._exit = function(a) {
|
|
1065
|
+
return loadedRuntimes.delete(i), o.originalExit(a);
|
|
1066
|
+
}, o[RuntimeId] = i, loadedRuntimes.set(i, o), i;
|
|
1067
1067
|
}
|
|
1068
1068
|
function getLoadedRuntime(e) {
|
|
1069
1069
|
return loadedRuntimes.get(e);
|
|
@@ -1078,12 +1078,12 @@ const currentJsRuntime = function() {
|
|
|
1078
1078
|
return e.unshift(t), e;
|
|
1079
1079
|
};
|
|
1080
1080
|
var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyDescriptor, __decorateClass = (e, t, r, s) => {
|
|
1081
|
-
for (var n = s > 1 ? void 0 : s ? __getOwnPropDesc(t, r) : t,
|
|
1082
|
-
(
|
|
1081
|
+
for (var n = s > 1 ? void 0 : s ? __getOwnPropDesc(t, r) : t, o = e.length - 1, i; o >= 0; o--)
|
|
1082
|
+
(i = e[o]) && (n = (s ? i(t, r, n) : i(n)) || n);
|
|
1083
1083
|
return s && n && __defProp(t, r, n), n;
|
|
1084
1084
|
};
|
|
1085
1085
|
const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
|
|
1086
|
-
var S, T, A, y, w, g, P, C, L, X,
|
|
1086
|
+
var S, T, A, y, w, g, P, C, N, Z, L, X, q, ee, O, te, M, re, D, se, $, ne, j, ie, W, oe, z, ae, G, le, V, ce;
|
|
1087
1087
|
class BasePHP {
|
|
1088
1088
|
/**
|
|
1089
1089
|
* Initializes a PHP runtime.
|
|
@@ -1093,10 +1093,11 @@ class BasePHP {
|
|
|
1093
1093
|
* @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
|
|
1094
1094
|
*/
|
|
1095
1095
|
constructor(e, t) {
|
|
1096
|
+
u(this, N);
|
|
1096
1097
|
u(this, L);
|
|
1098
|
+
u(this, q);
|
|
1097
1099
|
u(this, O);
|
|
1098
1100
|
u(this, M);
|
|
1099
|
-
u(this, q);
|
|
1100
1101
|
u(this, D);
|
|
1101
1102
|
u(this, $);
|
|
1102
1103
|
u(this, j);
|
|
@@ -1104,7 +1105,6 @@ class BasePHP {
|
|
|
1104
1105
|
u(this, z);
|
|
1105
1106
|
u(this, G);
|
|
1106
1107
|
u(this, V);
|
|
1107
|
-
u(this, J);
|
|
1108
1108
|
u(this, S, void 0);
|
|
1109
1109
|
u(this, T, void 0);
|
|
1110
1110
|
u(this, A, void 0);
|
|
@@ -1218,29 +1218,36 @@ class BasePHP {
|
|
|
1218
1218
|
const t = await this.semaphore.acquire();
|
|
1219
1219
|
let r;
|
|
1220
1220
|
try {
|
|
1221
|
-
if (l(this, y) || (f(this,
|
|
1221
|
+
if (l(this, y) || (f(this, N, Z).call(this), h(this, y, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
|
|
1222
1222
|
throw new Error(
|
|
1223
1223
|
`The script path "${e.scriptPath}" does not exist.`
|
|
1224
1224
|
);
|
|
1225
|
-
f(this,
|
|
1225
|
+
f(this, j, ie).call(this, e.scriptPath || ""), f(this, q, ee).call(this, e.relativeUri || ""), f(this, M, re).call(this, e.method || "GET");
|
|
1226
1226
|
const s = normalizeHeaders(e.headers || {}), n = s.host || "example.com:443";
|
|
1227
|
-
f(this,
|
|
1228
|
-
const
|
|
1229
|
-
for (const a in
|
|
1230
|
-
f(this,
|
|
1231
|
-
const
|
|
1232
|
-
if (
|
|
1227
|
+
f(this, O, te).call(this, n, e.protocol || "http"), f(this, D, se).call(this, s), e.body && (r = f(this, $, ne).call(this, e.body)), typeof e.code == "string" && f(this, G, le).call(this, " ?>" + e.code), f(this, W, oe).call(this);
|
|
1228
|
+
const o = e.env || {};
|
|
1229
|
+
for (const a in o)
|
|
1230
|
+
f(this, z, ae).call(this, a, o[a]);
|
|
1231
|
+
const i = await f(this, V, ce).call(this);
|
|
1232
|
+
if (i.exitCode !== 0) {
|
|
1233
1233
|
const a = {
|
|
1234
|
-
stdout:
|
|
1235
|
-
stderr:
|
|
1234
|
+
stdout: i.text,
|
|
1235
|
+
stderr: i.errors
|
|
1236
1236
|
};
|
|
1237
1237
|
console.warn("PHP.run() output was:", a);
|
|
1238
1238
|
const c = new Error(
|
|
1239
|
-
`PHP.run() failed with exit code ${
|
|
1239
|
+
`PHP.run() failed with exit code ${i.exitCode} and the following output: ` + i.errors
|
|
1240
1240
|
);
|
|
1241
|
-
throw c.output = a, console.error(c), c;
|
|
1241
|
+
throw c.output = a, c.source = "request", console.error(c), c;
|
|
1242
1242
|
}
|
|
1243
|
-
return
|
|
1243
|
+
return i;
|
|
1244
|
+
} catch (s) {
|
|
1245
|
+
throw this.dispatchEvent({
|
|
1246
|
+
type: "request.error",
|
|
1247
|
+
error: s,
|
|
1248
|
+
// Distinguish between PHP request and PHP-wasm errors
|
|
1249
|
+
source: s.source ?? "php-wasm"
|
|
1250
|
+
}), s;
|
|
1244
1251
|
} finally {
|
|
1245
1252
|
try {
|
|
1246
1253
|
r && this[__private__dont__use].free(r);
|
|
@@ -1364,7 +1371,7 @@ class BasePHP {
|
|
|
1364
1371
|
h(this, y, !1), h(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
|
|
1365
1372
|
}
|
|
1366
1373
|
}
|
|
1367
|
-
S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w = new WeakMap(), g = new WeakMap(), P = new WeakMap(), C = new WeakMap(),
|
|
1374
|
+
S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w = new WeakMap(), g = new WeakMap(), P = new WeakMap(), C = new WeakMap(), N = new WeakSet(), Z = function() {
|
|
1368
1375
|
if (this.setPhpIniEntry("auto_prepend_file", "/internal/consts.php"), this.fileExists("/internal/consts.php") || this.writeFile(
|
|
1369
1376
|
"/internal/consts.php",
|
|
1370
1377
|
`<?php
|
|
@@ -1389,7 +1396,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1389
1396
|
);
|
|
1390
1397
|
}
|
|
1391
1398
|
this[__private__dont__use].ccall("php_wasm_init", null, [], []);
|
|
1392
|
-
},
|
|
1399
|
+
}, L = new WeakSet(), X = function() {
|
|
1393
1400
|
const e = "/internal/headers.json";
|
|
1394
1401
|
if (!this.fileExists(e))
|
|
1395
1402
|
throw new Error(
|
|
@@ -1399,14 +1406,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1399
1406
|
for (const s of t.headers) {
|
|
1400
1407
|
if (!s.includes(": "))
|
|
1401
1408
|
continue;
|
|
1402
|
-
const n = s.indexOf(": "),
|
|
1403
|
-
|
|
1409
|
+
const n = s.indexOf(": "), o = s.substring(0, n).toLowerCase(), i = s.substring(n + 2);
|
|
1410
|
+
o in r || (r[o] = []), r[o].push(i);
|
|
1404
1411
|
}
|
|
1405
1412
|
return {
|
|
1406
1413
|
headers: r,
|
|
1407
1414
|
httpStatusCode: t.status
|
|
1408
1415
|
};
|
|
1409
|
-
},
|
|
1416
|
+
}, q = new WeakSet(), ee = function(e) {
|
|
1410
1417
|
if (this[__private__dont__use].ccall(
|
|
1411
1418
|
"wasm_set_request_uri",
|
|
1412
1419
|
null,
|
|
@@ -1421,7 +1428,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1421
1428
|
[t]
|
|
1422
1429
|
);
|
|
1423
1430
|
}
|
|
1424
|
-
},
|
|
1431
|
+
}, O = new WeakSet(), te = function(e, t) {
|
|
1425
1432
|
this[__private__dont__use].ccall(
|
|
1426
1433
|
"wasm_set_request_host",
|
|
1427
1434
|
null,
|
|
@@ -1439,14 +1446,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1439
1446
|
[NUMBER],
|
|
1440
1447
|
[r]
|
|
1441
1448
|
), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
|
|
1442
|
-
},
|
|
1449
|
+
}, M = new WeakSet(), re = function(e) {
|
|
1443
1450
|
this[__private__dont__use].ccall(
|
|
1444
1451
|
"wasm_set_request_method",
|
|
1445
1452
|
null,
|
|
1446
1453
|
[STRING],
|
|
1447
1454
|
[e]
|
|
1448
1455
|
);
|
|
1449
|
-
},
|
|
1456
|
+
}, D = new WeakSet(), se = function(e) {
|
|
1450
1457
|
e.cookie && this[__private__dont__use].ccall(
|
|
1451
1458
|
"wasm_set_cookies",
|
|
1452
1459
|
null,
|
|
@@ -1470,7 +1477,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1470
1477
|
e[t]
|
|
1471
1478
|
);
|
|
1472
1479
|
}
|
|
1473
|
-
},
|
|
1480
|
+
}, $ = new WeakSet(), ne = function(e) {
|
|
1474
1481
|
let t, r;
|
|
1475
1482
|
typeof e == "string" ? (console.warn(
|
|
1476
1483
|
"Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"
|
|
@@ -1493,14 +1500,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1493
1500
|
[NUMBER],
|
|
1494
1501
|
[r]
|
|
1495
1502
|
), s;
|
|
1496
|
-
},
|
|
1503
|
+
}, j = new WeakSet(), ie = function(e) {
|
|
1497
1504
|
this[__private__dont__use].ccall(
|
|
1498
1505
|
"wasm_set_path_translated",
|
|
1499
1506
|
null,
|
|
1500
1507
|
[STRING],
|
|
1501
1508
|
[e]
|
|
1502
1509
|
);
|
|
1503
|
-
},
|
|
1510
|
+
}, W = new WeakSet(), oe = function() {
|
|
1504
1511
|
for (const e in l(this, g))
|
|
1505
1512
|
this[__private__dont__use].ccall(
|
|
1506
1513
|
"wasm_add_SERVER_entry",
|
|
@@ -1508,30 +1515,30 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1508
1515
|
[STRING, STRING],
|
|
1509
1516
|
[e, l(this, g)[e]]
|
|
1510
1517
|
);
|
|
1511
|
-
},
|
|
1518
|
+
}, z = new WeakSet(), ae = function(e, t) {
|
|
1512
1519
|
this[__private__dont__use].ccall(
|
|
1513
1520
|
"wasm_add_ENV_entry",
|
|
1514
1521
|
null,
|
|
1515
1522
|
[STRING, STRING],
|
|
1516
1523
|
[e, t]
|
|
1517
1524
|
);
|
|
1518
|
-
},
|
|
1525
|
+
}, G = new WeakSet(), le = function(e) {
|
|
1519
1526
|
this[__private__dont__use].ccall(
|
|
1520
1527
|
"wasm_set_php_code",
|
|
1521
1528
|
null,
|
|
1522
1529
|
[STRING],
|
|
1523
1530
|
[e]
|
|
1524
1531
|
);
|
|
1525
|
-
},
|
|
1532
|
+
}, V = new WeakSet(), ce = async function() {
|
|
1526
1533
|
var n;
|
|
1527
1534
|
let e, t;
|
|
1528
1535
|
try {
|
|
1529
|
-
e = await new Promise((
|
|
1536
|
+
e = await new Promise((o, i) => {
|
|
1530
1537
|
var c;
|
|
1531
1538
|
t = (d) => {
|
|
1532
1539
|
console.error(d), console.error(d.error);
|
|
1533
|
-
const
|
|
1534
|
-
|
|
1540
|
+
const _ = new Error("Rethrown");
|
|
1541
|
+
_.cause = d.error, _.betterMessage = d.message, i(_);
|
|
1535
1542
|
}, (c = l(this, w)) == null || c.addEventListener(
|
|
1536
1543
|
"error",
|
|
1537
1544
|
t
|
|
@@ -1543,9 +1550,9 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1543
1550
|
[],
|
|
1544
1551
|
{ async: !0 }
|
|
1545
1552
|
);
|
|
1546
|
-
return a instanceof Promise ? a.then(
|
|
1553
|
+
return a instanceof Promise ? a.then(o, i) : o(a);
|
|
1547
1554
|
});
|
|
1548
|
-
} catch (
|
|
1555
|
+
} catch (o) {
|
|
1549
1556
|
for (const d in this)
|
|
1550
1557
|
typeof this[d] == "function" && (this[d] = () => {
|
|
1551
1558
|
throw new Error(
|
|
@@ -1553,12 +1560,12 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1553
1560
|
);
|
|
1554
1561
|
});
|
|
1555
1562
|
this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
|
|
1556
|
-
const
|
|
1557
|
-
throw c.cause =
|
|
1563
|
+
const i = o, a = "betterMessage" in i ? i.betterMessage : i.message, c = new Error(a);
|
|
1564
|
+
throw c.cause = i, console.error(c), c;
|
|
1558
1565
|
} finally {
|
|
1559
1566
|
(n = l(this, w)) == null || n.removeEventListener("error", t), h(this, g, {});
|
|
1560
1567
|
}
|
|
1561
|
-
const { headers: r, httpStatusCode: s } = f(this,
|
|
1568
|
+
const { headers: r, httpStatusCode: s } = f(this, L, X).call(this);
|
|
1562
1569
|
return new PHPResponse(
|
|
1563
1570
|
s,
|
|
1564
1571
|
r,
|
|
@@ -1617,9 +1624,9 @@ function copyFS(e, t, r) {
|
|
|
1617
1624
|
return;
|
|
1618
1625
|
}
|
|
1619
1626
|
t.mkdirTree(r);
|
|
1620
|
-
const n = e.readdir(r).filter((
|
|
1621
|
-
for (const
|
|
1622
|
-
copyFS(e, t, joinPaths(r,
|
|
1627
|
+
const n = e.readdir(r).filter((o) => o !== "." && o !== "..");
|
|
1628
|
+
for (const o of n)
|
|
1629
|
+
copyFS(e, t, joinPaths(r, o));
|
|
1623
1630
|
}
|
|
1624
1631
|
function isLocalPHP(e) {
|
|
1625
1632
|
return !(e instanceof BasePHP);
|
|
@@ -1637,11 +1644,11 @@ function rotatePHPRuntime({
|
|
|
1637
1644
|
if (++s < r)
|
|
1638
1645
|
return;
|
|
1639
1646
|
s = 0;
|
|
1640
|
-
const
|
|
1647
|
+
const o = await e.semaphore.acquire();
|
|
1641
1648
|
try {
|
|
1642
1649
|
e.hotSwapPHPRuntime(await t());
|
|
1643
1650
|
} finally {
|
|
1644
|
-
|
|
1651
|
+
o();
|
|
1645
1652
|
}
|
|
1646
1653
|
}
|
|
1647
1654
|
return e.addEventListener("request.end", n), function() {
|
|
@@ -1650,9 +1657,9 @@ function rotatePHPRuntime({
|
|
|
1650
1657
|
}
|
|
1651
1658
|
async function writeFiles(e, t, r, { rmRoot: s = !1 } = {}) {
|
|
1652
1659
|
s && await e.isDir(t) && await e.rmdir(t, { recursive: !0 });
|
|
1653
|
-
for (const [n,
|
|
1654
|
-
const
|
|
1655
|
-
await e.fileExists(dirname(
|
|
1660
|
+
for (const [n, o] of Object.entries(r)) {
|
|
1661
|
+
const i = joinPaths(t, n);
|
|
1662
|
+
await e.fileExists(dirname(i)) || await e.mkdir(dirname(i)), await e.writeFile(i, o);
|
|
1656
1663
|
}
|
|
1657
1664
|
}
|
|
1658
1665
|
export {
|
|
@@ -1668,6 +1675,7 @@ export {
|
|
|
1668
1675
|
SupportedPHPVersionsList,
|
|
1669
1676
|
UnhandledRejectionsTarget,
|
|
1670
1677
|
__private__dont__use,
|
|
1678
|
+
applyRewriteRules,
|
|
1671
1679
|
ensurePathPrefix,
|
|
1672
1680
|
isExitCodeZero,
|
|
1673
1681
|
isLocalPHP,
|
package/lib/index.d.ts
CHANGED
|
@@ -16,8 +16,8 @@ export type { DataModule, EmscriptenOptions, PHPLoaderModule, PHPRuntime, PHPRun
|
|
|
16
16
|
export { rethrowFileSystemError } from './rethrow-file-system-error';
|
|
17
17
|
export { isLocalPHP } from './is-local-php';
|
|
18
18
|
export { isRemotePHP } from './is-remote-php';
|
|
19
|
-
export type { PHPRequestHandlerConfiguration } from './php-request-handler';
|
|
20
|
-
export { PHPRequestHandler } from './php-request-handler';
|
|
19
|
+
export type { PHPRequestHandlerConfiguration, RewriteRule, } from './php-request-handler';
|
|
20
|
+
export { PHPRequestHandler, applyRewriteRules } from './php-request-handler';
|
|
21
21
|
export type { PHPBrowserConfiguration } from './php-browser';
|
|
22
22
|
export { PHPBrowser } from './php-browser';
|
|
23
23
|
export { rotatePHPRuntime } from './rotate-php-runtime';
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { BasePHP } from './base-php';
|
|
2
2
|
import { PHPResponse } from './php-response';
|
|
3
3
|
import { PHPRequest, RequestHandler } from './universal-php';
|
|
4
|
+
export type RewriteRule = {
|
|
5
|
+
match: RegExp;
|
|
6
|
+
replacement: string;
|
|
7
|
+
};
|
|
4
8
|
export interface PHPRequestHandlerConfiguration {
|
|
5
9
|
/**
|
|
6
10
|
* The directory in the PHP filesystem where the server will look
|
|
@@ -11,10 +15,15 @@ export interface PHPRequestHandlerConfiguration {
|
|
|
11
15
|
* Request Handler URL. Used to populate $_SERVER details like HTTP_HOST.
|
|
12
16
|
*/
|
|
13
17
|
absoluteUrl?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Rewrite rules
|
|
20
|
+
*/
|
|
21
|
+
rewriteRules?: RewriteRule[];
|
|
14
22
|
}
|
|
15
23
|
/** @inheritDoc */
|
|
16
24
|
export declare class PHPRequestHandler implements RequestHandler {
|
|
17
25
|
#private;
|
|
26
|
+
rewriteRules: RewriteRule[];
|
|
18
27
|
/**
|
|
19
28
|
* The PHP instance
|
|
20
29
|
*/
|
|
@@ -53,3 +62,11 @@ export declare class PHPRequestHandler implements RequestHandler {
|
|
|
53
62
|
* @returns Whether the path seems like a PHP server path.
|
|
54
63
|
*/
|
|
55
64
|
export declare function seemsLikeAPHPRequestHandlerPath(path: string): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Applies the given rewrite rules to the given path.
|
|
67
|
+
*
|
|
68
|
+
* @param path The path to apply the rules to.
|
|
69
|
+
* @param rules The rules to apply.
|
|
70
|
+
* @returns The path with the rules applied.
|
|
71
|
+
*/
|
|
72
|
+
export declare function applyRewriteRules(path: string, rules: RewriteRule[]): string;
|
package/lib/universal-php.d.ts
CHANGED
|
@@ -6,6 +6,14 @@ import { PHPResponse } from './php-response';
|
|
|
6
6
|
export interface PHPRequestEndEvent {
|
|
7
7
|
type: 'request.end';
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Represents an error event related to the PHP request.
|
|
11
|
+
*/
|
|
12
|
+
export interface PHPRequestErrorEvent {
|
|
13
|
+
type: 'request.error';
|
|
14
|
+
error: Error;
|
|
15
|
+
source?: 'request' | 'php-wasm';
|
|
16
|
+
}
|
|
9
17
|
/**
|
|
10
18
|
* Represents a PHP runtime initialization event.
|
|
11
19
|
*/
|
|
@@ -23,7 +31,7 @@ export interface PHPRuntimeBeforeDestroyEvent {
|
|
|
23
31
|
* This is intentionally not an extension of CustomEvent
|
|
24
32
|
* to make it isomorphic between different JavaScript runtimes.
|
|
25
33
|
*/
|
|
26
|
-
export type PHPEvent = PHPRequestEndEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeDestroyEvent;
|
|
34
|
+
export type PHPEvent = PHPRequestEndEvent | PHPRequestErrorEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeDestroyEvent;
|
|
27
35
|
/**
|
|
28
36
|
* A callback function that handles PHP events.
|
|
29
37
|
*/
|
|
@@ -470,11 +478,6 @@ export interface PHPRunOptions {
|
|
|
470
478
|
* The code snippet to eval instead of a php file.
|
|
471
479
|
*/
|
|
472
480
|
code?: string;
|
|
473
|
-
/**
|
|
474
|
-
* Whether to throw an error if the PHP process exits with a non-zero code
|
|
475
|
-
* or outputs to stderr.
|
|
476
|
-
*/
|
|
477
|
-
throwOnError?: boolean;
|
|
478
481
|
}
|
|
479
482
|
/**
|
|
480
483
|
* Output of the PHP.wasm runtime.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@php-wasm/universal",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"description": "PHP.wasm – emscripten bindings for PHP",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"main": "./index.cjs",
|
|
37
37
|
"module": "./index.js",
|
|
38
38
|
"license": "GPL-2.0-or-later",
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "f6b98ad6d05617ee8cb1234c21318fdde17a6e56",
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=18.18.2",
|
|
42
42
|
"npm": ">=8.11.0"
|