@php-wasm/universal 0.1.59 → 0.1.61

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 CHANGED
@@ -1,10 +1,10 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=Symbol("error"),S=Symbol("message");class v extends Event{constructor(e,t={}){super(e),this[E]=t.error===void 0?null:t.error,this[S]=t.message===void 0?"":t.message}get error(){return this[E]}get message(){return this[S]}}Object.defineProperty(v.prototype,"error",{enumerable:!0});Object.defineProperty(v.prototype,"message",{enumerable:!0});const B=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:v;class C extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(e,t){++this.listenersCount,super.addEventListener(e,t)}removeEventListener(e,t){--this.listenersCount,super.removeEventListener(e,t)}hasListeners(){return this.listenersCount>0}}function M(s){s.asm={...s.asm};const e=new C;for(const t in s.asm)if(typeof s.asm[t]=="function"){const r=s.asm[t];s.asm[t]=function(...n){try{return r(...n)}catch(o){if(!(o instanceof Error))throw o;if("exitCode"in o&&o?.exitCode===0)return;const i=q(o,s.lastAsyncifyStackSource?.stack);if(s.lastAsyncifyStackSource&&(o.cause=s.lastAsyncifyStackSource),!e.hasListeners())throw z(i),o;e.dispatchEvent(new B("error",{error:o,message:i}))}}}return e}let w=[];function D(){return w}function q(s,e){if(s.message==="unreachable"){let t=W;e||(t+=`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=Symbol("error"),S=Symbol("message");class v extends Event{constructor(e,t={}){super(e),this[E]=t.error===void 0?null:t.error,this[S]=t.message===void 0?"":t.message}get error(){return this[E]}get message(){return this[S]}}Object.defineProperty(v.prototype,"error",{enumerable:!0});Object.defineProperty(v.prototype,"message",{enumerable:!0});const M=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:v;class C extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(e,t){++this.listenersCount,super.addEventListener(e,t)}removeEventListener(e,t){--this.listenersCount,super.removeEventListener(e,t)}hasListeners(){return this.listenersCount>0}}function B(n){n.asm={...n.asm};const e=new C;for(const t in n.asm)if(typeof n.asm[t]=="function"){const r=n.asm[t];n.asm[t]=function(...s){try{return r(...s)}catch(o){if(!(o instanceof Error))throw o;if("exitCode"in o&&o?.exitCode===0)return;const i=q(o,n.lastAsyncifyStackSource?.stack);if(n.lastAsyncifyStackSource&&(o.cause=n.lastAsyncifyStackSource),!e.hasListeners())throw z(i),o;e.dispatchEvent(new M("error",{error:o,message:i}))}}}return e}let w=[];function D(){return w}function q(n,e){if(n.message==="unreachable"){let t=W;e||(t+=`
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 }).
5
5
 
6
- `),w=G(e||s.stack||"");for(const r of w)t+=` * ${r}
7
- `;return t}return s.message}const W=`
6
+ `),w=G(e||n.stack||"");for(const r of w)t+=` * ${r}
7
+ `;return t}return n.message}const W=`
8
8
  "unreachable" WASM instruction executed.
9
9
 
10
10
  The typical reason is a PHP function missing from the ASYNCIFY_ONLY
@@ -28,13 +28,13 @@ the Dockerfile, you'll need to trigger this error again with long stack
28
28
  traces enabled. In node.js, you can do it using the --stack-trace-limit=100
29
29
  CLI option:
30
30
 
31
- `,x="\x1B[41m",j="\x1B[1m",H="\x1B[0m",T="\x1B[K";let k=!1;function z(s){if(!k){k=!0,console.log(`${x}
31
+ `,x="\x1B[41m",j="\x1B[1m",H="\x1B[0m",T="\x1B[K";let k=!1;function z(n){if(!k){k=!0,console.log(`${x}
32
32
  ${T}
33
- ${j} WASM ERROR${H}${x}`);for(const e of s.split(`
34
- `))console.log(`${T} ${e} `);console.log(`${H}`)}}function G(s){try{const e=s.split(`
35
- `).slice(1).map(t=>{const r=t.trim().substring(3).split(" ");return{fn:r.length>=2?r[0]:"<unknown>",isWasm:t.includes("wasm://")}}).filter(({fn:t,isWasm:r})=>r&&!t.startsWith("dynCall_")&&!t.startsWith("invoke_")).map(({fn:t})=>t);return Array.from(new Set(e))}catch{return[]}}class y{constructor(e,t,r,n="",o=0){this.httpStatusCode=e,this.headers=t,this.bytes=r,this.exitCode=o,this.errors=n}static fromRawData(e){return new y(e.httpStatusCode,e.headers,e.bytes,e.errors,e.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const R=["8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0","5.6"],V=R[0],Y=R;class U{#e;#t;constructor(e,t={}){this.requestHandler=e,this.#e={},this.#t={handleRedirects:!1,maxRedirects:4,...t}}async request(e,t=0){const r=await this.requestHandler.request({...e,headers:{...e.headers,cookie:this.#r()}});if(r.headers["set-cookie"]&&this.#s(r.headers["set-cookie"]),this.#t.handleRedirects&&r.headers.location&&t<this.#t.maxRedirects){const n=new URL(r.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:n.toString(),method:"GET",headers:{}},t+1)}return r}pathToInternalUrl(e){return this.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.internalUrlToPath(e)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}#s(e){for(const t of e)try{if(!t.includes("="))continue;const r=t.indexOf("="),n=t.substring(0,r),o=t.substring(r+1).split(";")[0];this.#e[n]=o}catch(r){console.error(r)}}#r(){const e=[];for(const t in this.#e)e.push(`${t}=${this.#e[t]}`);return e.join("; ")}}class J{constructor({concurrency:e}){this._running=0,this.concurrency=e,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(e=>this.queue.push(e));else return this._running++,()=>{this._running--,this.queue.length>0&&this.queue.shift()()}}async run(e){const t=await this.acquire();try{return await e()}finally{t()}}}const A="http://example.com";function P(s){return s.toString().substring(s.origin.length)}function b(s,e){return!e||!s.startsWith(e)?s:s.substring(e.length)}function O(s,e){return!e||s.startsWith(e)?s:e+s}class I{#e;#t;#s;#r;#o;#n;#i;#a;#l;constructor(e,t={}){this.#a=new J({concurrency:1});const{documentRoot:r="/www/",absoluteUrl:n=typeof location=="object"?location?.href:"",isStaticFilePath:o=()=>!1}=t;this.php=e,this.#e=r,this.#l=o;const i=new URL(n);this.#s=i.hostname,this.#r=i.port?Number(i.port):i.protocol==="https:"?443:80,this.#t=(i.protocol||"").replace(":","");const l=this.#r!==443&&this.#r!==80;this.#o=[this.#s,l?`:${this.#r}`:""].join(""),this.#n=i.pathname.replace(/\/+$/,""),this.#i=[`${this.#t}://`,this.#o,this.#n].join("")}pathToInternalUrl(e){return`${this.absoluteUrl}${e}`}internalUrlToPath(e){const t=new URL(e);return t.pathname.startsWith(this.#n)&&(t.pathname=t.pathname.slice(this.#n.length)),P(t)}get isRequestRunning(){return this.#a.running>0}get absoluteUrl(){return this.#i}get documentRoot(){return this.#e}async request(e){const t=e.url.startsWith("http://")||e.url.startsWith("https://"),r=new URL(e.url,t?void 0:A),n=b(r.pathname,this.#n);return this.#l(n)?this.#c(n):await this.#h(e,r)}#c(e){const t=`${this.#e}${e}`;if(!this.php.fileExists(t))return new y(404,{},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new y(200,{"content-length":[`${r.byteLength}`],"content-type":[Q(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)}async#h(e,t){const r=await this.#a.acquire();try{this.php.addServerGlobalEntry("DOCUMENT_ROOT",this.#e),this.php.addServerGlobalEntry("HTTPS",this.#i.startsWith("https://")?"on":"");let n="GET";const o={host:this.#o,...L(e.headers||{})},i=[];if(e.files&&Object.keys(e.files).length){n="POST";for(const u in e.files){const m=e.files[u];i.push({key:u,name:m.name,type:m.type,data:new Uint8Array(await m.arrayBuffer())})}o["content-type"]?.startsWith("multipart/form-data")&&(e.formData=K(e.body||""),o["content-type"]="application/x-www-form-urlencoded",delete e.body)}let l;e.formData!==void 0?(n="POST",o["content-type"]=o["content-type"]||"application/x-www-form-urlencoded",l=new URLSearchParams(e.formData).toString()):l=e.body;let c;try{c=this.#u(t.pathname)}catch{return new y(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:O(P(t),this.#n),protocol:this.#t,method:e.method||n,body:l,fileInfos:i,scriptPath:c,headers:o})}finally{r()}}#u(e){let t=b(e,this.#n);t.includes(".php")?t=t.split(".php")[0]+".php":(t.endsWith("/")||(t+="/"),t.endsWith("index.php")||(t+="index.php"));const r=`${this.#e}${t}`;if(this.php.fileExists(r))return r;if(!this.php.fileExists(`${this.#e}/index.php`))throw new Error(`File not found: ${r}`);return`${this.#e}/index.php`}}function K(s){const e={},t=s.match(/--(.*)\r\n/);if(!t)return e;const r=t[1],n=s.split(`--${r}`);return n.shift(),n.pop(),n.forEach(o=>{const i=o.indexOf(`\r
33
+ ${j} WASM ERROR${H}${x}`);for(const e of n.split(`
34
+ `))console.log(`${T} ${e} `);console.log(`${H}`)}}function G(n){try{const e=n.split(`
35
+ `).slice(1).map(t=>{const r=t.trim().substring(3).split(" ");return{fn:r.length>=2?r[0]:"<unknown>",isWasm:t.includes("wasm://")}}).filter(({fn:t,isWasm:r})=>r&&!t.startsWith("dynCall_")&&!t.startsWith("invoke_")).map(({fn:t})=>t);return Array.from(new Set(e))}catch{return[]}}class y{constructor(e,t,r,s="",o=0){this.httpStatusCode=e,this.headers=t,this.bytes=r,this.exitCode=o,this.errors=s}static fromRawData(e){return new y(e.httpStatusCode,e.headers,e.bytes,e.errors,e.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const R=["8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0","5.6"],V=R[0],Y=R;class U{#e;#t;constructor(e,t={}){this.requestHandler=e,this.#e={},this.#t={handleRedirects:!1,maxRedirects:4,...t}}async request(e,t=0){const r=await this.requestHandler.request({...e,headers:{...e.headers,cookie:this.#r()}});if(r.headers["set-cookie"]&&this.#s(r.headers["set-cookie"]),this.#t.handleRedirects&&r.headers.location&&t<this.#t.maxRedirects){const s=new URL(r.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:s.toString(),method:"GET",headers:{}},t+1)}return r}pathToInternalUrl(e){return this.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.internalUrlToPath(e)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}#s(e){for(const t of e)try{if(!t.includes("="))continue;const r=t.indexOf("="),s=t.substring(0,r),o=t.substring(r+1).split(";")[0];this.#e[s]=o}catch(r){console.error(r)}}#r(){const e=[];for(const t in this.#e)e.push(`${t}=${this.#e[t]}`);return e.join("; ")}}class J{constructor({concurrency:e}){this._running=0,this.concurrency=e,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(e=>this.queue.push(e));else{this._running++;let e=!1;return()=>{e||(e=!0,this._running--,this.queue.length>0&&this.queue.shift()())}}}async run(e){const t=await this.acquire();try{return await e()}finally{t()}}}const A="http://example.com";function P(n){return n.toString().substring(n.origin.length)}function b(n,e){return!e||!n.startsWith(e)?n:n.substring(e.length)}function O(n,e){return!e||n.startsWith(e)?n:e+n}class I{#e;#t;#s;#r;#o;#n;#i;#a;#l;constructor(e,t={}){this.#a=new J({concurrency:1});const{documentRoot:r="/www/",absoluteUrl:s=typeof location=="object"?location?.href:"",isStaticFilePath:o=()=>!1}=t;this.php=e,this.#e=r,this.#l=o;const i=new URL(s);this.#s=i.hostname,this.#r=i.port?Number(i.port):i.protocol==="https:"?443:80,this.#t=(i.protocol||"").replace(":","");const l=this.#r!==443&&this.#r!==80;this.#o=[this.#s,l?`:${this.#r}`:""].join(""),this.#n=i.pathname.replace(/\/+$/,""),this.#i=[`${this.#t}://`,this.#o,this.#n].join("")}pathToInternalUrl(e){return`${this.absoluteUrl}${e}`}internalUrlToPath(e){const t=new URL(e);return t.pathname.startsWith(this.#n)&&(t.pathname=t.pathname.slice(this.#n.length)),P(t)}get isRequestRunning(){return this.#a.running>0}get absoluteUrl(){return this.#i}get documentRoot(){return this.#e}async request(e){const t=e.url.startsWith("http://")||e.url.startsWith("https://"),r=new URL(e.url,t?void 0:A),s=b(r.pathname,this.#n);return this.#l(s)?this.#c(s):await this.#h(e,r)}#c(e){const t=`${this.#e}${e}`;if(!this.php.fileExists(t))return new y(404,{},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new y(200,{"content-length":[`${r.byteLength}`],"content-type":[Q(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)}async#h(e,t){const r=await this.#a.acquire();try{this.php.addServerGlobalEntry("DOCUMENT_ROOT",this.#e),this.php.addServerGlobalEntry("HTTPS",this.#i.startsWith("https://")?"on":"");let s="GET";const o={host:this.#o,...L(e.headers||{})},i=[];if(e.files&&Object.keys(e.files).length){s="POST";for(const u in e.files){const m=e.files[u];i.push({key:u,name:m.name,type:m.type,data:new Uint8Array(await m.arrayBuffer())})}o["content-type"]?.startsWith("multipart/form-data")&&(e.formData=K(e.body||""),o["content-type"]="application/x-www-form-urlencoded",delete e.body)}let l;e.formData!==void 0?(s="POST",o["content-type"]=o["content-type"]||"application/x-www-form-urlencoded",l=new URLSearchParams(e.formData).toString()):l=e.body;let c;try{c=this.#u(t.pathname)}catch{return new y(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:O(P(t),this.#n),protocol:this.#t,method:e.method||s,body:l,fileInfos:i,scriptPath:c,headers:o})}finally{r()}}#u(e){let t=b(e,this.#n);t.includes(".php")?t=t.split(".php")[0]+".php":(t.endsWith("/")||(t+="/"),t.endsWith("index.php")||(t+="index.php"));const r=`${this.#e}${t}`;if(this.php.fileExists(r))return r;if(!this.php.fileExists(`${this.#e}/index.php`))throw new Error(`File not found: ${r}`);return`${this.#e}/index.php`}}function K(n){const e={},t=n.match(/--(.*)\r\n/);if(!t)return e;const r=t[1],s=n.split(`--${r}`);return s.shift(),s.pop(),s.forEach(o=>{const i=o.indexOf(`\r
36
36
  \r
37
- `),l=o.substring(0,i).trim(),c=o.substring(i+4).trim(),u=l.match(/name="([^"]+)"/);if(u){const m=u[1];e[m]=c}}),e}function Q(s){switch(s.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"}}const F={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 p(s=""){return function(t,r,n){const o=n.value;n.value=function(...i){try{return o.apply(this,i)}catch(l){const c=typeof l=="object"?l?.errno:null;if(c in F){const u=F[c],m=typeof i[0]=="string"?i[0]:null,$=m!==null?s.replaceAll("{path}",m):s;throw new Error(`${$}: ${u}`,{cause:l})}throw l}}}}async function X(s,e={},t=[]){let r,n;const o=new Promise(c=>{n=c}),i=new Promise(c=>{r=c}),l=s.init(ee,{onAbort(c){console.error("WASM aborted: "),console.error(c)},ENV:{},locateFile:c=>c,...e,noInitialRun:!0,onRuntimeInitialized(){e.onRuntimeInitialized&&e.onRuntimeInitialized(),r()},monitorRunDependencies(c){c===0&&(delete l.monitorRunDependencies,n())}});for(const{default:c}of t)c(l);return t.length||n(),await o,await i,_.push(l),_.length-1}const _=[];function Z(s){return _[s]}const ee=function(){return typeof process<"u"&&process.release?.name==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}();var te=Object.defineProperty,re=Object.getOwnPropertyDescriptor,f=(s,e,t,r)=>{for(var n=r>1?void 0:r?re(e,t):e,o=s.length-1,i;o>=0;o--)(i=s[o])&&(n=(r?i(e,t,n):i(n))||n);return r&&n&&te(e,t,n),n};const h="string",g="number",a=Symbol("__private__dont__use");class d{constructor(e,t){this.#e=[],this.#t=!1,this.#s=null,this.#r={},e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new U(new I(this,t)))}#e;#t;#s;#r;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[a])throw new Error("PHP runtime already initialized.");const t=Z(e);if(!t)throw new Error("Invalid PHP runtime id.");this[a]=t,this.#s=M(t)}setPhpIniPath(e){if(this.#t)throw new Error("Cannot set PHP ini path after calling run().");this[a].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(this.#t)throw new Error("Cannot set PHP ini entries after calling run().");this.#e.push([e,t])}chdir(e){this[a].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){this.#t||(this.#o(),this.#t=!0),this.#u(e.scriptPath||""),this.#i(e.relativeUri||""),this.#l(e.method||"GET");const{host:t,...r}={host:"example.com:443",...L(e.headers||{})};if(this.#a(t,e.protocol||"http"),this.#c(r),e.body&&this.#h(e.body),e.fileInfos)for(const n of e.fileInfos)this.#p(n);return e.code&&this.#f(" ?>"+e.code),this.#d(),await this.#m()}#o(){if(this.#e.length>0){const e=this.#e.map(([t,r])=>`${t}=${r}`).join(`
37
+ `),l=o.substring(0,i).trim(),c=o.substring(i+4).trim(),u=l.match(/name="([^"]+)"/);if(u){const m=u[1];e[m]=c}}),e}function Q(n){switch(n.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"}}const F={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 p(n=""){return function(t,r,s){const o=s.value;s.value=function(...i){try{return o.apply(this,i)}catch(l){const c=typeof l=="object"?l?.errno:null;if(c in F){const u=F[c],m=typeof i[0]=="string"?i[0]:null,$=m!==null?n.replaceAll("{path}",m):n;throw new Error(`${$}: ${u}`,{cause:l})}throw l}}}}async function X(n,e={},t=[]){let r,s;const o=new Promise(c=>{s=c}),i=new Promise(c=>{r=c}),l=n.init(ee,{onAbort(c){console.error("WASM aborted: "),console.error(c)},ENV:{},locateFile:c=>c,...e,noInitialRun:!0,onRuntimeInitialized(){e.onRuntimeInitialized&&e.onRuntimeInitialized(),r()},monitorRunDependencies(c){c===0&&(delete l.monitorRunDependencies,s())}});for(const{default:c}of t)c(l);return t.length||s(),await o,await i,_.push(l),_.length-1}const _=[];function Z(n){return _[n]}const ee=function(){return typeof process<"u"&&process.release?.name==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}();var te=Object.defineProperty,re=Object.getOwnPropertyDescriptor,f=(n,e,t,r)=>{for(var s=r>1?void 0:r?re(e,t):e,o=n.length-1,i;o>=0;o--)(i=n[o])&&(s=(r?i(e,t,s):i(s))||s);return r&&s&&te(e,t,s),s};const h="string",g="number",a=Symbol("__private__dont__use");class d{constructor(e,t){this.#e=[],this.#t=!1,this.#s=null,this.#r={},this.#o=[],e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new U(new I(this,t)))}#e;#t;#s;#r;#o;async onMessage(e){this.#o.push(e)}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[a])throw new Error("PHP runtime already initialized.");const t=Z(e);if(!t)throw new Error("Invalid PHP runtime id.");this[a]=t,t.onMessage=r=>{for(const s of this.#o)s(r)},this.#s=B(t)}setPhpIniPath(e){if(this.#t)throw new Error("Cannot set PHP ini path after calling run().");this[a].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(this.#t)throw new Error("Cannot set PHP ini entries after calling run().");this.#e.push([e,t])}chdir(e){this[a].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){this.#t||(this.#n(),this.#t=!0),this.#d(e.scriptPath||""),this.#a(e.relativeUri||""),this.#c(e.method||"GET");const{host:t,...r}={host:"example.com:443",...L(e.headers||{})};if(this.#l(t,e.protocol||"http"),this.#h(r),e.body&&this.#u(e.body),e.fileInfos)for(const s of e.fileInfos)this.#f(s);return e.code&&this.#m(" ?>"+e.code),this.#p(),await this.#y()}#n(){if(this.#e.length>0){const e=this.#e.map(([t,r])=>`${t}=${r}`).join(`
38
38
  `)+`
39
39
 
40
- `;this[a].ccall("wasm_set_phpini_entries",null,[h],[e])}this[a].ccall("php_wasm_init",null,[],[])}#n(){const e="/tmp/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 n of t.headers){if(!n.includes(": "))continue;const o=n.indexOf(": "),i=n.substring(0,o).toLowerCase(),l=n.substring(o+2);i in r||(r[i]=[]),r[i].push(l)}return{headers:r,httpStatusCode:t.status}}#i(e){if(this[a].ccall("wasm_set_request_uri",null,[h],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[a].ccall("wasm_set_query_string",null,[h],[t])}}#a(e,t){this[a].ccall("wasm_set_request_host",null,[h],[e]);let r;try{r=parseInt(new URL(e).port,10)}catch{}(!r||isNaN(r)||r===80)&&(r=t==="https"?443:80),this[a].ccall("wasm_set_request_port",null,[g],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")}#l(e){this[a].ccall("wasm_set_request_method",null,[h],[e])}#c(e){e.cookie&&this[a].ccall("wasm_set_cookies",null,[h],[e.cookie]),e["content-type"]&&this[a].ccall("wasm_set_content_type",null,[h],[e["content-type"]]),e["content-length"]&&this[a].ccall("wasm_set_content_length",null,[g],[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])}}#h(e){this[a].ccall("wasm_set_request_body",null,[h],[e]),this[a].ccall("wasm_set_content_length",null,[g],[new TextEncoder().encode(e).length])}#u(e){this[a].ccall("wasm_set_path_translated",null,[h],[e])}addServerGlobalEntry(e,t){this.#r[e]=t}#d(){for(const e in this.#r)this[a].ccall("wasm_add_SERVER_entry",null,[h,h],[e,this.#r[e]])}#p(e){const{key:t,name:r,type:n,data:o}=e,i=`/tmp/${Math.random().toFixed(20)}`;this.writeFile(i,o);const l=0;this[a].ccall("wasm_add_uploaded_file",null,[h,h,h,h,g,g],[t,r,n,i,l,o.byteLength])}#f(e){this[a].ccall("wasm_set_php_code",null,[h],[e])}async#m(){let e,t;try{e=await new Promise((o,i)=>{t=c=>{const u=new Error("Rethrown");u.cause=c.error,u.betterMessage=c.message,i(u)},this.#s?.addEventListener("error",t);const l=this[a].ccall("wasm_sapi_handle_request",g,[],[]);return l instanceof Promise?l.then(o,i):o(l)})}catch(o){for(const u in this)typeof this[u]=="function"&&(this[u]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=D();const i=o,l="betterMessage"in i?i.betterMessage:i.message,c=new Error(l);throw c.cause=i,c}finally{this.#s?.removeEventListener("error",t),this.#r={}}const{headers:r,httpStatusCode:n}=this.#n();return new y(n,r,this.readFileAsBuffer("/tmp/stdout"),this.readFileAsText("/tmp/stderr"),e)}mkdir(e){this[a].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[a].FS.readFile(e)}writeFile(e,t){this[a].FS.writeFile(e,t)}unlink(e){this[a].FS.unlink(e)}mv(e,t){this[a].FS.rename(e,t)}rmdir(e,t={recursive:!0}){t?.recursive&&this.listFiles(e).forEach(r=>{const n=`${e}/${r}`;this.isDir(n)?this.rmdir(n,t):this.unlink(n)}),this[a].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[a].FS.readdir(e).filter(n=>n!=="."&&n!=="..");if(t.prependPath){const n=e.replace(/\/$/,"");return r.map(o=>`${n}/${o}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[a].FS.isDir(this[a].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[a].FS.lookupPath(e),!0}catch{return!1}}}f([p('Could not create directory "{path}"')],d.prototype,"mkdir",1);f([p('Could not create directory "{path}"')],d.prototype,"mkdirTree",1);f([p('Could not read "{path}"')],d.prototype,"readFileAsText",1);f([p('Could not read "{path}"')],d.prototype,"readFileAsBuffer",1);f([p('Could not write to "{path}"')],d.prototype,"writeFile",1);f([p('Could not unlink "{path}"')],d.prototype,"unlink",1);f([p('Could not move "{path}"')],d.prototype,"mv",1);f([p('Could not remove directory "{path}"')],d.prototype,"rmdir",1);f([p('Could not list files in "{path}"')],d.prototype,"listFiles",1);f([p('Could not stat "{path}"')],d.prototype,"isDir",1);f([p('Could not stat "{path}"')],d.prototype,"fileExists",1);function L(s){const e={};for(const t in s)e[t.toLowerCase()]=s[t];return e}function N(s){return!(s instanceof d)}function se(s){return!N(s)}exports.BasePHP=d;exports.DEFAULT_BASE_URL=A;exports.LatestSupportedPHPVersion=V;exports.PHPBrowser=U;exports.PHPRequestHandler=I;exports.PHPResponse=y;exports.SupportedPHPVersions=R;exports.SupportedPHPVersionsList=Y;exports.UnhandledRejectionsTarget=C;exports.__private__dont__use=a;exports.ensurePathPrefix=O;exports.isLocalPHP=N;exports.isRemotePHP=se;exports.loadPHPRuntime=X;exports.removePathPrefix=b;exports.rethrowFileSystemError=p;exports.toRelativeUrl=P;
40
+ `;this[a].ccall("wasm_set_phpini_entries",null,[h],[e])}this[a].ccall("php_wasm_init",null,[],[])}#i(){const e="/tmp/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 o=s.indexOf(": "),i=s.substring(0,o).toLowerCase(),l=s.substring(o+2);i in r||(r[i]=[]),r[i].push(l)}return{headers:r,httpStatusCode:t.status}}#a(e){if(this[a].ccall("wasm_set_request_uri",null,[h],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[a].ccall("wasm_set_query_string",null,[h],[t])}}#l(e,t){this[a].ccall("wasm_set_request_host",null,[h],[e]);let r;try{r=parseInt(new URL(e).port,10)}catch{}(!r||isNaN(r)||r===80)&&(r=t==="https"?443:80),this[a].ccall("wasm_set_request_port",null,[g],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")}#c(e){this[a].ccall("wasm_set_request_method",null,[h],[e])}#h(e){e.cookie&&this[a].ccall("wasm_set_cookies",null,[h],[e.cookie]),e["content-type"]&&this[a].ccall("wasm_set_content_type",null,[h],[e["content-type"]]),e["content-length"]&&this[a].ccall("wasm_set_content_length",null,[g],[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])}}#u(e){this[a].ccall("wasm_set_request_body",null,[h],[e]),this[a].ccall("wasm_set_content_length",null,[g],[new TextEncoder().encode(e).length])}#d(e){this[a].ccall("wasm_set_path_translated",null,[h],[e])}addServerGlobalEntry(e,t){this.#r[e]=t}#p(){for(const e in this.#r)this[a].ccall("wasm_add_SERVER_entry",null,[h,h],[e,this.#r[e]])}#f(e){const{key:t,name:r,type:s,data:o}=e,i=`/tmp/${Math.random().toFixed(20)}`;this.writeFile(i,o);const l=0;this[a].ccall("wasm_add_uploaded_file",null,[h,h,h,h,g,g],[t,r,s,i,l,o.byteLength])}#m(e){this[a].ccall("wasm_set_php_code",null,[h],[e])}async#y(){let e,t;try{e=await new Promise((o,i)=>{t=c=>{const u=new Error("Rethrown");u.cause=c.error,u.betterMessage=c.message,i(u)},this.#s?.addEventListener("error",t);const l=this[a].ccall("wasm_sapi_handle_request",g,[],[]);return l instanceof Promise?l.then(o,i):o(l)})}catch(o){for(const u in this)typeof this[u]=="function"&&(this[u]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=D();const i=o,l="betterMessage"in i?i.betterMessage:i.message,c=new Error(l);throw c.cause=i,c}finally{this.#s?.removeEventListener("error",t),this.#r={}}const{headers:r,httpStatusCode:s}=this.#i();return new y(s,r,this.readFileAsBuffer("/tmp/stdout"),this.readFileAsText("/tmp/stderr"),e)}mkdir(e){this[a].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[a].FS.readFile(e)}writeFile(e,t){this[a].FS.writeFile(e,t)}unlink(e){this[a].FS.unlink(e)}mv(e,t){this[a].FS.rename(e,t)}rmdir(e,t={recursive:!0}){t?.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[a].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[a].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(o=>`${s}/${o}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[a].FS.isDir(this[a].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[a].FS.lookupPath(e),!0}catch{return!1}}}f([p('Could not create directory "{path}"')],d.prototype,"mkdir",1);f([p('Could not create directory "{path}"')],d.prototype,"mkdirTree",1);f([p('Could not read "{path}"')],d.prototype,"readFileAsText",1);f([p('Could not read "{path}"')],d.prototype,"readFileAsBuffer",1);f([p('Could not write to "{path}"')],d.prototype,"writeFile",1);f([p('Could not unlink "{path}"')],d.prototype,"unlink",1);f([p('Could not move "{path}"')],d.prototype,"mv",1);f([p('Could not remove directory "{path}"')],d.prototype,"rmdir",1);f([p('Could not list files in "{path}"')],d.prototype,"listFiles",1);f([p('Could not stat "{path}"')],d.prototype,"isDir",1);f([p('Could not stat "{path}"')],d.prototype,"fileExists",1);function L(n){const e={};for(const t in n)e[t.toLowerCase()]=n[t];return e}function N(n){return!(n instanceof d)}function se(n){return!N(n)}exports.BasePHP=d;exports.DEFAULT_BASE_URL=A;exports.LatestSupportedPHPVersion=V;exports.PHPBrowser=U;exports.PHPRequestHandler=I;exports.PHPResponse=y;exports.SupportedPHPVersions=R;exports.SupportedPHPVersionsList=Y;exports.UnhandledRejectionsTarget=C;exports.__private__dont__use=a;exports.ensurePathPrefix=O;exports.isLocalPHP=N;exports.isRemotePHP=se;exports.loadPHPRuntime=X;exports.removePathPrefix=b;exports.rethrowFileSystemError=p;exports.toRelativeUrl=P;
package/index.js CHANGED
@@ -34,17 +34,17 @@ class O extends EventTarget {
34
34
  return this.listenersCount > 0;
35
35
  }
36
36
  }
37
- function I(s) {
38
- s.asm = {
39
- ...s.asm
37
+ function I(n) {
38
+ n.asm = {
39
+ ...n.asm
40
40
  };
41
41
  const e = new O();
42
- for (const t in s.asm)
43
- if (typeof s.asm[t] == "function") {
44
- const r = s.asm[t];
45
- s.asm[t] = function(...n) {
42
+ for (const t in n.asm)
43
+ if (typeof n.asm[t] == "function") {
44
+ const r = n.asm[t];
45
+ n.asm[t] = function(...s) {
46
46
  try {
47
- return r(...n);
47
+ return r(...s);
48
48
  } catch (o) {
49
49
  if (!(o instanceof Error))
50
50
  throw o;
@@ -52,9 +52,9 @@ function I(s) {
52
52
  return;
53
53
  const i = $(
54
54
  o,
55
- s.lastAsyncifyStackSource?.stack
55
+ n.lastAsyncifyStackSource?.stack
56
56
  );
57
- if (s.lastAsyncifyStackSource && (o.cause = s.lastAsyncifyStackSource), !e.hasListeners())
57
+ if (n.lastAsyncifyStackSource && (o.cause = n.lastAsyncifyStackSource), !e.hasListeners())
58
58
  throw D(i), o;
59
59
  e.dispatchEvent(
60
60
  new A("error", {
@@ -71,8 +71,8 @@ let w = [];
71
71
  function N() {
72
72
  return w;
73
73
  }
74
- function $(s, e) {
75
- if (s.message === "unreachable") {
74
+ function $(n, e) {
75
+ if (n.message === "unreachable") {
76
76
  let t = L;
77
77
  e || (t += `
78
78
 
@@ -80,14 +80,14 @@ This stack trace is lacking. For a better one initialize
80
80
  the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
81
81
 
82
82
  `), w = B(
83
- e || s.stack || ""
83
+ e || n.stack || ""
84
84
  );
85
85
  for (const r of w)
86
86
  t += ` * ${r}
87
87
  `;
88
88
  return t;
89
89
  }
90
- return s.message;
90
+ return n.message;
91
91
  }
92
92
  const L = `
93
93
  "unreachable" WASM instruction executed.
@@ -115,20 +115,20 @@ CLI option:
115
115
 
116
116
  `, R = "\x1B[41m", M = "\x1B[1m", E = "\x1B[0m", S = "\x1B[K";
117
117
  let x = !1;
118
- function D(s) {
118
+ function D(n) {
119
119
  if (!x) {
120
120
  x = !0, console.log(`${R}
121
121
  ${S}
122
122
  ${M} WASM ERROR${E}${R}`);
123
- for (const e of s.split(`
123
+ for (const e of n.split(`
124
124
  `))
125
125
  console.log(`${S} ${e} `);
126
126
  console.log(`${E}`);
127
127
  }
128
128
  }
129
- function B(s) {
129
+ function B(n) {
130
130
  try {
131
- const e = s.split(`
131
+ const e = n.split(`
132
132
  `).slice(1).map((t) => {
133
133
  const r = t.trim().substring(3).split(" ");
134
134
  return {
@@ -144,8 +144,8 @@ function B(s) {
144
144
  }
145
145
  }
146
146
  class g {
147
- constructor(e, t, r, n = "", o = 0) {
148
- this.httpStatusCode = e, this.headers = t, this.bytes = r, this.exitCode = o, this.errors = n;
147
+ constructor(e, t, r, s = "", o = 0) {
148
+ this.httpStatusCode = e, this.headers = t, this.bytes = r, this.exitCode = o, this.errors = s;
149
149
  }
150
150
  static fromRawData(e) {
151
151
  return new g(
@@ -226,13 +226,13 @@ class q {
226
226
  }
227
227
  });
228
228
  if (r.headers["set-cookie"] && this.#s(r.headers["set-cookie"]), this.#t.handleRedirects && r.headers.location && t < this.#t.maxRedirects) {
229
- const n = new URL(
229
+ const s = new URL(
230
230
  r.headers.location[0],
231
231
  this.requestHandler.absoluteUrl
232
232
  );
233
233
  return this.request(
234
234
  {
235
- url: n.toString(),
235
+ url: s.toString(),
236
236
  method: "GET",
237
237
  headers: {}
238
238
  },
@@ -262,8 +262,8 @@ class q {
262
262
  try {
263
263
  if (!t.includes("="))
264
264
  continue;
265
- const r = t.indexOf("="), n = t.substring(0, r), o = t.substring(r + 1).split(";")[0];
266
- this.#e[n] = o;
265
+ const r = t.indexOf("="), s = t.substring(0, r), o = t.substring(r + 1).split(";")[0];
266
+ this.#e[s] = o;
267
267
  } catch (r) {
268
268
  console.error(r);
269
269
  }
@@ -286,10 +286,13 @@ class W {
286
286
  for (; ; )
287
287
  if (this._running >= this.concurrency)
288
288
  await new Promise((e) => this.queue.push(e));
289
- else
290
- return this._running++, () => {
291
- this._running--, this.queue.length > 0 && this.queue.shift()();
289
+ else {
290
+ this._running++;
291
+ let e = !1;
292
+ return () => {
293
+ e || (e = !0, this._running--, this.queue.length > 0 && this.queue.shift()());
292
294
  };
295
+ }
293
296
  }
294
297
  async run(e) {
295
298
  const t = await this.acquire();
@@ -301,14 +304,14 @@ class W {
301
304
  }
302
305
  }
303
306
  const j = "http://example.com";
304
- function T(s) {
305
- return s.toString().substring(s.origin.length);
307
+ function T(n) {
308
+ return n.toString().substring(n.origin.length);
306
309
  }
307
- function k(s, e) {
308
- return !e || !s.startsWith(e) ? s : s.substring(e.length);
310
+ function k(n, e) {
311
+ return !e || !n.startsWith(e) ? n : n.substring(e.length);
309
312
  }
310
- function z(s, e) {
311
- return !e || s.startsWith(e) ? s : e + s;
313
+ function z(n, e) {
314
+ return !e || n.startsWith(e) ? n : e + n;
312
315
  }
313
316
  class G {
314
317
  #e;
@@ -328,11 +331,11 @@ class G {
328
331
  this.#a = new W({ concurrency: 1 });
329
332
  const {
330
333
  documentRoot: r = "/www/",
331
- absoluteUrl: n = typeof location == "object" ? location?.href : "",
334
+ absoluteUrl: s = typeof location == "object" ? location?.href : "",
332
335
  isStaticFilePath: o = () => !1
333
336
  } = t;
334
337
  this.php = e, this.#e = r, this.#l = o;
335
- const i = new URL(n);
338
+ const i = new URL(s);
336
339
  this.#s = i.hostname, this.#r = i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80, this.#t = (i.protocol || "").replace(":", "");
337
340
  const l = this.#r !== 443 && this.#r !== 80;
338
341
  this.#o = [
@@ -369,11 +372,11 @@ class G {
369
372
  const t = e.url.startsWith("http://") || e.url.startsWith("https://"), r = new URL(
370
373
  e.url,
371
374
  t ? void 0 : j
372
- ), n = k(
375
+ ), s = k(
373
376
  r.pathname,
374
377
  this.#n
375
378
  );
376
- return this.#l(n) ? this.#c(n) : await this.#h(e, r);
379
+ return this.#l(s) ? this.#c(s) : await this.#h(e, r);
377
380
  }
378
381
  /**
379
382
  * Serves a static file from the PHP filesystem.
@@ -418,13 +421,13 @@ class G {
418
421
  "HTTPS",
419
422
  this.#i.startsWith("https://") ? "on" : ""
420
423
  );
421
- let n = "GET";
424
+ let s = "GET";
422
425
  const o = {
423
426
  host: this.#o,
424
427
  ...H(e.headers || {})
425
428
  }, i = [];
426
429
  if (e.files && Object.keys(e.files).length) {
427
- n = "POST";
430
+ s = "POST";
428
431
  for (const u in e.files) {
429
432
  const m = e.files[u];
430
433
  i.push({
@@ -439,7 +442,7 @@ class G {
439
442
  ), o["content-type"] = "application/x-www-form-urlencoded", delete e.body);
440
443
  }
441
444
  let l;
442
- e.formData !== void 0 ? (n = "POST", o["content-type"] = o["content-type"] || "application/x-www-form-urlencoded", l = new URLSearchParams(
445
+ e.formData !== void 0 ? (s = "POST", o["content-type"] = o["content-type"] || "application/x-www-form-urlencoded", l = new URLSearchParams(
443
446
  e.formData
444
447
  ).toString()) : l = e.body;
445
448
  let c;
@@ -458,7 +461,7 @@ class G {
458
461
  this.#n
459
462
  ),
460
463
  protocol: this.#t,
461
- method: e.method || n,
464
+ method: e.method || s,
462
465
  body: l,
463
466
  fileInfos: i,
464
467
  scriptPath: c,
@@ -488,12 +491,12 @@ class G {
488
491
  return `${this.#e}/index.php`;
489
492
  }
490
493
  }
491
- function V(s) {
492
- const e = {}, t = s.match(/--(.*)\r\n/);
494
+ function V(n) {
495
+ const e = {}, t = n.match(/--(.*)\r\n/);
493
496
  if (!t)
494
497
  return e;
495
- const r = t[1], n = s.split(`--${r}`);
496
- return n.shift(), n.pop(), n.forEach((o) => {
498
+ const r = t[1], s = n.split(`--${r}`);
499
+ return s.shift(), s.pop(), s.forEach((o) => {
497
500
  const i = o.indexOf(`\r
498
501
  \r
499
502
  `), l = o.substring(0, i).trim(), c = o.substring(i + 4).trim(), u = l.match(/name="([^"]+)"/);
@@ -503,8 +506,8 @@ function V(s) {
503
506
  }
504
507
  }), e;
505
508
  }
506
- function Y(s) {
507
- switch (s.split(".").pop()) {
509
+ function Y(n) {
510
+ switch (n.split(".").pop()) {
508
511
  case "css":
509
512
  return "text/css";
510
513
  case "js":
@@ -622,16 +625,16 @@ const F = {
622
625
  75: "Cross-device link.",
623
626
  76: "Extension: Capabilities insufficient."
624
627
  };
625
- function p(s = "") {
626
- return function(t, r, n) {
627
- const o = n.value;
628
- n.value = function(...i) {
628
+ function p(n = "") {
629
+ return function(t, r, s) {
630
+ const o = s.value;
631
+ s.value = function(...i) {
629
632
  try {
630
633
  return o.apply(this, i);
631
634
  } catch (l) {
632
635
  const c = typeof l == "object" ? l?.errno : null;
633
636
  if (c in F) {
634
- const u = F[c], m = typeof i[0] == "string" ? i[0] : null, U = m !== null ? s.replaceAll("{path}", m) : s;
637
+ const u = F[c], m = typeof i[0] == "string" ? i[0] : null, U = m !== null ? n.replaceAll("{path}", m) : n;
635
638
  throw new Error(`${U}: ${u}`, {
636
639
  cause: l
637
640
  });
@@ -641,13 +644,13 @@ function p(s = "") {
641
644
  };
642
645
  };
643
646
  }
644
- async function re(s, e = {}, t = []) {
645
- let r, n;
647
+ async function re(n, e = {}, t = []) {
648
+ let r, s;
646
649
  const o = new Promise((c) => {
647
- n = c;
650
+ s = c;
648
651
  }), i = new Promise((c) => {
649
652
  r = c;
650
- }), l = s.init(K, {
653
+ }), l = n.init(K, {
651
654
  onAbort(c) {
652
655
  console.error("WASM aborted: "), console.error(c);
653
656
  },
@@ -662,24 +665,24 @@ async function re(s, e = {}, t = []) {
662
665
  e.onRuntimeInitialized && e.onRuntimeInitialized(), r();
663
666
  },
664
667
  monitorRunDependencies(c) {
665
- c === 0 && (delete l.monitorRunDependencies, n());
668
+ c === 0 && (delete l.monitorRunDependencies, s());
666
669
  }
667
670
  });
668
671
  for (const { default: c } of t)
669
672
  c(l);
670
- return t.length || n(), await o, await i, P.push(l), P.length - 1;
673
+ return t.length || s(), await o, await i, P.push(l), P.length - 1;
671
674
  }
672
675
  const P = [];
673
- function J(s) {
674
- return P[s];
676
+ function J(n) {
677
+ return P[n];
675
678
  }
676
679
  const K = function() {
677
680
  return typeof process < "u" && process.release?.name === "node" ? "NODE" : typeof window < "u" ? "WEB" : typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope ? "WORKER" : "NODE";
678
681
  }();
679
- var Q = Object.defineProperty, X = Object.getOwnPropertyDescriptor, f = (s, e, t, r) => {
680
- for (var n = r > 1 ? void 0 : r ? X(e, t) : e, o = s.length - 1, i; o >= 0; o--)
681
- (i = s[o]) && (n = (r ? i(e, t, n) : i(n)) || n);
682
- return r && n && Q(e, t, n), n;
682
+ var Q = Object.defineProperty, X = Object.getOwnPropertyDescriptor, f = (n, e, t, r) => {
683
+ for (var s = r > 1 ? void 0 : r ? X(e, t) : e, o = n.length - 1, i; o >= 0; o--)
684
+ (i = n[o]) && (s = (r ? i(e, t, s) : i(s)) || s);
685
+ return r && s && Q(e, t, s), s;
683
686
  };
684
687
  const h = "string", y = "number", a = Symbol("__private__dont__use");
685
688
  class d {
@@ -691,7 +694,7 @@ class d {
691
694
  * @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
692
695
  */
693
696
  constructor(e, t) {
694
- this.#e = [], this.#t = !1, this.#s = null, this.#r = {}, e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new q(
697
+ this.#e = [], this.#t = !1, this.#s = null, this.#r = {}, this.#o = [], e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new q(
695
698
  new G(this, t)
696
699
  ));
697
700
  }
@@ -699,6 +702,11 @@ class d {
699
702
  #t;
700
703
  #s;
701
704
  #r;
705
+ #o;
706
+ /** @inheritDoc */
707
+ async onMessage(e) {
708
+ this.#o.push(e);
709
+ }
702
710
  /** @inheritDoc */
703
711
  get absoluteUrl() {
704
712
  return this.requestHandler.requestHandler.absoluteUrl;
@@ -723,7 +731,10 @@ class d {
723
731
  const t = J(e);
724
732
  if (!t)
725
733
  throw new Error("Invalid PHP runtime id.");
726
- this[a] = t, this.#s = I(t);
734
+ this[a] = t, t.onMessage = (r) => {
735
+ for (const s of this.#o)
736
+ s(r);
737
+ }, this.#s = I(t);
727
738
  }
728
739
  /** @inheritDoc */
729
740
  setPhpIniPath(e) {
@@ -754,17 +765,17 @@ class d {
754
765
  }
755
766
  /** @inheritDoc */
756
767
  async run(e) {
757
- this.#t || (this.#o(), this.#t = !0), this.#u(e.scriptPath || ""), this.#i(e.relativeUri || ""), this.#l(e.method || "GET");
768
+ this.#t || (this.#n(), this.#t = !0), this.#d(e.scriptPath || ""), this.#a(e.relativeUri || ""), this.#c(e.method || "GET");
758
769
  const { host: t, ...r } = {
759
770
  host: "example.com:443",
760
771
  ...H(e.headers || {})
761
772
  };
762
- if (this.#a(t, e.protocol || "http"), this.#c(r), e.body && this.#h(e.body), e.fileInfos)
763
- for (const n of e.fileInfos)
764
- this.#p(n);
765
- return e.code && this.#f(" ?>" + e.code), this.#d(), await this.#m();
773
+ if (this.#l(t, e.protocol || "http"), this.#h(r), e.body && this.#u(e.body), e.fileInfos)
774
+ for (const s of e.fileInfos)
775
+ this.#f(s);
776
+ return e.code && this.#m(" ?>" + e.code), this.#p(), await this.#y();
766
777
  }
767
- #o() {
778
+ #n() {
768
779
  if (this.#e.length > 0) {
769
780
  const e = this.#e.map(([t, r]) => `${t}=${r}`).join(`
770
781
  `) + `
@@ -779,17 +790,17 @@ class d {
779
790
  }
780
791
  this[a].ccall("php_wasm_init", null, [], []);
781
792
  }
782
- #n() {
793
+ #i() {
783
794
  const e = "/tmp/headers.json";
784
795
  if (!this.fileExists(e))
785
796
  throw new Error(
786
797
  "SAPI Error: Could not find response headers file."
787
798
  );
788
799
  const t = JSON.parse(this.readFileAsText(e)), r = {};
789
- for (const n of t.headers) {
790
- if (!n.includes(": "))
800
+ for (const s of t.headers) {
801
+ if (!s.includes(": "))
791
802
  continue;
792
- const o = n.indexOf(": "), i = n.substring(0, o).toLowerCase(), l = n.substring(o + 2);
803
+ const o = s.indexOf(": "), i = s.substring(0, o).toLowerCase(), l = s.substring(o + 2);
793
804
  i in r || (r[i] = []), r[i].push(l);
794
805
  }
795
806
  return {
@@ -797,7 +808,7 @@ class d {
797
808
  httpStatusCode: t.status
798
809
  };
799
810
  }
800
- #i(e) {
811
+ #a(e) {
801
812
  if (this[a].ccall(
802
813
  "wasm_set_request_uri",
803
814
  null,
@@ -813,7 +824,7 @@ class d {
813
824
  );
814
825
  }
815
826
  }
816
- #a(e, t) {
827
+ #l(e, t) {
817
828
  this[a].ccall(
818
829
  "wasm_set_request_host",
819
830
  null,
@@ -832,7 +843,7 @@ class d {
832
843
  [r]
833
844
  ), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
834
845
  }
835
- #l(e) {
846
+ #c(e) {
836
847
  this[a].ccall(
837
848
  "wasm_set_request_method",
838
849
  null,
@@ -840,7 +851,7 @@ class d {
840
851
  [e]
841
852
  );
842
853
  }
843
- #c(e) {
854
+ #h(e) {
844
855
  e.cookie && this[a].ccall(
845
856
  "wasm_set_cookies",
846
857
  null,
@@ -865,7 +876,7 @@ class d {
865
876
  );
866
877
  }
867
878
  }
868
- #h(e) {
879
+ #u(e) {
869
880
  this[a].ccall(
870
881
  "wasm_set_request_body",
871
882
  null,
@@ -878,7 +889,7 @@ class d {
878
889
  [new TextEncoder().encode(e).length]
879
890
  );
880
891
  }
881
- #u(e) {
892
+ #d(e) {
882
893
  this[a].ccall(
883
894
  "wasm_set_path_translated",
884
895
  null,
@@ -889,7 +900,7 @@ class d {
889
900
  addServerGlobalEntry(e, t) {
890
901
  this.#r[e] = t;
891
902
  }
892
- #d() {
903
+ #p() {
893
904
  for (const e in this.#r)
894
905
  this[a].ccall(
895
906
  "wasm_add_SERVER_entry",
@@ -907,18 +918,18 @@ class d {
907
918
  *
908
919
  * @param fileInfo - File details
909
920
  */
910
- #p(e) {
911
- const { key: t, name: r, type: n, data: o } = e, i = `/tmp/${Math.random().toFixed(20)}`;
921
+ #f(e) {
922
+ const { key: t, name: r, type: s, data: o } = e, i = `/tmp/${Math.random().toFixed(20)}`;
912
923
  this.writeFile(i, o);
913
924
  const l = 0;
914
925
  this[a].ccall(
915
926
  "wasm_add_uploaded_file",
916
927
  null,
917
928
  [h, h, h, h, y, y],
918
- [t, r, n, i, l, o.byteLength]
929
+ [t, r, s, i, l, o.byteLength]
919
930
  );
920
931
  }
921
- #f(e) {
932
+ #m(e) {
922
933
  this[a].ccall(
923
934
  "wasm_set_php_code",
924
935
  null,
@@ -926,7 +937,7 @@ class d {
926
937
  [e]
927
938
  );
928
939
  }
929
- async #m() {
940
+ async #y() {
930
941
  let e, t;
931
942
  try {
932
943
  e = await new Promise((o, i) => {
@@ -958,9 +969,9 @@ class d {
958
969
  } finally {
959
970
  this.#s?.removeEventListener("error", t), this.#r = {};
960
971
  }
961
- const { headers: r, httpStatusCode: n } = this.#n();
972
+ const { headers: r, httpStatusCode: s } = this.#i();
962
973
  return new g(
963
- n,
974
+ s,
964
975
  r,
965
976
  this.readFileAsBuffer("/tmp/stdout"),
966
977
  this.readFileAsText("/tmp/stderr"),
@@ -990,8 +1001,8 @@ class d {
990
1001
  }
991
1002
  rmdir(e, t = { recursive: !0 }) {
992
1003
  t?.recursive && this.listFiles(e).forEach((r) => {
993
- const n = `${e}/${r}`;
994
- this.isDir(n) ? this.rmdir(n, t) : this.unlink(n);
1004
+ const s = `${e}/${r}`;
1005
+ this.isDir(s) ? this.rmdir(s, t) : this.unlink(s);
995
1006
  }), this[a].FS.rmdir(e);
996
1007
  }
997
1008
  listFiles(e, t = { prependPath: !1 }) {
@@ -999,11 +1010,11 @@ class d {
999
1010
  return [];
1000
1011
  try {
1001
1012
  const r = this[a].FS.readdir(e).filter(
1002
- (n) => n !== "." && n !== ".."
1013
+ (s) => s !== "." && s !== ".."
1003
1014
  );
1004
1015
  if (t.prependPath) {
1005
- const n = e.replace(/\/$/, "");
1006
- return r.map((o) => `${n}/${o}`);
1016
+ const s = e.replace(/\/$/, "");
1017
+ return r.map((o) => `${s}/${o}`);
1007
1018
  }
1008
1019
  return r;
1009
1020
  } catch (r) {
@@ -1056,17 +1067,17 @@ f([
1056
1067
  f([
1057
1068
  p('Could not stat "{path}"')
1058
1069
  ], d.prototype, "fileExists", 1);
1059
- function H(s) {
1070
+ function H(n) {
1060
1071
  const e = {};
1061
- for (const t in s)
1062
- e[t.toLowerCase()] = s[t];
1072
+ for (const t in n)
1073
+ e[t.toLowerCase()] = n[t];
1063
1074
  return e;
1064
1075
  }
1065
- function Z(s) {
1066
- return !(s instanceof d);
1076
+ function Z(n) {
1077
+ return !(n instanceof d);
1067
1078
  }
1068
- function se(s) {
1069
- return !Z(s);
1079
+ function se(n) {
1080
+ return !Z(n);
1070
1081
  }
1071
1082
  export {
1072
1083
  d as BasePHP,
package/lib/base-php.d.ts CHANGED
@@ -2,7 +2,7 @@ import { PHPBrowser } from './php-browser';
2
2
  import { PHPRequestHandlerConfiguration } from './php-request-handler';
3
3
  import { PHPResponse } from './php-response';
4
4
  import type { PHPRuntimeId } from './load-php-runtime';
5
- import { IsomorphicLocalPHP, PHPRequest, PHPRunOptions, RmDirOptions, ListFilesOptions } from './universal-php';
5
+ import { IsomorphicLocalPHP, MessageListener, PHPRequest, PHPRunOptions, RmDirOptions, ListFilesOptions } from './universal-php';
6
6
  export declare const __private__dont__use: unique symbol;
7
7
  /**
8
8
  * An environment-agnostic wrapper around the Emscripten PHP runtime
@@ -25,6 +25,8 @@ export declare abstract class BasePHP implements IsomorphicLocalPHP {
25
25
  */
26
26
  constructor(PHPRuntimeId?: PHPRuntimeId, serverOptions?: PHPRequestHandlerConfiguration);
27
27
  /** @inheritDoc */
28
+ onMessage(listener: MessageListener): Promise<void>;
29
+ /** @inheritDoc */
28
30
  get absoluteUrl(): string;
29
31
  /** @inheritDoc */
30
32
  get documentRoot(): string;
package/lib/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type { FileInfo, IsomorphicLocalPHP, IsomorphicRemotePHP, PHPOutput, PHPRunOptions, UniversalPHP, ListFilesOptions, RmDirOptions, HTTPMethod, PHPRequest, PHPRequestHeaders, RequestHandler, } from './universal-php';
1
+ export type { FileInfo, IsomorphicLocalPHP, IsomorphicRemotePHP, MessageListener, PHPOutput, PHPRunOptions, UniversalPHP, ListFilesOptions, RmDirOptions, HTTPMethod, PHPRequest, PHPRequestHeaders, RequestHandler, } from './universal-php';
2
2
  export { UnhandledRejectionsTarget } from './wasm-error-reporting';
3
3
  export { PHPResponse } from './php-response';
4
4
  export type { PHPResponseData } from './php-response';
@@ -146,4 +146,6 @@ export type EmscriptenOptions = {
146
146
  quit?: (status: number, toThrow: any) => void;
147
147
  onRuntimeInitialized?: () => void;
148
148
  monitorRunDependencies?: (left: number) => void;
149
+ onMessage?: (listener: EmscriptenMessageListener) => void;
149
150
  } & Record<string, any>;
151
+ export type EmscriptenMessageListener = (type: string, data: string) => void;
@@ -303,7 +303,48 @@ export interface IsomorphicLocalPHP extends RequestHandler {
303
303
  * @param options - PHP runtime options.
304
304
  */
305
305
  run(options: PHPRunOptions): Promise<PHPResponse>;
306
+ /**
307
+ * Listens to message sent by the PHP code.
308
+ *
309
+ * To dispatch messages, call:
310
+ *
311
+ * post_message_to_js(string $data)
312
+ *
313
+ * Arguments:
314
+ * $data – any extra information as a string
315
+ *
316
+ * @example
317
+ *
318
+ * ```ts
319
+ * const php = await PHP.load('8.0');
320
+ *
321
+ * php.onMessage(
322
+ * // The data is always passed as a string
323
+ * function (data: string) {
324
+ * // Let's decode and log the data:
325
+ * console.log(JSON.parse(data));
326
+ * }
327
+ * );
328
+ *
329
+ * // Now that we have a listener in place, let's
330
+ * // dispatch a message:
331
+ * await php.run({
332
+ * code: `<?php
333
+ * post_message_to_js(
334
+ * json_encode([
335
+ * 'post_id' => '15',
336
+ * 'post_title' => 'This is a blog post!'
337
+ * ])
338
+ * ));
339
+ * `,
340
+ * });
341
+ * ```
342
+ *
343
+ * @param listener Callback function to handle the message.
344
+ */
345
+ onMessage(listener: MessageListener): void;
306
346
  }
347
+ export type MessageListener = (data: string) => void;
307
348
  export type IsomorphicRemotePHP = Remote<IsomorphicLocalPHP>;
308
349
  export type UniversalPHP = IsomorphicLocalPHP | IsomorphicRemotePHP;
309
350
  export type HTTPMethod = 'GET' | 'POST' | 'HEAD' | 'OPTIONS' | 'PATCH' | 'PUT' | 'DELETE';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/universal",
3
- "version": "0.1.59",
3
+ "version": "0.1.61",
4
4
  "description": "PHP.wasm – emscripten bindings for PHP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -36,5 +36,5 @@
36
36
  "main": "./index.cjs",
37
37
  "module": "./index.js",
38
38
  "license": "GPL-2.0-or-later",
39
- "gitHead": "2bc229b001da476da85d98d1b130ef86ea8e685b"
39
+ "gitHead": "f2cd7382004f7b003904b5db1d33d37fd2b1bfab"
40
40
  }