@php-wasm/universal 0.6.3 → 0.6.4
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 +11 -11
- package/index.js +179 -143
- package/lib/base-php.d.ts +8 -0
- package/lib/universal-php.d.ts +4 -0
- 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 a=(e,t,r)=>(J(e,t,"read from private field"),r?r.call(e):t.get(e)),
|
|
1
|
+
"use strict";var J=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var a=(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"});if(typeof File>"u"){class e extends Blob{constructor(r,s,n){super(r);let i;n!=null&&n.lastModified&&(i=new Date),(!i||isNaN(i.getFullYear()))&&(i=new Date),this.lastModifiedDate=i,this.lastModified=i.getMilliseconds(),this.name=s||""}}global.File=e}function asPromise(e){return new Promise(function(t,r){e.onload=e.onerror=function(s){e.onload=e.onerror=null,s.type==="load"?t(e.result):r(new Error("Failed to read the blob/file"))}})}typeof Blob.prototype.arrayBuffer>"u"&&(Blob.prototype.arrayBuffer=function(){const t=new FileReader;return t.readAsArrayBuffer(this),asPromise(t)});typeof Blob.prototype.text>"u"&&(Blob.prototype.text=function(){const t=new FileReader;return t.readAsText(this),asPromise(t)});function isByobSupported(){const e=new Uint8Array([1,2,3,4]),r=new File([e],"test").stream();try{return r.getReader({mode:"byob"}),!0}catch{return!1}}(typeof Blob.prototype.stream>"u"||!isByobSupported())&&(Blob.prototype.stream=function(){let e=0;const t=this;return new ReadableStream({type:"bytes",autoAllocateChunkSize:512*1024,async pull(r){const s=r.byobRequest.view,i=await t.slice(e,e+s.byteLength).arrayBuffer(),o=new Uint8Array(i);new Uint8Array(s.buffer).set(o);const l=o.byteLength;r.byobRequest.respond(l),e+=l,e>=t.size&&r.close()}})});if(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 i;try{return s(...n)}catch(o){if(!(o instanceof Error))throw o;const l=clarifyErrorMessage(o,(i=e.lastAsyncifyStackSource)==null?void 0:i.stack);if(e.lastAsyncifyStackSource&&(o.cause=e.lastAsyncifyStackSource),t.hasListeners()){t.dispatchEvent(new ErrorEvent("error",{error:o,message:l}));return}throw isExitCodeZero(o)||showCriticalErrorBox(l),o}}}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,21 +32,21 @@ 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 createSpawnHandler(e){return function(t){const
|
|
36
|
-
`),n.push(`Content-Disposition: form-data; name="${
|
|
37
|
-
`),
|
|
38
|
-
|
|
39
|
-
`),
|
|
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 i=[];let o="";for(let l=0;l<e.length;l++){const c=e[l];c==="\\"?((e[l+1]==='"'||e[l+1]==="'")&&l++,o+=e[l]):s===0?c==='"'||c==="'"?(s=1,n=c):c.match(/\s/)?(o.trim().length&&i.push(o.trim()),o=c):i.length&&!o?o=i.pop()+c:o+=c:s===1&&(c===n?(s=0,n=""):o+=c)}return o&&i.push(o.trim()),i}function createSpawnHandler(e){return function(t,r=[],s={}){const n=new ChildProcess,i=new ProcessApi(n);return setTimeout(async()=>{let o=[];if(r.length)o=[t,...r];else if(typeof t=="string")o=splitShellCommand(t);else if(Array.isArray(t))o=t;else throw new Error("Invalid command ",t);await e(o,i,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:i,done:o}=await r.read(new Uint8Array(t-s));if(o){r.releaseLock(),n.close();return}s+=i.length,n.enqueue(i),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 i=[t];for(;i.length;){const o=i.pop();if(!o)return;const l=await e.listFiles(o);for(const c of l){const d=`${o}/${c}`;if(n.includes(d.substring(t.length+1)))continue;await e.isDir(d)?i.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="",i=0){this.httpStatusCode=t,this.headers=r,this.bytes=s,this.exitCode=i,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"]),a(this,b).handleRedirects&&s.headers.location&&r<a(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),i=r.substring(s+1).split(";")[0];a(this,E)[n]=i}catch(s){console.error(s)}}serializeCookies(){const t=[];for(const r in a(this,E))t.push(`${r}=${a(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
|
+
`),n.push(`Content-Disposition: form-data; name="${c}"`),d instanceof File&&n.push(`; filename="${d.name}"`),n.push(`\r
|
|
37
|
+
`),d instanceof File&&(n.push("Content-Type: application/octet-stream"),n.push(`\r
|
|
38
|
+
`)),n.push(`\r
|
|
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((d,u)=>d+u.length,0),o=new Uint8Array(i);let l=0;for(const d of n)o.set(typeof d=="string"?s.encode(d):d,l),l+=d.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 P,x,k,v,H,_,F,R,L,Y,U,Z,I,K;class PHPRequestHandler{constructor(t,r={}){c(this,L);c(this,U);c(this,I);c(this,P,void 0);c(this,x,void 0);c(this,k,void 0);c(this,v,void 0);c(this,H,void 0);c(this,_,void 0);c(this,F,void 0);c(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,P,s);const i=new URL(n);h(this,k,i.hostname),h(this,v,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,x,(i.protocol||"").replace(":",""));const o=a(this,v)!==443&&a(this,v)!==80;h(this,H,[a(this,k),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,P)}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,P)}${n}`;return seemsLikeAPHPRequestHandlerPath(i)?await p(this,U,Z).call(this,t,s):p(this,L,Y).call(this,i)}}P=new WeakMap,x=new WeakMap,k=new WeakMap,v=new WeakMap,H=new WeakMap,_=new WeakMap,F=new WeakMap,R=new WeakMap,L=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)},U=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,P)),this.php.addServerGlobalEntry("HTTPS",a(this,F).startsWith("https://")?"on":"");let o="GET";const l={host:a(this,H),...normalizeHeaders(t.headers||{})};let d=t.body;if(typeof d=="object"&&!(d instanceof Uint8Array)){o="POST";const{bytes:f,contentType:B}=await encodeAsMultipart(d);d=f,l["content-type"]=B}let u;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{}u=p(this,I,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:d,scriptPath:u,headers:l})}finally{s()}},I=new WeakSet,K=function(t){let r=removePathPrefix(t,a(this,_));r.includes(".php")?r=r.split(".php")[0]+".php":(r.endsWith("/")||(r+="/"),r.endsWith("index.php")||(r+="index.php"));const s=`${a(this,P)}${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 d=typeof l=="object"?l==null?void 0:l.errno:null;if(d in FileErrorCodes){const u=FileErrorCodes[d],f=typeof o[0]=="string"?o[0]:null,B=f!==null?e.replaceAll("{path}",f):e;throw new Error(`${B}: ${u}`,{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 b,T,A,m,w,g,y,C,q,Q,N,X,M,ee,$,te,O,re,D,se,j,ne,z,ie,W,oe,G,ae,V,le;class BasePHP{constructor(e,t){c(this,q);c(this,N);c(this,M);c(this,$);c(this,O);c(this,D);c(this,j);c(this,z);c(this,W);c(this,G);c(this,V);c(this,b,void 0);c(this,T,void 0);c(this,A,void 0);c(this,m,void 0);c(this,w,void 0);c(this,g,void 0);c(this,y,void 0);c(this,C,void 0);h(this,b,[]),h(this,m,!1),h(this,w,null),h(this,g,{}),h(this,y,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,y).has(e)||a(this,y).set(e,new Set),a(this,y).get(e).add(t)}removeEventListener(e,t){var r;(r=a(this,y).get(e))==null||r.delete(t)}dispatchEvent(e){const t=a(this,y).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,m))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,m))throw new Error("Cannot set PHP ini entries after calling run().");a(this,b).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{a(this,m)||(p(this,q,Q).call(this),h(this,m,!0)),p(this,z,ie).call(this,e.scriptPath||""),p(this,M,ee).call(this,e.relativeUri||""),p(this,O,re).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";p(this,$,te).call(this,n,e.protocol||"http"),p(this,D,se).call(this,s),e.body&&(r=p(this,j,ne).call(this,e.body)),typeof e.code=="string"&&p(this,G,ae).call(this," ?>"+e.code),p(this,W,oe).call(this);const i=await p(this,V,le).call(this);if(e.throwOnError&&i.exitCode!==0){const o={stdout:i.text,stderr:i.errors};console.warn("PHP.run() output was:",o);const l=new Error(`PHP.run() failed with exit code ${i.exitCode} and the following output`);throw l.output=o,l}return i}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("/tmp/consts.json")&&this.readFileAsText("/tmp/consts.json")||"{}")}catch{}this.writeFile("/tmp/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;recreateMemFS(this[__private__dont__use].FS,t,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}h(this,m,!1),h(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}b=new WeakMap,T=new WeakMap,A=new WeakMap,m=new WeakMap,w=new WeakMap,g=new WeakMap,y=new WeakMap,C=new WeakMap,q=new WeakSet,Q=function(){if(this.setPhpIniEntry("auto_prepend_file","/tmp/consts.php"),this.fileExists("/tmp/consts.php")||this.writeFile("/tmp/consts.php",`<?php
|
|
42
|
-
if(file_exists('/
|
|
43
|
-
$consts = json_decode(file_get_contents('/
|
|
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
|
|
42
|
+
if(file_exists('/internal/consts.json')) {
|
|
43
|
+
$consts = json_decode(file_get_contents('/internal/consts.json'), true);
|
|
44
44
|
foreach ($consts as $const => $value) {
|
|
45
45
|
if (!defined($const) && is_scalar($value)) {
|
|
46
46
|
define($const, $value);
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
}`),a(this,
|
|
49
|
+
}`),a(this,S).length>0){const e=a(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,[],[])},M=new WeakSet,ee=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(": "),i=s.substring(0,n).toLowerCase(),o=s.substring(n+2);i in r||(r[i]=[]),r[i].push(o)}return{headers:r,httpStatusCode:t.status}},q=new WeakSet,te=function(e){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[t])}},O=new WeakSet,re=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")},D=new WeakSet,se=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},$=new WeakSet,ne=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])}},j=new WeakSet,ie=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},z=new WeakSet,oe=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},W=new WeakSet,ae=function(){for(const e in a(this,g))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,a(this,g)[e]])},G=new WeakSet,le=function(e,t){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[e,t])},V=new WeakSet,ce=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},Q=new WeakSet,ue=async function(){var n;let e,t;try{e=await new Promise((i,o)=>{var c;t=d=>{console.error(d),console.error(d.error);const f=new Error("Rethrown");f.cause=d.error,f.betterMessage=d.message,o(f)},(c=a(this,w))==null||c.addEventListener("error",t);const l=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return l instanceof Promise?l.then(i,o):i(l)})}catch(i){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 o=i,l="betterMessage"in o?o.betterMessage:o.message,c=new Error(l);throw c.cause=o,console.error(c),c}finally{(n=a(this,w))==null||n.removeEventListener("error",t),h(this,g,{})}const{headers:r,httpStatusCode:s}=p(this,M,ee).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(i=>i!=="."&&i!=="..");for(const i of n)copyFS(e,t,joinPaths(r,i))}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 i=await e.semaphore.acquire();try{e.hotSwapPHPRuntime(await t())}finally{i()}}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,i]of Object.entries(r)){const o=joinPaths(t,n);await e.fileExists(dirname(o))||await e.mkdir(dirname(o)),await e.writeFile(o,i)}}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.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,7 +2,7 @@ var J = (e, t, r) => {
|
|
|
2
2
|
if (!t.has(e))
|
|
3
3
|
throw TypeError("Cannot " + r);
|
|
4
4
|
};
|
|
5
|
-
var a = (e, t, r) => (J(e, t, "read from private field"), r ? r.call(e) : t.get(e)),
|
|
5
|
+
var a = (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);
|
|
@@ -274,12 +274,31 @@ function normalizePathsArray(e, t) {
|
|
|
274
274
|
e.unshift("..");
|
|
275
275
|
return e;
|
|
276
276
|
}
|
|
277
|
+
function splitShellCommand(e) {
|
|
278
|
+
let s = 0, n = "";
|
|
279
|
+
const i = [];
|
|
280
|
+
let o = "";
|
|
281
|
+
for (let l = 0; l < e.length; l++) {
|
|
282
|
+
const c = e[l];
|
|
283
|
+
c === "\\" ? ((e[l + 1] === '"' || e[l + 1] === "'") && l++, o += e[l]) : s === 0 ? c === '"' || c === "'" ? (s = 1, n = c) : c.match(/\s/) ? (o.trim().length && i.push(o.trim()), o = c) : i.length && !o ? o = i.pop() + c : o += c : s === 1 && (c === n ? (s = 0, n = "") : o += c);
|
|
284
|
+
}
|
|
285
|
+
return o && i.push(o.trim()), i;
|
|
286
|
+
}
|
|
277
287
|
function createSpawnHandler(e) {
|
|
278
|
-
return function(t) {
|
|
279
|
-
const
|
|
288
|
+
return function(t, r = [], s = {}) {
|
|
289
|
+
const n = new ChildProcess(), i = new ProcessApi(n);
|
|
280
290
|
return setTimeout(async () => {
|
|
281
|
-
|
|
282
|
-
|
|
291
|
+
let o = [];
|
|
292
|
+
if (r.length)
|
|
293
|
+
o = [t, ...r];
|
|
294
|
+
else if (typeof t == "string")
|
|
295
|
+
o = splitShellCommand(t);
|
|
296
|
+
else if (Array.isArray(t))
|
|
297
|
+
o = t;
|
|
298
|
+
else
|
|
299
|
+
throw new Error("Invalid command ", t);
|
|
300
|
+
await e(o, i, s), n.emit("spawn", !0);
|
|
301
|
+
}), n;
|
|
283
302
|
};
|
|
284
303
|
}
|
|
285
304
|
class EventEmitter {
|
|
@@ -304,9 +323,15 @@ class ProcessApi extends EventEmitter {
|
|
|
304
323
|
stdout(t) {
|
|
305
324
|
typeof t == "string" && (t = new TextEncoder().encode(t)), this.childProcess.stdout.emit("data", t);
|
|
306
325
|
}
|
|
326
|
+
stdoutEnd() {
|
|
327
|
+
this.childProcess.stdout.emit("end", {});
|
|
328
|
+
}
|
|
307
329
|
stderr(t) {
|
|
308
330
|
typeof t == "string" && (t = new TextEncoder().encode(t)), this.childProcess.stderr.emit("data", t);
|
|
309
331
|
}
|
|
332
|
+
stderrEnd() {
|
|
333
|
+
this.childProcess.stderr.emit("end", {});
|
|
334
|
+
}
|
|
310
335
|
exit(t) {
|
|
311
336
|
this.exited || (this.exited = !0, this.childProcess.emit("exit", t));
|
|
312
337
|
}
|
|
@@ -468,16 +493,16 @@ async function* iteratePhpFiles(e, t, {
|
|
|
468
493
|
if (!o)
|
|
469
494
|
return;
|
|
470
495
|
const l = await e.listFiles(o);
|
|
471
|
-
for (const
|
|
472
|
-
const
|
|
473
|
-
if (n.includes(
|
|
496
|
+
for (const c of l) {
|
|
497
|
+
const d = `${o}/${c}`;
|
|
498
|
+
if (n.includes(d.substring(t.length + 1)))
|
|
474
499
|
continue;
|
|
475
|
-
await e.isDir(
|
|
476
|
-
streamReadFileFromPHP(e,
|
|
500
|
+
await e.isDir(d) ? i.push(d) : yield new StreamedFile(
|
|
501
|
+
streamReadFileFromPHP(e, d),
|
|
477
502
|
r ? joinPaths(
|
|
478
503
|
s || "",
|
|
479
|
-
|
|
480
|
-
) :
|
|
504
|
+
d.substring(t.length + 1)
|
|
505
|
+
) : d
|
|
481
506
|
);
|
|
482
507
|
}
|
|
483
508
|
}
|
|
@@ -546,16 +571,16 @@ const SupportedPHPVersions = [
|
|
|
546
571
|
], SupportedPHPExtensionBundles = {
|
|
547
572
|
"kitchen-sink": SupportedPHPExtensionsList
|
|
548
573
|
};
|
|
549
|
-
var E,
|
|
574
|
+
var E, b;
|
|
550
575
|
class PHPBrowser {
|
|
551
576
|
/**
|
|
552
577
|
* @param server - The PHP server to browse.
|
|
553
578
|
* @param config - The browser configuration.
|
|
554
579
|
*/
|
|
555
580
|
constructor(t, r = {}) {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
this.requestHandler = t, h(this, E, {}), h(this,
|
|
581
|
+
u(this, E, void 0);
|
|
582
|
+
u(this, b, void 0);
|
|
583
|
+
this.requestHandler = t, h(this, E, {}), h(this, b, {
|
|
559
584
|
handleRedirects: !1,
|
|
560
585
|
maxRedirects: 4,
|
|
561
586
|
...r
|
|
@@ -583,7 +608,7 @@ class PHPBrowser {
|
|
|
583
608
|
cookie: this.serializeCookies()
|
|
584
609
|
}
|
|
585
610
|
});
|
|
586
|
-
if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), a(this,
|
|
611
|
+
if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), a(this, b).handleRedirects && s.headers.location && r < a(this, b).maxRedirects) {
|
|
587
612
|
const n = new URL(
|
|
588
613
|
s.headers.location[0],
|
|
589
614
|
this.requestHandler.absoluteUrl
|
|
@@ -633,7 +658,7 @@ class PHPBrowser {
|
|
|
633
658
|
return t.join("; ");
|
|
634
659
|
}
|
|
635
660
|
}
|
|
636
|
-
E = new WeakMap(),
|
|
661
|
+
E = new WeakMap(), b = new WeakMap();
|
|
637
662
|
const DEFAULT_BASE_URL = "http://example.com";
|
|
638
663
|
function toRelativeUrl(e) {
|
|
639
664
|
return e.toString().substring(e.origin.length);
|
|
@@ -646,22 +671,22 @@ function ensurePathPrefix(e, t) {
|
|
|
646
671
|
}
|
|
647
672
|
async function encodeAsMultipart(e) {
|
|
648
673
|
const t = `----${Math.random().toString(36).slice(2)}`, r = `multipart/form-data; boundary=${t}`, s = new TextEncoder(), n = [];
|
|
649
|
-
for (const [
|
|
674
|
+
for (const [c, d] of Object.entries(e))
|
|
650
675
|
n.push(`--${t}\r
|
|
651
|
-
`), n.push(`Content-Disposition: form-data; name="${
|
|
652
|
-
`),
|
|
653
|
-
|
|
654
|
-
`),
|
|
676
|
+
`), n.push(`Content-Disposition: form-data; name="${c}"`), d instanceof File && n.push(`; filename="${d.name}"`), n.push(`\r
|
|
677
|
+
`), d instanceof File && (n.push("Content-Type: application/octet-stream"), n.push(`\r
|
|
678
|
+
`)), n.push(`\r
|
|
679
|
+
`), d instanceof File ? n.push(await fileToUint8Array(d)) : n.push(d), n.push(`\r
|
|
655
680
|
`);
|
|
656
681
|
n.push(`--${t}--\r
|
|
657
682
|
`);
|
|
658
|
-
const i = n.reduce((
|
|
683
|
+
const i = n.reduce((c, d) => c + d.length, 0), o = new Uint8Array(i);
|
|
659
684
|
let l = 0;
|
|
660
|
-
for (const
|
|
685
|
+
for (const c of n)
|
|
661
686
|
o.set(
|
|
662
|
-
typeof
|
|
687
|
+
typeof c == "string" ? s.encode(c) : c,
|
|
663
688
|
l
|
|
664
|
-
), l +=
|
|
689
|
+
), l += c.length;
|
|
665
690
|
return { bytes: o, contentType: r };
|
|
666
691
|
}
|
|
667
692
|
function fileToUint8Array(e) {
|
|
@@ -672,7 +697,7 @@ function fileToUint8Array(e) {
|
|
|
672
697
|
}, r.readAsArrayBuffer(e);
|
|
673
698
|
});
|
|
674
699
|
}
|
|
675
|
-
var
|
|
700
|
+
var m, H, k, v, x, _, F, R, B, Y, I, Z, L, K;
|
|
676
701
|
class PHPRequestHandler {
|
|
677
702
|
/**
|
|
678
703
|
* @param php - The PHP instance.
|
|
@@ -685,7 +710,7 @@ class PHPRequestHandler {
|
|
|
685
710
|
* @param fsPath - Absolute path of the static file to serve.
|
|
686
711
|
* @returns The response.
|
|
687
712
|
*/
|
|
688
|
-
|
|
713
|
+
u(this, B);
|
|
689
714
|
/**
|
|
690
715
|
* Runs the requested PHP file with all the request and $_SERVER
|
|
691
716
|
* superglobals populated.
|
|
@@ -693,7 +718,7 @@ class PHPRequestHandler {
|
|
|
693
718
|
* @param request - The request.
|
|
694
719
|
* @returns The response.
|
|
695
720
|
*/
|
|
696
|
-
|
|
721
|
+
u(this, I);
|
|
697
722
|
/**
|
|
698
723
|
* Resolve the requested path to the filesystem path of the requested PHP file.
|
|
699
724
|
*
|
|
@@ -703,21 +728,21 @@ class PHPRequestHandler {
|
|
|
703
728
|
* @throws {Error} If the requested path doesn't exist.
|
|
704
729
|
* @returns The resolved filesystem path.
|
|
705
730
|
*/
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
731
|
+
u(this, L);
|
|
732
|
+
u(this, m, void 0);
|
|
733
|
+
u(this, H, void 0);
|
|
734
|
+
u(this, k, void 0);
|
|
735
|
+
u(this, v, void 0);
|
|
736
|
+
u(this, x, void 0);
|
|
737
|
+
u(this, _, void 0);
|
|
738
|
+
u(this, F, void 0);
|
|
739
|
+
u(this, R, void 0);
|
|
715
740
|
h(this, R, new Semaphore({ concurrency: 1 }));
|
|
716
741
|
const {
|
|
717
742
|
documentRoot: s = "/www/",
|
|
718
743
|
absoluteUrl: n = typeof location == "object" ? location == null ? void 0 : location.href : ""
|
|
719
744
|
} = r;
|
|
720
|
-
this.php = t, h(this,
|
|
745
|
+
this.php = t, h(this, m, s);
|
|
721
746
|
const i = new URL(n);
|
|
722
747
|
h(this, k, i.hostname), h(this, v, i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80), h(this, H, (i.protocol || "").replace(":", ""));
|
|
723
748
|
const o = a(this, v) !== 443 && a(this, v) !== 80;
|
|
@@ -748,7 +773,7 @@ class PHPRequestHandler {
|
|
|
748
773
|
}
|
|
749
774
|
/** @inheritDoc */
|
|
750
775
|
get documentRoot() {
|
|
751
|
-
return a(this,
|
|
776
|
+
return a(this, m);
|
|
752
777
|
}
|
|
753
778
|
/** @inheritDoc */
|
|
754
779
|
async request(t) {
|
|
@@ -758,11 +783,11 @@ class PHPRequestHandler {
|
|
|
758
783
|
), n = removePathPrefix(
|
|
759
784
|
s.pathname,
|
|
760
785
|
a(this, _)
|
|
761
|
-
), i = `${a(this,
|
|
762
|
-
return seemsLikeAPHPRequestHandlerPath(i) ? await f(this, I, Z).call(this, t, s) : f(this,
|
|
786
|
+
), i = `${a(this, m)}${n}`;
|
|
787
|
+
return seemsLikeAPHPRequestHandlerPath(i) ? await f(this, I, Z).call(this, t, s) : f(this, B, Y).call(this, i);
|
|
763
788
|
}
|
|
764
789
|
}
|
|
765
|
-
|
|
790
|
+
m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x = new WeakMap(), _ = new WeakMap(), F = new WeakMap(), R = new WeakMap(), B = new WeakSet(), Y = function(t) {
|
|
766
791
|
if (!this.php.fileExists(t))
|
|
767
792
|
return new PHPResponse(
|
|
768
793
|
404,
|
|
@@ -799,7 +824,7 @@ P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
799
824
|
);
|
|
800
825
|
const s = await a(this, R).acquire();
|
|
801
826
|
try {
|
|
802
|
-
this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", a(this,
|
|
827
|
+
this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", a(this, m)), this.php.addServerGlobalEntry(
|
|
803
828
|
"HTTPS",
|
|
804
829
|
a(this, F).startsWith("https://") ? "on" : ""
|
|
805
830
|
);
|
|
@@ -808,13 +833,13 @@ P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
808
833
|
host: a(this, x),
|
|
809
834
|
...normalizeHeaders(t.headers || {})
|
|
810
835
|
};
|
|
811
|
-
let
|
|
812
|
-
if (typeof
|
|
836
|
+
let c = t.body;
|
|
837
|
+
if (typeof c == "object" && !(c instanceof Uint8Array)) {
|
|
813
838
|
o = "POST";
|
|
814
|
-
const { bytes: p, contentType:
|
|
815
|
-
|
|
839
|
+
const { bytes: p, contentType: U } = await encodeAsMultipart(c);
|
|
840
|
+
c = p, l["content-type"] = U;
|
|
816
841
|
}
|
|
817
|
-
let
|
|
842
|
+
let d;
|
|
818
843
|
try {
|
|
819
844
|
let p = r.pathname;
|
|
820
845
|
if ((i = t.headers) != null && i["x-rewrite-url"])
|
|
@@ -824,7 +849,7 @@ P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
824
849
|
).pathname;
|
|
825
850
|
} catch {
|
|
826
851
|
}
|
|
827
|
-
|
|
852
|
+
d = f(this, L, K).call(this, p);
|
|
828
853
|
} catch {
|
|
829
854
|
return new PHPResponse(
|
|
830
855
|
404,
|
|
@@ -839,8 +864,8 @@ P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
839
864
|
),
|
|
840
865
|
protocol: a(this, H),
|
|
841
866
|
method: t.method || o,
|
|
842
|
-
body:
|
|
843
|
-
scriptPath:
|
|
867
|
+
body: c,
|
|
868
|
+
scriptPath: d,
|
|
844
869
|
headers: l
|
|
845
870
|
});
|
|
846
871
|
} finally {
|
|
@@ -848,8 +873,8 @@ P = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), x =
|
|
|
848
873
|
}
|
|
849
874
|
}, L = new WeakSet(), K = function(t) {
|
|
850
875
|
let r = removePathPrefix(t, a(this, _));
|
|
851
|
-
r.includes(".php") ? r = r.split(".php")[0] + ".php" : (r.endsWith("/") || (r
|
|
852
|
-
const s = `${a(this,
|
|
876
|
+
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";
|
|
877
|
+
const s = `${a(this, m)}${r}`;
|
|
853
878
|
if (this.php.fileExists(s))
|
|
854
879
|
return s;
|
|
855
880
|
throw new Error(`File not found: ${s}`);
|
|
@@ -994,10 +1019,10 @@ function rethrowFileSystemError(e = "") {
|
|
|
994
1019
|
try {
|
|
995
1020
|
return i.apply(this, o);
|
|
996
1021
|
} catch (l) {
|
|
997
|
-
const
|
|
998
|
-
if (
|
|
999
|
-
const
|
|
1000
|
-
throw new Error(`${
|
|
1022
|
+
const c = typeof l == "object" ? l == null ? void 0 : l.errno : null;
|
|
1023
|
+
if (c in FileErrorCodes) {
|
|
1024
|
+
const d = FileErrorCodes[c], p = typeof o[0] == "string" ? o[0] : null, U = p !== null ? e.replaceAll("{path}", p) : e;
|
|
1025
|
+
throw new Error(`${U}: ${d}`, {
|
|
1001
1026
|
cause: l
|
|
1002
1027
|
});
|
|
1003
1028
|
}
|
|
@@ -1048,7 +1073,7 @@ var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyD
|
|
|
1048
1073
|
return s && n && __defProp(t, r, n), n;
|
|
1049
1074
|
};
|
|
1050
1075
|
const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
|
|
1051
|
-
var
|
|
1076
|
+
var S, T, A, y, w, g, P, C, N, X, M, ee, q, te, O, re, $, se, D, ne, j, ie, z, oe, W, ae, G, le, V, ce, Q, ue;
|
|
1052
1077
|
class BasePHP {
|
|
1053
1078
|
/**
|
|
1054
1079
|
* Initializes a PHP runtime.
|
|
@@ -1058,38 +1083,39 @@ class BasePHP {
|
|
|
1058
1083
|
* @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
|
|
1059
1084
|
*/
|
|
1060
1085
|
constructor(e, t) {
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1086
|
+
u(this, N);
|
|
1087
|
+
u(this, M);
|
|
1088
|
+
u(this, q);
|
|
1089
|
+
u(this, O);
|
|
1090
|
+
u(this, $);
|
|
1091
|
+
u(this, D);
|
|
1092
|
+
u(this, j);
|
|
1093
|
+
u(this, z);
|
|
1094
|
+
u(this, W);
|
|
1095
|
+
u(this, G);
|
|
1096
|
+
u(this, V);
|
|
1097
|
+
u(this, Q);
|
|
1098
|
+
u(this, S, void 0);
|
|
1099
|
+
u(this, T, void 0);
|
|
1100
|
+
u(this, A, void 0);
|
|
1101
|
+
u(this, y, void 0);
|
|
1102
|
+
u(this, w, void 0);
|
|
1103
|
+
u(this, g, void 0);
|
|
1104
|
+
u(this, P, void 0);
|
|
1105
|
+
u(this, C, void 0);
|
|
1106
|
+
h(this, S, []), h(this, y, !1), h(this, w, null), h(this, g, {}), h(this, P, /* @__PURE__ */ new Map()), h(this, C, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new PHPBrowser(
|
|
1081
1107
|
new PHPRequestHandler(this, t)
|
|
1082
1108
|
));
|
|
1083
1109
|
}
|
|
1084
1110
|
addEventListener(e, t) {
|
|
1085
|
-
a(this,
|
|
1111
|
+
a(this, P).has(e) || a(this, P).set(e, /* @__PURE__ */ new Set()), a(this, P).get(e).add(t);
|
|
1086
1112
|
}
|
|
1087
1113
|
removeEventListener(e, t) {
|
|
1088
1114
|
var r;
|
|
1089
|
-
(r = a(this,
|
|
1115
|
+
(r = a(this, P).get(e)) == null || r.delete(t);
|
|
1090
1116
|
}
|
|
1091
1117
|
dispatchEvent(e) {
|
|
1092
|
-
const t = a(this,
|
|
1118
|
+
const t = a(this, P).get(e.type);
|
|
1093
1119
|
if (t)
|
|
1094
1120
|
for (const r of t)
|
|
1095
1121
|
r(e);
|
|
@@ -1152,7 +1178,7 @@ class BasePHP {
|
|
|
1152
1178
|
}
|
|
1153
1179
|
/** @inheritDoc */
|
|
1154
1180
|
setPhpIniPath(e) {
|
|
1155
|
-
if (a(this,
|
|
1181
|
+
if (a(this, y))
|
|
1156
1182
|
throw new Error("Cannot set PHP ini path after calling run().");
|
|
1157
1183
|
h(this, T, e), this[__private__dont__use].ccall(
|
|
1158
1184
|
"wasm_set_phpini_path",
|
|
@@ -1163,9 +1189,9 @@ class BasePHP {
|
|
|
1163
1189
|
}
|
|
1164
1190
|
/** @inheritDoc */
|
|
1165
1191
|
setPhpIniEntry(e, t) {
|
|
1166
|
-
if (a(this,
|
|
1192
|
+
if (a(this, y))
|
|
1167
1193
|
throw new Error("Cannot set PHP ini entries after calling run().");
|
|
1168
|
-
a(this,
|
|
1194
|
+
a(this, S).push([e, t]);
|
|
1169
1195
|
}
|
|
1170
1196
|
/** @inheritDoc */
|
|
1171
1197
|
chdir(e) {
|
|
@@ -1182,22 +1208,29 @@ class BasePHP {
|
|
|
1182
1208
|
const t = await this.semaphore.acquire();
|
|
1183
1209
|
let r;
|
|
1184
1210
|
try {
|
|
1185
|
-
a(this,
|
|
1211
|
+
if (a(this, y) || (f(this, N, X).call(this), h(this, y, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
|
|
1212
|
+
throw new Error(
|
|
1213
|
+
`The script path "${e.scriptPath}" does not exist.`
|
|
1214
|
+
);
|
|
1215
|
+
f(this, z, oe).call(this, e.scriptPath || ""), f(this, q, te).call(this, e.relativeUri || ""), f(this, $, se).call(this, e.method || "GET");
|
|
1186
1216
|
const s = normalizeHeaders(e.headers || {}), n = s.host || "example.com:443";
|
|
1187
|
-
f(this,
|
|
1188
|
-
const i =
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1217
|
+
f(this, O, re).call(this, n, e.protocol || "http"), f(this, D, ne).call(this, s), e.body && (r = f(this, j, ie).call(this, e.body)), typeof e.code == "string" && f(this, V, ce).call(this, " ?>" + e.code), f(this, W, ae).call(this);
|
|
1218
|
+
const i = e.env || {};
|
|
1219
|
+
for (const l in i)
|
|
1220
|
+
f(this, G, le).call(this, l, i[l]);
|
|
1221
|
+
const o = await f(this, Q, ue).call(this);
|
|
1222
|
+
if (e.throwOnError && o.exitCode !== 0) {
|
|
1223
|
+
const l = {
|
|
1224
|
+
stdout: o.text,
|
|
1225
|
+
stderr: o.errors
|
|
1193
1226
|
};
|
|
1194
|
-
console.warn("PHP.run() output was:",
|
|
1195
|
-
const
|
|
1196
|
-
`PHP.run() failed with exit code ${
|
|
1227
|
+
console.warn("PHP.run() output was:", l);
|
|
1228
|
+
const c = new Error(
|
|
1229
|
+
`PHP.run() failed with exit code ${o.exitCode} and the following output: ` + o.errors
|
|
1197
1230
|
);
|
|
1198
|
-
throw
|
|
1231
|
+
throw c.output = l, console.error(c), c;
|
|
1199
1232
|
}
|
|
1200
|
-
return
|
|
1233
|
+
return o;
|
|
1201
1234
|
} finally {
|
|
1202
1235
|
try {
|
|
1203
1236
|
r && this[__private__dont__use].free(r);
|
|
@@ -1215,12 +1248,12 @@ class BasePHP {
|
|
|
1215
1248
|
let r = {};
|
|
1216
1249
|
try {
|
|
1217
1250
|
r = JSON.parse(
|
|
1218
|
-
this.fileExists("/
|
|
1251
|
+
this.fileExists("/internal/consts.json") && this.readFileAsText("/internal/consts.json") || "{}"
|
|
1219
1252
|
);
|
|
1220
1253
|
} catch {
|
|
1221
1254
|
}
|
|
1222
1255
|
this.writeFile(
|
|
1223
|
-
"/
|
|
1256
|
+
"/internal/consts.json",
|
|
1224
1257
|
JSON.stringify({
|
|
1225
1258
|
...r,
|
|
1226
1259
|
[e]: t
|
|
@@ -1307,7 +1340,7 @@ class BasePHP {
|
|
|
1307
1340
|
}
|
|
1308
1341
|
if (this.initializeRuntime(e), a(this, T) && this.setPhpIniPath(a(this, T)), a(this, A) && this.setSapiName(a(this, A)), this.requestHandler) {
|
|
1309
1342
|
const r = this.documentRoot;
|
|
1310
|
-
|
|
1343
|
+
copyFS(t, this[__private__dont__use].FS, r);
|
|
1311
1344
|
}
|
|
1312
1345
|
}
|
|
1313
1346
|
exit(e = 0) {
|
|
@@ -1318,23 +1351,23 @@ class BasePHP {
|
|
|
1318
1351
|
this[__private__dont__use]._exit(e);
|
|
1319
1352
|
} catch {
|
|
1320
1353
|
}
|
|
1321
|
-
h(this,
|
|
1354
|
+
h(this, y, !1), h(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
|
|
1322
1355
|
}
|
|
1323
1356
|
}
|
|
1324
|
-
|
|
1325
|
-
if (this.setPhpIniEntry("auto_prepend_file", "/
|
|
1326
|
-
"/
|
|
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(), X = function() {
|
|
1358
|
+
if (this.setPhpIniEntry("auto_prepend_file", "/internal/consts.php"), this.fileExists("/internal/consts.php") || this.writeFile(
|
|
1359
|
+
"/internal/consts.php",
|
|
1327
1360
|
`<?php
|
|
1328
|
-
if(file_exists('/
|
|
1329
|
-
$consts = json_decode(file_get_contents('/
|
|
1361
|
+
if(file_exists('/internal/consts.json')) {
|
|
1362
|
+
$consts = json_decode(file_get_contents('/internal/consts.json'), true);
|
|
1330
1363
|
foreach ($consts as $const => $value) {
|
|
1331
1364
|
if (!defined($const) && is_scalar($value)) {
|
|
1332
1365
|
define($const, $value);
|
|
1333
1366
|
}
|
|
1334
1367
|
}
|
|
1335
1368
|
}`
|
|
1336
|
-
), a(this,
|
|
1337
|
-
const e = a(this,
|
|
1369
|
+
), a(this, S).length > 0) {
|
|
1370
|
+
const e = a(this, S).map(([t, r]) => `${t}=${r}`).join(`
|
|
1338
1371
|
`) + `
|
|
1339
1372
|
|
|
1340
1373
|
`;
|
|
@@ -1346,8 +1379,8 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
|
|
|
1346
1379
|
);
|
|
1347
1380
|
}
|
|
1348
1381
|
this[__private__dont__use].ccall("php_wasm_init", null, [], []);
|
|
1349
|
-
},
|
|
1350
|
-
const e = "/
|
|
1382
|
+
}, M = new WeakSet(), ee = function() {
|
|
1383
|
+
const e = "/internal/headers.json";
|
|
1351
1384
|
if (!this.fileExists(e))
|
|
1352
1385
|
throw new Error(
|
|
1353
1386
|
"SAPI Error: Could not find response headers file."
|
|
@@ -1363,7 +1396,7 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
|
|
|
1363
1396
|
headers: r,
|
|
1364
1397
|
httpStatusCode: t.status
|
|
1365
1398
|
};
|
|
1366
|
-
},
|
|
1399
|
+
}, q = new WeakSet(), te = function(e) {
|
|
1367
1400
|
if (this[__private__dont__use].ccall(
|
|
1368
1401
|
"wasm_set_request_uri",
|
|
1369
1402
|
null,
|
|
@@ -1378,7 +1411,7 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
|
|
|
1378
1411
|
[t]
|
|
1379
1412
|
);
|
|
1380
1413
|
}
|
|
1381
|
-
},
|
|
1414
|
+
}, O = new WeakSet(), re = function(e, t) {
|
|
1382
1415
|
this[__private__dont__use].ccall(
|
|
1383
1416
|
"wasm_set_request_host",
|
|
1384
1417
|
null,
|
|
@@ -1396,14 +1429,14 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
|
|
|
1396
1429
|
[NUMBER],
|
|
1397
1430
|
[r]
|
|
1398
1431
|
), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
|
|
1399
|
-
},
|
|
1432
|
+
}, $ = new WeakSet(), se = function(e) {
|
|
1400
1433
|
this[__private__dont__use].ccall(
|
|
1401
1434
|
"wasm_set_request_method",
|
|
1402
1435
|
null,
|
|
1403
1436
|
[STRING],
|
|
1404
1437
|
[e]
|
|
1405
1438
|
);
|
|
1406
|
-
}, D = new WeakSet(),
|
|
1439
|
+
}, D = new WeakSet(), ne = function(e) {
|
|
1407
1440
|
e.cookie && this[__private__dont__use].ccall(
|
|
1408
1441
|
"wasm_set_cookies",
|
|
1409
1442
|
null,
|
|
@@ -1427,7 +1460,7 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
|
|
|
1427
1460
|
e[t]
|
|
1428
1461
|
);
|
|
1429
1462
|
}
|
|
1430
|
-
}, j = new WeakSet(),
|
|
1463
|
+
}, j = new WeakSet(), ie = function(e) {
|
|
1431
1464
|
let t, r;
|
|
1432
1465
|
typeof e == "string" ? (console.warn(
|
|
1433
1466
|
"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"
|
|
@@ -1450,14 +1483,14 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
|
|
|
1450
1483
|
[NUMBER],
|
|
1451
1484
|
[r]
|
|
1452
1485
|
), s;
|
|
1453
|
-
}, z = new WeakSet(),
|
|
1486
|
+
}, z = new WeakSet(), oe = function(e) {
|
|
1454
1487
|
this[__private__dont__use].ccall(
|
|
1455
1488
|
"wasm_set_path_translated",
|
|
1456
1489
|
null,
|
|
1457
1490
|
[STRING],
|
|
1458
1491
|
[e]
|
|
1459
1492
|
);
|
|
1460
|
-
}, W = new WeakSet(),
|
|
1493
|
+
}, W = new WeakSet(), ae = function() {
|
|
1461
1494
|
for (const e in a(this, g))
|
|
1462
1495
|
this[__private__dont__use].ccall(
|
|
1463
1496
|
"wasm_add_SERVER_entry",
|
|
@@ -1465,23 +1498,31 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
|
|
|
1465
1498
|
[STRING, STRING],
|
|
1466
1499
|
[e, a(this, g)[e]]
|
|
1467
1500
|
);
|
|
1468
|
-
}, G = new WeakSet(),
|
|
1501
|
+
}, G = new WeakSet(), le = function(e, t) {
|
|
1502
|
+
this[__private__dont__use].ccall(
|
|
1503
|
+
"wasm_add_ENV_entry",
|
|
1504
|
+
null,
|
|
1505
|
+
[STRING, STRING],
|
|
1506
|
+
[e, t]
|
|
1507
|
+
);
|
|
1508
|
+
}, V = new WeakSet(), ce = function(e) {
|
|
1469
1509
|
this[__private__dont__use].ccall(
|
|
1470
1510
|
"wasm_set_php_code",
|
|
1471
1511
|
null,
|
|
1472
1512
|
[STRING],
|
|
1473
1513
|
[e]
|
|
1474
1514
|
);
|
|
1475
|
-
},
|
|
1515
|
+
}, Q = new WeakSet(), ue = async function() {
|
|
1476
1516
|
var n;
|
|
1477
1517
|
let e, t;
|
|
1478
1518
|
try {
|
|
1479
1519
|
e = await new Promise((i, o) => {
|
|
1480
|
-
var
|
|
1481
|
-
t = (
|
|
1520
|
+
var c;
|
|
1521
|
+
t = (d) => {
|
|
1522
|
+
console.error(d), console.error(d.error);
|
|
1482
1523
|
const p = new Error("Rethrown");
|
|
1483
|
-
p.cause =
|
|
1484
|
-
}, (
|
|
1524
|
+
p.cause = d.error, p.betterMessage = d.message, o(p);
|
|
1525
|
+
}, (c = a(this, w)) == null || c.addEventListener(
|
|
1485
1526
|
"error",
|
|
1486
1527
|
t
|
|
1487
1528
|
);
|
|
@@ -1495,24 +1536,24 @@ b = new WeakMap(), T = new WeakMap(), A = new WeakMap(), m = new WeakMap(), w =
|
|
|
1495
1536
|
return l instanceof Promise ? l.then(i, o) : i(l);
|
|
1496
1537
|
});
|
|
1497
1538
|
} catch (i) {
|
|
1498
|
-
for (const
|
|
1499
|
-
typeof this[
|
|
1539
|
+
for (const d in this)
|
|
1540
|
+
typeof this[d] == "function" && (this[d] = () => {
|
|
1500
1541
|
throw new Error(
|
|
1501
1542
|
"PHP runtime has crashed – see the earlier error for details."
|
|
1502
1543
|
);
|
|
1503
1544
|
});
|
|
1504
1545
|
this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
|
|
1505
|
-
const o = i, l = "betterMessage" in o ? o.betterMessage : o.message,
|
|
1506
|
-
throw
|
|
1546
|
+
const o = i, l = "betterMessage" in o ? o.betterMessage : o.message, c = new Error(l);
|
|
1547
|
+
throw c.cause = o, console.error(c), c;
|
|
1507
1548
|
} finally {
|
|
1508
1549
|
(n = a(this, w)) == null || n.removeEventListener("error", t), h(this, g, {});
|
|
1509
1550
|
}
|
|
1510
|
-
const { headers: r, httpStatusCode: s } = f(this,
|
|
1551
|
+
const { headers: r, httpStatusCode: s } = f(this, M, ee).call(this);
|
|
1511
1552
|
return new PHPResponse(
|
|
1512
1553
|
s,
|
|
1513
1554
|
r,
|
|
1514
|
-
this.readFileAsBuffer("/
|
|
1515
|
-
this.readFileAsText("/
|
|
1555
|
+
this.readFileAsBuffer("/internal/stdout"),
|
|
1556
|
+
this.readFileAsText("/internal/stderr"),
|
|
1516
1557
|
e
|
|
1517
1558
|
);
|
|
1518
1559
|
};
|
|
@@ -1552,28 +1593,23 @@ function normalizeHeaders(e) {
|
|
|
1552
1593
|
t[r.toLowerCase()] = e[r];
|
|
1553
1594
|
return t;
|
|
1554
1595
|
}
|
|
1555
|
-
function
|
|
1596
|
+
function copyFS(e, t, r) {
|
|
1556
1597
|
let s;
|
|
1557
1598
|
try {
|
|
1558
|
-
s =
|
|
1599
|
+
s = e.lookupPath(r);
|
|
1559
1600
|
} catch {
|
|
1560
1601
|
return;
|
|
1561
1602
|
}
|
|
1562
1603
|
if (!("contents" in s.node))
|
|
1563
1604
|
return;
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
return;
|
|
1567
|
-
} catch {
|
|
1568
|
-
}
|
|
1569
|
-
if (!t.isDir(s.node.mode)) {
|
|
1570
|
-
e.writeFile(r, t.readFile(r));
|
|
1605
|
+
if (!e.isDir(s.node.mode)) {
|
|
1606
|
+
t.writeFile(r, e.readFile(r));
|
|
1571
1607
|
return;
|
|
1572
1608
|
}
|
|
1573
|
-
|
|
1574
|
-
const n =
|
|
1609
|
+
t.mkdirTree(r);
|
|
1610
|
+
const n = e.readdir(r).filter((i) => i !== "." && i !== "..");
|
|
1575
1611
|
for (const i of n)
|
|
1576
|
-
|
|
1612
|
+
copyFS(e, t, joinPaths(r, i));
|
|
1577
1613
|
}
|
|
1578
1614
|
function isLocalPHP(e) {
|
|
1579
1615
|
return !(e instanceof BasePHP);
|
package/lib/base-php.d.ts
CHANGED
|
@@ -92,3 +92,11 @@ export declare abstract class BasePHP implements IsomorphicLocalPHP {
|
|
|
92
92
|
exit(code?: number): void;
|
|
93
93
|
}
|
|
94
94
|
export declare function normalizeHeaders(headers: PHPRequestHeaders): PHPRequestHeaders;
|
|
95
|
+
type EmscriptenFS = any;
|
|
96
|
+
export declare function syncFSTo(source: BasePHP, target: BasePHP, path?: string | null): void;
|
|
97
|
+
/**
|
|
98
|
+
* Copies the MEMFS directory structure from one FS in another FS.
|
|
99
|
+
* Non-MEMFS nodes are ignored.
|
|
100
|
+
*/
|
|
101
|
+
export declare function copyFS(source: EmscriptenFS, target: EmscriptenFS, path: string): void;
|
|
102
|
+
export {};
|
package/lib/universal-php.d.ts
CHANGED
|
@@ -462,6 +462,10 @@ export interface PHPRunOptions {
|
|
|
462
462
|
* Request body.
|
|
463
463
|
*/
|
|
464
464
|
body?: string | Uint8Array;
|
|
465
|
+
/**
|
|
466
|
+
* Environment variables to set for this run.
|
|
467
|
+
*/
|
|
468
|
+
env?: Record<string, string>;
|
|
465
469
|
/**
|
|
466
470
|
* The code snippet to eval instead of a php file.
|
|
467
471
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@php-wasm/universal",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
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": "8b74852e9701f5083b367f9a294f34200230ce79",
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=18.18.2",
|
|
42
42
|
"npm": ">=8.11.0"
|