@php-wasm/universal 3.1.0 → 3.1.2

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,8 +1,8 @@
1
- var q = (r) => {
1
+ var G = (r) => {
2
2
  throw TypeError(r);
3
3
  };
4
- var B = (r, e, t) => e.has(r) || q("Cannot " + t);
5
- var u = (r, e, t) => (B(r, e, "read from private field"), t ? t.call(r) : e.get(r)), y = (r, e, t) => e.has(r) ? q("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(r) : e.set(r, t), g = (r, e, t, s) => (B(r, e, "write to private field"), s ? s.call(r, t) : e.set(r, t), t), m = (r, e, t) => (B(r, e, "access private method"), t);
4
+ var W = (r, e, t) => e.has(r) || G("Cannot " + t);
5
+ var u = (r, e, t) => (W(r, e, "read from private field"), t ? t.call(r) : e.get(r)), y = (r, e, t) => e.has(r) ? G("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(r) : e.set(r, t), g = (r, e, t, s) => (W(r, e, "write to private field"), s ? s.call(r, t) : e.set(r, t), t), m = (r, e, t) => (W(r, e, "access private method"), t);
6
6
  import "@php-wasm/node-polyfills";
7
7
  import { logger } from "@php-wasm/logger";
8
8
  import { dirname, joinPaths, Semaphore, createSpawnHandler, basename, normalizePath, AcquireTimeoutError, splitShellCommand } from "@php-wasm/util";
@@ -431,6 +431,19 @@ class PHPWorker {
431
431
  async request(e) {
432
432
  return await _private.get(this).requestHandler.request(e);
433
433
  }
434
+ /**
435
+ * Handles a request with streaming support for large responses.
436
+ * Returns a StreamedPHPResponse that allows processing the response
437
+ * body incrementally without buffering the entire response in memory.
438
+ *
439
+ * This is useful for large file downloads (>2GB) that would otherwise
440
+ * exceed JavaScript's Uint8Array size limits.
441
+ *
442
+ * @param request - PHP Request data.
443
+ */
444
+ async requestStreamed(e) {
445
+ return await _private.get(this).requestHandler.requestStreamed(e);
446
+ }
434
447
  /** @inheritDoc @php-wasm/universal!/PHP.run */
435
448
  async run(e) {
436
449
  const { php: t, reap: s } = await this.acquirePHPInstance();
@@ -623,9 +636,54 @@ const currentJsRuntime = function() {
623
636
  201: "Created",
624
637
  200: "OK"
625
638
  };
626
- class StreamedPHPResponse {
639
+ var C;
640
+ const D = class D {
627
641
  constructor(e, t, s, n) {
628
- this.parsedHeaders = null, this.cachedStdoutBytes = null, this.cachedStderrText = null, this.headersStream = e, this.stdout = t, this.stderr = s, this.exitCode = n;
642
+ /**
643
+ * Response headers stream (internal).
644
+ */
645
+ y(this, C);
646
+ this.parsedHeaders = null, this.cachedStdoutBytes = null, this.cachedStderrText = null, g(this, C, e), this.stdout = t, this.stderr = s, this.exitCode = n;
647
+ }
648
+ /**
649
+ * Creates a StreamedPHPResponse from a buffered PHPResponse.
650
+ * Useful for unifying response handling when both types may be returned.
651
+ */
652
+ static fromPHPResponse(e) {
653
+ const t = new ReadableStream({
654
+ start(i) {
655
+ i.enqueue(e.bytes), i.close();
656
+ }
657
+ }), s = () => new ReadableStream({
658
+ start(i) {
659
+ i.close();
660
+ }
661
+ }), n = new D(
662
+ s(),
663
+ t,
664
+ s(),
665
+ Promise.resolve(e.exitCode)
666
+ );
667
+ return n.parsedHeaders = Promise.resolve({
668
+ headers: e.headers,
669
+ httpStatusCode: e.httpStatusCode
670
+ }), n;
671
+ }
672
+ /**
673
+ * Creates a StreamedPHPResponse for a given HTTP status code.
674
+ * Shorthand for `StreamedPHPResponse.fromPHPResponse(PHPResponse.forHttpCode(...))`.
675
+ */
676
+ static forHttpCode(e, t = "") {
677
+ return D.fromPHPResponse(
678
+ PHPResponse.forHttpCode(e, t)
679
+ );
680
+ }
681
+ /**
682
+ * Returns the raw headers stream for serialization purposes.
683
+ * For parsed headers, use the `headers` property instead.
684
+ */
685
+ getHeadersStream() {
686
+ return u(this, C);
629
687
  }
630
688
  /**
631
689
  * True if the response is successful (HTTP status code 200-399),
@@ -685,9 +743,11 @@ class StreamedPHPResponse {
685
743
  return this.cachedStderrText || (this.cachedStderrText = streamToText(this.stderr)), this.cachedStderrText;
686
744
  }
687
745
  async getParsedHeaders() {
688
- return this.parsedHeaders || (this.parsedHeaders = parseHeadersStream(this.headersStream)), await this.parsedHeaders;
746
+ return this.parsedHeaders || (this.parsedHeaders = parseHeadersStream(u(this, C))), await this.parsedHeaders;
689
747
  }
690
- }
748
+ };
749
+ C = new WeakMap();
750
+ let StreamedPHPResponse = D;
691
751
  async function parseHeadersStream(r) {
692
752
  const e = await streamToText(r);
693
753
  let t;
@@ -961,7 +1021,7 @@ class PHPExecutionFailureError extends Error {
961
1021
  }
962
1022
  }
963
1023
  const PHP_INI_PATH = "/internal/shared/php.ini", AUTO_PREPEND_SCRIPT = "/internal/shared/auto_prepend_file.php", OPCACHE_FILE_FOLDER = "/internal/shared/opcache";
964
- var M, R, b, S, T, H, w, h, V, G, J, Y, X, Q, K, Z, D, ee, W, j;
1024
+ var M, R, b, S, H, T, w, h, J, Y, X, Q, K, Z, ee, te, j, re, q, z;
965
1025
  class PHP {
966
1026
  /**
967
1027
  * Initializes a PHP runtime.
@@ -979,8 +1039,8 @@ class PHP {
979
1039
  // Listen to all events
980
1040
  ["*", /* @__PURE__ */ new Set()]
981
1041
  ]));
982
- y(this, T, []);
983
- y(this, H, {});
1042
+ y(this, H, []);
1043
+ y(this, T, {});
984
1044
  y(this, w, {
985
1045
  enabled: !1,
986
1046
  recreateRuntime: () => 0,
@@ -1058,8 +1118,8 @@ class PHP {
1058
1118
  * @param listener Callback function to handle the message.
1059
1119
  */
1060
1120
  onMessage(r) {
1061
- return u(this, T).push(r), async () => {
1062
- g(this, T, u(this, T).filter(
1121
+ return u(this, H).push(r), async () => {
1122
+ g(this, H, u(this, H).filter(
1063
1123
  (e) => e !== r
1064
1124
  ));
1065
1125
  };
@@ -1153,7 +1213,7 @@ class PHP {
1153
1213
  }
1154
1214
  `
1155
1215
  ), e.onMessage = async (t) => {
1156
- for (const s of u(this, T)) {
1216
+ for (const s of u(this, H)) {
1157
1217
  const n = await s(t);
1158
1218
  if (n)
1159
1219
  return n;
@@ -1396,7 +1456,7 @@ class PHP {
1396
1456
  async runStream(r) {
1397
1457
  const e = await this.semaphore.acquire();
1398
1458
  let t;
1399
- const s = m(this, h, j).call(this, async () => {
1459
+ const s = m(this, h, z).call(this, async () => {
1400
1460
  if (u(this, R) || (await this[__private__dont__use].ccall(
1401
1461
  "php_wasm_init",
1402
1462
  null,
@@ -1409,22 +1469,22 @@ class PHP {
1409
1469
  throw new Error(
1410
1470
  `The script path "${r.scriptPath}" does not exist.`
1411
1471
  );
1412
- m(this, h, G).call(this, r.relativeUri || ""), m(this, h, Q).call(this, r.method || "GET");
1413
- const i = normalizeHeaders(r.headers || {}), o = i.host || "example.com:443", a = m(this, h, X).call(this, o, r.protocol || "http");
1414
- if (m(this, h, J).call(this, o), m(this, h, Y).call(this, a), m(this, h, K).call(this, i), r.body && (t = m(this, h, Z).call(this, r.body)), typeof r.code == "string")
1415
- this.writeFile("/internal/eval.php", r.code), m(this, h, D).call(this, "/internal/eval.php");
1472
+ m(this, h, Y).call(this, r.relativeUri || ""), m(this, h, Z).call(this, r.method || "GET");
1473
+ const i = normalizeHeaders(r.headers || {}), o = i.host || "example.com:443", a = m(this, h, K).call(this, o, r.protocol || "http");
1474
+ if (m(this, h, X).call(this, o), m(this, h, Q).call(this, a), m(this, h, ee).call(this, i), r.body && (t = m(this, h, te).call(this, r.body)), typeof r.code == "string")
1475
+ this.writeFile("/internal/eval.php", r.code), m(this, h, j).call(this, "/internal/eval.php");
1416
1476
  else if (typeof r.scriptPath == "string")
1417
- m(this, h, D).call(this, r.scriptPath || "");
1477
+ m(this, h, j).call(this, r.scriptPath || "");
1418
1478
  else
1419
1479
  throw new TypeError(
1420
1480
  "The request object must have either a `code` or a `scriptPath` property."
1421
1481
  );
1422
- const c = m(this, h, V).call(this, r.$_SERVER, i, a);
1482
+ const c = m(this, h, J).call(this, r.$_SERVER, i, a);
1423
1483
  for (const d in c)
1424
- m(this, h, ee).call(this, d, c[d]);
1484
+ m(this, h, re).call(this, d, c[d]);
1425
1485
  const l = r.env || {};
1426
1486
  for (const d in l)
1427
- m(this, h, W).call(this, d, l[d]);
1487
+ m(this, h, q).call(this, d, l[d]);
1428
1488
  return await this[__private__dont__use].ccall(
1429
1489
  "wasm_sapi_handle_request",
1430
1490
  NUMBER,
@@ -1672,13 +1732,13 @@ class PHP {
1672
1732
  async hotSwapPHPRuntime(r) {
1673
1733
  const e = this[__private__dont__use].FS, t = this.listFiles("/").map((c) => `/${c}`), s = this[__private__dont__use].spawnProcess, n = e.cwd();
1674
1734
  e.chdir("/");
1675
- const i = Object.entries(u(this, H)).map(
1735
+ const i = Object.entries(u(this, T)).map(
1676
1736
  ([c, l]) => ({
1677
1737
  mountHandler: l.mountHandler,
1678
1738
  vfsPath: c
1679
1739
  })
1680
1740
  ), o = Object.values(
1681
- u(this, H)
1741
+ u(this, T)
1682
1742
  ).reverse();
1683
1743
  for (const c of o)
1684
1744
  await c.unmount();
@@ -1718,10 +1778,10 @@ class PHP {
1718
1778
  ), s = {
1719
1779
  mountHandler: e,
1720
1780
  unmount: async () => {
1721
- await t(), delete u(this, H)[r];
1781
+ await t(), delete u(this, T)[r];
1722
1782
  }
1723
1783
  };
1724
- return u(this, H)[r] = s, () => {
1784
+ return u(this, T)[r] = s, () => {
1725
1785
  s.unmount();
1726
1786
  };
1727
1787
  }
@@ -1743,10 +1803,10 @@ class PHP {
1743
1803
  return this.subProcess(r, e);
1744
1804
  u(this, R) && (u(this, w).needsRotating = !0);
1745
1805
  const t = await this.semaphore.acquire();
1746
- return await m(this, h, j).call(this, () => {
1806
+ return await m(this, h, z).call(this, () => {
1747
1807
  const s = e.env || {};
1748
1808
  for (const [n, i] of Object.entries(s))
1749
- m(this, h, W).call(this, n, i);
1809
+ m(this, h, q).call(this, n, i);
1750
1810
  r = [r[0], "-c", PHP_INI_PATH, ...r.slice(1)];
1751
1811
  for (const n of r)
1752
1812
  this[__private__dont__use].ccall(
@@ -1837,7 +1897,7 @@ class PHP {
1837
1897
  this.exit(0);
1838
1898
  }
1839
1899
  }
1840
- M = new WeakMap(), R = new WeakMap(), b = new WeakMap(), S = new WeakMap(), T = new WeakMap(), H = new WeakMap(), w = new WeakMap(), h = new WeakSet(), /**
1900
+ M = new WeakMap(), R = new WeakMap(), b = new WeakMap(), S = new WeakMap(), H = new WeakMap(), T = new WeakMap(), w = new WeakMap(), h = new WeakSet(), /**
1841
1901
  * Prepares the $_SERVER entries for the PHP runtime.
1842
1902
  *
1843
1903
  * @param defaults Default entries to include in $_SERVER.
@@ -1846,7 +1906,7 @@ M = new WeakMap(), R = new WeakMap(), b = new WeakMap(), S = new WeakMap(), T =
1846
1906
  * was provided.
1847
1907
  * @returns Computed $_SERVER entries.
1848
1908
  */
1849
- V = function(r, e, t) {
1909
+ J = function(r, e, t) {
1850
1910
  const s = {
1851
1911
  ...r || {}
1852
1912
  };
@@ -1856,7 +1916,7 @@ V = function(r, e, t) {
1856
1916
  ["content-type", "content-length"].includes(n.toLowerCase()) && (i = ""), s[`${i}${n.toUpperCase().replace(/-/g, "_")}`] = e[n];
1857
1917
  }
1858
1918
  return s;
1859
- }, G = function(r) {
1919
+ }, Y = function(r) {
1860
1920
  this[__private__dont__use].ccall(
1861
1921
  "wasm_set_request_uri",
1862
1922
  null,
@@ -1870,35 +1930,35 @@ V = function(r, e, t) {
1870
1930
  [STRING],
1871
1931
  [e]
1872
1932
  );
1873
- }, J = function(r) {
1933
+ }, X = function(r) {
1874
1934
  this[__private__dont__use].ccall(
1875
1935
  "wasm_set_request_host",
1876
1936
  null,
1877
1937
  [STRING],
1878
1938
  [r]
1879
1939
  );
1880
- }, Y = function(r) {
1940
+ }, Q = function(r) {
1881
1941
  this[__private__dont__use].ccall(
1882
1942
  "wasm_set_request_port",
1883
1943
  null,
1884
1944
  [NUMBER],
1885
1945
  [r]
1886
1946
  );
1887
- }, X = function(r, e) {
1947
+ }, K = function(r, e) {
1888
1948
  let t;
1889
1949
  try {
1890
1950
  t = parseInt(new URL(r).port, 10);
1891
1951
  } catch {
1892
1952
  }
1893
1953
  return (!t || isNaN(t) || t === 80) && (t = e === "https" ? 443 : 80), t;
1894
- }, Q = function(r) {
1954
+ }, Z = function(r) {
1895
1955
  this[__private__dont__use].ccall(
1896
1956
  "wasm_set_request_method",
1897
1957
  null,
1898
1958
  [STRING],
1899
1959
  [r]
1900
1960
  );
1901
- }, K = function(r) {
1961
+ }, ee = function(r) {
1902
1962
  r.cookie && this[__private__dont__use].ccall(
1903
1963
  "wasm_set_cookies",
1904
1964
  null,
@@ -1915,7 +1975,7 @@ V = function(r, e, t) {
1915
1975
  [NUMBER],
1916
1976
  [parseInt(r["content-length"], 10)]
1917
1977
  );
1918
- }, Z = function(r) {
1978
+ }, te = function(r) {
1919
1979
  let e, t;
1920
1980
  typeof r == "string" ? (logger.warn(
1921
1981
  "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"
@@ -1938,28 +1998,28 @@ V = function(r, e, t) {
1938
1998
  [NUMBER],
1939
1999
  [t]
1940
2000
  ), s;
1941
- }, D = function(r) {
2001
+ }, j = function(r) {
1942
2002
  this[__private__dont__use].ccall(
1943
2003
  "wasm_set_path_translated",
1944
2004
  null,
1945
2005
  [STRING],
1946
2006
  [r]
1947
2007
  );
1948
- }, ee = function(r, e) {
2008
+ }, re = function(r, e) {
1949
2009
  this[__private__dont__use].ccall(
1950
2010
  "wasm_add_SERVER_entry",
1951
2011
  null,
1952
2012
  [STRING, STRING],
1953
2013
  [r, e]
1954
2014
  );
1955
- }, W = function(r, e) {
2015
+ }, q = function(r, e) {
1956
2016
  this[__private__dont__use].ccall(
1957
2017
  "wasm_add_ENV_entry",
1958
2018
  null,
1959
2019
  [STRING, STRING],
1960
2020
  [r, e]
1961
2021
  );
1962
- }, j = async function(r) {
2022
+ }, z = async function(r) {
1963
2023
  u(this, w).enabled && u(this, w).needsRotating && await this.rotateRuntime(), ++u(this, w).requestsMade, u(this, w).requestsMade >= u(this, w).maxRequests && (u(this, w).needsRotating = !0);
1964
2024
  const e = this[__private__dont__use], t = await createInvertedReadableStream();
1965
2025
  e.onHeaders = (p) => {
@@ -1983,10 +2043,10 @@ V = function(r, e, t) {
1983
2043
  return await Promise.race([
1984
2044
  r(),
1985
2045
  new Promise((_, F) => {
1986
- var z;
1987
- c = ($) => {
1988
- isExitCode($.error) || F($.error);
1989
- }, (z = u(this, b)) == null || z.addEventListener(
2046
+ var $;
2047
+ c = (V) => {
2048
+ isExitCode(V.error) || F(V.error);
2049
+ }, ($ = u(this, b)) == null || $.addEventListener(
1990
2050
  "error",
1991
2051
  c,
1992
2052
  { once: !0 }
@@ -2468,7 +2528,7 @@ const _default = "application/octet-stream", asx = "video/x-ms-asf", atom = "app
2468
2528
  xspf,
2469
2529
  zip
2470
2530
  };
2471
- var v, C, N, L, I, E, A, k, O, P, te, U, re, se, ne;
2531
+ var v, I, O, L, A, E, N, k, U, P, se, B, ne, ie, oe;
2472
2532
  class PHPRequestHandler {
2473
2533
  /**
2474
2534
  * The request handler needs to decide whether to serve a static asset or
@@ -2484,14 +2544,14 @@ class PHPRequestHandler {
2484
2544
  constructor(e) {
2485
2545
  y(this, P);
2486
2546
  y(this, v);
2487
- y(this, C);
2488
- y(this, N);
2489
- y(this, L);
2490
2547
  y(this, I);
2491
- y(this, E);
2548
+ y(this, O);
2549
+ y(this, L);
2492
2550
  y(this, A);
2551
+ y(this, E);
2552
+ y(this, N);
2493
2553
  y(this, k);
2494
- y(this, O);
2554
+ y(this, U);
2495
2555
  const {
2496
2556
  documentRoot: t = "/www/",
2497
2557
  absoluteUrl: s = typeof location == "object" ? location.href : DEFAULT_BASE_URL,
@@ -2522,16 +2582,16 @@ class PHPRequestHandler {
2522
2582
  );
2523
2583
  g(this, k, e.cookieStore === void 0 ? new HttpCookieStore() : e.cookieStore), g(this, v, t);
2524
2584
  const c = new URL(s);
2525
- g(this, N, c.hostname), g(this, L, c.port ? Number(c.port) : c.protocol === "https:" ? 443 : 80), g(this, C, (c.protocol || "").replace(":", ""));
2585
+ g(this, O, c.hostname), g(this, L, c.port ? Number(c.port) : c.protocol === "https:" ? 443 : 80), g(this, I, (c.protocol || "").replace(":", ""));
2526
2586
  const l = u(this, L) !== 443 && u(this, L) !== 80;
2527
- g(this, I, [
2528
- u(this, N),
2587
+ g(this, A, [
2588
+ u(this, O),
2529
2589
  l ? `:${u(this, L)}` : ""
2530
- ].join("")), g(this, E, c.pathname.replace(/\/+$/, "")), g(this, A, [
2531
- `${u(this, C)}://`,
2532
- u(this, I),
2590
+ ].join("")), g(this, E, c.pathname.replace(/\/+$/, "")), g(this, N, [
2591
+ `${u(this, I)}://`,
2592
+ u(this, A),
2533
2593
  u(this, E)
2534
- ].join("")), this.rewriteRules = n, g(this, O, i), this.getFileNotFoundAction = o;
2594
+ ].join("")), this.rewriteRules = n, g(this, U, i), this.getFileNotFoundAction = o;
2535
2595
  }
2536
2596
  async getPrimaryPhp() {
2537
2597
  return await this.instanceManager.getPrimaryPhp();
@@ -2561,7 +2621,7 @@ class PHPRequestHandler {
2561
2621
  * The absolute URL of this PHPRequestHandler instance.
2562
2622
  */
2563
2623
  get absoluteUrl() {
2564
- return u(this, A);
2624
+ return u(this, N);
2565
2625
  }
2566
2626
  /**
2567
2627
  * The directory in the PHP filesystem where the server will look
@@ -2619,11 +2679,32 @@ class PHPRequestHandler {
2619
2679
  * @param request - PHP Request data.
2620
2680
  */
2621
2681
  async request(e) {
2682
+ const t = await this.requestStreamed(e), s = await PHPResponse.fromStreamedResponse(t);
2683
+ return s.ok() && s.exitCode !== 0 ? new PHPResponse(
2684
+ 500,
2685
+ s.headers,
2686
+ s.bytes,
2687
+ s.errors,
2688
+ s.exitCode
2689
+ ) : s;
2690
+ }
2691
+ /**
2692
+ * Serves the request with streaming support – returns a StreamedPHPResponse
2693
+ * that allows processing the response body incrementally without buffering
2694
+ * the entire response in memory.
2695
+ *
2696
+ * This is useful for large file downloads (>2GB) that would otherwise
2697
+ * exceed JavaScript's Uint8Array size limits.
2698
+ *
2699
+ * @param request - PHP Request data.
2700
+ * @returns A StreamedPHPResponse.
2701
+ */
2702
+ async requestStreamed(e) {
2622
2703
  const t = looksLikeAbsoluteUrl(e.url), s = new URL(
2623
2704
  // Remove the hash part of the URL as it's not meant for the server.
2624
2705
  e.url.split("#")[0],
2625
2706
  t ? void 0 : DEFAULT_BASE_URL
2626
- ), n = m(this, P, te).call(this, s), i = await this.getPrimaryPhp(), o = removePathPrefix(
2707
+ ), n = m(this, P, se).call(this, s), i = await this.getPrimaryPhp(), o = removePathPrefix(
2627
2708
  /**
2628
2709
  * URL.pathname returns a URL-encoded path. We need to decode it
2629
2710
  * before using it as a filesystem path.
@@ -2631,13 +2712,15 @@ class PHPRequestHandler {
2631
2712
  decodeURIComponent(n.pathname),
2632
2713
  u(this, E)
2633
2714
  );
2634
- let a = m(this, P, U).call(this, o);
2715
+ let a = m(this, P, B).call(this, o);
2635
2716
  if (i.isDir(a)) {
2636
2717
  if (!o.endsWith("/"))
2637
- return new PHPResponse(
2638
- 301,
2639
- { Location: [`${n.pathname}/`] },
2640
- new Uint8Array(0)
2718
+ return StreamedPHPResponse.fromPHPResponse(
2719
+ new PHPResponse(
2720
+ 301,
2721
+ { Location: [`${n.pathname}/`] },
2722
+ new Uint8Array(0)
2723
+ )
2641
2724
  );
2642
2725
  for (const c of ["index.php", "index.html"]) {
2643
2726
  const l = joinPaths(a, c);
@@ -2654,10 +2737,10 @@ class PHPRequestHandler {
2654
2737
  let c = o;
2655
2738
  for (; c.startsWith("/") && c !== dirname(c); ) {
2656
2739
  c = dirname(c);
2657
- const l = m(this, P, U).call(this, c);
2740
+ const l = m(this, P, B).call(this, c);
2658
2741
  if (i.isFile(l) && // Only run partial path resolution for PHP files.
2659
2742
  l.endsWith(".php")) {
2660
- a = m(this, P, U).call(this, c);
2743
+ a = m(this, P, B).call(this, c);
2661
2744
  break;
2662
2745
  }
2663
2746
  }
@@ -2668,32 +2751,23 @@ class PHPRequestHandler {
2668
2751
  );
2669
2752
  switch (c.type) {
2670
2753
  case "response":
2671
- return c.response;
2754
+ return StreamedPHPResponse.fromPHPResponse(
2755
+ c.response
2756
+ );
2672
2757
  case "internal-redirect":
2673
2758
  a = joinPaths(u(this, v), c.uri);
2674
2759
  break;
2675
2760
  case "404":
2676
- return PHPResponse.forHttpCode(404);
2761
+ return StreamedPHPResponse.forHttpCode(404);
2677
2762
  default:
2678
2763
  throw new Error(
2679
2764
  `Unsupported file-not-found action type: '${c.type}'`
2680
2765
  );
2681
2766
  }
2682
2767
  }
2683
- if (i.isFile(a))
2684
- if (a.endsWith(".php")) {
2685
- const c = await m(this, P, se).call(this, e, s, n, a);
2686
- return c.ok() && c.exitCode !== 0 ? new PHPResponse(
2687
- 500,
2688
- c.headers,
2689
- c.bytes,
2690
- c.errors,
2691
- c.exitCode
2692
- ) : c;
2693
- } else
2694
- return m(this, P, re).call(this, i, a);
2695
- else
2696
- return PHPResponse.forHttpCode(404);
2768
+ return i.isFile(a) ? a.endsWith(".php") ? await m(this, P, ie).call(this, e, s, n, a) : StreamedPHPResponse.fromPHPResponse(
2769
+ m(this, P, ne).call(this, i, a)
2770
+ ) : StreamedPHPResponse.forHttpCode(404);
2697
2771
  }
2698
2772
  /**
2699
2773
  * Computes the essential $_SERVER entries for a request.
@@ -2787,7 +2861,7 @@ class PHPRequestHandler {
2787
2861
  const n = {
2788
2862
  REMOTE_ADDR: "127.0.0.1",
2789
2863
  DOCUMENT_ROOT: u(this, v),
2790
- HTTPS: u(this, A).startsWith("https://") ? "on" : ""
2864
+ HTTPS: u(this, N).startsWith("https://") ? "on" : ""
2791
2865
  };
2792
2866
  return n.REQUEST_URI = e.pathname + e.search, s.startsWith(u(this, v)) && (n.SCRIPT_NAME = s.substring(
2793
2867
  u(this, v).length
@@ -2802,13 +2876,13 @@ class PHPRequestHandler {
2802
2876
  await this.instanceManager[Symbol.asyncDispose]();
2803
2877
  }
2804
2878
  }
2805
- v = new WeakMap(), C = new WeakMap(), N = new WeakMap(), L = new WeakMap(), I = new WeakMap(), E = new WeakMap(), A = new WeakMap(), k = new WeakMap(), O = new WeakMap(), P = new WeakSet(), /**
2879
+ v = new WeakMap(), I = new WeakMap(), O = new WeakMap(), L = new WeakMap(), A = new WeakMap(), E = new WeakMap(), N = new WeakMap(), k = new WeakMap(), U = new WeakMap(), P = new WeakSet(), /**
2806
2880
  * Apply the rewrite rules to the original request URL.
2807
2881
  *
2808
2882
  * @param originalRequestUrl - The original request URL.
2809
2883
  * @returns The rewritten request URL.
2810
2884
  */
2811
- te = function(e) {
2885
+ se = function(e) {
2812
2886
  const t = removePathPrefix(
2813
2887
  decodeURIComponent(e.pathname),
2814
2888
  u(this, E)
@@ -2831,8 +2905,8 @@ te = function(e) {
2831
2905
  * @param urlPath - The URL path to resolve (e.g., '/phpmyadmin/index.php')
2832
2906
  * @returns The resolved filesystem path
2833
2907
  */
2834
- U = function(e) {
2835
- for (const t of u(this, O))
2908
+ B = function(e) {
2909
+ for (const t of u(this, U))
2836
2910
  if (e === t.urlPrefix || e.startsWith(t.urlPrefix + "/")) {
2837
2911
  const s = e.slice(t.urlPrefix.length);
2838
2912
  return joinPaths(t.fsPath, s);
@@ -2844,7 +2918,7 @@ U = function(e) {
2844
2918
  * @param fsPath - Absolute path of the static file to serve.
2845
2919
  * @returns The response.
2846
2920
  */
2847
- re = function(e, t) {
2921
+ ne = function(e, t) {
2848
2922
  const s = e.readFileAsBuffer(t);
2849
2923
  return new PHPResponse(
2850
2924
  200,
@@ -2859,57 +2933,58 @@ re = function(e, t) {
2859
2933
  },
2860
2934
  s
2861
2935
  );
2862
- }, se = async function(e, t, s, n) {
2936
+ }, ie = async function(e, t, s, n) {
2863
2937
  let i;
2864
2938
  try {
2865
2939
  i = await this.instanceManager.acquirePHPInstance();
2866
- } catch (o) {
2867
- return o instanceof MaxPhpInstancesError ? PHPResponse.forHttpCode(502) : PHPResponse.forHttpCode(500);
2940
+ } catch (a) {
2941
+ return a instanceof MaxPhpInstancesError ? StreamedPHPResponse.forHttpCode(502) : StreamedPHPResponse.forHttpCode(500);
2868
2942
  }
2943
+ let o;
2869
2944
  try {
2870
- return await m(this, P, ne).call(this, i.php, e, t, s, n);
2871
- } finally {
2872
- i.reap();
2873
- }
2874
- }, ne = async function(e, t, s, n, i) {
2945
+ o = await m(this, P, oe).call(this, i.php, e, t, s, n);
2946
+ } catch (a) {
2947
+ throw i.reap(), a;
2948
+ }
2949
+ return o.finished.finally(() => {
2950
+ i == null || i.reap();
2951
+ }), o;
2952
+ }, oe = async function(e, t, s, n, i) {
2875
2953
  let o = "GET";
2876
2954
  const a = {
2877
- host: u(this, I),
2955
+ host: u(this, A),
2878
2956
  ...normalizeHeaders(t.headers || {})
2879
2957
  };
2880
2958
  u(this, k) && (a.cookie = u(this, k).getCookieRequestHeader());
2881
2959
  let c = t.body;
2882
2960
  if (typeof c == "object" && !(c instanceof Uint8Array)) {
2883
2961
  o = "POST";
2884
- const { bytes: l, contentType: d } = await encodeAsMultipart(c);
2885
- c = l, a["content-type"] = d;
2962
+ const { bytes: d, contentType: p } = await encodeAsMultipart(c);
2963
+ c = d, a["content-type"] = p;
2886
2964
  }
2887
- try {
2888
- const l = await e.run({
2889
- relativeUri: ensurePathPrefix(
2890
- toRelativeUrl(new URL(n.toString())),
2891
- u(this, E)
2892
- ),
2893
- protocol: u(this, C),
2894
- method: t.method || o,
2895
- $_SERVER: this.prepare_$_SERVER_superglobal(
2896
- s,
2897
- n,
2898
- i
2899
- ),
2900
- body: c,
2901
- scriptPath: i,
2902
- headers: a
2965
+ const l = await e.runStream({
2966
+ relativeUri: ensurePathPrefix(
2967
+ toRelativeUrl(new URL(n.toString())),
2968
+ u(this, E)
2969
+ ),
2970
+ protocol: u(this, I),
2971
+ method: t.method || o,
2972
+ $_SERVER: this.prepare_$_SERVER_superglobal(
2973
+ s,
2974
+ n,
2975
+ i
2976
+ ),
2977
+ body: c,
2978
+ scriptPath: i,
2979
+ headers: a
2980
+ });
2981
+ if (u(this, k)) {
2982
+ const d = u(this, k);
2983
+ l.headers.then((p) => {
2984
+ d.rememberCookiesFromResponseHeaders(p);
2903
2985
  });
2904
- return u(this, k) && u(this, k).rememberCookiesFromResponseHeaders(
2905
- l.headers
2906
- ), l;
2907
- } catch (l) {
2908
- const d = l;
2909
- if (d != null && d.response)
2910
- return d.response;
2911
- throw l;
2912
2986
  }
2987
+ return l;
2913
2988
  };
2914
2989
  function inferMimeType(r) {
2915
2990
  const e = r.split(".").pop();
@@ -3792,25 +3867,33 @@ function setupTransferHandlers() {
3792
3867
  }, transferHandlers.set("StreamedPHPResponse", {
3793
3868
  canHandle: (t) => t instanceof StreamedPHPResponse,
3794
3869
  serialize(t) {
3795
- const s = supportsTransferableStreams(), n = promiseToPort(t.exitCode);
3870
+ const s = supportsTransferableStreams(), n = promiseToPort(t.exitCode), i = t.getHeadersStream();
3796
3871
  if (s)
3797
- return [{
3798
- __type: "StreamedPHPResponse",
3799
- headers: t.headersStream,
3800
- stdout: t.stdout,
3801
- stderr: t.stderr,
3802
- exitCodePort: n
3803
- }, [n]];
3804
- const i = streamToPort(t.headersStream), o = streamToPort(t.stdout), a = streamToPort(t.stderr);
3872
+ return [
3873
+ {
3874
+ __type: "StreamedPHPResponse",
3875
+ headers: i,
3876
+ stdout: t.stdout,
3877
+ stderr: t.stderr,
3878
+ exitCodePort: n
3879
+ },
3880
+ [
3881
+ i,
3882
+ t.stdout,
3883
+ t.stderr,
3884
+ n
3885
+ ]
3886
+ ];
3887
+ const o = streamToPort(i), a = streamToPort(t.stdout), c = streamToPort(t.stderr);
3805
3888
  return [
3806
3889
  {
3807
3890
  __type: "StreamedPHPResponse",
3808
- headersPort: i,
3809
- stdoutPort: o,
3810
- stderrPort: a,
3891
+ headersPort: o,
3892
+ stdoutPort: a,
3893
+ stderrPort: c,
3811
3894
  exitCodePort: n
3812
3895
  },
3813
- [i, o, a, n]
3896
+ [o, a, c, n]
3814
3897
  ];
3815
3898
  },
3816
3899
  deserialize(t) {