@php-wasm/universal 0.6.6 → 0.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs +5 -5
- package/index.js +254 -239
- 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 J=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};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 l=0;for(const c of n)o.set(typeof c=="string"?s.encode(c):c,l),l+=c.length;return{bytes:o,contentType:r}}function fileToUint8Array(e){return new Promise(t=>{const r=new FileReader;r.onload=()=>{t(new Uint8Array(r.result))},r.readAsArrayBuffer(e)})}var m,x,U,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,U,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,U,i.hostname),h(this,v,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,x,(i.protocol||"").replace(":",""));const o=a(this,v)!==443&&a(this,v)!==80;h(this,H,[a(this,U),o?`:${a(this,v)}`:""].join("")),h(this,_,i.pathname.replace(/\/+$/,"")),h(this,F,[`${a(this,x)}://`,a(this,H),a(this,_)].join(""))}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(a(this,_))&&(r.pathname=r.pathname.slice(a(this,_).length)),toRelativeUrl(r)}get isRequestRunning(){return a(this,R).running>0}get absoluteUrl(){return a(this,F)}get documentRoot(){return a(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,a(this,_)),i=`${a(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,U=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(a(this,R).running>0&&((n=t.headers)==null?void 0:n["x-request-issuer"])==="php")return console.warn("Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."),new PHPResponse(502,{},new TextEncoder().encode("502 Bad Gateway"));const s=await a(this,R).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",a(this,m)),this.php.addServerGlobalEntry("HTTPS",a(this,F).startsWith("https://")?"on":"");let o="GET";const l={host:a(this,H),...normalizeHeaders(t.headers||{})};let c=t.body;if(typeof c=="object"&&!(c instanceof Uint8Array)){o="POST";const{bytes:f,contentType:k}=await encodeAsMultipart(c);c=f,l["content-type"]=k}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),a(this,_)),protocol:a(this,x),method:t.method||o,body:c,scriptPath:d,headers:l})}finally{s()}},L=new WeakSet,K=function(t){let r=removePathPrefix(t,a(this,_));r.includes(".php")?r=r.split(".php")[0]+".php":this.php.isDir(`${a(this,m)}${r}`)?(r.endsWith("/")||(r=`${r}/`),r=`${r}index.php`):r="/index.php";const s=`${a(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(l){const c=typeof l=="object"?l==null?void 0:l.errno:null;if(c in FileErrorCodes){const d=FileErrorCodes[c],f=typeof o[0]=="string"?o[0]:null,k=f!==null?e.replaceAll("{path}",f):e;throw new Error(`${k}: ${d}`,{cause:l})}throw l}}}}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(l){n(l),console.error(l)},ENV:{},locateFile:l=>l,...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(l){return loadedRuntimes.delete(o),i.originalExit(l)},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,M,ee,q,te,O,re,D,se,$,ne,j,ie,z,oe,W,ae,G,le,V,ce,Q,ue;class BasePHP{constructor(e,t){u(this,N);u(this,M);u(this,q);u(this,O);u(this,D);u(this,$);u(this,j);u(this,z);u(this,W);u(this,G);u(this,V);u(this,Q);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){a(this,P).has(e)||a(this,P).set(e,new Set),a(this,P).get(e).add(t)}removeEventListener(e,t){var r;(r=a(this,P).get(e))==null||r.delete(t)}dispatchEvent(e){const t=a(this,P).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){a(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 a(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(a(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(a(this,y))throw new Error("Cannot set PHP ini entries after calling run().");a(this,S).push([e,t])}chdir(e){this[__private__dont__use].FS.chdir(e)}async request(e,t){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,t)}async run(e){const t=await this.semaphore.acquire();let r;try{if(a(this,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,z,oe).call(this,e.scriptPath||""),p(this,q,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,O,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,W,ae).call(this);const i=e.env||{};for(const l in i)p(this,G,le).call(this,l,i[l]);const o=await p(this,Q,ue).call(this);if(e.throwOnError&&o.exitCode!==0){const l={stdout:o.text,stderr:o.errors};console.warn("PHP.run() output was:",l);const c=new Error(`PHP.run() failed with exit code ${o.exitCode} and the following output: `+o.errors);throw c.output=l,console.error(c),c}return o}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){a(this,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),a(this,T)&&this.setPhpIniPath(a(this,T)),a(this,A)&&this.setSapiName(a(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) {
|
|
@@ -46,7 +46,7 @@ ${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
|
|
|
46
46
|
define($const, $value);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
}`),
|
|
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
|
@@ -2,62 +2,72 @@ var J = (e, t, r) => {
|
|
|
2
2
|
if (!t.has(e))
|
|
3
3
|
throw TypeError("Cannot " + r);
|
|
4
4
|
};
|
|
5
|
-
var
|
|
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
9
|
}, h = (e, t, r, s) => (J(e, t, "write to private field"), s ? s.call(e, r) : t.set(e, r), r);
|
|
10
10
|
var f = (e, t, r) => (J(e, t, "access private method"), r);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
const currentJsRuntime$1 = function() {
|
|
12
|
+
var e;
|
|
13
|
+
return typeof process < "u" && ((e = process.release) == null ? void 0 : e.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : (
|
|
14
|
+
// @ts-ignore
|
|
15
|
+
typeof WorkerGlobalScope < "u" && // @ts-ignore
|
|
16
|
+
self instanceof WorkerGlobalScope ? "WORKER" : "NODE"
|
|
17
|
+
);
|
|
18
|
+
}();
|
|
19
|
+
if (currentJsRuntime$1 === "NODE") {
|
|
20
|
+
let e = function(r) {
|
|
21
|
+
return new Promise(function(s, n) {
|
|
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
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}, t = function() {
|
|
27
|
+
const r = new Uint8Array([1, 2, 3, 4]), n = new File([r], "test").stream();
|
|
28
|
+
try {
|
|
29
|
+
return n.getReader({ mode: "byob" }), !0;
|
|
30
|
+
} catch {
|
|
31
|
+
return !1;
|
|
17
32
|
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
|
|
29
|
-
const t = new FileReader();
|
|
30
|
-
return t.readAsArrayBuffer(this), asPromise(t);
|
|
31
|
-
});
|
|
32
|
-
typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
|
|
33
|
-
const t = new FileReader();
|
|
34
|
-
return t.readAsText(this), asPromise(t);
|
|
35
|
-
});
|
|
36
|
-
function isByobSupported() {
|
|
37
|
-
const e = new Uint8Array([1, 2, 3, 4]), r = new File([e], "test").stream();
|
|
38
|
-
try {
|
|
39
|
-
return r.getReader({ mode: "byob" }), !0;
|
|
40
|
-
} catch {
|
|
41
|
-
return !1;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
(typeof Blob.prototype.stream > "u" || !isByobSupported()) && (Blob.prototype.stream = function() {
|
|
45
|
-
let e = 0;
|
|
46
|
-
const t = this;
|
|
47
|
-
return new ReadableStream({
|
|
48
|
-
type: "bytes",
|
|
49
|
-
// 0.5 MB seems like a reasonable chunk size, let's adjust
|
|
50
|
-
// this if needed.
|
|
51
|
-
autoAllocateChunkSize: 512 * 1024,
|
|
52
|
-
async pull(r) {
|
|
53
|
-
const s = r.byobRequest.view, i = await t.slice(e, e + s.byteLength).arrayBuffer(), o = new Uint8Array(i);
|
|
54
|
-
new Uint8Array(s.buffer).set(o);
|
|
55
|
-
const l = o.byteLength;
|
|
56
|
-
r.byobRequest.respond(l), e += l, e >= t.size && r.close();
|
|
33
|
+
};
|
|
34
|
+
if (typeof File > "u") {
|
|
35
|
+
class r extends Blob {
|
|
36
|
+
constructor(n, o, i) {
|
|
37
|
+
super(n);
|
|
38
|
+
let a;
|
|
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
|
+
}
|
|
57
41
|
}
|
|
42
|
+
global.File = r;
|
|
43
|
+
}
|
|
44
|
+
typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
|
|
45
|
+
const s = new FileReader();
|
|
46
|
+
return s.readAsArrayBuffer(this), e(s);
|
|
47
|
+
}), typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
|
|
48
|
+
const s = new FileReader();
|
|
49
|
+
return s.readAsText(this), e(s);
|
|
50
|
+
}), (typeof Blob.prototype.stream > "u" || !t()) && (Blob.prototype.stream = function() {
|
|
51
|
+
let r = 0;
|
|
52
|
+
const s = this;
|
|
53
|
+
return new ReadableStream({
|
|
54
|
+
type: "bytes",
|
|
55
|
+
// 0.5 MB seems like a reasonable chunk size, let's adjust
|
|
56
|
+
// this if needed.
|
|
57
|
+
autoAllocateChunkSize: 512 * 1024,
|
|
58
|
+
async pull(n) {
|
|
59
|
+
const o = n.byobRequest.view, a = await s.slice(
|
|
60
|
+
r,
|
|
61
|
+
r + o.byteLength
|
|
62
|
+
).arrayBuffer(), c = new Uint8Array(a);
|
|
63
|
+
new Uint8Array(o.buffer).set(c);
|
|
64
|
+
const d = c.byteLength;
|
|
65
|
+
n.byobRequest.respond(d), r += d, r >= s.size && n.close();
|
|
66
|
+
}
|
|
67
|
+
});
|
|
58
68
|
});
|
|
59
|
-
}
|
|
60
|
-
if (typeof CustomEvent > "u") {
|
|
69
|
+
}
|
|
70
|
+
if (currentJsRuntime$1 === "NODE" && typeof CustomEvent > "u") {
|
|
61
71
|
class e extends Event {
|
|
62
72
|
constructor(r, s = {}) {
|
|
63
73
|
super(r, s), this.detail = s.detail;
|
|
@@ -115,26 +125,26 @@ function improveWASMErrorReporting(e) {
|
|
|
115
125
|
if (typeof e.asm[r] == "function") {
|
|
116
126
|
const s = e.asm[r];
|
|
117
127
|
e.asm[r] = function(...n) {
|
|
118
|
-
var
|
|
128
|
+
var o;
|
|
119
129
|
try {
|
|
120
130
|
return s(...n);
|
|
121
|
-
} catch (
|
|
122
|
-
if (!(
|
|
123
|
-
throw
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
(
|
|
131
|
+
} catch (i) {
|
|
132
|
+
if (!(i instanceof Error))
|
|
133
|
+
throw i;
|
|
134
|
+
const a = clarifyErrorMessage(
|
|
135
|
+
i,
|
|
136
|
+
(o = e.lastAsyncifyStackSource) == null ? void 0 : o.stack
|
|
127
137
|
);
|
|
128
|
-
if (e.lastAsyncifyStackSource && (
|
|
138
|
+
if (e.lastAsyncifyStackSource && (i.cause = e.lastAsyncifyStackSource), t.hasListeners()) {
|
|
129
139
|
t.dispatchEvent(
|
|
130
140
|
new ErrorEvent("error", {
|
|
131
|
-
error:
|
|
132
|
-
message:
|
|
141
|
+
error: i,
|
|
142
|
+
message: a
|
|
133
143
|
})
|
|
134
144
|
);
|
|
135
145
|
return;
|
|
136
146
|
}
|
|
137
|
-
throw isExitCodeZero(
|
|
147
|
+
throw isExitCodeZero(i) || showCriticalErrorBox(a), i;
|
|
138
148
|
}
|
|
139
149
|
};
|
|
140
150
|
}
|
|
@@ -276,28 +286,28 @@ function normalizePathsArray(e, t) {
|
|
|
276
286
|
}
|
|
277
287
|
function splitShellCommand(e) {
|
|
278
288
|
let s = 0, n = "";
|
|
279
|
-
const
|
|
280
|
-
let
|
|
281
|
-
for (let
|
|
282
|
-
const c = e[
|
|
283
|
-
c === "\\" ? ((e[
|
|
289
|
+
const o = [];
|
|
290
|
+
let i = "";
|
|
291
|
+
for (let a = 0; a < e.length; a++) {
|
|
292
|
+
const c = e[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);
|
|
284
294
|
}
|
|
285
|
-
return
|
|
295
|
+
return i && o.push(i.trim()), o;
|
|
286
296
|
}
|
|
287
297
|
function createSpawnHandler(e) {
|
|
288
298
|
return function(t, r = [], s = {}) {
|
|
289
|
-
const n = new ChildProcess(),
|
|
299
|
+
const n = new ChildProcess(), o = new ProcessApi(n);
|
|
290
300
|
return setTimeout(async () => {
|
|
291
|
-
let
|
|
301
|
+
let i = [];
|
|
292
302
|
if (r.length)
|
|
293
|
-
|
|
303
|
+
i = [t, ...r];
|
|
294
304
|
else if (typeof t == "string")
|
|
295
|
-
|
|
305
|
+
i = splitShellCommand(t);
|
|
296
306
|
else if (Array.isArray(t))
|
|
297
|
-
|
|
307
|
+
i = t;
|
|
298
308
|
else
|
|
299
309
|
throw new Error("Invalid command ", t);
|
|
300
|
-
await e(
|
|
310
|
+
await e(i, o, s), n.emit("spawn", !0);
|
|
301
311
|
}), n;
|
|
302
312
|
};
|
|
303
313
|
}
|
|
@@ -398,14 +408,14 @@ function limitBytes(e, t) {
|
|
|
398
408
|
let s = 0;
|
|
399
409
|
return new ReadableStream({
|
|
400
410
|
async pull(n) {
|
|
401
|
-
const { value:
|
|
411
|
+
const { value: o, done: i } = await r.read(
|
|
402
412
|
new Uint8Array(t - s)
|
|
403
413
|
);
|
|
404
|
-
if (
|
|
414
|
+
if (i) {
|
|
405
415
|
r.releaseLock(), n.close();
|
|
406
416
|
return;
|
|
407
417
|
}
|
|
408
|
-
s +=
|
|
418
|
+
s += o.length, n.enqueue(o), s >= t && (r.releaseLock(), n.close());
|
|
409
419
|
},
|
|
410
420
|
cancel() {
|
|
411
421
|
r.cancel();
|
|
@@ -487,17 +497,17 @@ async function* iteratePhpFiles(e, t, {
|
|
|
487
497
|
exceptPaths: n = []
|
|
488
498
|
} = {}) {
|
|
489
499
|
t = normalizePath(t);
|
|
490
|
-
const
|
|
491
|
-
for (;
|
|
492
|
-
const
|
|
493
|
-
if (!
|
|
500
|
+
const o = [t];
|
|
501
|
+
for (; o.length; ) {
|
|
502
|
+
const i = o.pop();
|
|
503
|
+
if (!i)
|
|
494
504
|
return;
|
|
495
|
-
const
|
|
496
|
-
for (const c of
|
|
497
|
-
const d = `${
|
|
505
|
+
const a = await e.listFiles(i);
|
|
506
|
+
for (const c of a) {
|
|
507
|
+
const d = `${i}/${c}`;
|
|
498
508
|
if (n.includes(d.substring(t.length + 1)))
|
|
499
509
|
continue;
|
|
500
|
-
await e.isDir(d) ?
|
|
510
|
+
await e.isDir(d) ? o.push(d) : yield new StreamedFile(
|
|
501
511
|
streamReadFileFromPHP(e, d),
|
|
502
512
|
r ? joinPaths(
|
|
503
513
|
s || "",
|
|
@@ -519,8 +529,8 @@ function writeFilesStreamToPhp(e, t) {
|
|
|
519
529
|
});
|
|
520
530
|
}
|
|
521
531
|
class PHPResponse {
|
|
522
|
-
constructor(t, r, s, n = "",
|
|
523
|
-
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;
|
|
524
534
|
}
|
|
525
535
|
static fromRawData(t) {
|
|
526
536
|
return new PHPResponse(
|
|
@@ -608,7 +618,7 @@ class PHPBrowser {
|
|
|
608
618
|
cookie: this.serializeCookies()
|
|
609
619
|
}
|
|
610
620
|
});
|
|
611
|
-
if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]),
|
|
621
|
+
if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), l(this, b).handleRedirects && s.headers.location && r < l(this, b).maxRedirects) {
|
|
612
622
|
const n = new URL(
|
|
613
623
|
s.headers.location[0],
|
|
614
624
|
this.requestHandler.absoluteUrl
|
|
@@ -645,16 +655,16 @@ class PHPBrowser {
|
|
|
645
655
|
try {
|
|
646
656
|
if (!r.includes("="))
|
|
647
657
|
continue;
|
|
648
|
-
const s = r.indexOf("="), n = r.substring(0, s),
|
|
649
|
-
|
|
658
|
+
const s = r.indexOf("="), n = r.substring(0, s), o = r.substring(s + 1).split(";")[0];
|
|
659
|
+
l(this, E)[n] = o;
|
|
650
660
|
} catch (s) {
|
|
651
661
|
console.error(s);
|
|
652
662
|
}
|
|
653
663
|
}
|
|
654
664
|
serializeCookies() {
|
|
655
665
|
const t = [];
|
|
656
|
-
for (const r in
|
|
657
|
-
t.push(`${r}=${
|
|
666
|
+
for (const r in l(this, E))
|
|
667
|
+
t.push(`${r}=${l(this, E)[r]}`);
|
|
658
668
|
return t.join("; ");
|
|
659
669
|
}
|
|
660
670
|
}
|
|
@@ -680,14 +690,14 @@ async function encodeAsMultipart(e) {
|
|
|
680
690
|
`);
|
|
681
691
|
n.push(`--${t}--\r
|
|
682
692
|
`);
|
|
683
|
-
const
|
|
684
|
-
let
|
|
693
|
+
const o = n.reduce((c, d) => c + d.length, 0), i = new Uint8Array(o);
|
|
694
|
+
let a = 0;
|
|
685
695
|
for (const c of n)
|
|
686
|
-
|
|
696
|
+
i.set(
|
|
687
697
|
typeof c == "string" ? s.encode(c) : c,
|
|
688
|
-
|
|
689
|
-
),
|
|
690
|
-
return { bytes:
|
|
698
|
+
a
|
|
699
|
+
), a += c.length;
|
|
700
|
+
return { bytes: i, contentType: r };
|
|
691
701
|
}
|
|
692
702
|
function fileToUint8Array(e) {
|
|
693
703
|
return new Promise((t) => {
|
|
@@ -697,7 +707,7 @@ function fileToUint8Array(e) {
|
|
|
697
707
|
}, r.readAsArrayBuffer(e);
|
|
698
708
|
});
|
|
699
709
|
}
|
|
700
|
-
var m, H, k, v,
|
|
710
|
+
var m, H, k, v, F, p, x, R, U, Q, B, Y, I, K;
|
|
701
711
|
class PHPRequestHandler {
|
|
702
712
|
/**
|
|
703
713
|
* @param php - The PHP instance.
|
|
@@ -710,7 +720,7 @@ class PHPRequestHandler {
|
|
|
710
720
|
* @param fsPath - Absolute path of the static file to serve.
|
|
711
721
|
* @returns The response.
|
|
712
722
|
*/
|
|
713
|
-
u(this,
|
|
723
|
+
u(this, U);
|
|
714
724
|
/**
|
|
715
725
|
* Runs the requested PHP file with all the request and $_SERVER
|
|
716
726
|
* superglobals populated.
|
|
@@ -718,7 +728,7 @@ class PHPRequestHandler {
|
|
|
718
728
|
* @param request - The request.
|
|
719
729
|
* @returns The response.
|
|
720
730
|
*/
|
|
721
|
-
u(this,
|
|
731
|
+
u(this, B);
|
|
722
732
|
/**
|
|
723
733
|
* Resolve the requested path to the filesystem path of the requested PHP file.
|
|
724
734
|
*
|
|
@@ -728,32 +738,33 @@ class PHPRequestHandler {
|
|
|
728
738
|
* @throws {Error} If the requested path doesn't exist.
|
|
729
739
|
* @returns The resolved filesystem path.
|
|
730
740
|
*/
|
|
731
|
-
u(this,
|
|
741
|
+
u(this, I);
|
|
732
742
|
u(this, m, void 0);
|
|
733
743
|
u(this, H, void 0);
|
|
734
744
|
u(this, k, void 0);
|
|
735
745
|
u(this, v, void 0);
|
|
736
|
-
u(this, x, void 0);
|
|
737
|
-
u(this, _, void 0);
|
|
738
746
|
u(this, F, void 0);
|
|
747
|
+
u(this, p, void 0);
|
|
748
|
+
u(this, x, void 0);
|
|
739
749
|
u(this, R, void 0);
|
|
740
750
|
h(this, R, new Semaphore({ concurrency: 1 }));
|
|
741
751
|
const {
|
|
742
752
|
documentRoot: s = "/www/",
|
|
743
|
-
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 = []
|
|
744
755
|
} = r;
|
|
745
756
|
this.php = t, h(this, m, s);
|
|
746
757
|
const i = new URL(n);
|
|
747
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(":", ""));
|
|
748
|
-
const
|
|
749
|
-
h(this,
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
].join("")), h(this,
|
|
753
|
-
`${
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
].join(""));
|
|
759
|
+
const a = l(this, v) !== 443 && l(this, v) !== 80;
|
|
760
|
+
h(this, F, [
|
|
761
|
+
l(this, k),
|
|
762
|
+
a ? `:${l(this, v)}` : ""
|
|
763
|
+
].join("")), h(this, p, i.pathname.replace(/\/+$/, "")), h(this, x, [
|
|
764
|
+
`${l(this, H)}://`,
|
|
765
|
+
l(this, F),
|
|
766
|
+
l(this, p)
|
|
767
|
+
].join("")), this.rewriteRules = o;
|
|
757
768
|
}
|
|
758
769
|
/** @inheritDoc */
|
|
759
770
|
pathToInternalUrl(t) {
|
|
@@ -762,32 +773,32 @@ class PHPRequestHandler {
|
|
|
762
773
|
/** @inheritDoc */
|
|
763
774
|
internalUrlToPath(t) {
|
|
764
775
|
const r = new URL(t);
|
|
765
|
-
return r.pathname.startsWith(
|
|
776
|
+
return r.pathname.startsWith(l(this, p)) && (r.pathname = r.pathname.slice(l(this, p).length)), toRelativeUrl(r);
|
|
766
777
|
}
|
|
767
778
|
get isRequestRunning() {
|
|
768
|
-
return
|
|
779
|
+
return l(this, R).running > 0;
|
|
769
780
|
}
|
|
770
781
|
/** @inheritDoc */
|
|
771
782
|
get absoluteUrl() {
|
|
772
|
-
return
|
|
783
|
+
return l(this, x);
|
|
773
784
|
}
|
|
774
785
|
/** @inheritDoc */
|
|
775
786
|
get documentRoot() {
|
|
776
|
-
return
|
|
787
|
+
return l(this, m);
|
|
777
788
|
}
|
|
778
789
|
/** @inheritDoc */
|
|
779
790
|
async request(t) {
|
|
780
791
|
const r = t.url.startsWith("http://") || t.url.startsWith("https://"), s = new URL(
|
|
781
792
|
t.url,
|
|
782
793
|
r ? void 0 : DEFAULT_BASE_URL
|
|
783
|
-
), n =
|
|
784
|
-
s.pathname,
|
|
785
|
-
|
|
786
|
-
),
|
|
787
|
-
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);
|
|
788
799
|
}
|
|
789
800
|
}
|
|
790
|
-
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) {
|
|
791
802
|
if (!this.php.fileExists(t))
|
|
792
803
|
return new PHPResponse(
|
|
793
804
|
404,
|
|
@@ -812,9 +823,9 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
812
823
|
},
|
|
813
824
|
r
|
|
814
825
|
);
|
|
815
|
-
},
|
|
816
|
-
var n
|
|
817
|
-
if (
|
|
826
|
+
}, B = new WeakSet(), Y = async function(t, r) {
|
|
827
|
+
var n;
|
|
828
|
+
if (l(this, R).running > 0 && ((n = t.headers) == null ? void 0 : n["x-request-issuer"]) === "php")
|
|
818
829
|
return console.warn(
|
|
819
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."
|
|
820
831
|
), new PHPResponse(
|
|
@@ -822,34 +833,26 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
822
833
|
{},
|
|
823
834
|
new TextEncoder().encode("502 Bad Gateway")
|
|
824
835
|
);
|
|
825
|
-
const s = await
|
|
836
|
+
const s = await l(this, R).acquire();
|
|
826
837
|
try {
|
|
827
|
-
this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT",
|
|
838
|
+
this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", l(this, m)), this.php.addServerGlobalEntry(
|
|
828
839
|
"HTTPS",
|
|
829
|
-
|
|
840
|
+
l(this, x).startsWith("https://") ? "on" : ""
|
|
830
841
|
);
|
|
831
842
|
let o = "GET";
|
|
832
|
-
const
|
|
833
|
-
host:
|
|
843
|
+
const i = {
|
|
844
|
+
host: l(this, F),
|
|
834
845
|
...normalizeHeaders(t.headers || {})
|
|
835
846
|
};
|
|
836
|
-
let
|
|
837
|
-
if (typeof
|
|
847
|
+
let a = t.body;
|
|
848
|
+
if (typeof a == "object" && !(a instanceof Uint8Array)) {
|
|
838
849
|
o = "POST";
|
|
839
|
-
const { bytes:
|
|
840
|
-
|
|
850
|
+
const { bytes: d, contentType: _ } = await encodeAsMultipart(a);
|
|
851
|
+
a = d, i["content-type"] = _;
|
|
841
852
|
}
|
|
842
|
-
let
|
|
853
|
+
let c;
|
|
843
854
|
try {
|
|
844
|
-
|
|
845
|
-
if ((i = t.headers) != null && i["x-rewrite-url"])
|
|
846
|
-
try {
|
|
847
|
-
p = new URL(
|
|
848
|
-
t.headers["x-rewrite-url"]
|
|
849
|
-
).pathname;
|
|
850
|
-
} catch {
|
|
851
|
-
}
|
|
852
|
-
d = f(this, L, K).call(this, p);
|
|
855
|
+
c = f(this, I, K).call(this, r.pathname);
|
|
853
856
|
} catch {
|
|
854
857
|
return new PHPResponse(
|
|
855
858
|
404,
|
|
@@ -860,21 +863,21 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
860
863
|
return await this.php.run({
|
|
861
864
|
relativeUri: ensurePathPrefix(
|
|
862
865
|
toRelativeUrl(r),
|
|
863
|
-
|
|
866
|
+
l(this, p)
|
|
864
867
|
),
|
|
865
|
-
protocol:
|
|
868
|
+
protocol: l(this, H),
|
|
866
869
|
method: t.method || o,
|
|
867
|
-
body:
|
|
868
|
-
scriptPath:
|
|
869
|
-
headers:
|
|
870
|
+
body: a,
|
|
871
|
+
scriptPath: c,
|
|
872
|
+
headers: i
|
|
870
873
|
});
|
|
871
874
|
} finally {
|
|
872
875
|
s();
|
|
873
876
|
}
|
|
874
|
-
},
|
|
875
|
-
let r = removePathPrefix(t,
|
|
876
|
-
r.includes(".php") ? r = r.split(".php")[0] + ".php" : this.php.isDir(`${
|
|
877
|
-
const s = `${
|
|
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";
|
|
880
|
+
const s = `${l(this, m)}${r}`;
|
|
878
881
|
if (this.php.fileExists(s))
|
|
879
882
|
return s;
|
|
880
883
|
throw new Error(`File not found: ${s}`);
|
|
@@ -928,6 +931,12 @@ function seemsLikeAPHPFile(e) {
|
|
|
928
931
|
function seemsLikeADirectoryRoot(e) {
|
|
929
932
|
return !e.split("/").pop().includes(".");
|
|
930
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
|
+
}
|
|
931
940
|
const FileErrorCodes = {
|
|
932
941
|
0: "No error occurred. System call completed successfully.",
|
|
933
942
|
1: "Argument list too long.",
|
|
@@ -1014,19 +1023,19 @@ function getEmscriptenFsError(e) {
|
|
|
1014
1023
|
}
|
|
1015
1024
|
function rethrowFileSystemError(e = "") {
|
|
1016
1025
|
return function(r, s, n) {
|
|
1017
|
-
const
|
|
1018
|
-
n.value = function(...
|
|
1026
|
+
const o = n.value;
|
|
1027
|
+
n.value = function(...i) {
|
|
1019
1028
|
try {
|
|
1020
|
-
return
|
|
1021
|
-
} catch (
|
|
1022
|
-
const c = typeof
|
|
1029
|
+
return o.apply(this, i);
|
|
1030
|
+
} catch (a) {
|
|
1031
|
+
const c = typeof a == "object" ? a == null ? void 0 : a.errno : null;
|
|
1023
1032
|
if (c in FileErrorCodes) {
|
|
1024
|
-
const d = FileErrorCodes[c],
|
|
1025
|
-
throw new Error(`${
|
|
1026
|
-
cause:
|
|
1033
|
+
const d = FileErrorCodes[c], _ = typeof i[0] == "string" ? i[0] : null, ue = _ !== null ? e.replaceAll("{path}", _) : e;
|
|
1034
|
+
throw new Error(`${ue}: ${d}`, {
|
|
1035
|
+
cause: a
|
|
1027
1036
|
});
|
|
1028
1037
|
}
|
|
1029
|
-
throw
|
|
1038
|
+
throw a;
|
|
1030
1039
|
}
|
|
1031
1040
|
};
|
|
1032
1041
|
};
|
|
@@ -1034,15 +1043,15 @@ function rethrowFileSystemError(e = "") {
|
|
|
1034
1043
|
const RuntimeId = Symbol("RuntimeId"), loadedRuntimes = /* @__PURE__ */ new Map();
|
|
1035
1044
|
let lastRuntimeId = 0;
|
|
1036
1045
|
async function loadPHPRuntime(e, t = {}) {
|
|
1037
|
-
const [r, s, n] = makePromise(),
|
|
1038
|
-
onAbort(
|
|
1039
|
-
n(
|
|
1046
|
+
const [r, s, n] = makePromise(), o = e.init(currentJsRuntime, {
|
|
1047
|
+
onAbort(a) {
|
|
1048
|
+
n(a), console.error(a);
|
|
1040
1049
|
},
|
|
1041
1050
|
ENV: {},
|
|
1042
1051
|
// Emscripten sometimes prepends a '/' to the path, which
|
|
1043
1052
|
// breaks vite dev mode. An identity `locateFile` function
|
|
1044
1053
|
// fixes it.
|
|
1045
|
-
locateFile: (
|
|
1054
|
+
locateFile: (a) => a,
|
|
1046
1055
|
...t,
|
|
1047
1056
|
noInitialRun: !0,
|
|
1048
1057
|
onRuntimeInitialized() {
|
|
@@ -1050,10 +1059,10 @@ async function loadPHPRuntime(e, t = {}) {
|
|
|
1050
1059
|
}
|
|
1051
1060
|
});
|
|
1052
1061
|
await r;
|
|
1053
|
-
const
|
|
1054
|
-
return
|
|
1055
|
-
return loadedRuntimes.delete(
|
|
1056
|
-
},
|
|
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;
|
|
1057
1066
|
}
|
|
1058
1067
|
function getLoadedRuntime(e) {
|
|
1059
1068
|
return loadedRuntimes.get(e);
|
|
@@ -1068,12 +1077,12 @@ const currentJsRuntime = function() {
|
|
|
1068
1077
|
return e.unshift(t), e;
|
|
1069
1078
|
};
|
|
1070
1079
|
var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyDescriptor, __decorateClass = (e, t, r, s) => {
|
|
1071
|
-
for (var n = s > 1 ? void 0 : s ? __getOwnPropDesc(t, r) : t,
|
|
1072
|
-
(
|
|
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);
|
|
1073
1082
|
return s && n && __defProp(t, r, n), n;
|
|
1074
1083
|
};
|
|
1075
1084
|
const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
|
|
1076
|
-
var S, T, A, y, w, g, P, C, N, X,
|
|
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;
|
|
1077
1086
|
class BasePHP {
|
|
1078
1087
|
/**
|
|
1079
1088
|
* Initializes a PHP runtime.
|
|
@@ -1084,17 +1093,17 @@ class BasePHP {
|
|
|
1084
1093
|
*/
|
|
1085
1094
|
constructor(e, t) {
|
|
1086
1095
|
u(this, N);
|
|
1087
|
-
u(this,
|
|
1088
|
-
u(this, q);
|
|
1096
|
+
u(this, L);
|
|
1089
1097
|
u(this, O);
|
|
1090
|
-
u(this,
|
|
1098
|
+
u(this, q);
|
|
1099
|
+
u(this, M);
|
|
1091
1100
|
u(this, D);
|
|
1101
|
+
u(this, $);
|
|
1092
1102
|
u(this, j);
|
|
1093
|
-
u(this, z);
|
|
1094
1103
|
u(this, W);
|
|
1104
|
+
u(this, z);
|
|
1095
1105
|
u(this, G);
|
|
1096
1106
|
u(this, V);
|
|
1097
|
-
u(this, Q);
|
|
1098
1107
|
u(this, S, void 0);
|
|
1099
1108
|
u(this, T, void 0);
|
|
1100
1109
|
u(this, A, void 0);
|
|
@@ -1108,21 +1117,21 @@ class BasePHP {
|
|
|
1108
1117
|
));
|
|
1109
1118
|
}
|
|
1110
1119
|
addEventListener(e, t) {
|
|
1111
|
-
|
|
1120
|
+
l(this, P).has(e) || l(this, P).set(e, /* @__PURE__ */ new Set()), l(this, P).get(e).add(t);
|
|
1112
1121
|
}
|
|
1113
1122
|
removeEventListener(e, t) {
|
|
1114
1123
|
var r;
|
|
1115
|
-
(r =
|
|
1124
|
+
(r = l(this, P).get(e)) == null || r.delete(t);
|
|
1116
1125
|
}
|
|
1117
1126
|
dispatchEvent(e) {
|
|
1118
|
-
const t =
|
|
1127
|
+
const t = l(this, P).get(e.type);
|
|
1119
1128
|
if (t)
|
|
1120
1129
|
for (const r of t)
|
|
1121
1130
|
r(e);
|
|
1122
1131
|
}
|
|
1123
1132
|
/** @inheritDoc */
|
|
1124
1133
|
async onMessage(e) {
|
|
1125
|
-
|
|
1134
|
+
l(this, C).push(e);
|
|
1126
1135
|
}
|
|
1127
1136
|
/** @inheritDoc */
|
|
1128
1137
|
async setSpawnHandler(handler) {
|
|
@@ -1153,7 +1162,7 @@ class BasePHP {
|
|
|
1153
1162
|
if (!t)
|
|
1154
1163
|
throw new Error("Invalid PHP runtime id.");
|
|
1155
1164
|
this[__private__dont__use] = t, t.onMessage = async (r) => {
|
|
1156
|
-
for (const s of
|
|
1165
|
+
for (const s of l(this, C)) {
|
|
1157
1166
|
const n = await s(r);
|
|
1158
1167
|
if (n)
|
|
1159
1168
|
return n;
|
|
@@ -1178,7 +1187,7 @@ class BasePHP {
|
|
|
1178
1187
|
}
|
|
1179
1188
|
/** @inheritDoc */
|
|
1180
1189
|
setPhpIniPath(e) {
|
|
1181
|
-
if (
|
|
1190
|
+
if (l(this, y))
|
|
1182
1191
|
throw new Error("Cannot set PHP ini path after calling run().");
|
|
1183
1192
|
h(this, T, e), this[__private__dont__use].ccall(
|
|
1184
1193
|
"wasm_set_phpini_path",
|
|
@@ -1189,9 +1198,9 @@ class BasePHP {
|
|
|
1189
1198
|
}
|
|
1190
1199
|
/** @inheritDoc */
|
|
1191
1200
|
setPhpIniEntry(e, t) {
|
|
1192
|
-
if (
|
|
1201
|
+
if (l(this, y))
|
|
1193
1202
|
throw new Error("Cannot set PHP ini entries after calling run().");
|
|
1194
|
-
|
|
1203
|
+
l(this, S).push([e, t]);
|
|
1195
1204
|
}
|
|
1196
1205
|
/** @inheritDoc */
|
|
1197
1206
|
chdir(e) {
|
|
@@ -1208,29 +1217,34 @@ class BasePHP {
|
|
|
1208
1217
|
const t = await this.semaphore.acquire();
|
|
1209
1218
|
let r;
|
|
1210
1219
|
try {
|
|
1211
|
-
if (
|
|
1220
|
+
if (l(this, y) || (f(this, N, Z).call(this), h(this, y, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
|
|
1212
1221
|
throw new Error(
|
|
1213
1222
|
`The script path "${e.scriptPath}" does not exist.`
|
|
1214
1223
|
);
|
|
1215
|
-
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");
|
|
1216
1225
|
const s = normalizeHeaders(e.headers || {}), n = s.host || "example.com:443";
|
|
1217
|
-
f(this,
|
|
1218
|
-
const
|
|
1219
|
-
for (const
|
|
1220
|
-
f(this,
|
|
1221
|
-
const
|
|
1222
|
-
if (e.throwOnError &&
|
|
1223
|
-
const
|
|
1224
|
-
stdout:
|
|
1225
|
-
stderr:
|
|
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) {
|
|
1232
|
+
const a = {
|
|
1233
|
+
stdout: i.text,
|
|
1234
|
+
stderr: i.errors
|
|
1226
1235
|
};
|
|
1227
|
-
console.warn("PHP.run() output was:",
|
|
1236
|
+
console.warn("PHP.run() output was:", a);
|
|
1228
1237
|
const c = new Error(
|
|
1229
|
-
`PHP.run() failed with exit code ${
|
|
1238
|
+
`PHP.run() failed with exit code ${i.exitCode} and the following output: ` + i.errors
|
|
1230
1239
|
);
|
|
1231
|
-
throw c.output =
|
|
1240
|
+
throw c.output = a, console.error(c), c;
|
|
1232
1241
|
}
|
|
1233
|
-
return
|
|
1242
|
+
return i;
|
|
1243
|
+
} catch (s) {
|
|
1244
|
+
throw this.dispatchEvent({
|
|
1245
|
+
type: "request.error",
|
|
1246
|
+
error: s
|
|
1247
|
+
}), s;
|
|
1234
1248
|
} finally {
|
|
1235
1249
|
try {
|
|
1236
1250
|
r && this[__private__dont__use].free(r);
|
|
@@ -1242,7 +1256,7 @@ class BasePHP {
|
|
|
1242
1256
|
}
|
|
1243
1257
|
}
|
|
1244
1258
|
addServerGlobalEntry(e, t) {
|
|
1245
|
-
|
|
1259
|
+
l(this, g)[e] = t;
|
|
1246
1260
|
}
|
|
1247
1261
|
defineConstant(e, t) {
|
|
1248
1262
|
let r = {};
|
|
@@ -1338,7 +1352,7 @@ class BasePHP {
|
|
|
1338
1352
|
this.exit();
|
|
1339
1353
|
} catch {
|
|
1340
1354
|
}
|
|
1341
|
-
if (this.initializeRuntime(e),
|
|
1355
|
+
if (this.initializeRuntime(e), l(this, T) && this.setPhpIniPath(l(this, T)), l(this, A) && this.setSapiName(l(this, A)), this.requestHandler) {
|
|
1342
1356
|
const r = this.documentRoot;
|
|
1343
1357
|
copyFS(t, this[__private__dont__use].FS, r);
|
|
1344
1358
|
}
|
|
@@ -1354,7 +1368,7 @@ class BasePHP {
|
|
|
1354
1368
|
h(this, y, !1), h(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
|
|
1355
1369
|
}
|
|
1356
1370
|
}
|
|
1357
|
-
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(),
|
|
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() {
|
|
1358
1372
|
if (this.setPhpIniEntry("auto_prepend_file", "/internal/consts.php"), this.fileExists("/internal/consts.php") || this.writeFile(
|
|
1359
1373
|
"/internal/consts.php",
|
|
1360
1374
|
`<?php
|
|
@@ -1366,8 +1380,8 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1366
1380
|
}
|
|
1367
1381
|
}
|
|
1368
1382
|
}`
|
|
1369
|
-
),
|
|
1370
|
-
const e =
|
|
1383
|
+
), l(this, S).length > 0) {
|
|
1384
|
+
const e = l(this, S).map(([t, r]) => `${t}=${r}`).join(`
|
|
1371
1385
|
`) + `
|
|
1372
1386
|
|
|
1373
1387
|
`;
|
|
@@ -1379,7 +1393,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1379
1393
|
);
|
|
1380
1394
|
}
|
|
1381
1395
|
this[__private__dont__use].ccall("php_wasm_init", null, [], []);
|
|
1382
|
-
},
|
|
1396
|
+
}, L = new WeakSet(), X = function() {
|
|
1383
1397
|
const e = "/internal/headers.json";
|
|
1384
1398
|
if (!this.fileExists(e))
|
|
1385
1399
|
throw new Error(
|
|
@@ -1389,14 +1403,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1389
1403
|
for (const s of t.headers) {
|
|
1390
1404
|
if (!s.includes(": "))
|
|
1391
1405
|
continue;
|
|
1392
|
-
const n = s.indexOf(": "),
|
|
1393
|
-
|
|
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);
|
|
1394
1408
|
}
|
|
1395
1409
|
return {
|
|
1396
1410
|
headers: r,
|
|
1397
1411
|
httpStatusCode: t.status
|
|
1398
1412
|
};
|
|
1399
|
-
},
|
|
1413
|
+
}, O = new WeakSet(), ee = function(e) {
|
|
1400
1414
|
if (this[__private__dont__use].ccall(
|
|
1401
1415
|
"wasm_set_request_uri",
|
|
1402
1416
|
null,
|
|
@@ -1411,7 +1425,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1411
1425
|
[t]
|
|
1412
1426
|
);
|
|
1413
1427
|
}
|
|
1414
|
-
},
|
|
1428
|
+
}, q = new WeakSet(), te = function(e, t) {
|
|
1415
1429
|
this[__private__dont__use].ccall(
|
|
1416
1430
|
"wasm_set_request_host",
|
|
1417
1431
|
null,
|
|
@@ -1429,14 +1443,14 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1429
1443
|
[NUMBER],
|
|
1430
1444
|
[r]
|
|
1431
1445
|
), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
|
|
1432
|
-
},
|
|
1446
|
+
}, M = new WeakSet(), re = function(e) {
|
|
1433
1447
|
this[__private__dont__use].ccall(
|
|
1434
1448
|
"wasm_set_request_method",
|
|
1435
1449
|
null,
|
|
1436
1450
|
[STRING],
|
|
1437
1451
|
[e]
|
|
1438
1452
|
);
|
|
1439
|
-
}, D = new WeakSet(),
|
|
1453
|
+
}, D = new WeakSet(), se = function(e) {
|
|
1440
1454
|
e.cookie && this[__private__dont__use].ccall(
|
|
1441
1455
|
"wasm_set_cookies",
|
|
1442
1456
|
null,
|
|
@@ -1460,7 +1474,7 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1460
1474
|
e[t]
|
|
1461
1475
|
);
|
|
1462
1476
|
}
|
|
1463
|
-
},
|
|
1477
|
+
}, $ = new WeakSet(), ne = function(e) {
|
|
1464
1478
|
let t, r;
|
|
1465
1479
|
typeof e == "string" ? (console.warn(
|
|
1466
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"
|
|
@@ -1483,59 +1497,59 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1483
1497
|
[NUMBER],
|
|
1484
1498
|
[r]
|
|
1485
1499
|
), s;
|
|
1486
|
-
},
|
|
1500
|
+
}, j = new WeakSet(), ie = function(e) {
|
|
1487
1501
|
this[__private__dont__use].ccall(
|
|
1488
1502
|
"wasm_set_path_translated",
|
|
1489
1503
|
null,
|
|
1490
1504
|
[STRING],
|
|
1491
1505
|
[e]
|
|
1492
1506
|
);
|
|
1493
|
-
}, W = new WeakSet(),
|
|
1494
|
-
for (const e in
|
|
1507
|
+
}, W = new WeakSet(), oe = function() {
|
|
1508
|
+
for (const e in l(this, g))
|
|
1495
1509
|
this[__private__dont__use].ccall(
|
|
1496
1510
|
"wasm_add_SERVER_entry",
|
|
1497
1511
|
null,
|
|
1498
1512
|
[STRING, STRING],
|
|
1499
|
-
[e,
|
|
1513
|
+
[e, l(this, g)[e]]
|
|
1500
1514
|
);
|
|
1501
|
-
},
|
|
1515
|
+
}, z = new WeakSet(), ae = function(e, t) {
|
|
1502
1516
|
this[__private__dont__use].ccall(
|
|
1503
1517
|
"wasm_add_ENV_entry",
|
|
1504
1518
|
null,
|
|
1505
1519
|
[STRING, STRING],
|
|
1506
1520
|
[e, t]
|
|
1507
1521
|
);
|
|
1508
|
-
},
|
|
1522
|
+
}, G = new WeakSet(), le = function(e) {
|
|
1509
1523
|
this[__private__dont__use].ccall(
|
|
1510
1524
|
"wasm_set_php_code",
|
|
1511
1525
|
null,
|
|
1512
1526
|
[STRING],
|
|
1513
1527
|
[e]
|
|
1514
1528
|
);
|
|
1515
|
-
},
|
|
1529
|
+
}, V = new WeakSet(), ce = async function() {
|
|
1516
1530
|
var n;
|
|
1517
1531
|
let e, t;
|
|
1518
1532
|
try {
|
|
1519
|
-
e = await new Promise((
|
|
1533
|
+
e = await new Promise((o, i) => {
|
|
1520
1534
|
var c;
|
|
1521
1535
|
t = (d) => {
|
|
1522
1536
|
console.error(d), console.error(d.error);
|
|
1523
|
-
const
|
|
1524
|
-
|
|
1525
|
-
}, (c =
|
|
1537
|
+
const _ = new Error("Rethrown");
|
|
1538
|
+
_.cause = d.error, _.betterMessage = d.message, i(_);
|
|
1539
|
+
}, (c = l(this, w)) == null || c.addEventListener(
|
|
1526
1540
|
"error",
|
|
1527
1541
|
t
|
|
1528
1542
|
);
|
|
1529
|
-
const
|
|
1543
|
+
const a = this[__private__dont__use].ccall(
|
|
1530
1544
|
"wasm_sapi_handle_request",
|
|
1531
1545
|
NUMBER,
|
|
1532
1546
|
[],
|
|
1533
1547
|
[],
|
|
1534
1548
|
{ async: !0 }
|
|
1535
1549
|
);
|
|
1536
|
-
return
|
|
1550
|
+
return a instanceof Promise ? a.then(o, i) : o(a);
|
|
1537
1551
|
});
|
|
1538
|
-
} catch (
|
|
1552
|
+
} catch (o) {
|
|
1539
1553
|
for (const d in this)
|
|
1540
1554
|
typeof this[d] == "function" && (this[d] = () => {
|
|
1541
1555
|
throw new Error(
|
|
@@ -1543,12 +1557,12 @@ S = new WeakMap(), T = new WeakMap(), A = new WeakMap(), y = new WeakMap(), w =
|
|
|
1543
1557
|
);
|
|
1544
1558
|
});
|
|
1545
1559
|
this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
|
|
1546
|
-
const
|
|
1547
|
-
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;
|
|
1548
1562
|
} finally {
|
|
1549
|
-
(n =
|
|
1563
|
+
(n = l(this, w)) == null || n.removeEventListener("error", t), h(this, g, {});
|
|
1550
1564
|
}
|
|
1551
|
-
const { headers: r, httpStatusCode: s } = f(this,
|
|
1565
|
+
const { headers: r, httpStatusCode: s } = f(this, L, X).call(this);
|
|
1552
1566
|
return new PHPResponse(
|
|
1553
1567
|
s,
|
|
1554
1568
|
r,
|
|
@@ -1607,9 +1621,9 @@ function copyFS(e, t, r) {
|
|
|
1607
1621
|
return;
|
|
1608
1622
|
}
|
|
1609
1623
|
t.mkdirTree(r);
|
|
1610
|
-
const n = e.readdir(r).filter((
|
|
1611
|
-
for (const
|
|
1612
|
-
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));
|
|
1613
1627
|
}
|
|
1614
1628
|
function isLocalPHP(e) {
|
|
1615
1629
|
return !(e instanceof BasePHP);
|
|
@@ -1627,11 +1641,11 @@ function rotatePHPRuntime({
|
|
|
1627
1641
|
if (++s < r)
|
|
1628
1642
|
return;
|
|
1629
1643
|
s = 0;
|
|
1630
|
-
const
|
|
1644
|
+
const o = await e.semaphore.acquire();
|
|
1631
1645
|
try {
|
|
1632
1646
|
e.hotSwapPHPRuntime(await t());
|
|
1633
1647
|
} finally {
|
|
1634
|
-
|
|
1648
|
+
o();
|
|
1635
1649
|
}
|
|
1636
1650
|
}
|
|
1637
1651
|
return e.addEventListener("request.end", n), function() {
|
|
@@ -1640,9 +1654,9 @@ function rotatePHPRuntime({
|
|
|
1640
1654
|
}
|
|
1641
1655
|
async function writeFiles(e, t, r, { rmRoot: s = !1 } = {}) {
|
|
1642
1656
|
s && await e.isDir(t) && await e.rmdir(t, { recursive: !0 });
|
|
1643
|
-
for (const [n,
|
|
1644
|
-
const
|
|
1645
|
-
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);
|
|
1646
1660
|
}
|
|
1647
1661
|
}
|
|
1648
1662
|
export {
|
|
@@ -1658,6 +1672,7 @@ export {
|
|
|
1658
1672
|
SupportedPHPVersionsList,
|
|
1659
1673
|
UnhandledRejectionsTarget,
|
|
1660
1674
|
__private__dont__use,
|
|
1675
|
+
applyRewriteRules,
|
|
1661
1676
|
ensurePathPrefix,
|
|
1662
1677
|
isExitCodeZero,
|
|
1663
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"
|