@php-wasm/universal 0.6.7 → 0.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +4 -4
- package/index.js +157 -152
- package/lib/index.d.ts +2 -2
- package/lib/php-request-handler.d.ts +17 -0
- package/lib/universal-php.d.ts +8 -1
- 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,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,O,ee,q,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,O);u(this,q);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,O,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,q,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(e.throwOnError&&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,console.error(c),c}return i}catch(s){throw this.dispatchEvent({type:"request.error",error:s}),s}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){l(this,g)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/internal/consts.json")&&this.readFileAsText("/internal/consts.json")||"{}")}catch{}this.writeFile("/internal/consts.json",JSON.stringify({...r,[e]:t}))}mkdir(e){this[__private__dont__use].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[__private__dont__use].FS.readFile(e)}writeFile(e,t){this[__private__dont__use].FS.writeFile(e,t)}unlink(e){this[__private__dont__use].FS.unlink(e)}mv(e,t){try{this[__private__dont__use].FS.rename(e,t)}catch(r){const s=getEmscriptenFsError(r);throw s?new Error(`Could not move ${e} to ${t}: ${s}`,{cause:r}):r}}rmdir(e,t={recursive:!0}){t!=null&&t.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[__private__dont__use].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[__private__dont__use].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(n=>`${s}/${n}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[__private__dont__use].FS.isDir(this[__private__dont__use].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[__private__dont__use].FS.lookupPath(e),!0}catch{return!1}}hotSwapPHPRuntime(e){const t=this[__private__dont__use].FS;try{this.exit()}catch{}if(this.initializeRuntime(e),l(this,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}},O=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])}},q=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() {
|
|
@@ -790,14 +791,14 @@ class PHPRequestHandler {
|
|
|
790
791
|
const r = t.url.startsWith("http://") || t.url.startsWith("https://"), s = new URL(
|
|
791
792
|
t.url,
|
|
792
793
|
r ? void 0 : DEFAULT_BASE_URL
|
|
793
|
-
), n =
|
|
794
|
-
s.pathname,
|
|
795
|
-
|
|
796
|
-
),
|
|
797
|
-
return seemsLikeAPHPRequestHandlerPath(
|
|
794
|
+
), n = applyRewriteRules(
|
|
795
|
+
removePathPrefix(s.pathname, l(this, p)),
|
|
796
|
+
this.rewriteRules
|
|
797
|
+
), o = `${l(this, m)}${n}`;
|
|
798
|
+
return seemsLikeAPHPRequestHandlerPath(o) ? await f(this, B, Y).call(this, t, s) : f(this, U, Q).call(this, o);
|
|
798
799
|
}
|
|
799
800
|
}
|
|
800
|
-
m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(),
|
|
801
|
+
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
802
|
if (!this.php.fileExists(t))
|
|
802
803
|
return new PHPResponse(
|
|
803
804
|
404,
|
|
@@ -822,8 +823,8 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
822
823
|
},
|
|
823
824
|
r
|
|
824
825
|
);
|
|
825
|
-
},
|
|
826
|
-
var n
|
|
826
|
+
}, B = new WeakSet(), Y = async function(t, r) {
|
|
827
|
+
var n;
|
|
827
828
|
if (l(this, R).running > 0 && ((n = t.headers) == null ? void 0 : n["x-request-issuer"]) === "php")
|
|
828
829
|
return console.warn(
|
|
829
830
|
"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 +837,22 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
836
837
|
try {
|
|
837
838
|
this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", l(this, m)), this.php.addServerGlobalEntry(
|
|
838
839
|
"HTTPS",
|
|
839
|
-
l(this,
|
|
840
|
+
l(this, x).startsWith("https://") ? "on" : ""
|
|
840
841
|
);
|
|
841
842
|
let o = "GET";
|
|
842
|
-
const
|
|
843
|
-
host: l(this,
|
|
843
|
+
const i = {
|
|
844
|
+
host: l(this, F),
|
|
844
845
|
...normalizeHeaders(t.headers || {})
|
|
845
846
|
};
|
|
846
|
-
let
|
|
847
|
-
if (typeof
|
|
847
|
+
let a = t.body;
|
|
848
|
+
if (typeof a == "object" && !(a instanceof Uint8Array)) {
|
|
848
849
|
o = "POST";
|
|
849
|
-
const { bytes:
|
|
850
|
-
|
|
850
|
+
const { bytes: d, contentType: _ } = await encodeAsMultipart(a);
|
|
851
|
+
a = d, i["content-type"] = _;
|
|
851
852
|
}
|
|
852
|
-
let
|
|
853
|
+
let c;
|
|
853
854
|
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);
|
|
855
|
+
c = f(this, I, K).call(this, r.pathname);
|
|
863
856
|
} catch {
|
|
864
857
|
return new PHPResponse(
|
|
865
858
|
404,
|
|
@@ -870,20 +863,20 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
870
863
|
return await this.php.run({
|
|
871
864
|
relativeUri: ensurePathPrefix(
|
|
872
865
|
toRelativeUrl(r),
|
|
873
|
-
l(this,
|
|
866
|
+
l(this, p)
|
|
874
867
|
),
|
|
875
868
|
protocol: l(this, H),
|
|
876
869
|
method: t.method || o,
|
|
877
|
-
body:
|
|
878
|
-
scriptPath:
|
|
879
|
-
headers:
|
|
870
|
+
body: a,
|
|
871
|
+
scriptPath: c,
|
|
872
|
+
headers: i
|
|
880
873
|
});
|
|
881
874
|
} finally {
|
|
882
875
|
s();
|
|
883
876
|
}
|
|
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";
|
|
877
|
+
}, I = new WeakSet(), K = function(t) {
|
|
878
|
+
let r = removePathPrefix(t, l(this, p));
|
|
879
|
+
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
880
|
const s = `${l(this, m)}${r}`;
|
|
888
881
|
if (this.php.fileExists(s))
|
|
889
882
|
return s;
|
|
@@ -938,6 +931,12 @@ function seemsLikeAPHPFile(e) {
|
|
|
938
931
|
function seemsLikeADirectoryRoot(e) {
|
|
939
932
|
return !e.split("/").pop().includes(".");
|
|
940
933
|
}
|
|
934
|
+
function applyRewriteRules(e, t) {
|
|
935
|
+
for (const r of t)
|
|
936
|
+
if (new RegExp(r.match).test(e))
|
|
937
|
+
return e.replace(r.match, r.replacement);
|
|
938
|
+
return e;
|
|
939
|
+
}
|
|
941
940
|
const FileErrorCodes = {
|
|
942
941
|
0: "No error occurred. System call completed successfully.",
|
|
943
942
|
1: "Argument list too long.",
|
|
@@ -1024,15 +1023,15 @@ function getEmscriptenFsError(e) {
|
|
|
1024
1023
|
}
|
|
1025
1024
|
function rethrowFileSystemError(e = "") {
|
|
1026
1025
|
return function(r, s, n) {
|
|
1027
|
-
const
|
|
1028
|
-
n.value = function(...
|
|
1026
|
+
const o = n.value;
|
|
1027
|
+
n.value = function(...i) {
|
|
1029
1028
|
try {
|
|
1030
|
-
return
|
|
1029
|
+
return o.apply(this, i);
|
|
1031
1030
|
} catch (a) {
|
|
1032
1031
|
const c = typeof a == "object" ? a == null ? void 0 : a.errno : null;
|
|
1033
1032
|
if (c in FileErrorCodes) {
|
|
1034
|
-
const d = FileErrorCodes[c],
|
|
1035
|
-
throw new Error(`${
|
|
1033
|
+
const d = FileErrorCodes[c], _ = typeof i[0] == "string" ? i[0] : null, ue = _ !== null ? e.replaceAll("{path}", _) : e;
|
|
1034
|
+
throw new Error(`${ue}: ${d}`, {
|
|
1036
1035
|
cause: a
|
|
1037
1036
|
});
|
|
1038
1037
|
}
|
|
@@ -1044,7 +1043,7 @@ function rethrowFileSystemError(e = "") {
|
|
|
1044
1043
|
const RuntimeId = Symbol("RuntimeId"), loadedRuntimes = /* @__PURE__ */ new Map();
|
|
1045
1044
|
let lastRuntimeId = 0;
|
|
1046
1045
|
async function loadPHPRuntime(e, t = {}) {
|
|
1047
|
-
const [r, s, n] = makePromise(),
|
|
1046
|
+
const [r, s, n] = makePromise(), o = e.init(currentJsRuntime, {
|
|
1048
1047
|
onAbort(a) {
|
|
1049
1048
|
n(a), console.error(a);
|
|
1050
1049
|
},
|
|
@@ -1060,10 +1059,10 @@ async function loadPHPRuntime(e, t = {}) {
|
|
|
1060
1059
|
}
|
|
1061
1060
|
});
|
|
1062
1061
|
await r;
|
|
1063
|
-
const
|
|
1064
|
-
return
|
|
1065
|
-
return loadedRuntimes.delete(
|
|
1066
|
-
},
|
|
1062
|
+
const i = ++lastRuntimeId;
|
|
1063
|
+
return o.id = i, o.originalExit = o._exit, o._exit = function(a) {
|
|
1064
|
+
return loadedRuntimes.delete(i), o.originalExit(a);
|
|
1065
|
+
}, o[RuntimeId] = i, loadedRuntimes.set(i, o), i;
|
|
1067
1066
|
}
|
|
1068
1067
|
function getLoadedRuntime(e) {
|
|
1069
1068
|
return loadedRuntimes.get(e);
|
|
@@ -1078,12 +1077,12 @@ const currentJsRuntime = function() {
|
|
|
1078
1077
|
return e.unshift(t), e;
|
|
1079
1078
|
};
|
|
1080
1079
|
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
|
-
(
|
|
1080
|
+
for (var n = s > 1 ? void 0 : s ? __getOwnPropDesc(t, r) : t, o = e.length - 1, i; o >= 0; o--)
|
|
1081
|
+
(i = e[o]) && (n = (s ? i(t, r, n) : i(n)) || n);
|
|
1083
1082
|
return s && n && __defProp(t, r, n), n;
|
|
1084
1083
|
};
|
|
1085
1084
|
const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
|
|
1086
|
-
var S, T, A, y, w, g, P, C, L, X, O, ee,
|
|
1085
|
+
var S, T, A, y, w, g, P, C, N, Z, L, X, O, ee, q, te, M, re, D, se, $, ne, j, ie, W, oe, z, ae, G, le, V, ce;
|
|
1087
1086
|
class BasePHP {
|
|
1088
1087
|
/**
|
|
1089
1088
|
* Initializes a PHP runtime.
|
|
@@ -1093,10 +1092,11 @@ class BasePHP {
|
|
|
1093
1092
|
* @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
|
|
1094
1093
|
*/
|
|
1095
1094
|
constructor(e, t) {
|
|
1095
|
+
u(this, N);
|
|
1096
1096
|
u(this, L);
|
|
1097
1097
|
u(this, O);
|
|
1098
|
-
u(this, M);
|
|
1099
1098
|
u(this, q);
|
|
1099
|
+
u(this, M);
|
|
1100
1100
|
u(this, D);
|
|
1101
1101
|
u(this, $);
|
|
1102
1102
|
u(this, j);
|
|
@@ -1104,7 +1104,6 @@ class BasePHP {
|
|
|
1104
1104
|
u(this, z);
|
|
1105
1105
|
u(this, G);
|
|
1106
1106
|
u(this, V);
|
|
1107
|
-
u(this, J);
|
|
1108
1107
|
u(this, S, void 0);
|
|
1109
1108
|
u(this, T, void 0);
|
|
1110
1109
|
u(this, A, void 0);
|
|
@@ -1218,29 +1217,34 @@ class BasePHP {
|
|
|
1218
1217
|
const t = await this.semaphore.acquire();
|
|
1219
1218
|
let r;
|
|
1220
1219
|
try {
|
|
1221
|
-
if (l(this, y) || (f(this,
|
|
1220
|
+
if (l(this, y) || (f(this, N, Z).call(this), h(this, y, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
|
|
1222
1221
|
throw new Error(
|
|
1223
1222
|
`The script path "${e.scriptPath}" does not exist.`
|
|
1224
1223
|
);
|
|
1225
|
-
f(this,
|
|
1224
|
+
f(this, j, ie).call(this, e.scriptPath || ""), f(this, O, ee).call(this, e.relativeUri || ""), f(this, M, re).call(this, e.method || "GET");
|
|
1226
1225
|
const s = normalizeHeaders(e.headers || {}), n = s.host || "example.com:443";
|
|
1227
|
-
f(this, q,
|
|
1228
|
-
const
|
|
1229
|
-
for (const a in
|
|
1230
|
-
f(this,
|
|
1231
|
-
const
|
|
1232
|
-
if (e.throwOnError &&
|
|
1226
|
+
f(this, q, 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);
|
|
1227
|
+
const o = e.env || {};
|
|
1228
|
+
for (const a in o)
|
|
1229
|
+
f(this, z, ae).call(this, a, o[a]);
|
|
1230
|
+
const i = await f(this, V, ce).call(this);
|
|
1231
|
+
if (e.throwOnError && i.exitCode !== 0) {
|
|
1233
1232
|
const a = {
|
|
1234
|
-
stdout:
|
|
1235
|
-
stderr:
|
|
1233
|
+
stdout: i.text,
|
|
1234
|
+
stderr: i.errors
|
|
1236
1235
|
};
|
|
1237
1236
|
console.warn("PHP.run() output was:", a);
|
|
1238
1237
|
const c = new Error(
|
|
1239
|
-
`PHP.run() failed with exit code ${
|
|
1238
|
+
`PHP.run() failed with exit code ${i.exitCode} and the following output: ` + i.errors
|
|
1240
1239
|
);
|
|
1241
1240
|
throw c.output = a, console.error(c), c;
|
|
1242
1241
|
}
|
|
1243
|
-
return
|
|
1242
|
+
return i;
|
|
1243
|
+
} catch (s) {
|
|
1244
|
+
throw this.dispatchEvent({
|
|
1245
|
+
type: "request.error",
|
|
1246
|
+
error: s
|
|
1247
|
+
}), s;
|
|
1244
1248
|
} finally {
|
|
1245
1249
|
try {
|
|
1246
1250
|
r && this[__private__dont__use].free(r);
|
|
@@ -1364,7 +1368,7 @@ class BasePHP {
|
|
|
1364
1368
|
h(this, y, !1), h(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
|
|
1365
1369
|
}
|
|
1366
1370
|
}
|
|
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(),
|
|
1371
|
+
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
1372
|
if (this.setPhpIniEntry("auto_prepend_file", "/internal/consts.php"), this.fileExists("/internal/consts.php") || this.writeFile(
|
|
1369
1373
|
"/internal/consts.php",
|
|
1370
1374
|
`<?php
|
|
@@ -1389,7 +1393,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1389
1393
|
);
|
|
1390
1394
|
}
|
|
1391
1395
|
this[__private__dont__use].ccall("php_wasm_init", null, [], []);
|
|
1392
|
-
},
|
|
1396
|
+
}, L = new WeakSet(), X = function() {
|
|
1393
1397
|
const e = "/internal/headers.json";
|
|
1394
1398
|
if (!this.fileExists(e))
|
|
1395
1399
|
throw new Error(
|
|
@@ -1399,14 +1403,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1399
1403
|
for (const s of t.headers) {
|
|
1400
1404
|
if (!s.includes(": "))
|
|
1401
1405
|
continue;
|
|
1402
|
-
const n = s.indexOf(": "),
|
|
1403
|
-
|
|
1406
|
+
const n = s.indexOf(": "), o = s.substring(0, n).toLowerCase(), i = s.substring(n + 2);
|
|
1407
|
+
o in r || (r[o] = []), r[o].push(i);
|
|
1404
1408
|
}
|
|
1405
1409
|
return {
|
|
1406
1410
|
headers: r,
|
|
1407
1411
|
httpStatusCode: t.status
|
|
1408
1412
|
};
|
|
1409
|
-
},
|
|
1413
|
+
}, O = new WeakSet(), ee = function(e) {
|
|
1410
1414
|
if (this[__private__dont__use].ccall(
|
|
1411
1415
|
"wasm_set_request_uri",
|
|
1412
1416
|
null,
|
|
@@ -1421,7 +1425,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1421
1425
|
[t]
|
|
1422
1426
|
);
|
|
1423
1427
|
}
|
|
1424
|
-
}, q = new WeakSet(),
|
|
1428
|
+
}, q = new WeakSet(), te = function(e, t) {
|
|
1425
1429
|
this[__private__dont__use].ccall(
|
|
1426
1430
|
"wasm_set_request_host",
|
|
1427
1431
|
null,
|
|
@@ -1439,14 +1443,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1439
1443
|
[NUMBER],
|
|
1440
1444
|
[r]
|
|
1441
1445
|
), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
|
|
1442
|
-
},
|
|
1446
|
+
}, M = new WeakSet(), re = function(e) {
|
|
1443
1447
|
this[__private__dont__use].ccall(
|
|
1444
1448
|
"wasm_set_request_method",
|
|
1445
1449
|
null,
|
|
1446
1450
|
[STRING],
|
|
1447
1451
|
[e]
|
|
1448
1452
|
);
|
|
1449
|
-
},
|
|
1453
|
+
}, D = new WeakSet(), se = function(e) {
|
|
1450
1454
|
e.cookie && this[__private__dont__use].ccall(
|
|
1451
1455
|
"wasm_set_cookies",
|
|
1452
1456
|
null,
|
|
@@ -1470,7 +1474,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1470
1474
|
e[t]
|
|
1471
1475
|
);
|
|
1472
1476
|
}
|
|
1473
|
-
},
|
|
1477
|
+
}, $ = new WeakSet(), ne = function(e) {
|
|
1474
1478
|
let t, r;
|
|
1475
1479
|
typeof e == "string" ? (console.warn(
|
|
1476
1480
|
"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 +1497,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1493
1497
|
[NUMBER],
|
|
1494
1498
|
[r]
|
|
1495
1499
|
), s;
|
|
1496
|
-
},
|
|
1500
|
+
}, j = new WeakSet(), ie = function(e) {
|
|
1497
1501
|
this[__private__dont__use].ccall(
|
|
1498
1502
|
"wasm_set_path_translated",
|
|
1499
1503
|
null,
|
|
1500
1504
|
[STRING],
|
|
1501
1505
|
[e]
|
|
1502
1506
|
);
|
|
1503
|
-
},
|
|
1507
|
+
}, W = new WeakSet(), oe = function() {
|
|
1504
1508
|
for (const e in l(this, g))
|
|
1505
1509
|
this[__private__dont__use].ccall(
|
|
1506
1510
|
"wasm_add_SERVER_entry",
|
|
@@ -1508,30 +1512,30 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1508
1512
|
[STRING, STRING],
|
|
1509
1513
|
[e, l(this, g)[e]]
|
|
1510
1514
|
);
|
|
1511
|
-
},
|
|
1515
|
+
}, z = new WeakSet(), ae = function(e, t) {
|
|
1512
1516
|
this[__private__dont__use].ccall(
|
|
1513
1517
|
"wasm_add_ENV_entry",
|
|
1514
1518
|
null,
|
|
1515
1519
|
[STRING, STRING],
|
|
1516
1520
|
[e, t]
|
|
1517
1521
|
);
|
|
1518
|
-
},
|
|
1522
|
+
}, G = new WeakSet(), le = function(e) {
|
|
1519
1523
|
this[__private__dont__use].ccall(
|
|
1520
1524
|
"wasm_set_php_code",
|
|
1521
1525
|
null,
|
|
1522
1526
|
[STRING],
|
|
1523
1527
|
[e]
|
|
1524
1528
|
);
|
|
1525
|
-
},
|
|
1529
|
+
}, V = new WeakSet(), ce = async function() {
|
|
1526
1530
|
var n;
|
|
1527
1531
|
let e, t;
|
|
1528
1532
|
try {
|
|
1529
|
-
e = await new Promise((
|
|
1533
|
+
e = await new Promise((o, i) => {
|
|
1530
1534
|
var c;
|
|
1531
1535
|
t = (d) => {
|
|
1532
1536
|
console.error(d), console.error(d.error);
|
|
1533
|
-
const
|
|
1534
|
-
|
|
1537
|
+
const _ = new Error("Rethrown");
|
|
1538
|
+
_.cause = d.error, _.betterMessage = d.message, i(_);
|
|
1535
1539
|
}, (c = l(this, w)) == null || c.addEventListener(
|
|
1536
1540
|
"error",
|
|
1537
1541
|
t
|
|
@@ -1543,9 +1547,9 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1543
1547
|
[],
|
|
1544
1548
|
{ async: !0 }
|
|
1545
1549
|
);
|
|
1546
|
-
return a instanceof Promise ? a.then(
|
|
1550
|
+
return a instanceof Promise ? a.then(o, i) : o(a);
|
|
1547
1551
|
});
|
|
1548
|
-
} catch (
|
|
1552
|
+
} catch (o) {
|
|
1549
1553
|
for (const d in this)
|
|
1550
1554
|
typeof this[d] == "function" && (this[d] = () => {
|
|
1551
1555
|
throw new Error(
|
|
@@ -1553,12 +1557,12 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1553
1557
|
);
|
|
1554
1558
|
});
|
|
1555
1559
|
this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
|
|
1556
|
-
const
|
|
1557
|
-
throw c.cause =
|
|
1560
|
+
const i = o, a = "betterMessage" in i ? i.betterMessage : i.message, c = new Error(a);
|
|
1561
|
+
throw c.cause = i, console.error(c), c;
|
|
1558
1562
|
} finally {
|
|
1559
1563
|
(n = l(this, w)) == null || n.removeEventListener("error", t), h(this, g, {});
|
|
1560
1564
|
}
|
|
1561
|
-
const { headers: r, httpStatusCode: s } = f(this,
|
|
1565
|
+
const { headers: r, httpStatusCode: s } = f(this, L, X).call(this);
|
|
1562
1566
|
return new PHPResponse(
|
|
1563
1567
|
s,
|
|
1564
1568
|
r,
|
|
@@ -1617,9 +1621,9 @@ function copyFS(e, t, r) {
|
|
|
1617
1621
|
return;
|
|
1618
1622
|
}
|
|
1619
1623
|
t.mkdirTree(r);
|
|
1620
|
-
const n = e.readdir(r).filter((
|
|
1621
|
-
for (const
|
|
1622
|
-
copyFS(e, t, joinPaths(r,
|
|
1624
|
+
const n = e.readdir(r).filter((o) => o !== "." && o !== "..");
|
|
1625
|
+
for (const o of n)
|
|
1626
|
+
copyFS(e, t, joinPaths(r, o));
|
|
1623
1627
|
}
|
|
1624
1628
|
function isLocalPHP(e) {
|
|
1625
1629
|
return !(e instanceof BasePHP);
|
|
@@ -1637,11 +1641,11 @@ function rotatePHPRuntime({
|
|
|
1637
1641
|
if (++s < r)
|
|
1638
1642
|
return;
|
|
1639
1643
|
s = 0;
|
|
1640
|
-
const
|
|
1644
|
+
const o = await e.semaphore.acquire();
|
|
1641
1645
|
try {
|
|
1642
1646
|
e.hotSwapPHPRuntime(await t());
|
|
1643
1647
|
} finally {
|
|
1644
|
-
|
|
1648
|
+
o();
|
|
1645
1649
|
}
|
|
1646
1650
|
}
|
|
1647
1651
|
return e.addEventListener("request.end", n), function() {
|
|
@@ -1650,9 +1654,9 @@ function rotatePHPRuntime({
|
|
|
1650
1654
|
}
|
|
1651
1655
|
async function writeFiles(e, t, r, { rmRoot: s = !1 } = {}) {
|
|
1652
1656
|
s && await e.isDir(t) && await e.rmdir(t, { recursive: !0 });
|
|
1653
|
-
for (const [n,
|
|
1654
|
-
const
|
|
1655
|
-
await e.fileExists(dirname(
|
|
1657
|
+
for (const [n, o] of Object.entries(r)) {
|
|
1658
|
+
const i = joinPaths(t, n);
|
|
1659
|
+
await e.fileExists(dirname(i)) || await e.mkdir(dirname(i)), await e.writeFile(i, o);
|
|
1656
1660
|
}
|
|
1657
1661
|
}
|
|
1658
1662
|
export {
|
|
@@ -1668,6 +1672,7 @@ export {
|
|
|
1668
1672
|
SupportedPHPVersionsList,
|
|
1669
1673
|
UnhandledRejectionsTarget,
|
|
1670
1674
|
__private__dont__use,
|
|
1675
|
+
applyRewriteRules,
|
|
1671
1676
|
ensurePathPrefix,
|
|
1672
1677
|
isExitCodeZero,
|
|
1673
1678
|
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,13 @@ 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
|
+
}
|
|
9
16
|
/**
|
|
10
17
|
* Represents a PHP runtime initialization event.
|
|
11
18
|
*/
|
|
@@ -23,7 +30,7 @@ export interface PHPRuntimeBeforeDestroyEvent {
|
|
|
23
30
|
* This is intentionally not an extension of CustomEvent
|
|
24
31
|
* to make it isomorphic between different JavaScript runtimes.
|
|
25
32
|
*/
|
|
26
|
-
export type PHPEvent = PHPRequestEndEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeDestroyEvent;
|
|
33
|
+
export type PHPEvent = PHPRequestEndEvent | PHPRequestErrorEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeDestroyEvent;
|
|
27
34
|
/**
|
|
28
35
|
* A callback function that handles PHP events.
|
|
29
36
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@php-wasm/universal",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.8",
|
|
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": "cb7b1af260489022238495a2fc0d96f767a1294a",
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=18.18.2",
|
|
42
42
|
"npm": ">=8.11.0"
|