@php-wasm/universal 0.6.15 → 0.6.16
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 +7 -7
- package/index.js +93 -79
- package/lib/base-php.d.ts +5 -0
- package/package.json +2 -2
package/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var J=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var l=(e,t,r)=>(J(e,t,"read from private field"),r?r.call(e):t.get(e)),
|
|
1
|
+
"use strict";var J=(e,t,r)=>{if(!t.has(e))throw TypeError("Cannot "+r)};var l=(e,t,r)=>(J(e,t,"read from private field"),r?r.call(e):t.get(e)),d=(e,t,r)=>{if(t.has(e))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(e):t.set(e,r)},h=(e,t,r,s)=>(J(e,t,"write to private field"),s?s.call(e,r):t.set(e,r),r);var p=(e,t,r)=>(J(e,t,"access private method"),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const currentJsRuntime$1=function(){var e;return typeof process<"u"&&((e=process.release)==null?void 0:e.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}();if(currentJsRuntime$1==="NODE"){let e=function(r){return new Promise(function(s,n){r.onload=r.onerror=function(o){r.onload=r.onerror=null,o.type==="load"?s(r.result):n(new Error("Failed to read the blob/file"))}})},t=function(){const r=new Uint8Array([1,2,3,4]),n=new File([r],"test").stream();try{return n.getReader({mode:"byob"}),!0}catch{return!1}};if(typeof File>"u"){class r extends Blob{constructor(n,o,i){super(n);let a;i!=null&&i.lastModified&&(a=new Date),(!a||isNaN(a.getFullYear()))&&(a=new Date),this.lastModifiedDate=a,this.lastModified=a.getMilliseconds(),this.name=o||""}}global.File=r}typeof Blob.prototype.arrayBuffer>"u"&&(Blob.prototype.arrayBuffer=function(){const s=new FileReader;return s.readAsArrayBuffer(this),e(s)}),typeof Blob.prototype.text>"u"&&(Blob.prototype.text=function(){const s=new FileReader;return s.readAsText(this),e(s)}),(typeof Blob.prototype.stream>"u"||!t())&&(Blob.prototype.stream=function(){let r=0;const s=this;return new ReadableStream({type:"bytes",autoAllocateChunkSize:512*1024,async pull(n){const o=n.byobRequest.view,a=await s.slice(r,r+o.byteLength).arrayBuffer(),c=new Uint8Array(a);new Uint8Array(o.buffer).set(c);const u=c.byteLength;n.byobRequest.respond(u),r+=u,r>=s.size&&n.close()}})})}if(currentJsRuntime$1==="NODE"&&typeof CustomEvent>"u"){class e extends Event{constructor(r,s={}){super(r,s),this.detail=s.detail}initCustomEvent(){}}globalThis.CustomEvent=e}const kError=Symbol("error"),kMessage=Symbol("message");class ErrorEvent2 extends Event{constructor(t,r={}){super(t),this[kError]=r.error===void 0?null:r.error,this[kMessage]=r.message===void 0?"":r.message}get error(){return this[kError]}get message(){return this[kMessage]}}Object.defineProperty(ErrorEvent2.prototype,"error",{enumerable:!0});Object.defineProperty(ErrorEvent2.prototype,"message",{enumerable:!0});const ErrorEvent=typeof globalThis.ErrorEvent=="function"?globalThis.ErrorEvent:ErrorEvent2;function isExitCodeZero(e){return e instanceof Error?"exitCode"in e&&(e==null?void 0:e.exitCode)===0||(e==null?void 0:e.name)==="ExitStatus"&&"status"in e&&e.status===0:!1}class UnhandledRejectionsTarget extends EventTarget{constructor(){super(...arguments),this.listenersCount=0}addEventListener(t,r){++this.listenersCount,super.addEventListener(t,r)}removeEventListener(t,r){--this.listenersCount,super.removeEventListener(t,r)}hasListeners(){return this.listenersCount>0}}function improveWASMErrorReporting(e){e.asm={...e.asm};const t=new UnhandledRejectionsTarget;for(const r in e.asm)if(typeof e.asm[r]=="function"){const s=e.asm[r];e.asm[r]=function(...n){var o;try{return s(...n)}catch(i){if(!(i instanceof Error))throw i;const a=clarifyErrorMessage(i,(o=e.lastAsyncifyStackSource)==null?void 0:o.stack);if(e.lastAsyncifyStackSource&&(i.cause=e.lastAsyncifyStackSource),t.hasListeners()){t.dispatchEvent(new ErrorEvent("error",{error:i,message:a}));return}throw isExitCodeZero(i)||showCriticalErrorBox(a),i}}}return t}let functionsMaybeMissingFromAsyncify=[];function getFunctionsMaybeMissingFromAsyncify(){return functionsMaybeMissingFromAsyncify}function clarifyErrorMessage(e,t){if(e.message==="unreachable"){let r=UNREACHABLE_ERROR;t||(r+=`
|
|
2
2
|
|
|
3
3
|
This stack trace is lacking. For a better one initialize
|
|
4
4
|
the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
|
|
@@ -32,13 +32,13 @@ CLI option:
|
|
|
32
32
|
${eol}
|
|
33
33
|
${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
|
|
34
34
|
`))console.log(`${eol} ${t} `);console.log(`${reset}`)}}function extractPHPFunctionsFromStack(e){try{const t=e.split(`
|
|
35
|
-
`).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(t))}catch{return[]}}class Semaphore{constructor({concurrency:t}){this._running=0,this.concurrency=t,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(t=>this.queue.push(t));else{this._running++;let t=!1;return()=>{t||(t=!0,this._running--,this.queue.length>0&&this.queue.shift()())}}}async run(t){const r=await this.acquire();try{return await t()}finally{r()}}}function joinPaths(...e){let t=e.join("/");const r=t[0]==="/",s=t.substring(t.length-1)==="/";return t=normalizePath(t),!t&&!r&&(t="."),t&&s&&(t+="/"),t}function dirname(e){if(e==="/")return"/";e=normalizePath(e);const t=e.lastIndexOf("/");return t===-1?"":t===0?"/":e.substr(0,t)}function normalizePath(e){const t=e[0]==="/";return e=normalizePathsArray(e.split("/").filter(r=>!!r),!t).join("/"),(t?"/":"")+e.replace(/\/$/,"")}function normalizePathsArray(e,t){let r=0;for(let s=e.length-1;s>=0;s--){const n=e[s];n==="."?e.splice(s,1):n===".."?(e.splice(s,1),r++):r&&(e.splice(s,1),r--)}if(t)for(;r;r--)e.unshift("..");return e}function splitShellCommand(e){let s=0,n="";const o=[];let i="";for(let a=0;a<e.length;a++){const c=e[a];c==="\\"?((e[a+1]==='"'||e[a+1]==="'")&&a++,i+=e[a]):s===0?c==='"'||c==="'"?(s=1,n=c):c.match(/\s/)?(i.trim().length&&o.push(i.trim()),i=c):o.length&&!i?i=o.pop()+c:i+=c:s===1&&(c===n?(s=0,n=""):i+=c)}return i&&o.push(i.trim()),o}function createSpawnHandler(e){return function(t,r=[],s={}){const n=new ChildProcess,o=new ProcessApi(n);return setTimeout(async()=>{let i=[];if(r.length)i=[t,...r];else if(typeof t=="string")i=splitShellCommand(t);else if(Array.isArray(t))i=t;else throw new Error("Invalid command ",t);await e(i,o,s),n.emit("spawn",!0)}),n}}class EventEmitter{constructor(){this.listeners={}}emit(t,r){this.listeners[t]&&this.listeners[t].forEach(function(s){s(r)})}on(t,r){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(r)}}class ProcessApi extends EventEmitter{constructor(t){super(),this.childProcess=t,this.exited=!1,this.stdinData=[],t.on("stdin",r=>{this.stdinData?this.stdinData.push(r.slice()):this.emit("stdin",r)})}stdout(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stdout.emit("data",t)}stdoutEnd(){this.childProcess.stdout.emit("end",{})}stderr(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stderr.emit("data",t)}stderrEnd(){this.childProcess.stderr.emit("end",{})}exit(t){this.exited||(this.exited=!0,this.childProcess.emit("exit",t))}flushStdin(){if(this.stdinData)for(let t=0;t<this.stdinData.length;t++)this.emit("stdin",this.stdinData[t]);this.stdinData=null}}let lastPid=9743;class ChildProcess extends EventEmitter{constructor(t=lastPid++){super(),this.pid=t,this.stdout=new EventEmitter,this.stderr=new EventEmitter;const r=this;this.stdin={write:s=>{r.emit("stdin",s)}}}}function concatUint8Array(...e){const t=new Uint8Array(e.reduce((s,n)=>s+n.length,0));let r=0;for(const s of e)t.set(s,r),r+=s.length;return t}function concatBytes(e){if(e===void 0){let t=new Uint8Array;return new TransformStream({transform(r){t=concatUint8Array(t,r)},flush(r){r.enqueue(t)}})}else{const t=new ArrayBuffer(e||0);let r=0;return new TransformStream({transform(s){new Uint8Array(t).set(s,r),r+=s.byteLength},flush(s){s.enqueue(new Uint8Array(t))}})}}function limitBytes(e,t){if(t===0)return new ReadableStream({start(n){n.close()}});const r=e.getReader({mode:"byob"});let s=0;return new ReadableStream({async pull(n){const{value:o,done:i}=await r.read(new Uint8Array(t-s));if(i){r.releaseLock(),n.close();return}s+=o.length,n.enqueue(o),s>=t&&(r.releaseLock(),n.close())},cancel(){r.cancel()}})}async function collectBytes(e,t){return t!==void 0&&(e=limitBytes(e,t)),await e.pipeThrough(concatBytes(t)).getReader().read().then(({value:r})=>r)}class StreamedFile extends File{constructor(t,r,s){super([],r,{type:s}),this.readableStream=t}slice(){throw new Error("slice() is not possible on a StreamedFile")}stream(){return this.readableStream}async text(){return new TextDecoder().decode(await this.arrayBuffer())}async arrayBuffer(){return await collectBytes(this.stream())}}ReadableStream.prototype[Symbol.asyncIterator]||(ReadableStream.prototype[Symbol.asyncIterator]=async function*(){const e=this.getReader();try{for(;;){const{done:t,value:r}=await e.read();if(t)return;yield r}}finally{e.releaseLock()}},ReadableStream.prototype.iterate=ReadableStream.prototype[Symbol.asyncIterator]);function streamReadFileFromPHP(e,t){return new ReadableStream({async pull(r){const s=await e.readFileAsBuffer(t);r.enqueue(s),r.close()}})}async function*iteratePhpFiles(e,t,{relativePaths:r=!0,pathPrefix:s,exceptPaths:n=[]}={}){t=normalizePath(t);const o=[t];for(;o.length;){const i=o.pop();if(!i)return;const a=await e.listFiles(i);for(const c of a){const
|
|
36
|
-
`),n.push(`Content-Disposition: form-data; name="${c}"`),
|
|
37
|
-
`),
|
|
35
|
+
`).slice(1).map(r=>{const s=r.trim().substring(3).split(" ");return{fn:s.length>=2?s[0]:"<unknown>",isWasm:r.includes("wasm://")}}).filter(({fn:r,isWasm:s})=>s&&!r.startsWith("dynCall_")&&!r.startsWith("invoke_")).map(({fn:r})=>r);return Array.from(new Set(t))}catch{return[]}}class Semaphore{constructor({concurrency:t}){this._running=0,this.concurrency=t,this.queue=[]}get running(){return this._running}async acquire(){for(;;)if(this._running>=this.concurrency)await new Promise(t=>this.queue.push(t));else{this._running++;let t=!1;return()=>{t||(t=!0,this._running--,this.queue.length>0&&this.queue.shift()())}}}async run(t){const r=await this.acquire();try{return await t()}finally{r()}}}function joinPaths(...e){let t=e.join("/");const r=t[0]==="/",s=t.substring(t.length-1)==="/";return t=normalizePath(t),!t&&!r&&(t="."),t&&s&&(t+="/"),t}function dirname(e){if(e==="/")return"/";e=normalizePath(e);const t=e.lastIndexOf("/");return t===-1?"":t===0?"/":e.substr(0,t)}function normalizePath(e){const t=e[0]==="/";return e=normalizePathsArray(e.split("/").filter(r=>!!r),!t).join("/"),(t?"/":"")+e.replace(/\/$/,"")}function normalizePathsArray(e,t){let r=0;for(let s=e.length-1;s>=0;s--){const n=e[s];n==="."?e.splice(s,1):n===".."?(e.splice(s,1),r++):r&&(e.splice(s,1),r--)}if(t)for(;r;r--)e.unshift("..");return e}function splitShellCommand(e){let s=0,n="";const o=[];let i="";for(let a=0;a<e.length;a++){const c=e[a];c==="\\"?((e[a+1]==='"'||e[a+1]==="'")&&a++,i+=e[a]):s===0?c==='"'||c==="'"?(s=1,n=c):c.match(/\s/)?(i.trim().length&&o.push(i.trim()),i=c):o.length&&!i?i=o.pop()+c:i+=c:s===1&&(c===n?(s=0,n=""):i+=c)}return i&&o.push(i.trim()),o}function createSpawnHandler(e){return function(t,r=[],s={}){const n=new ChildProcess,o=new ProcessApi(n);return setTimeout(async()=>{let i=[];if(r.length)i=[t,...r];else if(typeof t=="string")i=splitShellCommand(t);else if(Array.isArray(t))i=t;else throw new Error("Invalid command ",t);await e(i,o,s),n.emit("spawn",!0)}),n}}class EventEmitter{constructor(){this.listeners={}}emit(t,r){this.listeners[t]&&this.listeners[t].forEach(function(s){s(r)})}on(t,r){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(r)}}class ProcessApi extends EventEmitter{constructor(t){super(),this.childProcess=t,this.exited=!1,this.stdinData=[],t.on("stdin",r=>{this.stdinData?this.stdinData.push(r.slice()):this.emit("stdin",r)})}stdout(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stdout.emit("data",t)}stdoutEnd(){this.childProcess.stdout.emit("end",{})}stderr(t){typeof t=="string"&&(t=new TextEncoder().encode(t)),this.childProcess.stderr.emit("data",t)}stderrEnd(){this.childProcess.stderr.emit("end",{})}exit(t){this.exited||(this.exited=!0,this.childProcess.emit("exit",t))}flushStdin(){if(this.stdinData)for(let t=0;t<this.stdinData.length;t++)this.emit("stdin",this.stdinData[t]);this.stdinData=null}}let lastPid=9743;class ChildProcess extends EventEmitter{constructor(t=lastPid++){super(),this.pid=t,this.stdout=new EventEmitter,this.stderr=new EventEmitter;const r=this;this.stdin={write:s=>{r.emit("stdin",s)}}}}function concatUint8Array(...e){const t=new Uint8Array(e.reduce((s,n)=>s+n.length,0));let r=0;for(const s of e)t.set(s,r),r+=s.length;return t}function concatBytes(e){if(e===void 0){let t=new Uint8Array;return new TransformStream({transform(r){t=concatUint8Array(t,r)},flush(r){r.enqueue(t)}})}else{const t=new ArrayBuffer(e||0);let r=0;return new TransformStream({transform(s){new Uint8Array(t).set(s,r),r+=s.byteLength},flush(s){s.enqueue(new Uint8Array(t))}})}}function limitBytes(e,t){if(t===0)return new ReadableStream({start(n){n.close()}});const r=e.getReader({mode:"byob"});let s=0;return new ReadableStream({async pull(n){const{value:o,done:i}=await r.read(new Uint8Array(t-s));if(i){r.releaseLock(),n.close();return}s+=o.length,n.enqueue(o),s>=t&&(r.releaseLock(),n.close())},cancel(){r.cancel()}})}async function collectBytes(e,t){return t!==void 0&&(e=limitBytes(e,t)),await e.pipeThrough(concatBytes(t)).getReader().read().then(({value:r})=>r)}class StreamedFile extends File{constructor(t,r,s){super([],r,{type:s}),this.readableStream=t}slice(){throw new Error("slice() is not possible on a StreamedFile")}stream(){return this.readableStream}async text(){return new TextDecoder().decode(await this.arrayBuffer())}async arrayBuffer(){return await collectBytes(this.stream())}}ReadableStream.prototype[Symbol.asyncIterator]||(ReadableStream.prototype[Symbol.asyncIterator]=async function*(){const e=this.getReader();try{for(;;){const{done:t,value:r}=await e.read();if(t)return;yield r}}finally{e.releaseLock()}},ReadableStream.prototype.iterate=ReadableStream.prototype[Symbol.asyncIterator]);function streamReadFileFromPHP(e,t){return new ReadableStream({async pull(r){const s=await e.readFileAsBuffer(t);r.enqueue(s),r.close()}})}async function*iteratePhpFiles(e,t,{relativePaths:r=!0,pathPrefix:s,exceptPaths:n=[]}={}){t=normalizePath(t);const o=[t];for(;o.length;){const i=o.pop();if(!i)return;const a=await e.listFiles(i);for(const c of a){const u=`${i}/${c}`;if(n.includes(u.substring(t.length+1)))continue;await e.isDir(u)?o.push(u):yield new StreamedFile(streamReadFileFromPHP(e,u),r?joinPaths(s||"",u.substring(t.length+1)):u)}}}function writeFilesStreamToPhp(e,t){return new WritableStream({async write(r){const s=joinPaths(t,r.name);r.type==="directory"?await e.mkdir(s):(await e.mkdir(dirname(s)),await e.writeFile(s,new Uint8Array(await r.arrayBuffer())))}})}class PHPResponse{constructor(t,r,s,n="",o=0){this.httpStatusCode=t,this.headers=r,this.bytes=s,this.exitCode=o,this.errors=n}static fromRawData(t){return new PHPResponse(t.httpStatusCode,t.headers,t.bytes,t.errors,t.exitCode)}toRawData(){return{headers:this.headers,bytes:this.bytes,errors:this.errors,exitCode:this.exitCode,httpStatusCode:this.httpStatusCode}}get json(){return JSON.parse(this.text)}get text(){return new TextDecoder().decode(this.bytes)}}const SupportedPHPVersions=["8.3","8.2","8.1","8.0","7.4","7.3","7.2","7.1","7.0"],LatestSupportedPHPVersion=SupportedPHPVersions[0],SupportedPHPVersionsList=SupportedPHPVersions,SupportedPHPExtensionsList=["iconv","mbstring","xml-bundle","gd"],SupportedPHPExtensionBundles={"kitchen-sink":SupportedPHPExtensionsList,light:[]};var E,b;class PHPBrowser{constructor(t,r={}){d(this,E,void 0);d(this,b,void 0);this.requestHandler=t,h(this,E,{}),h(this,b,{handleRedirects:!1,maxRedirects:4,...r})}async request(t,r=0){const s=await this.requestHandler.request({...t,headers:{...t.headers,cookie:this.serializeCookies()}});if(s.headers["set-cookie"]&&this.setCookies(s.headers["set-cookie"]),l(this,b).handleRedirects&&s.headers.location&&r<l(this,b).maxRedirects){const n=new URL(s.headers.location[0],this.requestHandler.absoluteUrl);return this.request({url:n.toString(),method:"GET",headers:{}},r+1)}return s}pathToInternalUrl(t){return this.requestHandler.pathToInternalUrl(t)}internalUrlToPath(t){return this.requestHandler.internalUrlToPath(t)}get absoluteUrl(){return this.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.documentRoot}setCookies(t){for(const r of t)try{if(!r.includes("="))continue;const s=r.indexOf("="),n=r.substring(0,s),o=r.substring(s+1).split(";")[0];l(this,E)[n]=o}catch(s){console.error(s)}}serializeCookies(){const t=[];for(const r in l(this,E))t.push(`${r}=${l(this,E)[r]}`);return t.join("; ")}}E=new WeakMap,b=new WeakMap;const DEFAULT_BASE_URL="http://example.com";function toRelativeUrl(e){return e.toString().substring(e.origin.length)}function removePathPrefix(e,t){return!t||!e.startsWith(t)?e:e.substring(t.length)}function ensurePathPrefix(e,t){return!t||e.startsWith(t)?e:t+e}async function encodeAsMultipart(e){const t=`----${Math.random().toString(36).slice(2)}`,r=`multipart/form-data; boundary=${t}`,s=new TextEncoder,n=[];for(const[c,u]of Object.entries(e))n.push(`--${t}\r
|
|
36
|
+
`),n.push(`Content-Disposition: form-data; name="${c}"`),u instanceof File&&n.push(`; filename="${u.name}"`),n.push(`\r
|
|
37
|
+
`),u instanceof File&&(n.push("Content-Type: application/octet-stream"),n.push(`\r
|
|
38
38
|
`)),n.push(`\r
|
|
39
|
-
`),
|
|
39
|
+
`),u instanceof File?n.push(await fileToUint8Array(u)):n.push(u),n.push(`\r
|
|
40
40
|
`);n.push(`--${t}--\r
|
|
41
|
-
`);const o=n.reduce((c,d)=>c+d.length,0),i=new Uint8Array(o);let a=0;for(const c of n)i.set(typeof c=="string"?s.encode(c):c,a),a+=c.length;return{bytes:i,contentType:r}}function fileToUint8Array(e){return new Promise(t=>{const r=new FileReader;r.onload=()=>{t(new Uint8Array(r.result))},r.readAsArrayBuffer(e)})}var m,x,k,R,H,f,F,v,U,Q,B,Y,I,Z;class PHPRequestHandler{constructor(t,r={}){u(this,U);u(this,B);u(this,I);u(this,m,void 0);u(this,x,void 0);u(this,k,void 0);u(this,R,void 0);u(this,H,void 0);u(this,f,void 0);u(this,F,void 0);u(this,v,void 0);h(this,v,new Semaphore({concurrency:1}));const{documentRoot:s="/www/",absoluteUrl:n=typeof location=="object"?location==null?void 0:location.href:"",rewriteRules:o=[]}=r;this.php=t,h(this,m,s);const i=new URL(n);h(this,k,i.hostname),h(this,R,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,x,(i.protocol||"").replace(":",""));const a=l(this,R)!==443&&l(this,R)!==80;h(this,H,[l(this,k),a?`:${l(this,R)}`:""].join("")),h(this,f,i.pathname.replace(/\/+$/,"")),h(this,F,[`${l(this,x)}://`,l(this,H),l(this,f)].join("")),this.rewriteRules=o}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(l(this,f))&&(r.pathname=r.pathname.slice(l(this,f).length)),toRelativeUrl(r)}get isRequestRunning(){return l(this,v).running>0}get absoluteUrl(){return l(this,F)}get documentRoot(){return l(this,m)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url.split("#")[0],r?void 0:DEFAULT_BASE_URL),n=applyRewriteRules(removePathPrefix(decodeURIComponent(s.pathname),l(this,f)),this.rewriteRules),o=joinPaths(l(this,m),n);return seemsLikeAPHPRequestHandlerPath(o)?await p(this,B,Y).call(this,t,s):p(this,U,Q).call(this,o)}}m=new WeakMap,x=new WeakMap,k=new WeakMap,R=new WeakMap,H=new WeakMap,f=new WeakMap,F=new WeakMap,v=new WeakMap,U=new WeakSet,Q=function(t){if(!this.php.fileExists(t))return new PHPResponse(404,{"x-file-type":["static"]},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new PHPResponse(200,{"content-length":[`${r.byteLength}`],"content-type":[inferMimeType(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)},B=new WeakSet,Y=async function(t,r){var n;if(l(this,v).running>0&&((n=t.headers)==null?void 0:n["x-request-issuer"])==="php")return console.warn("Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."),new PHPResponse(502,{},new TextEncoder().encode("502 Bad Gateway"));const s=await l(this,v).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",l(this,m)),this.php.addServerGlobalEntry("HTTPS",l(this,F).startsWith("https://")?"on":"");let o="GET";const i={host:l(this,H),...normalizeHeaders(t.headers||{})};let a=t.body;if(typeof a=="object"&&!(a instanceof Uint8Array)){o="POST";const{bytes:d,contentType:_}=await encodeAsMultipart(a);a=d,i["content-type"]=_}let c;try{c=p(this,I,Z).call(this,decodeURIComponent(r.pathname))}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),l(this,f)),protocol:l(this,x),method:t.method||o,body:a,scriptPath:c,headers:i})}finally{s()}},I=new WeakSet,Z=function(t){let r=removePathPrefix(t,l(this,f));r=applyRewriteRules(r,this.rewriteRules),r.includes(".php")?r=r.split(".php")[0]+".php":this.php.isDir(`${l(this,m)}${r}`)?(r.endsWith("/")||(r=`${r}/`),r=`${r}index.php`):r="/index.php";const s=`${l(this,m)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};function inferMimeType(e){switch(e.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}function seemsLikeAPHPRequestHandlerPath(e){return seemsLikeAPHPFile(e)||seemsLikeADirectoryRoot(e)}function seemsLikeAPHPFile(e){return e.endsWith(".php")||e.includes(".php/")}function seemsLikeADirectoryRoot(e){return!e.split("/").pop().includes(".")}function applyRewriteRules(e,t){for(const r of t)if(new RegExp(r.match).test(e))return e.replace(r.match,r.replacement);return e}const FileErrorCodes={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function getEmscriptenFsError(e){const t=typeof e=="object"?e==null?void 0:e.errno:null;if(t in FileErrorCodes)return FileErrorCodes[t]}function rethrowFileSystemError(e=""){return function(r,s,n){const o=n.value;n.value=function(...i){try{return o.apply(this,i)}catch(a){const c=typeof a=="object"?a==null?void 0:a.errno:null;if(c in FileErrorCodes){const d=FileErrorCodes[c],_=typeof i[0]=="string"?i[0]:null,ue=_!==null?e.replaceAll("{path}",_):e;throw new Error(`${ue}: ${d}`,{cause:a})}throw a}}}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(e,t={}){const[r,s,n]=makePromise(),o=e.init(currentJsRuntime,{onAbort(a){n(a),console.error(a)},ENV:{},locateFile:a=>a,...t,noInitialRun:!0,onRuntimeInitialized(){t.onRuntimeInitialized&&t.onRuntimeInitialized(),s()}});await r;const i=++lastRuntimeId;return o.id=i,o.originalExit=o._exit,o._exit=function(a){return loadedRuntimes.delete(i),o.originalExit(a)},o[RuntimeId]=i,loadedRuntimes.set(i,o),i}function getLoadedRuntime(e){return loadedRuntimes.get(e)}const currentJsRuntime=function(){var e;return typeof process<"u"&&((e=process.release)==null?void 0:e.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),makePromise=()=>{const e=[],t=new Promise((r,s)=>{e.push(r,s)});return e.unshift(t),e};var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__decorateClass=(e,t,r,s)=>{for(var n=s>1?void 0:s?__getOwnPropDesc(t,r):t,o=e.length-1,i;o>=0;o--)(i=e[o])&&(n=(s?i(t,r,n):i(n))||n);return s&&n&&__defProp(t,r,n),n};const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");var S,T,C,y,w,g,P,A,L,K,N,X,q,ee,O,te,M,re,D,se,$,ne,j,ie,W,oe,z,ae,G,le,V,ce;class BasePHP{constructor(e,t){u(this,L);u(this,N);u(this,q);u(this,O);u(this,M);u(this,D);u(this,$);u(this,j);u(this,W);u(this,z);u(this,G);u(this,V);u(this,S,void 0);u(this,T,void 0);u(this,C,void 0);u(this,y,void 0);u(this,w,void 0);u(this,g,void 0);u(this,P,void 0);u(this,A,void 0);h(this,S,[]),h(this,y,!1),h(this,w,null),h(this,g,{}),h(this,P,new Map),h(this,A,[]),this.semaphore=new Semaphore({concurrency:1}),e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new PHPBrowser(new PHPRequestHandler(this,t)))}addEventListener(e,t){l(this,P).has(e)||l(this,P).set(e,new Set),l(this,P).get(e).add(t)}removeEventListener(e,t){var r;(r=l(this,P).get(e))==null||r.delete(t)}dispatchEvent(e){const t=l(this,P).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){l(this,A).push(e)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const t=getLoadedRuntime(e);if(!t)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=t,t.onMessage=async r=>{for(const s of l(this,A)){const n=await s(r);if(n)return n}return""},h(this,w,improveWASMErrorReporting(t)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(e){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[e])!==0)throw new Error("Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?");h(this,C,e)}setPhpIniPath(e){if(l(this,y))throw new Error("Cannot set PHP ini path after calling run().");h(this,T,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(l(this,y))throw new Error("Cannot set PHP ini entries after calling run().");l(this,S).push([e,t])}chdir(e){this[__private__dont__use].FS.chdir(e)}async request(e,t){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,t)}async run(e){const t=await this.semaphore.acquire();let r;try{if(l(this,y)||(p(this,L,K).call(this),h(this,y,!0)),e.scriptPath&&!this.fileExists(e.scriptPath))throw new Error(`The script path "${e.scriptPath}" does not exist.`);p(this,j,ie).call(this,e.scriptPath||""),p(this,q,ee).call(this,e.relativeUri||""),p(this,M,re).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";p(this,O,te).call(this,n,e.protocol||"http"),p(this,D,se).call(this,s),e.body&&(r=p(this,$,ne).call(this,e.body)),typeof e.code=="string"&&p(this,G,le).call(this," ?>"+e.code),p(this,W,oe).call(this);const o=e.env||{};for(const a in o)p(this,z,ae).call(this,a,o[a]);const i=await p(this,V,ce).call(this);if(i.exitCode!==0){console.warn("PHP.run() output was:",i.text);const a=new Error(`PHP.run() failed with exit code ${i.exitCode} and the following output: `+i.errors);throw a.response=i,a.source="request",console.error(a),a}return i}catch(s){throw this.dispatchEvent({type:"request.error",error:s,source:s.source??"php-wasm"}),s}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){l(this,g)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/internal/consts.json")&&this.readFileAsText("/internal/consts.json")||"{}")}catch{}this.writeFile("/internal/consts.json",JSON.stringify({...r,[e]:t}))}mkdir(e){this[__private__dont__use].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[__private__dont__use].FS.readFile(e)}writeFile(e,t){this[__private__dont__use].FS.writeFile(e,t)}unlink(e){this[__private__dont__use].FS.unlink(e)}mv(e,t){try{this[__private__dont__use].FS.rename(e,t)}catch(r){const s=getEmscriptenFsError(r);throw s?new Error(`Could not move ${e} to ${t}: ${s}`,{cause:r}):r}}rmdir(e,t={recursive:!0}){t!=null&&t.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[__private__dont__use].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[__private__dont__use].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(n=>`${s}/${n}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[__private__dont__use].FS.isDir(this[__private__dont__use].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[__private__dont__use].FS.lookupPath(e),!0}catch{return!1}}hotSwapPHPRuntime(e){const t=this[__private__dont__use].FS;try{this.exit()}catch{}if(this.initializeRuntime(e),l(this,T)&&this.setPhpIniPath(l(this,T)),l(this,C)&&this.setSapiName(l(this,C)),this.requestHandler){const r=this.documentRoot;copyFS(t,this[__private__dont__use].FS,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}h(this,y,!1),h(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,T=new WeakMap,C=new WeakMap,y=new WeakMap,w=new WeakMap,g=new WeakMap,P=new WeakMap,A=new WeakMap,L=new WeakSet,K=function(){if(this.setPhpIniEntry("auto_prepend_file","/internal/consts.php"),this.fileExists("/internal/consts.php")||this.writeFile("/internal/consts.php",`<?php
|
|
41
|
+
`);const o=n.reduce((c,u)=>c+u.length,0),i=new Uint8Array(o);let a=0;for(const c of n)i.set(typeof c=="string"?s.encode(c):c,a),a+=c.length;return{bytes:i,contentType:r}}function fileToUint8Array(e){return new Promise(t=>{const r=new FileReader;r.onload=()=>{t(new Uint8Array(r.result))},r.readAsArrayBuffer(e)})}var m,x,k,R,H,_,F,v,U,Q,B,Y,I,Z;class PHPRequestHandler{constructor(t,r={}){d(this,U);d(this,B);d(this,I);d(this,m,void 0);d(this,x,void 0);d(this,k,void 0);d(this,R,void 0);d(this,H,void 0);d(this,_,void 0);d(this,F,void 0);d(this,v,void 0);h(this,v,new Semaphore({concurrency:1}));const{documentRoot:s="/www/",absoluteUrl:n=typeof location=="object"?location==null?void 0:location.href:"",rewriteRules:o=[]}=r;this.php=t,h(this,m,s);const i=new URL(n);h(this,k,i.hostname),h(this,R,i.port?Number(i.port):i.protocol==="https:"?443:80),h(this,x,(i.protocol||"").replace(":",""));const a=l(this,R)!==443&&l(this,R)!==80;h(this,H,[l(this,k),a?`:${l(this,R)}`:""].join("")),h(this,_,i.pathname.replace(/\/+$/,"")),h(this,F,[`${l(this,x)}://`,l(this,H),l(this,_)].join("")),this.rewriteRules=o}pathToInternalUrl(t){return`${this.absoluteUrl}${t}`}internalUrlToPath(t){const r=new URL(t);return r.pathname.startsWith(l(this,_))&&(r.pathname=r.pathname.slice(l(this,_).length)),toRelativeUrl(r)}get isRequestRunning(){return l(this,v).running>0}get absoluteUrl(){return l(this,F)}get documentRoot(){return l(this,m)}async request(t){const r=t.url.startsWith("http://")||t.url.startsWith("https://"),s=new URL(t.url.split("#")[0],r?void 0:DEFAULT_BASE_URL),n=applyRewriteRules(removePathPrefix(decodeURIComponent(s.pathname),l(this,_)),this.rewriteRules),o=joinPaths(l(this,m),n);return seemsLikeAPHPRequestHandlerPath(o)?await p(this,B,Y).call(this,t,s):p(this,U,Q).call(this,o)}}m=new WeakMap,x=new WeakMap,k=new WeakMap,R=new WeakMap,H=new WeakMap,_=new WeakMap,F=new WeakMap,v=new WeakMap,U=new WeakSet,Q=function(t){if(!this.php.fileExists(t))return new PHPResponse(404,{"x-file-type":["static"]},new TextEncoder().encode("404 File not found"));const r=this.php.readFileAsBuffer(t);return new PHPResponse(200,{"content-length":[`${r.byteLength}`],"content-type":[inferMimeType(t)],"accept-ranges":["bytes"],"cache-control":["public, max-age=0"]},r)},B=new WeakSet,Y=async function(t,r){var n;if(l(this,v).running>0&&((n=t.headers)==null?void 0:n["x-request-issuer"])==="php")return console.warn("Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."),new PHPResponse(502,{},new TextEncoder().encode("502 Bad Gateway"));const s=await l(this,v).acquire();try{this.php.addServerGlobalEntry("REMOTE_ADDR","127.0.0.1"),this.php.addServerGlobalEntry("DOCUMENT_ROOT",l(this,m)),this.php.addServerGlobalEntry("HTTPS",l(this,F).startsWith("https://")?"on":"");let o="GET";const i={host:l(this,H),...normalizeHeaders(t.headers||{})};let a=t.body;if(typeof a=="object"&&!(a instanceof Uint8Array)){o="POST";const{bytes:u,contentType:f}=await encodeAsMultipart(a);a=u,i["content-type"]=f}let c;try{c=p(this,I,Z).call(this,decodeURIComponent(r.pathname))}catch{return new PHPResponse(404,{},new TextEncoder().encode("404 File not found"))}try{return await this.php.run({relativeUri:ensurePathPrefix(toRelativeUrl(r),l(this,_)),protocol:l(this,x),method:t.method||o,body:a,scriptPath:c,headers:i})}catch(u){const f=u;if(f!=null&&f.response)return f.response;throw u}}finally{s()}},I=new WeakSet,Z=function(t){let r=removePathPrefix(t,l(this,_));r=applyRewriteRules(r,this.rewriteRules),r.includes(".php")?r=r.split(".php")[0]+".php":this.php.isDir(`${l(this,m)}${r}`)?(r.endsWith("/")||(r=`${r}/`),r=`${r}index.php`):r="/index.php";const s=`${l(this,m)}${r}`;if(this.php.fileExists(s))return s;throw new Error(`File not found: ${s}`)};function inferMimeType(e){switch(e.split(".").pop()){case"css":return"text/css";case"js":return"application/javascript";case"png":return"image/png";case"jpg":case"jpeg":return"image/jpeg";case"gif":return"image/gif";case"svg":return"image/svg+xml";case"woff":return"font/woff";case"woff2":return"font/woff2";case"ttf":return"font/ttf";case"otf":return"font/otf";case"eot":return"font/eot";case"ico":return"image/x-icon";case"html":return"text/html";case"json":return"application/json";case"xml":return"application/xml";case"txt":case"md":return"text/plain";default:return"application-octet-stream"}}function seemsLikeAPHPRequestHandlerPath(e){return seemsLikeAPHPFile(e)||seemsLikeADirectoryRoot(e)}function seemsLikeAPHPFile(e){return e.endsWith(".php")||e.includes(".php/")}function seemsLikeADirectoryRoot(e){return!e.split("/").pop().includes(".")}function applyRewriteRules(e,t){for(const r of t)if(new RegExp(r.match).test(e))return e.replace(r.match,r.replacement);return e}const FileErrorCodes={0:"No error occurred. System call completed successfully.",1:"Argument list too long.",2:"Permission denied.",3:"Address in use.",4:"Address not available.",5:"Address family not supported.",6:"Resource unavailable, or operation would block.",7:"Connection already in progress.",8:"Bad file descriptor.",9:"Bad message.",10:"Device or resource busy.",11:"Operation canceled.",12:"No child processes.",13:"Connection aborted.",14:"Connection refused.",15:"Connection reset.",16:"Resource deadlock would occur.",17:"Destination address required.",18:"Mathematics argument out of domain of function.",19:"Reserved.",20:"File exists.",21:"Bad address.",22:"File too large.",23:"Host is unreachable.",24:"Identifier removed.",25:"Illegal byte sequence.",26:"Operation in progress.",27:"Interrupted function.",28:"Invalid argument.",29:"I/O error.",30:"Socket is connected.",31:"There is a directory under that path.",32:"Too many levels of symbolic links.",33:"File descriptor value too large.",34:"Too many links.",35:"Message too large.",36:"Reserved.",37:"Filename too long.",38:"Network is down.",39:"Connection aborted by network.",40:"Network unreachable.",41:"Too many files open in system.",42:"No buffer space available.",43:"No such device.",44:"There is no such file or directory OR the parent directory does not exist.",45:"Executable file format error.",46:"No locks available.",47:"Reserved.",48:"Not enough space.",49:"No message of the desired type.",50:"Protocol not available.",51:"No space left on device.",52:"Function not supported.",53:"The socket is not connected.",54:"Not a directory or a symbolic link to a directory.",55:"Directory not empty.",56:"State not recoverable.",57:"Not a socket.",58:"Not supported, or operation not supported on socket.",59:"Inappropriate I/O control operation.",60:"No such device or address.",61:"Value too large to be stored in data type.",62:"Previous owner died.",63:"Operation not permitted.",64:"Broken pipe.",65:"Protocol error.",66:"Protocol not supported.",67:"Protocol wrong type for socket.",68:"Result too large.",69:"Read-only file system.",70:"Invalid seek.",71:"No such process.",72:"Reserved.",73:"Connection timed out.",74:"Text file busy.",75:"Cross-device link.",76:"Extension: Capabilities insufficient."};function getEmscriptenFsError(e){const t=typeof e=="object"?e==null?void 0:e.errno:null;if(t in FileErrorCodes)return FileErrorCodes[t]}function rethrowFileSystemError(e=""){return function(r,s,n){const o=n.value;n.value=function(...i){try{return o.apply(this,i)}catch(a){const c=typeof a=="object"?a==null?void 0:a.errno:null;if(c in FileErrorCodes){const u=FileErrorCodes[c],f=typeof i[0]=="string"?i[0]:null,ue=f!==null?e.replaceAll("{path}",f):e;throw new Error(`${ue}: ${u}`,{cause:a})}throw a}}}}const RuntimeId=Symbol("RuntimeId"),loadedRuntimes=new Map;let lastRuntimeId=0;async function loadPHPRuntime(e,t={}){const[r,s,n]=makePromise(),o=e.init(currentJsRuntime,{onAbort(a){n(a),console.error(a)},ENV:{},locateFile:a=>a,...t,noInitialRun:!0,onRuntimeInitialized(){t.onRuntimeInitialized&&t.onRuntimeInitialized(),s()}});await r;const i=++lastRuntimeId;return o.id=i,o.originalExit=o._exit,o._exit=function(a){return loadedRuntimes.delete(i),o.originalExit(a)},o[RuntimeId]=i,loadedRuntimes.set(i,o),i}function getLoadedRuntime(e){return loadedRuntimes.get(e)}const currentJsRuntime=function(){var e;return typeof process<"u"&&((e=process.release)==null?void 0:e.name)==="node"?"NODE":typeof window<"u"?"WEB":typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?"WORKER":"NODE"}(),makePromise=()=>{const e=[],t=new Promise((r,s)=>{e.push(r,s)});return e.unshift(t),e};var __defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__decorateClass=(e,t,r,s)=>{for(var n=s>1?void 0:s?__getOwnPropDesc(t,r):t,o=e.length-1,i;o>=0;o--)(i=e[o])&&(n=(s?i(t,r,n):i(n))||n);return s&&n&&__defProp(t,r,n),n};const STRING="string",NUMBER="number",__private__dont__use=Symbol("__private__dont__use");class PHPExecutionFailureError extends Error{constructor(t,r,s){super(t),this.response=r,this.source=s}}var S,T,C,y,w,g,P,A,L,K,N,X,q,ee,O,te,M,re,D,se,$,ne,j,ie,W,oe,z,ae,G,le,V,ce;class BasePHP{constructor(e,t){d(this,L);d(this,N);d(this,q);d(this,O);d(this,M);d(this,D);d(this,$);d(this,j);d(this,W);d(this,z);d(this,G);d(this,V);d(this,S,void 0);d(this,T,void 0);d(this,C,void 0);d(this,y,void 0);d(this,w,void 0);d(this,g,void 0);d(this,P,void 0);d(this,A,void 0);h(this,S,[]),h(this,y,!1),h(this,w,null),h(this,g,{}),h(this,P,new Map),h(this,A,[]),this.semaphore=new Semaphore({concurrency:1}),e!==void 0&&this.initializeRuntime(e),t&&(this.requestHandler=new PHPBrowser(new PHPRequestHandler(this,t)))}addEventListener(e,t){l(this,P).has(e)||l(this,P).set(e,new Set),l(this,P).get(e).add(t)}removeEventListener(e,t){var r;(r=l(this,P).get(e))==null||r.delete(t)}dispatchEvent(e){const t=l(this,P).get(e.type);if(t)for(const r of t)r(e)}async onMessage(e){l(this,A).push(e)}async setSpawnHandler(handler){typeof handler=="string"&&(handler=createSpawnHandler(eval(handler))),this[__private__dont__use].spawnProcess=handler}get absoluteUrl(){return this.requestHandler.requestHandler.absoluteUrl}get documentRoot(){return this.requestHandler.requestHandler.documentRoot}pathToInternalUrl(e){return this.requestHandler.requestHandler.pathToInternalUrl(e)}internalUrlToPath(e){return this.requestHandler.requestHandler.internalUrlToPath(e)}initializeRuntime(e){if(this[__private__dont__use])throw new Error("PHP runtime already initialized.");const t=getLoadedRuntime(e);if(!t)throw new Error("Invalid PHP runtime id.");this[__private__dont__use]=t,t.onMessage=async r=>{for(const s of l(this,A)){const n=await s(r);if(n)return n}return""},h(this,w,improveWASMErrorReporting(t)),this.dispatchEvent({type:"runtime.initialized"})}async setSapiName(e){if(this[__private__dont__use].ccall("wasm_set_sapi_name",NUMBER,[STRING],[e])!==0)throw new Error("Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?");h(this,C,e)}setPhpIniPath(e){if(l(this,y))throw new Error("Cannot set PHP ini path after calling run().");h(this,T,e),this[__private__dont__use].ccall("wasm_set_phpini_path",null,["string"],[e])}setPhpIniEntry(e,t){if(l(this,y))throw new Error("Cannot set PHP ini entries after calling run().");l(this,S).push([e,t])}chdir(e){this[__private__dont__use].FS.chdir(e)}async request(e,t){if(!this.requestHandler)throw new Error("No request handler available.");return this.requestHandler.request(e,t)}async run(e){const t=await this.semaphore.acquire();let r;try{if(l(this,y)||(p(this,L,K).call(this),h(this,y,!0)),e.scriptPath&&!this.fileExists(e.scriptPath))throw new Error(`The script path "${e.scriptPath}" does not exist.`);p(this,j,ie).call(this,e.scriptPath||""),p(this,q,ee).call(this,e.relativeUri||""),p(this,M,re).call(this,e.method||"GET");const s=normalizeHeaders(e.headers||{}),n=s.host||"example.com:443";p(this,O,te).call(this,n,e.protocol||"http"),p(this,D,se).call(this,s),e.body&&(r=p(this,$,ne).call(this,e.body)),typeof e.code=="string"&&p(this,G,le).call(this," ?>"+e.code),p(this,W,oe).call(this);const o=e.env||{};for(const a in o)p(this,z,ae).call(this,a,o[a]);const i=await p(this,V,ce).call(this);if(i.exitCode!==0){console.warn("PHP.run() output was:",i.text);const a=new PHPExecutionFailureError(`PHP.run() failed with exit code ${i.exitCode} and the following output: `+i.errors,i,"request");throw console.error(a),a}return i}catch(s){throw this.dispatchEvent({type:"request.error",error:s,source:s.source??"php-wasm"}),s}finally{try{r&&this[__private__dont__use].free(r)}finally{t(),this.dispatchEvent({type:"request.end"})}}}addServerGlobalEntry(e,t){l(this,g)[e]=t}defineConstant(e,t){let r={};try{r=JSON.parse(this.fileExists("/internal/consts.json")&&this.readFileAsText("/internal/consts.json")||"{}")}catch{}this.writeFile("/internal/consts.json",JSON.stringify({...r,[e]:t}))}mkdir(e){this[__private__dont__use].FS.mkdirTree(e)}mkdirTree(e){this.mkdir(e)}readFileAsText(e){return new TextDecoder().decode(this.readFileAsBuffer(e))}readFileAsBuffer(e){return this[__private__dont__use].FS.readFile(e)}writeFile(e,t){this[__private__dont__use].FS.writeFile(e,t)}unlink(e){this[__private__dont__use].FS.unlink(e)}mv(e,t){try{this[__private__dont__use].FS.rename(e,t)}catch(r){const s=getEmscriptenFsError(r);throw s?new Error(`Could not move ${e} to ${t}: ${s}`,{cause:r}):r}}rmdir(e,t={recursive:!0}){t!=null&&t.recursive&&this.listFiles(e).forEach(r=>{const s=`${e}/${r}`;this.isDir(s)?this.rmdir(s,t):this.unlink(s)}),this[__private__dont__use].FS.rmdir(e)}listFiles(e,t={prependPath:!1}){if(!this.fileExists(e))return[];try{const r=this[__private__dont__use].FS.readdir(e).filter(s=>s!=="."&&s!=="..");if(t.prependPath){const s=e.replace(/\/$/,"");return r.map(n=>`${s}/${n}`)}return r}catch(r){return console.error(r,{path:e}),[]}}isDir(e){return this.fileExists(e)?this[__private__dont__use].FS.isDir(this[__private__dont__use].FS.lookupPath(e).node.mode):!1}fileExists(e){try{return this[__private__dont__use].FS.lookupPath(e),!0}catch{return!1}}hotSwapPHPRuntime(e){const t=this[__private__dont__use].FS;try{this.exit()}catch{}if(this.initializeRuntime(e),l(this,T)&&this.setPhpIniPath(l(this,T)),l(this,C)&&this.setSapiName(l(this,C)),this.requestHandler){const r=this.documentRoot;copyFS(t,this[__private__dont__use].FS,r)}}exit(e=0){this.dispatchEvent({type:"runtime.beforedestroy"});try{this[__private__dont__use]._exit(e)}catch{}h(this,y,!1),h(this,w,null),delete this[__private__dont__use].onMessage,delete this[__private__dont__use]}}S=new WeakMap,T=new WeakMap,C=new WeakMap,y=new WeakMap,w=new WeakMap,g=new WeakMap,P=new WeakMap,A=new WeakMap,L=new WeakSet,K=function(){if(this.setPhpIniEntry("auto_prepend_file","/internal/consts.php"),this.fileExists("/internal/consts.php")||this.writeFile("/internal/consts.php",`<?php
|
|
42
42
|
if(file_exists('/internal/consts.json')) {
|
|
43
43
|
$consts = json_decode(file_get_contents('/internal/consts.json'), true);
|
|
44
44
|
foreach ($consts as $const => $value) {
|
|
@@ -49,4 +49,4 @@ ${bold} WASM ERROR${reset}${redBg}`);for(const t of e.split(`
|
|
|
49
49
|
}`),l(this,S).length>0){const e=l(this,S).map(([t,r])=>`${t}=${r}`).join(`
|
|
50
50
|
`)+`
|
|
51
51
|
|
|
52
|
-
`;this[__private__dont__use].ccall("wasm_set_phpini_entries",null,[STRING],[e])}this[__private__dont__use].ccall("php_wasm_init",null,[],[])},N=new WeakSet,X=function(){const e="/internal/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const t=JSON.parse(this.readFileAsText(e)),r={};for(const s of t.headers){if(!s.includes(": "))continue;const n=s.indexOf(": "),o=s.substring(0,n).toLowerCase(),i=s.substring(n+2);o in r||(r[o]=[]),r[o].push(i)}return{headers:r,httpStatusCode:t.status}},q=new WeakSet,ee=function(e){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[t])}},O=new WeakSet,te=function(e,t){this[__private__dont__use].ccall("wasm_set_request_host",null,[STRING],[e]);let r;try{r=parseInt(new URL(e).port,10)}catch{}(!r||isNaN(r)||r===80)&&(r=t==="https"?443:80),this[__private__dont__use].ccall("wasm_set_request_port",null,[NUMBER],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")},M=new WeakSet,re=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},D=new WeakSet,se=function(e){e.cookie&&this[__private__dont__use].ccall("wasm_set_cookies",null,[STRING],[e.cookie]),e["content-type"]&&this[__private__dont__use].ccall("wasm_set_content_type",null,[STRING],[e["content-type"]]),e["content-length"]&&this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[parseInt(e["content-length"],10)]);for(const t in e){let r="HTTP_";["content-type","content-length"].includes(t.toLowerCase())&&(r=""),this.addServerGlobalEntry(`${r}${t.toUpperCase().replace(/-/g,"_")}`,e[t])}},$=new WeakSet,ne=function(e){let t,r;typeof e=="string"?(console.warn("Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"),r=this[__private__dont__use].lengthBytesUTF8(e),t=r+1):(r=e.byteLength,t=e.byteLength);const s=this[__private__dont__use].malloc(t);if(!s)throw new Error("Could not allocate memory for the request body.");return typeof e=="string"?this[__private__dont__use].stringToUTF8(e,s,t+1):this[__private__dont__use].HEAPU8.set(e,s),this[__private__dont__use].ccall("wasm_set_request_body",null,[NUMBER],[s]),this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[r]),s},j=new WeakSet,ie=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},W=new WeakSet,oe=function(){for(const e in l(this,g))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,l(this,g)[e]])},z=new WeakSet,ae=function(e,t){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[e,t])},G=new WeakSet,le=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},V=new WeakSet,ce=async function(){var n;let e,t;try{e=await new Promise((o,i)=>{var c;t=
|
|
52
|
+
`;this[__private__dont__use].ccall("wasm_set_phpini_entries",null,[STRING],[e])}this[__private__dont__use].ccall("php_wasm_init",null,[],[])},N=new WeakSet,X=function(){const e="/internal/headers.json";if(!this.fileExists(e))throw new Error("SAPI Error: Could not find response headers file.");const t=JSON.parse(this.readFileAsText(e)),r={};for(const s of t.headers){if(!s.includes(": "))continue;const n=s.indexOf(": "),o=s.substring(0,n).toLowerCase(),i=s.substring(n+2);o in r||(r[o]=[]),r[o].push(i)}return{headers:r,httpStatusCode:t.status}},q=new WeakSet,ee=function(e){if(this[__private__dont__use].ccall("wasm_set_request_uri",null,[STRING],[e]),e.includes("?")){const t=e.substring(e.indexOf("?")+1);this[__private__dont__use].ccall("wasm_set_query_string",null,[STRING],[t])}},O=new WeakSet,te=function(e,t){this[__private__dont__use].ccall("wasm_set_request_host",null,[STRING],[e]);let r;try{r=parseInt(new URL(e).port,10)}catch{}(!r||isNaN(r)||r===80)&&(r=t==="https"?443:80),this[__private__dont__use].ccall("wasm_set_request_port",null,[NUMBER],[r]),(t==="https"||!t&&r===443)&&this.addServerGlobalEntry("HTTPS","on")},M=new WeakSet,re=function(e){this[__private__dont__use].ccall("wasm_set_request_method",null,[STRING],[e])},D=new WeakSet,se=function(e){e.cookie&&this[__private__dont__use].ccall("wasm_set_cookies",null,[STRING],[e.cookie]),e["content-type"]&&this[__private__dont__use].ccall("wasm_set_content_type",null,[STRING],[e["content-type"]]),e["content-length"]&&this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[parseInt(e["content-length"],10)]);for(const t in e){let r="HTTP_";["content-type","content-length"].includes(t.toLowerCase())&&(r=""),this.addServerGlobalEntry(`${r}${t.toUpperCase().replace(/-/g,"_")}`,e[t])}},$=new WeakSet,ne=function(e){let t,r;typeof e=="string"?(console.warn("Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"),r=this[__private__dont__use].lengthBytesUTF8(e),t=r+1):(r=e.byteLength,t=e.byteLength);const s=this[__private__dont__use].malloc(t);if(!s)throw new Error("Could not allocate memory for the request body.");return typeof e=="string"?this[__private__dont__use].stringToUTF8(e,s,t+1):this[__private__dont__use].HEAPU8.set(e,s),this[__private__dont__use].ccall("wasm_set_request_body",null,[NUMBER],[s]),this[__private__dont__use].ccall("wasm_set_content_length",null,[NUMBER],[r]),s},j=new WeakSet,ie=function(e){this[__private__dont__use].ccall("wasm_set_path_translated",null,[STRING],[e])},W=new WeakSet,oe=function(){for(const e in l(this,g))this[__private__dont__use].ccall("wasm_add_SERVER_entry",null,[STRING,STRING],[e,l(this,g)[e]])},z=new WeakSet,ae=function(e,t){this[__private__dont__use].ccall("wasm_add_ENV_entry",null,[STRING,STRING],[e,t])},G=new WeakSet,le=function(e){this[__private__dont__use].ccall("wasm_set_php_code",null,[STRING],[e])},V=new WeakSet,ce=async function(){var n;let e,t;try{e=await new Promise((o,i)=>{var c;t=u=>{console.error(u),console.error(u.error);const f=new Error("Rethrown");f.cause=u.error,f.betterMessage=u.message,i(f)},(c=l(this,w))==null||c.addEventListener("error",t);const a=this[__private__dont__use].ccall("wasm_sapi_handle_request",NUMBER,[],[],{async:!0});return a instanceof Promise?a.then(o,i):o(a)})}catch(o){for(const u in this)typeof this[u]=="function"&&(this[u]=()=>{throw new Error("PHP runtime has crashed – see the earlier error for details.")});this.functionsMaybeMissingFromAsyncify=getFunctionsMaybeMissingFromAsyncify();const i=o,a="betterMessage"in i?i.betterMessage:i.message,c=new Error(a);throw c.cause=i,console.error(c),c}finally{(n=l(this,w))==null||n.removeEventListener("error",t),h(this,g,{})}const{headers:r,httpStatusCode:s}=p(this,N,X).call(this);return new PHPResponse(e===0?s:500,r,this.readFileAsBuffer("/internal/stdout"),this.readFileAsText("/internal/stderr"),e)};__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdir",1);__decorateClass([rethrowFileSystemError('Could not create directory "{path}"')],BasePHP.prototype,"mkdirTree",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsText",1);__decorateClass([rethrowFileSystemError('Could not read "{path}"')],BasePHP.prototype,"readFileAsBuffer",1);__decorateClass([rethrowFileSystemError('Could not write to "{path}"')],BasePHP.prototype,"writeFile",1);__decorateClass([rethrowFileSystemError('Could not unlink "{path}"')],BasePHP.prototype,"unlink",1);__decorateClass([rethrowFileSystemError('Could not remove directory "{path}"')],BasePHP.prototype,"rmdir",1);__decorateClass([rethrowFileSystemError('Could not list files in "{path}"')],BasePHP.prototype,"listFiles",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"isDir",1);__decorateClass([rethrowFileSystemError('Could not stat "{path}"')],BasePHP.prototype,"fileExists",1);function normalizeHeaders(e){const t={};for(const r in e)t[r.toLowerCase()]=e[r];return t}function copyFS(e,t,r){let s;try{s=e.lookupPath(r)}catch{return}if(!("contents"in s.node))return;if(!e.isDir(s.node.mode)){t.writeFile(r,e.readFile(r));return}t.mkdirTree(r);const n=e.readdir(r).filter(o=>o!=="."&&o!=="..");for(const o of n)copyFS(e,t,joinPaths(r,o))}function isLocalPHP(e){return!(e instanceof BasePHP)}function isRemotePHP(e){return!isLocalPHP(e)}function rotatePHPRuntime({php:e,recreateRuntime:t,maxRequests:r}){let s=0;async function n(){if(++s<r)return;s=0;const o=await e.semaphore.acquire();try{e.hotSwapPHPRuntime(await t())}finally{o()}}return e.addEventListener("request.end",n),function(){e.removeEventListener("request.end",n)}}async function writeFiles(e,t,r,{rmRoot:s=!1}={}){s&&await e.isDir(t)&&await e.rmdir(t,{recursive:!0});for(const[n,o]of Object.entries(r)){const i=joinPaths(t,n);await e.fileExists(dirname(i))||await e.mkdir(dirname(i)),await e.writeFile(i,o)}}exports.BasePHP=BasePHP;exports.DEFAULT_BASE_URL=DEFAULT_BASE_URL;exports.LatestSupportedPHPVersion=LatestSupportedPHPVersion;exports.PHPBrowser=PHPBrowser;exports.PHPRequestHandler=PHPRequestHandler;exports.PHPResponse=PHPResponse;exports.SupportedPHPExtensionBundles=SupportedPHPExtensionBundles;exports.SupportedPHPExtensionsList=SupportedPHPExtensionsList;exports.SupportedPHPVersions=SupportedPHPVersions;exports.SupportedPHPVersionsList=SupportedPHPVersionsList;exports.UnhandledRejectionsTarget=UnhandledRejectionsTarget;exports.__private__dont__use=__private__dont__use;exports.applyRewriteRules=applyRewriteRules;exports.ensurePathPrefix=ensurePathPrefix;exports.isExitCodeZero=isExitCodeZero;exports.isLocalPHP=isLocalPHP;exports.isRemotePHP=isRemotePHP;exports.iterateFiles=iteratePhpFiles;exports.loadPHPRuntime=loadPHPRuntime;exports.removePathPrefix=removePathPrefix;exports.rethrowFileSystemError=rethrowFileSystemError;exports.rotatePHPRuntime=rotatePHPRuntime;exports.toRelativeUrl=toRelativeUrl;exports.writeFiles=writeFiles;exports.writeFilesStreamToPhp=writeFilesStreamToPhp;
|
package/index.js
CHANGED
|
@@ -2,7 +2,7 @@ var J = (e, t, r) => {
|
|
|
2
2
|
if (!t.has(e))
|
|
3
3
|
throw TypeError("Cannot " + r);
|
|
4
4
|
};
|
|
5
|
-
var l = (e, t, r) => (J(e, t, "read from private field"), r ? r.call(e) : t.get(e)),
|
|
5
|
+
var l = (e, t, r) => (J(e, t, "read from private field"), r ? r.call(e) : t.get(e)), d = (e, t, r) => {
|
|
6
6
|
if (t.has(e))
|
|
7
7
|
throw TypeError("Cannot add the same private member more than once");
|
|
8
8
|
t instanceof WeakSet ? t.add(e) : t.set(e, r);
|
|
@@ -61,8 +61,8 @@ if (currentJsRuntime$1 === "NODE") {
|
|
|
61
61
|
r + o.byteLength
|
|
62
62
|
).arrayBuffer(), c = new Uint8Array(a);
|
|
63
63
|
new Uint8Array(o.buffer).set(c);
|
|
64
|
-
const
|
|
65
|
-
n.byobRequest.respond(
|
|
64
|
+
const u = c.byteLength;
|
|
65
|
+
n.byobRequest.respond(u), r += u, r >= s.size && n.close();
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
68
|
});
|
|
@@ -504,15 +504,15 @@ async function* iteratePhpFiles(e, t, {
|
|
|
504
504
|
return;
|
|
505
505
|
const a = await e.listFiles(i);
|
|
506
506
|
for (const c of a) {
|
|
507
|
-
const
|
|
508
|
-
if (n.includes(
|
|
507
|
+
const u = `${i}/${c}`;
|
|
508
|
+
if (n.includes(u.substring(t.length + 1)))
|
|
509
509
|
continue;
|
|
510
|
-
await e.isDir(
|
|
511
|
-
streamReadFileFromPHP(e,
|
|
510
|
+
await e.isDir(u) ? o.push(u) : yield new StreamedFile(
|
|
511
|
+
streamReadFileFromPHP(e, u),
|
|
512
512
|
r ? joinPaths(
|
|
513
513
|
s || "",
|
|
514
|
-
|
|
515
|
-
) :
|
|
514
|
+
u.substring(t.length + 1)
|
|
515
|
+
) : u
|
|
516
516
|
);
|
|
517
517
|
}
|
|
518
518
|
}
|
|
@@ -589,8 +589,8 @@ class PHPBrowser {
|
|
|
589
589
|
* @param config - The browser configuration.
|
|
590
590
|
*/
|
|
591
591
|
constructor(t, r = {}) {
|
|
592
|
-
|
|
593
|
-
|
|
592
|
+
d(this, E, void 0);
|
|
593
|
+
d(this, b, void 0);
|
|
594
594
|
this.requestHandler = t, h(this, E, {}), h(this, b, {
|
|
595
595
|
handleRedirects: !1,
|
|
596
596
|
maxRedirects: 4,
|
|
@@ -682,16 +682,16 @@ function ensurePathPrefix(e, t) {
|
|
|
682
682
|
}
|
|
683
683
|
async function encodeAsMultipart(e) {
|
|
684
684
|
const t = `----${Math.random().toString(36).slice(2)}`, r = `multipart/form-data; boundary=${t}`, s = new TextEncoder(), n = [];
|
|
685
|
-
for (const [c,
|
|
685
|
+
for (const [c, u] of Object.entries(e))
|
|
686
686
|
n.push(`--${t}\r
|
|
687
|
-
`), n.push(`Content-Disposition: form-data; name="${c}"`),
|
|
688
|
-
`),
|
|
687
|
+
`), n.push(`Content-Disposition: form-data; name="${c}"`), u instanceof File && n.push(`; filename="${u.name}"`), n.push(`\r
|
|
688
|
+
`), u instanceof File && (n.push("Content-Type: application/octet-stream"), n.push(`\r
|
|
689
689
|
`)), n.push(`\r
|
|
690
|
-
`),
|
|
690
|
+
`), u instanceof File ? n.push(await fileToUint8Array(u)) : n.push(u), n.push(`\r
|
|
691
691
|
`);
|
|
692
692
|
n.push(`--${t}--\r
|
|
693
693
|
`);
|
|
694
|
-
const o = n.reduce((c,
|
|
694
|
+
const o = n.reduce((c, u) => c + u.length, 0), i = new Uint8Array(o);
|
|
695
695
|
let a = 0;
|
|
696
696
|
for (const c of n)
|
|
697
697
|
i.set(
|
|
@@ -708,7 +708,7 @@ function fileToUint8Array(e) {
|
|
|
708
708
|
}, r.readAsArrayBuffer(e);
|
|
709
709
|
});
|
|
710
710
|
}
|
|
711
|
-
var m, H, k, v, F,
|
|
711
|
+
var m, H, k, v, F, _, x, R, U, Q, B, Y, I, K;
|
|
712
712
|
class PHPRequestHandler {
|
|
713
713
|
/**
|
|
714
714
|
* @param php - The PHP instance.
|
|
@@ -721,7 +721,7 @@ class PHPRequestHandler {
|
|
|
721
721
|
* @param fsPath - Absolute path of the static file to serve.
|
|
722
722
|
* @returns The response.
|
|
723
723
|
*/
|
|
724
|
-
|
|
724
|
+
d(this, U);
|
|
725
725
|
/**
|
|
726
726
|
* Runs the requested PHP file with all the request and $_SERVER
|
|
727
727
|
* superglobals populated.
|
|
@@ -729,7 +729,7 @@ class PHPRequestHandler {
|
|
|
729
729
|
* @param request - The request.
|
|
730
730
|
* @returns The response.
|
|
731
731
|
*/
|
|
732
|
-
|
|
732
|
+
d(this, B);
|
|
733
733
|
/**
|
|
734
734
|
* Resolve the requested path to the filesystem path of the requested PHP file.
|
|
735
735
|
*
|
|
@@ -739,15 +739,15 @@ class PHPRequestHandler {
|
|
|
739
739
|
* @throws {Error} If the requested path doesn't exist.
|
|
740
740
|
* @returns The resolved filesystem path.
|
|
741
741
|
*/
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
742
|
+
d(this, I);
|
|
743
|
+
d(this, m, void 0);
|
|
744
|
+
d(this, H, void 0);
|
|
745
|
+
d(this, k, void 0);
|
|
746
|
+
d(this, v, void 0);
|
|
747
|
+
d(this, F, void 0);
|
|
748
|
+
d(this, _, void 0);
|
|
749
|
+
d(this, x, void 0);
|
|
750
|
+
d(this, R, void 0);
|
|
751
751
|
h(this, R, new Semaphore({ concurrency: 1 }));
|
|
752
752
|
const {
|
|
753
753
|
documentRoot: s = "/www/",
|
|
@@ -761,10 +761,10 @@ class PHPRequestHandler {
|
|
|
761
761
|
h(this, F, [
|
|
762
762
|
l(this, k),
|
|
763
763
|
a ? `:${l(this, v)}` : ""
|
|
764
|
-
].join("")), h(this,
|
|
764
|
+
].join("")), h(this, _, i.pathname.replace(/\/+$/, "")), h(this, x, [
|
|
765
765
|
`${l(this, H)}://`,
|
|
766
766
|
l(this, F),
|
|
767
|
-
l(this,
|
|
767
|
+
l(this, _)
|
|
768
768
|
].join("")), this.rewriteRules = o;
|
|
769
769
|
}
|
|
770
770
|
/** @inheritDoc */
|
|
@@ -774,7 +774,7 @@ class PHPRequestHandler {
|
|
|
774
774
|
/** @inheritDoc */
|
|
775
775
|
internalUrlToPath(t) {
|
|
776
776
|
const r = new URL(t);
|
|
777
|
-
return r.pathname.startsWith(l(this,
|
|
777
|
+
return r.pathname.startsWith(l(this, _)) && (r.pathname = r.pathname.slice(l(this, _).length)), toRelativeUrl(r);
|
|
778
778
|
}
|
|
779
779
|
get isRequestRunning() {
|
|
780
780
|
return l(this, R).running > 0;
|
|
@@ -796,14 +796,14 @@ class PHPRequestHandler {
|
|
|
796
796
|
), n = applyRewriteRules(
|
|
797
797
|
removePathPrefix(
|
|
798
798
|
decodeURIComponent(s.pathname),
|
|
799
|
-
l(this,
|
|
799
|
+
l(this, _)
|
|
800
800
|
),
|
|
801
801
|
this.rewriteRules
|
|
802
802
|
), o = joinPaths(l(this, m), n);
|
|
803
803
|
return seemsLikeAPHPRequestHandlerPath(o) ? await f(this, B, Y).call(this, t, s) : f(this, U, Q).call(this, o);
|
|
804
804
|
}
|
|
805
805
|
}
|
|
806
|
-
m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), F = new WeakMap(),
|
|
806
|
+
m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), F = new WeakMap(), _ = new WeakMap(), x = new WeakMap(), R = new WeakMap(), U = new WeakSet(), Q = function(t) {
|
|
807
807
|
if (!this.php.fileExists(t))
|
|
808
808
|
return new PHPResponse(
|
|
809
809
|
404,
|
|
@@ -852,8 +852,8 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), F =
|
|
|
852
852
|
let a = t.body;
|
|
853
853
|
if (typeof a == "object" && !(a instanceof Uint8Array)) {
|
|
854
854
|
o = "POST";
|
|
855
|
-
const { bytes:
|
|
856
|
-
a =
|
|
855
|
+
const { bytes: u, contentType: p } = await encodeAsMultipart(a);
|
|
856
|
+
a = u, i["content-type"] = p;
|
|
857
857
|
}
|
|
858
858
|
let c;
|
|
859
859
|
try {
|
|
@@ -865,22 +865,29 @@ m = new WeakMap(), H = new WeakMap(), k = new WeakMap(), v = new WeakMap(), F =
|
|
|
865
865
|
new TextEncoder().encode("404 File not found")
|
|
866
866
|
);
|
|
867
867
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
868
|
+
try {
|
|
869
|
+
return await this.php.run({
|
|
870
|
+
relativeUri: ensurePathPrefix(
|
|
871
|
+
toRelativeUrl(r),
|
|
872
|
+
l(this, _)
|
|
873
|
+
),
|
|
874
|
+
protocol: l(this, H),
|
|
875
|
+
method: t.method || o,
|
|
876
|
+
body: a,
|
|
877
|
+
scriptPath: c,
|
|
878
|
+
headers: i
|
|
879
|
+
});
|
|
880
|
+
} catch (u) {
|
|
881
|
+
const p = u;
|
|
882
|
+
if (p != null && p.response)
|
|
883
|
+
return p.response;
|
|
884
|
+
throw u;
|
|
885
|
+
}
|
|
879
886
|
} finally {
|
|
880
887
|
s();
|
|
881
888
|
}
|
|
882
889
|
}, I = new WeakSet(), K = function(t) {
|
|
883
|
-
let r = removePathPrefix(t, l(this,
|
|
890
|
+
let r = removePathPrefix(t, l(this, _));
|
|
884
891
|
r = applyRewriteRules(r, this.rewriteRules), r.includes(".php") ? r = r.split(".php")[0] + ".php" : this.php.isDir(`${l(this, m)}${r}`) ? (r.endsWith("/") || (r = `${r}/`), r = `${r}index.php`) : r = "/index.php";
|
|
885
892
|
const s = `${l(this, m)}${r}`;
|
|
886
893
|
if (this.php.fileExists(s))
|
|
@@ -1035,8 +1042,8 @@ function rethrowFileSystemError(e = "") {
|
|
|
1035
1042
|
} catch (a) {
|
|
1036
1043
|
const c = typeof a == "object" ? a == null ? void 0 : a.errno : null;
|
|
1037
1044
|
if (c in FileErrorCodes) {
|
|
1038
|
-
const
|
|
1039
|
-
throw new Error(`${ue}: ${
|
|
1045
|
+
const u = FileErrorCodes[c], p = typeof i[0] == "string" ? i[0] : null, ue = p !== null ? e.replaceAll("{path}", p) : e;
|
|
1046
|
+
throw new Error(`${ue}: ${u}`, {
|
|
1040
1047
|
cause: a
|
|
1041
1048
|
});
|
|
1042
1049
|
}
|
|
@@ -1087,6 +1094,11 @@ var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyD
|
|
|
1087
1094
|
return s && n && __defProp(t, r, n), n;
|
|
1088
1095
|
};
|
|
1089
1096
|
const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
|
|
1097
|
+
class PHPExecutionFailureError extends Error {
|
|
1098
|
+
constructor(t, r, s) {
|
|
1099
|
+
super(t), this.response = r, this.source = s;
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1090
1102
|
var S, T, C, y, w, g, P, A, N, Z, L, X, q, ee, O, te, M, re, D, se, $, ne, j, ie, W, oe, z, ae, G, le, V, ce;
|
|
1091
1103
|
class BasePHP {
|
|
1092
1104
|
/**
|
|
@@ -1097,26 +1109,26 @@ class BasePHP {
|
|
|
1097
1109
|
* @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
|
|
1098
1110
|
*/
|
|
1099
1111
|
constructor(e, t) {
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1112
|
+
d(this, N);
|
|
1113
|
+
d(this, L);
|
|
1114
|
+
d(this, q);
|
|
1115
|
+
d(this, O);
|
|
1116
|
+
d(this, M);
|
|
1117
|
+
d(this, D);
|
|
1118
|
+
d(this, $);
|
|
1119
|
+
d(this, j);
|
|
1120
|
+
d(this, W);
|
|
1121
|
+
d(this, z);
|
|
1122
|
+
d(this, G);
|
|
1123
|
+
d(this, V);
|
|
1124
|
+
d(this, S, void 0);
|
|
1125
|
+
d(this, T, void 0);
|
|
1126
|
+
d(this, C, void 0);
|
|
1127
|
+
d(this, y, void 0);
|
|
1128
|
+
d(this, w, void 0);
|
|
1129
|
+
d(this, g, void 0);
|
|
1130
|
+
d(this, P, void 0);
|
|
1131
|
+
d(this, A, void 0);
|
|
1120
1132
|
h(this, S, []), h(this, y, !1), h(this, w, null), h(this, g, {}), h(this, P, /* @__PURE__ */ new Map()), h(this, A, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new PHPBrowser(
|
|
1121
1133
|
new PHPRequestHandler(this, t)
|
|
1122
1134
|
));
|
|
@@ -1235,10 +1247,12 @@ class BasePHP {
|
|
|
1235
1247
|
const i = await f(this, V, ce).call(this);
|
|
1236
1248
|
if (i.exitCode !== 0) {
|
|
1237
1249
|
console.warn("PHP.run() output was:", i.text);
|
|
1238
|
-
const a = new
|
|
1239
|
-
`PHP.run() failed with exit code ${i.exitCode} and the following output: ` + i.errors
|
|
1250
|
+
const a = new PHPExecutionFailureError(
|
|
1251
|
+
`PHP.run() failed with exit code ${i.exitCode} and the following output: ` + i.errors,
|
|
1252
|
+
i,
|
|
1253
|
+
"request"
|
|
1240
1254
|
);
|
|
1241
|
-
throw
|
|
1255
|
+
throw console.error(a), a;
|
|
1242
1256
|
}
|
|
1243
1257
|
return i;
|
|
1244
1258
|
} catch (s) {
|
|
@@ -1535,10 +1549,10 @@ S = new WeakMap(), T = new WeakMap(), C = new WeakMap(), y = new WeakMap(), w =
|
|
|
1535
1549
|
try {
|
|
1536
1550
|
e = await new Promise((o, i) => {
|
|
1537
1551
|
var c;
|
|
1538
|
-
t = (
|
|
1539
|
-
console.error(
|
|
1540
|
-
const
|
|
1541
|
-
|
|
1552
|
+
t = (u) => {
|
|
1553
|
+
console.error(u), console.error(u.error);
|
|
1554
|
+
const p = new Error("Rethrown");
|
|
1555
|
+
p.cause = u.error, p.betterMessage = u.message, i(p);
|
|
1542
1556
|
}, (c = l(this, w)) == null || c.addEventListener(
|
|
1543
1557
|
"error",
|
|
1544
1558
|
t
|
|
@@ -1553,8 +1567,8 @@ S = new WeakMap(), T = new WeakMap(), C = new WeakMap(), y = new WeakMap(), w =
|
|
|
1553
1567
|
return a instanceof Promise ? a.then(o, i) : o(a);
|
|
1554
1568
|
});
|
|
1555
1569
|
} catch (o) {
|
|
1556
|
-
for (const
|
|
1557
|
-
typeof this[
|
|
1570
|
+
for (const u in this)
|
|
1571
|
+
typeof this[u] == "function" && (this[u] = () => {
|
|
1558
1572
|
throw new Error(
|
|
1559
1573
|
"PHP runtime has crashed – see the earlier error for details."
|
|
1560
1574
|
);
|
|
@@ -1567,7 +1581,7 @@ S = new WeakMap(), T = new WeakMap(), C = new WeakMap(), y = new WeakMap(), w =
|
|
|
1567
1581
|
}
|
|
1568
1582
|
const { headers: r, httpStatusCode: s } = f(this, L, X).call(this);
|
|
1569
1583
|
return new PHPResponse(
|
|
1570
|
-
s,
|
|
1584
|
+
e === 0 ? s : 500,
|
|
1571
1585
|
r,
|
|
1572
1586
|
this.readFileAsBuffer("/internal/stdout"),
|
|
1573
1587
|
this.readFileAsText("/internal/stderr"),
|
package/lib/base-php.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ import type { PHPRuntimeId } from './load-php-runtime';
|
|
|
5
5
|
import { IsomorphicLocalPHP, MessageListener, PHPRequest, PHPRequestHeaders, PHPRunOptions, RmDirOptions, ListFilesOptions, SpawnHandler, PHPEventListener, PHPEvent } from './universal-php';
|
|
6
6
|
import { Semaphore } from '../../../util/src/index.ts';
|
|
7
7
|
export declare const __private__dont__use: unique symbol;
|
|
8
|
+
export declare class PHPExecutionFailureError extends Error {
|
|
9
|
+
response: PHPResponse;
|
|
10
|
+
source: 'request' | 'php-wasm';
|
|
11
|
+
constructor(message: string, response: PHPResponse, source: 'request' | 'php-wasm');
|
|
12
|
+
}
|
|
8
13
|
/**
|
|
9
14
|
* An environment-agnostic wrapper around the Emscripten PHP runtime
|
|
10
15
|
* that universals the super low-level API and provides a more convenient
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@php-wasm/universal",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.16",
|
|
4
4
|
"description": "PHP.wasm – emscripten bindings for PHP",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"main": "./index.cjs",
|
|
37
37
|
"module": "./index.js",
|
|
38
38
|
"license": "GPL-2.0-or-later",
|
|
39
|
-
"gitHead": "
|
|
39
|
+
"gitHead": "1981567e7eacecbc4a18c870267c20bf489afd8f",
|
|
40
40
|
"engines": {
|
|
41
41
|
"node": ">=18.18.0",
|
|
42
42
|
"npm": ">=8.11.0"
|