@php-wasm/universal 0.7.19 → 0.7.20

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,13 +1,13 @@
1
- var Q = (e, t, r) => {
1
+ var Y = (e, t, s) => {
2
2
  if (!t.has(e))
3
- throw TypeError("Cannot " + r);
3
+ throw TypeError("Cannot " + s);
4
4
  };
5
- var u = (e, t, r) => (Q(e, t, "read from private field"), r ? r.call(e) : t.get(e)), h = (e, t, r) => {
5
+ var u = (e, t, s) => (Y(e, t, "read from private field"), s ? s.call(e) : t.get(e)), d = (e, t, s) => {
6
6
  if (t.has(e))
7
7
  throw TypeError("Cannot add the same private member more than once");
8
- t instanceof WeakSet ? t.add(e) : t.set(e, r);
9
- }, d = (e, t, r, s) => (Q(e, t, "write to private field"), s ? s.call(e, r) : t.set(e, r), r);
10
- var p = (e, t, r) => (Q(e, t, "access private method"), r);
8
+ t instanceof WeakSet ? t.add(e) : t.set(e, s);
9
+ }, f = (e, t, s, r) => (Y(e, t, "write to private field"), r ? r.call(e, s) : t.set(e, s), s);
10
+ var h = (e, t, s) => (Y(e, t, "access private method"), s);
11
11
  const currentJsRuntime$1 = function() {
12
12
  var e;
13
13
  return typeof process < "u" && ((e = process.release) == null ? void 0 : e.name) === "node" ? "NODE" : typeof window < "u" ? "WEB" : (
@@ -17,14 +17,14 @@ const currentJsRuntime$1 = function() {
17
17
  );
18
18
  }();
19
19
  if (currentJsRuntime$1 === "NODE") {
20
- let e = function(r) {
21
- return new Promise(function(s, n) {
22
- r.onload = r.onerror = function(i) {
23
- r.onload = r.onerror = null, i.type === "load" ? s(r.result) : n(new Error("Failed to read the blob/file"));
20
+ let e = function(s) {
21
+ return new Promise(function(r, n) {
22
+ s.onload = s.onerror = function(i) {
23
+ s.onload = s.onerror = null, i.type === "load" ? r(s.result) : n(new Error("Failed to read the blob/file"));
24
24
  };
25
25
  });
26
26
  }, t = function() {
27
- const r = new Uint8Array([1, 2, 3, 4]), n = new File([r], "test").stream();
27
+ const s = new Uint8Array([1, 2, 3, 4]), n = new File([s], "test").stream();
28
28
  try {
29
29
  return n.getReader({ mode: "byob" }), !0;
30
30
  } catch {
@@ -32,78 +32,215 @@ if (currentJsRuntime$1 === "NODE") {
32
32
  }
33
33
  };
34
34
  if (typeof File > "u") {
35
- class r extends Blob {
35
+ class s extends Blob {
36
36
  constructor(n, i, o) {
37
37
  super(n);
38
- let a;
39
- o != null && o.lastModified && (a = /* @__PURE__ */ new Date()), (!a || isNaN(a.getFullYear())) && (a = /* @__PURE__ */ new Date()), this.lastModifiedDate = a, this.lastModified = a.getMilliseconds(), this.name = i || "";
38
+ let c;
39
+ o != null && o.lastModified && (c = /* @__PURE__ */ new Date()), (!c || isNaN(c.getFullYear())) && (c = /* @__PURE__ */ new Date()), this.lastModifiedDate = c, this.lastModified = c.getMilliseconds(), this.name = i || "";
40
40
  }
41
41
  }
42
- global.File = r;
42
+ global.File = s;
43
43
  }
44
44
  typeof Blob.prototype.arrayBuffer > "u" && (Blob.prototype.arrayBuffer = function() {
45
- const s = new FileReader();
46
- return s.readAsArrayBuffer(this), e(s);
45
+ const r = new FileReader();
46
+ return r.readAsArrayBuffer(this), e(r);
47
47
  }), typeof Blob.prototype.text > "u" && (Blob.prototype.text = function() {
48
- const s = new FileReader();
49
- return s.readAsText(this), e(s);
48
+ const r = new FileReader();
49
+ return r.readAsText(this), e(r);
50
50
  }), (typeof Blob.prototype.stream > "u" || !t()) && (Blob.prototype.stream = function() {
51
- let r = 0;
52
- const s = this;
51
+ let s = 0;
52
+ const r = this;
53
53
  return new ReadableStream({
54
54
  type: "bytes",
55
55
  // 0.5 MB seems like a reasonable chunk size, let's adjust
56
56
  // this if needed.
57
57
  autoAllocateChunkSize: 512 * 1024,
58
58
  async pull(n) {
59
- const i = n.byobRequest.view, a = await s.slice(
60
- r,
61
- r + i.byteLength
62
- ).arrayBuffer(), l = new Uint8Array(a);
59
+ const i = n.byobRequest.view, c = await r.slice(
60
+ s,
61
+ s + i.byteLength
62
+ ).arrayBuffer(), l = new Uint8Array(c);
63
63
  new Uint8Array(i.buffer).set(l);
64
- const c = l.byteLength;
65
- n.byobRequest.respond(c), r += c, r >= s.size && n.close();
64
+ const a = l.byteLength;
65
+ n.byobRequest.respond(a), s += a, s >= r.size && n.close();
66
66
  }
67
67
  });
68
68
  });
69
69
  }
70
70
  if (currentJsRuntime$1 === "NODE" && typeof CustomEvent > "u") {
71
71
  class e extends Event {
72
- constructor(r, s = {}) {
73
- super(r, s), this.detail = s.detail;
72
+ constructor(s, r = {}) {
73
+ super(s, r), this.detail = r.detail;
74
74
  }
75
75
  initCustomEvent() {
76
76
  }
77
77
  }
78
78
  globalThis.CustomEvent = e;
79
79
  }
80
- const kError = Symbol("error"), kMessage = Symbol("message");
81
- class ErrorEvent2 extends Event {
80
+ const responseTexts = {
81
+ 500: "Internal Server Error",
82
+ 502: "Bad Gateway",
83
+ 404: "Not Found",
84
+ 403: "Forbidden",
85
+ 401: "Unauthorized",
86
+ 400: "Bad Request",
87
+ 301: "Moved Permanently",
88
+ 302: "Found",
89
+ 307: "Temporary Redirect",
90
+ 308: "Permanent Redirect",
91
+ 204: "No Content",
92
+ 201: "Created",
93
+ 200: "OK"
94
+ };
95
+ class PHPResponse {
96
+ constructor(t, s, r, n = "", i = 0) {
97
+ this.httpStatusCode = t, this.headers = s, this.bytes = r, this.exitCode = i, this.errors = n;
98
+ }
99
+ static forHttpCode(t, s = "") {
100
+ return new PHPResponse(
101
+ t,
102
+ {},
103
+ new TextEncoder().encode(
104
+ s || responseTexts[t] || ""
105
+ )
106
+ );
107
+ }
108
+ static fromRawData(t) {
109
+ return new PHPResponse(
110
+ t.httpStatusCode,
111
+ t.headers,
112
+ t.bytes,
113
+ t.errors,
114
+ t.exitCode
115
+ );
116
+ }
117
+ toRawData() {
118
+ return {
119
+ headers: this.headers,
120
+ bytes: this.bytes,
121
+ errors: this.errors,
122
+ exitCode: this.exitCode,
123
+ httpStatusCode: this.httpStatusCode
124
+ };
125
+ }
82
126
  /**
83
- * Create a new `ErrorEvent`.
84
- *
85
- * @param type The name of the event
86
- * @param options A dictionary object that allows for setting
87
- * attributes via object members of the same name.
127
+ * Response body as JSON.
88
128
  */
89
- constructor(t, r = {}) {
90
- super(t), this[kError] = r.error === void 0 ? null : r.error, this[kMessage] = r.message === void 0 ? "" : r.message;
91
- }
92
- get error() {
93
- return this[kError];
129
+ get json() {
130
+ return JSON.parse(this.text);
94
131
  }
95
- get message() {
96
- return this[kMessage];
132
+ /**
133
+ * Response body as text.
134
+ */
135
+ get text() {
136
+ return new TextDecoder().decode(this.bytes);
97
137
  }
98
138
  }
99
- Object.defineProperty(ErrorEvent2.prototype, "error", { enumerable: !0 });
100
- Object.defineProperty(ErrorEvent2.prototype, "message", { enumerable: !0 });
101
- const ErrorEvent = typeof globalThis.ErrorEvent == "function" ? globalThis.ErrorEvent : ErrorEvent2;
102
- function isExitCodeZero(e) {
103
- 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;
139
+ const FileErrorCodes = {
140
+ 0: "No error occurred. System call completed successfully.",
141
+ 1: "Argument list too long.",
142
+ 2: "Permission denied.",
143
+ 3: "Address in use.",
144
+ 4: "Address not available.",
145
+ 5: "Address family not supported.",
146
+ 6: "Resource unavailable, or operation would block.",
147
+ 7: "Connection already in progress.",
148
+ 8: "Bad file descriptor.",
149
+ 9: "Bad message.",
150
+ 10: "Device or resource busy.",
151
+ 11: "Operation canceled.",
152
+ 12: "No child processes.",
153
+ 13: "Connection aborted.",
154
+ 14: "Connection refused.",
155
+ 15: "Connection reset.",
156
+ 16: "Resource deadlock would occur.",
157
+ 17: "Destination address required.",
158
+ 18: "Mathematics argument out of domain of function.",
159
+ 19: "Reserved.",
160
+ 20: "File exists.",
161
+ 21: "Bad address.",
162
+ 22: "File too large.",
163
+ 23: "Host is unreachable.",
164
+ 24: "Identifier removed.",
165
+ 25: "Illegal byte sequence.",
166
+ 26: "Operation in progress.",
167
+ 27: "Interrupted function.",
168
+ 28: "Invalid argument.",
169
+ 29: "I/O error.",
170
+ 30: "Socket is connected.",
171
+ 31: "There is a directory under that path.",
172
+ 32: "Too many levels of symbolic links.",
173
+ 33: "File descriptor value too large.",
174
+ 34: "Too many links.",
175
+ 35: "Message too large.",
176
+ 36: "Reserved.",
177
+ 37: "Filename too long.",
178
+ 38: "Network is down.",
179
+ 39: "Connection aborted by network.",
180
+ 40: "Network unreachable.",
181
+ 41: "Too many files open in system.",
182
+ 42: "No buffer space available.",
183
+ 43: "No such device.",
184
+ 44: "There is no such file or directory OR the parent directory does not exist.",
185
+ 45: "Executable file format error.",
186
+ 46: "No locks available.",
187
+ 47: "Reserved.",
188
+ 48: "Not enough space.",
189
+ 49: "No message of the desired type.",
190
+ 50: "Protocol not available.",
191
+ 51: "No space left on device.",
192
+ 52: "Function not supported.",
193
+ 53: "The socket is not connected.",
194
+ 54: "Not a directory or a symbolic link to a directory.",
195
+ 55: "Directory not empty.",
196
+ 56: "State not recoverable.",
197
+ 57: "Not a socket.",
198
+ 58: "Not supported, or operation not supported on socket.",
199
+ 59: "Inappropriate I/O control operation.",
200
+ 60: "No such device or address.",
201
+ 61: "Value too large to be stored in data type.",
202
+ 62: "Previous owner died.",
203
+ 63: "Operation not permitted.",
204
+ 64: "Broken pipe.",
205
+ 65: "Protocol error.",
206
+ 66: "Protocol not supported.",
207
+ 67: "Protocol wrong type for socket.",
208
+ 68: "Result too large.",
209
+ 69: "Read-only file system.",
210
+ 70: "Invalid seek.",
211
+ 71: "No such process.",
212
+ 72: "Reserved.",
213
+ 73: "Connection timed out.",
214
+ 74: "Text file busy.",
215
+ 75: "Cross-device link.",
216
+ 76: "Extension: Capabilities insufficient."
217
+ };
218
+ function getEmscriptenFsError(e) {
219
+ const t = typeof e == "object" ? e == null ? void 0 : e.errno : null;
220
+ if (t in FileErrorCodes)
221
+ return FileErrorCodes[t];
222
+ }
223
+ function rethrowFileSystemError(e = "") {
224
+ return function(s, r, n) {
225
+ const i = n.value;
226
+ n.value = function(...o) {
227
+ try {
228
+ return i.apply(this, o);
229
+ } catch (c) {
230
+ const l = typeof c == "object" ? c == null ? void 0 : c.errno : null;
231
+ if (l in FileErrorCodes) {
232
+ const a = FileErrorCodes[l], p = typeof o[0] == "string" ? o[0] : null, m = p !== null ? e.replaceAll("{path}", p) : e;
233
+ throw new Error(`${m}: ${a}`, {
234
+ cause: c
235
+ });
236
+ }
237
+ throw c;
238
+ }
239
+ };
240
+ };
104
241
  }
105
242
  const logToConsole = (e, ...t) => {
106
- switch (e.severity) {
243
+ switch (typeof e.message == "string" ? e.message = prepareLogMessage(e.message) : e.message.message && typeof e.message.message == "string" && (e.message.message = prepareLogMessage(e.message.message)), e.severity) {
107
244
  case "Debug":
108
245
  console.debug(e.message, ...t);
109
246
  break;
@@ -122,17 +259,15 @@ const logToConsole = (e, ...t) => {
122
259
  default:
123
260
  console.log(e.message, ...t);
124
261
  }
125
- }, prepareLogMessage = (e, ...t) => [
126
- typeof e == "object" ? JSON.stringify(e) : e,
127
- ...t.map((r) => JSON.stringify(r))
128
- ].join(" "), logs = [], addToLogArray = (e) => {
262
+ }, prepareLogMessage$1 = (e) => e instanceof Error ? [e.message, e.stack].join(`
263
+ `) : JSON.stringify(e, null, 2), logs = [], addToLogArray = (e) => {
129
264
  logs.push(e);
130
265
  }, logToMemory = (e) => {
131
266
  if (e.raw === !0)
132
267
  addToLogArray(e.message);
133
268
  else {
134
269
  const t = formatLogEntry(
135
- typeof e.message == "object" ? prepareLogMessage(e.message) : e.message,
270
+ typeof e.message == "object" ? prepareLogMessage$1(e.message) : e.message,
136
271
  e.severity ?? "Info",
137
272
  e.prefix ?? "JavaScript"
138
273
  );
@@ -161,9 +296,9 @@ class Logger extends EventTarget {
161
296
  * @param raw boolean
162
297
  * @param args any
163
298
  */
164
- logMessage(t, ...r) {
165
- for (const s of this.handlers)
166
- s(t, ...r);
299
+ logMessage(t, ...s) {
300
+ for (const r of this.handlers)
301
+ r(t, ...s);
167
302
  }
168
303
  /**
169
304
  * Log message
@@ -171,7 +306,7 @@ class Logger extends EventTarget {
171
306
  * @param message any
172
307
  * @param args any
173
308
  */
174
- log(t, ...r) {
309
+ log(t, ...s) {
175
310
  this.logMessage(
176
311
  {
177
312
  message: t,
@@ -179,7 +314,7 @@ class Logger extends EventTarget {
179
314
  prefix: "JavaScript",
180
315
  raw: !1
181
316
  },
182
- ...r
317
+ ...s
183
318
  );
184
319
  }
185
320
  /**
@@ -188,7 +323,7 @@ class Logger extends EventTarget {
188
323
  * @param message any
189
324
  * @param args any
190
325
  */
191
- debug(t, ...r) {
326
+ debug(t, ...s) {
192
327
  this.logMessage(
193
328
  {
194
329
  message: t,
@@ -196,7 +331,7 @@ class Logger extends EventTarget {
196
331
  prefix: "JavaScript",
197
332
  raw: !1
198
333
  },
199
- ...r
334
+ ...s
200
335
  );
201
336
  }
202
337
  /**
@@ -205,7 +340,7 @@ class Logger extends EventTarget {
205
340
  * @param message any
206
341
  * @param args any
207
342
  */
208
- info(t, ...r) {
343
+ info(t, ...s) {
209
344
  this.logMessage(
210
345
  {
211
346
  message: t,
@@ -213,7 +348,7 @@ class Logger extends EventTarget {
213
348
  prefix: "JavaScript",
214
349
  raw: !1
215
350
  },
216
- ...r
351
+ ...s
217
352
  );
218
353
  }
219
354
  /**
@@ -222,7 +357,7 @@ class Logger extends EventTarget {
222
357
  * @param message any
223
358
  * @param args any
224
359
  */
225
- warn(t, ...r) {
360
+ warn(t, ...s) {
226
361
  this.logMessage(
227
362
  {
228
363
  message: t,
@@ -230,7 +365,7 @@ class Logger extends EventTarget {
230
365
  prefix: "JavaScript",
231
366
  raw: !1
232
367
  },
233
- ...r
368
+ ...s
234
369
  );
235
370
  }
236
371
  /**
@@ -239,7 +374,7 @@ class Logger extends EventTarget {
239
374
  * @param message any
240
375
  * @param args any
241
376
  */
242
- error(t, ...r) {
377
+ error(t, ...s) {
243
378
  this.logMessage(
244
379
  {
245
380
  message: t,
@@ -247,35 +382,101 @@ class Logger extends EventTarget {
247
382
  prefix: "JavaScript",
248
383
  raw: !1
249
384
  },
250
- ...r
385
+ ...s
251
386
  );
252
387
  }
253
388
  }
254
- const logger = new Logger([logToMemory, logToConsole]), formatLogEntry = (e, t, r) => {
255
- const s = /* @__PURE__ */ new Date(), n = new Intl.DateTimeFormat("en-GB", {
389
+ const getDefaultHandlers = () => {
390
+ try {
391
+ if (process.env.NODE_ENV === "test")
392
+ return [logToMemory];
393
+ } catch {
394
+ }
395
+ return [logToMemory, logToConsole];
396
+ }, logger = new Logger(getDefaultHandlers()), prepareLogMessage = (e) => e.replace(/\t/g, ""), formatLogEntry = (e, t, s) => {
397
+ const r = /* @__PURE__ */ new Date(), n = new Intl.DateTimeFormat("en-GB", {
256
398
  year: "numeric",
257
399
  month: "short",
258
400
  day: "2-digit",
259
401
  timeZone: "UTC"
260
- }).format(s).replace(/ /g, "-"), i = new Intl.DateTimeFormat("en-GB", {
402
+ }).format(r).replace(/ /g, "-"), i = new Intl.DateTimeFormat("en-GB", {
261
403
  hour: "2-digit",
262
404
  minute: "2-digit",
263
405
  second: "2-digit",
264
406
  hour12: !1,
265
407
  timeZone: "UTC",
266
408
  timeZoneName: "short"
267
- }).format(s);
268
- return `[${n + " " + i}] ${r} ${t}: ${e}`;
269
- };
409
+ }).format(r), o = n + " " + i;
410
+ return e = prepareLogMessage(e), `[${o}] ${s} ${t}: ${e}`;
411
+ }, RuntimeId = Symbol("RuntimeId"), loadedRuntimes = /* @__PURE__ */ new Map();
412
+ let lastRuntimeId = 0;
413
+ async function loadPHPRuntime(e, t = {}) {
414
+ const [s, r, n] = makePromise(), i = e.init(currentJsRuntime, {
415
+ onAbort(c) {
416
+ n(c), logger.error(c);
417
+ },
418
+ ENV: {},
419
+ // Emscripten sometimes prepends a '/' to the path, which
420
+ // breaks vite dev mode. An identity `locateFile` function
421
+ // fixes it.
422
+ locateFile: (c) => c,
423
+ ...t,
424
+ noInitialRun: !0,
425
+ onRuntimeInitialized() {
426
+ t.onRuntimeInitialized && t.onRuntimeInitialized(), r();
427
+ }
428
+ });
429
+ await s;
430
+ const o = ++lastRuntimeId;
431
+ return i.id = o, i.originalExit = i._exit, i._exit = function(c) {
432
+ return loadedRuntimes.delete(o), i.originalExit(c);
433
+ }, i[RuntimeId] = o, loadedRuntimes.set(o, i), o;
434
+ }
435
+ function getLoadedRuntime(e) {
436
+ return loadedRuntimes.get(e);
437
+ }
438
+ const currentJsRuntime = function() {
439
+ var e;
440
+ 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";
441
+ }(), makePromise = () => {
442
+ const e = [], t = new Promise((s, r) => {
443
+ e.push(s, r);
444
+ });
445
+ return e.unshift(t), e;
446
+ }, kError = Symbol("error"), kMessage = Symbol("message");
447
+ class ErrorEvent2 extends Event {
448
+ /**
449
+ * Create a new `ErrorEvent`.
450
+ *
451
+ * @param type The name of the event
452
+ * @param options A dictionary object that allows for setting
453
+ * attributes via object members of the same name.
454
+ */
455
+ constructor(t, s = {}) {
456
+ super(t), this[kError] = s.error === void 0 ? null : s.error, this[kMessage] = s.message === void 0 ? "" : s.message;
457
+ }
458
+ get error() {
459
+ return this[kError];
460
+ }
461
+ get message() {
462
+ return this[kMessage];
463
+ }
464
+ }
465
+ Object.defineProperty(ErrorEvent2.prototype, "error", { enumerable: !0 });
466
+ Object.defineProperty(ErrorEvent2.prototype, "message", { enumerable: !0 });
467
+ const ErrorEvent = typeof globalThis.ErrorEvent == "function" ? globalThis.ErrorEvent : ErrorEvent2;
468
+ function isExitCodeZero(e) {
469
+ 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;
470
+ }
270
471
  class UnhandledRejectionsTarget extends EventTarget {
271
472
  constructor() {
272
473
  super(...arguments), this.listenersCount = 0;
273
474
  }
274
- addEventListener(t, r) {
275
- ++this.listenersCount, super.addEventListener(t, r);
475
+ addEventListener(t, s) {
476
+ ++this.listenersCount, super.addEventListener(t, s);
276
477
  }
277
- removeEventListener(t, r) {
278
- --this.listenersCount, super.removeEventListener(t, r);
478
+ removeEventListener(t, s) {
479
+ --this.listenersCount, super.removeEventListener(t, s);
279
480
  }
280
481
  hasListeners() {
281
482
  return this.listenersCount > 0;
@@ -286,17 +487,17 @@ function improveWASMErrorReporting(e) {
286
487
  ...e.asm
287
488
  };
288
489
  const t = new UnhandledRejectionsTarget();
289
- for (const r in e.asm)
290
- if (typeof e.asm[r] == "function") {
291
- const s = e.asm[r];
292
- e.asm[r] = function(...n) {
490
+ for (const s in e.asm)
491
+ if (typeof e.asm[s] == "function") {
492
+ const r = e.asm[s];
493
+ e.asm[s] = function(...n) {
293
494
  var i;
294
495
  try {
295
- return s(...n);
496
+ return r(...n);
296
497
  } catch (o) {
297
498
  if (!(o instanceof Error))
298
499
  throw o;
299
- const a = clarifyErrorMessage(
500
+ const c = clarifyErrorMessage(
300
501
  o,
301
502
  (i = e.lastAsyncifyStackSource) == null ? void 0 : i.stack
302
503
  );
@@ -304,12 +505,12 @@ function improveWASMErrorReporting(e) {
304
505
  t.dispatchEvent(
305
506
  new ErrorEvent("error", {
306
507
  error: o,
307
- message: a
508
+ message: c
308
509
  })
309
510
  );
310
511
  return;
311
512
  }
312
- throw isExitCodeZero(o) || showCriticalErrorBox(a), o;
513
+ throw isExitCodeZero(o) || showCriticalErrorBox(c), o;
313
514
  }
314
515
  };
315
516
  }
@@ -321,8 +522,8 @@ function getFunctionsMaybeMissingFromAsyncify() {
321
522
  }
322
523
  function clarifyErrorMessage(e, t) {
323
524
  if (e.message === "unreachable") {
324
- let r = UNREACHABLE_ERROR;
325
- t || (r += `
525
+ let s = UNREACHABLE_ERROR;
526
+ t || (s += `
326
527
 
327
528
  This stack trace is lacking. For a better one initialize
328
529
  the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
@@ -330,10 +531,10 @@ the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
330
531
  `), functionsMaybeMissingFromAsyncify = extractPHPFunctionsFromStack(
331
532
  t || e.stack || ""
332
533
  );
333
- for (const s of functionsMaybeMissingFromAsyncify)
334
- r += ` * ${s}
534
+ for (const r of functionsMaybeMissingFromAsyncify)
535
+ s += ` * ${r}
335
536
  `;
336
- return r;
537
+ return s;
337
538
  }
338
539
  return e.message;
339
540
  }
@@ -377,43 +578,20 @@ ${bold} WASM ERROR${reset}${redBg}`);
377
578
  function extractPHPFunctionsFromStack(e) {
378
579
  try {
379
580
  const t = e.split(`
380
- `).slice(1).map((r) => {
381
- const s = r.trim().substring(3).split(" ");
581
+ `).slice(1).map((s) => {
582
+ const r = s.trim().substring(3).split(" ");
382
583
  return {
383
- fn: s.length >= 2 ? s[0] : "<unknown>",
384
- isWasm: r.includes("wasm://")
584
+ fn: r.length >= 2 ? r[0] : "<unknown>",
585
+ isWasm: s.includes("wasm://")
385
586
  };
386
587
  }).filter(
387
- ({ fn: r, isWasm: s }) => s && !r.startsWith("dynCall_") && !r.startsWith("invoke_")
388
- ).map(({ fn: r }) => r);
588
+ ({ fn: s, isWasm: r }) => r && !s.startsWith("dynCall_") && !s.startsWith("invoke_")
589
+ ).map(({ fn: s }) => s);
389
590
  return Array.from(new Set(t));
390
591
  } catch {
391
592
  return [];
392
593
  }
393
594
  }
394
- class HttpCookieStore {
395
- constructor() {
396
- this.cookies = {};
397
- }
398
- rememberCookiesFromResponseHeaders(t) {
399
- if (t != null && t["set-cookie"])
400
- for (const r of t["set-cookie"])
401
- try {
402
- if (!r.includes("="))
403
- continue;
404
- const s = r.indexOf("="), n = r.substring(0, s), i = r.substring(s + 1).split(";")[0];
405
- this.cookies[n] = i;
406
- } catch (s) {
407
- logger.error(s);
408
- }
409
- }
410
- getCookieRequestHeader() {
411
- const t = [];
412
- for (const r in this.cookies)
413
- t.push(`${r}=${this.cookies[r]}`);
414
- return t.join("; ");
415
- }
416
- }
417
595
  const SleepFinished = Symbol("SleepFinished");
418
596
  function sleep(e) {
419
597
  return new Promise((t) => {
@@ -426,8 +604,8 @@ class AcquireTimeoutError extends Error {
426
604
  }
427
605
  }
428
606
  class Semaphore {
429
- constructor({ concurrency: t, timeout: r }) {
430
- this._running = 0, this.concurrency = t, this.timeout = r, this.queue = [];
607
+ constructor({ concurrency: t, timeout: s }) {
608
+ this._running = 0, this.concurrency = t, this.timeout = s, this.queue = [];
431
609
  }
432
610
  get remaining() {
433
611
  return this.concurrency - this.running;
@@ -438,12 +616,12 @@ class Semaphore {
438
616
  async acquire() {
439
617
  for (; ; )
440
618
  if (this._running >= this.concurrency) {
441
- const t = new Promise((r) => {
442
- this.queue.push(r);
619
+ const t = new Promise((s) => {
620
+ this.queue.push(s);
443
621
  });
444
622
  this.timeout !== void 0 ? await Promise.race([t, sleep(this.timeout)]).then(
445
- (r) => {
446
- if (r === SleepFinished)
623
+ (s) => {
624
+ if (s === SleepFinished)
447
625
  throw new AcquireTimeoutError();
448
626
  }
449
627
  ) : await t;
@@ -456,18 +634,18 @@ class Semaphore {
456
634
  }
457
635
  }
458
636
  async run(t) {
459
- const r = await this.acquire();
637
+ const s = await this.acquire();
460
638
  try {
461
639
  return await t();
462
640
  } finally {
463
- r();
641
+ s();
464
642
  }
465
643
  }
466
644
  }
467
645
  function joinPaths(...e) {
468
646
  let t = e.join("/");
469
- const r = t[0] === "/", s = t.substring(t.length - 1) === "/";
470
- return t = normalizePath(t), !t && !r && (t = "."), t && s && (t += "/"), t;
647
+ const s = t[0] === "/", r = t.substring(t.length - 1) === "/";
648
+ return t = normalizePath(t), !t && !s && (t = "."), t && r && (t += "/"), t;
471
649
  }
472
650
  function dirname(e) {
473
651
  if (e === "/")
@@ -479,38 +657,38 @@ function dirname(e) {
479
657
  function normalizePath(e) {
480
658
  const t = e[0] === "/";
481
659
  return e = normalizePathsArray(
482
- e.split("/").filter((r) => !!r),
660
+ e.split("/").filter((s) => !!s),
483
661
  !t
484
662
  ).join("/"), (t ? "/" : "") + e.replace(/\/$/, "");
485
663
  }
486
664
  function normalizePathsArray(e, t) {
487
- let r = 0;
488
- for (let s = e.length - 1; s >= 0; s--) {
489
- const n = e[s];
490
- n === "." ? e.splice(s, 1) : n === ".." ? (e.splice(s, 1), r++) : r && (e.splice(s, 1), r--);
665
+ let s = 0;
666
+ for (let r = e.length - 1; r >= 0; r--) {
667
+ const n = e[r];
668
+ n === "." ? e.splice(r, 1) : n === ".." ? (e.splice(r, 1), s++) : s && (e.splice(r, 1), s--);
491
669
  }
492
670
  if (t)
493
- for (; r; r--)
671
+ for (; s; s--)
494
672
  e.unshift("..");
495
673
  return e;
496
674
  }
497
675
  function splitShellCommand(e) {
498
- let s = 0, n = "";
676
+ let r = 0, n = "";
499
677
  const i = [];
500
678
  let o = "";
501
- for (let a = 0; a < e.length; a++) {
502
- const l = e[a];
503
- l === "\\" ? ((e[a + 1] === '"' || e[a + 1] === "'") && a++, o += e[a]) : s === 0 ? l === '"' || l === "'" ? (s = 1, n = l) : l.match(/\s/) ? (o.trim().length && i.push(o.trim()), o = l) : i.length && !o ? o = i.pop() + l : o += l : s === 1 && (l === n ? (s = 0, n = "") : o += l);
679
+ for (let c = 0; c < e.length; c++) {
680
+ const l = e[c];
681
+ l === "\\" ? ((e[c + 1] === '"' || e[c + 1] === "'") && c++, o += e[c]) : r === 0 ? l === '"' || l === "'" ? (r = 1, n = l) : l.match(/\s/) ? (o.trim().length && i.push(o.trim()), o = l) : i.length && !o ? o = i.pop() + l : o += l : r === 1 && (l === n ? (r = 0, n = "") : o += l);
504
682
  }
505
683
  return o && i.push(o.trim()), i;
506
684
  }
507
685
  function createSpawnHandler(e) {
508
- return function(t, r = [], s = {}) {
686
+ return function(t, s = [], r = {}) {
509
687
  const n = new ChildProcess(), i = new ProcessApi(n);
510
688
  return setTimeout(async () => {
511
689
  let o = [];
512
- if (r.length)
513
- o = [t, ...r];
690
+ if (s.length)
691
+ o = [t, ...s];
514
692
  else if (typeof t == "string")
515
693
  o = splitShellCommand(t);
516
694
  else if (Array.isArray(t))
@@ -518,9 +696,9 @@ function createSpawnHandler(e) {
518
696
  else
519
697
  throw new Error("Invalid command ", t);
520
698
  try {
521
- await e(o, i, s);
522
- } catch (a) {
523
- n.emit("error", a), typeof a == "object" && a !== null && "message" in a && typeof a.message == "string" && i.stderr(a.message), i.exit(1);
699
+ await e(o, i, r);
700
+ } catch (c) {
701
+ n.emit("error", c), typeof c == "object" && c !== null && "message" in c && typeof c.message == "string" && i.stderr(c.message), i.exit(1);
524
702
  }
525
703
  n.emit("spawn", !0);
526
704
  }), n;
@@ -530,19 +708,19 @@ class EventEmitter {
530
708
  constructor() {
531
709
  this.listeners = {};
532
710
  }
533
- emit(t, r) {
534
- this.listeners[t] && this.listeners[t].forEach(function(s) {
535
- s(r);
711
+ emit(t, s) {
712
+ this.listeners[t] && this.listeners[t].forEach(function(r) {
713
+ r(s);
536
714
  });
537
715
  }
538
- on(t, r) {
539
- this.listeners[t] || (this.listeners[t] = []), this.listeners[t].push(r);
716
+ on(t, s) {
717
+ this.listeners[t] || (this.listeners[t] = []), this.listeners[t].push(s);
540
718
  }
541
719
  }
542
720
  class ProcessApi extends EventEmitter {
543
721
  constructor(t) {
544
- super(), this.childProcess = t, this.exited = !1, this.stdinData = [], t.on("stdin", (r) => {
545
- this.stdinData ? this.stdinData.push(r.slice()) : this.emit("stdin", r);
722
+ super(), this.childProcess = t, this.exited = !1, this.stdinData = [], t.on("stdin", (s) => {
723
+ this.stdinData ? this.stdinData.push(s.slice()) : this.emit("stdin", s);
546
724
  });
547
725
  }
548
726
  stdout(t) {
@@ -571,1081 +749,1058 @@ let lastPid = 9743;
571
749
  class ChildProcess extends EventEmitter {
572
750
  constructor(t = lastPid++) {
573
751
  super(), this.pid = t, this.stdout = new EventEmitter(), this.stderr = new EventEmitter();
574
- const r = this;
752
+ const s = this;
575
753
  this.stdin = {
576
- write: (s) => {
577
- r.emit("stdin", s);
754
+ write: (r) => {
755
+ s.emit("stdin", r);
578
756
  }
579
757
  };
580
758
  }
581
759
  }
582
- function concatUint8Array(...e) {
583
- const t = new Uint8Array(
584
- e.reduce((s, n) => s + n.length, 0)
585
- );
586
- let r = 0;
587
- for (const s of e)
588
- t.set(s, r), r += s.length;
589
- return t;
760
+ var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyDescriptor, __decorateClass = (e, t, s, r) => {
761
+ for (var n = r > 1 ? void 0 : r ? __getOwnPropDesc(t, s) : t, i = e.length - 1, o; i >= 0; i--)
762
+ (o = e[i]) && (n = (r ? o(t, s, n) : o(n)) || n);
763
+ return r && n && __defProp(t, s, n), n;
764
+ };
765
+ const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
766
+ class PHPExecutionFailureError extends Error {
767
+ constructor(t, s, r) {
768
+ super(t), this.response = s, this.source = r;
769
+ }
590
770
  }
591
- function concatBytes(e) {
592
- if (e === void 0) {
593
- let t = new Uint8Array();
594
- return new TransformStream({
595
- transform(r) {
596
- t = concatUint8Array(t, r);
597
- },
598
- flush(r) {
599
- r.enqueue(t);
600
- }
601
- });
602
- } else {
603
- const t = new ArrayBuffer(e || 0);
604
- let r = 0;
605
- return new TransformStream({
606
- transform(s) {
607
- new Uint8Array(t).set(s, r), r += s.byteLength;
608
- },
609
- flush(s) {
610
- s.enqueue(new Uint8Array(t));
611
- }
612
- });
613
- }
614
- }
615
- function limitBytes(e, t) {
616
- if (t === 0)
617
- return new ReadableStream({
618
- start(n) {
619
- n.close();
620
- }
621
- });
622
- const r = e.getReader({ mode: "byob" });
623
- let s = 0;
624
- return new ReadableStream({
625
- async pull(n) {
626
- const { value: i, done: o } = await r.read(
627
- new Uint8Array(t - s)
628
- );
629
- if (o) {
630
- r.releaseLock(), n.close();
631
- return;
632
- }
633
- s += i.length, n.enqueue(i), s >= t && (r.releaseLock(), n.close());
634
- },
635
- cancel() {
636
- r.cancel();
637
- }
638
- });
639
- }
640
- async function collectBytes(e, t) {
641
- return t !== void 0 && (e = limitBytes(e, t)), await e.pipeThrough(concatBytes(t)).getReader().read().then(({ value: r }) => r);
642
- }
643
- class StreamedFile extends File {
771
+ const PHP_INI_PATH = "/internal/shared/php.ini", AUTO_PREPEND_SCRIPT = "/internal/shared/auto_prepend_file.php";
772
+ var b, v, x, P, R, C, X, M, ee, N, te, O, se, L, re, B, ne, U, ie, j, oe, $, ae, D, ce, k, Z, q, le, z, ue, W, de;
773
+ class BasePHP {
644
774
  /**
645
- * Creates a new StreamedFile instance.
775
+ * Initializes a PHP runtime.
646
776
  *
647
- * @param readableStream The readable stream containing the file data.
648
- * @param name The name of the file.
649
- * @param type The MIME type of the file.
777
+ * @internal
778
+ * @param PHPRuntime - Optional. PHP Runtime ID as initialized by loadPHPRuntime.
779
+ * @param requestHandlerOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
650
780
  */
651
- constructor(t, r, s) {
652
- super([], r, { type: s }), this.readableStream = t;
781
+ constructor(e) {
782
+ /**
783
+ * Prepares the $_SERVER entries for the PHP runtime.
784
+ *
785
+ * @param defaults Default entries to include in $_SERVER.
786
+ * @param headers HTTP headers to include in $_SERVER (as HTTP_ prefixed entries).
787
+ * @param port HTTP port, used to determine infer $_SERVER['HTTPS'] value if none
788
+ * was provided.
789
+ * @returns Computed $_SERVER entries.
790
+ */
791
+ d(this, C);
792
+ d(this, M);
793
+ d(this, N);
794
+ d(this, O);
795
+ d(this, L);
796
+ d(this, B);
797
+ d(this, U);
798
+ d(this, j);
799
+ d(this, $);
800
+ d(this, D);
801
+ d(this, k);
802
+ d(this, q);
803
+ d(this, z);
804
+ d(this, W);
805
+ d(this, b, void 0);
806
+ d(this, v, void 0);
807
+ d(this, x, void 0);
808
+ d(this, P, void 0);
809
+ d(this, R, void 0);
810
+ f(this, v, !1), f(this, x, null), f(this, P, /* @__PURE__ */ new Map()), f(this, R, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e);
653
811
  }
654
- /**
655
- * Overrides the slice() method of the File class.
656
- *
657
- * @returns A Blob representing a portion of the file.
658
- */
659
- slice() {
660
- throw new Error("slice() is not possible on a StreamedFile");
812
+ addEventListener(e, t) {
813
+ u(this, P).has(e) || u(this, P).set(e, /* @__PURE__ */ new Set()), u(this, P).get(e).add(t);
661
814
  }
662
- /**
663
- * Returns the readable stream associated with the file.
664
- *
665
- * @returns The readable stream.
666
- */
667
- stream() {
668
- return this.readableStream;
815
+ removeEventListener(e, t) {
816
+ var s;
817
+ (s = u(this, P).get(e)) == null || s.delete(t);
669
818
  }
670
- /**
671
- * Loads the file data into memory and then returns it as a string.
672
- *
673
- * @returns File data as text.
674
- */
675
- async text() {
676
- return new TextDecoder().decode(await this.arrayBuffer());
819
+ dispatchEvent(e) {
820
+ const t = u(this, P).get(e.type);
821
+ if (t)
822
+ for (const s of t)
823
+ s(e);
677
824
  }
678
- /**
679
- * Loads the file data into memory and then returns it as an ArrayBuffer.
680
- *
681
- * @returns File data as an ArrayBuffer.
682
- */
683
- async arrayBuffer() {
684
- return await collectBytes(this.stream());
825
+ /** @inheritDoc */
826
+ async onMessage(e) {
827
+ u(this, R).push(e);
685
828
  }
686
- }
687
- ReadableStream.prototype[Symbol.asyncIterator] || (ReadableStream.prototype[Symbol.asyncIterator] = async function* () {
688
- const e = this.getReader();
689
- try {
690
- for (; ; ) {
691
- const { done: t, value: r } = await e.read();
692
- if (t)
693
- return;
694
- yield r;
695
- }
696
- } finally {
697
- e.releaseLock();
829
+ /** @inheritDoc */
830
+ async setSpawnHandler(handler) {
831
+ typeof handler == "string" && (handler = createSpawnHandler(eval(handler))), this[__private__dont__use].spawnProcess = handler;
698
832
  }
699
- }, ReadableStream.prototype.iterate = // @ts-ignore
700
- ReadableStream.prototype[Symbol.asyncIterator]);
701
- function streamReadFileFromPHP(e, t) {
702
- return new ReadableStream({
703
- async pull(r) {
704
- const s = await e.readFileAsBuffer(t);
705
- r.enqueue(s), r.close();
706
- }
707
- });
708
- }
709
- async function* iteratePhpFiles(e, t, {
710
- relativePaths: r = !0,
711
- pathPrefix: s,
712
- exceptPaths: n = []
713
- } = {}) {
714
- t = normalizePath(t);
715
- const i = [t];
716
- for (; i.length; ) {
717
- const o = i.pop();
718
- if (!o)
719
- return;
720
- const a = await e.listFiles(o);
721
- for (const l of a) {
722
- const c = `${o}/${l}`;
723
- if (n.includes(c.substring(t.length + 1)))
724
- continue;
725
- await e.isDir(c) ? i.push(c) : yield new StreamedFile(
726
- streamReadFileFromPHP(e, c),
727
- r ? joinPaths(
728
- s || "",
729
- c.substring(t.length + 1)
730
- ) : c
731
- );
732
- }
833
+ /** @inheritDoc */
834
+ get absoluteUrl() {
835
+ return this.requestHandler.absoluteUrl;
733
836
  }
734
- }
735
- function writeFilesStreamToPhp(e, t) {
736
- return new WritableStream({
737
- async write(r) {
738
- const s = joinPaths(t, r.name);
739
- r.type === "directory" ? await e.mkdir(s) : (await e.mkdir(dirname(s)), await e.writeFile(
740
- s,
741
- new Uint8Array(await r.arrayBuffer())
742
- ));
743
- }
744
- });
745
- }
746
- class MaxPhpInstancesError extends Error {
747
- constructor(t) {
748
- super(
749
- `Requested more concurrent PHP instances than the limit (${t}).`
750
- ), this.name = this.constructor.name;
837
+ /** @inheritDoc */
838
+ get documentRoot() {
839
+ return this.requestHandler.documentRoot;
751
840
  }
752
- }
753
- class PHPProcessManager {
754
- constructor(t) {
755
- this.primaryIdle = !0, this.nextInstance = null, this.allInstances = [], this.maxPhpInstances = (t == null ? void 0 : t.maxPhpInstances) ?? 5, this.phpFactory = t == null ? void 0 : t.phpFactory, this.primaryPhp = t == null ? void 0 : t.primaryPhp, this.semaphore = new Semaphore({
756
- concurrency: this.maxPhpInstances,
757
- /**
758
- * Wait up to 5 seconds for resources to become available
759
- * before assuming that all the PHP instances are deadlocked.
760
- */
761
- timeout: (t == null ? void 0 : t.timeout) || 5e3
841
+ /** @inheritDoc */
842
+ pathToInternalUrl(e) {
843
+ return this.requestHandler.pathToInternalUrl(e);
844
+ }
845
+ /** @inheritDoc */
846
+ internalUrlToPath(e) {
847
+ return this.requestHandler.internalUrlToPath(e);
848
+ }
849
+ initializeRuntime(e) {
850
+ if (this[__private__dont__use])
851
+ throw new Error("PHP runtime already initialized.");
852
+ const t = getLoadedRuntime(e);
853
+ if (!t)
854
+ throw new Error("Invalid PHP runtime id.");
855
+ this[__private__dont__use] = t, this[__private__dont__use].ccall(
856
+ "wasm_set_phpini_path",
857
+ null,
858
+ ["string"],
859
+ [PHP_INI_PATH]
860
+ ), this.fileExists(PHP_INI_PATH) || this.writeFile(
861
+ PHP_INI_PATH,
862
+ [
863
+ "auto_prepend_file=" + AUTO_PREPEND_SCRIPT,
864
+ "memory_limit=256M",
865
+ "ignore_repeated_errors = 1",
866
+ "error_reporting = E_ALL",
867
+ "display_errors = 1",
868
+ "html_errors = 1",
869
+ "display_startup_errors = On",
870
+ "log_errors = 1",
871
+ "always_populate_raw_post_data = -1",
872
+ "upload_max_filesize = 2000M",
873
+ "post_max_size = 2000M",
874
+ "disable_functions = curl_exec,curl_multi_exec",
875
+ "allow_url_fopen = Off",
876
+ "allow_url_include = Off",
877
+ "session.save_path = /home/web_user",
878
+ "implicit_flush = 1",
879
+ "output_buffering = 0",
880
+ "max_execution_time = 0",
881
+ "max_input_time = -1"
882
+ ].join(`
883
+ `)
884
+ ), this.fileExists(AUTO_PREPEND_SCRIPT) || this.writeFile(
885
+ AUTO_PREPEND_SCRIPT,
886
+ `<?php
887
+ // Define constants set via defineConstant() calls
888
+ if(file_exists('/internal/shared/consts.json')) {
889
+ $consts = json_decode(file_get_contents('/internal/shared/consts.json'), true);
890
+ foreach ($consts as $const => $value) {
891
+ if (!defined($const) && is_scalar($value)) {
892
+ define($const, $value);
893
+ }
894
+ }
895
+ }
896
+ // Preload all the files from /internal/shared/preload
897
+ foreach (glob('/internal/shared/preload/*.php') as $file) {
898
+ require_once $file;
899
+ }
900
+ `
901
+ ), t.onMessage = async (s) => {
902
+ for (const r of u(this, R)) {
903
+ const n = await r(s);
904
+ if (n)
905
+ return n;
906
+ }
907
+ return "";
908
+ }, f(this, x, improveWASMErrorReporting(t)), this.dispatchEvent({
909
+ type: "runtime.initialized"
762
910
  });
763
911
  }
764
- /**
765
- * Get the primary PHP instance.
766
- *
767
- * If the primary PHP instance is not set, it will be spawned
768
- * using the provided phpFactory.
769
- *
770
- * @throws {Error} when called twice before the first call is resolved.
771
- */
772
- async getPrimaryPhp() {
773
- if (!this.phpFactory && !this.primaryPhp)
912
+ /** @inheritDoc */
913
+ async setSapiName(e) {
914
+ if (this[__private__dont__use].ccall(
915
+ "wasm_set_sapi_name",
916
+ NUMBER,
917
+ [STRING],
918
+ [e]
919
+ ) !== 0)
774
920
  throw new Error(
775
- "phpFactory or primaryPhp must be set before calling getPrimaryPhp()."
921
+ "Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?"
776
922
  );
777
- if (!this.primaryPhp) {
778
- const t = await this.spawn({ isPrimary: !0 });
779
- this.primaryPhp = t.php;
780
- }
781
- return this.primaryPhp;
923
+ f(this, b, e);
782
924
  }
783
- /**
784
- * Get a PHP instance.
785
- *
786
- * It could be either the primary PHP instance, an idle disposable PHP instance,
787
- * or a newly spawned PHP instance – depending on the resource availability.
788
- *
789
- * @throws {MaxPhpInstancesError} when the maximum number of PHP instances is reached
790
- * and the waiting timeout is exceeded.
791
- */
792
- async acquirePHPInstance() {
793
- if (this.primaryIdle)
794
- return this.primaryIdle = !1, {
795
- php: await this.getPrimaryPhp(),
796
- reap: () => this.primaryIdle = !0
797
- };
798
- const t = this.nextInstance || this.spawn({ isPrimary: !1 });
799
- return this.semaphore.remaining > 0 ? this.nextInstance = this.spawn({ isPrimary: !1 }) : this.nextInstance = null, await t;
925
+ /** @inheritDoc */
926
+ chdir(e) {
927
+ this[__private__dont__use].FS.chdir(e);
800
928
  }
801
929
  /**
802
- * Initiated spawning of a new PHP instance.
803
- * This function is synchronous on purpose – it needs to synchronously
804
- * add the spawn promise to the allInstances array without waiting
805
- * for PHP to spawn.
930
+ * Do not use. Use new PHPRequestHandler() instead.
931
+ * @deprecated
806
932
  */
807
- spawn(t) {
808
- if (t.isPrimary && this.allInstances.length > 0)
809
- throw new Error(
810
- "Requested spawning a primary PHP instance when another primary instance already started spawning."
811
- );
812
- const r = this.doSpawn(t);
813
- this.allInstances.push(r);
814
- const s = () => {
815
- this.allInstances = this.allInstances.filter(
816
- (n) => n !== r
817
- );
818
- };
819
- return r.catch((n) => {
820
- throw s(), n;
821
- }).then((n) => ({
822
- ...n,
823
- reap: () => {
824
- s(), n.reap();
825
- }
826
- }));
933
+ async request(e) {
934
+ if (logger.warn(
935
+ "PHP.request() is deprecated. Please use new PHPRequestHandler() instead."
936
+ ), !this.requestHandler)
937
+ throw new Error("No request handler available.");
938
+ return this.requestHandler.request(e);
827
939
  }
828
- /**
829
- * Actually acquires the lock and spawns a new PHP instance.
830
- */
831
- async doSpawn(t) {
832
- let r;
833
- try {
834
- r = await this.semaphore.acquire();
835
- } catch (s) {
836
- throw s instanceof AcquireTimeoutError ? new MaxPhpInstancesError(this.maxPhpInstances) : s;
837
- }
940
+ /** @inheritDoc */
941
+ async run(e) {
942
+ const t = await this.semaphore.acquire();
943
+ let s;
838
944
  try {
839
- const s = await this.phpFactory(t);
840
- return {
841
- php: s,
842
- reap() {
843
- s.exit(), r();
844
- }
845
- };
846
- } catch (s) {
847
- throw r(), s;
848
- }
945
+ if (u(this, v) || (h(this, M, ee).call(this), f(this, v, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
946
+ throw new Error(
947
+ `The script path "${e.scriptPath}" does not exist.`
948
+ );
949
+ h(this, O, se).call(this, e.relativeUri || ""), h(this, j, oe).call(this, e.method || "GET");
950
+ const r = normalizeHeaders(e.headers || {}), n = r.host || "example.com:443", i = h(this, U, ie).call(this, n, e.protocol || "http");
951
+ h(this, L, re).call(this, n), h(this, B, ne).call(this, i), h(this, $, ae).call(this, r), e.body && (s = h(this, D, ce).call(this, e.body)), typeof e.code == "string" ? (this.writeFile("/internal/eval.php", e.code), h(this, k, Z).call(this, "/internal/eval.php")) : h(this, k, Z).call(this, e.scriptPath || "");
952
+ const o = h(this, C, X).call(this, e.$_SERVER, r, i);
953
+ for (const a in o)
954
+ h(this, q, le).call(this, a, o[a]);
955
+ const c = e.env || {};
956
+ for (const a in c)
957
+ h(this, z, ue).call(this, a, c[a]);
958
+ const l = await h(this, W, de).call(this);
959
+ if (l.exitCode !== 0) {
960
+ logger.warn("PHP.run() output was:", l.text);
961
+ const a = new PHPExecutionFailureError(
962
+ `PHP.run() failed with exit code ${l.exitCode} and the following output: ` + l.errors,
963
+ l,
964
+ "request"
965
+ );
966
+ throw logger.error(a), a;
967
+ }
968
+ return l;
969
+ } catch (r) {
970
+ throw this.dispatchEvent({
971
+ type: "request.error",
972
+ error: r,
973
+ // Distinguish between PHP request and PHP-wasm errors
974
+ source: r.source ?? "php-wasm"
975
+ }), r;
976
+ } finally {
977
+ try {
978
+ s && this[__private__dont__use].free(s);
979
+ } finally {
980
+ t(), this.dispatchEvent({
981
+ type: "request.end"
982
+ });
983
+ }
984
+ }
849
985
  }
850
- async [Symbol.asyncDispose]() {
851
- this.primaryPhp && this.primaryPhp.exit(), await Promise.all(
852
- this.allInstances.map(
853
- (t) => t.then(({ reap: r }) => r())
854
- )
986
+ defineConstant(e, t) {
987
+ let s = {};
988
+ try {
989
+ s = JSON.parse(
990
+ this.fileExists("/internal/shared/consts.json") && this.readFileAsText("/internal/shared/consts.json") || "{}"
991
+ );
992
+ } catch {
993
+ }
994
+ this.writeFile(
995
+ "/internal/shared/consts.json",
996
+ JSON.stringify({
997
+ ...s,
998
+ [e]: t
999
+ })
855
1000
  );
856
1001
  }
857
- }
858
- const responseTexts = {
859
- 500: "Internal Server Error",
860
- 502: "Bad Gateway",
861
- 404: "Not Found",
862
- 403: "Forbidden",
863
- 401: "Unauthorized",
864
- 400: "Bad Request",
865
- 301: "Moved Permanently",
866
- 302: "Found",
867
- 307: "Temporary Redirect",
868
- 308: "Permanent Redirect",
869
- 204: "No Content",
870
- 201: "Created",
871
- 200: "OK"
872
- };
873
- class PHPResponse {
874
- constructor(t, r, s, n = "", i = 0) {
875
- this.httpStatusCode = t, this.headers = r, this.bytes = s, this.exitCode = i, this.errors = n;
1002
+ mkdir(e) {
1003
+ this[__private__dont__use].FS.mkdirTree(e);
876
1004
  }
877
- static forHttpCode(t, r = "") {
878
- return new PHPResponse(
879
- t,
880
- {},
881
- new TextEncoder().encode(
882
- r || responseTexts[t] || ""
883
- )
884
- );
1005
+ mkdirTree(e) {
1006
+ this.mkdir(e);
885
1007
  }
886
- static fromRawData(t) {
887
- return new PHPResponse(
888
- t.httpStatusCode,
889
- t.headers,
890
- t.bytes,
891
- t.errors,
892
- t.exitCode
893
- );
1008
+ readFileAsText(e) {
1009
+ return new TextDecoder().decode(this.readFileAsBuffer(e));
894
1010
  }
895
- toRawData() {
896
- return {
897
- headers: this.headers,
898
- bytes: this.bytes,
899
- errors: this.errors,
900
- exitCode: this.exitCode,
901
- httpStatusCode: this.httpStatusCode
902
- };
1011
+ readFileAsBuffer(e) {
1012
+ return this[__private__dont__use].FS.readFile(e);
903
1013
  }
904
- /**
905
- * Response body as JSON.
906
- */
907
- get json() {
908
- return JSON.parse(this.text);
1014
+ writeFile(e, t) {
1015
+ this[__private__dont__use].FS.writeFile(e, t);
909
1016
  }
910
- /**
911
- * Response body as text.
912
- */
913
- get text() {
914
- return new TextDecoder().decode(this.bytes);
1017
+ unlink(e) {
1018
+ this[__private__dont__use].FS.unlink(e);
915
1019
  }
916
- }
917
- const SupportedPHPVersions = [
918
- "8.3",
919
- "8.2",
920
- "8.1",
921
- "8.0",
922
- "7.4",
923
- "7.3",
924
- "7.2",
925
- "7.1",
926
- "7.0"
927
- ], LatestSupportedPHPVersion = SupportedPHPVersions[0], SupportedPHPVersionsList = SupportedPHPVersions, SupportedPHPExtensionsList = [
928
- "iconv",
929
- "mbstring",
930
- "xml-bundle",
931
- "gd"
932
- ], SupportedPHPExtensionBundles = {
933
- "kitchen-sink": SupportedPHPExtensionsList,
934
- light: []
935
- }, FileErrorCodes = {
936
- 0: "No error occurred. System call completed successfully.",
937
- 1: "Argument list too long.",
938
- 2: "Permission denied.",
939
- 3: "Address in use.",
940
- 4: "Address not available.",
941
- 5: "Address family not supported.",
942
- 6: "Resource unavailable, or operation would block.",
943
- 7: "Connection already in progress.",
944
- 8: "Bad file descriptor.",
945
- 9: "Bad message.",
946
- 10: "Device or resource busy.",
947
- 11: "Operation canceled.",
948
- 12: "No child processes.",
949
- 13: "Connection aborted.",
950
- 14: "Connection refused.",
951
- 15: "Connection reset.",
952
- 16: "Resource deadlock would occur.",
953
- 17: "Destination address required.",
954
- 18: "Mathematics argument out of domain of function.",
955
- 19: "Reserved.",
956
- 20: "File exists.",
957
- 21: "Bad address.",
958
- 22: "File too large.",
959
- 23: "Host is unreachable.",
960
- 24: "Identifier removed.",
961
- 25: "Illegal byte sequence.",
962
- 26: "Operation in progress.",
963
- 27: "Interrupted function.",
964
- 28: "Invalid argument.",
965
- 29: "I/O error.",
966
- 30: "Socket is connected.",
967
- 31: "There is a directory under that path.",
968
- 32: "Too many levels of symbolic links.",
969
- 33: "File descriptor value too large.",
970
- 34: "Too many links.",
971
- 35: "Message too large.",
972
- 36: "Reserved.",
973
- 37: "Filename too long.",
974
- 38: "Network is down.",
975
- 39: "Connection aborted by network.",
976
- 40: "Network unreachable.",
977
- 41: "Too many files open in system.",
978
- 42: "No buffer space available.",
979
- 43: "No such device.",
980
- 44: "There is no such file or directory OR the parent directory does not exist.",
981
- 45: "Executable file format error.",
982
- 46: "No locks available.",
983
- 47: "Reserved.",
984
- 48: "Not enough space.",
985
- 49: "No message of the desired type.",
986
- 50: "Protocol not available.",
987
- 51: "No space left on device.",
988
- 52: "Function not supported.",
989
- 53: "The socket is not connected.",
990
- 54: "Not a directory or a symbolic link to a directory.",
991
- 55: "Directory not empty.",
992
- 56: "State not recoverable.",
993
- 57: "Not a socket.",
994
- 58: "Not supported, or operation not supported on socket.",
995
- 59: "Inappropriate I/O control operation.",
996
- 60: "No such device or address.",
997
- 61: "Value too large to be stored in data type.",
998
- 62: "Previous owner died.",
999
- 63: "Operation not permitted.",
1000
- 64: "Broken pipe.",
1001
- 65: "Protocol error.",
1002
- 66: "Protocol not supported.",
1003
- 67: "Protocol wrong type for socket.",
1004
- 68: "Result too large.",
1005
- 69: "Read-only file system.",
1006
- 70: "Invalid seek.",
1007
- 71: "No such process.",
1008
- 72: "Reserved.",
1009
- 73: "Connection timed out.",
1010
- 74: "Text file busy.",
1011
- 75: "Cross-device link.",
1012
- 76: "Extension: Capabilities insufficient."
1013
- };
1014
- function getEmscriptenFsError(e) {
1015
- const t = typeof e == "object" ? e == null ? void 0 : e.errno : null;
1016
- if (t in FileErrorCodes)
1017
- return FileErrorCodes[t];
1018
- }
1019
- function rethrowFileSystemError(e = "") {
1020
- return function(r, s, n) {
1021
- const i = n.value;
1022
- n.value = function(...o) {
1023
- try {
1024
- return i.apply(this, o);
1025
- } catch (a) {
1026
- const l = typeof a == "object" ? a == null ? void 0 : a.errno : null;
1027
- if (l in FileErrorCodes) {
1028
- const c = FileErrorCodes[l], g = typeof o[0] == "string" ? o[0] : null, me = g !== null ? e.replaceAll("{path}", g) : e;
1029
- throw new Error(`${me}: ${c}`, {
1030
- cause: a
1031
- });
1020
+ /** @inheritDoc */
1021
+ mv(e, t) {
1022
+ const s = this[__private__dont__use].FS;
1023
+ try {
1024
+ const r = s.lookupPath(e).node.mount, n = this.fileExists(t) ? s.lookupPath(t).node.mount : s.lookupPath(dirname(t)).node.mount;
1025
+ r.mountpoint !== n.mountpoint ? (copyRecursive(s, e, t), this.rmdir(e, { recursive: !0 })) : s.rename(e, t);
1026
+ } catch (r) {
1027
+ const n = getEmscriptenFsError(r);
1028
+ throw n ? new Error(
1029
+ `Could not move ${e} to ${t}: ${n}`,
1030
+ {
1031
+ cause: r
1032
1032
  }
1033
- throw a;
1033
+ ) : r;
1034
+ }
1035
+ }
1036
+ rmdir(e, t = { recursive: !0 }) {
1037
+ t != null && t.recursive && this.listFiles(e).forEach((s) => {
1038
+ const r = `${e}/${s}`;
1039
+ this.isDir(r) ? this.rmdir(r, t) : this.unlink(r);
1040
+ }), this[__private__dont__use].FS.rmdir(e);
1041
+ }
1042
+ listFiles(e, t = { prependPath: !1 }) {
1043
+ if (!this.fileExists(e))
1044
+ return [];
1045
+ try {
1046
+ const s = this[__private__dont__use].FS.readdir(e).filter(
1047
+ (r) => r !== "." && r !== ".."
1048
+ );
1049
+ if (t.prependPath) {
1050
+ const r = e.replace(/\/$/, "");
1051
+ return s.map((n) => `${r}/${n}`);
1034
1052
  }
1035
- };
1036
- };
1037
- }
1038
- const RuntimeId = Symbol("RuntimeId"), loadedRuntimes = /* @__PURE__ */ new Map();
1039
- let lastRuntimeId = 0;
1040
- async function loadPHPRuntime(e, t = {}) {
1041
- const [r, s, n] = makePromise(), i = e.init(currentJsRuntime, {
1042
- onAbort(a) {
1043
- n(a), logger.error(a);
1044
- },
1045
- ENV: {},
1046
- // Emscripten sometimes prepends a '/' to the path, which
1047
- // breaks vite dev mode. An identity `locateFile` function
1048
- // fixes it.
1049
- locateFile: (a) => a,
1050
- ...t,
1051
- noInitialRun: !0,
1052
- onRuntimeInitialized() {
1053
- t.onRuntimeInitialized && t.onRuntimeInitialized(), s();
1053
+ return s;
1054
+ } catch (s) {
1055
+ return logger.error(s, { path: e }), [];
1056
+ }
1057
+ }
1058
+ isDir(e) {
1059
+ return this.fileExists(e) ? this[__private__dont__use].FS.isDir(
1060
+ this[__private__dont__use].FS.lookupPath(e).node.mode
1061
+ ) : !1;
1062
+ }
1063
+ fileExists(e) {
1064
+ try {
1065
+ return this[__private__dont__use].FS.lookupPath(e), !0;
1066
+ } catch {
1067
+ return !1;
1054
1068
  }
1055
- });
1056
- await r;
1057
- const o = ++lastRuntimeId;
1058
- return i.id = o, i.originalExit = i._exit, i._exit = function(a) {
1059
- return loadedRuntimes.delete(o), i.originalExit(a);
1060
- }, i[RuntimeId] = o, loadedRuntimes.set(o, i), o;
1061
- }
1062
- function getLoadedRuntime(e) {
1063
- return loadedRuntimes.get(e);
1064
- }
1065
- const currentJsRuntime = function() {
1066
- var e;
1067
- 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";
1068
- }(), makePromise = () => {
1069
- const e = [], t = new Promise((r, s) => {
1070
- e.push(r, s);
1071
- });
1072
- return e.unshift(t), e;
1073
- };
1074
- var __defProp = Object.defineProperty, __getOwnPropDesc = Object.getOwnPropertyDescriptor, __decorateClass = (e, t, r, s) => {
1075
- for (var n = s > 1 ? void 0 : s ? __getOwnPropDesc(t, r) : t, i = e.length - 1, o; i >= 0; i--)
1076
- (o = e[i]) && (n = (s ? o(t, r, n) : o(n)) || n);
1077
- return s && n && __defProp(t, r, n), n;
1078
- };
1079
- const STRING = "string", NUMBER = "number", __private__dont__use = Symbol("__private__dont__use");
1080
- class PHPExecutionFailureError extends Error {
1081
- constructor(t, r, s) {
1082
- super(t), this.response = r, this.source = s;
1083
1069
  }
1084
- }
1085
- var w, v, R, f, P, _, S, C, Z, I, Y, A, K, k, X, M, ee, B, te, L, re, N, se, U, ne, O, ie, D, oe, $, ae, q, le, j, ce, z, ue;
1086
- class BasePHP {
1087
1070
  /**
1088
- * Initializes a PHP runtime.
1071
+ * Hot-swaps the PHP runtime for a new one without
1072
+ * interrupting the operations of this PHP instance.
1089
1073
  *
1090
- * @internal
1091
- * @param PHPRuntime - Optional. PHP Runtime ID as initialized by loadPHPRuntime.
1092
- * @param requestHandlerOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
1074
+ * @param runtime
1075
+ * @param cwd. Internal, the VFS path to recreate in the new runtime.
1076
+ * This arg is temporary and will be removed once BasePHP
1077
+ * is fully decoupled from the request handler and
1078
+ * accepts a constructor-level cwd argument.
1093
1079
  */
1094
- constructor(e) {
1095
- /**
1096
- * Prepares the $_SERVER entries for the PHP runtime.
1097
- *
1098
- * @param defaults Default entries to include in $_SERVER.
1099
- * @param headers HTTP headers to include in $_SERVER (as HTTP_ prefixed entries).
1100
- * @param port HTTP port, used to determine infer $_SERVER['HTTPS'] value if none
1101
- * was provided.
1102
- * @returns Computed $_SERVER entries.
1103
- */
1104
- h(this, C);
1105
- h(this, I);
1106
- h(this, A);
1107
- h(this, k);
1108
- h(this, M);
1109
- h(this, B);
1110
- h(this, L);
1111
- h(this, N);
1112
- h(this, U);
1113
- h(this, O);
1114
- h(this, D);
1115
- h(this, $);
1116
- h(this, q);
1117
- h(this, j);
1118
- h(this, z);
1119
- h(this, w, void 0);
1120
- h(this, v, void 0);
1121
- h(this, R, void 0);
1122
- h(this, f, void 0);
1123
- h(this, P, void 0);
1124
- h(this, _, void 0);
1125
- h(this, S, void 0);
1126
- d(this, w, []), d(this, f, !1), d(this, P, null), d(this, _, /* @__PURE__ */ new Map()), d(this, S, []), this.semaphore = new Semaphore({ concurrency: 1 }), e !== void 0 && this.initializeRuntime(e);
1080
+ hotSwapPHPRuntime(e, t) {
1081
+ const s = this[__private__dont__use].FS;
1082
+ try {
1083
+ this.exit();
1084
+ } catch {
1085
+ }
1086
+ this.initializeRuntime(e), u(this, b) && this.setSapiName(u(this, b)), t && copyFS(s, this[__private__dont__use].FS, t);
1127
1087
  }
1128
- addEventListener(e, t) {
1129
- u(this, _).has(e) || u(this, _).set(e, /* @__PURE__ */ new Set()), u(this, _).get(e).add(t);
1088
+ exit(e = 0) {
1089
+ this.dispatchEvent({
1090
+ type: "runtime.beforedestroy"
1091
+ });
1092
+ try {
1093
+ this[__private__dont__use]._exit(e);
1094
+ } catch {
1095
+ }
1096
+ f(this, v, !1), f(this, x, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1130
1097
  }
1131
- removeEventListener(e, t) {
1132
- var r;
1133
- (r = u(this, _).get(e)) == null || r.delete(t);
1098
+ [Symbol.dispose]() {
1099
+ u(this, v) && this.exit(0);
1134
1100
  }
1135
- dispatchEvent(e) {
1136
- const t = u(this, _).get(e.type);
1137
- if (t)
1138
- for (const r of t)
1139
- r(e);
1101
+ }
1102
+ b = new WeakMap(), v = new WeakMap(), x = new WeakMap(), P = new WeakMap(), R = new WeakMap(), C = new WeakSet(), X = function(e, t, s) {
1103
+ const r = {
1104
+ ...e || {}
1105
+ };
1106
+ r.HTTPS = r.HTTPS || s === 443 ? "on" : "off";
1107
+ for (const n in t) {
1108
+ let i = "HTTP_";
1109
+ ["content-type", "content-length"].includes(n.toLowerCase()) && (i = ""), r[`${i}${n.toUpperCase().replace(/-/g, "_")}`] = t[n];
1140
1110
  }
1141
- /** @inheritDoc */
1142
- async onMessage(e) {
1143
- u(this, S).push(e);
1111
+ return r;
1112
+ }, M = new WeakSet(), ee = function() {
1113
+ this[__private__dont__use].ccall("php_wasm_init", null, [], []);
1114
+ }, N = new WeakSet(), te = function() {
1115
+ const e = "/internal/headers.json";
1116
+ if (!this.fileExists(e))
1117
+ throw new Error(
1118
+ "SAPI Error: Could not find response headers file."
1119
+ );
1120
+ const t = JSON.parse(this.readFileAsText(e)), s = {};
1121
+ for (const r of t.headers) {
1122
+ if (!r.includes(": "))
1123
+ continue;
1124
+ const n = r.indexOf(": "), i = r.substring(0, n).toLowerCase(), o = r.substring(n + 2);
1125
+ i in s || (s[i] = []), s[i].push(o);
1144
1126
  }
1145
- /** @inheritDoc */
1146
- async setSpawnHandler(handler) {
1147
- typeof handler == "string" && (handler = createSpawnHandler(eval(handler))), this[__private__dont__use].spawnProcess = handler;
1127
+ return {
1128
+ headers: s,
1129
+ httpStatusCode: t.status
1130
+ };
1131
+ }, O = new WeakSet(), se = function(e) {
1132
+ if (this[__private__dont__use].ccall(
1133
+ "wasm_set_request_uri",
1134
+ null,
1135
+ [STRING],
1136
+ [e]
1137
+ ), e.includes("?")) {
1138
+ const t = e.substring(e.indexOf("?") + 1);
1139
+ this[__private__dont__use].ccall(
1140
+ "wasm_set_query_string",
1141
+ null,
1142
+ [STRING],
1143
+ [t]
1144
+ );
1148
1145
  }
1149
- /** @inheritDoc */
1150
- get absoluteUrl() {
1151
- return this.requestHandler.absoluteUrl;
1146
+ }, L = new WeakSet(), re = function(e) {
1147
+ this[__private__dont__use].ccall(
1148
+ "wasm_set_request_host",
1149
+ null,
1150
+ [STRING],
1151
+ [e]
1152
+ );
1153
+ }, B = new WeakSet(), ne = function(e) {
1154
+ this[__private__dont__use].ccall(
1155
+ "wasm_set_request_port",
1156
+ null,
1157
+ [NUMBER],
1158
+ [e]
1159
+ );
1160
+ }, U = new WeakSet(), ie = function(e, t) {
1161
+ let s;
1162
+ try {
1163
+ s = parseInt(new URL(e).port, 10);
1164
+ } catch {
1152
1165
  }
1153
- /** @inheritDoc */
1154
- get documentRoot() {
1155
- return this.requestHandler.documentRoot;
1166
+ return (!s || isNaN(s) || s === 80) && (s = t === "https" ? 443 : 80), s;
1167
+ }, j = new WeakSet(), oe = function(e) {
1168
+ this[__private__dont__use].ccall(
1169
+ "wasm_set_request_method",
1170
+ null,
1171
+ [STRING],
1172
+ [e]
1173
+ );
1174
+ }, $ = new WeakSet(), ae = function(e) {
1175
+ e.cookie && this[__private__dont__use].ccall(
1176
+ "wasm_set_cookies",
1177
+ null,
1178
+ [STRING],
1179
+ [e.cookie]
1180
+ ), e["content-type"] && this[__private__dont__use].ccall(
1181
+ "wasm_set_content_type",
1182
+ null,
1183
+ [STRING],
1184
+ [e["content-type"]]
1185
+ ), e["content-length"] && this[__private__dont__use].ccall(
1186
+ "wasm_set_content_length",
1187
+ null,
1188
+ [NUMBER],
1189
+ [parseInt(e["content-length"], 10)]
1190
+ );
1191
+ }, D = new WeakSet(), ce = function(e) {
1192
+ let t, s;
1193
+ typeof e == "string" ? (logger.warn(
1194
+ "Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"
1195
+ ), s = this[__private__dont__use].lengthBytesUTF8(e), t = s + 1) : (s = e.byteLength, t = e.byteLength);
1196
+ const r = this[__private__dont__use].malloc(t);
1197
+ if (!r)
1198
+ throw new Error("Could not allocate memory for the request body.");
1199
+ return typeof e == "string" ? this[__private__dont__use].stringToUTF8(
1200
+ e,
1201
+ r,
1202
+ t + 1
1203
+ ) : this[__private__dont__use].HEAPU8.set(e, r), this[__private__dont__use].ccall(
1204
+ "wasm_set_request_body",
1205
+ null,
1206
+ [NUMBER],
1207
+ [r]
1208
+ ), this[__private__dont__use].ccall(
1209
+ "wasm_set_content_length",
1210
+ null,
1211
+ [NUMBER],
1212
+ [s]
1213
+ ), r;
1214
+ }, k = new WeakSet(), Z = function(e) {
1215
+ this[__private__dont__use].ccall(
1216
+ "wasm_set_path_translated",
1217
+ null,
1218
+ [STRING],
1219
+ [e]
1220
+ );
1221
+ }, q = new WeakSet(), le = function(e, t) {
1222
+ this[__private__dont__use].ccall(
1223
+ "wasm_add_SERVER_entry",
1224
+ null,
1225
+ [STRING, STRING],
1226
+ [e, t]
1227
+ );
1228
+ }, z = new WeakSet(), ue = function(e, t) {
1229
+ this[__private__dont__use].ccall(
1230
+ "wasm_add_ENV_entry",
1231
+ null,
1232
+ [STRING, STRING],
1233
+ [e, t]
1234
+ );
1235
+ }, W = new WeakSet(), de = async function() {
1236
+ var n;
1237
+ let e, t;
1238
+ try {
1239
+ e = await new Promise((i, o) => {
1240
+ var l;
1241
+ t = (a) => {
1242
+ logger.error(a), logger.error(a.error);
1243
+ const p = new Error("Rethrown");
1244
+ p.cause = a.error, p.betterMessage = a.message, o(p);
1245
+ }, (l = u(this, x)) == null || l.addEventListener(
1246
+ "error",
1247
+ t
1248
+ );
1249
+ const c = this[__private__dont__use].ccall(
1250
+ "wasm_sapi_handle_request",
1251
+ NUMBER,
1252
+ [],
1253
+ [],
1254
+ { async: !0 }
1255
+ );
1256
+ return c instanceof Promise ? c.then(i, o) : i(c);
1257
+ });
1258
+ } catch (i) {
1259
+ for (const a in this)
1260
+ typeof this[a] == "function" && (this[a] = () => {
1261
+ throw new Error(
1262
+ "PHP runtime has crashed – see the earlier error for details."
1263
+ );
1264
+ });
1265
+ this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
1266
+ const o = i, c = "betterMessage" in o ? o.betterMessage : o.message, l = new Error(c);
1267
+ throw l.cause = o, logger.error(l), l;
1268
+ } finally {
1269
+ (n = u(this, x)) == null || n.removeEventListener("error", t);
1156
1270
  }
1157
- /** @inheritDoc */
1158
- pathToInternalUrl(e) {
1159
- return this.requestHandler.pathToInternalUrl(e);
1271
+ const { headers: s, httpStatusCode: r } = h(this, N, te).call(this);
1272
+ return new PHPResponse(
1273
+ e === 0 ? r : 500,
1274
+ s,
1275
+ this.readFileAsBuffer("/internal/stdout"),
1276
+ this.readFileAsText("/internal/stderr"),
1277
+ e
1278
+ );
1279
+ };
1280
+ __decorateClass([
1281
+ rethrowFileSystemError('Could not create directory "{path}"')
1282
+ ], BasePHP.prototype, "mkdir", 1);
1283
+ __decorateClass([
1284
+ rethrowFileSystemError('Could not create directory "{path}"')
1285
+ ], BasePHP.prototype, "mkdirTree", 1);
1286
+ __decorateClass([
1287
+ rethrowFileSystemError('Could not read "{path}"')
1288
+ ], BasePHP.prototype, "readFileAsText", 1);
1289
+ __decorateClass([
1290
+ rethrowFileSystemError('Could not read "{path}"')
1291
+ ], BasePHP.prototype, "readFileAsBuffer", 1);
1292
+ __decorateClass([
1293
+ rethrowFileSystemError('Could not write to "{path}"')
1294
+ ], BasePHP.prototype, "writeFile", 1);
1295
+ __decorateClass([
1296
+ rethrowFileSystemError('Could not unlink "{path}"')
1297
+ ], BasePHP.prototype, "unlink", 1);
1298
+ __decorateClass([
1299
+ rethrowFileSystemError('Could not remove directory "{path}"')
1300
+ ], BasePHP.prototype, "rmdir", 1);
1301
+ __decorateClass([
1302
+ rethrowFileSystemError('Could not list files in "{path}"')
1303
+ ], BasePHP.prototype, "listFiles", 1);
1304
+ __decorateClass([
1305
+ rethrowFileSystemError('Could not stat "{path}"')
1306
+ ], BasePHP.prototype, "isDir", 1);
1307
+ __decorateClass([
1308
+ rethrowFileSystemError('Could not stat "{path}"')
1309
+ ], BasePHP.prototype, "fileExists", 1);
1310
+ function normalizeHeaders(e) {
1311
+ const t = {};
1312
+ for (const s in e)
1313
+ t[s.toLowerCase()] = e[s];
1314
+ return t;
1315
+ }
1316
+ function copyFS(e, t, s) {
1317
+ let r;
1318
+ try {
1319
+ r = e.lookupPath(s);
1320
+ } catch {
1321
+ return;
1160
1322
  }
1161
- /** @inheritDoc */
1162
- internalUrlToPath(e) {
1163
- return this.requestHandler.internalUrlToPath(e);
1323
+ if (!("contents" in r.node))
1324
+ return;
1325
+ if (!e.isDir(r.node.mode)) {
1326
+ t.writeFile(s, e.readFile(s));
1327
+ return;
1164
1328
  }
1165
- initializeRuntime(e) {
1166
- if (this[__private__dont__use])
1167
- throw new Error("PHP runtime already initialized.");
1168
- const t = getLoadedRuntime(e);
1169
- if (!t)
1170
- throw new Error("Invalid PHP runtime id.");
1171
- this[__private__dont__use] = t, t.onMessage = async (r) => {
1172
- for (const s of u(this, S)) {
1173
- const n = await s(r);
1174
- if (n)
1175
- return n;
1176
- }
1177
- return "";
1178
- }, d(this, P, improveWASMErrorReporting(t)), this.dispatchEvent({
1179
- type: "runtime.initialized"
1329
+ t.mkdirTree(s);
1330
+ const n = e.readdir(s).filter((i) => i !== "." && i !== "..");
1331
+ for (const i of n)
1332
+ copyFS(e, t, joinPaths(s, i));
1333
+ }
1334
+ function copyRecursive(e, t, s) {
1335
+ const r = e.lookupPath(t).node;
1336
+ if (e.isDir(r.mode)) {
1337
+ e.mkdirTree(s);
1338
+ const n = e.readdir(t).filter(
1339
+ (i) => i !== "." && i !== ".."
1340
+ );
1341
+ for (const i of n)
1342
+ copyRecursive(
1343
+ e,
1344
+ joinPaths(t, i),
1345
+ joinPaths(s, i)
1346
+ );
1347
+ } else
1348
+ e.writeFile(s, e.readFile(t));
1349
+ }
1350
+ const { hasOwnProperty } = Object.prototype, encode = (e, t = {}) => {
1351
+ typeof t == "string" && (t = { section: t }), t.align = t.align === !0, t.newline = t.newline === !0, t.sort = t.sort === !0, t.whitespace = t.whitespace === !0 || t.align === !0, t.platform = t.platform || typeof process < "u" && process.platform, t.bracketedArray = t.bracketedArray !== !1;
1352
+ const s = t.platform === "win32" ? `\r
1353
+ ` : `
1354
+ `, r = t.whitespace ? " = " : "=", n = [], i = t.sort ? Object.keys(e).sort() : Object.keys(e);
1355
+ let o = 0;
1356
+ t.align && (o = safe(
1357
+ i.filter((a) => e[a] === null || Array.isArray(e[a]) || typeof e[a] != "object").map((a) => Array.isArray(e[a]) ? `${a}[]` : a).concat([""]).reduce((a, p) => safe(a).length >= safe(p).length ? a : p)
1358
+ ).length);
1359
+ let c = "";
1360
+ const l = t.bracketedArray ? "[]" : "";
1361
+ for (const a of i) {
1362
+ const p = e[a];
1363
+ if (p && Array.isArray(p))
1364
+ for (const m of p)
1365
+ c += safe(`${a}${l}`).padEnd(o, " ") + r + safe(m) + s;
1366
+ else
1367
+ p && typeof p == "object" ? n.push(a) : c += safe(a).padEnd(o, " ") + r + safe(p) + s;
1368
+ }
1369
+ t.section && c.length && (c = "[" + safe(t.section) + "]" + (t.newline ? s + s : s) + c);
1370
+ for (const a of n) {
1371
+ const p = splitSections(a, ".").join("\\."), m = (t.section ? t.section + "." : "") + p, y = encode(e[a], {
1372
+ ...t,
1373
+ section: m
1180
1374
  });
1375
+ c.length && y.length && (c += s), c += y;
1181
1376
  }
1182
- /** @inheritDoc */
1183
- async setSapiName(e) {
1184
- if (this[__private__dont__use].ccall(
1185
- "wasm_set_sapi_name",
1186
- NUMBER,
1187
- [STRING],
1188
- [e]
1189
- ) !== 0)
1190
- throw new Error(
1191
- "Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?"
1192
- );
1193
- d(this, R, e);
1377
+ return c;
1378
+ };
1379
+ function splitSections(e, t) {
1380
+ var s = 0, r = 0, n = 0, i = [];
1381
+ do
1382
+ if (n = e.indexOf(t, s), n !== -1) {
1383
+ if (s = n + t.length, n > 0 && e[n - 1] === "\\")
1384
+ continue;
1385
+ i.push(e.slice(r, n)), r = n + t.length;
1386
+ }
1387
+ while (n !== -1);
1388
+ return i.push(e.slice(r)), i;
1389
+ }
1390
+ const decode = (e, t = {}) => {
1391
+ t.bracketedArray = t.bracketedArray !== !1;
1392
+ const s = /* @__PURE__ */ Object.create(null);
1393
+ let r = s, n = null;
1394
+ const i = /^\[([^\]]*)\]\s*$|^([^=]+)(=(.*))?$/i, o = e.split(/[\r\n]+/g), c = {};
1395
+ for (const a of o) {
1396
+ if (!a || a.match(/^\s*[;#]/) || a.match(/^\s*$/))
1397
+ continue;
1398
+ const p = a.match(i);
1399
+ if (!p)
1400
+ continue;
1401
+ if (p[1] !== void 0) {
1402
+ if (n = unsafe(p[1]), n === "__proto__") {
1403
+ r = /* @__PURE__ */ Object.create(null);
1404
+ continue;
1405
+ }
1406
+ r = s[n] = s[n] || /* @__PURE__ */ Object.create(null);
1407
+ continue;
1408
+ }
1409
+ const m = unsafe(p[2]);
1410
+ let y;
1411
+ t.bracketedArray ? y = m.length > 2 && m.slice(-2) === "[]" : (c[m] = ((c == null ? void 0 : c[m]) || 0) + 1, y = c[m] > 1);
1412
+ const _ = y ? m.slice(0, -2) : m;
1413
+ if (_ === "__proto__")
1414
+ continue;
1415
+ const A = p[3] ? unsafe(p[4]) : !0, K = A === "true" || A === "false" || A === "null" ? JSON.parse(A) : A;
1416
+ y && (hasOwnProperty.call(r, _) ? Array.isArray(r[_]) || (r[_] = [r[_]]) : r[_] = []), Array.isArray(r[_]) ? r[_].push(K) : r[_] = K;
1194
1417
  }
1195
- /** @inheritDoc */
1196
- setPhpIniPath(e) {
1197
- if (u(this, f))
1198
- throw new Error("Cannot set PHP ini path after calling run().");
1199
- d(this, v, e), this[__private__dont__use].ccall(
1200
- "wasm_set_phpini_path",
1201
- null,
1202
- ["string"],
1203
- [e]
1204
- );
1418
+ const l = [];
1419
+ for (const a of Object.keys(s)) {
1420
+ if (!hasOwnProperty.call(s, a) || typeof s[a] != "object" || Array.isArray(s[a]))
1421
+ continue;
1422
+ const p = splitSections(a, ".");
1423
+ r = s;
1424
+ const m = p.pop(), y = m.replace(/\\\./g, ".");
1425
+ for (const _ of p)
1426
+ _ !== "__proto__" && ((!hasOwnProperty.call(r, _) || typeof r[_] != "object") && (r[_] = /* @__PURE__ */ Object.create(null)), r = r[_]);
1427
+ r === s && y === m || (r[y] = s[a], l.push(a));
1428
+ }
1429
+ for (const a of l)
1430
+ delete s[a];
1431
+ return s;
1432
+ }, isQuoted = (e) => e.startsWith('"') && e.endsWith('"') || e.startsWith("'") && e.endsWith("'"), safe = (e) => typeof e != "string" || e.match(/[=\r\n]/) || e.match(/^\[/) || e.length > 1 && isQuoted(e) || e !== e.trim() ? JSON.stringify(e) : e.split(";").join("\\;").split("#").join("\\#"), unsafe = (e) => {
1433
+ if (e = (e || "").trim(), isQuoted(e)) {
1434
+ e.charAt(0) === "'" && (e = e.slice(1, -1));
1435
+ try {
1436
+ e = JSON.parse(e);
1437
+ } catch {
1438
+ }
1439
+ } else {
1440
+ let t = !1, s = "";
1441
+ for (let r = 0, n = e.length; r < n; r++) {
1442
+ const i = e.charAt(r);
1443
+ if (t)
1444
+ "\\;#".indexOf(i) !== -1 ? s += i : s += "\\" + i, t = !1;
1445
+ else {
1446
+ if (";#".indexOf(i) !== -1)
1447
+ break;
1448
+ i === "\\" ? t = !0 : s += i;
1449
+ }
1450
+ }
1451
+ return t && (s += "\\"), s.trim();
1205
1452
  }
1206
- /** @inheritDoc */
1207
- setPhpIniEntry(e, t) {
1208
- if (u(this, f))
1209
- throw new Error("Cannot set PHP ini entries after calling run().");
1210
- u(this, w).push([e, t]);
1453
+ return e;
1454
+ };
1455
+ var ini = {
1456
+ parse: decode,
1457
+ decode,
1458
+ stringify: encode,
1459
+ encode,
1460
+ safe,
1461
+ unsafe
1462
+ };
1463
+ async function getPhpIniEntries(e, t) {
1464
+ const s = ini.parse(await e.readFileAsText(PHP_INI_PATH));
1465
+ if (t === void 0)
1466
+ return s;
1467
+ const r = {};
1468
+ for (const n of t)
1469
+ r[n] = s[n];
1470
+ return r;
1471
+ }
1472
+ async function setPhpIniEntries(e, t) {
1473
+ const s = ini.parse(await e.readFileAsText(PHP_INI_PATH));
1474
+ for (const [r, n] of Object.entries(t))
1475
+ n == null ? delete s[r] : s[r] = n;
1476
+ await e.writeFile(PHP_INI_PATH, ini.stringify(s));
1477
+ }
1478
+ async function withPHPIniValues(e, t, s) {
1479
+ const r = await e.readFileAsText(PHP_INI_PATH);
1480
+ try {
1481
+ return await setPhpIniEntries(e, t), await s();
1482
+ } finally {
1483
+ await e.writeFile(PHP_INI_PATH, r);
1211
1484
  }
1212
- /** @inheritDoc */
1213
- chdir(e) {
1214
- this[__private__dont__use].FS.chdir(e);
1485
+ }
1486
+ class HttpCookieStore {
1487
+ constructor() {
1488
+ this.cookies = {};
1215
1489
  }
1216
- /**
1217
- * Do not use. Use new PHPRequestHandler() instead.
1218
- * @deprecated
1219
- */
1220
- async request(e) {
1221
- if (logger.warn(
1222
- "PHP.request() is deprecated. Please use new PHPRequestHandler() instead."
1223
- ), !this.requestHandler)
1224
- throw new Error("No request handler available.");
1225
- return this.requestHandler.request(e);
1490
+ rememberCookiesFromResponseHeaders(t) {
1491
+ if (t != null && t["set-cookie"])
1492
+ for (const s of t["set-cookie"])
1493
+ try {
1494
+ if (!s.includes("="))
1495
+ continue;
1496
+ const r = s.indexOf("="), n = s.substring(0, r), i = s.substring(r + 1).split(";")[0];
1497
+ this.cookies[n] = i;
1498
+ } catch (r) {
1499
+ logger.error(r);
1500
+ }
1501
+ }
1502
+ getCookieRequestHeader() {
1503
+ const t = [];
1504
+ for (const s in this.cookies)
1505
+ t.push(`${s}=${this.cookies[s]}`);
1506
+ return t.join("; ");
1226
1507
  }
1227
- /** @inheritDoc */
1228
- async run(e) {
1229
- const t = await this.semaphore.acquire();
1230
- let r;
1231
- try {
1232
- if (u(this, f) || (p(this, I, Y).call(this), d(this, f, !0)), e.scriptPath && !this.fileExists(e.scriptPath))
1233
- throw new Error(
1234
- `The script path "${e.scriptPath}" does not exist.`
1235
- );
1236
- p(this, D, oe).call(this, e.scriptPath || ""), p(this, k, X).call(this, e.relativeUri || ""), p(this, N, se).call(this, e.method || "GET");
1237
- const s = normalizeHeaders(e.headers || {}), n = s.host || "example.com:443", i = p(this, L, re).call(this, n, e.protocol || "http");
1238
- p(this, M, ee).call(this, n), p(this, B, te).call(this, i), p(this, U, ne).call(this, s), e.body && (r = p(this, O, ie).call(this, e.body)), typeof e.code == "string" && p(this, j, ce).call(this, " ?>" + e.code);
1239
- const o = p(this, C, Z).call(this, e.$_SERVER, s, i);
1240
- for (const c in o)
1241
- p(this, $, ae).call(this, c, o[c]);
1242
- const a = e.env || {};
1243
- for (const c in a)
1244
- p(this, q, le).call(this, c, a[c]);
1245
- const l = await p(this, z, ue).call(this);
1246
- if (l.exitCode !== 0) {
1247
- logger.warn("PHP.run() output was:", l.text);
1248
- const c = new PHPExecutionFailureError(
1249
- `PHP.run() failed with exit code ${l.exitCode} and the following output: ` + l.errors,
1250
- l,
1251
- "request"
1252
- );
1253
- throw logger.error(c), c;
1508
+ }
1509
+ function concatUint8Array(...e) {
1510
+ const t = new Uint8Array(
1511
+ e.reduce((r, n) => r + n.length, 0)
1512
+ );
1513
+ let s = 0;
1514
+ for (const r of e)
1515
+ t.set(r, s), s += r.length;
1516
+ return t;
1517
+ }
1518
+ function concatBytes(e) {
1519
+ if (e === void 0) {
1520
+ let t = new Uint8Array();
1521
+ return new TransformStream({
1522
+ transform(s) {
1523
+ t = concatUint8Array(t, s);
1524
+ },
1525
+ flush(s) {
1526
+ s.enqueue(t);
1254
1527
  }
1255
- return l;
1256
- } catch (s) {
1257
- throw this.dispatchEvent({
1258
- type: "request.error",
1259
- error: s,
1260
- // Distinguish between PHP request and PHP-wasm errors
1261
- source: s.source ?? "php-wasm"
1262
- }), s;
1263
- } finally {
1264
- try {
1265
- r && this[__private__dont__use].free(r);
1266
- } finally {
1267
- t(), this.dispatchEvent({
1268
- type: "request.end"
1269
- });
1528
+ });
1529
+ } else {
1530
+ const t = new ArrayBuffer(e || 0);
1531
+ let s = 0;
1532
+ return new TransformStream({
1533
+ transform(r) {
1534
+ new Uint8Array(t).set(r, s), s += r.byteLength;
1535
+ },
1536
+ flush(r) {
1537
+ r.enqueue(new Uint8Array(t));
1270
1538
  }
1271
- }
1539
+ });
1272
1540
  }
1273
- defineConstant(e, t) {
1274
- let r = {};
1275
- try {
1276
- r = JSON.parse(
1277
- this.fileExists("/internal/consts.json") && this.readFileAsText("/internal/consts.json") || "{}"
1541
+ }
1542
+ function limitBytes(e, t) {
1543
+ if (t === 0)
1544
+ return new ReadableStream({
1545
+ start(n) {
1546
+ n.close();
1547
+ }
1548
+ });
1549
+ const s = e.getReader({ mode: "byob" });
1550
+ let r = 0;
1551
+ return new ReadableStream({
1552
+ async pull(n) {
1553
+ const { value: i, done: o } = await s.read(
1554
+ new Uint8Array(t - r)
1278
1555
  );
1279
- } catch {
1556
+ if (o) {
1557
+ s.releaseLock(), n.close();
1558
+ return;
1559
+ }
1560
+ r += i.length, n.enqueue(i), r >= t && (s.releaseLock(), n.close());
1561
+ },
1562
+ cancel() {
1563
+ s.cancel();
1280
1564
  }
1281
- this.writeFile(
1282
- "/internal/consts.json",
1283
- JSON.stringify({
1284
- ...r,
1285
- [e]: t
1286
- })
1287
- );
1288
- }
1289
- mkdir(e) {
1290
- this[__private__dont__use].FS.mkdirTree(e);
1291
- }
1292
- mkdirTree(e) {
1293
- this.mkdir(e);
1565
+ });
1566
+ }
1567
+ async function collectBytes(e, t) {
1568
+ return t !== void 0 && (e = limitBytes(e, t)), await e.pipeThrough(concatBytes(t)).getReader().read().then(({ value: s }) => s);
1569
+ }
1570
+ class StreamedFile extends File {
1571
+ /**
1572
+ * Creates a new StreamedFile instance.
1573
+ *
1574
+ * @param readableStream The readable stream containing the file data.
1575
+ * @param name The name of the file.
1576
+ * @param type The MIME type of the file.
1577
+ */
1578
+ constructor(t, s, r) {
1579
+ super([], s, { type: r }), this.readableStream = t;
1294
1580
  }
1295
- readFileAsText(e) {
1296
- return new TextDecoder().decode(this.readFileAsBuffer(e));
1581
+ /**
1582
+ * Overrides the slice() method of the File class.
1583
+ *
1584
+ * @returns A Blob representing a portion of the file.
1585
+ */
1586
+ slice() {
1587
+ throw new Error("slice() is not possible on a StreamedFile");
1297
1588
  }
1298
- readFileAsBuffer(e) {
1299
- return this[__private__dont__use].FS.readFile(e);
1589
+ /**
1590
+ * Returns the readable stream associated with the file.
1591
+ *
1592
+ * @returns The readable stream.
1593
+ */
1594
+ stream() {
1595
+ return this.readableStream;
1300
1596
  }
1301
- writeFile(e, t) {
1302
- this[__private__dont__use].FS.writeFile(e, t);
1597
+ /**
1598
+ * Loads the file data into memory and then returns it as a string.
1599
+ *
1600
+ * @returns File data as text.
1601
+ */
1602
+ async text() {
1603
+ return new TextDecoder().decode(await this.arrayBuffer());
1303
1604
  }
1304
- unlink(e) {
1305
- this[__private__dont__use].FS.unlink(e);
1605
+ /**
1606
+ * Loads the file data into memory and then returns it as an ArrayBuffer.
1607
+ *
1608
+ * @returns File data as an ArrayBuffer.
1609
+ */
1610
+ async arrayBuffer() {
1611
+ return await collectBytes(this.stream());
1306
1612
  }
1307
- /** @inheritDoc */
1308
- mv(e, t) {
1309
- try {
1310
- this[__private__dont__use].FS.rename(e, t);
1311
- } catch (r) {
1312
- const s = getEmscriptenFsError(r);
1313
- throw s ? new Error(
1314
- `Could not move ${e} to ${t}: ${s}`,
1315
- {
1316
- cause: r
1317
- }
1318
- ) : r;
1613
+ }
1614
+ ReadableStream.prototype[Symbol.asyncIterator] || (ReadableStream.prototype[Symbol.asyncIterator] = async function* () {
1615
+ const e = this.getReader();
1616
+ try {
1617
+ for (; ; ) {
1618
+ const { done: t, value: s } = await e.read();
1619
+ if (t)
1620
+ return;
1621
+ yield s;
1319
1622
  }
1623
+ } finally {
1624
+ e.releaseLock();
1320
1625
  }
1321
- rmdir(e, t = { recursive: !0 }) {
1322
- t != null && t.recursive && this.listFiles(e).forEach((r) => {
1323
- const s = `${e}/${r}`;
1324
- this.isDir(s) ? this.rmdir(s, t) : this.unlink(s);
1325
- }), this[__private__dont__use].FS.rmdir(e);
1326
- }
1327
- listFiles(e, t = { prependPath: !1 }) {
1328
- if (!this.fileExists(e))
1329
- return [];
1330
- try {
1331
- const r = this[__private__dont__use].FS.readdir(e).filter(
1332
- (s) => s !== "." && s !== ".."
1626
+ }, ReadableStream.prototype.iterate = // @ts-ignore
1627
+ ReadableStream.prototype[Symbol.asyncIterator]);
1628
+ function streamReadFileFromPHP(e, t) {
1629
+ return new ReadableStream({
1630
+ async pull(s) {
1631
+ const r = await e.readFileAsBuffer(t);
1632
+ s.enqueue(r), s.close();
1633
+ }
1634
+ });
1635
+ }
1636
+ async function* iteratePhpFiles(e, t, {
1637
+ relativePaths: s = !0,
1638
+ pathPrefix: r,
1639
+ exceptPaths: n = []
1640
+ } = {}) {
1641
+ t = normalizePath(t);
1642
+ const i = [t];
1643
+ for (; i.length; ) {
1644
+ const o = i.pop();
1645
+ if (!o)
1646
+ return;
1647
+ const c = await e.listFiles(o);
1648
+ for (const l of c) {
1649
+ const a = `${o}/${l}`;
1650
+ if (n.includes(a.substring(t.length + 1)))
1651
+ continue;
1652
+ await e.isDir(a) ? i.push(a) : yield new StreamedFile(
1653
+ streamReadFileFromPHP(e, a),
1654
+ s ? joinPaths(
1655
+ r || "",
1656
+ a.substring(t.length + 1)
1657
+ ) : a
1333
1658
  );
1334
- if (t.prependPath) {
1335
- const s = e.replace(/\/$/, "");
1336
- return r.map((n) => `${s}/${n}`);
1337
- }
1338
- return r;
1339
- } catch (r) {
1340
- return logger.error(r, { path: e }), [];
1341
1659
  }
1342
1660
  }
1343
- isDir(e) {
1344
- return this.fileExists(e) ? this[__private__dont__use].FS.isDir(
1345
- this[__private__dont__use].FS.lookupPath(e).node.mode
1346
- ) : !1;
1661
+ }
1662
+ function writeFilesStreamToPhp(e, t) {
1663
+ return new WritableStream({
1664
+ async write(s) {
1665
+ const r = joinPaths(t, s.name);
1666
+ s.type === "directory" ? await e.mkdir(r) : (await e.mkdir(dirname(r)), await e.writeFile(
1667
+ r,
1668
+ new Uint8Array(await s.arrayBuffer())
1669
+ ));
1670
+ }
1671
+ });
1672
+ }
1673
+ class MaxPhpInstancesError extends Error {
1674
+ constructor(t) {
1675
+ super(
1676
+ `Requested more concurrent PHP instances than the limit (${t}).`
1677
+ ), this.name = this.constructor.name;
1347
1678
  }
1348
- fileExists(e) {
1349
- try {
1350
- return this[__private__dont__use].FS.lookupPath(e), !0;
1351
- } catch {
1352
- return !1;
1679
+ }
1680
+ class PHPProcessManager {
1681
+ constructor(t) {
1682
+ this.primaryIdle = !0, this.nextInstance = null, this.allInstances = [], this.maxPhpInstances = (t == null ? void 0 : t.maxPhpInstances) ?? 5, this.phpFactory = t == null ? void 0 : t.phpFactory, this.primaryPhp = t == null ? void 0 : t.primaryPhp, this.semaphore = new Semaphore({
1683
+ concurrency: this.maxPhpInstances,
1684
+ /**
1685
+ * Wait up to 5 seconds for resources to become available
1686
+ * before assuming that all the PHP instances are deadlocked.
1687
+ */
1688
+ timeout: (t == null ? void 0 : t.timeout) || 5e3
1689
+ });
1690
+ }
1691
+ /**
1692
+ * Get the primary PHP instance.
1693
+ *
1694
+ * If the primary PHP instance is not set, it will be spawned
1695
+ * using the provided phpFactory.
1696
+ *
1697
+ * @throws {Error} when called twice before the first call is resolved.
1698
+ */
1699
+ async getPrimaryPhp() {
1700
+ if (!this.phpFactory && !this.primaryPhp)
1701
+ throw new Error(
1702
+ "phpFactory or primaryPhp must be set before calling getPrimaryPhp()."
1703
+ );
1704
+ if (!this.primaryPhp) {
1705
+ const t = await this.spawn({ isPrimary: !0 });
1706
+ this.primaryPhp = t.php;
1353
1707
  }
1708
+ return this.primaryPhp;
1354
1709
  }
1355
1710
  /**
1356
- * Hot-swaps the PHP runtime for a new one without
1357
- * interrupting the operations of this PHP instance.
1711
+ * Get a PHP instance.
1358
1712
  *
1359
- * @param runtime
1360
- * @param cwd. Internal, the VFS path to recreate in the new runtime.
1361
- * This arg is temporary and will be removed once BasePHP
1362
- * is fully decoupled from the request handler and
1363
- * accepts a constructor-level cwd argument.
1713
+ * It could be either the primary PHP instance, an idle disposable PHP instance,
1714
+ * or a newly spawned PHP instance depending on the resource availability.
1715
+ *
1716
+ * @throws {MaxPhpInstancesError} when the maximum number of PHP instances is reached
1717
+ * and the waiting timeout is exceeded.
1718
+ */
1719
+ async acquirePHPInstance() {
1720
+ if (this.primaryIdle)
1721
+ return this.primaryIdle = !1, {
1722
+ php: await this.getPrimaryPhp(),
1723
+ reap: () => this.primaryIdle = !0
1724
+ };
1725
+ const t = this.nextInstance || this.spawn({ isPrimary: !1 });
1726
+ return this.semaphore.remaining > 0 ? this.nextInstance = this.spawn({ isPrimary: !1 }) : this.nextInstance = null, await t;
1727
+ }
1728
+ /**
1729
+ * Initiated spawning of a new PHP instance.
1730
+ * This function is synchronous on purpose – it needs to synchronously
1731
+ * add the spawn promise to the allInstances array without waiting
1732
+ * for PHP to spawn.
1733
+ */
1734
+ spawn(t) {
1735
+ if (t.isPrimary && this.allInstances.length > 0)
1736
+ throw new Error(
1737
+ "Requested spawning a primary PHP instance when another primary instance already started spawning."
1738
+ );
1739
+ const s = this.doSpawn(t);
1740
+ this.allInstances.push(s);
1741
+ const r = () => {
1742
+ this.allInstances = this.allInstances.filter(
1743
+ (n) => n !== s
1744
+ );
1745
+ };
1746
+ return s.catch((n) => {
1747
+ throw r(), n;
1748
+ }).then((n) => ({
1749
+ ...n,
1750
+ reap: () => {
1751
+ r(), n.reap();
1752
+ }
1753
+ }));
1754
+ }
1755
+ /**
1756
+ * Actually acquires the lock and spawns a new PHP instance.
1364
1757
  */
1365
- hotSwapPHPRuntime(e, t) {
1366
- const r = this[__private__dont__use].FS;
1758
+ async doSpawn(t) {
1759
+ let s;
1367
1760
  try {
1368
- this.exit();
1369
- } catch {
1761
+ s = await this.semaphore.acquire();
1762
+ } catch (r) {
1763
+ throw r instanceof AcquireTimeoutError ? new MaxPhpInstancesError(this.maxPhpInstances) : r;
1370
1764
  }
1371
- this.initializeRuntime(e), u(this, v) && this.setPhpIniPath(u(this, v)), u(this, R) && this.setSapiName(u(this, R)), t && copyFS(r, this[__private__dont__use].FS, t);
1372
- }
1373
- exit(e = 0) {
1374
- this.dispatchEvent({
1375
- type: "runtime.beforedestroy"
1376
- });
1377
1765
  try {
1378
- this[__private__dont__use]._exit(e);
1379
- } catch {
1766
+ const r = await this.phpFactory(t);
1767
+ return {
1768
+ php: r,
1769
+ reap() {
1770
+ r.exit(), s();
1771
+ }
1772
+ };
1773
+ } catch (r) {
1774
+ throw s(), r;
1380
1775
  }
1381
- d(this, f, !1), d(this, P, null), delete this[__private__dont__use].onMessage, delete this[__private__dont__use];
1382
- }
1383
- [Symbol.dispose]() {
1384
- u(this, f) && this.exit(0);
1385
- }
1386
- }
1387
- w = new WeakMap(), v = new WeakMap(), R = new WeakMap(), f = new WeakMap(), P = new WeakMap(), _ = new WeakMap(), S = new WeakMap(), C = new WeakSet(), Z = function(e, t, r) {
1388
- const s = {
1389
- ...e || {}
1390
- };
1391
- s.HTTPS = s.HTTPS || r === 443 ? "on" : "off";
1392
- for (const n in t) {
1393
- let i = "HTTP_";
1394
- ["content-type", "content-length"].includes(n.toLowerCase()) && (i = ""), s[`${i}${n.toUpperCase().replace(/-/g, "_")}`] = t[n];
1395
- }
1396
- return s;
1397
- }, I = new WeakSet(), Y = function() {
1398
- if (this.setPhpIniEntry("auto_prepend_file", "/internal/consts.php"), this.fileExists("/internal/consts.php") || this.writeFile(
1399
- "/internal/consts.php",
1400
- `<?php
1401
- if(file_exists('/internal/consts.json')) {
1402
- $consts = json_decode(file_get_contents('/internal/consts.json'), true);
1403
- foreach ($consts as $const => $value) {
1404
- if (!defined($const) && is_scalar($value)) {
1405
- define($const, $value);
1406
- }
1407
- }
1408
- }`
1409
- ), u(this, w).length > 0) {
1410
- const e = u(this, w).map(([t, r]) => `${t}=${r}`).join(`
1411
- `) + `
1412
-
1413
- `;
1414
- this[__private__dont__use].ccall(
1415
- "wasm_set_phpini_entries",
1416
- null,
1417
- [STRING],
1418
- [e]
1419
- );
1420
- }
1421
- this[__private__dont__use].ccall("php_wasm_init", null, [], []);
1422
- }, A = new WeakSet(), K = function() {
1423
- const e = "/internal/headers.json";
1424
- if (!this.fileExists(e))
1425
- throw new Error(
1426
- "SAPI Error: Could not find response headers file."
1427
- );
1428
- const t = JSON.parse(this.readFileAsText(e)), r = {};
1429
- for (const s of t.headers) {
1430
- if (!s.includes(": "))
1431
- continue;
1432
- const n = s.indexOf(": "), i = s.substring(0, n).toLowerCase(), o = s.substring(n + 2);
1433
- i in r || (r[i] = []), r[i].push(o);
1434
1776
  }
1435
- return {
1436
- headers: r,
1437
- httpStatusCode: t.status
1438
- };
1439
- }, k = new WeakSet(), X = function(e) {
1440
- if (this[__private__dont__use].ccall(
1441
- "wasm_set_request_uri",
1442
- null,
1443
- [STRING],
1444
- [e]
1445
- ), e.includes("?")) {
1446
- const t = e.substring(e.indexOf("?") + 1);
1447
- this[__private__dont__use].ccall(
1448
- "wasm_set_query_string",
1449
- null,
1450
- [STRING],
1451
- [t]
1777
+ async [Symbol.asyncDispose]() {
1778
+ this.primaryPhp && this.primaryPhp.exit(), await Promise.all(
1779
+ this.allInstances.map(
1780
+ (t) => t.then(({ reap: s }) => s())
1781
+ )
1452
1782
  );
1453
1783
  }
1454
- }, M = new WeakSet(), ee = function(e) {
1455
- this[__private__dont__use].ccall(
1456
- "wasm_set_request_host",
1457
- null,
1458
- [STRING],
1459
- [e]
1460
- );
1461
- }, B = new WeakSet(), te = function(e) {
1462
- this[__private__dont__use].ccall(
1463
- "wasm_set_request_port",
1464
- null,
1465
- [NUMBER],
1466
- [e]
1467
- );
1468
- }, L = new WeakSet(), re = function(e, t) {
1469
- let r;
1470
- try {
1471
- r = parseInt(new URL(e).port, 10);
1472
- } catch {
1473
- }
1474
- return (!r || isNaN(r) || r === 80) && (r = t === "https" ? 443 : 80), r;
1475
- }, N = new WeakSet(), se = function(e) {
1476
- this[__private__dont__use].ccall(
1477
- "wasm_set_request_method",
1478
- null,
1479
- [STRING],
1480
- [e]
1481
- );
1482
- }, U = new WeakSet(), ne = function(e) {
1483
- e.cookie && this[__private__dont__use].ccall(
1484
- "wasm_set_cookies",
1485
- null,
1486
- [STRING],
1487
- [e.cookie]
1488
- ), e["content-type"] && this[__private__dont__use].ccall(
1489
- "wasm_set_content_type",
1490
- null,
1491
- [STRING],
1492
- [e["content-type"]]
1493
- ), e["content-length"] && this[__private__dont__use].ccall(
1494
- "wasm_set_content_length",
1495
- null,
1496
- [NUMBER],
1497
- [parseInt(e["content-length"], 10)]
1498
- );
1499
- }, O = new WeakSet(), ie = function(e) {
1500
- let t, r;
1501
- typeof e == "string" ? (logger.warn(
1502
- "Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"
1503
- ), r = this[__private__dont__use].lengthBytesUTF8(e), t = r + 1) : (r = e.byteLength, t = e.byteLength);
1504
- const s = this[__private__dont__use].malloc(t);
1505
- if (!s)
1506
- throw new Error("Could not allocate memory for the request body.");
1507
- return typeof e == "string" ? this[__private__dont__use].stringToUTF8(
1508
- e,
1509
- s,
1510
- t + 1
1511
- ) : this[__private__dont__use].HEAPU8.set(e, s), this[__private__dont__use].ccall(
1512
- "wasm_set_request_body",
1513
- null,
1514
- [NUMBER],
1515
- [s]
1516
- ), this[__private__dont__use].ccall(
1517
- "wasm_set_content_length",
1518
- null,
1519
- [NUMBER],
1520
- [r]
1521
- ), s;
1522
- }, D = new WeakSet(), oe = function(e) {
1523
- this[__private__dont__use].ccall(
1524
- "wasm_set_path_translated",
1525
- null,
1526
- [STRING],
1527
- [e]
1528
- );
1529
- }, $ = new WeakSet(), ae = function(e, t) {
1530
- this[__private__dont__use].ccall(
1531
- "wasm_add_SERVER_entry",
1532
- null,
1533
- [STRING, STRING],
1534
- [e, t]
1535
- );
1536
- }, q = new WeakSet(), le = function(e, t) {
1537
- this[__private__dont__use].ccall(
1538
- "wasm_add_ENV_entry",
1539
- null,
1540
- [STRING, STRING],
1541
- [e, t]
1542
- );
1543
- }, j = new WeakSet(), ce = function(e) {
1544
- this[__private__dont__use].ccall(
1545
- "wasm_set_php_code",
1546
- null,
1547
- [STRING],
1548
- [e]
1549
- );
1550
- }, z = new WeakSet(), ue = async function() {
1551
- var n;
1552
- let e, t;
1553
- try {
1554
- e = await new Promise((i, o) => {
1555
- var l;
1556
- t = (c) => {
1557
- logger.error(c), logger.error(c.error);
1558
- const g = new Error("Rethrown");
1559
- g.cause = c.error, g.betterMessage = c.message, o(g);
1560
- }, (l = u(this, P)) == null || l.addEventListener(
1561
- "error",
1562
- t
1563
- );
1564
- const a = this[__private__dont__use].ccall(
1565
- "wasm_sapi_handle_request",
1566
- NUMBER,
1567
- [],
1568
- [],
1569
- { async: !0 }
1570
- );
1571
- return a instanceof Promise ? a.then(i, o) : i(a);
1572
- });
1573
- } catch (i) {
1574
- for (const c in this)
1575
- typeof this[c] == "function" && (this[c] = () => {
1576
- throw new Error(
1577
- "PHP runtime has crashed – see the earlier error for details."
1578
- );
1579
- });
1580
- this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
1581
- const o = i, a = "betterMessage" in o ? o.betterMessage : o.message, l = new Error(a);
1582
- throw l.cause = o, logger.error(l), l;
1583
- } finally {
1584
- (n = u(this, P)) == null || n.removeEventListener("error", t);
1585
- }
1586
- const { headers: r, httpStatusCode: s } = p(this, A, K).call(this);
1587
- return new PHPResponse(
1588
- e === 0 ? s : 500,
1589
- r,
1590
- this.readFileAsBuffer("/internal/stdout"),
1591
- this.readFileAsText("/internal/stderr"),
1592
- e
1593
- );
1594
- };
1595
- __decorateClass([
1596
- rethrowFileSystemError('Could not create directory "{path}"')
1597
- ], BasePHP.prototype, "mkdir", 1);
1598
- __decorateClass([
1599
- rethrowFileSystemError('Could not create directory "{path}"')
1600
- ], BasePHP.prototype, "mkdirTree", 1);
1601
- __decorateClass([
1602
- rethrowFileSystemError('Could not read "{path}"')
1603
- ], BasePHP.prototype, "readFileAsText", 1);
1604
- __decorateClass([
1605
- rethrowFileSystemError('Could not read "{path}"')
1606
- ], BasePHP.prototype, "readFileAsBuffer", 1);
1607
- __decorateClass([
1608
- rethrowFileSystemError('Could not write to "{path}"')
1609
- ], BasePHP.prototype, "writeFile", 1);
1610
- __decorateClass([
1611
- rethrowFileSystemError('Could not unlink "{path}"')
1612
- ], BasePHP.prototype, "unlink", 1);
1613
- __decorateClass([
1614
- rethrowFileSystemError('Could not remove directory "{path}"')
1615
- ], BasePHP.prototype, "rmdir", 1);
1616
- __decorateClass([
1617
- rethrowFileSystemError('Could not list files in "{path}"')
1618
- ], BasePHP.prototype, "listFiles", 1);
1619
- __decorateClass([
1620
- rethrowFileSystemError('Could not stat "{path}"')
1621
- ], BasePHP.prototype, "isDir", 1);
1622
- __decorateClass([
1623
- rethrowFileSystemError('Could not stat "{path}"')
1624
- ], BasePHP.prototype, "fileExists", 1);
1625
- function normalizeHeaders(e) {
1626
- const t = {};
1627
- for (const r in e)
1628
- t[r.toLowerCase()] = e[r];
1629
- return t;
1630
- }
1631
- function copyFS(e, t, r) {
1632
- let s;
1633
- try {
1634
- s = e.lookupPath(r);
1635
- } catch {
1636
- return;
1637
- }
1638
- if (!("contents" in s.node))
1639
- return;
1640
- if (!e.isDir(s.node.mode)) {
1641
- t.writeFile(r, e.readFile(r));
1642
- return;
1643
- }
1644
- t.mkdirTree(r);
1645
- const n = e.readdir(r).filter((i) => i !== "." && i !== "..");
1646
- for (const i of n)
1647
- copyFS(e, t, joinPaths(r, i));
1648
1784
  }
1785
+ const SupportedPHPVersions = [
1786
+ "8.3",
1787
+ "8.2",
1788
+ "8.1",
1789
+ "8.0",
1790
+ "7.4",
1791
+ "7.3",
1792
+ "7.2",
1793
+ "7.1",
1794
+ "7.0"
1795
+ ], LatestSupportedPHPVersion = SupportedPHPVersions[0], SupportedPHPVersionsList = SupportedPHPVersions, SupportedPHPExtensionsList = [
1796
+ "iconv",
1797
+ "mbstring",
1798
+ "xml-bundle",
1799
+ "gd"
1800
+ ], SupportedPHPExtensionBundles = {
1801
+ "kitchen-sink": SupportedPHPExtensionsList,
1802
+ light: []
1803
+ };
1649
1804
  function isLocalPHP(e) {
1650
1805
  return !(e instanceof BasePHP);
1651
1806
  }
@@ -1663,34 +1818,130 @@ function ensurePathPrefix(e, t) {
1663
1818
  return !t || e.startsWith(t) ? e : t + e;
1664
1819
  }
1665
1820
  async function encodeAsMultipart(e) {
1666
- const t = `----${Math.random().toString(36).slice(2)}`, r = `multipart/form-data; boundary=${t}`, s = new TextEncoder(), n = [];
1667
- for (const [l, c] of Object.entries(e))
1821
+ const t = `----${Math.random().toString(36).slice(2)}`, s = `multipart/form-data; boundary=${t}`, r = new TextEncoder(), n = [];
1822
+ for (const [l, a] of Object.entries(e))
1668
1823
  n.push(`--${t}\r
1669
- `), n.push(`Content-Disposition: form-data; name="${l}"`), c instanceof File && n.push(`; filename="${c.name}"`), n.push(`\r
1670
- `), c instanceof File && (n.push("Content-Type: application/octet-stream"), n.push(`\r
1824
+ `), n.push(`Content-Disposition: form-data; name="${l}"`), a instanceof File && n.push(`; filename="${a.name}"`), n.push(`\r
1825
+ `), a instanceof File && (n.push("Content-Type: application/octet-stream"), n.push(`\r
1671
1826
  `)), n.push(`\r
1672
- `), c instanceof File ? n.push(await fileToUint8Array(c)) : n.push(c), n.push(`\r
1827
+ `), a instanceof File ? n.push(await fileToUint8Array(a)) : n.push(a), n.push(`\r
1673
1828
  `);
1674
1829
  n.push(`--${t}--\r
1675
1830
  `);
1676
- const i = n.reduce((l, c) => l + c.length, 0), o = new Uint8Array(i);
1677
- let a = 0;
1831
+ const i = n.reduce((l, a) => l + a.length, 0), o = new Uint8Array(i);
1832
+ let c = 0;
1678
1833
  for (const l of n)
1679
1834
  o.set(
1680
- typeof l == "string" ? s.encode(l) : l,
1681
- a
1682
- ), a += l.length;
1683
- return { bytes: o, contentType: r };
1835
+ typeof l == "string" ? r.encode(l) : l,
1836
+ c
1837
+ ), c += l.length;
1838
+ return { bytes: o, contentType: s };
1684
1839
  }
1685
1840
  function fileToUint8Array(e) {
1686
1841
  return new Promise((t) => {
1687
- const r = new FileReader();
1688
- r.onload = () => {
1689
- t(new Uint8Array(r.result));
1690
- }, r.readAsArrayBuffer(e);
1842
+ const s = new FileReader();
1843
+ s.onload = () => {
1844
+ t(new Uint8Array(s.result));
1845
+ }, s.readAsArrayBuffer(e);
1691
1846
  });
1692
1847
  }
1693
- var y, b, T, E, x, m, F, H, W, he, G, de, J, pe, V, fe;
1848
+ const _default = "application/octet-stream", asx = "video/x-ms-asf", atom = "application/atom+xml", avi = "video/x-msvideo", avif = "image/avif", bin = "application/octet-stream", bmp = "image/x-ms-bmp", cco = "application/x-cocoa", css = "text/css", data = "application/octet-stream", deb = "application/octet-stream", der = "application/x-x509-ca-cert", dmg = "application/octet-stream", doc = "application/msword", docx = "application/vnd.openxmlformats-officedocument.wordprocessingml.document", eot = "application/vnd.ms-fontobject", flv = "video/x-flv", gif = "image/gif", gz = "application/gzip", hqx = "application/mac-binhex40", htc = "text/x-component", html = "text/html", ico = "image/x-icon", iso = "application/octet-stream", jad = "text/vnd.sun.j2me.app-descriptor", jar = "application/java-archive", jardiff = "application/x-java-archive-diff", jng = "image/x-jng", jnlp = "application/x-java-jnlp-file", jpg = "image/jpeg", jpeg = "image/jpeg", js = "application/javascript", json = "application/json", kml = "application/vnd.google-earth.kml+xml", kmz = "application/vnd.google-earth.kmz", m3u8 = "application/vnd.apple.mpegurl", m4a = "audio/x-m4a", m4v = "video/x-m4v", md = "text/plain", mid = "audio/midi", mml = "text/mathml", mng = "video/x-mng", mov = "video/quicktime", mp3 = "audio/mpeg", mp4 = "video/mp4", mpeg = "video/mpeg", msi = "application/octet-stream", odg = "application/vnd.oasis.opendocument.graphics", odp = "application/vnd.oasis.opendocument.presentation", ods = "application/vnd.oasis.opendocument.spreadsheet", odt = "application/vnd.oasis.opendocument.text", ogg = "audio/ogg", otf = "font/otf", pdf = "application/pdf", pl = "application/x-perl", png = "image/png", ppt = "application/vnd.ms-powerpoint", pptx = "application/vnd.openxmlformats-officedocument.presentationml.presentation", prc = "application/x-pilot", ps = "application/postscript", ra = "audio/x-realaudio", rar = "application/x-rar-compressed", rpm = "application/x-redhat-package-manager", rss = "application/rss+xml", rtf = "application/rtf", run = "application/x-makeself", sea = "application/x-sea", sit = "application/x-stuffit", svg = "image/svg+xml", swf = "application/x-shockwave-flash", tcl = "application/x-tcl", tar = "application/x-tar", tif = "image/tiff", ts = "video/mp2t", ttf = "font/ttf", txt = "text/plain", wasm = "application/wasm", wbmp = "image/vnd.wap.wbmp", webm = "video/webm", webp = "image/webp", wml = "text/vnd.wap.wml", wmlc = "application/vnd.wap.wmlc", wmv = "video/x-ms-wmv", woff = "font/woff", woff2 = "font/woff2", xhtml = "application/xhtml+xml", xls = "application/vnd.ms-excel", xlsx = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", xml = "text/xml", xpi = "application/x-xpinstall", xspf = "application/xspf+xml", zip = "application/zip", mimeTypes = {
1849
+ _default,
1850
+ "3gpp": "video/3gpp",
1851
+ "7z": "application/x-7z-compressed",
1852
+ asx,
1853
+ atom,
1854
+ avi,
1855
+ avif,
1856
+ bin,
1857
+ bmp,
1858
+ cco,
1859
+ css,
1860
+ data,
1861
+ deb,
1862
+ der,
1863
+ dmg,
1864
+ doc,
1865
+ docx,
1866
+ eot,
1867
+ flv,
1868
+ gif,
1869
+ gz,
1870
+ hqx,
1871
+ htc,
1872
+ html,
1873
+ ico,
1874
+ iso,
1875
+ jad,
1876
+ jar,
1877
+ jardiff,
1878
+ jng,
1879
+ jnlp,
1880
+ jpg,
1881
+ jpeg,
1882
+ js,
1883
+ json,
1884
+ kml,
1885
+ kmz,
1886
+ m3u8,
1887
+ m4a,
1888
+ m4v,
1889
+ md,
1890
+ mid,
1891
+ mml,
1892
+ mng,
1893
+ mov,
1894
+ mp3,
1895
+ mp4,
1896
+ mpeg,
1897
+ msi,
1898
+ odg,
1899
+ odp,
1900
+ ods,
1901
+ odt,
1902
+ ogg,
1903
+ otf,
1904
+ pdf,
1905
+ pl,
1906
+ png,
1907
+ ppt,
1908
+ pptx,
1909
+ prc,
1910
+ ps,
1911
+ ra,
1912
+ rar,
1913
+ rpm,
1914
+ rss,
1915
+ rtf,
1916
+ run,
1917
+ sea,
1918
+ sit,
1919
+ svg,
1920
+ swf,
1921
+ tcl,
1922
+ tar,
1923
+ tif,
1924
+ ts,
1925
+ ttf,
1926
+ txt,
1927
+ wasm,
1928
+ wbmp,
1929
+ webm,
1930
+ webp,
1931
+ wml,
1932
+ wmlc,
1933
+ wmv,
1934
+ woff,
1935
+ woff2,
1936
+ xhtml,
1937
+ xls,
1938
+ xlsx,
1939
+ xml,
1940
+ xpi,
1941
+ xspf,
1942
+ zip
1943
+ };
1944
+ var g, S, I, E, F, w, H, T, G, pe, V, he, J, fe, Q, me;
1694
1945
  class PHPRequestHandler {
1695
1946
  /**
1696
1947
  * The request handler needs to decide whether to serve a static asset or
@@ -1710,11 +1961,11 @@ class PHPRequestHandler {
1710
1961
  * @param fsPath - Absolute path of the static file to serve.
1711
1962
  * @returns The response.
1712
1963
  */
1713
- h(this, W);
1964
+ d(this, G);
1714
1965
  /**
1715
1966
  * Spawns a new PHP instance and dispatches a request to it.
1716
1967
  */
1717
- h(this, G);
1968
+ d(this, V);
1718
1969
  /**
1719
1970
  * Runs the requested PHP file with all the request and $_SERVER
1720
1971
  * superglobals populated.
@@ -1722,7 +1973,7 @@ class PHPRequestHandler {
1722
1973
  * @param request - The request.
1723
1974
  * @returns The response.
1724
1975
  */
1725
- h(this, J);
1976
+ d(this, J);
1726
1977
  /**
1727
1978
  * Resolve the requested path to the filesystem path of the requested PHP file.
1728
1979
  *
@@ -1732,40 +1983,40 @@ class PHPRequestHandler {
1732
1983
  * @throws {Error} If the requested path doesn't exist.
1733
1984
  * @returns The resolved filesystem path.
1734
1985
  */
1735
- h(this, V);
1736
- h(this, y, void 0);
1737
- h(this, b, void 0);
1738
- h(this, T, void 0);
1739
- h(this, E, void 0);
1740
- h(this, x, void 0);
1741
- h(this, m, void 0);
1742
- h(this, F, void 0);
1743
- h(this, H, void 0);
1986
+ d(this, Q);
1987
+ d(this, g, void 0);
1988
+ d(this, S, void 0);
1989
+ d(this, I, void 0);
1990
+ d(this, E, void 0);
1991
+ d(this, F, void 0);
1992
+ d(this, w, void 0);
1993
+ d(this, H, void 0);
1994
+ d(this, T, void 0);
1744
1995
  const {
1745
- documentRoot: r = "/www/",
1746
- absoluteUrl: s = typeof location == "object" ? location == null ? void 0 : location.href : "",
1996
+ documentRoot: s = "/www/",
1997
+ absoluteUrl: r = typeof location == "object" ? location == null ? void 0 : location.href : "",
1747
1998
  rewriteRules: n = []
1748
1999
  } = t;
1749
2000
  "processManager" in t ? this.processManager = t.processManager : this.processManager = new PHPProcessManager({
1750
- phpFactory: async (a) => {
2001
+ phpFactory: async (c) => {
1751
2002
  const l = await t.phpFactory({
1752
- ...a,
2003
+ ...c,
1753
2004
  requestHandler: this
1754
2005
  });
1755
2006
  return l.requestHandler = this, l;
1756
2007
  },
1757
2008
  maxPhpInstances: t.maxPhpInstances
1758
- }), d(this, H, new HttpCookieStore()), d(this, y, r);
1759
- const i = new URL(s);
1760
- d(this, T, i.hostname), d(this, E, i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80), d(this, b, (i.protocol || "").replace(":", ""));
2009
+ }), f(this, T, new HttpCookieStore()), f(this, g, s);
2010
+ const i = new URL(r);
2011
+ f(this, I, i.hostname), f(this, E, i.port ? Number(i.port) : i.protocol === "https:" ? 443 : 80), f(this, S, (i.protocol || "").replace(":", ""));
1761
2012
  const o = u(this, E) !== 443 && u(this, E) !== 80;
1762
- d(this, x, [
1763
- u(this, T),
2013
+ f(this, F, [
2014
+ u(this, I),
1764
2015
  o ? `:${u(this, E)}` : ""
1765
- ].join("")), d(this, m, i.pathname.replace(/\/+$/, "")), d(this, F, [
1766
- `${u(this, b)}://`,
1767
- u(this, x),
1768
- u(this, m)
2016
+ ].join("")), f(this, w, i.pathname.replace(/\/+$/, "")), f(this, H, [
2017
+ `${u(this, S)}://`,
2018
+ u(this, F),
2019
+ u(this, w)
1769
2020
  ].join("")), this.rewriteRules = n;
1770
2021
  }
1771
2022
  async getPrimaryPhp() {
@@ -1789,21 +2040,21 @@ class PHPRequestHandler {
1789
2040
  * @returns The relative path.
1790
2041
  */
1791
2042
  internalUrlToPath(t) {
1792
- const r = new URL(t);
1793
- return r.pathname.startsWith(u(this, m)) && (r.pathname = r.pathname.slice(u(this, m).length)), toRelativeUrl(r);
2043
+ const s = new URL(t);
2044
+ return s.pathname.startsWith(u(this, w)) && (s.pathname = s.pathname.slice(u(this, w).length)), toRelativeUrl(s);
1794
2045
  }
1795
2046
  /**
1796
2047
  * The absolute URL of this PHPRequestHandler instance.
1797
2048
  */
1798
2049
  get absoluteUrl() {
1799
- return u(this, F);
2050
+ return u(this, H);
1800
2051
  }
1801
2052
  /**
1802
2053
  * The directory in the PHP filesystem where the server will look
1803
2054
  * for the files to serve. Default: `/var/www`.
1804
2055
  */
1805
2056
  get documentRoot() {
1806
- return u(this, y);
2057
+ return u(this, g);
1807
2058
  }
1808
2059
  /**
1809
2060
  * Serves the request – either by serving a static file, or by
@@ -1854,22 +2105,22 @@ class PHPRequestHandler {
1854
2105
  * @param request - PHP Request data.
1855
2106
  */
1856
2107
  async request(t) {
1857
- const r = t.url.startsWith("http://") || t.url.startsWith("https://"), s = new URL(
2108
+ const s = t.url.startsWith("http://") || t.url.startsWith("https://"), r = new URL(
1858
2109
  // Remove the hash part of the URL as it's not meant for the server.
1859
2110
  t.url.split("#")[0],
1860
- r ? void 0 : DEFAULT_BASE_URL
2111
+ s ? void 0 : DEFAULT_BASE_URL
1861
2112
  ), n = applyRewriteRules(
1862
2113
  removePathPrefix(
1863
- decodeURIComponent(s.pathname),
1864
- u(this, m)
2114
+ decodeURIComponent(r.pathname),
2115
+ u(this, w)
1865
2116
  ),
1866
2117
  this.rewriteRules
1867
- ), i = joinPaths(u(this, y), n);
1868
- return seemsLikeAPHPRequestHandlerPath(i) ? p(this, G, de).call(this, t, s) : p(this, W, he).call(this, await this.processManager.getPrimaryPhp(), i);
2118
+ ), i = joinPaths(u(this, g), n);
2119
+ return seemsLikeAPHPRequestHandlerPath(i) ? h(this, V, he).call(this, t, r) : h(this, G, pe).call(this, await this.processManager.getPrimaryPhp(), i);
1869
2120
  }
1870
2121
  }
1871
- y = new WeakMap(), b = new WeakMap(), T = new WeakMap(), E = new WeakMap(), x = new WeakMap(), m = new WeakMap(), F = new WeakMap(), H = new WeakMap(), W = new WeakSet(), he = function(t, r) {
1872
- if (!t.fileExists(r))
2122
+ g = new WeakMap(), S = new WeakMap(), I = new WeakMap(), E = new WeakMap(), F = new WeakMap(), w = new WeakMap(), H = new WeakMap(), T = new WeakMap(), G = new WeakSet(), pe = function(t, s) {
2123
+ if (!t.fileExists(s))
1873
2124
  return new PHPResponse(
1874
2125
  404,
1875
2126
  // Let the service worker know that no static file was found
@@ -1879,156 +2130,88 @@ y = new WeakMap(), b = new WeakMap(), T = new WeakMap(), E = new WeakMap(), x =
1879
2130
  },
1880
2131
  new TextEncoder().encode("404 File not found")
1881
2132
  );
1882
- const s = t.readFileAsBuffer(r);
2133
+ const r = t.readFileAsBuffer(s);
1883
2134
  return new PHPResponse(
1884
2135
  200,
1885
2136
  {
1886
- "content-length": [`${s.byteLength}`],
2137
+ "content-length": [`${r.byteLength}`],
1887
2138
  // @TODO: Infer the content-type from the arrayBuffer instead of the file path.
1888
2139
  // The code below won't return the correct mime-type if the extension
1889
2140
  // was tampered with.
1890
- "content-type": [inferMimeType(r)],
2141
+ "content-type": [inferMimeType(s)],
1891
2142
  "accept-ranges": ["bytes"],
1892
2143
  "cache-control": ["public, max-age=0"]
1893
2144
  },
1894
- s
2145
+ r
1895
2146
  );
1896
- }, G = new WeakSet(), de = async function(t, r) {
1897
- let s;
2147
+ }, V = new WeakSet(), he = async function(t, s) {
2148
+ let r;
1898
2149
  try {
1899
- s = await this.processManager.acquirePHPInstance();
2150
+ r = await this.processManager.acquirePHPInstance();
1900
2151
  } catch (n) {
1901
2152
  return n instanceof MaxPhpInstancesError ? PHPResponse.forHttpCode(502) : PHPResponse.forHttpCode(500);
1902
2153
  }
1903
2154
  try {
1904
- return await p(this, J, pe).call(this, s.php, t, r);
2155
+ return await h(this, J, fe).call(this, r.php, t, s);
1905
2156
  } finally {
1906
- s.reap();
2157
+ r.reap();
1907
2158
  }
1908
- }, J = new WeakSet(), pe = async function(t, r, s) {
2159
+ }, J = new WeakSet(), fe = async function(t, s, r) {
1909
2160
  let n = "GET";
1910
2161
  const i = {
1911
- host: u(this, x),
1912
- ...normalizeHeaders(r.headers || {}),
1913
- cookie: u(this, H).getCookieRequestHeader()
2162
+ host: u(this, F),
2163
+ ...normalizeHeaders(s.headers || {}),
2164
+ cookie: u(this, T).getCookieRequestHeader()
1914
2165
  };
1915
- let o = r.body;
2166
+ let o = s.body;
1916
2167
  if (typeof o == "object" && !(o instanceof Uint8Array)) {
1917
2168
  n = "POST";
1918
- const { bytes: l, contentType: c } = await encodeAsMultipart(o);
1919
- o = l, i["content-type"] = c;
2169
+ const { bytes: l, contentType: a } = await encodeAsMultipart(o);
2170
+ o = l, i["content-type"] = a;
1920
2171
  }
1921
- let a;
2172
+ let c;
1922
2173
  try {
1923
- a = p(this, V, fe).call(this, t, decodeURIComponent(s.pathname));
2174
+ c = h(this, Q, me).call(this, t, decodeURIComponent(r.pathname));
1924
2175
  } catch {
1925
2176
  return PHPResponse.forHttpCode(404);
1926
2177
  }
1927
2178
  try {
1928
2179
  const l = await t.run({
1929
2180
  relativeUri: ensurePathPrefix(
1930
- toRelativeUrl(s),
1931
- u(this, m)
2181
+ toRelativeUrl(r),
2182
+ u(this, w)
1932
2183
  ),
1933
- protocol: u(this, b),
1934
- method: r.method || n,
2184
+ protocol: u(this, S),
2185
+ method: s.method || n,
1935
2186
  $_SERVER: {
1936
2187
  REMOTE_ADDR: "127.0.0.1",
1937
- DOCUMENT_ROOT: u(this, y),
1938
- HTTPS: u(this, F).startsWith("https://") ? "on" : ""
2188
+ DOCUMENT_ROOT: u(this, g),
2189
+ HTTPS: u(this, H).startsWith("https://") ? "on" : ""
1939
2190
  },
1940
2191
  body: o,
1941
- scriptPath: a,
2192
+ scriptPath: c,
1942
2193
  headers: i
1943
2194
  });
1944
- return u(this, H).rememberCookiesFromResponseHeaders(
2195
+ return u(this, T).rememberCookiesFromResponseHeaders(
1945
2196
  l.headers
1946
2197
  ), l;
1947
2198
  } catch (l) {
1948
- const c = l;
1949
- if (c != null && c.response)
1950
- return c.response;
2199
+ const a = l;
2200
+ if (a != null && a.response)
2201
+ return a.response;
1951
2202
  throw l;
1952
2203
  }
1953
- }, V = new WeakSet(), fe = function(t, r) {
1954
- let s = removePathPrefix(r, u(this, m));
1955
- s = applyRewriteRules(s, this.rewriteRules), s.includes(".php") ? s = s.split(".php")[0] + ".php" : t.isDir(`${u(this, y)}${s}`) ? (s.endsWith("/") || (s = `${s}/`), s = `${s}index.php`) : s = "/index.php";
1956
- const n = `${u(this, y)}${s}`;
1957
- if (t.fileExists(n))
2204
+ }, Q = new WeakSet(), me = function(t, s) {
2205
+ let r = removePathPrefix(s, u(this, w));
2206
+ r = applyRewriteRules(r, this.rewriteRules), r.includes(".php") ? r = r.split(".php")[0] + ".php" : t.isDir(`${u(this, g)}${r}`) ? (r.endsWith("/") || (r = `${r}/`), r = `${r}index.php`) : r = "/index.php";
2207
+ let n = `${u(this, g)}${r}`;
2208
+ if (t.fileExists(n) || (n = `${u(this, g)}/index.php`), t.fileExists(n))
1958
2209
  return n;
1959
2210
  throw new Error(`File not found: ${n}`);
1960
2211
  };
1961
2212
  function inferMimeType(e) {
1962
- switch (e.split(".").pop()) {
1963
- case "css":
1964
- return "text/css";
1965
- case "js":
1966
- return "application/javascript";
1967
- case "png":
1968
- return "image/png";
1969
- case "jpg":
1970
- case "jpeg":
1971
- return "image/jpeg";
1972
- case "gif":
1973
- return "image/gif";
1974
- case "svg":
1975
- return "image/svg+xml";
1976
- case "woff":
1977
- return "font/woff";
1978
- case "woff2":
1979
- return "font/woff2";
1980
- case "ttf":
1981
- return "font/ttf";
1982
- case "otf":
1983
- return "font/otf";
1984
- case "eot":
1985
- return "font/eot";
1986
- case "ico":
1987
- return "image/x-icon";
1988
- case "html":
1989
- return "text/html";
1990
- case "json":
1991
- return "application/json";
1992
- case "xml":
1993
- return "application/xml";
1994
- case "txt":
1995
- case "md":
1996
- return "text/plain";
1997
- case "pdf":
1998
- return "application/pdf";
1999
- case "webp":
2000
- return "image/webp";
2001
- case "mp3":
2002
- return "audio/mpeg";
2003
- case "mp4":
2004
- return "video/mp4";
2005
- case "csv":
2006
- return "text/csv";
2007
- case "xls":
2008
- return "application/vnd.ms-excel";
2009
- case "xlsx":
2010
- return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
2011
- case "doc":
2012
- return "application/msword";
2013
- case "docx":
2014
- return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
2015
- case "ppt":
2016
- return "application/vnd.ms-powerpoint";
2017
- case "pptx":
2018
- return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
2019
- case "zip":
2020
- return "application/zip";
2021
- case "rar":
2022
- return "application/x-rar-compressed";
2023
- case "tar":
2024
- return "application/x-tar";
2025
- case "gz":
2026
- return "application/gzip";
2027
- case "7z":
2028
- return "application/x-7z-compressed";
2029
- default:
2030
- return "application-octet-stream";
2031
- }
2213
+ const t = e.split(".").pop();
2214
+ return mimeTypes[t] || mimeTypes._default;
2032
2215
  }
2033
2216
  function seemsLikeAPHPRequestHandlerPath(e) {
2034
2217
  return seemsLikeAPHPFile(e) || seemsLikeADirectoryRoot(e);
@@ -2040,15 +2223,15 @@ function seemsLikeADirectoryRoot(e) {
2040
2223
  return !e.split("/").pop().includes(".");
2041
2224
  }
2042
2225
  function applyRewriteRules(e, t) {
2043
- for (const r of t)
2044
- if (new RegExp(r.match).test(e))
2045
- return e.replace(r.match, r.replacement);
2226
+ for (const s of t)
2227
+ if (new RegExp(s.match).test(e))
2228
+ return e.replace(s.match, s.replacement);
2046
2229
  return e;
2047
2230
  }
2048
2231
  function rotatePHPRuntime({
2049
2232
  php: e,
2050
2233
  cwd: t,
2051
- recreateRuntime: r,
2234
+ recreateRuntime: s,
2052
2235
  /*
2053
2236
  * 400 is an arbitrary number that should trigger a rotation
2054
2237
  * way before the memory gets too fragmented. If it doesn't,
@@ -2057,16 +2240,16 @@ function rotatePHPRuntime({
2057
2240
  * fragmentation.
2058
2241
  * * Resetting HEAP to its initial value.
2059
2242
  */
2060
- maxRequests: s = 400
2243
+ maxRequests: r = 400
2061
2244
  }) {
2062
2245
  let n = 0;
2063
2246
  async function i() {
2064
- if (++n < s)
2247
+ if (++n < r)
2065
2248
  return;
2066
2249
  n = 0;
2067
2250
  const o = await e.semaphore.acquire();
2068
2251
  try {
2069
- e.hotSwapPHPRuntime(await r(), t);
2252
+ e.hotSwapPHPRuntime(await s(), t);
2070
2253
  } finally {
2071
2254
  o();
2072
2255
  }
@@ -2075,13 +2258,27 @@ function rotatePHPRuntime({
2075
2258
  e.removeEventListener("request.end", i);
2076
2259
  };
2077
2260
  }
2078
- async function writeFiles(e, t, r, { rmRoot: s = !1 } = {}) {
2079
- s && await e.isDir(t) && await e.rmdir(t, { recursive: !0 });
2080
- for (const [n, i] of Object.entries(r)) {
2261
+ async function writeFiles(e, t, s, { rmRoot: r = !1 } = {}) {
2262
+ r && await e.isDir(t) && await e.rmdir(t, { recursive: !0 });
2263
+ for (const [n, i] of Object.entries(s)) {
2081
2264
  const o = joinPaths(t, n);
2082
2265
  await e.fileExists(dirname(o)) || await e.mkdir(dirname(o)), await e.writeFile(o, i);
2083
2266
  }
2084
2267
  }
2268
+ function proxyFileSystem(e, t, s) {
2269
+ const r = Object.getOwnPropertySymbols(e)[0];
2270
+ for (const n of s)
2271
+ t.fileExists(n) || t.mkdir(n), e.fileExists(n) || e.mkdir(n), t[r].FS.mount(
2272
+ // @ts-ignore
2273
+ t[r].PROXYFS,
2274
+ {
2275
+ root: n,
2276
+ // @ts-ignore
2277
+ fs: e[r].FS
2278
+ },
2279
+ n
2280
+ );
2281
+ }
2085
2282
  export {
2086
2283
  BasePHP,
2087
2284
  DEFAULT_BASE_URL,
@@ -2098,15 +2295,19 @@ export {
2098
2295
  __private__dont__use,
2099
2296
  applyRewriteRules,
2100
2297
  ensurePathPrefix,
2298
+ getPhpIniEntries,
2101
2299
  isExitCodeZero,
2102
2300
  isLocalPHP,
2103
2301
  isRemotePHP,
2104
2302
  iteratePhpFiles as iterateFiles,
2105
2303
  loadPHPRuntime,
2304
+ proxyFileSystem,
2106
2305
  removePathPrefix,
2107
2306
  rethrowFileSystemError,
2108
2307
  rotatePHPRuntime,
2308
+ setPhpIniEntries,
2109
2309
  toRelativeUrl,
2310
+ withPHPIniValues,
2110
2311
  writeFiles,
2111
2312
  writeFilesStreamToPhp
2112
2313
  };