@php-wasm/util
Advanced tools
| /** | ||
| * Explicitly marks an event whose `stdin` ReadableStream needs an independent | ||
| * branch per listener and must be transferred across worker boundaries. The | ||
| * global symbol registry keeps the marker stable if this package is loaded | ||
| * more than once in the same realm. | ||
| */ | ||
| export declare const phpEventStdinTransfer: unique symbol; | ||
| export type PHPEventWithStdinTransfer = { | ||
| type: string; | ||
| stdin: ReadableStream<Uint8Array>; | ||
| [phpEventStdinTransfer]: true; | ||
| }; |
| import { type PHPEventWithStdinTransfer } from '../php-event'; | ||
| /** | ||
| * Limit captured sendmail stdin to 20 MB to match common email size limits. | ||
| * | ||
| * Gmail limits email attachments to 25 MB https://support.google.com/mail/answer/6584 | ||
| * Outlook limits email attachments to 20 MB https://support.microsoft.com/outlook/reduce-attachment-size-to-send-large-files-with-outlook | ||
| */ | ||
| export declare const SENDMAIL_CAPTURE_MAX_SIZE: number; | ||
| /** | ||
| * Emitted when a sendmail null transport receives the first stdin bytes from | ||
| * `mail()`, `popen()`, `proc_open()`, or any other spawn of a `sendmail` binary. | ||
| */ | ||
| export interface PHPSendmailSpawnedEvent extends PHPEventWithStdinTransfer { | ||
| type: 'sendmail.spawned'; | ||
| } | ||
| /** | ||
| * Creates a sendmail-compatible null transport for the given PHP instance. | ||
| * Every message handed to sendmail – via mail(), proc_open(), etc. – is streamed | ||
| * from stdin, dispatched as a `sendmail.spawned` event, and never delivered. | ||
| * A listener that wants real delivery must relay the message itself. | ||
| * | ||
| * The captured payload is exposed as the raw bytes written to sendmail stdin. | ||
| * | ||
| * This stream does not apply backpressure to PHP. Each listener queues unread | ||
| * chunks in JavaScript memory when it reads more slowly than PHP writes. The | ||
| * source accepts at most SENDMAIL_CAPTURE_MAX_SIZE bytes. Cancelling the stream | ||
| * stops delivery through that stream without terminating the sendmail process. | ||
| */ | ||
| export declare function sendmailSpawnHandler(php: { | ||
| dispatchEvent: (event: PHPSendmailSpawnedEvent) => void; | ||
| }): any; |
+3
-1
@@ -1,2 +0,4 @@ | ||
| "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=Symbol("SleepFinished");function P(i){return new Promise(e=>{setTimeout(()=>e(d),i)})}class g extends Error{constructor(){super("Acquiring lock timed out")}}class E{constructor({concurrency:e,timeout:t}){this._running=0,this.concurrency=e,this.timeout=t,this.queue=[]}get remaining(){return this.concurrency-this.running}get running(){return this._running}async acquire(){if(this._running>=this.concurrency){const t=new Promise(r=>{this.queue.push(r)});if(this.timeout!==void 0){const r=this.queue.at(-1);if(await Promise.race([t,P(this.timeout)])===d)throw this.queue.splice(this.queue.indexOf(r),1),new g}else await t}this._running++;let e=!1;return()=>{e||(e=!0,this._running--,this.queue.length>0&&this.queue.shift()())}}async run(e){const t=await this.acquire();try{return await e()}finally{t()}}}class S extends Error{constructor(e,t){super(e),this.userFriendlyMessage=t??e}}function p(...i){function e(o){return o.substring(o.length-1)==="/"}let t=i.join("/");const r=t[0]==="/",s=e(t);return t=f(t),!t&&!r&&(t="."),t&&s&&!e(t)&&(t+="/"),t}function x(i){if(i==="/")return"/";i=f(i);const e=i.lastIndexOf("/");return e===-1?"":e===0?"/":i.substr(0,e)}function T(i){if(i==="/")return"/";i=f(i);const e=i.lastIndexOf("/");return e===-1?i:i.substr(e+1)}function f(i){const e=i[0]==="/";return i=_(i.split("/").filter(t=>!!t),!e).join("/"),(e?"/":"")+i.replace(/\/$/,"")}function _(i,e){let t=0;for(let r=i.length-1;r>=0;r--){const s=i[r];s==="."?i.splice(r,1):s===".."?(i.splice(r,1),t++):t&&(i.splice(r,1),t--)}if(e)for(;t;t--)i.unshift("..");return i}function A(i,e){return i==="/"?!0:(i=f(i),e=f(e),e.startsWith(i+"/")||e===i)}function M(i){return p("/",f(i||"/"))}function O(i){let e=i.replaceAll("\\","/");const t=e.match(/^([A-Za-z]):\//);return t&&(e="/"+t[1]+e.slice(2)),e}class c{constructor(){this.listeners={}}emit(e,t){this.listeners[e]&&this.listeners[e].forEach(function(r){r(t)})}on(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(t)}once(e,t){const r=(...s)=>{this.off(e,r),t(...s)};this.on(e,r)}off(e,t){this.listeners[e]&&(this.listeners[e]=this.listeners[e].filter(r=>r!==t))}}function w(i){let r=0,s="";const o=[];let n="";for(let l=0;l<i.length;l++){const u=i[l];u==="\\"?((i[l+1]==='"'||i[l+1]==="'")&&l++,n+=i[l]):r===0?u==='"'||u==="'"?(r=1,s=u):u.match(/\s/)?(n.trim().length&&o.push(n.trim()),n=u):o.length&&!n?n=o.pop()+u:n+=u:r===1&&(u===s?(r=0,s=""):n+=u)}return n&&o.push(n.trim()),o}class h extends c{constructor(e){if(super(),this.buffer=[],this.writing=!1,this.ended=!1,this.length=0,!e.write)throw new Error("WritablePolyfill requires write option");this._write=e.write,this.highWaterMark=e.highWaterMark??16*1024,this.decodeStrings=e.decodeStrings??!0,this.defaultEncoding=e.defaultEncoding??"utf8",this.defer=typeof queueMicrotask=="function"?queueMicrotask:t=>setTimeout(t,0)}write(e,t=this.defaultEncoding,r=()=>{}){if(typeof t=="function"&&(r=t,t=this.defaultEncoding),this.ended){const o=new Error("write after end"),n=this.defer;return n(()=>r(o)),this.emit("error",o),!1}if(this.decodeStrings&&typeof e=="string"){if(typeof Buffer<"u"&&typeof Buffer.from=="function")e=Buffer.from(e,t);else if(typeof TextEncoder<"u")e=new TextEncoder().encode(e);else throw new Error("String chunks are not supported in this environment: Buffer and TextEncoder are unavailable.");t="buffer"}this.length+=e.length??1;const s=this.length>=this.highWaterMark;return this.buffer.push({chunk:e,encoding:t,cb:r}),this.writing||this._clearBuffer(),!s}end(e,t,r){typeof e=="function"?(r=e,e=void 0):typeof t=="function"&&(r=t,t=void 0),e!==void 0&&this.write(e,t,()=>{}),this.ended=!0,this.writing||this._clearBuffer(),r&&this.defer(r)}cork(){}uncork(){}setDefaultEncoding(e){return this.defaultEncoding=e,this}_clearBuffer(){const e=this.buffer.shift();if(!e){this.ended&&this.emit("finish");return}this.writing=!0,this._write(e.chunk,e.encoding,t=>{this.writing=!1,this.length-=e.chunk.length??1,t&&this.emit("error",t),e.cb(t),this.buffer.length?this._clearBuffer():(this.length<this.highWaterMark&&this.emit("drain"),this.ended&&this.emit("finish"))})}}function B(i){return function(e,t=[],r={}){const s=new U,o=new k(s);return setTimeout(async()=>{let n=[];if(t.length)n=[e,...t];else if(typeof e=="string")n=w(e);else if(Array.isArray(e))n=e;else throw new Error("Invalid command ",e);try{const l=i(n,o,r);if(typeof l!="object"||l===null||!("then"in l))throw new Error(`The program callback passed to createSpawnHandler() did not return a promise. It indicates there's a bug in your code. The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() call. All the streams would be closed already. Make sure to put an "await new Promise(resolve => setTimeout(resolve, 1))before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`);if(o.exited)throw new Error(`The program callback passed to createSpawnHandler() exited synchronously. It indicates there's a bug in your code. The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() call. All the streams would be closed already. Make sure to put an "await new Promise(resolve => setTimeout(resolve, 1))before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`);s.emit("spawn",!0),await l}catch(l){s.emit("error",l),typeof l=="object"&&l!==null&&"message"in l&&typeof l.message=="string"&&o.stderr(l.message),o.exit(1)}}),s}}class k extends c{constructor(e){super(),this.exited=!1,this.stdinBuffer=[],this.childProcess=e,e.on("stdin",t=>{this.stdinBuffer?this.stdinBuffer.push(t.slice()):this.emit("stdin",t)})}stdinEnd(){this.childProcess.stdin.ended||this.childProcess.stdin.end()}stdout(e){this.childProcess.stdout.write(e)}stdoutEnd(){this.childProcess.stdout.ended||this.childProcess.stdout.end()}stderr(e){this.childProcess.stderr.write(e)}stderrEnd(){this.childProcess.stderr.ended||this.childProcess.stderr.end()}notifySpawn(){this.childProcess.emit("spawn",!0)}exit(e){this.exited||(this.exited=!0,this.stdinEnd(),this.stdoutEnd(),this.stderrEnd(),this.childProcess.emit("exit",e))}on(e,t){if(super.on(e,t),e==="stdin"&&this.stdinBuffer){for(let r=0;r<this.stdinBuffer.length;r++)this.emit("stdin",this.stdinBuffer[r]);this.stdinBuffer=null}}}let q=9743;class U extends c{constructor(e=q++){super(),this.pid=e;const t=this;this.stdout=new h({write(r,s,o){t.stdout.emit("data",r),o()}}),this.stderr=new h({write:(r,s,o)=>{t.stderr.emit("data",r),o()}}),this.stdin=new h({write:(r,s,o)=>{t.emit("stdin",r),o()}})}}function y(i=36,e="!@#$%^&*()_+=-[]/.,<>?"){const t="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"+e;let r="";for(let s=i;s>0;--s)r+=t[Math.floor(Math.random()*t.length)];return r}function D(){return y(36,"-_")}function m(i){return`json_decode(base64_decode('${j(JSON.stringify(i))}'), true)`}function W(i){const e={};for(const t in i)e[t]=m(i[t]);return e}function j(i){return I(new TextEncoder().encode(i))}function I(i){const e=String.fromCodePoint(...i);return btoa(e)}function H(i,...e){let t="",r=0;for(let s=0;s<i.length;s++)if(i[s]==="%"&&s+1<i.length){s++;const o=i[s];switch(o){case"s":{const n=e[r++];let l;if(typeof n=="object")try{l=JSON.stringify(n,(u,a)=>typeof a=="bigint"?`0x${a.toString(16)}`:a,2)}catch{}else l=String(n);t+=l;break}case"d":{const n=e[r++];typeof n=="bigint"?t+=n.toString():t+=Math.floor(Number(n));break}case"f":{const n=e[r++];t+=Number(n);break}case"x":{const n=e[r++];typeof n=="bigint"?t+=n.toString(16):t+=Math.floor(Number(n)).toString(16);break}case"%":{t+="%";break}default:t+="%"+o}}else t+=i[s];return t}function b(i){let e=0;i.forEach(s=>e+=s.length);const t=new Uint8Array(e);let r=0;return i.forEach(s=>{t.set(s,r),r+=s.length}),t}function Q(i){return b(i.map(e=>new Uint8Array(e))).buffer}exports.AcquireTimeoutError=g;exports.EventEmitterPolyfill=c;exports.PhpWasmError=S;exports.Semaphore=E;exports.WritablePolyfill=h;exports.basename=T;exports.concatArrayBuffers=Q;exports.concatUint8Arrays=b;exports.createSpawnHandler=B;exports.dirname=x;exports.ensureAbsolutePath=M;exports.isParentOf=A;exports.joinPaths=p;exports.normalizePath=f;exports.phpVar=m;exports.phpVars=W;exports.randomFilename=D;exports.randomString=y;exports.splitShellCommand=w;exports.sprintf=H;exports.toPosixPath=O; | ||
| "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=Symbol("SleepFinished");function M(i){return new Promise(e=>{setTimeout(()=>e(w),i)})}class p extends Error{constructor(){super("Acquiring lock timed out")}}class A{constructor({concurrency:e,timeout:t}){this._running=0,this.concurrency=e,this.timeout=t,this.queue=[]}get remaining(){return this.concurrency-this.running}get running(){return this._running}async acquire(){if(this._running>=this.concurrency){const t=new Promise(r=>{this.queue.push(r)});if(this.timeout!==void 0){const r=this.queue.at(-1);if(await Promise.race([t,M(this.timeout)])===w)throw this.queue.splice(this.queue.indexOf(r),1),new p}else await t}this._running++;let e=!1;return()=>{e||(e=!0,this._running--,this.queue.length>0&&this.queue.shift()())}}async run(e){const t=await this.acquire();try{return await e()}finally{t()}}}class O extends Error{constructor(e,t){super(e),this.userFriendlyMessage=t??e}}function m(...i){function e(o){return o.substring(o.length-1)==="/"}let t=i.join("/");const r=t[0]==="/",s=e(t);return t=f(t),!t&&!r&&(t="."),t&&s&&!e(t)&&(t+="/"),t}function B(i,e){if(i.includes("\0")||e.includes("\0"))return;const t=f(e);if(!t)return;const r=f(i.startsWith("/")?i:m(t,i));if(!(r===t||!y(t,r)))return r}function U(i){if(i==="/")return"/";i=f(i);const e=i.lastIndexOf("/");return e===-1?"":e===0?"/":i.substr(0,e)}function q(i){if(i==="/")return"/";i=f(i);const e=i.lastIndexOf("/");return e===-1?i:i.substr(e+1)}function f(i){const e=i[0]==="/";return i=k(i.split("/").filter(t=>!!t),!e).join("/"),(e?"/":"")+i.replace(/\/$/,"")}function k(i,e){let t=0;for(let r=i.length-1;r>=0;r--){const s=i[r];s==="."?i.splice(r,1):s===".."?(i.splice(r,1),t++):t&&(i.splice(r,1),t--)}if(e)for(;t;t--)i.unshift("..");return i}function y(i,e){return i==="/"?!0:(i=f(i),e=f(e),e.startsWith(i+"/")||e===i)}function v(i){return m("/",f(i||"/"))}function D(i){let e=i.replaceAll("\\","/");const t=e.match(/^([A-Za-z]):\//);return t&&(e="/"+t[1]+e.slice(2)),e}class g{constructor(){this.listeners={}}emit(e,t){this.listeners[e]&&this.listeners[e].forEach(function(r){r(t)})}on(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(t)}once(e,t){const r=(...s)=>{this.off(e,r),t(...s)};this.on(e,r)}off(e,t){this.listeners[e]&&(this.listeners[e]=this.listeners[e].filter(r=>r!==t))}}function E(i){let r=0,s="";const o=[];let n="";for(let l=0;l<i.length;l++){const a=i[l];a==="\\"?((i[l+1]==='"'||i[l+1]==="'")&&l++,n+=i[l]):r===0?a==='"'||a==="'"?(r=1,s=a):a.match(/\s/)?(n.trim().length&&o.push(n.trim()),n=a):o.length&&!n?n=o.pop()+a:n+=a:r===1&&(a===s?(r=0,s=""):n+=a)}return n&&o.push(n.trim()),o}class h extends g{constructor(e){if(super(),this.buffer=[],this.writing=!1,this.ended=!1,this.length=0,!e.write)throw new Error("WritablePolyfill requires write option");this._write=e.write,this.highWaterMark=e.highWaterMark??16*1024,this.decodeStrings=e.decodeStrings??!0,this.defaultEncoding=e.defaultEncoding??"utf8",this.defer=typeof queueMicrotask=="function"?queueMicrotask:t=>setTimeout(t,0)}write(e,t=this.defaultEncoding,r=()=>{}){if(typeof t=="function"&&(r=t,t=this.defaultEncoding),this.ended){const o=new Error("write after end"),n=this.defer;return n(()=>r(o)),this.emit("error",o),!1}if(this.decodeStrings&&typeof e=="string"){if(typeof Buffer<"u"&&typeof Buffer.from=="function")e=Buffer.from(e,t);else if(typeof TextEncoder<"u")e=new TextEncoder().encode(e);else throw new Error("String chunks are not supported in this environment: Buffer and TextEncoder are unavailable.");t="buffer"}this.length+=e.length??1;const s=this.length>=this.highWaterMark;return this.buffer.push({chunk:e,encoding:t,cb:r}),this.writing||this._clearBuffer(),!s}end(e,t,r){typeof e=="function"?(r=e,e=void 0):typeof t=="function"&&(r=t,t=void 0),e!==void 0&&this.write(e,t,()=>{}),this.ended=!0,this.writing||this._clearBuffer(),r&&this.defer(r)}cork(){}uncork(){}setDefaultEncoding(e){return this.defaultEncoding=e,this}_clearBuffer(){const e=this.buffer.shift();if(!e){this.ended&&this.emit("finish");return}this.writing=!0,this._write(e.chunk,e.encoding,t=>{this.writing=!1,this.length-=e.chunk.length??1,t&&this.emit("error",t),e.cb(t),this.buffer.length?this._clearBuffer():(this.length<this.highWaterMark&&this.emit("drain"),this.ended&&this.emit("finish"))})}}function P(i){return function(e,t=[],r={}){const s=new z,o=new I(s);return setTimeout(async()=>{let n=[];if(t.length)n=[e,...t];else if(typeof e=="string")n=E(e);else if(Array.isArray(e))n=e;else throw new Error("Invalid command ",e);try{const l=i(n,o,r);if(typeof l!="object"||l===null||!("then"in l))throw new Error(`The program callback passed to createSpawnHandler() did not return a promise. It indicates there's a bug in your code. The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() call. All the streams would be closed already. Make sure to put an "await new Promise(resolve => setTimeout(resolve, 1))before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`);if(o.exited)throw new Error(`The program callback passed to createSpawnHandler() exited synchronously. It indicates there's a bug in your code. The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() call. All the streams would be closed already. Make sure to put an "await new Promise(resolve => setTimeout(resolve, 1))before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`);s.emit("spawn",!0),await l}catch(l){s.emit("error",l),typeof l=="object"&&l!==null&&"message"in l&&typeof l.message=="string"&&o.stderr(l.message),o.exit(1)}}),s}}class I extends g{constructor(e){super(),this.exited=!1,this.stdinBuffer=[],this.childProcess=e,e.on("stdin",t=>{this.stdinBuffer?this.stdinBuffer.push(t.slice()):this.emit("stdin",t)})}stdinEnd(){this.childProcess.stdin.ended||this.childProcess.stdin.end()}stdout(e){this.childProcess.stdout.write(e)}stdoutEnd(){this.childProcess.stdout.ended||this.childProcess.stdout.end()}stderr(e){this.childProcess.stderr.write(e)}stderrEnd(){this.childProcess.stderr.ended||this.childProcess.stderr.end()}notifySpawn(){this.childProcess.emit("spawn",!0)}exit(e){this.exited||(this.exited=!0,this.stdinEnd(),this.stdoutEnd(),this.stderrEnd(),this.childProcess.emit("exit",e))}on(e,t){if(super.on(e,t),e==="stdin"&&this.stdinBuffer){for(let r=0;r<this.stdinBuffer.length;r++)this.emit("stdin",this.stdinBuffer[r]);this.stdinBuffer=null}}}let W=9743;class z extends g{constructor(e=W++){super(),this.pid=e;const t=this;this.stdout=new h({write(r,s,o){t.stdout.emit("data",r),o()}}),this.stderr=new h({write:(r,s,o)=>{t.stderr.emit("data",r),o()}}),this.stdin=new h({write:(r,s,o)=>{t.emit("stdin",r),o()}})}}const b=Symbol.for("@php-wasm/php-event-stdin-transfer"),d=20*1024*1024;function H(i){return P(async function(e,t){let r=0,s=!1,o=!1,n=!1,l;const a=new ReadableStream({start(c){l=c},cancel(){n=!0}});t.on("stdin",c=>{if(s||(s=!0,i.dispatchEvent({type:"sendmail.spawned",stdin:a,[b]:!0})),r+=c.length,r>d){o=!0;try{l.error(new Error(`sendmail: Message size exceeds fixed maximum message size (${d})`))}catch{}return}n||l.enqueue(c.slice())});const u=t.childProcess.stdin;if(u.ended||u.writableEnded||u.writableFinished||await new Promise(c=>{if(u.ended||u.writableEnded||u.writableFinished){c();return}const T=()=>{c()};u.once("finish",T)}),o){t.stderr(`sendmail: Message size exceeds fixed maximum message size (${d}) | ||
| `),t.exit(1);return}if(r===0){t.stderr(`sendmail: fatal: No message bytes received over stdin | ||
| `),t.exit(75);return}try{l.close()}catch{}t.exit(0)})}function S(i=36,e="!@#$%^&*()_+=-[]/.,<>?"){const t="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"+e;let r="";for(let s=i;s>0;--s)r+=t[Math.floor(Math.random()*t.length)];return r}function j(){return S(36,"-_")}function x(i){return`json_decode(base64_decode('${C(JSON.stringify(i))}'), true)`}function N(i){const e={};for(const t in i)e[t]=x(i[t]);return e}function C(i){return F(new TextEncoder().encode(i))}function F(i){const e=String.fromCodePoint(...i);return btoa(e)}function Q(i,...e){let t="",r=0;for(let s=0;s<i.length;s++)if(i[s]==="%"&&s+1<i.length){s++;const o=i[s];switch(o){case"s":{const n=e[r++];let l;if(typeof n=="object")try{l=JSON.stringify(n,(a,u)=>typeof u=="bigint"?`0x${u.toString(16)}`:u,2)}catch{}else l=String(n);t+=l;break}case"d":{const n=e[r++];typeof n=="bigint"?t+=n.toString():t+=Math.floor(Number(n));break}case"f":{const n=e[r++];t+=Number(n);break}case"x":{const n=e[r++];typeof n=="bigint"?t+=n.toString(16):t+=Math.floor(Number(n)).toString(16);break}case"%":{t+="%";break}default:t+="%"+o}}else t+=i[s];return t}function _(i){let e=0;i.forEach(s=>e+=s.length);const t=new Uint8Array(e);let r=0;return i.forEach(s=>{t.set(s,r),r+=s.length}),t}function L(i){return _(i.map(e=>new Uint8Array(e))).buffer}exports.AcquireTimeoutError=p;exports.EventEmitterPolyfill=g;exports.PhpWasmError=O;exports.SENDMAIL_CAPTURE_MAX_SIZE=d;exports.Semaphore=A;exports.WritablePolyfill=h;exports.basename=q;exports.concatArrayBuffers=L;exports.concatUint8Arrays=_;exports.createSpawnHandler=P;exports.dirname=U;exports.ensureAbsolutePath=v;exports.isParentOf=y;exports.joinPaths=m;exports.normalizePath=f;exports.phpEventStdinTransfer=b;exports.phpVar=x;exports.phpVars=N;exports.randomFilename=j;exports.randomString=S;exports.resolvePathUnder=B;exports.sendmailSpawnHandler=H;exports.splitShellCommand=E;exports.sprintf=Q;exports.toPosixPath=D; | ||
| //# sourceMappingURL=index.cjs.map |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.cjs","sources":["../../../../packages/php-wasm/util/src/lib/sleep.ts","../../../../packages/php-wasm/util/src/lib/semaphore.ts","../../../../packages/php-wasm/util/src/lib/php-wasm-error.ts","../../../../packages/php-wasm/util/src/lib/paths.ts","../../../../packages/php-wasm/util/src/lib/event-emitter-polyfill.ts","../../../../packages/php-wasm/util/src/lib/split-shell-command.ts","../../../../packages/php-wasm/util/src/lib/writable-polyfill.ts","../../../../packages/php-wasm/util/src/lib/create-spawn-handler.ts","../../../../packages/php-wasm/util/src/lib/random-string.ts","../../../../packages/php-wasm/util/src/lib/random-filename.ts","../../../../packages/php-wasm/util/src/lib/php-vars.ts","../../../../packages/php-wasm/util/src/lib/sprintf.ts","../../../../packages/php-wasm/util/src/lib/index.ts"],"sourcesContent":["export const SleepFinished = Symbol('SleepFinished');\n\nexport function sleep(ms: number): Promise<typeof SleepFinished> {\n\treturn new Promise((resolve) => {\n\t\tsetTimeout(() => resolve(SleepFinished), ms);\n\t});\n}\n","import { SleepFinished, sleep } from './sleep';\n\nexport interface SemaphoreOptions {\n\t/**\n\t * The maximum number of concurrent locks.\n\t */\n\tconcurrency: number;\n\t/**\n\t * The maximum time to wait for a lock to become available.\n\t */\n\ttimeout?: number;\n}\n\nexport class AcquireTimeoutError extends Error {\n\tconstructor() {\n\t\tsuper('Acquiring lock timed out');\n\t}\n}\n\nexport default class Semaphore {\n\tprivate _running = 0;\n\tprivate concurrency: number;\n\tprivate timeout?: number;\n\tprivate queue: (() => void)[];\n\n\tconstructor({ concurrency, timeout }: SemaphoreOptions) {\n\t\tthis.concurrency = concurrency;\n\t\tthis.timeout = timeout;\n\t\tthis.queue = [];\n\t}\n\n\tget remaining(): number {\n\t\treturn this.concurrency - this.running;\n\t}\n\n\tget running(): number {\n\t\treturn this._running;\n\t}\n\n\tasync acquire(): Promise<() => void> {\n\t\t// Concurrency exhausted - wait in queue for other workers to finish:\n\t\tif (this._running >= this.concurrency) {\n\t\t\t// Create a promise and store its resolver in the queue.\n\t\t\tconst acquired = new Promise<void>((resolve) => {\n\t\t\t\tthis.queue.push(resolve);\n\t\t\t});\n\n\t\t\t// Wait until it is resolved by another worker or a timeout occurs.\n\t\t\tif (this.timeout !== undefined) {\n\t\t\t\t// Store the resolver for cleanup in case of timeout.\n\t\t\t\tconst resolve = this.queue.at(-1)!;\n\t\t\t\tconst result = await Promise.race([\n\t\t\t\t\tacquired,\n\t\t\t\t\tsleep(this.timeout),\n\t\t\t\t]);\n\t\t\t\tif (result === SleepFinished) {\n\t\t\t\t\t// Remove the resolver for the timed out worker from the queue.\n\t\t\t\t\tthis.queue.splice(this.queue.indexOf(resolve), 1);\n\t\t\t\t\tthrow new AcquireTimeoutError();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait acquired;\n\t\t\t}\n\t\t}\n\n\t\t// Acquire the lock:\n\t\tthis._running++;\n\t\tlet released = false;\n\n\t\t// Return a release function:\n\t\treturn () => {\n\t\t\tif (released) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treleased = true;\n\t\t\tthis._running--;\n\n\t\t\t// Release the first item in the queue (call its resolver):\n\t\t\tif (this.queue.length > 0) {\n\t\t\t\tthis.queue.shift()!();\n\t\t\t}\n\t\t};\n\t}\n\n\tasync run<T>(fn: () => T | Promise<T>): Promise<T> {\n\t\tconst release = await this.acquire();\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\trelease();\n\t\t}\n\t}\n}\n","export class PhpWasmError extends Error {\n\tuserFriendlyMessage?: string;\n\tconstructor(message: string, userFriendlyMessage?: string) {\n\t\tsuper(message);\n\t\tthis.userFriendlyMessage = userFriendlyMessage ?? message;\n\t}\n}\n","/**\n * The functions in this module are mostly copied from the generated\n * Emscripten PHP module. This enables features like filesystem journaling,\n * which use some low-level Emscripten APIs and need access to the\n * same path helpers.\n */\n\n/**\n * Joins paths together.\n *\n * For example:\n *\n * > joinPaths('wordpress', 'wp-content')\n * 'wordpress/wp-content'\n *\n * Use this for all PHP paths and **do not** use path.join().\n * This is important because Emscripten paths are **always**\n * POSIX-style paths. Imagine joining paths on Windows:\n *\n * > path.join('wordpress', 'wp-content')\n * '\\\\wordpress\\\\wp-content' // invalid in PHP.wasm\n *\n * See the path.join issue for more details:\n *\n * https://github.com/WordPress/playground-tools/issues/11#issuecomment-1579074763\n *\n * @param paths Paths segments to join\n * @returns A joined path\n */\nexport function joinPaths(...paths: string[]) {\n\tfunction hasTrailingSlash(p: string) {\n\t\treturn p.substring(p.length - 1) === '/';\n\t}\n\n\tlet path = paths.join('/');\n\tconst isAbsolute = path[0] === '/';\n\tconst trailingSlash = hasTrailingSlash(path);\n\tpath = normalizePath(path);\n\tif (!path && !isAbsolute) {\n\t\tpath = '.';\n\t}\n\tif (path && trailingSlash && !hasTrailingSlash(path)) {\n\t\tpath += '/';\n\t}\n\treturn path;\n}\n\n/**\n * Returns the directory name of a path.\n *\n * @param path\n * @returns\n */\nexport function dirname(path: string) {\n\tif (path === '/') {\n\t\treturn '/';\n\t}\n\n\tpath = normalizePath(path);\n\n\tconst lastSlash = path.lastIndexOf('/');\n\tif (lastSlash === -1) {\n\t\treturn '';\n\t} else if (lastSlash === 0) {\n\t\treturn '/';\n\t}\n\treturn path.substr(0, lastSlash);\n}\n\n/**\n * Returns the last portion of a path.\n *\n * @param path - The path to extract the basename from.\n * @returns The basename of the path.\n */\nexport function basename(path: string) {\n\tif (path === '/') {\n\t\treturn '/';\n\t}\n\n\tpath = normalizePath(path);\n\n\tconst lastSlash = path.lastIndexOf('/');\n\tif (lastSlash === -1) {\n\t\treturn path;\n\t}\n\treturn path.substr(lastSlash + 1);\n}\n\n/**\n * Normalizes a path.\n *\n * For example:\n *\n * > normalizePath('wordpress/wp-content/../')\n * 'wordpress'\n *\n * @param path\n * @returns\n */\nexport function normalizePath(path: string) {\n\tconst isAbsolute = path[0] === '/';\n\tpath = normalizePathsArray(\n\t\tpath.split('/').filter((p: any) => !!p),\n\t\t!isAbsolute\n\t).join('/');\n\treturn (isAbsolute ? '/' : '') + path.replace(/\\/$/, '');\n}\n\n/**\n * Normalizes paths.\n *\n * For example:\n *\n * > normalizePathsArray(['wordpress', 'wp-content', '..', '', '.',\n * 'wp-includes']) ['wordpress', 'wp-includes']\n *\n * @param parts parts of the path to normalize\n * @param allowAboveRoot allow paths above the root\n * @returns normalized paths\n */\nexport function normalizePathsArray(parts: string[], allowAboveRoot: boolean) {\n\tlet up = 0;\n\tfor (let i = parts.length - 1; i >= 0; i--) {\n\t\tconst last = parts[i];\n\t\tif (last === '.') {\n\t\t\tparts.splice(i, 1);\n\t\t} else if (last === '..') {\n\t\t\tparts.splice(i, 1);\n\t\t\tup++;\n\t\t} else if (up) {\n\t\t\tparts.splice(i, 1);\n\t\t\tup--;\n\t\t}\n\t}\n\tif (allowAboveRoot) {\n\t\tfor (; up; up--) {\n\t\t\tparts.unshift('..');\n\t\t}\n\t}\n\treturn parts;\n}\n\n/**\n * Checks if the given parent path is an ancestor of the given child path.\n *\n * @param parent The parent path to check.\n * @param child The child path to verify against the parent.\n * @returns Whether the `parent` path is an ancestor of the `child` path.\n */\nexport function isParentOf(parent: string, child: string) {\n\tif (parent === '/') {\n\t\treturn true;\n\t}\n\tparent = normalizePath(parent);\n\tchild = normalizePath(child);\n\treturn child.startsWith(parent + '/') || child === parent;\n}\n\n/**\n * Guarantees a path is absolute by prepending `/` if needed.\n *\n * Useful when working with user-provided paths that might be relative,\n * or when you need to normalize edge cases like empty strings.\n *\n * For example:\n *\n * > ensureAbsolutePath('wp-content/uploads')\n * '/wp-content/uploads'\n *\n * > ensureAbsolutePath('/already/absolute')\n * '/already/absolute'\n *\n * > ensureAbsolutePath('')\n * '/'\n *\n * @param path - The path to make absolute.\n * @returns An absolute, normalized path starting with `/`.\n */\nexport function ensureAbsolutePath(path: string) {\n\treturn joinPaths('/', normalizePath(path || '/'));\n}\n\n/**\n * Converts a native OS path to a POSIX-style path.\n *\n * Transformations:\n * 1. Backslashes → forward slashes\n * 2. Windows drive letter `C:\\` → `/C/` (colons are invalid in\n * Emscripten VFS paths and cause ENOTDIR errno 28)\n *\n * On POSIX systems this is effectively a no-op.\n *\n * @see https://github.com/emscripten-core/emscripten/issues/17829\n */\nexport function toPosixPath(nativePath: string): string {\n\tlet result = nativePath.replaceAll('\\\\', '/');\n\t// Handle Windows drive letter: C:/ → /C/\n\tconst driveMatch = result.match(/^([A-Za-z]):\\//);\n\tif (driveMatch) {\n\t\tresult = '/' + driveMatch[1] + result.slice(2);\n\t}\n\treturn result;\n}\n","/**\n * Polyfills Node.js EventEmitter API. The main goal is to enable\n * using a child_process.spawn()-like API in both Node.js and the browser.\n *\n * @see https://nodejs.org/api/events.html#events_class_eventemitter\n */\ntype Listener = (...args: any[]) => any;\n\nexport class EventEmitterPolyfill {\n\tlisteners: Record<string, Listener[]> = {};\n\temit(eventName: string, data?: any) {\n\t\tif (this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName].forEach(function (listener) {\n\t\t\t\tlistener(data);\n\t\t\t});\n\t\t}\n\t}\n\ton(eventName: string, listener: Listener) {\n\t\tif (!this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName] = [];\n\t\t}\n\t\tthis.listeners[eventName].push(listener);\n\t}\n\tonce(eventName: string, listener: Listener) {\n\t\tconst wrappedListener = (...args: any[]) => {\n\t\t\tthis.off(eventName, wrappedListener);\n\t\t\tlistener(...args);\n\t\t};\n\t\tthis.on(eventName, wrappedListener);\n\t}\n\toff(eventName: string, listener: Listener) {\n\t\tif (this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName] = this.listeners[eventName].filter(\n\t\t\t\t(l) => l !== listener\n\t\t\t);\n\t\t}\n\t}\n}\n","/**\n * Naive shell command parser.\n * Ensures that commands like `wp option set blogname \"My blog name\"` are split\n * into `['wp', 'option', 'set', 'blogname', 'My blog name']` instead of\n * `['wp', 'option', 'set', 'blogname', 'My', 'blog', 'name']`.\n *\n * @param command\n * @returns\n */\nexport function splitShellCommand(command: string) {\n\tconst MODE_UNQUOTED = 0;\n\tconst MODE_IN_QUOTE = 1;\n\n\tlet mode = MODE_UNQUOTED;\n\tlet quote = '';\n\n\tconst parts: string[] = [];\n\tlet currentPart = '';\n\tfor (let i = 0; i < command.length; i++) {\n\t\tconst char = command[i];\n\t\tif (char === '\\\\') {\n\t\t\t// Escaped quotes are treated as normal characters\n\t\t\t// This is a very naive approach to escaping, but it's good enough for\n\t\t\t// now. @TODO: Iterate on this later, perhaps using bun shell. @see https://github.com/WordPress/wordpress-playground/issues/1062\n\t\t\tif (command[i + 1] === '\"' || command[i + 1] === \"'\") {\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tcurrentPart += command[i];\n\t\t} else if (mode === MODE_UNQUOTED) {\n\t\t\tif (char === '\"' || char === \"'\") {\n\t\t\t\tmode = MODE_IN_QUOTE;\n\t\t\t\tquote = char;\n\t\t\t} else if (char.match(/\\s/)) {\n\t\t\t\tif (currentPart.trim().length) {\n\t\t\t\t\tparts.push(currentPart.trim());\n\t\t\t\t}\n\t\t\t\tcurrentPart = char;\n\t\t\t} else if (parts.length && !currentPart) {\n\t\t\t\t// We just closed a quote to continue the same\n\t\t\t\t// argument with different escaping style, e.g.:\n\t\t\t\t// php -r 'require '\\''vendor/autoload.php'\\''\n\t\t\t\tcurrentPart = parts.pop()! + char;\n\t\t\t} else {\n\t\t\t\tcurrentPart += char;\n\t\t\t}\n\t\t} else if (mode === MODE_IN_QUOTE) {\n\t\t\tif (char === quote) {\n\t\t\t\tmode = MODE_UNQUOTED;\n\t\t\t\tquote = '';\n\t\t\t} else {\n\t\t\t\tcurrentPart += char;\n\t\t\t}\n\t\t}\n\t}\n\tif (currentPart) {\n\t\tparts.push(currentPart.trim());\n\t}\n\treturn parts;\n}\n","/**\n * Polyfills Node.js WritableStream API. The main goal is to enable\n * using a child_process.spawn()-like API in both Node.js and the browser.\n *\n * @see https://nodejs.org/api/stream.html#stream_writable_end_chunk_encoding_callback\n */\nimport { EventEmitterPolyfill } from './event-emitter-polyfill';\n\nexport interface WritableOptions {\n\thighWaterMark?: number;\n\tdecodeStrings?: boolean;\n\tdefaultEncoding?: BufferEncoding;\n\twrite: (chunk: any, encoding: BufferEncoding, cb: WriteCallback) => void;\n}\n\nexport type WriteCallback = (error?: Error | null) => void;\n\nexport class WritablePolyfill extends EventEmitterPolyfill {\n\tprivate buffer: Array<{\n\t\tchunk: any;\n\t\tencoding: BufferEncoding;\n\t\tcb: WriteCallback;\n\t}> = [];\n\tprivate writing = false;\n\tpublic ended = false;\n\tprivate length = 0;\n\tprivate highWaterMark: number;\n\tprivate decodeStrings: boolean;\n\tprivate defaultEncoding: BufferEncoding;\n\tprivate defer: (fn: () => void) => void;\n\tprivate _write: (\n\t\tchunk: any,\n\t\tencoding: BufferEncoding,\n\t\tcb: WriteCallback\n\t) => void;\n\n\tconstructor(opts: WritableOptions) {\n\t\tsuper();\n\t\tif (!opts.write) {\n\t\t\tthrow new Error('WritablePolyfill requires write option');\n\t\t}\n\t\tthis._write = opts.write;\n\t\tthis.highWaterMark = opts.highWaterMark ?? 16 * 1024;\n\t\tthis.decodeStrings = opts.decodeStrings ?? true;\n\t\tthis.defaultEncoding = opts.defaultEncoding ?? 'utf8';\n\t\t// queueMicrotask keeps browser support; fallback for older environments.\n\t\tthis.defer =\n\t\t\ttypeof queueMicrotask === 'function'\n\t\t\t\t? queueMicrotask\n\t\t\t\t: (fn) => setTimeout(fn, 0);\n\t}\n\n\twrite(\n\t\tchunk: any,\n\t\tencoding: BufferEncoding | WriteCallback = this.defaultEncoding,\n\t\tcb: WriteCallback = () => {}\n\t): boolean {\n\t\tif (typeof encoding === 'function') {\n\t\t\tcb = encoding as WriteCallback;\n\t\t\tencoding = this.defaultEncoding;\n\t\t}\n\n\t\tif (this.ended) {\n\t\t\tconst err = new Error('write after end');\n\t\t\t// We can't call this.defer() directly. If this.defer is\n\t\t\t// `queueMicrotask`, a `this.defer()` call will pass the\n\t\t\t// WritablePolyfill instance as `this` argument and cause\n\t\t\t// the browser to throw an error similar to \"Invalid\n\t\t\t// invocation\".\n\t\t\tconst defer = this.defer;\n\t\t\tdefer(() => cb(err));\n\t\t\tthis.emit('error', err);\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this.decodeStrings && typeof chunk === 'string') {\n\t\t\tif (\n\t\t\t\ttypeof Buffer !== 'undefined' &&\n\t\t\t\ttypeof (Buffer as any).from === 'function'\n\t\t\t) {\n\t\t\t\tchunk = Buffer.from(chunk, encoding as BufferEncoding);\n\t\t\t} else if (typeof TextEncoder !== 'undefined') {\n\t\t\t\tchunk = new TextEncoder().encode(chunk);\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'String chunks are not supported in this environment: Buffer and TextEncoder are unavailable.'\n\t\t\t\t);\n\t\t\t}\n\t\t\tencoding = 'buffer' as BufferEncoding;\n\t\t}\n\n\t\tthis.length += chunk.length ?? 1;\n\t\tconst needDrain = this.length >= this.highWaterMark;\n\n\t\tthis.buffer.push({ chunk, encoding: encoding as BufferEncoding, cb });\n\n\t\tif (!this.writing) this._clearBuffer();\n\n\t\treturn !needDrain;\n\t}\n\n\tend(\n\t\tchunk?: any,\n\t\tencoding?: BufferEncoding | WriteCallback,\n\t\tcb?: WriteCallback\n\t): void {\n\t\tif (typeof chunk === 'function') {\n\t\t\tcb = chunk;\n\t\t\tchunk = undefined;\n\t\t} else if (typeof encoding === 'function') {\n\t\t\tcb = encoding as WriteCallback;\n\t\t\tencoding = undefined;\n\t\t}\n\n\t\tif (chunk !== undefined)\n\t\t\tthis.write(chunk, encoding as BufferEncoding, () => {});\n\t\tthis.ended = true;\n\t\tif (!this.writing) this._clearBuffer();\n\t\tif (cb) this.defer(cb);\n\t}\n\n\t// Stubs kept for API parity; add logic if you depend on corking.\n\tcork(): void {}\n\tuncork(): void {}\n\n\tsetDefaultEncoding(enc: BufferEncoding): this {\n\t\tthis.defaultEncoding = enc;\n\t\treturn this;\n\t}\n\n\tprivate _clearBuffer(): void {\n\t\tconst entry = this.buffer.shift();\n\t\tif (!entry) {\n\t\t\tif (this.ended) this.emit('finish');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.writing = true;\n\t\tthis._write(entry.chunk, entry.encoding, (err?: Error | null) => {\n\t\t\tthis.writing = false;\n\t\t\tthis.length -= entry.chunk.length ?? 1;\n\t\t\tif (err) this.emit('error', err);\n\t\t\tentry.cb(err);\n\n\t\t\tif (this.buffer.length) {\n\t\t\t\tthis._clearBuffer();\n\t\t\t} else {\n\t\t\t\tif (this.length < this.highWaterMark) this.emit('drain');\n\t\t\t\tif (this.ended) this.emit('finish');\n\t\t\t}\n\t\t});\n\t}\n}\n","import { EventEmitterPolyfill } from './event-emitter-polyfill';\nimport { splitShellCommand } from './split-shell-command';\nimport { WritablePolyfill, type WriteCallback } from './writable-polyfill';\n\ntype Listener = (...args: any[]) => any;\n\nexport interface ProcessOptions {\n\tcwd?: string;\n\tenv?: Record<string, string>;\n}\n\n/**\n * Usage:\n * ```ts\n * php.setSpawnHandler(\n * createSpawnHandler(function (command, processApi) {\n * console.log(processApi.flushStdin());\n * processApi.stdout('/\\n/tmp\\n/home');\n *\t processApi.exit(0);\n * })\n * );\n * ```\n * @param program\n * @returns\n */\nexport function createSpawnHandler(\n\tprogram: (\n\t\tcommand: string[],\n\t\tprocessApi: ProcessApi,\n\t\toptions: ProcessOptions\n\t) => void | Promise<void>\n): any {\n\treturn function (\n\t\tcommand: string | string[],\n\t\targsArray: string[] = [],\n\t\toptions: ProcessOptions = {}\n\t) {\n\t\tconst childProcess = new ChildProcess();\n\t\tconst processApi = new ProcessApi(childProcess);\n\t\t// Give PHP a chance to register listeners\n\t\tsetTimeout(async () => {\n\t\t\tlet commandArray = [];\n\t\t\tif (argsArray.length) {\n\t\t\t\tcommandArray = [command as string, ...argsArray];\n\t\t\t} else if (typeof command === 'string') {\n\t\t\t\tcommandArray = splitShellCommand(command);\n\t\t\t} else if (Array.isArray(command)) {\n\t\t\t\tcommandArray = command;\n\t\t\t} else {\n\t\t\t\tthrow new Error('Invalid command ', command);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst promise = program(commandArray, processApi, options);\n\t\t\t\tif (\n\t\t\t\t\ttypeof promise !== 'object' ||\n\t\t\t\t\tpromise === null ||\n\t\t\t\t\t!('then' in promise)\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`The program callback passed to createSpawnHandler() did not return a promise. It indicates there's a bug in your code. ` +\n\t\t\t\t\t\t\t`The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() ` +\n\t\t\t\t\t\t\t`call. All the streams would be closed already. Make sure to put an \"await new Promise(resolve => setTimeout(resolve, 1))` +\n\t\t\t\t\t\t\t`before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`\n\t\t\t\t\t);\n\t\t\t\t} else if (processApi.exited) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`The program callback passed to createSpawnHandler() exited synchronously. It indicates there's a bug in your code. ` +\n\t\t\t\t\t\t\t`The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() ` +\n\t\t\t\t\t\t\t`call. All the streams would be closed already. Make sure to put an \"await new Promise(resolve => setTimeout(resolve, 1))` +\n\t\t\t\t\t\t\t`before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tchildProcess.emit('spawn', true);\n\t\t\t\tawait promise;\n\t\t\t} catch (e) {\n\t\t\t\tchildProcess.emit('error', e);\n\t\t\t\tif (\n\t\t\t\t\ttypeof e === 'object' &&\n\t\t\t\t\te !== null &&\n\t\t\t\t\t'message' in e &&\n\t\t\t\t\ttypeof e.message === 'string'\n\t\t\t\t) {\n\t\t\t\t\tprocessApi.stderr(e.message);\n\t\t\t\t}\n\t\t\t\tprocessApi.exit(1);\n\t\t\t}\n\t\t});\n\t\treturn childProcess;\n\t};\n}\n\nexport class ProcessApi extends EventEmitterPolyfill {\n\tpublic exited = false;\n\t/**\n\t * Keeps track of the data that was written to stdin before the\n\t * first listener was registered.\n\t */\n\tprivate stdinBuffer: Uint8Array[] | null = [];\n\tpublic childProcess: ChildProcess;\n\tconstructor(childProcess: ChildProcess) {\n\t\tsuper();\n\t\tthis.childProcess = childProcess;\n\t\tchildProcess.on('stdin', (data: Uint8Array) => {\n\t\t\tif (this.stdinBuffer) {\n\t\t\t\t// Need to clone the data buffer as it's reused by PHP\n\t\t\t\t// and the next data chunk will overwrite the previous one.\n\t\t\t\tthis.stdinBuffer.push(data.slice());\n\t\t\t} else {\n\t\t\t\tthis.emit('stdin', data);\n\t\t\t}\n\t\t});\n\t}\n\tstdinEnd() {\n\t\tif (!this.childProcess.stdin.ended) {\n\t\t\tthis.childProcess.stdin.end();\n\t\t}\n\t}\n\tstdout(data: string | ArrayBuffer) {\n\t\tthis.childProcess.stdout.write(data);\n\t}\n\tstdoutEnd() {\n\t\tif (!this.childProcess.stdout.ended) {\n\t\t\tthis.childProcess.stdout.end();\n\t\t}\n\t}\n\tstderr(data: string | ArrayBuffer) {\n\t\tthis.childProcess.stderr.write(data);\n\t}\n\tstderrEnd() {\n\t\tif (!this.childProcess.stderr.ended) {\n\t\t\tthis.childProcess.stderr.end();\n\t\t}\n\t}\n\tnotifySpawn() {\n\t\tthis.childProcess.emit('spawn', true);\n\t}\n\texit(code: number) {\n\t\tif (!this.exited) {\n\t\t\tthis.exited = true;\n\t\t\tthis.stdinEnd();\n\t\t\tthis.stdoutEnd();\n\t\t\tthis.stderrEnd();\n\t\t\tthis.childProcess.emit('exit', code);\n\t\t}\n\t}\n\toverride on(eventName: string, listener: Listener) {\n\t\tsuper.on(eventName, listener);\n\t\t/**\n\t\t * If it's the first stdin listener, flush all the data we've\n\t\t * buffered so far.\n\t\t */\n\t\tif (eventName === 'stdin' && this.stdinBuffer) {\n\t\t\tfor (let i = 0; i < this.stdinBuffer.length; i++) {\n\t\t\t\tthis.emit('stdin', this.stdinBuffer[i]);\n\t\t\t}\n\t\t\tthis.stdinBuffer = null;\n\t\t}\n\t}\n}\n\nlet lastPid = 9743;\nexport class ChildProcess extends EventEmitterPolyfill {\n\tstdout: WritablePolyfill;\n\tstderr: WritablePolyfill;\n\tstdin: WritablePolyfill;\n\tpid: number;\n\tconstructor(pid = lastPid++) {\n\t\tsuper();\n\t\tthis.pid = pid;\n\t\t// eslint-disable-next-line @typescript-eslint/no-this-alias\n\t\tconst self = this;\n\t\tthis.stdout = new WritablePolyfill({\n\t\t\twrite(data: any, encoding: BufferEncoding, cb: WriteCallback) {\n\t\t\t\tself.stdout.emit('data', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t\tthis.stderr = new WritablePolyfill({\n\t\t\twrite: (data: any, encoding: BufferEncoding, cb: WriteCallback) => {\n\t\t\t\tself.stderr.emit('data', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t\tthis.stdin = new WritablePolyfill({\n\t\t\twrite: (data: any, encoding: BufferEncoding, cb: WriteCallback) => {\n\t\t\t\tself.emit('stdin', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t}\n}\n","export function randomString(\n\tlength = 36,\n\tspecialChars = '!@#$%^&*()_+=-[]/.,<>?'\n) {\n\tconst chars =\n\t\t'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' +\n\t\tspecialChars;\n\tlet result = '';\n\tfor (let i = length; i > 0; --i)\n\t\tresult += chars[Math.floor(Math.random() * chars.length)];\n\treturn result;\n}\n","import { randomString } from './random-string';\n\nexport function randomFilename() {\n\treturn randomString(36, '-_');\n}\n","export function phpVar(value: unknown): string {\n\treturn `json_decode(base64_decode('${stringToBase64(\n\t\tJSON.stringify(value)\n\t)}'), true)`;\n}\n\nexport function phpVars<T extends Record<string, unknown>>(\n\tvars: T\n): Record<keyof T, string> {\n\tconst result: Record<string, string> = {};\n\tfor (const key in vars) {\n\t\tresult[key] = phpVar(vars[key]);\n\t}\n\treturn result as Record<keyof T, string>;\n}\n\nfunction stringToBase64(str: string) {\n\treturn bytesToBase64(new TextEncoder().encode(str));\n}\n\nfunction bytesToBase64(bytes: Uint8Array) {\n\tconst binString = String.fromCodePoint(...bytes);\n\treturn btoa(binString);\n}\n","/**\n * Formats a string like sprintf().\n *\n * This function:\n * - Supports basic format specifiers: %s, %d, %f, %x, %%\n * - Supports bigint values\n *\n * The purpose of this function is for use in optional php-wasm tracing.\n * If we use printf-style formatting for trace messages, we let the trace\n * function decide whether to format and do not have to pay for formatting\n * unless tracing is enabled.\n */\nexport function sprintf(format: string, ...args: any[]): string {\n\tlet result = '';\n\tlet argIndex = 0;\n\n\tfor (let i = 0; i < format.length; i++) {\n\t\tif (format[i] === '%' && i + 1 < format.length) {\n\t\t\ti++;\n\t\t\tconst specifier = format[i];\n\n\t\t\tswitch (specifier) {\n\t\t\t\tcase 's': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tlet str;\n\t\t\t\t\tif (typeof arg === 'object') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// If an object doesn't provide its own toString(),\n\t\t\t\t\t\t\t// try to represent it as JSON.\n\t\t\t\t\t\t\tstr = JSON.stringify(\n\t\t\t\t\t\t\t\targ,\n\t\t\t\t\t\t\t\t// Represent bigint values as strings in JSON.stringify().\n\t\t\t\t\t\t\t\t(key, value) => {\n\t\t\t\t\t\t\t\t\tif (typeof value === 'bigint') {\n\t\t\t\t\t\t\t\t\t\treturn `0x${value.toString(16)}`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Ignore error and use default representation.\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstr = String(arg);\n\t\t\t\t\t}\n\n\t\t\t\t\tresult += str;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'd': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += arg.toString();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Math.floor(Number(arg));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'f': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += Number(arg);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Number(arg);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'x': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += arg.toString(16);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Math.floor(Number(arg)).toString(16);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase '%': {\n\t\t\t\t\tresult += '%';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\tresult += '%' + specifier;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tresult += format[i];\n\t\t}\n\t}\n\n\treturn result;\n}\n","import Semaphore, { AcquireTimeoutError } from './semaphore';\nexport { Semaphore, AcquireTimeoutError };\nexport { PhpWasmError } from './php-wasm-error';\nexport type { SemaphoreOptions } from './semaphore';\nexport {\n\tdirname,\n\tjoinPaths,\n\tbasename,\n\tnormalizePath,\n\tisParentOf,\n\tensureAbsolutePath,\n\ttoPosixPath,\n} from './paths';\nexport { createSpawnHandler } from './create-spawn-handler';\nexport { randomString } from './random-string';\nexport { randomFilename } from './random-filename';\nexport { splitShellCommand } from './split-shell-command';\nexport { WritablePolyfill, type WritableOptions } from './writable-polyfill';\nexport { EventEmitterPolyfill } from './event-emitter-polyfill';\nexport * from './php-vars';\n\nexport * from './sprintf';\n\nexport function concatUint8Arrays(arrays: Uint8Array[]): Uint8Array {\n\tlet totalLength = 0;\n\tarrays.forEach((a) => (totalLength += a.length));\n\tconst result = new Uint8Array(totalLength);\n\tlet offset = 0;\n\tarrays.forEach((a) => {\n\t\tresult.set(a, offset);\n\t\toffset += a.length;\n\t});\n\treturn result;\n}\n\nexport function concatArrayBuffers(buffers: ArrayBuffer[]): ArrayBuffer {\n\treturn concatUint8Arrays(buffers.map((b) => new Uint8Array(b)))\n\t\t.buffer as ArrayBuffer;\n}\n"],"names":["SleepFinished","sleep","ms","resolve","AcquireTimeoutError","Semaphore","concurrency","timeout","acquired","released","fn","release","PhpWasmError","message","userFriendlyMessage","joinPaths","paths","hasTrailingSlash","p","path","isAbsolute","trailingSlash","normalizePath","dirname","lastSlash","basename","normalizePathsArray","parts","allowAboveRoot","up","i","last","isParentOf","parent","child","ensureAbsolutePath","toPosixPath","nativePath","result","driveMatch","EventEmitterPolyfill","eventName","data","listener","wrappedListener","args","l","splitShellCommand","command","mode","quote","currentPart","char","WritablePolyfill","opts","chunk","encoding","cb","err","defer","needDrain","enc","entry","createSpawnHandler","program","argsArray","options","childProcess","ChildProcess","processApi","ProcessApi","commandArray","promise","e","code","lastPid","pid","self","randomString","length","specialChars","chars","randomFilename","phpVar","value","stringToBase64","phpVars","vars","key","str","bytesToBase64","bytes","binString","sprintf","format","argIndex","specifier","arg","concatUint8Arrays","arrays","totalLength","a","offset","concatArrayBuffers","buffers","b"],"mappings":"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"} | ||
| {"version":3,"file":"index.cjs","sources":["../../../../packages/php-wasm/util/src/lib/sleep.ts","../../../../packages/php-wasm/util/src/lib/semaphore.ts","../../../../packages/php-wasm/util/src/lib/php-wasm-error.ts","../../../../packages/php-wasm/util/src/lib/paths.ts","../../../../packages/php-wasm/util/src/lib/event-emitter-polyfill.ts","../../../../packages/php-wasm/util/src/lib/split-shell-command.ts","../../../../packages/php-wasm/util/src/lib/writable-polyfill.ts","../../../../packages/php-wasm/util/src/lib/create-spawn-handler.ts","../../../../packages/php-wasm/util/src/lib/php-event.ts","../../../../packages/php-wasm/util/src/lib/spawn-handlers/sendmail.ts","../../../../packages/php-wasm/util/src/lib/random-string.ts","../../../../packages/php-wasm/util/src/lib/random-filename.ts","../../../../packages/php-wasm/util/src/lib/php-vars.ts","../../../../packages/php-wasm/util/src/lib/sprintf.ts","../../../../packages/php-wasm/util/src/lib/index.ts"],"sourcesContent":["export const SleepFinished = Symbol('SleepFinished');\n\nexport function sleep(ms: number): Promise<typeof SleepFinished> {\n\treturn new Promise((resolve) => {\n\t\tsetTimeout(() => resolve(SleepFinished), ms);\n\t});\n}\n","import { SleepFinished, sleep } from './sleep';\n\nexport interface SemaphoreOptions {\n\t/**\n\t * The maximum number of concurrent locks.\n\t */\n\tconcurrency: number;\n\t/**\n\t * The maximum time to wait for a lock to become available.\n\t */\n\ttimeout?: number;\n}\n\nexport class AcquireTimeoutError extends Error {\n\tconstructor() {\n\t\tsuper('Acquiring lock timed out');\n\t}\n}\n\nexport default class Semaphore {\n\tprivate _running = 0;\n\tprivate concurrency: number;\n\tprivate timeout?: number;\n\tprivate queue: (() => void)[];\n\n\tconstructor({ concurrency, timeout }: SemaphoreOptions) {\n\t\tthis.concurrency = concurrency;\n\t\tthis.timeout = timeout;\n\t\tthis.queue = [];\n\t}\n\n\tget remaining(): number {\n\t\treturn this.concurrency - this.running;\n\t}\n\n\tget running(): number {\n\t\treturn this._running;\n\t}\n\n\tasync acquire(): Promise<() => void> {\n\t\t// Concurrency exhausted - wait in queue for other workers to finish:\n\t\tif (this._running >= this.concurrency) {\n\t\t\t// Create a promise and store its resolver in the queue.\n\t\t\tconst acquired = new Promise<void>((resolve) => {\n\t\t\t\tthis.queue.push(resolve);\n\t\t\t});\n\n\t\t\t// Wait until it is resolved by another worker or a timeout occurs.\n\t\t\tif (this.timeout !== undefined) {\n\t\t\t\t// Store the resolver for cleanup in case of timeout.\n\t\t\t\tconst resolve = this.queue.at(-1)!;\n\t\t\t\tconst result = await Promise.race([\n\t\t\t\t\tacquired,\n\t\t\t\t\tsleep(this.timeout),\n\t\t\t\t]);\n\t\t\t\tif (result === SleepFinished) {\n\t\t\t\t\t// Remove the resolver for the timed out worker from the queue.\n\t\t\t\t\tthis.queue.splice(this.queue.indexOf(resolve), 1);\n\t\t\t\t\tthrow new AcquireTimeoutError();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait acquired;\n\t\t\t}\n\t\t}\n\n\t\t// Acquire the lock:\n\t\tthis._running++;\n\t\tlet released = false;\n\n\t\t// Return a release function:\n\t\treturn () => {\n\t\t\tif (released) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treleased = true;\n\t\t\tthis._running--;\n\n\t\t\t// Release the first item in the queue (call its resolver):\n\t\t\tif (this.queue.length > 0) {\n\t\t\t\tthis.queue.shift()!();\n\t\t\t}\n\t\t};\n\t}\n\n\tasync run<T>(fn: () => T | Promise<T>): Promise<T> {\n\t\tconst release = await this.acquire();\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\trelease();\n\t\t}\n\t}\n}\n","export class PhpWasmError extends Error {\n\tuserFriendlyMessage?: string;\n\tconstructor(message: string, userFriendlyMessage?: string) {\n\t\tsuper(message);\n\t\tthis.userFriendlyMessage = userFriendlyMessage ?? message;\n\t}\n}\n","/**\n * The functions in this module are mostly copied from the generated\n * Emscripten PHP module. This enables features like filesystem journaling,\n * which use some low-level Emscripten APIs and need access to the\n * same path helpers.\n */\n\n/**\n * Joins paths together.\n *\n * For example:\n *\n * > joinPaths('wordpress', 'wp-content')\n * 'wordpress/wp-content'\n *\n * Use this for all PHP paths and **do not** use path.join().\n * This is important because Emscripten paths are **always**\n * POSIX-style paths. Imagine joining paths on Windows:\n *\n * > path.join('wordpress', 'wp-content')\n * '\\\\wordpress\\\\wp-content' // invalid in PHP.wasm\n *\n * See the path.join issue for more details:\n *\n * https://github.com/WordPress/playground-tools/issues/11#issuecomment-1579074763\n *\n * @param paths Paths segments to join\n * @returns A joined path\n */\nexport function joinPaths(...paths: string[]) {\n\tfunction hasTrailingSlash(p: string) {\n\t\treturn p.substring(p.length - 1) === '/';\n\t}\n\n\tlet path = paths.join('/');\n\tconst isAbsolute = path[0] === '/';\n\tconst trailingSlash = hasTrailingSlash(path);\n\tpath = normalizePath(path);\n\tif (!path && !isAbsolute) {\n\t\tpath = '.';\n\t}\n\tif (path && trailingSlash && !hasTrailingSlash(path)) {\n\t\tpath += '/';\n\t}\n\treturn path;\n}\n\n/**\n * Resolves a path and returns it only when it stays under a parent path.\n *\n * Absolute paths are checked as-is. Relative paths are resolved from the\n * parent path. The parent itself is not considered to be under the parent.\n * Paths containing null bytes are rejected before resolution.\n *\n * @param path The absolute or relative path to resolve.\n * @param parentPath The path the result must stay under.\n * @returns The normalized resolved path, or undefined when it is not a child.\n */\nexport function resolvePathUnder(path: string, parentPath: string) {\n\tif (path.includes('\\0') || parentPath.includes('\\0')) {\n\t\treturn undefined;\n\t}\n\tconst normalizedParentPath = normalizePath(parentPath);\n\tif (!normalizedParentPath) {\n\t\treturn undefined;\n\t}\n\tconst resolvedPath = normalizePath(\n\t\tpath.startsWith('/') ? path : joinPaths(normalizedParentPath, path)\n\t);\n\tif (\n\t\tresolvedPath === normalizedParentPath ||\n\t\t!isParentOf(normalizedParentPath, resolvedPath)\n\t) {\n\t\treturn undefined;\n\t}\n\treturn resolvedPath;\n}\n\n/**\n * Returns the directory name of a path.\n *\n * @param path\n * @returns\n */\nexport function dirname(path: string) {\n\tif (path === '/') {\n\t\treturn '/';\n\t}\n\n\tpath = normalizePath(path);\n\n\tconst lastSlash = path.lastIndexOf('/');\n\tif (lastSlash === -1) {\n\t\treturn '';\n\t} else if (lastSlash === 0) {\n\t\treturn '/';\n\t}\n\treturn path.substr(0, lastSlash);\n}\n\n/**\n * Returns the last portion of a path.\n *\n * @param path - The path to extract the basename from.\n * @returns The basename of the path.\n */\nexport function basename(path: string) {\n\tif (path === '/') {\n\t\treturn '/';\n\t}\n\n\tpath = normalizePath(path);\n\n\tconst lastSlash = path.lastIndexOf('/');\n\tif (lastSlash === -1) {\n\t\treturn path;\n\t}\n\treturn path.substr(lastSlash + 1);\n}\n\n/**\n * Normalizes a path.\n *\n * For example:\n *\n * > normalizePath('wordpress/wp-content/../')\n * 'wordpress'\n *\n * @param path\n * @returns\n */\nexport function normalizePath(path: string) {\n\tconst isAbsolute = path[0] === '/';\n\tpath = normalizePathsArray(\n\t\tpath.split('/').filter((p: any) => !!p),\n\t\t!isAbsolute\n\t).join('/');\n\treturn (isAbsolute ? '/' : '') + path.replace(/\\/$/, '');\n}\n\n/**\n * Normalizes paths.\n *\n * For example:\n *\n * > normalizePathsArray(['wordpress', 'wp-content', '..', '', '.',\n * 'wp-includes']) ['wordpress', 'wp-includes']\n *\n * @param parts parts of the path to normalize\n * @param allowAboveRoot allow paths above the root\n * @returns normalized paths\n */\nexport function normalizePathsArray(parts: string[], allowAboveRoot: boolean) {\n\tlet up = 0;\n\tfor (let i = parts.length - 1; i >= 0; i--) {\n\t\tconst last = parts[i];\n\t\tif (last === '.') {\n\t\t\tparts.splice(i, 1);\n\t\t} else if (last === '..') {\n\t\t\tparts.splice(i, 1);\n\t\t\tup++;\n\t\t} else if (up) {\n\t\t\tparts.splice(i, 1);\n\t\t\tup--;\n\t\t}\n\t}\n\tif (allowAboveRoot) {\n\t\tfor (; up; up--) {\n\t\t\tparts.unshift('..');\n\t\t}\n\t}\n\treturn parts;\n}\n\n/**\n * Checks if the given parent path is an ancestor of the given child path.\n *\n * @param parent The parent path to check.\n * @param child The child path to verify against the parent.\n * @returns Whether the `parent` path is an ancestor of the `child` path.\n */\nexport function isParentOf(parent: string, child: string) {\n\tif (parent === '/') {\n\t\treturn true;\n\t}\n\tparent = normalizePath(parent);\n\tchild = normalizePath(child);\n\treturn child.startsWith(parent + '/') || child === parent;\n}\n\n/**\n * Guarantees a path is absolute by prepending `/` if needed.\n *\n * Useful when working with user-provided paths that might be relative,\n * or when you need to normalize edge cases like empty strings.\n *\n * For example:\n *\n * > ensureAbsolutePath('wp-content/uploads')\n * '/wp-content/uploads'\n *\n * > ensureAbsolutePath('/already/absolute')\n * '/already/absolute'\n *\n * > ensureAbsolutePath('')\n * '/'\n *\n * @param path - The path to make absolute.\n * @returns An absolute, normalized path starting with `/`.\n */\nexport function ensureAbsolutePath(path: string) {\n\treturn joinPaths('/', normalizePath(path || '/'));\n}\n\n/**\n * Converts a native OS path to a POSIX-style path.\n *\n * Transformations:\n * 1. Backslashes → forward slashes\n * 2. Windows drive letter `C:\\` → `/C/` (colons are invalid in\n * Emscripten VFS paths and cause ENOTDIR errno 28)\n *\n * On POSIX systems this is effectively a no-op.\n *\n * @see https://github.com/emscripten-core/emscripten/issues/17829\n */\nexport function toPosixPath(nativePath: string): string {\n\tlet result = nativePath.replaceAll('\\\\', '/');\n\t// Handle Windows drive letter: C:/ → /C/\n\tconst driveMatch = result.match(/^([A-Za-z]):\\//);\n\tif (driveMatch) {\n\t\tresult = '/' + driveMatch[1] + result.slice(2);\n\t}\n\treturn result;\n}\n","/**\n * Polyfills Node.js EventEmitter API. The main goal is to enable\n * using a child_process.spawn()-like API in both Node.js and the browser.\n *\n * @see https://nodejs.org/api/events.html#events_class_eventemitter\n */\ntype Listener = (...args: any[]) => any;\n\nexport class EventEmitterPolyfill {\n\tlisteners: Record<string, Listener[]> = {};\n\temit(eventName: string, data?: any) {\n\t\tif (this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName].forEach(function (listener) {\n\t\t\t\tlistener(data);\n\t\t\t});\n\t\t}\n\t}\n\ton(eventName: string, listener: Listener) {\n\t\tif (!this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName] = [];\n\t\t}\n\t\tthis.listeners[eventName].push(listener);\n\t}\n\tonce(eventName: string, listener: Listener) {\n\t\tconst wrappedListener = (...args: any[]) => {\n\t\t\tthis.off(eventName, wrappedListener);\n\t\t\tlistener(...args);\n\t\t};\n\t\tthis.on(eventName, wrappedListener);\n\t}\n\toff(eventName: string, listener: Listener) {\n\t\tif (this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName] = this.listeners[eventName].filter(\n\t\t\t\t(l) => l !== listener\n\t\t\t);\n\t\t}\n\t}\n}\n","/**\n * Naive shell command parser.\n * Ensures that commands like `wp option set blogname \"My blog name\"` are split\n * into `['wp', 'option', 'set', 'blogname', 'My blog name']` instead of\n * `['wp', 'option', 'set', 'blogname', 'My', 'blog', 'name']`.\n *\n * @param command\n * @returns\n */\nexport function splitShellCommand(command: string) {\n\tconst MODE_UNQUOTED = 0;\n\tconst MODE_IN_QUOTE = 1;\n\n\tlet mode = MODE_UNQUOTED;\n\tlet quote = '';\n\n\tconst parts: string[] = [];\n\tlet currentPart = '';\n\tfor (let i = 0; i < command.length; i++) {\n\t\tconst char = command[i];\n\t\tif (char === '\\\\') {\n\t\t\t// Escaped quotes are treated as normal characters\n\t\t\t// This is a very naive approach to escaping, but it's good enough for\n\t\t\t// now. @TODO: Iterate on this later, perhaps using bun shell. @see https://github.com/WordPress/wordpress-playground/issues/1062\n\t\t\tif (command[i + 1] === '\"' || command[i + 1] === \"'\") {\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tcurrentPart += command[i];\n\t\t} else if (mode === MODE_UNQUOTED) {\n\t\t\tif (char === '\"' || char === \"'\") {\n\t\t\t\tmode = MODE_IN_QUOTE;\n\t\t\t\tquote = char;\n\t\t\t} else if (char.match(/\\s/)) {\n\t\t\t\tif (currentPart.trim().length) {\n\t\t\t\t\tparts.push(currentPart.trim());\n\t\t\t\t}\n\t\t\t\tcurrentPart = char;\n\t\t\t} else if (parts.length && !currentPart) {\n\t\t\t\t// We just closed a quote to continue the same\n\t\t\t\t// argument with different escaping style, e.g.:\n\t\t\t\t// php -r 'require '\\''vendor/autoload.php'\\''\n\t\t\t\tcurrentPart = parts.pop()! + char;\n\t\t\t} else {\n\t\t\t\tcurrentPart += char;\n\t\t\t}\n\t\t} else if (mode === MODE_IN_QUOTE) {\n\t\t\tif (char === quote) {\n\t\t\t\tmode = MODE_UNQUOTED;\n\t\t\t\tquote = '';\n\t\t\t} else {\n\t\t\t\tcurrentPart += char;\n\t\t\t}\n\t\t}\n\t}\n\tif (currentPart) {\n\t\tparts.push(currentPart.trim());\n\t}\n\treturn parts;\n}\n","/**\n * Polyfills Node.js WritableStream API. The main goal is to enable\n * using a child_process.spawn()-like API in both Node.js and the browser.\n *\n * @see https://nodejs.org/api/stream.html#stream_writable_end_chunk_encoding_callback\n */\nimport { EventEmitterPolyfill } from './event-emitter-polyfill';\n\nexport interface WritableOptions {\n\thighWaterMark?: number;\n\tdecodeStrings?: boolean;\n\tdefaultEncoding?: BufferEncoding;\n\twrite: (chunk: any, encoding: BufferEncoding, cb: WriteCallback) => void;\n}\n\nexport type WriteCallback = (error?: Error | null) => void;\n\nexport class WritablePolyfill extends EventEmitterPolyfill {\n\tprivate buffer: Array<{\n\t\tchunk: any;\n\t\tencoding: BufferEncoding;\n\t\tcb: WriteCallback;\n\t}> = [];\n\tprivate writing = false;\n\tpublic ended = false;\n\tprivate length = 0;\n\tprivate highWaterMark: number;\n\tprivate decodeStrings: boolean;\n\tprivate defaultEncoding: BufferEncoding;\n\tprivate defer: (fn: () => void) => void;\n\tprivate _write: (\n\t\tchunk: any,\n\t\tencoding: BufferEncoding,\n\t\tcb: WriteCallback\n\t) => void;\n\n\tconstructor(opts: WritableOptions) {\n\t\tsuper();\n\t\tif (!opts.write) {\n\t\t\tthrow new Error('WritablePolyfill requires write option');\n\t\t}\n\t\tthis._write = opts.write;\n\t\tthis.highWaterMark = opts.highWaterMark ?? 16 * 1024;\n\t\tthis.decodeStrings = opts.decodeStrings ?? true;\n\t\tthis.defaultEncoding = opts.defaultEncoding ?? 'utf8';\n\t\t// queueMicrotask keeps browser support; fallback for older environments.\n\t\tthis.defer =\n\t\t\ttypeof queueMicrotask === 'function'\n\t\t\t\t? queueMicrotask\n\t\t\t\t: (fn) => setTimeout(fn, 0);\n\t}\n\n\twrite(\n\t\tchunk: any,\n\t\tencoding: BufferEncoding | WriteCallback = this.defaultEncoding,\n\t\tcb: WriteCallback = () => {}\n\t): boolean {\n\t\tif (typeof encoding === 'function') {\n\t\t\tcb = encoding as WriteCallback;\n\t\t\tencoding = this.defaultEncoding;\n\t\t}\n\n\t\tif (this.ended) {\n\t\t\tconst err = new Error('write after end');\n\t\t\t// We can't call this.defer() directly. If this.defer is\n\t\t\t// `queueMicrotask`, a `this.defer()` call will pass the\n\t\t\t// WritablePolyfill instance as `this` argument and cause\n\t\t\t// the browser to throw an error similar to \"Invalid\n\t\t\t// invocation\".\n\t\t\tconst defer = this.defer;\n\t\t\tdefer(() => cb(err));\n\t\t\tthis.emit('error', err);\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this.decodeStrings && typeof chunk === 'string') {\n\t\t\tif (\n\t\t\t\ttypeof Buffer !== 'undefined' &&\n\t\t\t\ttypeof (Buffer as any).from === 'function'\n\t\t\t) {\n\t\t\t\tchunk = Buffer.from(chunk, encoding as BufferEncoding);\n\t\t\t} else if (typeof TextEncoder !== 'undefined') {\n\t\t\t\tchunk = new TextEncoder().encode(chunk);\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'String chunks are not supported in this environment: Buffer and TextEncoder are unavailable.'\n\t\t\t\t);\n\t\t\t}\n\t\t\tencoding = 'buffer' as BufferEncoding;\n\t\t}\n\n\t\tthis.length += chunk.length ?? 1;\n\t\tconst needDrain = this.length >= this.highWaterMark;\n\n\t\tthis.buffer.push({ chunk, encoding: encoding as BufferEncoding, cb });\n\n\t\tif (!this.writing) this._clearBuffer();\n\n\t\treturn !needDrain;\n\t}\n\n\tend(\n\t\tchunk?: any,\n\t\tencoding?: BufferEncoding | WriteCallback,\n\t\tcb?: WriteCallback\n\t): void {\n\t\tif (typeof chunk === 'function') {\n\t\t\tcb = chunk;\n\t\t\tchunk = undefined;\n\t\t} else if (typeof encoding === 'function') {\n\t\t\tcb = encoding as WriteCallback;\n\t\t\tencoding = undefined;\n\t\t}\n\n\t\tif (chunk !== undefined)\n\t\t\tthis.write(chunk, encoding as BufferEncoding, () => {});\n\t\tthis.ended = true;\n\t\tif (!this.writing) this._clearBuffer();\n\t\tif (cb) this.defer(cb);\n\t}\n\n\t// Stubs kept for API parity; add logic if you depend on corking.\n\tcork(): void {}\n\tuncork(): void {}\n\n\tsetDefaultEncoding(enc: BufferEncoding): this {\n\t\tthis.defaultEncoding = enc;\n\t\treturn this;\n\t}\n\n\tprivate _clearBuffer(): void {\n\t\tconst entry = this.buffer.shift();\n\t\tif (!entry) {\n\t\t\tif (this.ended) this.emit('finish');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.writing = true;\n\t\tthis._write(entry.chunk, entry.encoding, (err?: Error | null) => {\n\t\t\tthis.writing = false;\n\t\t\tthis.length -= entry.chunk.length ?? 1;\n\t\t\tif (err) this.emit('error', err);\n\t\t\tentry.cb(err);\n\n\t\t\tif (this.buffer.length) {\n\t\t\t\tthis._clearBuffer();\n\t\t\t} else {\n\t\t\t\tif (this.length < this.highWaterMark) this.emit('drain');\n\t\t\t\tif (this.ended) this.emit('finish');\n\t\t\t}\n\t\t});\n\t}\n}\n","import { EventEmitterPolyfill } from './event-emitter-polyfill';\nimport { splitShellCommand } from './split-shell-command';\nimport { WritablePolyfill, type WriteCallback } from './writable-polyfill';\n\ntype Listener = (...args: any[]) => any;\n\nexport interface ProcessOptions {\n\tcwd?: string;\n\tenv?: Record<string, string>;\n}\n\n/**\n * Usage:\n * ```ts\n * php.setSpawnHandler(\n * createSpawnHandler(function (command, processApi) {\n * console.log(processApi.flushStdin());\n * processApi.stdout('/\\n/tmp\\n/home');\n *\t processApi.exit(0);\n * })\n * );\n * ```\n * @param program\n * @returns\n */\nexport function createSpawnHandler(\n\tprogram: (\n\t\tcommand: string[],\n\t\tprocessApi: ProcessApi,\n\t\toptions: ProcessOptions\n\t) => void | Promise<void>\n): any {\n\treturn function (\n\t\tcommand: string | string[],\n\t\targsArray: string[] = [],\n\t\toptions: ProcessOptions = {}\n\t) {\n\t\tconst childProcess = new ChildProcess();\n\t\tconst processApi = new ProcessApi(childProcess);\n\t\t// Give PHP a chance to register listeners\n\t\tsetTimeout(async () => {\n\t\t\tlet commandArray = [];\n\t\t\tif (argsArray.length) {\n\t\t\t\tcommandArray = [command as string, ...argsArray];\n\t\t\t} else if (typeof command === 'string') {\n\t\t\t\tcommandArray = splitShellCommand(command);\n\t\t\t} else if (Array.isArray(command)) {\n\t\t\t\tcommandArray = command;\n\t\t\t} else {\n\t\t\t\tthrow new Error('Invalid command ', command);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst promise = program(commandArray, processApi, options);\n\t\t\t\tif (\n\t\t\t\t\ttypeof promise !== 'object' ||\n\t\t\t\t\tpromise === null ||\n\t\t\t\t\t!('then' in promise)\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`The program callback passed to createSpawnHandler() did not return a promise. It indicates there's a bug in your code. ` +\n\t\t\t\t\t\t\t`The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() ` +\n\t\t\t\t\t\t\t`call. All the streams would be closed already. Make sure to put an \"await new Promise(resolve => setTimeout(resolve, 1))` +\n\t\t\t\t\t\t\t`before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`\n\t\t\t\t\t);\n\t\t\t\t} else if (processApi.exited) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`The program callback passed to createSpawnHandler() exited synchronously. It indicates there's a bug in your code. ` +\n\t\t\t\t\t\t\t`The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() ` +\n\t\t\t\t\t\t\t`call. All the streams would be closed already. Make sure to put an \"await new Promise(resolve => setTimeout(resolve, 1))` +\n\t\t\t\t\t\t\t`before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tchildProcess.emit('spawn', true);\n\t\t\t\tawait promise;\n\t\t\t} catch (e) {\n\t\t\t\tchildProcess.emit('error', e);\n\t\t\t\tif (\n\t\t\t\t\ttypeof e === 'object' &&\n\t\t\t\t\te !== null &&\n\t\t\t\t\t'message' in e &&\n\t\t\t\t\ttypeof e.message === 'string'\n\t\t\t\t) {\n\t\t\t\t\tprocessApi.stderr(e.message);\n\t\t\t\t}\n\t\t\t\tprocessApi.exit(1);\n\t\t\t}\n\t\t});\n\t\treturn childProcess;\n\t};\n}\n\nexport class ProcessApi extends EventEmitterPolyfill {\n\tpublic exited = false;\n\t/**\n\t * Keeps track of the data that was written to stdin before the\n\t * first listener was registered.\n\t */\n\tprivate stdinBuffer: Uint8Array[] | null = [];\n\tpublic childProcess: ChildProcess;\n\tconstructor(childProcess: ChildProcess) {\n\t\tsuper();\n\t\tthis.childProcess = childProcess;\n\t\tchildProcess.on('stdin', (data: Uint8Array) => {\n\t\t\tif (this.stdinBuffer) {\n\t\t\t\t// Need to clone the data buffer as it's reused by PHP\n\t\t\t\t// and the next data chunk will overwrite the previous one.\n\t\t\t\tthis.stdinBuffer.push(data.slice());\n\t\t\t} else {\n\t\t\t\tthis.emit('stdin', data);\n\t\t\t}\n\t\t});\n\t}\n\tstdinEnd() {\n\t\tif (!this.childProcess.stdin.ended) {\n\t\t\tthis.childProcess.stdin.end();\n\t\t}\n\t}\n\tstdout(data: string | ArrayBuffer) {\n\t\tthis.childProcess.stdout.write(data);\n\t}\n\tstdoutEnd() {\n\t\tif (!this.childProcess.stdout.ended) {\n\t\t\tthis.childProcess.stdout.end();\n\t\t}\n\t}\n\tstderr(data: string | ArrayBuffer) {\n\t\tthis.childProcess.stderr.write(data);\n\t}\n\tstderrEnd() {\n\t\tif (!this.childProcess.stderr.ended) {\n\t\t\tthis.childProcess.stderr.end();\n\t\t}\n\t}\n\tnotifySpawn() {\n\t\tthis.childProcess.emit('spawn', true);\n\t}\n\texit(code: number) {\n\t\tif (!this.exited) {\n\t\t\tthis.exited = true;\n\t\t\tthis.stdinEnd();\n\t\t\tthis.stdoutEnd();\n\t\t\tthis.stderrEnd();\n\t\t\tthis.childProcess.emit('exit', code);\n\t\t}\n\t}\n\toverride on(eventName: string, listener: Listener) {\n\t\tsuper.on(eventName, listener);\n\t\t/**\n\t\t * If it's the first stdin listener, flush all the data we've\n\t\t * buffered so far.\n\t\t */\n\t\tif (eventName === 'stdin' && this.stdinBuffer) {\n\t\t\tfor (let i = 0; i < this.stdinBuffer.length; i++) {\n\t\t\t\tthis.emit('stdin', this.stdinBuffer[i]);\n\t\t\t}\n\t\t\tthis.stdinBuffer = null;\n\t\t}\n\t}\n}\n\nlet lastPid = 9743;\nexport class ChildProcess extends EventEmitterPolyfill {\n\tstdout: WritablePolyfill;\n\tstderr: WritablePolyfill;\n\tstdin: WritablePolyfill;\n\tpid: number;\n\tconstructor(pid = lastPid++) {\n\t\tsuper();\n\t\tthis.pid = pid;\n\t\t// eslint-disable-next-line @typescript-eslint/no-this-alias\n\t\tconst self = this;\n\t\tthis.stdout = new WritablePolyfill({\n\t\t\twrite(data: any, encoding: BufferEncoding, cb: WriteCallback) {\n\t\t\t\tself.stdout.emit('data', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t\tthis.stderr = new WritablePolyfill({\n\t\t\twrite: (data: any, encoding: BufferEncoding, cb: WriteCallback) => {\n\t\t\t\tself.stderr.emit('data', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t\tthis.stdin = new WritablePolyfill({\n\t\t\twrite: (data: any, encoding: BufferEncoding, cb: WriteCallback) => {\n\t\t\t\tself.emit('stdin', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t}\n}\n","/**\n * Explicitly marks an event whose `stdin` ReadableStream needs an independent\n * branch per listener and must be transferred across worker boundaries. The\n * global symbol registry keeps the marker stable if this package is loaded\n * more than once in the same realm.\n */\nexport const phpEventStdinTransfer = Symbol.for(\n\t'@php-wasm/php-event-stdin-transfer'\n);\n\nexport type PHPEventWithStdinTransfer = {\n\ttype: string;\n\tstdin: ReadableStream<Uint8Array>;\n\t[phpEventStdinTransfer]: true;\n};\n","import { createSpawnHandler } from '../create-spawn-handler';\nimport {\n\tphpEventStdinTransfer,\n\ttype PHPEventWithStdinTransfer,\n} from '../php-event';\n\n/**\n * Limit captured sendmail stdin to 20 MB to match common email size limits.\n *\n * Gmail limits email attachments to 25 MB https://support.google.com/mail/answer/6584\n * Outlook limits email attachments to 20 MB https://support.microsoft.com/outlook/reduce-attachment-size-to-send-large-files-with-outlook\n */\nexport const SENDMAIL_CAPTURE_MAX_SIZE = 20 * 1024 * 1024;\n\n/**\n * Emitted when a sendmail null transport receives the first stdin bytes from\n * `mail()`, `popen()`, `proc_open()`, or any other spawn of a `sendmail` binary.\n */\nexport interface PHPSendmailSpawnedEvent extends PHPEventWithStdinTransfer {\n\ttype: 'sendmail.spawned';\n}\n\n/**\n * Creates a sendmail-compatible null transport for the given PHP instance.\n * Every message handed to sendmail – via mail(), proc_open(), etc. – is streamed\n * from stdin, dispatched as a `sendmail.spawned` event, and never delivered.\n * A listener that wants real delivery must relay the message itself.\n *\n * The captured payload is exposed as the raw bytes written to sendmail stdin.\n *\n * This stream does not apply backpressure to PHP. Each listener queues unread\n * chunks in JavaScript memory when it reads more slowly than PHP writes. The\n * source accepts at most SENDMAIL_CAPTURE_MAX_SIZE bytes. Cancelling the stream\n * stops delivery through that stream without terminating the sendmail process.\n */\nexport function sendmailSpawnHandler(php: {\n\tdispatchEvent: (event: PHPSendmailSpawnedEvent) => void;\n}) {\n\treturn createSpawnHandler(async function (commandArray, processApi) {\n\t\tlet totalLength = 0;\n\t\tlet dispatched = false;\n\t\tlet exceededMaxSize = false;\n\t\tlet streamCancelled = false;\n\t\tlet controller: ReadableStreamDefaultController<Uint8Array>;\n\t\t// Construct the stream before registering stdin. Event dispatch is synchronous,\n\t\t// and a listener may start reading as soon as the first chunk arrives.\n\t\tconst stdinStream = new ReadableStream<Uint8Array>({\n\t\t\tstart(streamController) {\n\t\t\t\tcontroller = streamController;\n\t\t\t},\n\t\t\tcancel() {\n\t\t\t\t// Cancellation only means no reader wants more bytes from this source. Keep\n\t\t\t\t// the null transport alive so PHP can finish writing and receive an exit code.\n\t\t\t\tstreamCancelled = true;\n\t\t\t},\n\t\t});\n\n\t\tprocessApi.on('stdin', (data: Uint8Array) => {\n\t\t\tif (!dispatched) {\n\t\t\t\t// Do not publish an email until sendmail receives actual message bytes. An\n\t\t\t\t// invocation that closes stdin immediately is a failed send, not an empty email.\n\t\t\t\tdispatched = true;\n\t\t\t\tphp.dispatchEvent({\n\t\t\t\t\ttype: 'sendmail.spawned',\n\t\t\t\t\tstdin: stdinStream,\n\t\t\t\t\t[phpEventStdinTransfer]: true,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\ttotalLength += data.length;\n\t\t\tif (totalLength > SENDMAIL_CAPTURE_MAX_SIZE) {\n\t\t\t\t// Fail the consumer now, but keep draining stdin. Exiting here would close\n\t\t\t\t// PHP's write end before the spawning code has finished with the process.\n\t\t\t\texceededMaxSize = true;\n\t\t\t\ttry {\n\t\t\t\t\tcontroller!.error(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`sendmail: Message size exceeds fixed maximum message size (${SENDMAIL_CAPTURE_MAX_SIZE})`\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\t// The consumer may have cancelled the stream.\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!streamCancelled) {\n\t\t\t\t// The PHP bridge reuses its input buffer for later chunks. A stream reader\n\t\t\t\t// may retain this one indefinitely, so it must receive an owned copy.\n\t\t\t\tcontroller!.enqueue(data.slice());\n\t\t\t}\n\t\t});\n\n\t\tconst stdin = processApi.childProcess\n\t\t\t.stdin as typeof processApi.childProcess.stdin & {\n\t\t\twritableEnded?: boolean;\n\t\t\twritableFinished?: boolean;\n\t\t};\n\t\t// proc_open() may write long after the spawn handler starts. Keep sendmail\n\t\t// alive until descriptor 0 closes or PHP will observe a truncated pipe.\n\t\tif (!(stdin.ended || stdin.writableEnded || stdin.writableFinished)) {\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t// stdin can finish between the outer check and listener registration.\n\t\t\t\t// Recheck here or that race leaves the sendmail process waiting forever.\n\t\t\t\tif (\n\t\t\t\t\tstdin.ended ||\n\t\t\t\t\tstdin.writableEnded ||\n\t\t\t\t\tstdin.writableFinished\n\t\t\t\t) {\n\t\t\t\t\tresolve();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst finish = () => {\n\t\t\t\t\tresolve();\n\t\t\t\t};\n\n\t\t\t\tstdin.once('finish', finish);\n\t\t\t});\n\t\t}\n\n\t\tif (exceededMaxSize) {\n\t\t\tprocessApi.stderr(\n\t\t\t\t`sendmail: Message size exceeds fixed maximum message size (${SENDMAIL_CAPTURE_MAX_SIZE})\\n`\n\t\t\t);\n\t\t\tprocessApi.exit(1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (totalLength === 0) {\n\t\t\t// EX_TEMPFAIL is the sendmail-compatible result for an invocation that never\n\t\t\t// supplied a message. In particular, do not turn it into a successful no-op.\n\t\t\tprocessApi.stderr(\n\t\t\t\t'sendmail: fatal: No message bytes received over stdin\\n'\n\t\t\t);\n\t\t\tprocessApi.exit(75);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tcontroller!.close();\n\t\t} catch {\n\t\t\t// The consumer may have cancelled the stream.\n\t\t}\n\t\tprocessApi.exit(0);\n\t});\n}\n","export function randomString(\n\tlength = 36,\n\tspecialChars = '!@#$%^&*()_+=-[]/.,<>?'\n) {\n\tconst chars =\n\t\t'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' +\n\t\tspecialChars;\n\tlet result = '';\n\tfor (let i = length; i > 0; --i)\n\t\tresult += chars[Math.floor(Math.random() * chars.length)];\n\treturn result;\n}\n","import { randomString } from './random-string';\n\nexport function randomFilename() {\n\treturn randomString(36, '-_');\n}\n","export function phpVar(value: unknown): string {\n\treturn `json_decode(base64_decode('${stringToBase64(\n\t\tJSON.stringify(value)\n\t)}'), true)`;\n}\n\nexport function phpVars<T extends Record<string, unknown>>(\n\tvars: T\n): Record<keyof T, string> {\n\tconst result: Record<string, string> = {};\n\tfor (const key in vars) {\n\t\tresult[key] = phpVar(vars[key]);\n\t}\n\treturn result as Record<keyof T, string>;\n}\n\nfunction stringToBase64(str: string) {\n\treturn bytesToBase64(new TextEncoder().encode(str));\n}\n\nfunction bytesToBase64(bytes: Uint8Array) {\n\tconst binString = String.fromCodePoint(...bytes);\n\treturn btoa(binString);\n}\n","/**\n * Formats a string like sprintf().\n *\n * This function:\n * - Supports basic format specifiers: %s, %d, %f, %x, %%\n * - Supports bigint values\n *\n * The purpose of this function is for use in optional php-wasm tracing.\n * If we use printf-style formatting for trace messages, we let the trace\n * function decide whether to format and do not have to pay for formatting\n * unless tracing is enabled.\n */\nexport function sprintf(format: string, ...args: any[]): string {\n\tlet result = '';\n\tlet argIndex = 0;\n\n\tfor (let i = 0; i < format.length; i++) {\n\t\tif (format[i] === '%' && i + 1 < format.length) {\n\t\t\ti++;\n\t\t\tconst specifier = format[i];\n\n\t\t\tswitch (specifier) {\n\t\t\t\tcase 's': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tlet str;\n\t\t\t\t\tif (typeof arg === 'object') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// If an object doesn't provide its own toString(),\n\t\t\t\t\t\t\t// try to represent it as JSON.\n\t\t\t\t\t\t\tstr = JSON.stringify(\n\t\t\t\t\t\t\t\targ,\n\t\t\t\t\t\t\t\t// Represent bigint values as strings in JSON.stringify().\n\t\t\t\t\t\t\t\t(key, value) => {\n\t\t\t\t\t\t\t\t\tif (typeof value === 'bigint') {\n\t\t\t\t\t\t\t\t\t\treturn `0x${value.toString(16)}`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Ignore error and use default representation.\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstr = String(arg);\n\t\t\t\t\t}\n\n\t\t\t\t\tresult += str;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'd': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += arg.toString();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Math.floor(Number(arg));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'f': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += Number(arg);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Number(arg);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'x': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += arg.toString(16);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Math.floor(Number(arg)).toString(16);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase '%': {\n\t\t\t\t\tresult += '%';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\tresult += '%' + specifier;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tresult += format[i];\n\t\t}\n\t}\n\n\treturn result;\n}\n","import Semaphore, { AcquireTimeoutError } from './semaphore';\nexport { Semaphore, AcquireTimeoutError };\nexport { PhpWasmError } from './php-wasm-error';\nexport type { SemaphoreOptions } from './semaphore';\nexport {\n\tdirname,\n\tjoinPaths,\n\tbasename,\n\tnormalizePath,\n\tisParentOf,\n\tresolvePathUnder,\n\tensureAbsolutePath,\n\ttoPosixPath,\n} from './paths';\nexport { createSpawnHandler } from './create-spawn-handler';\nexport { phpEventStdinTransfer } from './php-event';\nexport type { PHPEventWithStdinTransfer } from './php-event';\nexport {\n\tsendmailSpawnHandler,\n\tSENDMAIL_CAPTURE_MAX_SIZE,\n} from './spawn-handlers/sendmail';\nexport type { PHPSendmailSpawnedEvent } from './spawn-handlers/sendmail';\nexport { randomString } from './random-string';\nexport { randomFilename } from './random-filename';\nexport { splitShellCommand } from './split-shell-command';\nexport { WritablePolyfill, type WritableOptions } from './writable-polyfill';\nexport { EventEmitterPolyfill } from './event-emitter-polyfill';\nexport * from './php-vars';\n\nexport * from './sprintf';\n\nexport function concatUint8Arrays(arrays: Uint8Array[]): Uint8Array {\n\tlet totalLength = 0;\n\tarrays.forEach((a) => (totalLength += a.length));\n\tconst result = new Uint8Array(totalLength);\n\tlet offset = 0;\n\tarrays.forEach((a) => {\n\t\tresult.set(a, offset);\n\t\toffset += a.length;\n\t});\n\treturn result;\n}\n\nexport function concatArrayBuffers(buffers: ArrayBuffer[]): ArrayBuffer {\n\treturn concatUint8Arrays(buffers.map((b) => new Uint8Array(b)))\n\t\t.buffer as ArrayBuffer;\n}\n"],"names":["SleepFinished","sleep","ms","resolve","AcquireTimeoutError","Semaphore","concurrency","timeout","acquired","released","fn","release","PhpWasmError","message","userFriendlyMessage","joinPaths","paths","hasTrailingSlash","p","path","isAbsolute","trailingSlash","normalizePath","resolvePathUnder","parentPath","normalizedParentPath","resolvedPath","isParentOf","dirname","lastSlash","basename","normalizePathsArray","parts","allowAboveRoot","up","i","last","parent","child","ensureAbsolutePath","toPosixPath","nativePath","result","driveMatch","EventEmitterPolyfill","eventName","data","listener","wrappedListener","args","l","splitShellCommand","command","mode","quote","currentPart","char","WritablePolyfill","opts","chunk","encoding","cb","err","defer","needDrain","enc","entry","createSpawnHandler","program","argsArray","options","childProcess","ChildProcess","processApi","ProcessApi","commandArray","promise","e","code","lastPid","pid","self","phpEventStdinTransfer","SENDMAIL_CAPTURE_MAX_SIZE","sendmailSpawnHandler","php","totalLength","dispatched","exceededMaxSize","streamCancelled","controller","stdinStream","streamController","stdin","finish","randomString","length","specialChars","chars","randomFilename","phpVar","value","stringToBase64","phpVars","vars","key","str","bytesToBase64","bytes","binString","sprintf","format","argIndex","specifier","arg","concatUint8Arrays","arrays","a","offset","concatArrayBuffers","buffers","b"],"mappings":"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"} |
+148
-68
@@ -1,8 +0,8 @@ | ||
| const d = Symbol("SleepFinished"); | ||
| function g(i) { | ||
| const w = Symbol("SleepFinished"); | ||
| function p(i) { | ||
| return new Promise((e) => { | ||
| setTimeout(() => e(d), i); | ||
| setTimeout(() => e(w), i); | ||
| }); | ||
| } | ||
| class p extends Error { | ||
| class E extends Error { | ||
| constructor() { | ||
@@ -12,3 +12,3 @@ super("Acquiring lock timed out"); | ||
| } | ||
| class A { | ||
| class D { | ||
| constructor({ concurrency: e, timeout: t }) { | ||
@@ -32,5 +32,5 @@ this._running = 0, this.concurrency = e, this.timeout = t, this.queue = []; | ||
| t, | ||
| g(this.timeout) | ||
| ]) === d) | ||
| throw this.queue.splice(this.queue.indexOf(r), 1), new p(); | ||
| p(this.timeout) | ||
| ]) === w) | ||
| throw this.queue.splice(this.queue.indexOf(r), 1), new E(); | ||
| } else | ||
@@ -54,3 +54,3 @@ await t; | ||
| } | ||
| class O extends Error { | ||
| class v extends Error { | ||
| constructor(e, t) { | ||
@@ -60,3 +60,3 @@ super(e), this.userFriendlyMessage = t ?? e; | ||
| } | ||
| function w(...i) { | ||
| function m(...i) { | ||
| function e(o) { | ||
@@ -67,21 +67,33 @@ return o.substring(o.length - 1) === "/"; | ||
| const r = t[0] === "/", s = e(t); | ||
| return t = f(t), !t && !r && (t = "."), t && s && !e(t) && (t += "/"), t; | ||
| return t = c(t), !t && !r && (t = "."), t && s && !e(t) && (t += "/"), t; | ||
| } | ||
| function B(i) { | ||
| function I(i, e) { | ||
| if (i.includes("\0") || e.includes("\0")) | ||
| return; | ||
| const t = c(e); | ||
| if (!t) | ||
| return; | ||
| const r = c( | ||
| i.startsWith("/") ? i : m(t, i) | ||
| ); | ||
| if (!(r === t || !P(t, r))) | ||
| return r; | ||
| } | ||
| function z(i) { | ||
| if (i === "/") | ||
| return "/"; | ||
| i = f(i); | ||
| i = c(i); | ||
| const e = i.lastIndexOf("/"); | ||
| return e === -1 ? "" : e === 0 ? "/" : i.substr(0, e); | ||
| } | ||
| function k(i) { | ||
| function W(i) { | ||
| if (i === "/") | ||
| return "/"; | ||
| i = f(i); | ||
| i = c(i); | ||
| const e = i.lastIndexOf("/"); | ||
| return e === -1 ? i : i.substr(e + 1); | ||
| } | ||
| function f(i) { | ||
| function c(i) { | ||
| const e = i[0] === "/"; | ||
| return i = y( | ||
| return i = b( | ||
| i.split("/").filter((t) => !!t), | ||
@@ -91,3 +103,3 @@ !e | ||
| } | ||
| function y(i, e) { | ||
| function b(i, e) { | ||
| let t = 0; | ||
@@ -103,9 +115,9 @@ for (let r = i.length - 1; r >= 0; r--) { | ||
| } | ||
| function q(i, e) { | ||
| return i === "/" ? !0 : (i = f(i), e = f(e), e.startsWith(i + "/") || e === i); | ||
| function P(i, e) { | ||
| return i === "/" ? !0 : (i = c(i), e = c(e), e.startsWith(i + "/") || e === i); | ||
| } | ||
| function U(i) { | ||
| return w("/", f(i || "/")); | ||
| function H(i) { | ||
| return m("/", c(i || "/")); | ||
| } | ||
| function D(i) { | ||
| function N(i) { | ||
| let e = i.replaceAll("\\", "/"); | ||
@@ -115,3 +127,3 @@ const t = e.match(/^([A-Za-z]):\//); | ||
| } | ||
| class a { | ||
| class g { | ||
| constructor() { | ||
@@ -140,3 +152,3 @@ this.listeners = {}; | ||
| } | ||
| function m(i) { | ||
| function x(i) { | ||
| let r = 0, s = ""; | ||
@@ -151,3 +163,3 @@ const o = []; | ||
| } | ||
| class h extends a { | ||
| class h extends g { | ||
| constructor(e) { | ||
@@ -202,5 +214,5 @@ if (super(), this.buffer = [], this.writing = !1, this.ended = !1, this.length = 0, !e.write) | ||
| } | ||
| function I(i) { | ||
| function S(i) { | ||
| return function(e, t = [], r = {}) { | ||
| const s = new P(), o = new b(s); | ||
| const s = new T(), o = new _(s); | ||
| return setTimeout(async () => { | ||
@@ -211,3 +223,3 @@ let n = []; | ||
| else if (typeof e == "string") | ||
| n = m(e); | ||
| n = x(e); | ||
| else if (Array.isArray(e)) | ||
@@ -234,3 +246,3 @@ n = e; | ||
| } | ||
| class b extends a { | ||
| class _ extends g { | ||
| constructor(e) { | ||
@@ -270,5 +282,5 @@ super(), this.exited = !1, this.stdinBuffer = [], this.childProcess = e, e.on("stdin", (t) => { | ||
| } | ||
| let E = 9743; | ||
| class P extends a { | ||
| constructor(e = E++) { | ||
| let M = 9743; | ||
| class T extends g { | ||
| constructor(e = M++) { | ||
| super(), this.pid = e; | ||
@@ -291,3 +303,67 @@ const t = this; | ||
| } | ||
| function x(i = 36, e = "!@#$%^&*()_+=-[]/.,<>?") { | ||
| const O = Symbol.for( | ||
| "@php-wasm/php-event-stdin-transfer" | ||
| ), d = 20 * 1024 * 1024; | ||
| function j(i) { | ||
| return S(async function(e, t) { | ||
| let r = 0, s = !1, o = !1, n = !1, l; | ||
| const u = new ReadableStream({ | ||
| start(a) { | ||
| l = a; | ||
| }, | ||
| cancel() { | ||
| n = !0; | ||
| } | ||
| }); | ||
| t.on("stdin", (a) => { | ||
| if (s || (s = !0, i.dispatchEvent({ | ||
| type: "sendmail.spawned", | ||
| stdin: u, | ||
| [O]: !0 | ||
| })), r += a.length, r > d) { | ||
| o = !0; | ||
| try { | ||
| l.error( | ||
| new Error( | ||
| `sendmail: Message size exceeds fixed maximum message size (${d})` | ||
| ) | ||
| ); | ||
| } catch { | ||
| } | ||
| return; | ||
| } | ||
| n || l.enqueue(a.slice()); | ||
| }); | ||
| const f = t.childProcess.stdin; | ||
| if (f.ended || f.writableEnded || f.writableFinished || await new Promise((a) => { | ||
| if (f.ended || f.writableEnded || f.writableFinished) { | ||
| a(); | ||
| return; | ||
| } | ||
| const y = () => { | ||
| a(); | ||
| }; | ||
| f.once("finish", y); | ||
| }), o) { | ||
| t.stderr( | ||
| `sendmail: Message size exceeds fixed maximum message size (${d}) | ||
| ` | ||
| ), t.exit(1); | ||
| return; | ||
| } | ||
| if (r === 0) { | ||
| t.stderr( | ||
| `sendmail: fatal: No message bytes received over stdin | ||
| ` | ||
| ), t.exit(75); | ||
| return; | ||
| } | ||
| try { | ||
| l.close(); | ||
| } catch { | ||
| } | ||
| t.exit(0); | ||
| }); | ||
| } | ||
| function A(i = 36, e = "!@#$%^&*()_+=-[]/.,<>?") { | ||
| const t = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + e; | ||
@@ -299,24 +375,24 @@ let r = ""; | ||
| } | ||
| function W() { | ||
| return x(36, "-_"); | ||
| function Q() { | ||
| return A(36, "-_"); | ||
| } | ||
| function S(i) { | ||
| return `json_decode(base64_decode('${_( | ||
| function B(i) { | ||
| return `json_decode(base64_decode('${k( | ||
| JSON.stringify(i) | ||
| )}'), true)`; | ||
| } | ||
| function j(i) { | ||
| function F(i) { | ||
| const e = {}; | ||
| for (const t in i) | ||
| e[t] = S(i[t]); | ||
| e[t] = B(i[t]); | ||
| return e; | ||
| } | ||
| function _(i) { | ||
| return T(new TextEncoder().encode(i)); | ||
| function k(i) { | ||
| return q(new TextEncoder().encode(i)); | ||
| } | ||
| function T(i) { | ||
| function q(i) { | ||
| const e = String.fromCodePoint(...i); | ||
| return btoa(e); | ||
| } | ||
| function H(i, ...e) { | ||
| function C(i, ...e) { | ||
| let t = "", r = 0; | ||
@@ -336,3 +412,3 @@ for (let s = 0; s < i.length; s++) | ||
| // Represent bigint values as strings in JSON.stringify(). | ||
| (u, c) => typeof c == "bigint" ? `0x${c.toString(16)}` : c, | ||
| (u, f) => typeof f == "bigint" ? `0x${f.toString(16)}` : f, | ||
| 2 | ||
@@ -373,3 +449,3 @@ ); | ||
| } | ||
| function M(i) { | ||
| function U(i) { | ||
| let e = 0; | ||
@@ -383,28 +459,32 @@ i.forEach((s) => e += s.length); | ||
| } | ||
| function Q(i) { | ||
| return M(i.map((e) => new Uint8Array(e))).buffer; | ||
| function $(i) { | ||
| return U(i.map((e) => new Uint8Array(e))).buffer; | ||
| } | ||
| export { | ||
| p as AcquireTimeoutError, | ||
| a as EventEmitterPolyfill, | ||
| O as PhpWasmError, | ||
| A as Semaphore, | ||
| E as AcquireTimeoutError, | ||
| g as EventEmitterPolyfill, | ||
| v as PhpWasmError, | ||
| d as SENDMAIL_CAPTURE_MAX_SIZE, | ||
| D as Semaphore, | ||
| h as WritablePolyfill, | ||
| k as basename, | ||
| Q as concatArrayBuffers, | ||
| M as concatUint8Arrays, | ||
| I as createSpawnHandler, | ||
| B as dirname, | ||
| U as ensureAbsolutePath, | ||
| q as isParentOf, | ||
| w as joinPaths, | ||
| f as normalizePath, | ||
| S as phpVar, | ||
| j as phpVars, | ||
| W as randomFilename, | ||
| x as randomString, | ||
| m as splitShellCommand, | ||
| H as sprintf, | ||
| D as toPosixPath | ||
| W as basename, | ||
| $ as concatArrayBuffers, | ||
| U as concatUint8Arrays, | ||
| S as createSpawnHandler, | ||
| z as dirname, | ||
| H as ensureAbsolutePath, | ||
| P as isParentOf, | ||
| m as joinPaths, | ||
| c as normalizePath, | ||
| O as phpEventStdinTransfer, | ||
| B as phpVar, | ||
| F as phpVars, | ||
| Q as randomFilename, | ||
| A as randomString, | ||
| I as resolvePathUnder, | ||
| j as sendmailSpawnHandler, | ||
| x as splitShellCommand, | ||
| C as sprintf, | ||
| N as toPosixPath | ||
| }; | ||
| //# sourceMappingURL=index.js.map |
+1
-1
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sources":["../../../../packages/php-wasm/util/src/lib/sleep.ts","../../../../packages/php-wasm/util/src/lib/semaphore.ts","../../../../packages/php-wasm/util/src/lib/php-wasm-error.ts","../../../../packages/php-wasm/util/src/lib/paths.ts","../../../../packages/php-wasm/util/src/lib/event-emitter-polyfill.ts","../../../../packages/php-wasm/util/src/lib/split-shell-command.ts","../../../../packages/php-wasm/util/src/lib/writable-polyfill.ts","../../../../packages/php-wasm/util/src/lib/create-spawn-handler.ts","../../../../packages/php-wasm/util/src/lib/random-string.ts","../../../../packages/php-wasm/util/src/lib/random-filename.ts","../../../../packages/php-wasm/util/src/lib/php-vars.ts","../../../../packages/php-wasm/util/src/lib/sprintf.ts","../../../../packages/php-wasm/util/src/lib/index.ts"],"sourcesContent":["export const SleepFinished = Symbol('SleepFinished');\n\nexport function sleep(ms: number): Promise<typeof SleepFinished> {\n\treturn new Promise((resolve) => {\n\t\tsetTimeout(() => resolve(SleepFinished), ms);\n\t});\n}\n","import { SleepFinished, sleep } from './sleep';\n\nexport interface SemaphoreOptions {\n\t/**\n\t * The maximum number of concurrent locks.\n\t */\n\tconcurrency: number;\n\t/**\n\t * The maximum time to wait for a lock to become available.\n\t */\n\ttimeout?: number;\n}\n\nexport class AcquireTimeoutError extends Error {\n\tconstructor() {\n\t\tsuper('Acquiring lock timed out');\n\t}\n}\n\nexport default class Semaphore {\n\tprivate _running = 0;\n\tprivate concurrency: number;\n\tprivate timeout?: number;\n\tprivate queue: (() => void)[];\n\n\tconstructor({ concurrency, timeout }: SemaphoreOptions) {\n\t\tthis.concurrency = concurrency;\n\t\tthis.timeout = timeout;\n\t\tthis.queue = [];\n\t}\n\n\tget remaining(): number {\n\t\treturn this.concurrency - this.running;\n\t}\n\n\tget running(): number {\n\t\treturn this._running;\n\t}\n\n\tasync acquire(): Promise<() => void> {\n\t\t// Concurrency exhausted - wait in queue for other workers to finish:\n\t\tif (this._running >= this.concurrency) {\n\t\t\t// Create a promise and store its resolver in the queue.\n\t\t\tconst acquired = new Promise<void>((resolve) => {\n\t\t\t\tthis.queue.push(resolve);\n\t\t\t});\n\n\t\t\t// Wait until it is resolved by another worker or a timeout occurs.\n\t\t\tif (this.timeout !== undefined) {\n\t\t\t\t// Store the resolver for cleanup in case of timeout.\n\t\t\t\tconst resolve = this.queue.at(-1)!;\n\t\t\t\tconst result = await Promise.race([\n\t\t\t\t\tacquired,\n\t\t\t\t\tsleep(this.timeout),\n\t\t\t\t]);\n\t\t\t\tif (result === SleepFinished) {\n\t\t\t\t\t// Remove the resolver for the timed out worker from the queue.\n\t\t\t\t\tthis.queue.splice(this.queue.indexOf(resolve), 1);\n\t\t\t\t\tthrow new AcquireTimeoutError();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait acquired;\n\t\t\t}\n\t\t}\n\n\t\t// Acquire the lock:\n\t\tthis._running++;\n\t\tlet released = false;\n\n\t\t// Return a release function:\n\t\treturn () => {\n\t\t\tif (released) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treleased = true;\n\t\t\tthis._running--;\n\n\t\t\t// Release the first item in the queue (call its resolver):\n\t\t\tif (this.queue.length > 0) {\n\t\t\t\tthis.queue.shift()!();\n\t\t\t}\n\t\t};\n\t}\n\n\tasync run<T>(fn: () => T | Promise<T>): Promise<T> {\n\t\tconst release = await this.acquire();\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\trelease();\n\t\t}\n\t}\n}\n","export class PhpWasmError extends Error {\n\tuserFriendlyMessage?: string;\n\tconstructor(message: string, userFriendlyMessage?: string) {\n\t\tsuper(message);\n\t\tthis.userFriendlyMessage = userFriendlyMessage ?? message;\n\t}\n}\n","/**\n * The functions in this module are mostly copied from the generated\n * Emscripten PHP module. This enables features like filesystem journaling,\n * which use some low-level Emscripten APIs and need access to the\n * same path helpers.\n */\n\n/**\n * Joins paths together.\n *\n * For example:\n *\n * > joinPaths('wordpress', 'wp-content')\n * 'wordpress/wp-content'\n *\n * Use this for all PHP paths and **do not** use path.join().\n * This is important because Emscripten paths are **always**\n * POSIX-style paths. Imagine joining paths on Windows:\n *\n * > path.join('wordpress', 'wp-content')\n * '\\\\wordpress\\\\wp-content' // invalid in PHP.wasm\n *\n * See the path.join issue for more details:\n *\n * https://github.com/WordPress/playground-tools/issues/11#issuecomment-1579074763\n *\n * @param paths Paths segments to join\n * @returns A joined path\n */\nexport function joinPaths(...paths: string[]) {\n\tfunction hasTrailingSlash(p: string) {\n\t\treturn p.substring(p.length - 1) === '/';\n\t}\n\n\tlet path = paths.join('/');\n\tconst isAbsolute = path[0] === '/';\n\tconst trailingSlash = hasTrailingSlash(path);\n\tpath = normalizePath(path);\n\tif (!path && !isAbsolute) {\n\t\tpath = '.';\n\t}\n\tif (path && trailingSlash && !hasTrailingSlash(path)) {\n\t\tpath += '/';\n\t}\n\treturn path;\n}\n\n/**\n * Returns the directory name of a path.\n *\n * @param path\n * @returns\n */\nexport function dirname(path: string) {\n\tif (path === '/') {\n\t\treturn '/';\n\t}\n\n\tpath = normalizePath(path);\n\n\tconst lastSlash = path.lastIndexOf('/');\n\tif (lastSlash === -1) {\n\t\treturn '';\n\t} else if (lastSlash === 0) {\n\t\treturn '/';\n\t}\n\treturn path.substr(0, lastSlash);\n}\n\n/**\n * Returns the last portion of a path.\n *\n * @param path - The path to extract the basename from.\n * @returns The basename of the path.\n */\nexport function basename(path: string) {\n\tif (path === '/') {\n\t\treturn '/';\n\t}\n\n\tpath = normalizePath(path);\n\n\tconst lastSlash = path.lastIndexOf('/');\n\tif (lastSlash === -1) {\n\t\treturn path;\n\t}\n\treturn path.substr(lastSlash + 1);\n}\n\n/**\n * Normalizes a path.\n *\n * For example:\n *\n * > normalizePath('wordpress/wp-content/../')\n * 'wordpress'\n *\n * @param path\n * @returns\n */\nexport function normalizePath(path: string) {\n\tconst isAbsolute = path[0] === '/';\n\tpath = normalizePathsArray(\n\t\tpath.split('/').filter((p: any) => !!p),\n\t\t!isAbsolute\n\t).join('/');\n\treturn (isAbsolute ? '/' : '') + path.replace(/\\/$/, '');\n}\n\n/**\n * Normalizes paths.\n *\n * For example:\n *\n * > normalizePathsArray(['wordpress', 'wp-content', '..', '', '.',\n * 'wp-includes']) ['wordpress', 'wp-includes']\n *\n * @param parts parts of the path to normalize\n * @param allowAboveRoot allow paths above the root\n * @returns normalized paths\n */\nexport function normalizePathsArray(parts: string[], allowAboveRoot: boolean) {\n\tlet up = 0;\n\tfor (let i = parts.length - 1; i >= 0; i--) {\n\t\tconst last = parts[i];\n\t\tif (last === '.') {\n\t\t\tparts.splice(i, 1);\n\t\t} else if (last === '..') {\n\t\t\tparts.splice(i, 1);\n\t\t\tup++;\n\t\t} else if (up) {\n\t\t\tparts.splice(i, 1);\n\t\t\tup--;\n\t\t}\n\t}\n\tif (allowAboveRoot) {\n\t\tfor (; up; up--) {\n\t\t\tparts.unshift('..');\n\t\t}\n\t}\n\treturn parts;\n}\n\n/**\n * Checks if the given parent path is an ancestor of the given child path.\n *\n * @param parent The parent path to check.\n * @param child The child path to verify against the parent.\n * @returns Whether the `parent` path is an ancestor of the `child` path.\n */\nexport function isParentOf(parent: string, child: string) {\n\tif (parent === '/') {\n\t\treturn true;\n\t}\n\tparent = normalizePath(parent);\n\tchild = normalizePath(child);\n\treturn child.startsWith(parent + '/') || child === parent;\n}\n\n/**\n * Guarantees a path is absolute by prepending `/` if needed.\n *\n * Useful when working with user-provided paths that might be relative,\n * or when you need to normalize edge cases like empty strings.\n *\n * For example:\n *\n * > ensureAbsolutePath('wp-content/uploads')\n * '/wp-content/uploads'\n *\n * > ensureAbsolutePath('/already/absolute')\n * '/already/absolute'\n *\n * > ensureAbsolutePath('')\n * '/'\n *\n * @param path - The path to make absolute.\n * @returns An absolute, normalized path starting with `/`.\n */\nexport function ensureAbsolutePath(path: string) {\n\treturn joinPaths('/', normalizePath(path || '/'));\n}\n\n/**\n * Converts a native OS path to a POSIX-style path.\n *\n * Transformations:\n * 1. Backslashes → forward slashes\n * 2. Windows drive letter `C:\\` → `/C/` (colons are invalid in\n * Emscripten VFS paths and cause ENOTDIR errno 28)\n *\n * On POSIX systems this is effectively a no-op.\n *\n * @see https://github.com/emscripten-core/emscripten/issues/17829\n */\nexport function toPosixPath(nativePath: string): string {\n\tlet result = nativePath.replaceAll('\\\\', '/');\n\t// Handle Windows drive letter: C:/ → /C/\n\tconst driveMatch = result.match(/^([A-Za-z]):\\//);\n\tif (driveMatch) {\n\t\tresult = '/' + driveMatch[1] + result.slice(2);\n\t}\n\treturn result;\n}\n","/**\n * Polyfills Node.js EventEmitter API. The main goal is to enable\n * using a child_process.spawn()-like API in both Node.js and the browser.\n *\n * @see https://nodejs.org/api/events.html#events_class_eventemitter\n */\ntype Listener = (...args: any[]) => any;\n\nexport class EventEmitterPolyfill {\n\tlisteners: Record<string, Listener[]> = {};\n\temit(eventName: string, data?: any) {\n\t\tif (this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName].forEach(function (listener) {\n\t\t\t\tlistener(data);\n\t\t\t});\n\t\t}\n\t}\n\ton(eventName: string, listener: Listener) {\n\t\tif (!this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName] = [];\n\t\t}\n\t\tthis.listeners[eventName].push(listener);\n\t}\n\tonce(eventName: string, listener: Listener) {\n\t\tconst wrappedListener = (...args: any[]) => {\n\t\t\tthis.off(eventName, wrappedListener);\n\t\t\tlistener(...args);\n\t\t};\n\t\tthis.on(eventName, wrappedListener);\n\t}\n\toff(eventName: string, listener: Listener) {\n\t\tif (this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName] = this.listeners[eventName].filter(\n\t\t\t\t(l) => l !== listener\n\t\t\t);\n\t\t}\n\t}\n}\n","/**\n * Naive shell command parser.\n * Ensures that commands like `wp option set blogname \"My blog name\"` are split\n * into `['wp', 'option', 'set', 'blogname', 'My blog name']` instead of\n * `['wp', 'option', 'set', 'blogname', 'My', 'blog', 'name']`.\n *\n * @param command\n * @returns\n */\nexport function splitShellCommand(command: string) {\n\tconst MODE_UNQUOTED = 0;\n\tconst MODE_IN_QUOTE = 1;\n\n\tlet mode = MODE_UNQUOTED;\n\tlet quote = '';\n\n\tconst parts: string[] = [];\n\tlet currentPart = '';\n\tfor (let i = 0; i < command.length; i++) {\n\t\tconst char = command[i];\n\t\tif (char === '\\\\') {\n\t\t\t// Escaped quotes are treated as normal characters\n\t\t\t// This is a very naive approach to escaping, but it's good enough for\n\t\t\t// now. @TODO: Iterate on this later, perhaps using bun shell. @see https://github.com/WordPress/wordpress-playground/issues/1062\n\t\t\tif (command[i + 1] === '\"' || command[i + 1] === \"'\") {\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tcurrentPart += command[i];\n\t\t} else if (mode === MODE_UNQUOTED) {\n\t\t\tif (char === '\"' || char === \"'\") {\n\t\t\t\tmode = MODE_IN_QUOTE;\n\t\t\t\tquote = char;\n\t\t\t} else if (char.match(/\\s/)) {\n\t\t\t\tif (currentPart.trim().length) {\n\t\t\t\t\tparts.push(currentPart.trim());\n\t\t\t\t}\n\t\t\t\tcurrentPart = char;\n\t\t\t} else if (parts.length && !currentPart) {\n\t\t\t\t// We just closed a quote to continue the same\n\t\t\t\t// argument with different escaping style, e.g.:\n\t\t\t\t// php -r 'require '\\''vendor/autoload.php'\\''\n\t\t\t\tcurrentPart = parts.pop()! + char;\n\t\t\t} else {\n\t\t\t\tcurrentPart += char;\n\t\t\t}\n\t\t} else if (mode === MODE_IN_QUOTE) {\n\t\t\tif (char === quote) {\n\t\t\t\tmode = MODE_UNQUOTED;\n\t\t\t\tquote = '';\n\t\t\t} else {\n\t\t\t\tcurrentPart += char;\n\t\t\t}\n\t\t}\n\t}\n\tif (currentPart) {\n\t\tparts.push(currentPart.trim());\n\t}\n\treturn parts;\n}\n","/**\n * Polyfills Node.js WritableStream API. The main goal is to enable\n * using a child_process.spawn()-like API in both Node.js and the browser.\n *\n * @see https://nodejs.org/api/stream.html#stream_writable_end_chunk_encoding_callback\n */\nimport { EventEmitterPolyfill } from './event-emitter-polyfill';\n\nexport interface WritableOptions {\n\thighWaterMark?: number;\n\tdecodeStrings?: boolean;\n\tdefaultEncoding?: BufferEncoding;\n\twrite: (chunk: any, encoding: BufferEncoding, cb: WriteCallback) => void;\n}\n\nexport type WriteCallback = (error?: Error | null) => void;\n\nexport class WritablePolyfill extends EventEmitterPolyfill {\n\tprivate buffer: Array<{\n\t\tchunk: any;\n\t\tencoding: BufferEncoding;\n\t\tcb: WriteCallback;\n\t}> = [];\n\tprivate writing = false;\n\tpublic ended = false;\n\tprivate length = 0;\n\tprivate highWaterMark: number;\n\tprivate decodeStrings: boolean;\n\tprivate defaultEncoding: BufferEncoding;\n\tprivate defer: (fn: () => void) => void;\n\tprivate _write: (\n\t\tchunk: any,\n\t\tencoding: BufferEncoding,\n\t\tcb: WriteCallback\n\t) => void;\n\n\tconstructor(opts: WritableOptions) {\n\t\tsuper();\n\t\tif (!opts.write) {\n\t\t\tthrow new Error('WritablePolyfill requires write option');\n\t\t}\n\t\tthis._write = opts.write;\n\t\tthis.highWaterMark = opts.highWaterMark ?? 16 * 1024;\n\t\tthis.decodeStrings = opts.decodeStrings ?? true;\n\t\tthis.defaultEncoding = opts.defaultEncoding ?? 'utf8';\n\t\t// queueMicrotask keeps browser support; fallback for older environments.\n\t\tthis.defer =\n\t\t\ttypeof queueMicrotask === 'function'\n\t\t\t\t? queueMicrotask\n\t\t\t\t: (fn) => setTimeout(fn, 0);\n\t}\n\n\twrite(\n\t\tchunk: any,\n\t\tencoding: BufferEncoding | WriteCallback = this.defaultEncoding,\n\t\tcb: WriteCallback = () => {}\n\t): boolean {\n\t\tif (typeof encoding === 'function') {\n\t\t\tcb = encoding as WriteCallback;\n\t\t\tencoding = this.defaultEncoding;\n\t\t}\n\n\t\tif (this.ended) {\n\t\t\tconst err = new Error('write after end');\n\t\t\t// We can't call this.defer() directly. If this.defer is\n\t\t\t// `queueMicrotask`, a `this.defer()` call will pass the\n\t\t\t// WritablePolyfill instance as `this` argument and cause\n\t\t\t// the browser to throw an error similar to \"Invalid\n\t\t\t// invocation\".\n\t\t\tconst defer = this.defer;\n\t\t\tdefer(() => cb(err));\n\t\t\tthis.emit('error', err);\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this.decodeStrings && typeof chunk === 'string') {\n\t\t\tif (\n\t\t\t\ttypeof Buffer !== 'undefined' &&\n\t\t\t\ttypeof (Buffer as any).from === 'function'\n\t\t\t) {\n\t\t\t\tchunk = Buffer.from(chunk, encoding as BufferEncoding);\n\t\t\t} else if (typeof TextEncoder !== 'undefined') {\n\t\t\t\tchunk = new TextEncoder().encode(chunk);\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'String chunks are not supported in this environment: Buffer and TextEncoder are unavailable.'\n\t\t\t\t);\n\t\t\t}\n\t\t\tencoding = 'buffer' as BufferEncoding;\n\t\t}\n\n\t\tthis.length += chunk.length ?? 1;\n\t\tconst needDrain = this.length >= this.highWaterMark;\n\n\t\tthis.buffer.push({ chunk, encoding: encoding as BufferEncoding, cb });\n\n\t\tif (!this.writing) this._clearBuffer();\n\n\t\treturn !needDrain;\n\t}\n\n\tend(\n\t\tchunk?: any,\n\t\tencoding?: BufferEncoding | WriteCallback,\n\t\tcb?: WriteCallback\n\t): void {\n\t\tif (typeof chunk === 'function') {\n\t\t\tcb = chunk;\n\t\t\tchunk = undefined;\n\t\t} else if (typeof encoding === 'function') {\n\t\t\tcb = encoding as WriteCallback;\n\t\t\tencoding = undefined;\n\t\t}\n\n\t\tif (chunk !== undefined)\n\t\t\tthis.write(chunk, encoding as BufferEncoding, () => {});\n\t\tthis.ended = true;\n\t\tif (!this.writing) this._clearBuffer();\n\t\tif (cb) this.defer(cb);\n\t}\n\n\t// Stubs kept for API parity; add logic if you depend on corking.\n\tcork(): void {}\n\tuncork(): void {}\n\n\tsetDefaultEncoding(enc: BufferEncoding): this {\n\t\tthis.defaultEncoding = enc;\n\t\treturn this;\n\t}\n\n\tprivate _clearBuffer(): void {\n\t\tconst entry = this.buffer.shift();\n\t\tif (!entry) {\n\t\t\tif (this.ended) this.emit('finish');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.writing = true;\n\t\tthis._write(entry.chunk, entry.encoding, (err?: Error | null) => {\n\t\t\tthis.writing = false;\n\t\t\tthis.length -= entry.chunk.length ?? 1;\n\t\t\tif (err) this.emit('error', err);\n\t\t\tentry.cb(err);\n\n\t\t\tif (this.buffer.length) {\n\t\t\t\tthis._clearBuffer();\n\t\t\t} else {\n\t\t\t\tif (this.length < this.highWaterMark) this.emit('drain');\n\t\t\t\tif (this.ended) this.emit('finish');\n\t\t\t}\n\t\t});\n\t}\n}\n","import { EventEmitterPolyfill } from './event-emitter-polyfill';\nimport { splitShellCommand } from './split-shell-command';\nimport { WritablePolyfill, type WriteCallback } from './writable-polyfill';\n\ntype Listener = (...args: any[]) => any;\n\nexport interface ProcessOptions {\n\tcwd?: string;\n\tenv?: Record<string, string>;\n}\n\n/**\n * Usage:\n * ```ts\n * php.setSpawnHandler(\n * createSpawnHandler(function (command, processApi) {\n * console.log(processApi.flushStdin());\n * processApi.stdout('/\\n/tmp\\n/home');\n *\t processApi.exit(0);\n * })\n * );\n * ```\n * @param program\n * @returns\n */\nexport function createSpawnHandler(\n\tprogram: (\n\t\tcommand: string[],\n\t\tprocessApi: ProcessApi,\n\t\toptions: ProcessOptions\n\t) => void | Promise<void>\n): any {\n\treturn function (\n\t\tcommand: string | string[],\n\t\targsArray: string[] = [],\n\t\toptions: ProcessOptions = {}\n\t) {\n\t\tconst childProcess = new ChildProcess();\n\t\tconst processApi = new ProcessApi(childProcess);\n\t\t// Give PHP a chance to register listeners\n\t\tsetTimeout(async () => {\n\t\t\tlet commandArray = [];\n\t\t\tif (argsArray.length) {\n\t\t\t\tcommandArray = [command as string, ...argsArray];\n\t\t\t} else if (typeof command === 'string') {\n\t\t\t\tcommandArray = splitShellCommand(command);\n\t\t\t} else if (Array.isArray(command)) {\n\t\t\t\tcommandArray = command;\n\t\t\t} else {\n\t\t\t\tthrow new Error('Invalid command ', command);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst promise = program(commandArray, processApi, options);\n\t\t\t\tif (\n\t\t\t\t\ttypeof promise !== 'object' ||\n\t\t\t\t\tpromise === null ||\n\t\t\t\t\t!('then' in promise)\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`The program callback passed to createSpawnHandler() did not return a promise. It indicates there's a bug in your code. ` +\n\t\t\t\t\t\t\t`The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() ` +\n\t\t\t\t\t\t\t`call. All the streams would be closed already. Make sure to put an \"await new Promise(resolve => setTimeout(resolve, 1))` +\n\t\t\t\t\t\t\t`before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`\n\t\t\t\t\t);\n\t\t\t\t} else if (processApi.exited) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`The program callback passed to createSpawnHandler() exited synchronously. It indicates there's a bug in your code. ` +\n\t\t\t\t\t\t\t`The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() ` +\n\t\t\t\t\t\t\t`call. All the streams would be closed already. Make sure to put an \"await new Promise(resolve => setTimeout(resolve, 1))` +\n\t\t\t\t\t\t\t`before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tchildProcess.emit('spawn', true);\n\t\t\t\tawait promise;\n\t\t\t} catch (e) {\n\t\t\t\tchildProcess.emit('error', e);\n\t\t\t\tif (\n\t\t\t\t\ttypeof e === 'object' &&\n\t\t\t\t\te !== null &&\n\t\t\t\t\t'message' in e &&\n\t\t\t\t\ttypeof e.message === 'string'\n\t\t\t\t) {\n\t\t\t\t\tprocessApi.stderr(e.message);\n\t\t\t\t}\n\t\t\t\tprocessApi.exit(1);\n\t\t\t}\n\t\t});\n\t\treturn childProcess;\n\t};\n}\n\nexport class ProcessApi extends EventEmitterPolyfill {\n\tpublic exited = false;\n\t/**\n\t * Keeps track of the data that was written to stdin before the\n\t * first listener was registered.\n\t */\n\tprivate stdinBuffer: Uint8Array[] | null = [];\n\tpublic childProcess: ChildProcess;\n\tconstructor(childProcess: ChildProcess) {\n\t\tsuper();\n\t\tthis.childProcess = childProcess;\n\t\tchildProcess.on('stdin', (data: Uint8Array) => {\n\t\t\tif (this.stdinBuffer) {\n\t\t\t\t// Need to clone the data buffer as it's reused by PHP\n\t\t\t\t// and the next data chunk will overwrite the previous one.\n\t\t\t\tthis.stdinBuffer.push(data.slice());\n\t\t\t} else {\n\t\t\t\tthis.emit('stdin', data);\n\t\t\t}\n\t\t});\n\t}\n\tstdinEnd() {\n\t\tif (!this.childProcess.stdin.ended) {\n\t\t\tthis.childProcess.stdin.end();\n\t\t}\n\t}\n\tstdout(data: string | ArrayBuffer) {\n\t\tthis.childProcess.stdout.write(data);\n\t}\n\tstdoutEnd() {\n\t\tif (!this.childProcess.stdout.ended) {\n\t\t\tthis.childProcess.stdout.end();\n\t\t}\n\t}\n\tstderr(data: string | ArrayBuffer) {\n\t\tthis.childProcess.stderr.write(data);\n\t}\n\tstderrEnd() {\n\t\tif (!this.childProcess.stderr.ended) {\n\t\t\tthis.childProcess.stderr.end();\n\t\t}\n\t}\n\tnotifySpawn() {\n\t\tthis.childProcess.emit('spawn', true);\n\t}\n\texit(code: number) {\n\t\tif (!this.exited) {\n\t\t\tthis.exited = true;\n\t\t\tthis.stdinEnd();\n\t\t\tthis.stdoutEnd();\n\t\t\tthis.stderrEnd();\n\t\t\tthis.childProcess.emit('exit', code);\n\t\t}\n\t}\n\toverride on(eventName: string, listener: Listener) {\n\t\tsuper.on(eventName, listener);\n\t\t/**\n\t\t * If it's the first stdin listener, flush all the data we've\n\t\t * buffered so far.\n\t\t */\n\t\tif (eventName === 'stdin' && this.stdinBuffer) {\n\t\t\tfor (let i = 0; i < this.stdinBuffer.length; i++) {\n\t\t\t\tthis.emit('stdin', this.stdinBuffer[i]);\n\t\t\t}\n\t\t\tthis.stdinBuffer = null;\n\t\t}\n\t}\n}\n\nlet lastPid = 9743;\nexport class ChildProcess extends EventEmitterPolyfill {\n\tstdout: WritablePolyfill;\n\tstderr: WritablePolyfill;\n\tstdin: WritablePolyfill;\n\tpid: number;\n\tconstructor(pid = lastPid++) {\n\t\tsuper();\n\t\tthis.pid = pid;\n\t\t// eslint-disable-next-line @typescript-eslint/no-this-alias\n\t\tconst self = this;\n\t\tthis.stdout = new WritablePolyfill({\n\t\t\twrite(data: any, encoding: BufferEncoding, cb: WriteCallback) {\n\t\t\t\tself.stdout.emit('data', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t\tthis.stderr = new WritablePolyfill({\n\t\t\twrite: (data: any, encoding: BufferEncoding, cb: WriteCallback) => {\n\t\t\t\tself.stderr.emit('data', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t\tthis.stdin = new WritablePolyfill({\n\t\t\twrite: (data: any, encoding: BufferEncoding, cb: WriteCallback) => {\n\t\t\t\tself.emit('stdin', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t}\n}\n","export function randomString(\n\tlength = 36,\n\tspecialChars = '!@#$%^&*()_+=-[]/.,<>?'\n) {\n\tconst chars =\n\t\t'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' +\n\t\tspecialChars;\n\tlet result = '';\n\tfor (let i = length; i > 0; --i)\n\t\tresult += chars[Math.floor(Math.random() * chars.length)];\n\treturn result;\n}\n","import { randomString } from './random-string';\n\nexport function randomFilename() {\n\treturn randomString(36, '-_');\n}\n","export function phpVar(value: unknown): string {\n\treturn `json_decode(base64_decode('${stringToBase64(\n\t\tJSON.stringify(value)\n\t)}'), true)`;\n}\n\nexport function phpVars<T extends Record<string, unknown>>(\n\tvars: T\n): Record<keyof T, string> {\n\tconst result: Record<string, string> = {};\n\tfor (const key in vars) {\n\t\tresult[key] = phpVar(vars[key]);\n\t}\n\treturn result as Record<keyof T, string>;\n}\n\nfunction stringToBase64(str: string) {\n\treturn bytesToBase64(new TextEncoder().encode(str));\n}\n\nfunction bytesToBase64(bytes: Uint8Array) {\n\tconst binString = String.fromCodePoint(...bytes);\n\treturn btoa(binString);\n}\n","/**\n * Formats a string like sprintf().\n *\n * This function:\n * - Supports basic format specifiers: %s, %d, %f, %x, %%\n * - Supports bigint values\n *\n * The purpose of this function is for use in optional php-wasm tracing.\n * If we use printf-style formatting for trace messages, we let the trace\n * function decide whether to format and do not have to pay for formatting\n * unless tracing is enabled.\n */\nexport function sprintf(format: string, ...args: any[]): string {\n\tlet result = '';\n\tlet argIndex = 0;\n\n\tfor (let i = 0; i < format.length; i++) {\n\t\tif (format[i] === '%' && i + 1 < format.length) {\n\t\t\ti++;\n\t\t\tconst specifier = format[i];\n\n\t\t\tswitch (specifier) {\n\t\t\t\tcase 's': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tlet str;\n\t\t\t\t\tif (typeof arg === 'object') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// If an object doesn't provide its own toString(),\n\t\t\t\t\t\t\t// try to represent it as JSON.\n\t\t\t\t\t\t\tstr = JSON.stringify(\n\t\t\t\t\t\t\t\targ,\n\t\t\t\t\t\t\t\t// Represent bigint values as strings in JSON.stringify().\n\t\t\t\t\t\t\t\t(key, value) => {\n\t\t\t\t\t\t\t\t\tif (typeof value === 'bigint') {\n\t\t\t\t\t\t\t\t\t\treturn `0x${value.toString(16)}`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Ignore error and use default representation.\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstr = String(arg);\n\t\t\t\t\t}\n\n\t\t\t\t\tresult += str;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'd': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += arg.toString();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Math.floor(Number(arg));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'f': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += Number(arg);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Number(arg);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'x': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += arg.toString(16);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Math.floor(Number(arg)).toString(16);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase '%': {\n\t\t\t\t\tresult += '%';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\tresult += '%' + specifier;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tresult += format[i];\n\t\t}\n\t}\n\n\treturn result;\n}\n","import Semaphore, { AcquireTimeoutError } from './semaphore';\nexport { Semaphore, AcquireTimeoutError };\nexport { PhpWasmError } from './php-wasm-error';\nexport type { SemaphoreOptions } from './semaphore';\nexport {\n\tdirname,\n\tjoinPaths,\n\tbasename,\n\tnormalizePath,\n\tisParentOf,\n\tensureAbsolutePath,\n\ttoPosixPath,\n} from './paths';\nexport { createSpawnHandler } from './create-spawn-handler';\nexport { randomString } from './random-string';\nexport { randomFilename } from './random-filename';\nexport { splitShellCommand } from './split-shell-command';\nexport { WritablePolyfill, type WritableOptions } from './writable-polyfill';\nexport { EventEmitterPolyfill } from './event-emitter-polyfill';\nexport * from './php-vars';\n\nexport * from './sprintf';\n\nexport function concatUint8Arrays(arrays: Uint8Array[]): Uint8Array {\n\tlet totalLength = 0;\n\tarrays.forEach((a) => (totalLength += a.length));\n\tconst result = new Uint8Array(totalLength);\n\tlet offset = 0;\n\tarrays.forEach((a) => {\n\t\tresult.set(a, offset);\n\t\toffset += a.length;\n\t});\n\treturn result;\n}\n\nexport function concatArrayBuffers(buffers: ArrayBuffer[]): ArrayBuffer {\n\treturn concatUint8Arrays(buffers.map((b) => new Uint8Array(b)))\n\t\t.buffer as ArrayBuffer;\n}\n"],"names":["SleepFinished","sleep","ms","resolve","AcquireTimeoutError","Semaphore","concurrency","timeout","acquired","released","fn","release","PhpWasmError","message","userFriendlyMessage","joinPaths","paths","hasTrailingSlash","p","path","isAbsolute","trailingSlash","normalizePath","dirname","lastSlash","basename","normalizePathsArray","parts","allowAboveRoot","up","i","last","isParentOf","parent","child","ensureAbsolutePath","toPosixPath","nativePath","result","driveMatch","EventEmitterPolyfill","eventName","data","listener","wrappedListener","args","l","splitShellCommand","command","mode","quote","currentPart","char","WritablePolyfill","opts","chunk","encoding","cb","err","defer","needDrain","enc","entry","createSpawnHandler","program","argsArray","options","childProcess","ChildProcess","processApi","ProcessApi","commandArray","promise","e","code","lastPid","pid","self","randomString","length","specialChars","chars","randomFilename","phpVar","value","stringToBase64","phpVars","vars","key","str","bytesToBase64","bytes","binString","sprintf","format","argIndex","specifier","arg","concatUint8Arrays","arrays","totalLength","a","offset","concatArrayBuffers","buffers","b"],"mappings":"AAAO,MAAMA,IAAgB,OAAO,eAAe;AAE5C,SAASC,EAAMC,GAA2C;AAChE,SAAO,IAAI,QAAQ,CAACC,MAAY;AAC/B,eAAW,MAAMA,EAAQH,CAAa,GAAGE,CAAE;AAAA,EAC5C,CAAC;AACF;ACOO,MAAME,UAA4B,MAAM;AAAA,EAC9C,cAAc;AACb,UAAM,0BAA0B;AAAA,EACjC;AACD;AAEA,MAAqBC,EAAU;AAAA,EAM9B,YAAY,EAAE,aAAAC,GAAa,SAAAC,KAA6B;AALxD,SAAQ,WAAW,GAMlB,KAAK,cAAcD,GACnB,KAAK,UAAUC,GACf,KAAK,QAAQ,CAAA;AAAA,EACd;AAAA,EAEA,IAAI,YAAoB;AACvB,WAAO,KAAK,cAAc,KAAK;AAAA,EAChC;AAAA,EAEA,IAAI,UAAkB;AACrB,WAAO,KAAK;AAAA,EACb;AAAA,EAEA,MAAM,UAA+B;AAEpC,QAAI,KAAK,YAAY,KAAK,aAAa;AAEtC,YAAMC,IAAW,IAAI,QAAc,CAACL,MAAY;AAC/C,aAAK,MAAM,KAAKA,CAAO;AAAA,MACxB,CAAC;AAGD,UAAI,KAAK,YAAY,QAAW;AAE/B,cAAMA,IAAU,KAAK,MAAM,GAAG,EAAE;AAKhC,YAJe,MAAM,QAAQ,KAAK;AAAA,UACjCK;AAAA,UACAP,EAAM,KAAK,OAAO;AAAA,QAAA,CAClB,MACcD;AAEd,qBAAK,MAAM,OAAO,KAAK,MAAM,QAAQG,CAAO,GAAG,CAAC,GAC1C,IAAIC,EAAA;AAAA,MAEZ;AACC,cAAMI;AAAA,IAER;AAGA,SAAK;AACL,QAAIC,IAAW;AAGf,WAAO,MAAM;AACZ,MAAIA,MAGJA,IAAW,IACX,KAAK,YAGD,KAAK,MAAM,SAAS,KACvB,KAAK,MAAM,QAAM;AAAA,IAEnB;AAAA,EACD;AAAA,EAEA,MAAM,IAAOC,GAAsC;AAClD,UAAMC,IAAU,MAAM,KAAK,QAAA;AAC3B,QAAI;AACH,aAAO,MAAMD,EAAA;AAAA,IACd,UAAA;AACC,MAAAC,EAAA;AAAA,IACD;AAAA,EACD;AACD;AC5FO,MAAMC,UAAqB,MAAM;AAAA,EAEvC,YAAYC,GAAiBC,GAA8B;AAC1D,UAAMD,CAAO,GACb,KAAK,sBAAsBC,KAAuBD;AAAA,EACnD;AACD;ACuBO,SAASE,KAAaC,GAAiB;AAC7C,WAASC,EAAiBC,GAAW;AACpC,WAAOA,EAAE,UAAUA,EAAE,SAAS,CAAC,MAAM;AAAA,EACtC;AAEA,MAAIC,IAAOH,EAAM,KAAK,GAAG;AACzB,QAAMI,IAAaD,EAAK,CAAC,MAAM,KACzBE,IAAgBJ,EAAiBE,CAAI;AAC3C,SAAAA,IAAOG,EAAcH,CAAI,GACrB,CAACA,KAAQ,CAACC,MACbD,IAAO,MAEJA,KAAQE,KAAiB,CAACJ,EAAiBE,CAAI,MAClDA,KAAQ,MAEFA;AACR;AAQO,SAASI,EAAQJ,GAAc;AACrC,MAAIA,MAAS;AACZ,WAAO;AAGR,EAAAA,IAAOG,EAAcH,CAAI;AAEzB,QAAMK,IAAYL,EAAK,YAAY,GAAG;AACtC,SAAIK,MAAc,KACV,KACGA,MAAc,IACjB,MAEDL,EAAK,OAAO,GAAGK,CAAS;AAChC;AAQO,SAASC,EAASN,GAAc;AACtC,MAAIA,MAAS;AACZ,WAAO;AAGR,EAAAA,IAAOG,EAAcH,CAAI;AAEzB,QAAMK,IAAYL,EAAK,YAAY,GAAG;AACtC,SAAIK,MAAc,KACVL,IAEDA,EAAK,OAAOK,IAAY,CAAC;AACjC;AAaO,SAASF,EAAcH,GAAc;AAC3C,QAAMC,IAAaD,EAAK,CAAC,MAAM;AAC/B,SAAAA,IAAOO;AAAA,IACNP,EAAK,MAAM,GAAG,EAAE,OAAO,CAACD,MAAW,CAAC,CAACA,CAAC;AAAA,IACtC,CAACE;AAAA,EAAA,EACA,KAAK,GAAG,IACFA,IAAa,MAAM,MAAMD,EAAK,QAAQ,OAAO,EAAE;AACxD;AAcO,SAASO,EAAoBC,GAAiBC,GAAyB;AAC7E,MAAIC,IAAK;AACT,WAASC,IAAIH,EAAM,SAAS,GAAGG,KAAK,GAAGA,KAAK;AAC3C,UAAMC,IAAOJ,EAAMG,CAAC;AACpB,IAAIC,MAAS,MACZJ,EAAM,OAAOG,GAAG,CAAC,IACPC,MAAS,QACnBJ,EAAM,OAAOG,GAAG,CAAC,GACjBD,OACUA,MACVF,EAAM,OAAOG,GAAG,CAAC,GACjBD;AAAA,EAEF;AACA,MAAID;AACH,WAAOC,GAAIA;AACV,MAAAF,EAAM,QAAQ,IAAI;AAGpB,SAAOA;AACR;AASO,SAASK,EAAWC,GAAgBC,GAAe;AACzD,SAAID,MAAW,MACP,MAERA,IAASX,EAAcW,CAAM,GAC7BC,IAAQZ,EAAcY,CAAK,GACpBA,EAAM,WAAWD,IAAS,GAAG,KAAKC,MAAUD;AACpD;AAsBO,SAASE,EAAmBhB,GAAc;AAChD,SAAOJ,EAAU,KAAKO,EAAcH,KAAQ,GAAG,CAAC;AACjD;AAcO,SAASiB,EAAYC,GAA4B;AACvD,MAAIC,IAASD,EAAW,WAAW,MAAM,GAAG;AAE5C,QAAME,IAAaD,EAAO,MAAM,gBAAgB;AAChD,SAAIC,MACHD,IAAS,MAAMC,EAAW,CAAC,IAAID,EAAO,MAAM,CAAC,IAEvCA;AACR;ACnMO,MAAME,EAAqB;AAAA,EAA3B,cAAA;AACN,SAAA,YAAwC,CAAA;AAAA,EAAC;AAAA,EACzC,KAAKC,GAAmBC,GAAY;AACnC,IAAI,KAAK,UAAUD,CAAS,KAC3B,KAAK,UAAUA,CAAS,EAAE,QAAQ,SAAUE,GAAU;AACrD,MAAAA,EAASD,CAAI;AAAA,IACd,CAAC;AAAA,EAEH;AAAA,EACA,GAAGD,GAAmBE,GAAoB;AACzC,IAAK,KAAK,UAAUF,CAAS,MAC5B,KAAK,UAAUA,CAAS,IAAI,CAAA,IAE7B,KAAK,UAAUA,CAAS,EAAE,KAAKE,CAAQ;AAAA,EACxC;AAAA,EACA,KAAKF,GAAmBE,GAAoB;AAC3C,UAAMC,IAAkB,IAAIC,MAAgB;AAC3C,WAAK,IAAIJ,GAAWG,CAAe,GACnCD,EAAS,GAAGE,CAAI;AAAA,IACjB;AACA,SAAK,GAAGJ,GAAWG,CAAe;AAAA,EACnC;AAAA,EACA,IAAIH,GAAmBE,GAAoB;AAC1C,IAAI,KAAK,UAAUF,CAAS,MAC3B,KAAK,UAAUA,CAAS,IAAI,KAAK,UAAUA,CAAS,EAAE;AAAA,MACrD,CAACK,MAAMA,MAAMH;AAAA,IAAA;AAAA,EAGhB;AACD;AC5BO,SAASI,EAAkBC,GAAiB;AAIlD,MAAIC,IAAO,GACPC,IAAQ;AAEZ,QAAMvB,IAAkB,CAAA;AACxB,MAAIwB,IAAc;AAClB,WAASrB,IAAI,GAAGA,IAAIkB,EAAQ,QAAQlB,KAAK;AACxC,UAAMsB,IAAOJ,EAAQlB,CAAC;AACtB,IAAIsB,MAAS,SAIRJ,EAAQlB,IAAI,CAAC,MAAM,OAAOkB,EAAQlB,IAAI,CAAC,MAAM,QAChDA,KAEDqB,KAAeH,EAAQlB,CAAC,KACdmB,MAAS,IACfG,MAAS,OAAOA,MAAS,OAC5BH,IAAO,GACPC,IAAQE,KACEA,EAAK,MAAM,IAAI,KACrBD,EAAY,KAAA,EAAO,UACtBxB,EAAM,KAAKwB,EAAY,MAAM,GAE9BA,IAAcC,KACJzB,EAAM,UAAU,CAACwB,IAI3BA,IAAcxB,EAAM,QAASyB,IAE7BD,KAAeC,IAENH,MAAS,MACfG,MAASF,KACZD,IAAO,GACPC,IAAQ,MAERC,KAAeC;AAAA,EAGlB;AACA,SAAID,KACHxB,EAAM,KAAKwB,EAAY,MAAM,GAEvBxB;AACR;ACzCO,MAAM0B,UAAyBb,EAAqB;AAAA,EAmB1D,YAAYc,GAAuB;AAElC,QADA,MAAA,GAnBD,KAAQ,SAIH,CAAA,GACL,KAAQ,UAAU,IAClB,KAAO,QAAQ,IACf,KAAQ,SAAS,GAaZ,CAACA,EAAK;AACT,YAAM,IAAI,MAAM,wCAAwC;AAEzD,SAAK,SAASA,EAAK,OACnB,KAAK,gBAAgBA,EAAK,iBAAiB,KAAK,MAChD,KAAK,gBAAgBA,EAAK,iBAAiB,IAC3C,KAAK,kBAAkBA,EAAK,mBAAmB,QAE/C,KAAK,QACJ,OAAO,kBAAmB,aACvB,iBACA,CAAC5C,MAAO,WAAWA,GAAI,CAAC;AAAA,EAC7B;AAAA,EAEA,MACC6C,GACAC,IAA2C,KAAK,iBAChDC,IAAoB,MAAM;AAAA,EAAC,GACjB;AAMV,QALI,OAAOD,KAAa,eACvBC,IAAKD,GACLA,IAAW,KAAK,kBAGb,KAAK,OAAO;AACf,YAAME,IAAM,IAAI,MAAM,iBAAiB,GAMjCC,IAAQ,KAAK;AACnB,aAAAA,EAAM,MAAMF,EAAGC,CAAG,CAAC,GACnB,KAAK,KAAK,SAASA,CAAG,GACf;AAAA,IACR;AAEA,QAAI,KAAK,iBAAiB,OAAOH,KAAU,UAAU;AACpD,UACC,OAAO,SAAW,OAClB,OAAQ,OAAe,QAAS;AAEhC,QAAAA,IAAQ,OAAO,KAAKA,GAAOC,CAA0B;AAAA,eAC3C,OAAO,cAAgB;AACjC,QAAAD,IAAQ,IAAI,cAAc,OAAOA,CAAK;AAAA;AAEtC,cAAM,IAAI;AAAA,UACT;AAAA,QAAA;AAGF,MAAAC,IAAW;AAAA,IACZ;AAEA,SAAK,UAAUD,EAAM,UAAU;AAC/B,UAAMK,IAAY,KAAK,UAAU,KAAK;AAEtC,gBAAK,OAAO,KAAK,EAAE,OAAAL,GAAO,UAAAC,GAAsC,IAAAC,GAAI,GAE/D,KAAK,WAAS,KAAK,aAAA,GAEjB,CAACG;AAAA,EACT;AAAA,EAEA,IACCL,GACAC,GACAC,GACO;AACP,IAAI,OAAOF,KAAU,cACpBE,IAAKF,GACLA,IAAQ,UACE,OAAOC,KAAa,eAC9BC,IAAKD,GACLA,IAAW,SAGRD,MAAU,UACb,KAAK,MAAMA,GAAOC,GAA4B,MAAM;AAAA,IAAC,CAAC,GACvD,KAAK,QAAQ,IACR,KAAK,WAAS,KAAK,aAAA,GACpBC,KAAI,KAAK,MAAMA,CAAE;AAAA,EACtB;AAAA;AAAA,EAGA,OAAa;AAAA,EAAC;AAAA,EACd,SAAe;AAAA,EAAC;AAAA,EAEhB,mBAAmBI,GAA2B;AAC7C,gBAAK,kBAAkBA,GAChB;AAAA,EACR;AAAA,EAEQ,eAAqB;AAC5B,UAAMC,IAAQ,KAAK,OAAO,MAAA;AAC1B,QAAI,CAACA,GAAO;AACX,MAAI,KAAK,SAAO,KAAK,KAAK,QAAQ;AAClC;AAAA,IACD;AAEA,SAAK,UAAU,IACf,KAAK,OAAOA,EAAM,OAAOA,EAAM,UAAU,CAACJ,MAAuB;AAChE,WAAK,UAAU,IACf,KAAK,UAAUI,EAAM,MAAM,UAAU,GACjCJ,KAAK,KAAK,KAAK,SAASA,CAAG,GAC/BI,EAAM,GAAGJ,CAAG,GAER,KAAK,OAAO,SACf,KAAK,aAAA,KAED,KAAK,SAAS,KAAK,iBAAe,KAAK,KAAK,OAAO,GACnD,KAAK,SAAO,KAAK,KAAK,QAAQ;AAAA,IAEpC,CAAC;AAAA,EACF;AACD;AC/HO,SAASK,EACfC,GAKM;AACN,SAAO,SACNhB,GACAiB,IAAsB,CAAA,GACtBC,IAA0B,CAAA,GACzB;AACD,UAAMC,IAAe,IAAIC,EAAA,GACnBC,IAAa,IAAIC,EAAWH,CAAY;AAE9C,sBAAW,YAAY;AACtB,UAAII,IAAe,CAAA;AACnB,UAAIN,EAAU;AACb,QAAAM,IAAe,CAACvB,GAAmB,GAAGiB,CAAS;AAAA,eACrC,OAAOjB,KAAY;AAC7B,QAAAuB,IAAexB,EAAkBC,CAAO;AAAA,eAC9B,MAAM,QAAQA,CAAO;AAC/B,QAAAuB,IAAevB;AAAA;AAEf,cAAM,IAAI,MAAM,oBAAoBA,CAAO;AAE5C,UAAI;AACH,cAAMwB,IAAUR,EAAQO,GAAcF,GAAYH,CAAO;AACzD,YACC,OAAOM,KAAY,YACnBA,MAAY,QACZ,EAAE,UAAUA;AAEZ,gBAAM,IAAI;AAAA,YACT;AAAA,UAAA;AAKF,YAAWH,EAAW;AACrB,gBAAM,IAAI;AAAA,YACT;AAAA,UAAA;AAMF,QAAAF,EAAa,KAAK,SAAS,EAAI,GAC/B,MAAMK;AAAA,MACP,SAASC,GAAG;AACX,QAAAN,EAAa,KAAK,SAASM,CAAC,GAE3B,OAAOA,KAAM,YACbA,MAAM,QACN,aAAaA,KACb,OAAOA,EAAE,WAAY,YAErBJ,EAAW,OAAOI,EAAE,OAAO,GAE5BJ,EAAW,KAAK,CAAC;AAAA,MAClB;AAAA,IACD,CAAC,GACMF;AAAA,EACR;AACD;AAEO,MAAMG,UAAmB9B,EAAqB;AAAA,EAQpD,YAAY2B,GAA4B;AACvC,UAAA,GARD,KAAO,SAAS,IAKhB,KAAQ,cAAmC,CAAA,GAI1C,KAAK,eAAeA,GACpBA,EAAa,GAAG,SAAS,CAACzB,MAAqB;AAC9C,MAAI,KAAK,cAGR,KAAK,YAAY,KAAKA,EAAK,MAAA,CAAO,IAElC,KAAK,KAAK,SAASA,CAAI;AAAA,IAEzB,CAAC;AAAA,EACF;AAAA,EACA,WAAW;AACV,IAAK,KAAK,aAAa,MAAM,SAC5B,KAAK,aAAa,MAAM,IAAA;AAAA,EAE1B;AAAA,EACA,OAAOA,GAA4B;AAClC,SAAK,aAAa,OAAO,MAAMA,CAAI;AAAA,EACpC;AAAA,EACA,YAAY;AACX,IAAK,KAAK,aAAa,OAAO,SAC7B,KAAK,aAAa,OAAO,IAAA;AAAA,EAE3B;AAAA,EACA,OAAOA,GAA4B;AAClC,SAAK,aAAa,OAAO,MAAMA,CAAI;AAAA,EACpC;AAAA,EACA,YAAY;AACX,IAAK,KAAK,aAAa,OAAO,SAC7B,KAAK,aAAa,OAAO,IAAA;AAAA,EAE3B;AAAA,EACA,cAAc;AACb,SAAK,aAAa,KAAK,SAAS,EAAI;AAAA,EACrC;AAAA,EACA,KAAKgC,GAAc;AAClB,IAAK,KAAK,WACT,KAAK,SAAS,IACd,KAAK,SAAA,GACL,KAAK,UAAA,GACL,KAAK,UAAA,GACL,KAAK,aAAa,KAAK,QAAQA,CAAI;AAAA,EAErC;AAAA,EACS,GAAGjC,GAAmBE,GAAoB;AAMlD,QALA,MAAM,GAAGF,GAAWE,CAAQ,GAKxBF,MAAc,WAAW,KAAK,aAAa;AAC9C,eAASX,IAAI,GAAGA,IAAI,KAAK,YAAY,QAAQA;AAC5C,aAAK,KAAK,SAAS,KAAK,YAAYA,CAAC,CAAC;AAEvC,WAAK,cAAc;AAAA,IACpB;AAAA,EACD;AACD;AAEA,IAAI6C,IAAU;AACP,MAAMP,UAAqB5B,EAAqB;AAAA,EAKtD,YAAYoC,IAAMD,KAAW;AAC5B,UAAA,GACA,KAAK,MAAMC;AAEX,UAAMC,IAAO;AACb,SAAK,SAAS,IAAIxB,EAAiB;AAAA,MAClC,MAAMX,GAAWc,GAA0BC,GAAmB;AAC7D,QAAAoB,EAAK,OAAO,KAAK,QAAQnC,CAAI,GAC7Be,EAAA;AAAA,MACD;AAAA,IAAA,CACA,GACD,KAAK,SAAS,IAAIJ,EAAiB;AAAA,MAClC,OAAO,CAACX,GAAWc,GAA0BC,MAAsB;AAClE,QAAAoB,EAAK,OAAO,KAAK,QAAQnC,CAAI,GAC7Be,EAAA;AAAA,MACD;AAAA,IAAA,CACA,GACD,KAAK,QAAQ,IAAIJ,EAAiB;AAAA,MACjC,OAAO,CAACX,GAAWc,GAA0BC,MAAsB;AAClE,QAAAoB,EAAK,KAAK,SAASnC,CAAI,GACvBe,EAAA;AAAA,MACD;AAAA,IAAA,CACA;AAAA,EACF;AACD;AC9LO,SAASqB,EACfC,IAAS,IACTC,IAAe,0BACd;AACD,QAAMC,IACL,mEACAD;AACD,MAAI1C,IAAS;AACb,WAASR,IAAIiD,GAAQjD,IAAI,GAAG,EAAEA;AAC7B,IAAAQ,KAAU2C,EAAM,KAAK,MAAM,KAAK,WAAWA,EAAM,MAAM,CAAC;AACzD,SAAO3C;AACR;ACTO,SAAS4C,IAAiB;AAChC,SAAOJ,EAAa,IAAI,IAAI;AAC7B;ACJO,SAASK,EAAOC,GAAwB;AAC9C,SAAO,8BAA8BC;AAAA,IACpC,KAAK,UAAUD,CAAK;AAAA,EAAA,CACpB;AACF;AAEO,SAASE,EACfC,GAC0B;AAC1B,QAAMjD,IAAiC,CAAA;AACvC,aAAWkD,KAAOD;AACjB,IAAAjD,EAAOkD,CAAG,IAAIL,EAAOI,EAAKC,CAAG,CAAC;AAE/B,SAAOlD;AACR;AAEA,SAAS+C,EAAeI,GAAa;AACpC,SAAOC,EAAc,IAAI,YAAA,EAAc,OAAOD,CAAG,CAAC;AACnD;AAEA,SAASC,EAAcC,GAAmB;AACzC,QAAMC,IAAY,OAAO,cAAc,GAAGD,CAAK;AAC/C,SAAO,KAAKC,CAAS;AACtB;ACXO,SAASC,EAAQC,MAAmBjD,GAAqB;AAC/D,MAAIP,IAAS,IACTyD,IAAW;AAEf,WAASjE,IAAI,GAAGA,IAAIgE,EAAO,QAAQhE;AAClC,QAAIgE,EAAOhE,CAAC,MAAM,OAAOA,IAAI,IAAIgE,EAAO,QAAQ;AAC/C,MAAAhE;AACA,YAAMkE,IAAYF,EAAOhE,CAAC;AAE1B,cAAQkE,GAAA;AAAA,QACP,KAAK,KAAK;AACT,gBAAMC,IAAMpD,EAAKkD,GAAU;AAC3B,cAAIN;AACJ,cAAI,OAAOQ,KAAQ;AAClB,gBAAI;AAGH,cAAAR,IAAM,KAAK;AAAA,gBACVQ;AAAA;AAAA,gBAEA,CAACT,GAAKJ,MACD,OAAOA,KAAU,WACb,KAAKA,EAAM,SAAS,EAAE,CAAC,KAExBA;AAAA,gBAER;AAAA,cAAA;AAAA,YAEF,QAAQ;AAAA,YAER;AAAA;AAEA,YAAAK,IAAM,OAAOQ,CAAG;AAGjB,UAAA3D,KAAUmD;AACV;AAAA,QACD;AAAA,QACA,KAAK,KAAK;AACT,gBAAMQ,IAAMpD,EAAKkD,GAAU;AAC3B,UAAI,OAAOE,KAAQ,WAClB3D,KAAU2D,EAAI,SAAA,IAEd3D,KAAU,KAAK,MAAM,OAAO2D,CAAG,CAAC;AAEjC;AAAA,QACD;AAAA,QACA,KAAK,KAAK;AACT,gBAAMA,IAAMpD,EAAKkD,GAAU;AAC3B,UACCzD,KAAU,OAAO2D,CAAG;AAIrB;AAAA,QACD;AAAA,QACA,KAAK,KAAK;AACT,gBAAMA,IAAMpD,EAAKkD,GAAU;AAC3B,UAAI,OAAOE,KAAQ,WAClB3D,KAAU2D,EAAI,SAAS,EAAE,IAEzB3D,KAAU,KAAK,MAAM,OAAO2D,CAAG,CAAC,EAAE,SAAS,EAAE;AAE9C;AAAA,QACD;AAAA,QACA,KAAK,KAAK;AACT,UAAA3D,KAAU;AACV;AAAA,QACD;AAAA,QACA;AACC,UAAAA,KAAU,MAAM0D;AAAA,MACjB;AAAA,IAEF;AACC,MAAA1D,KAAUwD,EAAOhE,CAAC;AAIpB,SAAOQ;AACR;ACpEO,SAAS4D,EAAkBC,GAAkC;AACnE,MAAIC,IAAc;AAClB,EAAAD,EAAO,QAAQ,CAACE,MAAOD,KAAeC,EAAE,MAAO;AAC/C,QAAM/D,IAAS,IAAI,WAAW8D,CAAW;AACzC,MAAIE,IAAS;AACb,SAAAH,EAAO,QAAQ,CAACE,MAAM;AACrB,IAAA/D,EAAO,IAAI+D,GAAGC,CAAM,GACpBA,KAAUD,EAAE;AAAA,EACb,CAAC,GACM/D;AACR;AAEO,SAASiE,EAAmBC,GAAqC;AACvE,SAAON,EAAkBM,EAAQ,IAAI,CAACC,MAAM,IAAI,WAAWA,CAAC,CAAC,CAAC,EAC5D;AACH;"} | ||
| {"version":3,"file":"index.js","sources":["../../../../packages/php-wasm/util/src/lib/sleep.ts","../../../../packages/php-wasm/util/src/lib/semaphore.ts","../../../../packages/php-wasm/util/src/lib/php-wasm-error.ts","../../../../packages/php-wasm/util/src/lib/paths.ts","../../../../packages/php-wasm/util/src/lib/event-emitter-polyfill.ts","../../../../packages/php-wasm/util/src/lib/split-shell-command.ts","../../../../packages/php-wasm/util/src/lib/writable-polyfill.ts","../../../../packages/php-wasm/util/src/lib/create-spawn-handler.ts","../../../../packages/php-wasm/util/src/lib/php-event.ts","../../../../packages/php-wasm/util/src/lib/spawn-handlers/sendmail.ts","../../../../packages/php-wasm/util/src/lib/random-string.ts","../../../../packages/php-wasm/util/src/lib/random-filename.ts","../../../../packages/php-wasm/util/src/lib/php-vars.ts","../../../../packages/php-wasm/util/src/lib/sprintf.ts","../../../../packages/php-wasm/util/src/lib/index.ts"],"sourcesContent":["export const SleepFinished = Symbol('SleepFinished');\n\nexport function sleep(ms: number): Promise<typeof SleepFinished> {\n\treturn new Promise((resolve) => {\n\t\tsetTimeout(() => resolve(SleepFinished), ms);\n\t});\n}\n","import { SleepFinished, sleep } from './sleep';\n\nexport interface SemaphoreOptions {\n\t/**\n\t * The maximum number of concurrent locks.\n\t */\n\tconcurrency: number;\n\t/**\n\t * The maximum time to wait for a lock to become available.\n\t */\n\ttimeout?: number;\n}\n\nexport class AcquireTimeoutError extends Error {\n\tconstructor() {\n\t\tsuper('Acquiring lock timed out');\n\t}\n}\n\nexport default class Semaphore {\n\tprivate _running = 0;\n\tprivate concurrency: number;\n\tprivate timeout?: number;\n\tprivate queue: (() => void)[];\n\n\tconstructor({ concurrency, timeout }: SemaphoreOptions) {\n\t\tthis.concurrency = concurrency;\n\t\tthis.timeout = timeout;\n\t\tthis.queue = [];\n\t}\n\n\tget remaining(): number {\n\t\treturn this.concurrency - this.running;\n\t}\n\n\tget running(): number {\n\t\treturn this._running;\n\t}\n\n\tasync acquire(): Promise<() => void> {\n\t\t// Concurrency exhausted - wait in queue for other workers to finish:\n\t\tif (this._running >= this.concurrency) {\n\t\t\t// Create a promise and store its resolver in the queue.\n\t\t\tconst acquired = new Promise<void>((resolve) => {\n\t\t\t\tthis.queue.push(resolve);\n\t\t\t});\n\n\t\t\t// Wait until it is resolved by another worker or a timeout occurs.\n\t\t\tif (this.timeout !== undefined) {\n\t\t\t\t// Store the resolver for cleanup in case of timeout.\n\t\t\t\tconst resolve = this.queue.at(-1)!;\n\t\t\t\tconst result = await Promise.race([\n\t\t\t\t\tacquired,\n\t\t\t\t\tsleep(this.timeout),\n\t\t\t\t]);\n\t\t\t\tif (result === SleepFinished) {\n\t\t\t\t\t// Remove the resolver for the timed out worker from the queue.\n\t\t\t\t\tthis.queue.splice(this.queue.indexOf(resolve), 1);\n\t\t\t\t\tthrow new AcquireTimeoutError();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tawait acquired;\n\t\t\t}\n\t\t}\n\n\t\t// Acquire the lock:\n\t\tthis._running++;\n\t\tlet released = false;\n\n\t\t// Return a release function:\n\t\treturn () => {\n\t\t\tif (released) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treleased = true;\n\t\t\tthis._running--;\n\n\t\t\t// Release the first item in the queue (call its resolver):\n\t\t\tif (this.queue.length > 0) {\n\t\t\t\tthis.queue.shift()!();\n\t\t\t}\n\t\t};\n\t}\n\n\tasync run<T>(fn: () => T | Promise<T>): Promise<T> {\n\t\tconst release = await this.acquire();\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} finally {\n\t\t\trelease();\n\t\t}\n\t}\n}\n","export class PhpWasmError extends Error {\n\tuserFriendlyMessage?: string;\n\tconstructor(message: string, userFriendlyMessage?: string) {\n\t\tsuper(message);\n\t\tthis.userFriendlyMessage = userFriendlyMessage ?? message;\n\t}\n}\n","/**\n * The functions in this module are mostly copied from the generated\n * Emscripten PHP module. This enables features like filesystem journaling,\n * which use some low-level Emscripten APIs and need access to the\n * same path helpers.\n */\n\n/**\n * Joins paths together.\n *\n * For example:\n *\n * > joinPaths('wordpress', 'wp-content')\n * 'wordpress/wp-content'\n *\n * Use this for all PHP paths and **do not** use path.join().\n * This is important because Emscripten paths are **always**\n * POSIX-style paths. Imagine joining paths on Windows:\n *\n * > path.join('wordpress', 'wp-content')\n * '\\\\wordpress\\\\wp-content' // invalid in PHP.wasm\n *\n * See the path.join issue for more details:\n *\n * https://github.com/WordPress/playground-tools/issues/11#issuecomment-1579074763\n *\n * @param paths Paths segments to join\n * @returns A joined path\n */\nexport function joinPaths(...paths: string[]) {\n\tfunction hasTrailingSlash(p: string) {\n\t\treturn p.substring(p.length - 1) === '/';\n\t}\n\n\tlet path = paths.join('/');\n\tconst isAbsolute = path[0] === '/';\n\tconst trailingSlash = hasTrailingSlash(path);\n\tpath = normalizePath(path);\n\tif (!path && !isAbsolute) {\n\t\tpath = '.';\n\t}\n\tif (path && trailingSlash && !hasTrailingSlash(path)) {\n\t\tpath += '/';\n\t}\n\treturn path;\n}\n\n/**\n * Resolves a path and returns it only when it stays under a parent path.\n *\n * Absolute paths are checked as-is. Relative paths are resolved from the\n * parent path. The parent itself is not considered to be under the parent.\n * Paths containing null bytes are rejected before resolution.\n *\n * @param path The absolute or relative path to resolve.\n * @param parentPath The path the result must stay under.\n * @returns The normalized resolved path, or undefined when it is not a child.\n */\nexport function resolvePathUnder(path: string, parentPath: string) {\n\tif (path.includes('\\0') || parentPath.includes('\\0')) {\n\t\treturn undefined;\n\t}\n\tconst normalizedParentPath = normalizePath(parentPath);\n\tif (!normalizedParentPath) {\n\t\treturn undefined;\n\t}\n\tconst resolvedPath = normalizePath(\n\t\tpath.startsWith('/') ? path : joinPaths(normalizedParentPath, path)\n\t);\n\tif (\n\t\tresolvedPath === normalizedParentPath ||\n\t\t!isParentOf(normalizedParentPath, resolvedPath)\n\t) {\n\t\treturn undefined;\n\t}\n\treturn resolvedPath;\n}\n\n/**\n * Returns the directory name of a path.\n *\n * @param path\n * @returns\n */\nexport function dirname(path: string) {\n\tif (path === '/') {\n\t\treturn '/';\n\t}\n\n\tpath = normalizePath(path);\n\n\tconst lastSlash = path.lastIndexOf('/');\n\tif (lastSlash === -1) {\n\t\treturn '';\n\t} else if (lastSlash === 0) {\n\t\treturn '/';\n\t}\n\treturn path.substr(0, lastSlash);\n}\n\n/**\n * Returns the last portion of a path.\n *\n * @param path - The path to extract the basename from.\n * @returns The basename of the path.\n */\nexport function basename(path: string) {\n\tif (path === '/') {\n\t\treturn '/';\n\t}\n\n\tpath = normalizePath(path);\n\n\tconst lastSlash = path.lastIndexOf('/');\n\tif (lastSlash === -1) {\n\t\treturn path;\n\t}\n\treturn path.substr(lastSlash + 1);\n}\n\n/**\n * Normalizes a path.\n *\n * For example:\n *\n * > normalizePath('wordpress/wp-content/../')\n * 'wordpress'\n *\n * @param path\n * @returns\n */\nexport function normalizePath(path: string) {\n\tconst isAbsolute = path[0] === '/';\n\tpath = normalizePathsArray(\n\t\tpath.split('/').filter((p: any) => !!p),\n\t\t!isAbsolute\n\t).join('/');\n\treturn (isAbsolute ? '/' : '') + path.replace(/\\/$/, '');\n}\n\n/**\n * Normalizes paths.\n *\n * For example:\n *\n * > normalizePathsArray(['wordpress', 'wp-content', '..', '', '.',\n * 'wp-includes']) ['wordpress', 'wp-includes']\n *\n * @param parts parts of the path to normalize\n * @param allowAboveRoot allow paths above the root\n * @returns normalized paths\n */\nexport function normalizePathsArray(parts: string[], allowAboveRoot: boolean) {\n\tlet up = 0;\n\tfor (let i = parts.length - 1; i >= 0; i--) {\n\t\tconst last = parts[i];\n\t\tif (last === '.') {\n\t\t\tparts.splice(i, 1);\n\t\t} else if (last === '..') {\n\t\t\tparts.splice(i, 1);\n\t\t\tup++;\n\t\t} else if (up) {\n\t\t\tparts.splice(i, 1);\n\t\t\tup--;\n\t\t}\n\t}\n\tif (allowAboveRoot) {\n\t\tfor (; up; up--) {\n\t\t\tparts.unshift('..');\n\t\t}\n\t}\n\treturn parts;\n}\n\n/**\n * Checks if the given parent path is an ancestor of the given child path.\n *\n * @param parent The parent path to check.\n * @param child The child path to verify against the parent.\n * @returns Whether the `parent` path is an ancestor of the `child` path.\n */\nexport function isParentOf(parent: string, child: string) {\n\tif (parent === '/') {\n\t\treturn true;\n\t}\n\tparent = normalizePath(parent);\n\tchild = normalizePath(child);\n\treturn child.startsWith(parent + '/') || child === parent;\n}\n\n/**\n * Guarantees a path is absolute by prepending `/` if needed.\n *\n * Useful when working with user-provided paths that might be relative,\n * or when you need to normalize edge cases like empty strings.\n *\n * For example:\n *\n * > ensureAbsolutePath('wp-content/uploads')\n * '/wp-content/uploads'\n *\n * > ensureAbsolutePath('/already/absolute')\n * '/already/absolute'\n *\n * > ensureAbsolutePath('')\n * '/'\n *\n * @param path - The path to make absolute.\n * @returns An absolute, normalized path starting with `/`.\n */\nexport function ensureAbsolutePath(path: string) {\n\treturn joinPaths('/', normalizePath(path || '/'));\n}\n\n/**\n * Converts a native OS path to a POSIX-style path.\n *\n * Transformations:\n * 1. Backslashes → forward slashes\n * 2. Windows drive letter `C:\\` → `/C/` (colons are invalid in\n * Emscripten VFS paths and cause ENOTDIR errno 28)\n *\n * On POSIX systems this is effectively a no-op.\n *\n * @see https://github.com/emscripten-core/emscripten/issues/17829\n */\nexport function toPosixPath(nativePath: string): string {\n\tlet result = nativePath.replaceAll('\\\\', '/');\n\t// Handle Windows drive letter: C:/ → /C/\n\tconst driveMatch = result.match(/^([A-Za-z]):\\//);\n\tif (driveMatch) {\n\t\tresult = '/' + driveMatch[1] + result.slice(2);\n\t}\n\treturn result;\n}\n","/**\n * Polyfills Node.js EventEmitter API. The main goal is to enable\n * using a child_process.spawn()-like API in both Node.js and the browser.\n *\n * @see https://nodejs.org/api/events.html#events_class_eventemitter\n */\ntype Listener = (...args: any[]) => any;\n\nexport class EventEmitterPolyfill {\n\tlisteners: Record<string, Listener[]> = {};\n\temit(eventName: string, data?: any) {\n\t\tif (this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName].forEach(function (listener) {\n\t\t\t\tlistener(data);\n\t\t\t});\n\t\t}\n\t}\n\ton(eventName: string, listener: Listener) {\n\t\tif (!this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName] = [];\n\t\t}\n\t\tthis.listeners[eventName].push(listener);\n\t}\n\tonce(eventName: string, listener: Listener) {\n\t\tconst wrappedListener = (...args: any[]) => {\n\t\t\tthis.off(eventName, wrappedListener);\n\t\t\tlistener(...args);\n\t\t};\n\t\tthis.on(eventName, wrappedListener);\n\t}\n\toff(eventName: string, listener: Listener) {\n\t\tif (this.listeners[eventName]) {\n\t\t\tthis.listeners[eventName] = this.listeners[eventName].filter(\n\t\t\t\t(l) => l !== listener\n\t\t\t);\n\t\t}\n\t}\n}\n","/**\n * Naive shell command parser.\n * Ensures that commands like `wp option set blogname \"My blog name\"` are split\n * into `['wp', 'option', 'set', 'blogname', 'My blog name']` instead of\n * `['wp', 'option', 'set', 'blogname', 'My', 'blog', 'name']`.\n *\n * @param command\n * @returns\n */\nexport function splitShellCommand(command: string) {\n\tconst MODE_UNQUOTED = 0;\n\tconst MODE_IN_QUOTE = 1;\n\n\tlet mode = MODE_UNQUOTED;\n\tlet quote = '';\n\n\tconst parts: string[] = [];\n\tlet currentPart = '';\n\tfor (let i = 0; i < command.length; i++) {\n\t\tconst char = command[i];\n\t\tif (char === '\\\\') {\n\t\t\t// Escaped quotes are treated as normal characters\n\t\t\t// This is a very naive approach to escaping, but it's good enough for\n\t\t\t// now. @TODO: Iterate on this later, perhaps using bun shell. @see https://github.com/WordPress/wordpress-playground/issues/1062\n\t\t\tif (command[i + 1] === '\"' || command[i + 1] === \"'\") {\n\t\t\t\ti++;\n\t\t\t}\n\t\t\tcurrentPart += command[i];\n\t\t} else if (mode === MODE_UNQUOTED) {\n\t\t\tif (char === '\"' || char === \"'\") {\n\t\t\t\tmode = MODE_IN_QUOTE;\n\t\t\t\tquote = char;\n\t\t\t} else if (char.match(/\\s/)) {\n\t\t\t\tif (currentPart.trim().length) {\n\t\t\t\t\tparts.push(currentPart.trim());\n\t\t\t\t}\n\t\t\t\tcurrentPart = char;\n\t\t\t} else if (parts.length && !currentPart) {\n\t\t\t\t// We just closed a quote to continue the same\n\t\t\t\t// argument with different escaping style, e.g.:\n\t\t\t\t// php -r 'require '\\''vendor/autoload.php'\\''\n\t\t\t\tcurrentPart = parts.pop()! + char;\n\t\t\t} else {\n\t\t\t\tcurrentPart += char;\n\t\t\t}\n\t\t} else if (mode === MODE_IN_QUOTE) {\n\t\t\tif (char === quote) {\n\t\t\t\tmode = MODE_UNQUOTED;\n\t\t\t\tquote = '';\n\t\t\t} else {\n\t\t\t\tcurrentPart += char;\n\t\t\t}\n\t\t}\n\t}\n\tif (currentPart) {\n\t\tparts.push(currentPart.trim());\n\t}\n\treturn parts;\n}\n","/**\n * Polyfills Node.js WritableStream API. The main goal is to enable\n * using a child_process.spawn()-like API in both Node.js and the browser.\n *\n * @see https://nodejs.org/api/stream.html#stream_writable_end_chunk_encoding_callback\n */\nimport { EventEmitterPolyfill } from './event-emitter-polyfill';\n\nexport interface WritableOptions {\n\thighWaterMark?: number;\n\tdecodeStrings?: boolean;\n\tdefaultEncoding?: BufferEncoding;\n\twrite: (chunk: any, encoding: BufferEncoding, cb: WriteCallback) => void;\n}\n\nexport type WriteCallback = (error?: Error | null) => void;\n\nexport class WritablePolyfill extends EventEmitterPolyfill {\n\tprivate buffer: Array<{\n\t\tchunk: any;\n\t\tencoding: BufferEncoding;\n\t\tcb: WriteCallback;\n\t}> = [];\n\tprivate writing = false;\n\tpublic ended = false;\n\tprivate length = 0;\n\tprivate highWaterMark: number;\n\tprivate decodeStrings: boolean;\n\tprivate defaultEncoding: BufferEncoding;\n\tprivate defer: (fn: () => void) => void;\n\tprivate _write: (\n\t\tchunk: any,\n\t\tencoding: BufferEncoding,\n\t\tcb: WriteCallback\n\t) => void;\n\n\tconstructor(opts: WritableOptions) {\n\t\tsuper();\n\t\tif (!opts.write) {\n\t\t\tthrow new Error('WritablePolyfill requires write option');\n\t\t}\n\t\tthis._write = opts.write;\n\t\tthis.highWaterMark = opts.highWaterMark ?? 16 * 1024;\n\t\tthis.decodeStrings = opts.decodeStrings ?? true;\n\t\tthis.defaultEncoding = opts.defaultEncoding ?? 'utf8';\n\t\t// queueMicrotask keeps browser support; fallback for older environments.\n\t\tthis.defer =\n\t\t\ttypeof queueMicrotask === 'function'\n\t\t\t\t? queueMicrotask\n\t\t\t\t: (fn) => setTimeout(fn, 0);\n\t}\n\n\twrite(\n\t\tchunk: any,\n\t\tencoding: BufferEncoding | WriteCallback = this.defaultEncoding,\n\t\tcb: WriteCallback = () => {}\n\t): boolean {\n\t\tif (typeof encoding === 'function') {\n\t\t\tcb = encoding as WriteCallback;\n\t\t\tencoding = this.defaultEncoding;\n\t\t}\n\n\t\tif (this.ended) {\n\t\t\tconst err = new Error('write after end');\n\t\t\t// We can't call this.defer() directly. If this.defer is\n\t\t\t// `queueMicrotask`, a `this.defer()` call will pass the\n\t\t\t// WritablePolyfill instance as `this` argument and cause\n\t\t\t// the browser to throw an error similar to \"Invalid\n\t\t\t// invocation\".\n\t\t\tconst defer = this.defer;\n\t\t\tdefer(() => cb(err));\n\t\t\tthis.emit('error', err);\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this.decodeStrings && typeof chunk === 'string') {\n\t\t\tif (\n\t\t\t\ttypeof Buffer !== 'undefined' &&\n\t\t\t\ttypeof (Buffer as any).from === 'function'\n\t\t\t) {\n\t\t\t\tchunk = Buffer.from(chunk, encoding as BufferEncoding);\n\t\t\t} else if (typeof TextEncoder !== 'undefined') {\n\t\t\t\tchunk = new TextEncoder().encode(chunk);\n\t\t\t} else {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'String chunks are not supported in this environment: Buffer and TextEncoder are unavailable.'\n\t\t\t\t);\n\t\t\t}\n\t\t\tencoding = 'buffer' as BufferEncoding;\n\t\t}\n\n\t\tthis.length += chunk.length ?? 1;\n\t\tconst needDrain = this.length >= this.highWaterMark;\n\n\t\tthis.buffer.push({ chunk, encoding: encoding as BufferEncoding, cb });\n\n\t\tif (!this.writing) this._clearBuffer();\n\n\t\treturn !needDrain;\n\t}\n\n\tend(\n\t\tchunk?: any,\n\t\tencoding?: BufferEncoding | WriteCallback,\n\t\tcb?: WriteCallback\n\t): void {\n\t\tif (typeof chunk === 'function') {\n\t\t\tcb = chunk;\n\t\t\tchunk = undefined;\n\t\t} else if (typeof encoding === 'function') {\n\t\t\tcb = encoding as WriteCallback;\n\t\t\tencoding = undefined;\n\t\t}\n\n\t\tif (chunk !== undefined)\n\t\t\tthis.write(chunk, encoding as BufferEncoding, () => {});\n\t\tthis.ended = true;\n\t\tif (!this.writing) this._clearBuffer();\n\t\tif (cb) this.defer(cb);\n\t}\n\n\t// Stubs kept for API parity; add logic if you depend on corking.\n\tcork(): void {}\n\tuncork(): void {}\n\n\tsetDefaultEncoding(enc: BufferEncoding): this {\n\t\tthis.defaultEncoding = enc;\n\t\treturn this;\n\t}\n\n\tprivate _clearBuffer(): void {\n\t\tconst entry = this.buffer.shift();\n\t\tif (!entry) {\n\t\t\tif (this.ended) this.emit('finish');\n\t\t\treturn;\n\t\t}\n\n\t\tthis.writing = true;\n\t\tthis._write(entry.chunk, entry.encoding, (err?: Error | null) => {\n\t\t\tthis.writing = false;\n\t\t\tthis.length -= entry.chunk.length ?? 1;\n\t\t\tif (err) this.emit('error', err);\n\t\t\tentry.cb(err);\n\n\t\t\tif (this.buffer.length) {\n\t\t\t\tthis._clearBuffer();\n\t\t\t} else {\n\t\t\t\tif (this.length < this.highWaterMark) this.emit('drain');\n\t\t\t\tif (this.ended) this.emit('finish');\n\t\t\t}\n\t\t});\n\t}\n}\n","import { EventEmitterPolyfill } from './event-emitter-polyfill';\nimport { splitShellCommand } from './split-shell-command';\nimport { WritablePolyfill, type WriteCallback } from './writable-polyfill';\n\ntype Listener = (...args: any[]) => any;\n\nexport interface ProcessOptions {\n\tcwd?: string;\n\tenv?: Record<string, string>;\n}\n\n/**\n * Usage:\n * ```ts\n * php.setSpawnHandler(\n * createSpawnHandler(function (command, processApi) {\n * console.log(processApi.flushStdin());\n * processApi.stdout('/\\n/tmp\\n/home');\n *\t processApi.exit(0);\n * })\n * );\n * ```\n * @param program\n * @returns\n */\nexport function createSpawnHandler(\n\tprogram: (\n\t\tcommand: string[],\n\t\tprocessApi: ProcessApi,\n\t\toptions: ProcessOptions\n\t) => void | Promise<void>\n): any {\n\treturn function (\n\t\tcommand: string | string[],\n\t\targsArray: string[] = [],\n\t\toptions: ProcessOptions = {}\n\t) {\n\t\tconst childProcess = new ChildProcess();\n\t\tconst processApi = new ProcessApi(childProcess);\n\t\t// Give PHP a chance to register listeners\n\t\tsetTimeout(async () => {\n\t\t\tlet commandArray = [];\n\t\t\tif (argsArray.length) {\n\t\t\t\tcommandArray = [command as string, ...argsArray];\n\t\t\t} else if (typeof command === 'string') {\n\t\t\t\tcommandArray = splitShellCommand(command);\n\t\t\t} else if (Array.isArray(command)) {\n\t\t\t\tcommandArray = command;\n\t\t\t} else {\n\t\t\t\tthrow new Error('Invalid command ', command);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst promise = program(commandArray, processApi, options);\n\t\t\t\tif (\n\t\t\t\t\ttypeof promise !== 'object' ||\n\t\t\t\t\tpromise === null ||\n\t\t\t\t\t!('then' in promise)\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`The program callback passed to createSpawnHandler() did not return a promise. It indicates there's a bug in your code. ` +\n\t\t\t\t\t\t\t`The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() ` +\n\t\t\t\t\t\t\t`call. All the streams would be closed already. Make sure to put an \"await new Promise(resolve => setTimeout(resolve, 1))` +\n\t\t\t\t\t\t\t`before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`\n\t\t\t\t\t);\n\t\t\t\t} else if (processApi.exited) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`The program callback passed to createSpawnHandler() exited synchronously. It indicates there's a bug in your code. ` +\n\t\t\t\t\t\t\t`The callback must return a promise. PHP cannot interact with program that synchronously exists at the end of the proc_open() ` +\n\t\t\t\t\t\t\t`call. All the streams would be closed already. Make sure to put an \"await new Promise(resolve => setTimeout(resolve, 1))` +\n\t\t\t\t\t\t\t`before calling processApi.exit(0) in your callback to let PHP catch up with the stdout data.`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tchildProcess.emit('spawn', true);\n\t\t\t\tawait promise;\n\t\t\t} catch (e) {\n\t\t\t\tchildProcess.emit('error', e);\n\t\t\t\tif (\n\t\t\t\t\ttypeof e === 'object' &&\n\t\t\t\t\te !== null &&\n\t\t\t\t\t'message' in e &&\n\t\t\t\t\ttypeof e.message === 'string'\n\t\t\t\t) {\n\t\t\t\t\tprocessApi.stderr(e.message);\n\t\t\t\t}\n\t\t\t\tprocessApi.exit(1);\n\t\t\t}\n\t\t});\n\t\treturn childProcess;\n\t};\n}\n\nexport class ProcessApi extends EventEmitterPolyfill {\n\tpublic exited = false;\n\t/**\n\t * Keeps track of the data that was written to stdin before the\n\t * first listener was registered.\n\t */\n\tprivate stdinBuffer: Uint8Array[] | null = [];\n\tpublic childProcess: ChildProcess;\n\tconstructor(childProcess: ChildProcess) {\n\t\tsuper();\n\t\tthis.childProcess = childProcess;\n\t\tchildProcess.on('stdin', (data: Uint8Array) => {\n\t\t\tif (this.stdinBuffer) {\n\t\t\t\t// Need to clone the data buffer as it's reused by PHP\n\t\t\t\t// and the next data chunk will overwrite the previous one.\n\t\t\t\tthis.stdinBuffer.push(data.slice());\n\t\t\t} else {\n\t\t\t\tthis.emit('stdin', data);\n\t\t\t}\n\t\t});\n\t}\n\tstdinEnd() {\n\t\tif (!this.childProcess.stdin.ended) {\n\t\t\tthis.childProcess.stdin.end();\n\t\t}\n\t}\n\tstdout(data: string | ArrayBuffer) {\n\t\tthis.childProcess.stdout.write(data);\n\t}\n\tstdoutEnd() {\n\t\tif (!this.childProcess.stdout.ended) {\n\t\t\tthis.childProcess.stdout.end();\n\t\t}\n\t}\n\tstderr(data: string | ArrayBuffer) {\n\t\tthis.childProcess.stderr.write(data);\n\t}\n\tstderrEnd() {\n\t\tif (!this.childProcess.stderr.ended) {\n\t\t\tthis.childProcess.stderr.end();\n\t\t}\n\t}\n\tnotifySpawn() {\n\t\tthis.childProcess.emit('spawn', true);\n\t}\n\texit(code: number) {\n\t\tif (!this.exited) {\n\t\t\tthis.exited = true;\n\t\t\tthis.stdinEnd();\n\t\t\tthis.stdoutEnd();\n\t\t\tthis.stderrEnd();\n\t\t\tthis.childProcess.emit('exit', code);\n\t\t}\n\t}\n\toverride on(eventName: string, listener: Listener) {\n\t\tsuper.on(eventName, listener);\n\t\t/**\n\t\t * If it's the first stdin listener, flush all the data we've\n\t\t * buffered so far.\n\t\t */\n\t\tif (eventName === 'stdin' && this.stdinBuffer) {\n\t\t\tfor (let i = 0; i < this.stdinBuffer.length; i++) {\n\t\t\t\tthis.emit('stdin', this.stdinBuffer[i]);\n\t\t\t}\n\t\t\tthis.stdinBuffer = null;\n\t\t}\n\t}\n}\n\nlet lastPid = 9743;\nexport class ChildProcess extends EventEmitterPolyfill {\n\tstdout: WritablePolyfill;\n\tstderr: WritablePolyfill;\n\tstdin: WritablePolyfill;\n\tpid: number;\n\tconstructor(pid = lastPid++) {\n\t\tsuper();\n\t\tthis.pid = pid;\n\t\t// eslint-disable-next-line @typescript-eslint/no-this-alias\n\t\tconst self = this;\n\t\tthis.stdout = new WritablePolyfill({\n\t\t\twrite(data: any, encoding: BufferEncoding, cb: WriteCallback) {\n\t\t\t\tself.stdout.emit('data', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t\tthis.stderr = new WritablePolyfill({\n\t\t\twrite: (data: any, encoding: BufferEncoding, cb: WriteCallback) => {\n\t\t\t\tself.stderr.emit('data', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t\tthis.stdin = new WritablePolyfill({\n\t\t\twrite: (data: any, encoding: BufferEncoding, cb: WriteCallback) => {\n\t\t\t\tself.emit('stdin', data);\n\t\t\t\tcb();\n\t\t\t},\n\t\t});\n\t}\n}\n","/**\n * Explicitly marks an event whose `stdin` ReadableStream needs an independent\n * branch per listener and must be transferred across worker boundaries. The\n * global symbol registry keeps the marker stable if this package is loaded\n * more than once in the same realm.\n */\nexport const phpEventStdinTransfer = Symbol.for(\n\t'@php-wasm/php-event-stdin-transfer'\n);\n\nexport type PHPEventWithStdinTransfer = {\n\ttype: string;\n\tstdin: ReadableStream<Uint8Array>;\n\t[phpEventStdinTransfer]: true;\n};\n","import { createSpawnHandler } from '../create-spawn-handler';\nimport {\n\tphpEventStdinTransfer,\n\ttype PHPEventWithStdinTransfer,\n} from '../php-event';\n\n/**\n * Limit captured sendmail stdin to 20 MB to match common email size limits.\n *\n * Gmail limits email attachments to 25 MB https://support.google.com/mail/answer/6584\n * Outlook limits email attachments to 20 MB https://support.microsoft.com/outlook/reduce-attachment-size-to-send-large-files-with-outlook\n */\nexport const SENDMAIL_CAPTURE_MAX_SIZE = 20 * 1024 * 1024;\n\n/**\n * Emitted when a sendmail null transport receives the first stdin bytes from\n * `mail()`, `popen()`, `proc_open()`, or any other spawn of a `sendmail` binary.\n */\nexport interface PHPSendmailSpawnedEvent extends PHPEventWithStdinTransfer {\n\ttype: 'sendmail.spawned';\n}\n\n/**\n * Creates a sendmail-compatible null transport for the given PHP instance.\n * Every message handed to sendmail – via mail(), proc_open(), etc. – is streamed\n * from stdin, dispatched as a `sendmail.spawned` event, and never delivered.\n * A listener that wants real delivery must relay the message itself.\n *\n * The captured payload is exposed as the raw bytes written to sendmail stdin.\n *\n * This stream does not apply backpressure to PHP. Each listener queues unread\n * chunks in JavaScript memory when it reads more slowly than PHP writes. The\n * source accepts at most SENDMAIL_CAPTURE_MAX_SIZE bytes. Cancelling the stream\n * stops delivery through that stream without terminating the sendmail process.\n */\nexport function sendmailSpawnHandler(php: {\n\tdispatchEvent: (event: PHPSendmailSpawnedEvent) => void;\n}) {\n\treturn createSpawnHandler(async function (commandArray, processApi) {\n\t\tlet totalLength = 0;\n\t\tlet dispatched = false;\n\t\tlet exceededMaxSize = false;\n\t\tlet streamCancelled = false;\n\t\tlet controller: ReadableStreamDefaultController<Uint8Array>;\n\t\t// Construct the stream before registering stdin. Event dispatch is synchronous,\n\t\t// and a listener may start reading as soon as the first chunk arrives.\n\t\tconst stdinStream = new ReadableStream<Uint8Array>({\n\t\t\tstart(streamController) {\n\t\t\t\tcontroller = streamController;\n\t\t\t},\n\t\t\tcancel() {\n\t\t\t\t// Cancellation only means no reader wants more bytes from this source. Keep\n\t\t\t\t// the null transport alive so PHP can finish writing and receive an exit code.\n\t\t\t\tstreamCancelled = true;\n\t\t\t},\n\t\t});\n\n\t\tprocessApi.on('stdin', (data: Uint8Array) => {\n\t\t\tif (!dispatched) {\n\t\t\t\t// Do not publish an email until sendmail receives actual message bytes. An\n\t\t\t\t// invocation that closes stdin immediately is a failed send, not an empty email.\n\t\t\t\tdispatched = true;\n\t\t\t\tphp.dispatchEvent({\n\t\t\t\t\ttype: 'sendmail.spawned',\n\t\t\t\t\tstdin: stdinStream,\n\t\t\t\t\t[phpEventStdinTransfer]: true,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\ttotalLength += data.length;\n\t\t\tif (totalLength > SENDMAIL_CAPTURE_MAX_SIZE) {\n\t\t\t\t// Fail the consumer now, but keep draining stdin. Exiting here would close\n\t\t\t\t// PHP's write end before the spawning code has finished with the process.\n\t\t\t\texceededMaxSize = true;\n\t\t\t\ttry {\n\t\t\t\t\tcontroller!.error(\n\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t`sendmail: Message size exceeds fixed maximum message size (${SENDMAIL_CAPTURE_MAX_SIZE})`\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\t// The consumer may have cancelled the stream.\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!streamCancelled) {\n\t\t\t\t// The PHP bridge reuses its input buffer for later chunks. A stream reader\n\t\t\t\t// may retain this one indefinitely, so it must receive an owned copy.\n\t\t\t\tcontroller!.enqueue(data.slice());\n\t\t\t}\n\t\t});\n\n\t\tconst stdin = processApi.childProcess\n\t\t\t.stdin as typeof processApi.childProcess.stdin & {\n\t\t\twritableEnded?: boolean;\n\t\t\twritableFinished?: boolean;\n\t\t};\n\t\t// proc_open() may write long after the spawn handler starts. Keep sendmail\n\t\t// alive until descriptor 0 closes or PHP will observe a truncated pipe.\n\t\tif (!(stdin.ended || stdin.writableEnded || stdin.writableFinished)) {\n\t\t\tawait new Promise<void>((resolve) => {\n\t\t\t\t// stdin can finish between the outer check and listener registration.\n\t\t\t\t// Recheck here or that race leaves the sendmail process waiting forever.\n\t\t\t\tif (\n\t\t\t\t\tstdin.ended ||\n\t\t\t\t\tstdin.writableEnded ||\n\t\t\t\t\tstdin.writableFinished\n\t\t\t\t) {\n\t\t\t\t\tresolve();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst finish = () => {\n\t\t\t\t\tresolve();\n\t\t\t\t};\n\n\t\t\t\tstdin.once('finish', finish);\n\t\t\t});\n\t\t}\n\n\t\tif (exceededMaxSize) {\n\t\t\tprocessApi.stderr(\n\t\t\t\t`sendmail: Message size exceeds fixed maximum message size (${SENDMAIL_CAPTURE_MAX_SIZE})\\n`\n\t\t\t);\n\t\t\tprocessApi.exit(1);\n\t\t\treturn;\n\t\t}\n\n\t\tif (totalLength === 0) {\n\t\t\t// EX_TEMPFAIL is the sendmail-compatible result for an invocation that never\n\t\t\t// supplied a message. In particular, do not turn it into a successful no-op.\n\t\t\tprocessApi.stderr(\n\t\t\t\t'sendmail: fatal: No message bytes received over stdin\\n'\n\t\t\t);\n\t\t\tprocessApi.exit(75);\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tcontroller!.close();\n\t\t} catch {\n\t\t\t// The consumer may have cancelled the stream.\n\t\t}\n\t\tprocessApi.exit(0);\n\t});\n}\n","export function randomString(\n\tlength = 36,\n\tspecialChars = '!@#$%^&*()_+=-[]/.,<>?'\n) {\n\tconst chars =\n\t\t'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' +\n\t\tspecialChars;\n\tlet result = '';\n\tfor (let i = length; i > 0; --i)\n\t\tresult += chars[Math.floor(Math.random() * chars.length)];\n\treturn result;\n}\n","import { randomString } from './random-string';\n\nexport function randomFilename() {\n\treturn randomString(36, '-_');\n}\n","export function phpVar(value: unknown): string {\n\treturn `json_decode(base64_decode('${stringToBase64(\n\t\tJSON.stringify(value)\n\t)}'), true)`;\n}\n\nexport function phpVars<T extends Record<string, unknown>>(\n\tvars: T\n): Record<keyof T, string> {\n\tconst result: Record<string, string> = {};\n\tfor (const key in vars) {\n\t\tresult[key] = phpVar(vars[key]);\n\t}\n\treturn result as Record<keyof T, string>;\n}\n\nfunction stringToBase64(str: string) {\n\treturn bytesToBase64(new TextEncoder().encode(str));\n}\n\nfunction bytesToBase64(bytes: Uint8Array) {\n\tconst binString = String.fromCodePoint(...bytes);\n\treturn btoa(binString);\n}\n","/**\n * Formats a string like sprintf().\n *\n * This function:\n * - Supports basic format specifiers: %s, %d, %f, %x, %%\n * - Supports bigint values\n *\n * The purpose of this function is for use in optional php-wasm tracing.\n * If we use printf-style formatting for trace messages, we let the trace\n * function decide whether to format and do not have to pay for formatting\n * unless tracing is enabled.\n */\nexport function sprintf(format: string, ...args: any[]): string {\n\tlet result = '';\n\tlet argIndex = 0;\n\n\tfor (let i = 0; i < format.length; i++) {\n\t\tif (format[i] === '%' && i + 1 < format.length) {\n\t\t\ti++;\n\t\t\tconst specifier = format[i];\n\n\t\t\tswitch (specifier) {\n\t\t\t\tcase 's': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tlet str;\n\t\t\t\t\tif (typeof arg === 'object') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// If an object doesn't provide its own toString(),\n\t\t\t\t\t\t\t// try to represent it as JSON.\n\t\t\t\t\t\t\tstr = JSON.stringify(\n\t\t\t\t\t\t\t\targ,\n\t\t\t\t\t\t\t\t// Represent bigint values as strings in JSON.stringify().\n\t\t\t\t\t\t\t\t(key, value) => {\n\t\t\t\t\t\t\t\t\tif (typeof value === 'bigint') {\n\t\t\t\t\t\t\t\t\t\treturn `0x${value.toString(16)}`;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Ignore error and use default representation.\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tstr = String(arg);\n\t\t\t\t\t}\n\n\t\t\t\t\tresult += str;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'd': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += arg.toString();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Math.floor(Number(arg));\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'f': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += Number(arg);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Number(arg);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase 'x': {\n\t\t\t\t\tconst arg = args[argIndex++];\n\t\t\t\t\tif (typeof arg === 'bigint') {\n\t\t\t\t\t\tresult += arg.toString(16);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tresult += Math.floor(Number(arg)).toString(16);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcase '%': {\n\t\t\t\t\tresult += '%';\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tdefault: {\n\t\t\t\t\tresult += '%' + specifier;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tresult += format[i];\n\t\t}\n\t}\n\n\treturn result;\n}\n","import Semaphore, { AcquireTimeoutError } from './semaphore';\nexport { Semaphore, AcquireTimeoutError };\nexport { PhpWasmError } from './php-wasm-error';\nexport type { SemaphoreOptions } from './semaphore';\nexport {\n\tdirname,\n\tjoinPaths,\n\tbasename,\n\tnormalizePath,\n\tisParentOf,\n\tresolvePathUnder,\n\tensureAbsolutePath,\n\ttoPosixPath,\n} from './paths';\nexport { createSpawnHandler } from './create-spawn-handler';\nexport { phpEventStdinTransfer } from './php-event';\nexport type { PHPEventWithStdinTransfer } from './php-event';\nexport {\n\tsendmailSpawnHandler,\n\tSENDMAIL_CAPTURE_MAX_SIZE,\n} from './spawn-handlers/sendmail';\nexport type { PHPSendmailSpawnedEvent } from './spawn-handlers/sendmail';\nexport { randomString } from './random-string';\nexport { randomFilename } from './random-filename';\nexport { splitShellCommand } from './split-shell-command';\nexport { WritablePolyfill, type WritableOptions } from './writable-polyfill';\nexport { EventEmitterPolyfill } from './event-emitter-polyfill';\nexport * from './php-vars';\n\nexport * from './sprintf';\n\nexport function concatUint8Arrays(arrays: Uint8Array[]): Uint8Array {\n\tlet totalLength = 0;\n\tarrays.forEach((a) => (totalLength += a.length));\n\tconst result = new Uint8Array(totalLength);\n\tlet offset = 0;\n\tarrays.forEach((a) => {\n\t\tresult.set(a, offset);\n\t\toffset += a.length;\n\t});\n\treturn result;\n}\n\nexport function concatArrayBuffers(buffers: ArrayBuffer[]): ArrayBuffer {\n\treturn concatUint8Arrays(buffers.map((b) => new Uint8Array(b)))\n\t\t.buffer as ArrayBuffer;\n}\n"],"names":["SleepFinished","sleep","ms","resolve","AcquireTimeoutError","Semaphore","concurrency","timeout","acquired","released","fn","release","PhpWasmError","message","userFriendlyMessage","joinPaths","paths","hasTrailingSlash","p","path","isAbsolute","trailingSlash","normalizePath","resolvePathUnder","parentPath","normalizedParentPath","resolvedPath","isParentOf","dirname","lastSlash","basename","normalizePathsArray","parts","allowAboveRoot","up","i","last","parent","child","ensureAbsolutePath","toPosixPath","nativePath","result","driveMatch","EventEmitterPolyfill","eventName","data","listener","wrappedListener","args","l","splitShellCommand","command","mode","quote","currentPart","char","WritablePolyfill","opts","chunk","encoding","cb","err","defer","needDrain","enc","entry","createSpawnHandler","program","argsArray","options","childProcess","ChildProcess","processApi","ProcessApi","commandArray","promise","e","code","lastPid","pid","self","phpEventStdinTransfer","SENDMAIL_CAPTURE_MAX_SIZE","sendmailSpawnHandler","php","totalLength","dispatched","exceededMaxSize","streamCancelled","controller","stdinStream","streamController","stdin","finish","randomString","length","specialChars","chars","randomFilename","phpVar","value","stringToBase64","phpVars","vars","key","str","bytesToBase64","bytes","binString","sprintf","format","argIndex","specifier","arg","concatUint8Arrays","arrays","a","offset","concatArrayBuffers","buffers","b"],"mappings":"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"} |
+5
-1
@@ -5,4 +5,8 @@ import Semaphore, { AcquireTimeoutError } from './semaphore'; | ||
| export type { SemaphoreOptions } from './semaphore'; | ||
| export { dirname, joinPaths, basename, normalizePath, isParentOf, ensureAbsolutePath, toPosixPath, } from './paths'; | ||
| export { dirname, joinPaths, basename, normalizePath, isParentOf, resolvePathUnder, ensureAbsolutePath, toPosixPath, } from './paths'; | ||
| export { createSpawnHandler } from './create-spawn-handler'; | ||
| export { phpEventStdinTransfer } from './php-event'; | ||
| export type { PHPEventWithStdinTransfer } from './php-event'; | ||
| export { sendmailSpawnHandler, SENDMAIL_CAPTURE_MAX_SIZE, } from './spawn-handlers/sendmail'; | ||
| export type { PHPSendmailSpawnedEvent } from './spawn-handlers/sendmail'; | ||
| export { randomString } from './random-string'; | ||
@@ -9,0 +13,0 @@ export { randomFilename } from './random-filename'; |
+12
-0
@@ -31,2 +31,14 @@ /** | ||
| /** | ||
| * Resolves a path and returns it only when it stays under a parent path. | ||
| * | ||
| * Absolute paths are checked as-is. Relative paths are resolved from the | ||
| * parent path. The parent itself is not considered to be under the parent. | ||
| * Paths containing null bytes are rejected before resolution. | ||
| * | ||
| * @param path The absolute or relative path to resolve. | ||
| * @param parentPath The path the result must stay under. | ||
| * @returns The normalized resolved path, or undefined when it is not a child. | ||
| */ | ||
| export declare function resolvePathUnder(path: string, parentPath: string): string | undefined; | ||
| /** | ||
| * Returns the directory name of a path. | ||
@@ -33,0 +45,0 @@ * |
+2
-2
@@ -7,3 +7,3 @@ { | ||
| }, | ||
| "version": "3.1.44", | ||
| "version": "3.1.45", | ||
| "type": "module", | ||
@@ -31,3 +31,3 @@ "types": "index.d.ts", | ||
| "module": "./index.js", | ||
| "gitHead": "0dbdfe5a210d28802052ef7023d385eb005ff7a4", | ||
| "gitHead": "d8132e032daf7c1ac2fd568af48444d84a59ced2", | ||
| "engines": { | ||
@@ -34,0 +34,0 @@ "node": ">=20.10.0", |
151050
19.14%23
9.52%850
20.57%