@php-wasm/universal 0.5.6 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -1,74 +1,77 @@
1
- var ne = (r, e, t) => {
2
- if (!e.has(r))
3
- throw TypeError("Cannot " + t);
1
+ var K = (e, t, r) => {
2
+ if (!t.has(e))
3
+ throw TypeError("Cannot " + r);
4
4
  };
5
- var a = (r, e, t) => (ne(r, e, "read from private field"), t ? t.call(r) : e.get(r)), c = (r, e, t) => {
6
- if (e.has(r))
5
+ var a = (e, t, r) => (K(e, t, "read from private field"), r ? r.call(e) : t.get(e)), c = (e, t, r) => {
6
+ if (t.has(e))
7
7
  throw TypeError("Cannot add the same private member more than once");
8
- e instanceof WeakSet ? e.add(r) : e.set(r, t);
9
- }, p = (r, e, t, n) => (ne(r, e, "write to private field"), n ? n.call(r, t) : e.set(r, t), t);
10
- var m = (r, e, t) => (ne(r, e, "access private method"), t);
8
+ t instanceof WeakSet ? t.add(e) : t.set(e, r);
9
+ }, u = (e, t, r, s) => (K(e, t, "write to private field"), s ? s.call(e, r) : t.set(e, r), r);
10
+ var f = (e, t, r) => (K(e, t, "access private method"), r);
11
11
  if (typeof File > "u") {
12
- class r extends Blob {
13
- constructor(t, n, s) {
14
- super(t);
15
- let i;
16
- s != null && s.lastModified && (i = /* @__PURE__ */ new Date()), (!i || isNaN(i.getFullYear())) && (i = /* @__PURE__ */ new Date()), this.lastModifiedDate = i, this.lastModified = i.getMilliseconds(), this.name = n || "";
12
+ class e extends Blob {
13
+ constructor(r, s, i) {
14
+ super(r);
15
+ let n;
16
+ i != null && i.lastModified && (n = /* @__PURE__ */ new Date()), (!n || isNaN(n.getFullYear())) && (n = /* @__PURE__ */ new Date()), this.lastModifiedDate = n, this.lastModified = n.getMilliseconds(), this.name = s || "";
17
17
  }
18
18
  }
19
- global.File = r;
19
+ global.File = e;
20
20
  }
21
- function ye(r) {
22
- return new Promise(function(e, t) {
23
- r.onload = r.onerror = function(n) {
24
- r.onload = r.onerror = null, n.type === "load" ? e(r.result) : t(new Error("Failed to read the blob/file"));
21
+ function asPromise(e) {
22
+ return new Promise(function(t, r) {
23
+ e.onload = e.onerror = function(s) {
24
+ e.onload = e.onerror = null, s.type === "load" ? t(e.result) : r(new Error("Failed to read the blob/file"));
25
25
  };
26
26
  });
27
27
  }
28
28
  typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
29
- const e = new FileReader();
30
- return e.readAsArrayBuffer(this), ye(e);
29
+ const t = new FileReader();
30
+ return t.readAsArrayBuffer(this), asPromise(t);
31
31
  });
32
32
  typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
33
- const e = new FileReader();
34
- return e.readAsText(this), ye(e);
33
+ const t = new FileReader();
34
+ return t.readAsText(this), asPromise(t);
35
35
  });
36
- function Le() {
37
- const r = new Uint8Array([1, 2, 3, 4]), t = new File([r], "test").stream();
36
+ function isByobSupported() {
37
+ const e = new Uint8Array([1, 2, 3, 4]), r = new File([e], "test").stream();
38
38
  try {
39
- return t.getReader({ mode: "byob" }), !0;
39
+ return r.getReader({ mode: "byob" }), !0;
40
40
  } catch {
41
41
  return !1;
42
42
  }
43
43
  }
44
- (typeof Blob.prototype.stream > "u" || !Le()) && (Blob.prototype.stream = function() {
45
- let r = 0;
46
- const e = this;
44
+ (typeof Blob.prototype.stream > "u" || !isByobSupported()) && (Blob.prototype.stream = function() {
45
+ let e = 0;
46
+ const t = this;
47
47
  return new ReadableStream({
48
48
  type: "bytes",
49
49
  // 0.5 MB seems like a reasonable chunk size, let's adjust
50
50
  // this if needed.
51
51
  autoAllocateChunkSize: 512 * 1024,
52
- async pull(t) {
53
- const n = t.byobRequest.view, i = await e.slice(r, r + n.byteLength).arrayBuffer(), o = new Uint8Array(i);
54
- new Uint8Array(n.buffer).set(o);
52
+ async pull(r) {
53
+ const s = r.byobRequest.view, n = await t.slice(e, e + s.byteLength).arrayBuffer(), o = new Uint8Array(n);
54
+ new Uint8Array(s.buffer).set(o);
55
55
  const l = o.byteLength;
56
- t.byobRequest.respond(l), r += l, r >= e.size && t.close();
56
+ r.byobRequest.respond(l), e += l, e >= t.size && r.close();
57
57
  }
58
58
  });
59
59
  });
60
60
  if (typeof CustomEvent > "u") {
61
- class r extends Event {
62
- constructor(t, n = {}) {
63
- super(t, n), this.detail = n.detail;
61
+ class e extends Event {
62
+ constructor(r, s = {}) {
63
+ super(r, s), this.detail = s.detail;
64
64
  }
65
65
  initCustomEvent() {
66
66
  }
67
67
  }
68
- globalThis.CustomEvent = r;
68
+ globalThis.CustomEvent = e;
69
69
  }
70
- const ae = Symbol("error"), le = Symbol("message");
71
- class ie extends Event {
70
+ typeof crypto > "u" && import("./__vite-browser-external-2447137e.js").then((e) => {
71
+ global.crypto = e;
72
+ });
73
+ const kError = Symbol("error"), kMessage = Symbol("message");
74
+ class ErrorEvent2 extends Event {
72
75
  /**
73
76
  * Create a new `ErrorEvent`.
74
77
  *
@@ -76,93 +79,93 @@ class ie extends Event {
76
79
  * @param options A dictionary object that allows for setting
77
80
  * attributes via object members of the same name.
78
81
  */
79
- constructor(e, t = {}) {
80
- super(e), this[ae] = t.error === void 0 ? null : t.error, this[le] = t.message === void 0 ? "" : t.message;
82
+ constructor(t, r = {}) {
83
+ super(t), this[kError] = r.error === void 0 ? null : r.error, this[kMessage] = r.message === void 0 ? "" : r.message;
81
84
  }
82
85
  get error() {
83
- return this[ae];
86
+ return this[kError];
84
87
  }
85
88
  get message() {
86
- return this[le];
89
+ return this[kMessage];
87
90
  }
88
91
  }
89
- Object.defineProperty(ie.prototype, "error", { enumerable: !0 });
90
- Object.defineProperty(ie.prototype, "message", { enumerable: !0 });
91
- const Ie = typeof globalThis.ErrorEvent == "function" ? globalThis.ErrorEvent : ie;
92
- function Oe(r) {
93
- return r instanceof Error ? "exitCode" in r && (r == null ? void 0 : r.exitCode) === 0 || (r == null ? void 0 : r.name) === "ExitStatus" && "status" in r && r.status === 0 : !1;
92
+ Object.defineProperty(ErrorEvent2.prototype, "error", { enumerable: !0 });
93
+ Object.defineProperty(ErrorEvent2.prototype, "message", { enumerable: !0 });
94
+ const ErrorEvent = typeof globalThis.ErrorEvent == "function" ? globalThis.ErrorEvent : ErrorEvent2;
95
+ function isExitCodeZero(e) {
96
+ return e instanceof Error ? "exitCode" in e && (e == null ? void 0 : e.exitCode) === 0 || (e == null ? void 0 : e.name) === "ExitStatus" && "status" in e && e.status === 0 : !1;
94
97
  }
95
- class Ne extends EventTarget {
98
+ class UnhandledRejectionsTarget extends EventTarget {
96
99
  constructor() {
97
100
  super(...arguments), this.listenersCount = 0;
98
101
  }
99
- addEventListener(e, t) {
100
- ++this.listenersCount, super.addEventListener(e, t);
102
+ addEventListener(t, r) {
103
+ ++this.listenersCount, super.addEventListener(t, r);
101
104
  }
102
- removeEventListener(e, t) {
103
- --this.listenersCount, super.removeEventListener(e, t);
105
+ removeEventListener(t, r) {
106
+ --this.listenersCount, super.removeEventListener(t, r);
104
107
  }
105
108
  hasListeners() {
106
109
  return this.listenersCount > 0;
107
110
  }
108
111
  }
109
- function qe(r) {
110
- r.asm = {
111
- ...r.asm
112
+ function improveWASMErrorReporting(e) {
113
+ e.asm = {
114
+ ...e.asm
112
115
  };
113
- const e = new Ne();
114
- for (const t in r.asm)
115
- if (typeof r.asm[t] == "function") {
116
- const n = r.asm[t];
117
- r.asm[t] = function(...s) {
118
- var i;
116
+ const t = new UnhandledRejectionsTarget();
117
+ for (const r in e.asm)
118
+ if (typeof e.asm[r] == "function") {
119
+ const s = e.asm[r];
120
+ e.asm[r] = function(...i) {
121
+ var n;
119
122
  try {
120
- return n(...s);
123
+ return s(...i);
121
124
  } catch (o) {
122
125
  if (!(o instanceof Error))
123
126
  throw o;
124
- const l = Me(
127
+ const l = clarifyErrorMessage(
125
128
  o,
126
- (i = r.lastAsyncifyStackSource) == null ? void 0 : i.stack
129
+ (n = e.lastAsyncifyStackSource) == null ? void 0 : n.stack
127
130
  );
128
- if (r.lastAsyncifyStackSource && (o.cause = r.lastAsyncifyStackSource), e.hasListeners()) {
129
- e.dispatchEvent(
130
- new Ie("error", {
131
+ if (e.lastAsyncifyStackSource && (o.cause = e.lastAsyncifyStackSource), t.hasListeners()) {
132
+ t.dispatchEvent(
133
+ new ErrorEvent("error", {
131
134
  error: o,
132
135
  message: l
133
136
  })
134
137
  );
135
138
  return;
136
139
  }
137
- throw Oe(o) || ze(l), o;
140
+ throw isExitCodeZero(o) || showCriticalErrorBox(l), o;
138
141
  }
139
142
  };
140
143
  }
141
- return e;
144
+ return t;
142
145
  }
143
- let se = [];
144
- function De() {
145
- return se;
146
+ let functionsMaybeMissingFromAsyncify = [];
147
+ function getFunctionsMaybeMissingFromAsyncify() {
148
+ return functionsMaybeMissingFromAsyncify;
146
149
  }
147
- function Me(r, e) {
148
- if (r.message === "unreachable") {
149
- let t = je;
150
- e || (t += `
150
+ function clarifyErrorMessage(e, t) {
151
+ if (e.message === "unreachable") {
152
+ let r = UNREACHABLE_ERROR;
153
+ t || (r += `
151
154
 
152
155
  This stack trace is lacking. For a better one initialize
153
156
  the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
154
157
 
155
- `), se = Ge(
156
- e || r.stack || ""
158
+ `), functionsMaybeMissingFromAsyncify = extractPHPFunctionsFromStack(
159
+ t || e.stack || ""
157
160
  );
158
- for (const n of se)
159
- t += ` * ${n}
161
+ for (const s of functionsMaybeMissingFromAsyncify)
162
+ r += ` * ${s}
160
163
  `;
161
- return t;
164
+ return r;
162
165
  }
163
- return r.message;
166
+ return e.message;
164
167
  }
165
- const je = `
168
+ const UNREACHABLE_ERROR = `
166
169
  "unreachable" WASM instruction executed.
167
170
 
168
171
  The typical reason is a PHP function missing from the ASYNCIFY_ONLY
@@ -186,39 +189,39 @@ the Dockerfile, you'll need to trigger this error again with long stack
186
189
  traces enabled. In node.js, you can do it using the --stack-trace-limit=100
187
190
  CLI option:
188
191
 
189
- `, ce = "\x1B[41m", We = "\x1B[1m", ue = "\x1B[0m", he = "\x1B[K";
190
- let de = !1;
191
- function ze(r) {
192
- if (!de && (de = !0, !(r != null && r.trim().startsWith("Program terminated with exit")))) {
193
- console.log(`${ce}
194
- ${he}
195
- ${We} WASM ERROR${ue}${ce}`);
196
- for (const e of r.split(`
192
+ `, redBg = "\x1B[41m", bold = "\x1B[1m", reset = "\x1B[0m", eol = "\x1B[K";
193
+ let logged = !1;
194
+ function showCriticalErrorBox(e) {
195
+ if (!logged && (logged = !0, !(e != null && e.trim().startsWith("Program terminated with exit")))) {
196
+ console.log(`${redBg}
197
+ ${eol}
198
+ ${bold} WASM ERROR${reset}${redBg}`);
199
+ for (const t of e.split(`
197
200
  `))
198
- console.log(`${he} ${e} `);
199
- console.log(`${ue}`);
201
+ console.log(`${eol} ${t} `);
202
+ console.log(`${reset}`);
200
203
  }
201
204
  }
202
- function Ge(r) {
205
+ function extractPHPFunctionsFromStack(e) {
203
206
  try {
204
- const e = r.split(`
205
- `).slice(1).map((t) => {
206
- const n = t.trim().substring(3).split(" ");
207
+ const t = e.split(`
208
+ `).slice(1).map((r) => {
209
+ const s = r.trim().substring(3).split(" ");
207
210
  return {
208
- fn: n.length >= 2 ? n[0] : "<unknown>",
209
- isWasm: t.includes("wasm://")
211
+ fn: s.length >= 2 ? s[0] : "<unknown>",
212
+ isWasm: r.includes("wasm://")
210
213
  };
211
214
  }).filter(
212
- ({ fn: t, isWasm: n }) => n && !t.startsWith("dynCall_") && !t.startsWith("invoke_")
213
- ).map(({ fn: t }) => t);
214
- return Array.from(new Set(e));
215
+ ({ fn: r, isWasm: s }) => s && !r.startsWith("dynCall_") && !r.startsWith("invoke_")
216
+ ).map(({ fn: r }) => r);
217
+ return Array.from(new Set(t));
215
218
  } catch {
216
219
  return [];
217
220
  }
218
221
  }
219
- class we {
220
- constructor({ concurrency: e }) {
221
- this._running = 0, this.concurrency = e, this.queue = [];
222
+ class Semaphore {
223
+ constructor({ concurrency: t }) {
224
+ this._running = 0, this.concurrency = t, this.queue = [];
222
225
  }
223
226
  get running() {
224
227
  return this._running;
@@ -226,116 +229,171 @@ class we {
226
229
  async acquire() {
227
230
  for (; ; )
228
231
  if (this._running >= this.concurrency)
229
- await new Promise((e) => this.queue.push(e));
232
+ await new Promise((t) => this.queue.push(t));
230
233
  else {
231
234
  this._running++;
232
- let e = !1;
235
+ let t = !1;
233
236
  return () => {
234
- e || (e = !0, this._running--, this.queue.length > 0 && this.queue.shift()());
237
+ t || (t = !0, this._running--, this.queue.length > 0 && this.queue.shift()());
235
238
  };
236
239
  }
237
240
  }
238
- async run(e) {
239
- const t = await this.acquire();
241
+ async run(t) {
242
+ const r = await this.acquire();
240
243
  try {
241
- return await e();
244
+ return await t();
242
245
  } finally {
243
- t();
246
+ r();
244
247
  }
245
248
  }
246
249
  }
247
- function ge(...r) {
248
- let e = r.join("/");
249
- const t = e[0] === "/", n = e.substring(e.length - 1) === "/";
250
- return e = oe(e), !e && !t && (e = "."), e && n && (e += "/"), e;
250
+ function joinPaths(...e) {
251
+ let t = e.join("/");
252
+ const r = t[0] === "/", s = t.substring(t.length - 1) === "/";
253
+ return t = normalizePath(t), !t && !r && (t = "."), t && s && (t += "/"), t;
251
254
  }
252
- function Ve(r) {
253
- if (r === "/")
255
+ function dirname(e) {
256
+ if (e === "/")
254
257
  return "/";
255
- r = oe(r);
256
- const e = r.lastIndexOf("/");
257
- return e === -1 ? "" : e === 0 ? "/" : r.substr(0, e);
258
+ e = normalizePath(e);
259
+ const t = e.lastIndexOf("/");
260
+ return t === -1 ? "" : t === 0 ? "/" : e.substr(0, t);
258
261
  }
259
- function oe(r) {
260
- const e = r[0] === "/";
261
- return r = Je(
262
- r.split("/").filter((t) => !!t),
263
- !e
264
- ).join("/"), (e ? "/" : "") + r.replace(/\/$/, "");
262
+ function normalizePath(e) {
263
+ const t = e[0] === "/";
264
+ return e = normalizePathsArray(
265
+ e.split("/").filter((r) => !!r),
266
+ !t
267
+ ).join("/"), (t ? "/" : "") + e.replace(/\/$/, "");
265
268
  }
266
- function Je(r, e) {
267
- let t = 0;
268
- for (let n = r.length - 1; n >= 0; n--) {
269
- const s = r[n];
270
- s === "." ? r.splice(n, 1) : s === ".." ? (r.splice(n, 1), t++) : t && (r.splice(n, 1), t--);
271
- }
272
- if (e)
273
- for (; t; t--)
274
- r.unshift("..");
275
- return r;
269
+ function normalizePathsArray(e, t) {
270
+ let r = 0;
271
+ for (let s = e.length - 1; s >= 0; s--) {
272
+ const i = e[s];
273
+ i === "." ? e.splice(s, 1) : i === ".." ? (e.splice(s, 1), r++) : r && (e.splice(s, 1), r--);
274
+ }
275
+ if (t)
276
+ for (; r; r--)
277
+ e.unshift("..");
278
+ return e;
279
+ }
280
+ function createSpawnHandler(e) {
281
+ return function(t) {
282
+ const r = new ChildProcess(), s = new ProcessApi(r);
283
+ return setTimeout(async () => {
284
+ await e(t, s), r.emit("spawn", !0);
285
+ }), r;
286
+ };
287
+ }
288
+ class EventEmitter {
289
+ constructor() {
290
+ this.listeners = {};
291
+ }
292
+ emit(t, r) {
293
+ this.listeners[t] && this.listeners[t].forEach(function(s) {
294
+ s(r);
295
+ });
296
+ }
297
+ on(t, r) {
298
+ this.listeners[t] || (this.listeners[t] = []), this.listeners[t].push(r);
299
+ }
300
+ }
301
+ class ProcessApi extends EventEmitter {
302
+ constructor(t) {
303
+ super(), this.childProcess = t, this.exited = !1, this.stdinData = [], t.on("stdin", (r) => {
304
+ this.stdinData ? this.stdinData.push(r.slice()) : this.emit("stdin", r);
305
+ });
306
+ }
307
+ stdout(t) {
308
+ typeof t == "string" && (t = new TextEncoder().encode(t)), this.childProcess.stdout.emit("data", t);
309
+ }
310
+ stderr(t) {
311
+ typeof t == "string" && (t = new TextEncoder().encode(t)), this.childProcess.stderr.emit("data", t);
312
+ }
313
+ exit(t) {
314
+ this.exited || (this.exited = !0, this.childProcess.emit("exit", t));
315
+ }
316
+ flushStdin() {
317
+ if (this.stdinData)
318
+ for (let t = 0; t < this.stdinData.length; t++)
319
+ this.emit("stdin", this.stdinData[t]);
320
+ this.stdinData = null;
321
+ }
322
+ }
323
+ let lastPid = 9743;
324
+ class ChildProcess extends EventEmitter {
325
+ constructor(t = lastPid++) {
326
+ super(), this.pid = t, this.stdout = new EventEmitter(), this.stderr = new EventEmitter();
327
+ const r = this;
328
+ this.stdin = {
329
+ write: (s) => {
330
+ r.emit("stdin", s);
331
+ }
332
+ };
333
+ }
276
334
  }
277
- function Ye(...r) {
278
- const e = new Uint8Array(
279
- r.reduce((n, s) => n + s.length, 0)
335
+ function concatUint8Array(...e) {
336
+ const t = new Uint8Array(
337
+ e.reduce((s, i) => s + i.length, 0)
280
338
  );
281
- let t = 0;
282
- for (const n of r)
283
- e.set(n, t), t += n.length;
284
- return e;
339
+ let r = 0;
340
+ for (const s of e)
341
+ t.set(s, r), r += s.length;
342
+ return t;
285
343
  }
286
- function Ke(r) {
287
- if (r === void 0) {
288
- let e = new Uint8Array();
344
+ function concatBytes(e) {
345
+ if (e === void 0) {
346
+ let t = new Uint8Array();
289
347
  return new TransformStream({
290
- transform(t) {
291
- e = Ye(e, t);
348
+ transform(r) {
349
+ t = concatUint8Array(t, r);
292
350
  },
293
- flush(t) {
294
- t.enqueue(e);
351
+ flush(r) {
352
+ r.enqueue(t);
295
353
  }
296
354
  });
297
355
  } else {
298
- const e = new ArrayBuffer(r || 0);
299
- let t = 0;
356
+ const t = new ArrayBuffer(e || 0);
357
+ let r = 0;
300
358
  return new TransformStream({
301
- transform(n) {
302
- new Uint8Array(e).set(n, t), t += n.byteLength;
359
+ transform(s) {
360
+ new Uint8Array(t).set(s, r), r += s.byteLength;
303
361
  },
304
- flush(n) {
305
- n.enqueue(new Uint8Array(e));
362
+ flush(s) {
363
+ s.enqueue(new Uint8Array(t));
306
364
  }
307
365
  });
308
366
  }
309
367
  }
310
- function Ze(r, e) {
311
- if (e === 0)
368
+ function limitBytes(e, t) {
369
+ if (t === 0)
312
370
  return new ReadableStream({
313
- start(s) {
314
- s.close();
371
+ start(i) {
372
+ i.close();
315
373
  }
316
374
  });
317
- const t = r.getReader({ mode: "byob" });
318
- let n = 0;
375
+ const r = e.getReader({ mode: "byob" });
376
+ let s = 0;
319
377
  return new ReadableStream({
320
- async pull(s) {
321
- const { value: i, done: o } = await t.read(
322
- new Uint8Array(e - n)
378
+ async pull(i) {
379
+ const { value: n, done: o } = await r.read(
380
+ new Uint8Array(t - s)
323
381
  );
324
382
  if (o) {
325
- t.releaseLock(), s.close();
383
+ r.releaseLock(), i.close();
326
384
  return;
327
385
  }
328
- n += i.length, s.enqueue(i), n >= e && (t.releaseLock(), s.close());
386
+ s += n.length, i.enqueue(n), s >= t && (r.releaseLock(), i.close());
329
387
  },
330
388
  cancel() {
331
- t.cancel();
389
+ r.cancel();
332
390
  }
333
391
  });
334
392
  }
335
- async function Qe(r, e) {
336
- return e !== void 0 && (r = Ze(r, e)), await r.pipeThrough(Ke(e)).getReader().read().then(({ value: t }) => t);
393
+ async function collectBytes(e, t) {
394
+ return t !== void 0 && (e = limitBytes(e, t)), await e.pipeThrough(concatBytes(t)).getReader().read().then(({ value: r }) => r);
337
395
  }
338
- class Xe extends File {
396
+ class StreamedFile extends File {
339
397
  /**
340
398
  * Creates a new StreamedFile instance.
341
399
  *
@@ -343,8 +401,8 @@ class Xe extends File {
343
401
  * @param name The name of the file.
344
402
  * @param type The MIME type of the file.
345
403
  */
346
- constructor(e, t, n) {
347
- super([], t, { type: n }), this.readableStream = e;
404
+ constructor(t, r, s) {
405
+ super([], r, { type: s }), this.readableStream = t;
348
406
  }
349
407
  /**
350
408
  * Overrides the slice() method of the File class.
@@ -376,79 +434,79 @@ class Xe extends File {
376
434
  * @returns File data as an ArrayBuffer.
377
435
  */
378
436
  async arrayBuffer() {
379
- return await Qe(this.stream());
437
+ return await collectBytes(this.stream());
380
438
  }
381
439
  }
382
440
  ReadableStream.prototype[Symbol.asyncIterator] || (ReadableStream.prototype[Symbol.asyncIterator] = async function* () {
383
- const r = this.getReader();
441
+ const e = this.getReader();
384
442
  try {
385
443
  for (; ; ) {
386
- const { done: e, value: t } = await r.read();
387
- if (e)
444
+ const { done: t, value: r } = await e.read();
445
+ if (t)
388
446
  return;
389
- yield t;
447
+ yield r;
390
448
  }
391
449
  } finally {
392
- r.releaseLock();
450
+ e.releaseLock();
393
451
  }
394
452
  }, ReadableStream.prototype.iterate = // @ts-ignore
395
453
  ReadableStream.prototype[Symbol.asyncIterator]);
396
- function et(r, e) {
454
+ function streamReadFileFromPHP(e, t) {
397
455
  return new ReadableStream({
398
- async pull(t) {
399
- const n = await r.readFileAsBuffer(e);
400
- t.enqueue(n), t.close();
456
+ async pull(r) {
457
+ const s = await e.readFileAsBuffer(t);
458
+ r.enqueue(s), r.close();
401
459
  }
402
460
  });
403
461
  }
404
- async function* bt(r, e, {
405
- relativePaths: t = !0,
406
- pathPrefix: n,
407
- exceptPaths: s = []
462
+ async function* iteratePhpFiles(e, t, {
463
+ relativePaths: r = !0,
464
+ pathPrefix: s,
465
+ exceptPaths: i = []
408
466
  } = {}) {
409
- e = oe(e);
410
- const i = [e];
411
- for (; i.length; ) {
412
- const o = i.pop();
467
+ t = normalizePath(t);
468
+ const n = [t];
469
+ for (; n.length; ) {
470
+ const o = n.pop();
413
471
  if (!o)
414
472
  return;
415
- const l = await r.listFiles(o);
416
- for (const d of l) {
417
- const f = `${o}/${d}`;
418
- if (s.includes(f.substring(e.length + 1)))
473
+ const l = await e.listFiles(o);
474
+ for (const h of l) {
475
+ const d = `${o}/${h}`;
476
+ if (i.includes(d.substring(t.length + 1)))
419
477
  continue;
420
- await r.isDir(f) ? i.push(f) : yield new Xe(
421
- et(r, f),
422
- t ? ge(
423
- n || "",
424
- f.substring(e.length + 1)
425
- ) : f
478
+ await e.isDir(d) ? n.push(d) : yield new StreamedFile(
479
+ streamReadFileFromPHP(e, d),
480
+ r ? joinPaths(
481
+ s || "",
482
+ d.substring(t.length + 1)
483
+ ) : d
426
484
  );
427
485
  }
428
486
  }
429
487
  }
430
- function Pt(r, e) {
488
+ function writeFilesStreamToPhp(e, t) {
431
489
  return new WritableStream({
432
- async write(t) {
433
- const n = ge(e, t.name);
434
- t.type === "directory" ? await r.mkdir(n) : (await r.mkdir(Ve(n)), await r.writeFile(
435
- n,
436
- new Uint8Array(await t.arrayBuffer())
490
+ async write(r) {
491
+ const s = joinPaths(t, r.name);
492
+ r.type === "directory" ? await e.mkdir(s) : (await e.mkdir(dirname(s)), await e.writeFile(
493
+ s,
494
+ new Uint8Array(await r.arrayBuffer())
437
495
  ));
438
496
  }
439
497
  });
440
498
  }
441
- class H {
442
- constructor(e, t, n, s = "", i = 0) {
443
- this.httpStatusCode = e, this.headers = t, this.bytes = n, this.exitCode = i, this.errors = s;
444
- }
445
- static fromRawData(e) {
446
- return new H(
447
- e.httpStatusCode,
448
- e.headers,
449
- e.bytes,
450
- e.errors,
451
- e.exitCode
499
+ class PHPResponse {
500
+ constructor(t, r, s, i = "", n = 0) {
501
+ this.httpStatusCode = t, this.headers = r, this.bytes = s, this.exitCode = n, this.errors = i;
502
+ }
503
+ static fromRawData(t) {
504
+ return new PHPResponse(
505
+ t.httpStatusCode,
506
+ t.headers,
507
+ t.bytes,
508
+ t.errors,
509
+ t.exitCode
452
510
  );
453
511
  }
454
512
  toRawData() {
@@ -473,7 +531,7 @@ class H {
473
531
  return new TextDecoder().decode(this.bytes);
474
532
  }
475
533
  }
476
- const be = [
534
+ const SupportedPHPVersions = [
477
535
  "8.3",
478
536
  "8.2",
479
537
  "8.1",
@@ -483,27 +541,27 @@ const be = [
483
541
  "7.2",
484
542
  "7.1",
485
543
  "7.0"
486
- ], Et = be[0], St = be, tt = [
544
+ ], LatestSupportedPHPVersion = SupportedPHPVersions[0], SupportedPHPVersionsList = SupportedPHPVersions, SupportedPHPExtensionsList = [
487
545
  "iconv",
488
546
  "mbstring",
489
547
  "xml-bundle",
490
548
  "gd"
491
- ], vt = {
492
- "kitchen-sink": tt
549
+ ], SupportedPHPExtensionBundles = {
550
+ "kitchen-sink": SupportedPHPExtensionsList
493
551
  };
494
- var _, A;
495
- class rt {
552
+ var E, H;
553
+ class PHPBrowser {
496
554
  /**
497
555
  * @param server - The PHP server to browse.
498
556
  * @param config - The browser configuration.
499
557
  */
500
- constructor(e, t = {}) {
501
- c(this, _, void 0);
502
- c(this, A, void 0);
503
- this.requestHandler = e, p(this, _, {}), p(this, A, {
558
+ constructor(t, r = {}) {
559
+ c(this, E, void 0);
560
+ c(this, H, void 0);
561
+ this.requestHandler = t, u(this, E, {}), u(this, H, {
504
562
  handleRedirects: !1,
505
563
  maxRedirects: 4,
506
- ...t
564
+ ...r
507
565
  });
508
566
  }
509
567
  /**
@@ -520,37 +578,37 @@ class rt {
520
578
  * @param redirects - Internal. The number of redirects handled so far.
521
579
  * @returns PHPRequestHandler response.
522
580
  */
523
- async request(e, t = 0) {
524
- const n = await this.requestHandler.request({
525
- ...e,
581
+ async request(t, r = 0) {
582
+ const s = await this.requestHandler.request({
583
+ ...t,
526
584
  headers: {
527
- ...e.headers,
585
+ ...t.headers,
528
586
  cookie: this.serializeCookies()
529
587
  }
530
588
  });
531
- if (n.headers["set-cookie"] && this.setCookies(n.headers["set-cookie"]), a(this, A).handleRedirects && n.headers.location && t < a(this, A).maxRedirects) {
532
- const s = new URL(
533
- n.headers.location[0],
589
+ if (s.headers["set-cookie"] && this.setCookies(s.headers["set-cookie"]), a(this, H).handleRedirects && s.headers.location && r < a(this, H).maxRedirects) {
590
+ const i = new URL(
591
+ s.headers.location[0],
534
592
  this.requestHandler.absoluteUrl
535
593
  );
536
594
  return this.request(
537
595
  {
538
- url: s.toString(),
596
+ url: i.toString(),
539
597
  method: "GET",
540
598
  headers: {}
541
599
  },
542
- t + 1
600
+ r + 1
543
601
  );
544
602
  }
545
- return n;
603
+ return s;
546
604
  }
547
605
  /** @inheritDoc */
548
- pathToInternalUrl(e) {
549
- return this.requestHandler.pathToInternalUrl(e);
606
+ pathToInternalUrl(t) {
607
+ return this.requestHandler.pathToInternalUrl(t);
550
608
  }
551
609
  /** @inheritDoc */
552
- internalUrlToPath(e) {
553
- return this.requestHandler.internalUrlToPath(e);
610
+ internalUrlToPath(t) {
611
+ return this.requestHandler.internalUrlToPath(t);
554
612
  }
555
613
  /** @inheritDoc */
556
614
  get absoluteUrl() {
@@ -560,49 +618,49 @@ class rt {
560
618
  get documentRoot() {
561
619
  return this.requestHandler.documentRoot;
562
620
  }
563
- setCookies(e) {
564
- for (const t of e)
621
+ setCookies(t) {
622
+ for (const r of t)
565
623
  try {
566
- if (!t.includes("="))
624
+ if (!r.includes("="))
567
625
  continue;
568
- const n = t.indexOf("="), s = t.substring(0, n), i = t.substring(n + 1).split(";")[0];
569
- a(this, _)[s] = i;
570
- } catch (n) {
571
- console.error(n);
626
+ const s = r.indexOf("="), i = r.substring(0, s), n = r.substring(s + 1).split(";")[0];
627
+ a(this, E)[i] = n;
628
+ } catch (s) {
629
+ console.error(s);
572
630
  }
573
631
  }
574
632
  serializeCookies() {
575
- const e = [];
576
- for (const t in a(this, _))
577
- e.push(`${t}=${a(this, _)[t]}`);
578
- return e.join("; ");
633
+ const t = [];
634
+ for (const r in a(this, E))
635
+ t.push(`${r}=${a(this, E)[r]}`);
636
+ return t.join("; ");
579
637
  }
580
638
  }
581
- _ = new WeakMap(), A = new WeakMap();
582
- const nt = "http://example.com";
583
- function fe(r) {
584
- return r.toString().substring(r.origin.length);
639
+ E = new WeakMap(), H = new WeakMap();
640
+ const DEFAULT_BASE_URL = "http://example.com";
641
+ function toRelativeUrl(e) {
642
+ return e.toString().substring(e.origin.length);
585
643
  }
586
- function pe(r, e) {
587
- return !e || !r.startsWith(e) ? r : r.substring(e.length);
644
+ function removePathPrefix(e, t) {
645
+ return !t || !e.startsWith(t) ? e : e.substring(t.length);
588
646
  }
589
- function st(r, e) {
590
- return !e || r.startsWith(e) ? r : e + r;
647
+ function ensurePathPrefix(e, t) {
648
+ return !t || e.startsWith(t) ? e : t + e;
591
649
  }
592
- var g, $, O, F, U, b, B, L, M, Pe, j, Ee, W, Se;
593
- class it {
650
+ var P, x, A, v, F, m, T, R, L, Q, N, X, M, ee;
651
+ class PHPRequestHandler {
594
652
  /**
595
653
  * @param php - The PHP instance.
596
654
  * @param config - Request Handler configuration.
597
655
  */
598
- constructor(e, t = {}) {
656
+ constructor(t, r = {}) {
599
657
  /**
600
658
  * Serves a static file from the PHP filesystem.
601
659
  *
602
660
  * @param fsPath - Absolute path of the static file to serve.
603
661
  * @returns The response.
604
662
  */
605
- c(this, M);
663
+ c(this, L);
606
664
  /**
607
665
  * Runs the requested PHP file with all the request and $_SERVER
608
666
  * superglobals populated.
@@ -610,7 +668,7 @@ class it {
610
668
  * @param request - The request.
611
669
  * @returns The response.
612
670
  */
613
- c(this, j);
671
+ c(this, N);
614
672
  /**
615
673
  * Resolve the requested path to the filesystem path of the requested PHP file.
616
674
  *
@@ -620,68 +678,68 @@ class it {
620
678
  * @throws {Error} If the requested path doesn't exist.
621
679
  * @returns The resolved filesystem path.
622
680
  */
623
- c(this, W);
624
- c(this, g, void 0);
625
- c(this, $, void 0);
626
- c(this, O, void 0);
681
+ c(this, M);
682
+ c(this, P, void 0);
683
+ c(this, x, void 0);
684
+ c(this, A, void 0);
685
+ c(this, v, void 0);
627
686
  c(this, F, void 0);
628
- c(this, U, void 0);
629
- c(this, b, void 0);
630
- c(this, B, void 0);
631
- c(this, L, void 0);
632
- p(this, L, new we({ concurrency: 1 }));
687
+ c(this, m, void 0);
688
+ c(this, T, void 0);
689
+ c(this, R, void 0);
690
+ u(this, R, new Semaphore({ concurrency: 1 }));
633
691
  const {
634
- documentRoot: n = "/www/",
635
- absoluteUrl: s = typeof location == "object" ? location == null ? void 0 : location.href : ""
636
- } = t;
637
- this.php = e, p(this, g, n);
638
- const i = new URL(s);
639
- p(this, O, i.hostname), p(this, F, i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80), p(this, $, (i.protocol || "").replace(":", ""));
640
- const o = a(this, F) !== 443 && a(this, F) !== 80;
641
- p(this, U, [
642
- a(this, O),
643
- o ? `:${a(this, F)}` : ""
644
- ].join("")), p(this, b, i.pathname.replace(/\/+$/, "")), p(this, B, [
645
- `${a(this, $)}://`,
646
- a(this, U),
647
- a(this, b)
692
+ documentRoot: s = "/www/",
693
+ absoluteUrl: i = typeof location == "object" ? location == null ? void 0 : location.href : ""
694
+ } = r;
695
+ this.php = t, u(this, P, s);
696
+ const n = new URL(i);
697
+ u(this, A, n.hostname), u(this, v, n.port ? Number(n.port) : n.protocol === "https:" ? 443 : 80), u(this, x, (n.protocol || "").replace(":", ""));
698
+ const o = a(this, v) !== 443 && a(this, v) !== 80;
699
+ u(this, F, [
700
+ a(this, A),
701
+ o ? `:${a(this, v)}` : ""
702
+ ].join("")), u(this, m, n.pathname.replace(/\/+$/, "")), u(this, T, [
703
+ `${a(this, x)}://`,
704
+ a(this, F),
705
+ a(this, m)
648
706
  ].join(""));
649
707
  }
650
708
  /** @inheritDoc */
651
- pathToInternalUrl(e) {
652
- return `${this.absoluteUrl}${e}`;
709
+ pathToInternalUrl(t) {
710
+ return `${this.absoluteUrl}${t}`;
653
711
  }
654
712
  /** @inheritDoc */
655
- internalUrlToPath(e) {
656
- const t = new URL(e);
657
- return t.pathname.startsWith(a(this, b)) && (t.pathname = t.pathname.slice(a(this, b).length)), fe(t);
713
+ internalUrlToPath(t) {
714
+ const r = new URL(t);
715
+ return r.pathname.startsWith(a(this, m)) && (r.pathname = r.pathname.slice(a(this, m).length)), toRelativeUrl(r);
658
716
  }
659
717
  get isRequestRunning() {
660
- return a(this, L).running > 0;
718
+ return a(this, R).running > 0;
661
719
  }
662
720
  /** @inheritDoc */
663
721
  get absoluteUrl() {
664
- return a(this, B);
722
+ return a(this, T);
665
723
  }
666
724
  /** @inheritDoc */
667
725
  get documentRoot() {
668
- return a(this, g);
726
+ return a(this, P);
669
727
  }
670
728
  /** @inheritDoc */
671
- async request(e) {
672
- const t = e.url.startsWith("http://") || e.url.startsWith("https://"), n = new URL(
673
- e.url,
674
- t ? void 0 : nt
675
- ), s = pe(
676
- n.pathname,
677
- a(this, b)
678
- ), i = `${a(this, g)}${s}`;
679
- return lt(i) ? await m(this, j, Ee).call(this, e, n) : m(this, M, Pe).call(this, i);
729
+ async request(t) {
730
+ const r = t.url.startsWith("http://") || t.url.startsWith("https://"), s = new URL(
731
+ t.url,
732
+ r ? void 0 : DEFAULT_BASE_URL
733
+ ), i = removePathPrefix(
734
+ s.pathname,
735
+ a(this, m)
736
+ ), n = `${a(this, P)}${i}`;
737
+ return seemsLikeAPHPRequestHandlerPath(n) ? await f(this, N, X).call(this, t, s) : f(this, L, Q).call(this, n);
680
738
  }
681
739
  }
682
- g = new WeakMap(), $ = new WeakMap(), O = new WeakMap(), F = new WeakMap(), U = new WeakMap(), b = new WeakMap(), B = new WeakMap(), L = new WeakMap(), M = new WeakSet(), Pe = function(e) {
683
- if (!this.php.fileExists(e))
684
- return new H(
740
+ P = new WeakMap(), x = new WeakMap(), A = new WeakMap(), v = new WeakMap(), F = new WeakMap(), m = new WeakMap(), T = new WeakMap(), R = new WeakMap(), L = new WeakSet(), Q = function(t) {
741
+ if (!this.php.fileExists(t))
742
+ return new PHPResponse(
685
743
  404,
686
744
  // Let the service worker know that no static file was found
687
745
  // and that it's okay to issue a real fetch() to the server.
@@ -690,104 +748,118 @@ g = new WeakMap(), $ = new WeakMap(), O = new WeakMap(), F = new WeakMap(), U =
690
748
  },
691
749
  new TextEncoder().encode("404 File not found")
692
750
  );
693
- const t = this.php.readFileAsBuffer(e);
694
- return new H(
751
+ const r = this.php.readFileAsBuffer(t);
752
+ return new PHPResponse(
695
753
  200,
696
754
  {
697
- "content-length": [`${t.byteLength}`],
755
+ "content-length": [`${r.byteLength}`],
698
756
  // @TODO: Infer the content-type from the arrayBuffer instead of the file path.
699
757
  // The code below won't return the correct mime-type if the extension
700
758
  // was tampered with.
701
- "content-type": [at(e)],
759
+ "content-type": [inferMimeType(t)],
702
760
  "accept-ranges": ["bytes"],
703
761
  "cache-control": ["public, max-age=0"]
704
762
  },
705
- t
763
+ r
706
764
  );
707
- }, j = new WeakSet(), Ee = async function(e, t) {
708
- var s;
709
- const n = await a(this, L).acquire();
765
+ }, N = new WeakSet(), X = async function(t, r) {
766
+ var i, n, o;
767
+ if (a(this, R).running > 0 && ((i = t.headers) == null ? void 0 : i["x-request-issuer"]) === "php")
768
+ return console.warn(
769
+ "Possible deadlock: Called request() before the previous request() have finished. PHP likely issued an HTTP call to itself. Normally this would lead to infinite waiting as Request 1 holds the lock that the Request 2 is waiting to acquire. That's not useful, so PHPRequestHandler will return error 502 instead."
770
+ ), new PHPResponse(
771
+ 502,
772
+ {},
773
+ new TextEncoder().encode("502 Bad Gateway")
774
+ );
775
+ const s = await a(this, R).acquire();
710
776
  try {
711
- this.php.addServerGlobalEntry("DOCUMENT_ROOT", a(this, g)), this.php.addServerGlobalEntry(
777
+ this.php.addServerGlobalEntry("REMOTE_ADDR", "127.0.0.1"), this.php.addServerGlobalEntry("DOCUMENT_ROOT", a(this, P)), this.php.addServerGlobalEntry(
712
778
  "HTTPS",
713
- a(this, B).startsWith("https://") ? "on" : ""
779
+ a(this, T).startsWith("https://") ? "on" : ""
714
780
  );
715
- let i = "GET";
716
- const o = {
717
- host: a(this, U),
718
- ...Be(e.headers || {})
719
- }, l = [];
720
- if (e.files && Object.keys(e.files).length) {
721
- i = "POST";
722
- for (const h in e.files) {
723
- const S = e.files[h];
724
- l.push({
725
- key: h,
726
- name: S.name,
727
- type: S.type,
728
- data: new Uint8Array(await S.arrayBuffer())
781
+ let l = "GET";
782
+ const h = {
783
+ host: a(this, F),
784
+ ...normalizeHeaders(t.headers || {})
785
+ }, d = [];
786
+ if (t.files && Object.keys(t.files).length) {
787
+ l = "POST";
788
+ for (const S in t.files) {
789
+ const U = t.files[S];
790
+ d.push({
791
+ key: S,
792
+ name: U.name,
793
+ type: U.type,
794
+ data: new Uint8Array(await U.arrayBuffer())
729
795
  });
730
796
  }
731
- (s = o["content-type"]) != null && s.startsWith("multipart/form-data") && (e.formData = ot(
732
- e.body || ""
733
- ), o["content-type"] = "application/x-www-form-urlencoded", delete e.body);
797
+ (n = h["content-type"]) != null && n.startsWith("multipart/form-data") && (t.formData = parseMultipartFormDataString(
798
+ t.body || ""
799
+ ), h["content-type"] = "application/x-www-form-urlencoded", delete t.body);
734
800
  }
735
- let d;
736
- e.formData !== void 0 ? (i = "POST", o["content-type"] = o["content-type"] || "application/x-www-form-urlencoded", d = new URLSearchParams(
737
- e.formData
738
- ).toString()) : d = e.body;
739
- let f;
801
+ let p;
802
+ t.formData !== void 0 ? (l = "POST", h["content-type"] = h["content-type"] || "application/x-www-form-urlencoded", p = new URLSearchParams(
803
+ t.formData
804
+ ).toString()) : p = t.body;
805
+ let I;
740
806
  try {
741
- f = m(this, W, Se).call(this, t.pathname);
807
+ let S = r.pathname;
808
+ if ((o = t.headers) != null && o["x-rewrite-url"])
809
+ try {
810
+ S = new URL(
811
+ t.headers["x-rewrite-url"]
812
+ ).pathname;
813
+ } catch {
814
+ }
815
+ I = f(this, M, ee).call(this, S);
742
816
  } catch {
743
- return new H(
817
+ return new PHPResponse(
744
818
  404,
745
819
  {},
746
820
  new TextEncoder().encode("404 File not found")
747
821
  );
748
822
  }
749
823
  return await this.php.run({
750
- relativeUri: st(
751
- fe(t),
752
- a(this, b)
824
+ relativeUri: ensurePathPrefix(
825
+ toRelativeUrl(r),
826
+ a(this, m)
753
827
  ),
754
- protocol: a(this, $),
755
- method: e.method || i,
756
- body: d,
757
- fileInfos: l,
758
- scriptPath: f,
759
- headers: o
828
+ protocol: a(this, x),
829
+ method: t.method || l,
830
+ body: p,
831
+ fileInfos: d,
832
+ scriptPath: I,
833
+ headers: h
760
834
  });
761
835
  } finally {
762
- n();
763
- }
764
- }, W = new WeakSet(), Se = function(e) {
765
- let t = pe(e, a(this, b));
766
- t.includes(".php") ? t = t.split(".php")[0] + ".php" : (t.endsWith("/") || (t += "/"), t.endsWith("index.php") || (t += "index.php"));
767
- const n = `${a(this, g)}${t}`;
768
- if (this.php.fileExists(n))
769
- return n;
770
- if (!this.php.fileExists(`${a(this, g)}/index.php`))
771
- throw new Error(`File not found: ${n}`);
772
- return `${a(this, g)}/index.php`;
836
+ s();
837
+ }
838
+ }, M = new WeakSet(), ee = function(t) {
839
+ let r = removePathPrefix(t, a(this, m));
840
+ r.includes(".php") ? r = r.split(".php")[0] + ".php" : (r.endsWith("/") || (r += "/"), r.endsWith("index.php") || (r += "index.php"));
841
+ const s = `${a(this, P)}${r}`;
842
+ if (this.php.fileExists(s))
843
+ return s;
844
+ throw new Error(`File not found: ${s}`);
773
845
  };
774
- function ot(r) {
775
- const e = {}, t = r.match(/--(.*)\r\n/);
776
- if (!t)
777
- return e;
778
- const n = t[1], s = r.split(`--${n}`);
779
- return s.shift(), s.pop(), s.forEach((i) => {
780
- const o = i.indexOf(`\r
846
+ function parseMultipartFormDataString(e) {
847
+ const t = {}, r = e.match(/--(.*)\r\n/);
848
+ if (!r)
849
+ return t;
850
+ const s = r[1], i = e.split(`--${s}`);
851
+ return i.shift(), i.pop(), i.forEach((n) => {
852
+ const o = n.indexOf(`\r
781
853
  \r
782
- `), l = i.substring(0, o).trim(), d = i.substring(o + 4).trim(), f = l.match(/name="([^"]+)"/);
783
- if (f) {
784
- const h = f[1];
785
- e[h] = d;
854
+ `), l = n.substring(0, o).trim(), h = n.substring(o + 4).trim(), d = l.match(/name="([^"]+)"/);
855
+ if (d) {
856
+ const p = d[1];
857
+ t[p] = h;
786
858
  }
787
- }), e;
859
+ }), t;
788
860
  }
789
- function at(r) {
790
- switch (r.split(".").pop()) {
861
+ function inferMimeType(e) {
862
+ switch (e.split(".").pop()) {
791
863
  case "css":
792
864
  return "text/css";
793
865
  case "js":
@@ -826,16 +898,16 @@ function at(r) {
826
898
  return "application-octet-stream";
827
899
  }
828
900
  }
829
- function lt(r) {
830
- return ct(r) || ut(r);
901
+ function seemsLikeAPHPRequestHandlerPath(e) {
902
+ return seemsLikeAPHPFile(e) || seemsLikeADirectoryRoot(e);
831
903
  }
832
- function ct(r) {
833
- return r.endsWith(".php") || r.includes(".php/");
904
+ function seemsLikeAPHPFile(e) {
905
+ return e.endsWith(".php") || e.includes(".php/");
834
906
  }
835
- function ut(r) {
836
- return !r.split("/").pop().includes(".");
907
+ function seemsLikeADirectoryRoot(e) {
908
+ return !e.split("/").pop().includes(".");
837
909
  }
838
- const D = {
910
+ const FileErrorCodes = {
839
911
  0: "No error occurred. System call completed successfully.",
840
912
  1: "Argument list too long.",
841
913
  2: "Permission denied.",
@@ -914,22 +986,22 @@ const D = {
914
986
  75: "Cross-device link.",
915
987
  76: "Extension: Capabilities insufficient."
916
988
  };
917
- function ht(r) {
918
- const e = typeof r == "object" ? r == null ? void 0 : r.errno : null;
919
- if (e in D)
920
- return D[e];
989
+ function getEmscriptenFsError(e) {
990
+ const t = typeof e == "object" ? e == null ? void 0 : e.errno : null;
991
+ if (t in FileErrorCodes)
992
+ return FileErrorCodes[t];
921
993
  }
922
- function P(r = "") {
923
- return function(t, n, s) {
924
- const i = s.value;
925
- s.value = function(...o) {
994
+ function rethrowFileSystemError(e = "") {
995
+ return function(r, s, i) {
996
+ const n = i.value;
997
+ i.value = function(...o) {
926
998
  try {
927
- return i.apply(this, o);
999
+ return n.apply(this, o);
928
1000
  } catch (l) {
929
- const d = typeof l == "object" ? l == null ? void 0 : l.errno : null;
930
- if (d in D) {
931
- const f = D[d], h = typeof o[0] == "string" ? o[0] : null, S = h !== null ? r.replaceAll("{path}", h) : r;
932
- throw new Error(`${S}: ${f}`, {
1001
+ const h = typeof l == "object" ? l == null ? void 0 : l.errno : null;
1002
+ if (h in FileErrorCodes) {
1003
+ const d = FileErrorCodes[h], p = typeof o[0] == "string" ? o[0] : null, I = p !== null ? e.replaceAll("{path}", p) : e;
1004
+ throw new Error(`${I}: ${d}`, {
933
1005
  cause: l
934
1006
  });
935
1007
  }
@@ -938,56 +1010,50 @@ function P(r = "") {
938
1010
  };
939
1011
  };
940
1012
  }
941
- const dt = Symbol("RuntimeId"), q = /* @__PURE__ */ new Map();
942
- async function Rt(r, e = {}, t = []) {
943
- const [n, s, i] = me(), [o, l] = me(), d = r.init(pt, {
944
- onAbort(h) {
945
- i(h), l(), console.error(h);
1013
+ const RuntimeId = Symbol("RuntimeId"), loadedRuntimes = /* @__PURE__ */ new Map();
1014
+ let lastRuntimeId = 0;
1015
+ async function loadPHPRuntime(e, t = {}) {
1016
+ const [r, s, i] = makePromise(), n = e.init(currentJsRuntime, {
1017
+ onAbort(l) {
1018
+ i(l), console.error(l);
946
1019
  },
947
1020
  ENV: {},
948
1021
  // Emscripten sometimes prepends a '/' to the path, which
949
1022
  // breaks vite dev mode. An identity `locateFile` function
950
1023
  // fixes it.
951
- locateFile: (h) => h,
952
- ...e,
1024
+ locateFile: (l) => l,
1025
+ ...t,
953
1026
  noInitialRun: !0,
954
1027
  onRuntimeInitialized() {
955
- e.onRuntimeInitialized && e.onRuntimeInitialized(), s();
956
- },
957
- monitorRunDependencies(h) {
958
- h === 0 && (delete d.monitorRunDependencies, l());
1028
+ t.onRuntimeInitialized && t.onRuntimeInitialized(), s();
959
1029
  }
960
1030
  });
961
- await Promise.all(
962
- t.map(
963
- ({ default: h }) => h(d)
964
- )
965
- ), t.length || l(), await o, await n;
966
- const f = q.size;
967
- return d.originalExit = d._exit, d._exit = function(h) {
968
- return q.delete(f), d.originalExit(h);
969
- }, d[dt] = f, q.set(f, d), f;
1031
+ await r;
1032
+ const o = ++lastRuntimeId;
1033
+ return n.id = o, n.originalExit = n._exit, n._exit = function(l) {
1034
+ return loadedRuntimes.delete(o), n.originalExit(l);
1035
+ }, n[RuntimeId] = o, loadedRuntimes.set(o, n), o;
970
1036
  }
971
- function ft(r) {
972
- return q.get(r);
1037
+ function getLoadedRuntime(e) {
1038
+ return loadedRuntimes.get(e);
973
1039
  }
974
- const pt = function() {
975
- var r;
976
- return typeof process < "u" && ((r = process.release) == null ? void 0 : r.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope ? "WORKER" : "NODE";
977
- }(), me = () => {
978
- const r = [], e = new Promise((t, n) => {
979
- r.push(t, n);
1040
+ const currentJsRuntime = function() {
1041
+ var e;
1042
+ return typeof process < "u" && ((e = process.release) == null ? void 0 : e.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : typeof WorkerGlobalScope < "u" && self instanceof WorkerGlobalScope ? "WORKER" : "NODE";
1043
+ }(), makePromise = () => {
1044
+ const e = [], t = new Promise((r, s) => {
1045
+ e.push(r, s);
980
1046
  });
981
- return r.unshift(e), r;
1047
+ return e.unshift(t), e;
982
1048
  };
983
- var mt = Object.defineProperty, yt = Object.getOwnPropertyDescriptor, E = (r, e, t, n) => {
984
- for (var s = n > 1 ? void 0 : n ? yt(e, t) : e, i = r.length - 1, o; i >= 0; i--)
985
- (o = r[i]) && (s = (n ? o(e, t, s) : o(s)) || s);
986
- return n && s && mt(e, t, s), s;
1049
+ var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyDescriptor, __decorateClass = (e, t, r, s) => {
1050
+ for (var i = s > 1 ? void 0 : s ? __getOwnPropDesc(t, r) : t, n = e.length - 1, o; n >= 0; n--)
1051
+ (o = e[n]) && (i = (s ? o(t, r, i) : o(i)) || i);
1052
+ return s && i && __defProp(t, r, i), i;
987
1053
  };
988
- const y = "string", C = "number", u = Symbol("__private__dont__use");
989
- var k, R, T, x, v, I, N, z, ve, G, Re, V, xe, J, _e, Y, Fe, K, ke, Z, Te, Q, Ce, X, He, ee, Ae, te, $e, re, Ue;
990
- class w {
1054
+ const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
1055
+ var b, C, k, _, w, g, y, B, q, te, O, re, D, se, $, ne, j, ie, z, oe, G, ae, W, le, V, ce, J, ue, Y, de, Z, he;
1056
+ class BasePHP {
991
1057
  /**
992
1058
  * Initializes a PHP runtime.
993
1059
  *
@@ -996,15 +1062,15 @@ class w {
996
1062
  * @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
997
1063
  */
998
1064
  constructor(e, t) {
1065
+ c(this, q);
1066
+ c(this, O);
1067
+ c(this, D);
1068
+ c(this, $);
1069
+ c(this, j);
999
1070
  c(this, z);
1000
1071
  c(this, G);
1072
+ c(this, W);
1001
1073
  c(this, V);
1002
- c(this, J);
1003
- c(this, Y);
1004
- c(this, K);
1005
- c(this, Z);
1006
- c(this, Q);
1007
- c(this, X);
1008
1074
  /**
1009
1075
  * Adds file information to $_FILES superglobal in PHP.
1010
1076
  *
@@ -1014,40 +1080,41 @@ class w {
1014
1080
  *
1015
1081
  * @param fileInfo - File details
1016
1082
  */
1017
- c(this, ee);
1018
- c(this, te);
1019
- c(this, re);
1083
+ c(this, J);
1084
+ c(this, Y);
1085
+ c(this, Z);
1086
+ c(this, b, void 0);
1087
+ c(this, C, void 0);
1020
1088
  c(this, k, void 0);
1021
- c(this, R, void 0);
1022
- c(this, T, void 0);
1023
- c(this, x, void 0);
1024
- c(this, v, void 0);
1025
- c(this, I, void 0);
1026
- c(this, N, void 0);
1027
- p(this, k, []), p(this, R, !1), p(this, T, null), p(this, x, {}), p(this, v, /* @__PURE__ */ new Map()), p(this, I, []), p(this, N, new we({ concurrency: 1 })), e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new rt(
1028
- new it(this, t)
1089
+ c(this, _, void 0);
1090
+ c(this, w, void 0);
1091
+ c(this, g, void 0);
1092
+ c(this, y, void 0);
1093
+ c(this, B, void 0);
1094
+ u(this, b, []), u(this, _, !1), u(this, w, null), u(this, g, {}), u(this, y, /* @__PURE__ */ new Map()), u(this, B, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e), t && (this.requestHandler = new PHPBrowser(
1095
+ new PHPRequestHandler(this, t)
1029
1096
  ));
1030
1097
  }
1031
1098
  addEventListener(e, t) {
1032
- a(this, v).has(e) || a(this, v).set(e, /* @__PURE__ */ new Set()), a(this, v).get(e).add(t);
1099
+ a(this, y).has(e) || a(this, y).set(e, /* @__PURE__ */ new Set()), a(this, y).get(e).add(t);
1033
1100
  }
1034
1101
  removeEventListener(e, t) {
1035
- var n;
1036
- (n = a(this, v).get(e)) == null || n.delete(t);
1102
+ var r;
1103
+ (r = a(this, y).get(e)) == null || r.delete(t);
1037
1104
  }
1038
1105
  dispatchEvent(e) {
1039
- const t = a(this, v).get(e.type);
1106
+ const t = a(this, y).get(e.type);
1040
1107
  if (t)
1041
- for (const n of t)
1042
- n(e);
1108
+ for (const r of t)
1109
+ r(e);
1043
1110
  }
1044
1111
  /** @inheritDoc */
1045
1112
  async onMessage(e) {
1046
- a(this, I).push(e);
1113
+ a(this, B).push(e);
1047
1114
  }
1048
1115
  /** @inheritDoc */
1049
- async setSpawnHandler(e) {
1050
- this[u].spawnProcess = e;
1116
+ async setSpawnHandler(handler) {
1117
+ typeof handler == "string" && (handler = createSpawnHandler(eval(handler))), this[__private__dont__use].spawnProcess = handler;
1051
1118
  }
1052
1119
  /** @inheritDoc */
1053
1120
  get absoluteUrl() {
@@ -1068,25 +1135,40 @@ class w {
1068
1135
  );
1069
1136
  }
1070
1137
  initializeRuntime(e) {
1071
- if (this[u])
1138
+ if (this[__private__dont__use])
1072
1139
  throw new Error("PHP runtime already initialized.");
1073
- const t = ft(e);
1140
+ const t = getLoadedRuntime(e);
1074
1141
  if (!t)
1075
1142
  throw new Error("Invalid PHP runtime id.");
1076
- this[u] = t, t.onMessage = async (n) => {
1077
- for (const s of a(this, I)) {
1078
- const i = await s(n);
1143
+ this[__private__dont__use] = t, t.onMessage = async (r) => {
1144
+ for (const s of a(this, B)) {
1145
+ const i = await s(r);
1079
1146
  if (i)
1080
1147
  return i;
1081
1148
  }
1082
1149
  return "";
1083
- }, p(this, T, qe(t));
1150
+ }, u(this, w, improveWASMErrorReporting(t)), this.dispatchEvent({
1151
+ type: "runtime.initialized"
1152
+ });
1153
+ }
1154
+ /** @inheritDoc */
1155
+ async setSapiName(e) {
1156
+ if (this[__private__dont__use].ccall(
1157
+ "wasm_set_sapi_name",
1158
+ NUMBER,
1159
+ [STRING],
1160
+ [e]
1161
+ ) !== 0)
1162
+ throw new Error(
1163
+ "Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?"
1164
+ );
1165
+ u(this, k, e);
1084
1166
  }
1085
1167
  /** @inheritDoc */
1086
1168
  setPhpIniPath(e) {
1087
- if (a(this, R))
1169
+ if (a(this, _))
1088
1170
  throw new Error("Cannot set PHP ini path after calling run().");
1089
- this[u].ccall(
1171
+ u(this, C, e), this[__private__dont__use].ccall(
1090
1172
  "wasm_set_phpini_path",
1091
1173
  null,
1092
1174
  ["string"],
@@ -1095,13 +1177,13 @@ class w {
1095
1177
  }
1096
1178
  /** @inheritDoc */
1097
1179
  setPhpIniEntry(e, t) {
1098
- if (a(this, R))
1180
+ if (a(this, _))
1099
1181
  throw new Error("Cannot set PHP ini entries after calling run().");
1100
- a(this, k).push([e, t]);
1182
+ a(this, b).push([e, t]);
1101
1183
  }
1102
1184
  /** @inheritDoc */
1103
1185
  chdir(e) {
1104
- this[u].FS.chdir(e);
1186
+ this[__private__dont__use].FS.chdir(e);
1105
1187
  }
1106
1188
  /** @inheritDoc */
1107
1189
  async request(e, t) {
@@ -1111,27 +1193,45 @@ class w {
1111
1193
  }
1112
1194
  /** @inheritDoc */
1113
1195
  async run(e) {
1114
- const t = await a(this, N).acquire();
1196
+ const t = await this.semaphore.acquire();
1197
+ let r;
1115
1198
  try {
1116
- a(this, R) || (m(this, z, ve).call(this), p(this, R, !0)), m(this, Q, Ce).call(this, e.scriptPath || ""), m(this, V, xe).call(this, e.relativeUri || ""), m(this, Y, Fe).call(this, e.method || "GET");
1117
- const n = Be(e.headers || {}), s = n.host || "example.com:443";
1118
- if (m(this, J, _e).call(this, s, e.protocol || "http"), m(this, K, ke).call(this, n), e.body && m(this, Z, Te).call(this, e.body), e.fileInfos)
1119
- for (const i of e.fileInfos)
1120
- m(this, ee, Ae).call(this, i);
1121
- return e.code && m(this, te, $e).call(this, " ?>" + e.code), m(this, X, He).call(this), await m(this, re, Ue).call(this);
1199
+ a(this, _) || (f(this, q, te).call(this), u(this, _, !0)), f(this, W, le).call(this, e.scriptPath || ""), f(this, D, se).call(this, e.relativeUri || ""), f(this, j, ie).call(this, e.method || "GET");
1200
+ const s = normalizeHeaders(e.headers || {}), i = s.host || "example.com:443";
1201
+ if (f(this, $, ne).call(this, i, e.protocol || "http"), f(this, z, oe).call(this, s), e.body && (r = f(this, G, ae).call(this, e.body)), e.fileInfos)
1202
+ for (const o of e.fileInfos)
1203
+ f(this, J, ue).call(this, o);
1204
+ typeof e.code == "string" && f(this, Y, de).call(this, " ?>" + e.code), f(this, V, ce).call(this);
1205
+ const n = await f(this, Z, he).call(this);
1206
+ if (e.throwOnError && n.exitCode !== 0) {
1207
+ const o = {
1208
+ stdout: n.text,
1209
+ stderr: n.errors
1210
+ };
1211
+ console.warn("PHP.run() output was:", o);
1212
+ const l = new Error(
1213
+ `PHP.run() failed with exit code ${n.exitCode} and the following output`
1214
+ );
1215
+ throw l.output = o, l;
1216
+ }
1217
+ return n;
1122
1218
  } finally {
1123
- t(), this.dispatchEvent({
1124
- type: "request.end"
1125
- });
1219
+ try {
1220
+ r && this[__private__dont__use].free(r);
1221
+ } finally {
1222
+ t(), this.dispatchEvent({
1223
+ type: "request.end"
1224
+ });
1225
+ }
1126
1226
  }
1127
1227
  }
1128
1228
  addServerGlobalEntry(e, t) {
1129
- a(this, x)[e] = t;
1229
+ a(this, g)[e] = t;
1130
1230
  }
1131
1231
  defineConstant(e, t) {
1132
- let n = {};
1232
+ let r = {};
1133
1233
  try {
1134
- n = JSON.parse(
1234
+ r = JSON.parse(
1135
1235
  this.fileExists("/tmp/consts.json") && this.readFileAsText("/tmp/consts.json") || "{}"
1136
1236
  );
1137
1237
  } catch {
@@ -1139,13 +1239,13 @@ class w {
1139
1239
  this.writeFile(
1140
1240
  "/tmp/consts.json",
1141
1241
  JSON.stringify({
1142
- ...n,
1242
+ ...r,
1143
1243
  [e]: t
1144
1244
  })
1145
1245
  );
1146
1246
  }
1147
1247
  mkdir(e) {
1148
- this[u].FS.mkdirTree(e);
1248
+ this[__private__dont__use].FS.mkdirTree(e);
1149
1249
  }
1150
1250
  mkdirTree(e) {
1151
1251
  this.mkdir(e);
@@ -1154,67 +1254,91 @@ class w {
1154
1254
  return new TextDecoder().decode(this.readFileAsBuffer(e));
1155
1255
  }
1156
1256
  readFileAsBuffer(e) {
1157
- return this[u].FS.readFile(e);
1257
+ return this[__private__dont__use].FS.readFile(e);
1158
1258
  }
1159
1259
  writeFile(e, t) {
1160
- this[u].FS.writeFile(e, t);
1260
+ this[__private__dont__use].FS.writeFile(e, t);
1161
1261
  }
1162
1262
  unlink(e) {
1163
- this[u].FS.unlink(e);
1263
+ this[__private__dont__use].FS.unlink(e);
1164
1264
  }
1165
1265
  /** @inheritDoc */
1166
1266
  mv(e, t) {
1167
1267
  try {
1168
- this[u].FS.rename(e, t);
1169
- } catch (n) {
1170
- const s = ht(n);
1268
+ this[__private__dont__use].FS.rename(e, t);
1269
+ } catch (r) {
1270
+ const s = getEmscriptenFsError(r);
1171
1271
  throw s ? new Error(
1172
1272
  `Could not move ${e} to ${t}: ${s}`,
1173
1273
  {
1174
- cause: n
1274
+ cause: r
1175
1275
  }
1176
- ) : n;
1276
+ ) : r;
1177
1277
  }
1178
1278
  }
1179
1279
  rmdir(e, t = { recursive: !0 }) {
1180
- t != null && t.recursive && this.listFiles(e).forEach((n) => {
1181
- const s = `${e}/${n}`;
1280
+ t != null && t.recursive && this.listFiles(e).forEach((r) => {
1281
+ const s = `${e}/${r}`;
1182
1282
  this.isDir(s) ? this.rmdir(s, t) : this.unlink(s);
1183
- }), this[u].FS.rmdir(e);
1283
+ }), this[__private__dont__use].FS.rmdir(e);
1184
1284
  }
1185
1285
  listFiles(e, t = { prependPath: !1 }) {
1186
1286
  if (!this.fileExists(e))
1187
1287
  return [];
1188
1288
  try {
1189
- const n = this[u].FS.readdir(e).filter(
1289
+ const r = this[__private__dont__use].FS.readdir(e).filter(
1190
1290
  (s) => s !== "." && s !== ".."
1191
1291
  );
1192
1292
  if (t.prependPath) {
1193
1293
  const s = e.replace(/\/$/, "");
1194
- return n.map((i) => `${s}/${i}`);
1294
+ return r.map((i) => `${s}/${i}`);
1195
1295
  }
1196
- return n;
1197
- } catch (n) {
1198
- return console.error(n, { path: e }), [];
1296
+ return r;
1297
+ } catch (r) {
1298
+ return console.error(r, { path: e }), [];
1199
1299
  }
1200
1300
  }
1201
1301
  isDir(e) {
1202
- return this.fileExists(e) ? this[u].FS.isDir(
1203
- this[u].FS.lookupPath(e).node.mode
1302
+ return this.fileExists(e) ? this[__private__dont__use].FS.isDir(
1303
+ this[__private__dont__use].FS.lookupPath(e).node.mode
1204
1304
  ) : !1;
1205
1305
  }
1206
1306
  fileExists(e) {
1207
1307
  try {
1208
- return this[u].FS.lookupPath(e), !0;
1308
+ return this[__private__dont__use].FS.lookupPath(e), !0;
1209
1309
  } catch {
1210
1310
  return !1;
1211
1311
  }
1212
1312
  }
1313
+ /**
1314
+ * Hot-swaps the PHP runtime for a new one without
1315
+ * interrupting the operations of this PHP instance.
1316
+ *
1317
+ * @param runtime
1318
+ */
1319
+ hotSwapPHPRuntime(e) {
1320
+ const t = this[__private__dont__use].FS;
1321
+ try {
1322
+ this.exit();
1323
+ } catch {
1324
+ }
1325
+ if (this.initializeRuntime(e), a(this, C) && this.setPhpIniPath(a(this, C)), a(this, k) && this.setSapiName(a(this, k)), this.requestHandler) {
1326
+ const r = this.documentRoot;
1327
+ recreateMemFS(this[__private__dont__use].FS, t, r);
1328
+ }
1329
+ }
1213
1330
  exit(e = 0) {
1214
- return this[u]._exit(e);
1331
+ this.dispatchEvent({
1332
+ type: "runtime.beforedestroy"
1333
+ });
1334
+ try {
1335
+ this[__private__dont__use]._exit(e);
1336
+ } catch {
1337
+ }
1338
+ u(this, _, !1), u(this, w, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1215
1339
  }
1216
1340
  }
1217
- k = new WeakMap(), R = new WeakMap(), T = new WeakMap(), x = new WeakMap(), v = new WeakMap(), I = new WeakMap(), N = new WeakMap(), z = new WeakSet(), ve = function() {
1341
+ b = new WeakMap(), C = new WeakMap(), k = new WeakMap(), _ = new WeakMap(), w = new WeakMap(), g = new WeakMap(), y = new WeakMap(), B = new WeakMap(), q = new WeakSet(), te = function() {
1218
1342
  if (this.setPhpIniEntry("auto_prepend_file", "/tmp/consts.php"), this.fileExists("/tmp/consts.php") || this.writeFile(
1219
1343
  "/tmp/consts.php",
1220
1344
  `<?php
@@ -1226,251 +1350,311 @@ k = new WeakMap(), R = new WeakMap(), T = new WeakMap(), x = new WeakMap(), v =
1226
1350
  }
1227
1351
  }
1228
1352
  }`
1229
- ), a(this, k).length > 0) {
1230
- const e = a(this, k).map(([t, n]) => `${t}=${n}`).join(`
1353
+ ), a(this, b).length > 0) {
1354
+ const e = a(this, b).map(([t, r]) => `${t}=${r}`).join(`
1231
1355
  `) + `
1232
1356
 
1233
1357
  `;
1234
- this[u].ccall(
1358
+ this[__private__dont__use].ccall(
1235
1359
  "wasm_set_phpini_entries",
1236
1360
  null,
1237
- [y],
1361
+ [STRING],
1238
1362
  [e]
1239
1363
  );
1240
1364
  }
1241
- this[u].ccall("php_wasm_init", null, [], []);
1242
- }, G = new WeakSet(), Re = function() {
1365
+ this[__private__dont__use].ccall("php_wasm_init", null, [], []);
1366
+ }, O = new WeakSet(), re = function() {
1243
1367
  const e = "/tmp/headers.json";
1244
1368
  if (!this.fileExists(e))
1245
1369
  throw new Error(
1246
1370
  "SAPI Error: Could not find response headers file."
1247
1371
  );
1248
- const t = JSON.parse(this.readFileAsText(e)), n = {};
1372
+ const t = JSON.parse(this.readFileAsText(e)), r = {};
1249
1373
  for (const s of t.headers) {
1250
1374
  if (!s.includes(": "))
1251
1375
  continue;
1252
- const i = s.indexOf(": "), o = s.substring(0, i).toLowerCase(), l = s.substring(i + 2);
1253
- o in n || (n[o] = []), n[o].push(l);
1376
+ const i = s.indexOf(": "), n = s.substring(0, i).toLowerCase(), o = s.substring(i + 2);
1377
+ n in r || (r[n] = []), r[n].push(o);
1254
1378
  }
1255
1379
  return {
1256
- headers: n,
1380
+ headers: r,
1257
1381
  httpStatusCode: t.status
1258
1382
  };
1259
- }, V = new WeakSet(), xe = function(e) {
1260
- if (this[u].ccall(
1383
+ }, D = new WeakSet(), se = function(e) {
1384
+ if (this[__private__dont__use].ccall(
1261
1385
  "wasm_set_request_uri",
1262
1386
  null,
1263
- [y],
1387
+ [STRING],
1264
1388
  [e]
1265
1389
  ), e.includes("?")) {
1266
1390
  const t = e.substring(e.indexOf("?") + 1);
1267
- this[u].ccall(
1391
+ this[__private__dont__use].ccall(
1268
1392
  "wasm_set_query_string",
1269
1393
  null,
1270
- [y],
1394
+ [STRING],
1271
1395
  [t]
1272
1396
  );
1273
1397
  }
1274
- }, J = new WeakSet(), _e = function(e, t) {
1275
- this[u].ccall(
1398
+ }, $ = new WeakSet(), ne = function(e, t) {
1399
+ this[__private__dont__use].ccall(
1276
1400
  "wasm_set_request_host",
1277
1401
  null,
1278
- [y],
1402
+ [STRING],
1279
1403
  [e]
1280
1404
  );
1281
- let n;
1405
+ let r;
1282
1406
  try {
1283
- n = parseInt(new URL(e).port, 10);
1407
+ r = parseInt(new URL(e).port, 10);
1284
1408
  } catch {
1285
1409
  }
1286
- (!n || isNaN(n) || n === 80) && (n = t === "https" ? 443 : 80), this[u].ccall(
1410
+ (!r || isNaN(r) || r === 80) && (r = t === "https" ? 443 : 80), this[__private__dont__use].ccall(
1287
1411
  "wasm_set_request_port",
1288
1412
  null,
1289
- [C],
1290
- [n]
1291
- ), (t === "https" || !t && n === 443) && this.addServerGlobalEntry("HTTPS", "on");
1292
- }, Y = new WeakSet(), Fe = function(e) {
1293
- this[u].ccall(
1413
+ [NUMBER],
1414
+ [r]
1415
+ ), (t === "https" || !t && r === 443) && this.addServerGlobalEntry("HTTPS", "on");
1416
+ }, j = new WeakSet(), ie = function(e) {
1417
+ this[__private__dont__use].ccall(
1294
1418
  "wasm_set_request_method",
1295
1419
  null,
1296
- [y],
1420
+ [STRING],
1297
1421
  [e]
1298
1422
  );
1299
- }, K = new WeakSet(), ke = function(e) {
1300
- e.cookie && this[u].ccall(
1423
+ }, z = new WeakSet(), oe = function(e) {
1424
+ e.cookie && this[__private__dont__use].ccall(
1301
1425
  "wasm_set_cookies",
1302
1426
  null,
1303
- [y],
1427
+ [STRING],
1304
1428
  [e.cookie]
1305
- ), e["content-type"] && this[u].ccall(
1429
+ ), e["content-type"] && this[__private__dont__use].ccall(
1306
1430
  "wasm_set_content_type",
1307
1431
  null,
1308
- [y],
1432
+ [STRING],
1309
1433
  [e["content-type"]]
1310
- ), e["content-length"] && this[u].ccall(
1434
+ ), e["content-length"] && this[__private__dont__use].ccall(
1311
1435
  "wasm_set_content_length",
1312
1436
  null,
1313
- [C],
1437
+ [NUMBER],
1314
1438
  [parseInt(e["content-length"], 10)]
1315
1439
  );
1316
1440
  for (const t in e) {
1317
- let n = "HTTP_";
1318
- ["content-type", "content-length"].includes(t.toLowerCase()) && (n = ""), this.addServerGlobalEntry(
1319
- `${n}${t.toUpperCase().replace(/-/g, "_")}`,
1441
+ let r = "HTTP_";
1442
+ ["content-type", "content-length"].includes(t.toLowerCase()) && (r = ""), this.addServerGlobalEntry(
1443
+ `${r}${t.toUpperCase().replace(/-/g, "_")}`,
1320
1444
  e[t]
1321
1445
  );
1322
1446
  }
1323
- }, Z = new WeakSet(), Te = function(e) {
1324
- this[u].ccall(
1447
+ }, G = new WeakSet(), ae = function(e) {
1448
+ const t = this[__private__dont__use].lengthBytesUTF8(e), r = this[__private__dont__use].malloc(t + 1);
1449
+ if (!r)
1450
+ throw new Error("Could not allocate memory for the request body.");
1451
+ return this[__private__dont__use].stringToUTF8(
1452
+ e,
1453
+ r,
1454
+ t + 1
1455
+ ), this[__private__dont__use].ccall(
1325
1456
  "wasm_set_request_body",
1326
1457
  null,
1327
- [y],
1328
- [e]
1329
- ), this[u].ccall(
1458
+ [NUMBER],
1459
+ [r]
1460
+ ), this[__private__dont__use].ccall(
1330
1461
  "wasm_set_content_length",
1331
1462
  null,
1332
- [C],
1463
+ [NUMBER],
1333
1464
  [new TextEncoder().encode(e).length]
1334
- );
1335
- }, Q = new WeakSet(), Ce = function(e) {
1336
- this[u].ccall(
1465
+ ), r;
1466
+ }, W = new WeakSet(), le = function(e) {
1467
+ this[__private__dont__use].ccall(
1337
1468
  "wasm_set_path_translated",
1338
1469
  null,
1339
- [y],
1470
+ [STRING],
1340
1471
  [e]
1341
1472
  );
1342
- }, X = new WeakSet(), He = function() {
1343
- for (const e in a(this, x))
1344
- this[u].ccall(
1473
+ }, V = new WeakSet(), ce = function() {
1474
+ for (const e in a(this, g))
1475
+ this[__private__dont__use].ccall(
1345
1476
  "wasm_add_SERVER_entry",
1346
1477
  null,
1347
- [y, y],
1348
- [e, a(this, x)[e]]
1478
+ [STRING, STRING],
1479
+ [e, a(this, g)[e]]
1349
1480
  );
1350
- }, ee = new WeakSet(), Ae = function(e) {
1351
- const { key: t, name: n, type: s, data: i } = e, o = `/tmp/${Math.random().toFixed(20)}`;
1352
- this.writeFile(o, i);
1353
- const l = 0;
1354
- this[u].ccall(
1481
+ }, J = new WeakSet(), ue = function(e) {
1482
+ const { key: t, name: r, type: s, data: i } = e, n = `/tmp/${Math.random().toFixed(20)}`;
1483
+ this.writeFile(n, i);
1484
+ const o = 0;
1485
+ this[__private__dont__use].ccall(
1355
1486
  "wasm_add_uploaded_file",
1356
1487
  null,
1357
- [y, y, y, y, C, C],
1358
- [t, n, s, o, l, i.byteLength]
1488
+ [STRING, STRING, STRING, STRING, NUMBER, NUMBER],
1489
+ [t, r, s, n, o, i.byteLength]
1359
1490
  );
1360
- }, te = new WeakSet(), $e = function(e) {
1361
- this[u].ccall(
1491
+ }, Y = new WeakSet(), de = function(e) {
1492
+ this[__private__dont__use].ccall(
1362
1493
  "wasm_set_php_code",
1363
1494
  null,
1364
- [y],
1495
+ [STRING],
1365
1496
  [e]
1366
1497
  );
1367
- }, re = new WeakSet(), Ue = async function() {
1498
+ }, Z = new WeakSet(), he = async function() {
1368
1499
  var i;
1369
1500
  let e, t;
1370
1501
  try {
1371
- e = await new Promise((o, l) => {
1372
- var f;
1373
- t = (h) => {
1374
- const S = new Error("Rethrown");
1375
- S.cause = h.error, S.betterMessage = h.message, l(S);
1376
- }, (f = a(this, T)) == null || f.addEventListener(
1502
+ e = await new Promise((n, o) => {
1503
+ var h;
1504
+ t = (d) => {
1505
+ const p = new Error("Rethrown");
1506
+ p.cause = d.error, p.betterMessage = d.message, o(p);
1507
+ }, (h = a(this, w)) == null || h.addEventListener(
1377
1508
  "error",
1378
1509
  t
1379
1510
  );
1380
- const d = this[u].ccall(
1511
+ const l = this[__private__dont__use].ccall(
1381
1512
  "wasm_sapi_handle_request",
1382
- C,
1513
+ NUMBER,
1383
1514
  [],
1384
1515
  [],
1385
1516
  { async: !0 }
1386
1517
  );
1387
- return d instanceof Promise ? d.then(o, l) : o(d);
1518
+ return l instanceof Promise ? l.then(n, o) : n(l);
1388
1519
  });
1389
- } catch (o) {
1390
- for (const h in this)
1391
- typeof this[h] == "function" && (this[h] = () => {
1520
+ } catch (n) {
1521
+ for (const d in this)
1522
+ typeof this[d] == "function" && (this[d] = () => {
1392
1523
  throw new Error(
1393
1524
  "PHP runtime has crashed – see the earlier error for details."
1394
1525
  );
1395
1526
  });
1396
- this.functionsMaybeMissingFromAsyncify = De();
1397
- const l = o, d = "betterMessage" in l ? l.betterMessage : l.message, f = new Error(d);
1398
- throw f.cause = l, f;
1527
+ this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
1528
+ const o = n, l = "betterMessage" in o ? o.betterMessage : o.message, h = new Error(l);
1529
+ throw h.cause = o, h;
1399
1530
  } finally {
1400
- (i = a(this, T)) == null || i.removeEventListener("error", t), p(this, x, {});
1531
+ (i = a(this, w)) == null || i.removeEventListener("error", t), u(this, g, {});
1401
1532
  }
1402
- const { headers: n, httpStatusCode: s } = m(this, G, Re).call(this);
1403
- return new H(
1533
+ const { headers: r, httpStatusCode: s } = f(this, O, re).call(this);
1534
+ return new PHPResponse(
1404
1535
  s,
1405
- n,
1536
+ r,
1406
1537
  this.readFileAsBuffer("/tmp/stdout"),
1407
1538
  this.readFileAsText("/tmp/stderr"),
1408
1539
  e
1409
1540
  );
1410
1541
  };
1411
- E([
1412
- P('Could not create directory "{path}"')
1413
- ], w.prototype, "mkdir", 1);
1414
- E([
1415
- P('Could not create directory "{path}"')
1416
- ], w.prototype, "mkdirTree", 1);
1417
- E([
1418
- P('Could not read "{path}"')
1419
- ], w.prototype, "readFileAsText", 1);
1420
- E([
1421
- P('Could not read "{path}"')
1422
- ], w.prototype, "readFileAsBuffer", 1);
1423
- E([
1424
- P('Could not write to "{path}"')
1425
- ], w.prototype, "writeFile", 1);
1426
- E([
1427
- P('Could not unlink "{path}"')
1428
- ], w.prototype, "unlink", 1);
1429
- E([
1430
- P('Could not remove directory "{path}"')
1431
- ], w.prototype, "rmdir", 1);
1432
- E([
1433
- P('Could not list files in "{path}"')
1434
- ], w.prototype, "listFiles", 1);
1435
- E([
1436
- P('Could not stat "{path}"')
1437
- ], w.prototype, "isDir", 1);
1438
- E([
1439
- P('Could not stat "{path}"')
1440
- ], w.prototype, "fileExists", 1);
1441
- function Be(r) {
1442
- const e = {};
1443
- for (const t in r)
1444
- e[t.toLowerCase()] = r[t];
1445
- return e;
1542
+ __decorateClass([
1543
+ rethrowFileSystemError('Could not create directory "{path}"')
1544
+ ], BasePHP.prototype, "mkdir", 1);
1545
+ __decorateClass([
1546
+ rethrowFileSystemError('Could not create directory "{path}"')
1547
+ ], BasePHP.prototype, "mkdirTree", 1);
1548
+ __decorateClass([
1549
+ rethrowFileSystemError('Could not read "{path}"')
1550
+ ], BasePHP.prototype, "readFileAsText", 1);
1551
+ __decorateClass([
1552
+ rethrowFileSystemError('Could not read "{path}"')
1553
+ ], BasePHP.prototype, "readFileAsBuffer", 1);
1554
+ __decorateClass([
1555
+ rethrowFileSystemError('Could not write to "{path}"')
1556
+ ], BasePHP.prototype, "writeFile", 1);
1557
+ __decorateClass([
1558
+ rethrowFileSystemError('Could not unlink "{path}"')
1559
+ ], BasePHP.prototype, "unlink", 1);
1560
+ __decorateClass([
1561
+ rethrowFileSystemError('Could not remove directory "{path}"')
1562
+ ], BasePHP.prototype, "rmdir", 1);
1563
+ __decorateClass([
1564
+ rethrowFileSystemError('Could not list files in "{path}"')
1565
+ ], BasePHP.prototype, "listFiles", 1);
1566
+ __decorateClass([
1567
+ rethrowFileSystemError('Could not stat "{path}"')
1568
+ ], BasePHP.prototype, "isDir", 1);
1569
+ __decorateClass([
1570
+ rethrowFileSystemError('Could not stat "{path}"')
1571
+ ], BasePHP.prototype, "fileExists", 1);
1572
+ function normalizeHeaders(e) {
1573
+ const t = {};
1574
+ for (const r in e)
1575
+ t[r.toLowerCase()] = e[r];
1576
+ return t;
1446
1577
  }
1447
- function wt(r) {
1448
- return !(r instanceof w);
1578
+ function recreateMemFS(e, t, r) {
1579
+ let s;
1580
+ try {
1581
+ s = t.lookupPath(r);
1582
+ } catch {
1583
+ return;
1584
+ }
1585
+ if (!("contents" in s.node))
1586
+ return;
1587
+ try {
1588
+ e = e.lookupPath(r);
1589
+ return;
1590
+ } catch {
1591
+ }
1592
+ if (!t.isDir(s.node.mode)) {
1593
+ e.writeFile(r, t.readFile(r));
1594
+ return;
1595
+ }
1596
+ e.mkdirTree(r);
1597
+ const i = t.readdir(r).filter((n) => n !== "." && n !== "..");
1598
+ for (const n of i)
1599
+ recreateMemFS(e, t, joinPaths(r, n));
1600
+ }
1601
+ function isLocalPHP(e) {
1602
+ return !(e instanceof BasePHP);
1603
+ }
1604
+ function isRemotePHP(e) {
1605
+ return !isLocalPHP(e);
1606
+ }
1607
+ function rotatePHPRuntime({
1608
+ php: e,
1609
+ recreateRuntime: t,
1610
+ maxRequests: r
1611
+ }) {
1612
+ let s = 0;
1613
+ async function i() {
1614
+ if (++s < r)
1615
+ return;
1616
+ s = 0;
1617
+ const n = await e.semaphore.acquire();
1618
+ try {
1619
+ e.hotSwapPHPRuntime(await t());
1620
+ } finally {
1621
+ n();
1622
+ }
1623
+ }
1624
+ return e.addEventListener("request.end", i), function() {
1625
+ e.removeEventListener("request.end", i);
1626
+ };
1449
1627
  }
1450
- function xt(r) {
1451
- return !wt(r);
1628
+ async function writeFiles(e, t, r, { rmRoot: s = !1 } = {}) {
1629
+ s && await e.isDir(t) && await e.rmdir(t, { recursive: !0 });
1630
+ for (const [i, n] of Object.entries(r)) {
1631
+ const o = joinPaths(t, i);
1632
+ await e.fileExists(dirname(o)) || await e.mkdir(dirname(o)), await e.writeFile(o, n);
1633
+ }
1452
1634
  }
1453
1635
  export {
1454
- w as BasePHP,
1455
- nt as DEFAULT_BASE_URL,
1456
- Et as LatestSupportedPHPVersion,
1457
- rt as PHPBrowser,
1458
- it as PHPRequestHandler,
1459
- H as PHPResponse,
1460
- vt as SupportedPHPExtensionBundles,
1461
- tt as SupportedPHPExtensionsList,
1462
- be as SupportedPHPVersions,
1463
- St as SupportedPHPVersionsList,
1464
- Ne as UnhandledRejectionsTarget,
1465
- u as __private__dont__use,
1466
- st as ensurePathPrefix,
1467
- Oe as isExitCodeZero,
1468
- wt as isLocalPHP,
1469
- xt as isRemotePHP,
1470
- bt as iterateFiles,
1471
- Rt as loadPHPRuntime,
1472
- pe as removePathPrefix,
1473
- P as rethrowFileSystemError,
1474
- fe as toRelativeUrl,
1475
- Pt as writeFilesStreamToPhp
1636
+ BasePHP,
1637
+ DEFAULT_BASE_URL,
1638
+ LatestSupportedPHPVersion,
1639
+ PHPBrowser,
1640
+ PHPRequestHandler,
1641
+ PHPResponse,
1642
+ SupportedPHPExtensionBundles,
1643
+ SupportedPHPExtensionsList,
1644
+ SupportedPHPVersions,
1645
+ SupportedPHPVersionsList,
1646
+ UnhandledRejectionsTarget,
1647
+ __private__dont__use,
1648
+ ensurePathPrefix,
1649
+ isExitCodeZero,
1650
+ isLocalPHP,
1651
+ isRemotePHP,
1652
+ iteratePhpFiles as iterateFiles,
1653
+ loadPHPRuntime,
1654
+ removePathPrefix,
1655
+ rethrowFileSystemError,
1656
+ rotatePHPRuntime,
1657
+ toRelativeUrl,
1658
+ writeFiles,
1659
+ writeFilesStreamToPhp
1476
1660
  };