@php-wasm/universal 0.1.42 → 0.1.45

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,12 +1,10 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});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 v=["8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0","5.6"],$=v[0],B=v;class C{#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.#n()}});if(r.headers["set-cookie"]&&this.#r(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}#r(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)}}#n(){const e=[];for(const t in this.#e)e.push(`${t}=${this.#e[t]}`);return e.join("; ")}}class M{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 U="http://example.com";function w(s){return s.toString().substring(s.origin.length)}function P(s,e){return!e||!s.startsWith(e)?s:s.substring(e.length)}function A(s,e){return!e||s.startsWith(e)?s:e+s}class O{#e;#t;#r;#n;#o;#s;#i;#a;#l;constructor(e,t={}){this.#a=new M({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.#r=i.hostname,this.#n=i.port?Number(i.port):i.protocol==="https:"?443:80,this.#t=(i.protocol||"").replace(":","");const l=this.#n!==443&&this.#n!==80;this.#o=[this.#r,l?`:${this.#n}`:""].join(""),this.#s=i.pathname.replace(/\/+$/,""),this.#i=[`${this.#t}://`,this.#o,this.#s].join("")}pathToInternalUrl(e){return`${this.absoluteUrl}${e}`}internalUrlToPath(e){const t=new URL(e);return t.pathname.startsWith(this.#s)&&(t.pathname=t.pathname.slice(this.#s.length)),w(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:U),n=P(r.pathname,this.#s);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,...I(e.headers||{})},i=[];if(e.files&&Object.keys(e.files).length){n="POST";for(const c in e.files){const p=e.files[c];i.push({key:c,name:p.name,type:p.type,data:new Uint8Array(await p.arrayBuffer())})}o["content-type"]?.startsWith("multipart/form-data")&&(e.formData=D(e.body||""),o["content-type"]="application/x-www-form-urlencoded",delete e.body)}let l;return 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,await this.php.run({relativeUri:A(w(t),this.#s),protocol:this.#t,method:e.method||n,body:l,fileInfos:i,scriptPath:this.#u(t.pathname),headers:o})}finally{r()}}#u(e){let t=P(e,this.#s);t.includes(".php")?t=t.split(".php")[0]+".php":(t.endsWith("/")||(t+="/"),t.endsWith("index.php")||(t+="index.php"));const r=`${this.#e}${t}`;return this.php.fileExists(r)?r:`${this.#e}/index.php`}}function D(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
2
- \r
3
- `),l=o.substring(0,i).trim(),c=o.substring(i+4).trim(),p=l.match(/name="([^"]+)"/);if(p){const g=p[1];e[g]=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 S={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 d(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 S){const p=S[c],g=typeof i[0]=="string"?i[0]:null,L=g!==null?s.replaceAll("{path}",g):s;throw new Error(`${L}: ${p}`,{cause:l})}throw l}}}}async function W(s,e={},t=[]){let r,n;const o=new Promise(c=>{n=c}),i=new Promise(c=>{r=c}),l=s.init(z,{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,b.push(l),b.length-1}const b=[];function j(s){return b[s]}const z=function(){return typeof process<"u"&&process.release?.name==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),E=Symbol("error"),x=Symbol("message");class R extends Event{constructor(e,t={}){super(e),this[E]=t.error===void 0?null:t.error,this[x]=t.message===void 0?"":t.message}get error(){return this[E]}get message(){return this[x]}}Object.defineProperty(R.prototype,"error",{enumerable:!0});Object.defineProperty(R.prototype,"message",{enumerable:!0});const G=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:R;class V 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 Y(s){s.asm={...s.asm};const e=new V;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=K(o,s.lastAsyncifyStackSource?.stack);if(s.lastAsyncifyStackSource&&(o.cause=s.lastAsyncifyStackSource),!e.hasListeners())throw Z(i),o;e.dispatchEvent(new G("error",{error:o,message:i}))}}}return e}let _=[];function J(){return _}function K(s,e){if(s.message==="unreachable"){let t=Q;e||(t+=`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const S=Symbol("error"),E=Symbol("message");class v extends Event{constructor(e,t={}){super(e),this[S]=t.error===void 0?null:t.error,this[E]=t.message===void 0?"":t.message}get error(){return this[S]}get message(){return this[E]}}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+=`
4
2
 
5
3
  This stack trace is lacking. For a better one initialize
6
4
  the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
7
5
 
8
- `),_=ee(e||s.stack||"");for(const r of _)t+=` * ${r}
9
- `;return t}return s.message}const Q=`
6
+ `),w=G(e||s.stack||"");for(const r of w)t+=` * ${r}
7
+ `;return t}return s.message}const W=`
10
8
  "unreachable" WASM instruction executed.
11
9
 
12
10
  The typical reason is a PHP function missing from the ASYNCIFY_ONLY
@@ -30,11 +28,13 @@ the Dockerfile, you'll need to trigger this error again with long stack
30
28
  traces enabled. In node.js, you can do it using the --stack-trace-limit=100
31
29
  CLI option:
32
30
 
33
- `,H="\x1B[41m",X="\x1B[1m",T="\x1B[0m",k="\x1B[K";let F=!1;function Z(s){if(!F){F=!0,console.log(`${H}
34
- ${k}
35
- ${X} WASM ERROR${T}${H}`);for(const e of s.split(`
36
- `))console.log(`${k} ${e} `);console.log(`${T}`)}}function ee(s){try{const e=s.split(`
37
- `).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[]}}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",m="number",a=Symbol("__private__dont__use");class u{constructor(e,t){this.#e=[],this.#t=!1,this.#r=null,e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new C(new O(this,t)))}#e;#t;#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=j(e);if(!t)throw new Error("Invalid PHP runtime id.");this[a]=t,this.#r=Y(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.#h(e.scriptPath||""),this.#s(e.relativeUri||""),this.#a(e.method||"GET");const{host:t,...r}={host:"example.com:443",...I(e.headers||{})};if(this.#i(t,e.protocol||"http"),this.#l(r),e.body&&this.#c(e.body),e.fileInfos)for(const n of e.fileInfos)this.#u(n);return e.code&&this.#d(" ?>"+e.code),await this.#p()}#n(){if(this.#e.length>0){const e=this.#e.map(([t,r])=>`${t}=${r}`).join(`
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}
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,...N(e.headers||{})},i=[];if(e.files&&Object.keys(e.files).length){n="POST";for(const c in e.files){const p=e.files[c];i.push({key:c,name:p.name,type:p.type,data:new Uint8Array(await p.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;return 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,await this.php.run({relativeUri:O(P(t),this.#n),protocol:this.#t,method:e.method||n,body:l,fileInfos:i,scriptPath:this.#u(t.pathname),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}`;return this.php.fileExists(r)?r:`${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
36
+ \r
37
+ `),l=o.substring(0,i).trim(),c=o.substring(i+4).trim(),p=l.match(/name="([^"]+)"/);if(p){const g=p[1];e[g]=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 d(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 p=F[c],g=typeof i[0]=="string"?i[0]:null,$=g!==null?s.replaceAll("{path}",g):s;throw new Error(`${$}: ${p}`,{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",m="number",a=Symbol("__private__dont__use");class u{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",...N(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(`
38
38
  `)+`
39
39
 
40
- `;this[a].ccall("wasm_set_phpini_entries",null,[h],[e])}this[a].ccall("php_wasm_init",null,[],[])}#o(){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}}#s(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])}}#i(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,[m],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")}#a(e){this[a].ccall("wasm_set_request_method",null,[h],[e])}#l(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,[m],[parseInt(e["content-length"],10)]);for(const t in e)this.addServerGlobalEntry(`HTTP_${t.toUpperCase().replace(/-/g,"_")}`,e[t])}#c(e){this[a].ccall("wasm_set_request_body",null,[h],[e]),this[a].ccall("wasm_set_content_length",null,[m],[new TextEncoder().encode(e).length])}#h(e){this[a].ccall("wasm_set_path_translated",null,[h],[e])}addServerGlobalEntry(e,t){this[a].ccall("wasm_add_SERVER_entry",null,[h,h],[e,t])}#u(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,m,m],[t,r,n,i,l,o.byteLength])}#d(e){this[a].ccall("wasm_set_php_code",null,[h],[e])}async#p(){let e,t;try{e=await new Promise(async(o,i)=>{t=l=>{const c=new Error("Rethrown");c.cause=l.error,c.betterMessage=l.message,i(c)},this.#r?.addEventListener("error",t);try{o(await await this[a].ccall("wasm_sapi_handle_request",m,[],[]))}catch(l){i(l)}})}catch(o){for(const p in this)typeof this[p]=="function"&&(this[p]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=J();const i=o,l="betterMessage"in i?i.betterMessage:i.message,c=new Error(l);throw c.cause=i,c}finally{this.#r?.removeEventListener("error",t)}const{headers:r,httpStatusCode:n}=this.#o();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.mv(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){if(!this.fileExists(e))return[];try{return this[a].FS.readdir(e).filter(t=>t!=="."&&t!=="..")}catch(t){return console.error(t,{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([d('Could not create directory "{path}"')],u.prototype,"mkdir",1);f([d('Could not create directory "{path}"')],u.prototype,"mkdirTree",1);f([d('Could not read "{path}"')],u.prototype,"readFileAsText",1);f([d('Could not read "{path}"')],u.prototype,"readFileAsBuffer",1);f([d('Could not write to "{path}"')],u.prototype,"writeFile",1);f([d('Could not unlink "{path}"')],u.prototype,"unlink",1);f([d('Could not move "{path}"')],u.prototype,"mv",1);f([d('Could not remove directory "{path}"')],u.prototype,"rmdir",1);f([d('Could not list files in "{path}"')],u.prototype,"listFiles",1);f([d('Could not stat "{path}"')],u.prototype,"isDir",1);f([d('Could not stat "{path}"')],u.prototype,"fileExists",1);function I(s){const e={};for(const t in s)e[t.toLowerCase()]=s[t];return e}function N(s){return!(s instanceof u)}function se(s){return!N(s)}exports.BasePHP=u;exports.DEFAULT_BASE_URL=U;exports.LatestSupportedPHPVersion=$;exports.PHPBrowser=C;exports.PHPRequestHandler=O;exports.PHPResponse=y;exports.SupportedPHPVersions=v;exports.SupportedPHPVersionsList=B;exports.__private__dont__use=a;exports.ensurePathPrefix=A;exports.isLocalPHP=N;exports.isRemotePHP=se;exports.loadPHPRuntime=W;exports.removePathPrefix=P;exports.rethrowFileSystemError=d;exports.toRelativeUrl=w;
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,[m],[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,[m],[parseInt(e["content-length"],10)]);for(const t in e)this.addServerGlobalEntry(`HTTP_${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,[m],[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,m,m],[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(async(o,i)=>{t=l=>{const c=new Error("Rethrown");c.cause=l.error,c.betterMessage=l.message,i(c)},this.#s?.addEventListener("error",t);try{o(await await this[a].ccall("wasm_sapi_handle_request",m,[],[]))}catch(l){i(l)}})}catch(o){for(const p in this)typeof this[p]=="function"&&(this[p]=()=>{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.mv(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){if(!this.fileExists(e))return[];try{return this[a].FS.readdir(e).filter(t=>t!=="."&&t!=="..")}catch(t){return console.error(t,{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([d('Could not create directory "{path}"')],u.prototype,"mkdir",1);f([d('Could not create directory "{path}"')],u.prototype,"mkdirTree",1);f([d('Could not read "{path}"')],u.prototype,"readFileAsText",1);f([d('Could not read "{path}"')],u.prototype,"readFileAsBuffer",1);f([d('Could not write to "{path}"')],u.prototype,"writeFile",1);f([d('Could not unlink "{path}"')],u.prototype,"unlink",1);f([d('Could not move "{path}"')],u.prototype,"mv",1);f([d('Could not remove directory "{path}"')],u.prototype,"rmdir",1);f([d('Could not list files in "{path}"')],u.prototype,"listFiles",1);f([d('Could not stat "{path}"')],u.prototype,"isDir",1);f([d('Could not stat "{path}"')],u.prototype,"fileExists",1);function N(s){const e={};for(const t in s)e[t.toLowerCase()]=s[t];return e}function L(s){return!(s instanceof u)}function se(s){return!L(s)}exports.BasePHP=u;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=L;exports.isRemotePHP=se;exports.loadPHPRuntime=X;exports.removePathPrefix=b;exports.rethrowFileSystemError=d;exports.toRelativeUrl=P;
package/index.js CHANGED
@@ -1,3 +1,148 @@
1
+ const v = Symbol("error"), _ = Symbol("message");
2
+ class b extends Event {
3
+ /**
4
+ * Create a new `ErrorEvent`.
5
+ *
6
+ * @param type The name of the event
7
+ * @param options A dictionary object that allows for setting
8
+ * attributes via object members of the same name.
9
+ */
10
+ constructor(e, t = {}) {
11
+ super(e), this[v] = t.error === void 0 ? null : t.error, this[_] = t.message === void 0 ? "" : t.message;
12
+ }
13
+ get error() {
14
+ return this[v];
15
+ }
16
+ get message() {
17
+ return this[_];
18
+ }
19
+ }
20
+ Object.defineProperty(b.prototype, "error", { enumerable: !0 });
21
+ Object.defineProperty(b.prototype, "message", { enumerable: !0 });
22
+ const A = typeof globalThis.ErrorEvent == "function" ? globalThis.ErrorEvent : b;
23
+ class O extends EventTarget {
24
+ constructor() {
25
+ super(...arguments), this.listenersCount = 0;
26
+ }
27
+ addEventListener(e, t) {
28
+ ++this.listenersCount, super.addEventListener(e, t);
29
+ }
30
+ removeEventListener(e, t) {
31
+ --this.listenersCount, super.removeEventListener(e, t);
32
+ }
33
+ hasListeners() {
34
+ return this.listenersCount > 0;
35
+ }
36
+ }
37
+ function I(s) {
38
+ s.asm = {
39
+ ...s.asm
40
+ };
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) {
46
+ try {
47
+ return r(...n);
48
+ } catch (o) {
49
+ if (!(o instanceof Error))
50
+ throw o;
51
+ if ("exitCode" in o && o?.exitCode === 0)
52
+ return;
53
+ const i = L(
54
+ o,
55
+ s.lastAsyncifyStackSource?.stack
56
+ );
57
+ if (s.lastAsyncifyStackSource && (o.cause = s.lastAsyncifyStackSource), !e.hasListeners())
58
+ throw D(i), o;
59
+ e.dispatchEvent(
60
+ new A("error", {
61
+ error: o,
62
+ message: i
63
+ })
64
+ );
65
+ }
66
+ };
67
+ }
68
+ return e;
69
+ }
70
+ let w = [];
71
+ function N() {
72
+ return w;
73
+ }
74
+ function L(s, e) {
75
+ if (s.message === "unreachable") {
76
+ let t = $;
77
+ e || (t += `
78
+
79
+ This stack trace is lacking. For a better one initialize
80
+ the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
81
+
82
+ `), w = B(
83
+ e || s.stack || ""
84
+ );
85
+ for (const r of w)
86
+ t += ` * ${r}
87
+ `;
88
+ return t;
89
+ }
90
+ return s.message;
91
+ }
92
+ const $ = `
93
+ "unreachable" WASM instruction executed.
94
+
95
+ The typical reason is a PHP function missing from the ASYNCIFY_ONLY
96
+ list when building PHP.wasm.
97
+
98
+ You will need to file a new issue in the WordPress Playground repository
99
+ and paste this error message there:
100
+
101
+ https://github.com/WordPress/wordpress-playground/issues/new
102
+
103
+ If you're a core developer, the typical fix is to:
104
+
105
+ * Isolate a minimal reproduction of the error
106
+ * Add a reproduction of the error to php-asyncify.spec.ts in the WordPress Playground repository
107
+ * Run 'npm run fix-asyncify'
108
+ * Commit the changes, push to the repo, release updated NPM packages
109
+
110
+ Below is a list of all the PHP functions found in the stack trace to
111
+ help with the minimal reproduction. If they're all already listed in
112
+ the Dockerfile, you'll need to trigger this error again with long stack
113
+ traces enabled. In node.js, you can do it using the --stack-trace-limit=100
114
+ CLI option:
115
+
116
+ `, R = "\x1B[41m", M = "\x1B[1m", E = "\x1B[0m", S = "\x1B[K";
117
+ let x = !1;
118
+ function D(s) {
119
+ if (!x) {
120
+ x = !0, console.log(`${R}
121
+ ${S}
122
+ ${M} WASM ERROR${E}${R}`);
123
+ for (const e of s.split(`
124
+ `))
125
+ console.log(`${S} ${e} `);
126
+ console.log(`${E}`);
127
+ }
128
+ }
129
+ function B(s) {
130
+ try {
131
+ const e = s.split(`
132
+ `).slice(1).map((t) => {
133
+ const r = t.trim().substring(3).split(" ");
134
+ return {
135
+ fn: r.length >= 2 ? r[0] : "<unknown>",
136
+ isWasm: t.includes("wasm://")
137
+ };
138
+ }).filter(
139
+ ({ fn: t, isWasm: r }) => r && !t.startsWith("dynCall_") && !t.startsWith("invoke_")
140
+ ).map(({ fn: t }) => t);
141
+ return Array.from(new Set(e));
142
+ } catch {
143
+ return [];
144
+ }
145
+ }
1
146
  class y {
2
147
  constructor(e, t, r, n = "", o = 0) {
3
148
  this.httpStatusCode = e, this.headers = t, this.bytes = r, this.exitCode = o, this.errors = n;
@@ -44,7 +189,7 @@ const F = [
44
189
  "7.0",
45
190
  "5.6"
46
191
  ], ee = F[0], te = F;
47
- class A {
192
+ class q {
48
193
  #e;
49
194
  #t;
50
195
  /**
@@ -77,10 +222,10 @@ class A {
77
222
  ...e,
78
223
  headers: {
79
224
  ...e.headers,
80
- cookie: this.#n()
225
+ cookie: this.#r()
81
226
  }
82
227
  });
83
- if (r.headers["set-cookie"] && this.#r(r.headers["set-cookie"]), this.#t.handleRedirects && r.headers.location && t < this.#t.maxRedirects) {
228
+ if (r.headers["set-cookie"] && this.#s(r.headers["set-cookie"]), this.#t.handleRedirects && r.headers.location && t < this.#t.maxRedirects) {
84
229
  const n = new URL(
85
230
  r.headers.location[0],
86
231
  this.requestHandler.absoluteUrl
@@ -112,7 +257,7 @@ class A {
112
257
  get documentRoot() {
113
258
  return this.requestHandler.documentRoot;
114
259
  }
115
- #r(e) {
260
+ #s(e) {
116
261
  for (const t of e)
117
262
  try {
118
263
  if (!t.includes("="))
@@ -123,14 +268,14 @@ class A {
123
268
  console.error(r);
124
269
  }
125
270
  }
126
- #n() {
271
+ #r() {
127
272
  const e = [];
128
273
  for (const t in this.#e)
129
274
  e.push(`${t}=${this.#e[t]}`);
130
275
  return e.join("; ");
131
276
  }
132
277
  }
133
- class O {
278
+ class W {
134
279
  constructor({ concurrency: e }) {
135
280
  this._running = 0, this.concurrency = e, this.queue = [];
136
281
  }
@@ -155,23 +300,23 @@ class O {
155
300
  }
156
301
  }
157
302
  }
158
- const I = "http://example.com";
159
- function v(s) {
303
+ const j = "http://example.com";
304
+ function k(s) {
160
305
  return s.toString().substring(s.origin.length);
161
306
  }
162
- function _(s, e) {
307
+ function T(s, e) {
163
308
  return !e || !s.startsWith(e) ? s : s.substring(e.length);
164
309
  }
165
- function N(s, e) {
310
+ function z(s, e) {
166
311
  return !e || s.startsWith(e) ? s : e + s;
167
312
  }
168
- class L {
313
+ class G {
169
314
  #e;
170
315
  #t;
316
+ #s;
171
317
  #r;
172
- #n;
173
318
  #o;
174
- #s;
319
+ #n;
175
320
  #i;
176
321
  #a;
177
322
  #l;
@@ -180,7 +325,7 @@ class L {
180
325
  * @param config - Request Handler configuration.
181
326
  */
182
327
  constructor(e, t = {}) {
183
- this.#a = new O({ concurrency: 1 });
328
+ this.#a = new W({ concurrency: 1 });
184
329
  const {
185
330
  documentRoot: r = "/www/",
186
331
  absoluteUrl: n = typeof location == "object" ? location?.href : "",
@@ -188,15 +333,15 @@ class L {
188
333
  } = t;
189
334
  this.php = e, this.#e = r, this.#l = o;
190
335
  const i = new URL(n);
191
- this.#r = i.hostname, this.#n = i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80, this.#t = (i.protocol || "").replace(":", "");
192
- const l = this.#n !== 443 && this.#n !== 80;
336
+ this.#s = i.hostname, this.#r = i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80, this.#t = (i.protocol || "").replace(":", "");
337
+ const l = this.#r !== 443 && this.#r !== 80;
193
338
  this.#o = [
194
- this.#r,
195
- l ? `:${this.#n}` : ""
196
- ].join(""), this.#s = i.pathname.replace(/\/+$/, ""), this.#i = [
339
+ this.#s,
340
+ l ? `:${this.#r}` : ""
341
+ ].join(""), this.#n = i.pathname.replace(/\/+$/, ""), this.#i = [
197
342
  `${this.#t}://`,
198
343
  this.#o,
199
- this.#s
344
+ this.#n
200
345
  ].join("");
201
346
  }
202
347
  /** @inheritDoc */
@@ -206,7 +351,7 @@ class L {
206
351
  /** @inheritDoc */
207
352
  internalUrlToPath(e) {
208
353
  const t = new URL(e);
209
- return t.pathname.startsWith(this.#s) && (t.pathname = t.pathname.slice(this.#s.length)), v(t);
354
+ return t.pathname.startsWith(this.#n) && (t.pathname = t.pathname.slice(this.#n.length)), k(t);
210
355
  }
211
356
  get isRequestRunning() {
212
357
  return this.#a.running > 0;
@@ -223,10 +368,10 @@ class L {
223
368
  async request(e) {
224
369
  const t = e.url.startsWith("http://") || e.url.startsWith("https://"), r = new URL(
225
370
  e.url,
226
- t ? void 0 : I
227
- ), n = _(
371
+ t ? void 0 : j
372
+ ), n = T(
228
373
  r.pathname,
229
- this.#s
374
+ this.#n
230
375
  );
231
376
  return this.#l(n) ? this.#c(n) : await this.#h(e, r);
232
377
  }
@@ -252,7 +397,7 @@ class L {
252
397
  // @TODO: Infer the content-type from the arrayBuffer instead of the file path.
253
398
  // The code below won't return the correct mime-type if the extension
254
399
  // was tampered with.
255
- "content-type": [M(t)],
400
+ "content-type": [Y(t)],
256
401
  "accept-ranges": ["bytes"],
257
402
  "cache-control": ["public, max-age=0"]
258
403
  },
@@ -289,7 +434,7 @@ class L {
289
434
  data: new Uint8Array(await d.arrayBuffer())
290
435
  });
291
436
  }
292
- o["content-type"]?.startsWith("multipart/form-data") && (e.formData = $(
437
+ o["content-type"]?.startsWith("multipart/form-data") && (e.formData = V(
293
438
  e.body || ""
294
439
  ), o["content-type"] = "application/x-www-form-urlencoded", delete e.body);
295
440
  }
@@ -297,9 +442,9 @@ class L {
297
442
  return e.formData !== void 0 ? (n = "POST", o["content-type"] = o["content-type"] || "application/x-www-form-urlencoded", l = new URLSearchParams(
298
443
  e.formData
299
444
  ).toString()) : l = e.body, await this.php.run({
300
- relativeUri: N(
301
- v(t),
302
- this.#s
445
+ relativeUri: z(
446
+ k(t),
447
+ this.#n
303
448
  ),
304
449
  protocol: this.#t,
305
450
  method: e.method || n,
@@ -321,13 +466,13 @@ class L {
321
466
  * @returns The resolved filesystem path.
322
467
  */
323
468
  #u(e) {
324
- let t = _(e, this.#s);
469
+ let t = T(e, this.#n);
325
470
  t.includes(".php") ? t = t.split(".php")[0] + ".php" : (t.endsWith("/") || (t += "/"), t.endsWith("index.php") || (t += "index.php"));
326
471
  const r = `${this.#e}${t}`;
327
472
  return this.php.fileExists(r) ? r : `${this.#e}/index.php`;
328
473
  }
329
474
  }
330
- function $(s) {
475
+ function V(s) {
331
476
  const e = {}, t = s.match(/--(.*)\r\n/);
332
477
  if (!t)
333
478
  return e;
@@ -342,7 +487,7 @@ function $(s) {
342
487
  }
343
488
  }), e;
344
489
  }
345
- function M(s) {
490
+ function Y(s) {
346
491
  switch (s.split(".").pop()) {
347
492
  case "css":
348
493
  return "text/css";
@@ -382,7 +527,7 @@ function M(s) {
382
527
  return "application-octet-stream";
383
528
  }
384
529
  }
385
- const R = {
530
+ const C = {
386
531
  0: "No error occurred. System call completed successfully.",
387
532
  1: "Argument list too long.",
388
533
  2: "Permission denied.",
@@ -469,8 +614,8 @@ function p(s = "") {
469
614
  return o.apply(this, i);
470
615
  } catch (l) {
471
616
  const c = typeof l == "object" ? l?.errno : null;
472
- if (c in R) {
473
- const d = R[c], g = typeof i[0] == "string" ? i[0] : null, U = g !== null ? s.replaceAll("{path}", g) : s;
617
+ if (c in C) {
618
+ const d = C[c], g = typeof i[0] == "string" ? i[0] : null, U = g !== null ? s.replaceAll("{path}", g) : s;
474
619
  throw new Error(`${U}: ${d}`, {
475
620
  cause: l
476
621
  });
@@ -486,7 +631,7 @@ async function re(s, e = {}, t = []) {
486
631
  n = c;
487
632
  }), i = new Promise((c) => {
488
633
  r = c;
489
- }), l = s.init(B, {
634
+ }), l = s.init(K, {
490
635
  onAbort(c) {
491
636
  console.error("WASM aborted: "), console.error(c);
492
637
  },
@@ -506,159 +651,15 @@ async function re(s, e = {}, t = []) {
506
651
  });
507
652
  for (const { default: c } of t)
508
653
  c(l);
509
- return t.length || n(), await o, await i, w.push(l), w.length - 1;
510
- }
511
- const w = [];
512
- function D(s) {
513
- return w[s];
654
+ return t.length || n(), await o, await i, P.push(l), P.length - 1;
514
655
  }
515
- const B = function() {
516
- return typeof process < "u" && process.release?.name === "node" ? "NODE" : typeof window < "u" ? "WEB" : typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope ? "WORKER" : "NODE";
517
- }(), E = Symbol("error"), S = Symbol("message");
518
- class b extends Event {
519
- /**
520
- * Create a new `ErrorEvent`.
521
- *
522
- * @param type The name of the event
523
- * @param options A dictionary object that allows for setting
524
- * attributes via object members of the same name.
525
- */
526
- constructor(e, t = {}) {
527
- super(e), this[E] = t.error === void 0 ? null : t.error, this[S] = t.message === void 0 ? "" : t.message;
528
- }
529
- get error() {
530
- return this[E];
531
- }
532
- get message() {
533
- return this[S];
534
- }
535
- }
536
- Object.defineProperty(b.prototype, "error", { enumerable: !0 });
537
- Object.defineProperty(b.prototype, "message", { enumerable: !0 });
538
- const q = typeof globalThis.ErrorEvent == "function" ? globalThis.ErrorEvent : b;
539
- class W extends EventTarget {
540
- constructor() {
541
- super(...arguments), this.listenersCount = 0;
542
- }
543
- addEventListener(e, t) {
544
- ++this.listenersCount, super.addEventListener(e, t);
545
- }
546
- removeEventListener(e, t) {
547
- --this.listenersCount, super.removeEventListener(e, t);
548
- }
549
- hasListeners() {
550
- return this.listenersCount > 0;
551
- }
552
- }
553
- function j(s) {
554
- s.asm = {
555
- ...s.asm
556
- };
557
- const e = new W();
558
- for (const t in s.asm)
559
- if (typeof s.asm[t] == "function") {
560
- const r = s.asm[t];
561
- s.asm[t] = function(...n) {
562
- try {
563
- return r(...n);
564
- } catch (o) {
565
- if (!(o instanceof Error))
566
- throw o;
567
- if ("exitCode" in o && o?.exitCode === 0)
568
- return;
569
- const i = G(
570
- o,
571
- s.lastAsyncifyStackSource?.stack
572
- );
573
- if (s.lastAsyncifyStackSource && (o.cause = s.lastAsyncifyStackSource), !e.hasListeners())
574
- throw J(i), o;
575
- e.dispatchEvent(
576
- new q("error", {
577
- error: o,
578
- message: i
579
- })
580
- );
581
- }
582
- };
583
- }
584
- return e;
585
- }
586
- let P = [];
587
- function z() {
588
- return P;
589
- }
590
- function G(s, e) {
591
- if (s.message === "unreachable") {
592
- let t = V;
593
- e || (t += `
594
-
595
- This stack trace is lacking. For a better one initialize
596
- the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
597
-
598
- `), P = K(
599
- e || s.stack || ""
600
- );
601
- for (const r of P)
602
- t += ` * ${r}
603
- `;
604
- return t;
605
- }
606
- return s.message;
607
- }
608
- const V = `
609
- "unreachable" WASM instruction executed.
610
-
611
- The typical reason is a PHP function missing from the ASYNCIFY_ONLY
612
- list when building PHP.wasm.
613
-
614
- You will need to file a new issue in the WordPress Playground repository
615
- and paste this error message there:
616
-
617
- https://github.com/WordPress/wordpress-playground/issues/new
618
-
619
- If you're a core developer, the typical fix is to:
620
-
621
- * Isolate a minimal reproduction of the error
622
- * Add a reproduction of the error to php-asyncify.spec.ts in the WordPress Playground repository
623
- * Run 'npm run fix-asyncify'
624
- * Commit the changes, push to the repo, release updated NPM packages
625
-
626
- Below is a list of all the PHP functions found in the stack trace to
627
- help with the minimal reproduction. If they're all already listed in
628
- the Dockerfile, you'll need to trigger this error again with long stack
629
- traces enabled. In node.js, you can do it using the --stack-trace-limit=100
630
- CLI option:
631
-
632
- `, x = "\x1B[41m", Y = "\x1B[1m", k = "\x1B[0m", T = "\x1B[K";
633
- let C = !1;
656
+ const P = [];
634
657
  function J(s) {
635
- if (!C) {
636
- C = !0, console.log(`${x}
637
- ${T}
638
- ${Y} WASM ERROR${k}${x}`);
639
- for (const e of s.split(`
640
- `))
641
- console.log(`${T} ${e} `);
642
- console.log(`${k}`);
643
- }
644
- }
645
- function K(s) {
646
- try {
647
- const e = s.split(`
648
- `).slice(1).map((t) => {
649
- const r = t.trim().substring(3).split(" ");
650
- return {
651
- fn: r.length >= 2 ? r[0] : "<unknown>",
652
- isWasm: t.includes("wasm://")
653
- };
654
- }).filter(
655
- ({ fn: t, isWasm: r }) => r && !t.startsWith("dynCall_") && !t.startsWith("invoke_")
656
- ).map(({ fn: t }) => t);
657
- return Array.from(new Set(e));
658
- } catch {
659
- return [];
660
- }
658
+ return P[s];
661
659
  }
660
+ const K = function() {
661
+ return typeof process < "u" && process.release?.name === "node" ? "NODE" : typeof window < "u" ? "WEB" : typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope ? "WORKER" : "NODE";
662
+ }();
662
663
  var Q = Object.defineProperty, X = Object.getOwnPropertyDescriptor, f = (s, e, t, r) => {
663
664
  for (var n = r > 1 ? void 0 : r ? X(e, t) : e, o = s.length - 1, i; o >= 0; o--)
664
665
  (i = s[o]) && (n = (r ? i(e, t, n) : i(n)) || n);
@@ -674,12 +675,13 @@ class u {
674
675
  * @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
675
676
  */
676
677
  constructor(e, t) {
677
- this.#e = [], this.#t = !1, this.#r = null, e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new A(
678
- new L(this, t)
678
+ this.#e = [], this.#t = !1, this.#s = null, this.#r = {}, e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new q(
679
+ new G(this, t)
679
680
  ));
680
681
  }
681
682
  #e;
682
683
  #t;
684
+ #s;
683
685
  #r;
684
686
  /** @inheritDoc */
685
687
  get absoluteUrl() {
@@ -702,10 +704,10 @@ class u {
702
704
  initializeRuntime(e) {
703
705
  if (this[a])
704
706
  throw new Error("PHP runtime already initialized.");
705
- const t = D(e);
707
+ const t = J(e);
706
708
  if (!t)
707
709
  throw new Error("Invalid PHP runtime id.");
708
- this[a] = t, this.#r = j(t);
710
+ this[a] = t, this.#s = I(t);
709
711
  }
710
712
  /** @inheritDoc */
711
713
  setPhpIniPath(e) {
@@ -736,17 +738,17 @@ class u {
736
738
  }
737
739
  /** @inheritDoc */
738
740
  async run(e) {
739
- this.#t || (this.#n(), this.#t = !0), this.#h(e.scriptPath || ""), this.#s(e.relativeUri || ""), this.#a(e.method || "GET");
741
+ this.#t || (this.#o(), this.#t = !0), this.#u(e.scriptPath || ""), this.#i(e.relativeUri || ""), this.#l(e.method || "GET");
740
742
  const { host: t, ...r } = {
741
743
  host: "example.com:443",
742
744
  ...H(e.headers || {})
743
745
  };
744
- if (this.#i(t, e.protocol || "http"), this.#l(r), e.body && this.#c(e.body), e.fileInfos)
746
+ if (this.#a(t, e.protocol || "http"), this.#c(r), e.body && this.#h(e.body), e.fileInfos)
745
747
  for (const n of e.fileInfos)
746
- this.#u(n);
747
- return e.code && this.#d(" ?>" + e.code), await this.#p();
748
+ this.#p(n);
749
+ return e.code && this.#f(" ?>" + e.code), this.#d(), await this.#m();
748
750
  }
749
- #n() {
751
+ #o() {
750
752
  if (this.#e.length > 0) {
751
753
  const e = this.#e.map(([t, r]) => `${t}=${r}`).join(`
752
754
  `) + `
@@ -761,7 +763,7 @@ class u {
761
763
  }
762
764
  this[a].ccall("php_wasm_init", null, [], []);
763
765
  }
764
- #o() {
766
+ #n() {
765
767
  const e = "/tmp/headers.json";
766
768
  if (!this.fileExists(e))
767
769
  throw new Error(
@@ -779,7 +781,7 @@ class u {
779
781
  httpStatusCode: t.status
780
782
  };
781
783
  }
782
- #s(e) {
784
+ #i(e) {
783
785
  if (this[a].ccall(
784
786
  "wasm_set_request_uri",
785
787
  null,
@@ -795,7 +797,7 @@ class u {
795
797
  );
796
798
  }
797
799
  }
798
- #i(e, t) {
800
+ #a(e, t) {
799
801
  this[a].ccall(
800
802
  "wasm_set_request_host",
801
803
  null,
@@ -814,7 +816,7 @@ class u {
814
816
  [r]
815
817
  ), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
816
818
  }
817
- #a(e) {
819
+ #l(e) {
818
820
  this[a].ccall(
819
821
  "wasm_set_request_method",
820
822
  null,
@@ -822,7 +824,7 @@ class u {
822
824
  [e]
823
825
  );
824
826
  }
825
- #l(e) {
827
+ #c(e) {
826
828
  e.cookie && this[a].ccall(
827
829
  "wasm_set_cookies",
828
830
  null,
@@ -845,7 +847,7 @@ class u {
845
847
  e[t]
846
848
  );
847
849
  }
848
- #c(e) {
850
+ #h(e) {
849
851
  this[a].ccall(
850
852
  "wasm_set_request_body",
851
853
  null,
@@ -858,7 +860,7 @@ class u {
858
860
  [new TextEncoder().encode(e).length]
859
861
  );
860
862
  }
861
- #h(e) {
863
+ #u(e) {
862
864
  this[a].ccall(
863
865
  "wasm_set_path_translated",
864
866
  null,
@@ -867,12 +869,16 @@ class u {
867
869
  );
868
870
  }
869
871
  addServerGlobalEntry(e, t) {
870
- this[a].ccall(
871
- "wasm_add_SERVER_entry",
872
- null,
873
- [h, h],
874
- [e, t]
875
- );
872
+ this.#r[e] = t;
873
+ }
874
+ #d() {
875
+ for (const e in this.#r)
876
+ this[a].ccall(
877
+ "wasm_add_SERVER_entry",
878
+ null,
879
+ [h, h],
880
+ [e, this.#r[e]]
881
+ );
876
882
  }
877
883
  /**
878
884
  * Adds file information to $_FILES superglobal in PHP.
@@ -883,7 +889,7 @@ class u {
883
889
  *
884
890
  * @param fileInfo - File details
885
891
  */
886
- #u(e) {
892
+ #p(e) {
887
893
  const { key: t, name: r, type: n, data: o } = e, i = `/tmp/${Math.random().toFixed(20)}`;
888
894
  this.writeFile(i, o);
889
895
  const l = 0;
@@ -894,7 +900,7 @@ class u {
894
900
  [t, r, n, i, l, o.byteLength]
895
901
  );
896
902
  }
897
- #d(e) {
903
+ #f(e) {
898
904
  this[a].ccall(
899
905
  "wasm_set_php_code",
900
906
  null,
@@ -902,14 +908,14 @@ class u {
902
908
  [e]
903
909
  );
904
910
  }
905
- async #p() {
911
+ async #m() {
906
912
  let e, t;
907
913
  try {
908
914
  e = await new Promise(async (o, i) => {
909
915
  t = (l) => {
910
916
  const c = new Error("Rethrown");
911
917
  c.cause = l.error, c.betterMessage = l.message, i(c);
912
- }, this.#r?.addEventListener(
918
+ }, this.#s?.addEventListener(
913
919
  "error",
914
920
  t
915
921
  );
@@ -939,13 +945,13 @@ class u {
939
945
  "PHP runtime has crashed – see the earlier error for details."
940
946
  );
941
947
  });
942
- this.functionsMaybeMissingFromAsyncify = z();
948
+ this.functionsMaybeMissingFromAsyncify = N();
943
949
  const i = o, l = "betterMessage" in i ? i.betterMessage : i.message, c = new Error(l);
944
950
  throw c.cause = i, c;
945
951
  } finally {
946
- this.#r?.removeEventListener("error", t);
952
+ this.#s?.removeEventListener("error", t), this.#r = {};
947
953
  }
948
- const { headers: r, httpStatusCode: n } = this.#o();
954
+ const { headers: r, httpStatusCode: n } = this.#n();
949
955
  return new y(
950
956
  n,
951
957
  r,
@@ -1052,19 +1058,20 @@ function se(s) {
1052
1058
  }
1053
1059
  export {
1054
1060
  u as BasePHP,
1055
- I as DEFAULT_BASE_URL,
1061
+ j as DEFAULT_BASE_URL,
1056
1062
  ee as LatestSupportedPHPVersion,
1057
- A as PHPBrowser,
1058
- L as PHPRequestHandler,
1063
+ q as PHPBrowser,
1064
+ G as PHPRequestHandler,
1059
1065
  y as PHPResponse,
1060
1066
  F as SupportedPHPVersions,
1061
1067
  te as SupportedPHPVersionsList,
1068
+ O as UnhandledRejectionsTarget,
1062
1069
  a as __private__dont__use,
1063
- N as ensurePathPrefix,
1070
+ z as ensurePathPrefix,
1064
1071
  Z as isLocalPHP,
1065
1072
  se as isRemotePHP,
1066
1073
  re as loadPHPRuntime,
1067
- _ as removePathPrefix,
1074
+ T as removePathPrefix,
1068
1075
  p as rethrowFileSystemError,
1069
- v as toRelativeUrl
1076
+ k as toRelativeUrl
1070
1077
  };
package/lib/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export type { FileInfo, IsomorphicLocalPHP, IsomorphicRemotePHP, PHPOutput, PHPRunOptions, UniversalPHP, RmDirOptions, HTTPMethod, PHPRequest, PHPRequestHeaders, RequestHandler, } from './universal-php';
2
+ export { UnhandledRejectionsTarget } from './wasm-error-reporting';
2
3
  export { PHPResponse } from './php-response';
3
4
  export type { PHPResponseData } from './php-response';
4
5
  export type { ErrnoError } from './rethrow-file-system-error';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/universal",
3
- "version": "0.1.42",
3
+ "version": "0.1.45",
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": "14707001dbf7738ca8f173f3040559c6c165110e"
39
+ "gitHead": "ca75514c17b912dc8b5dc529f6d123295671320a"
40
40
  }