@php-wasm/universal 3.1.21 → 3.1.25

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 Y = (r) => {
1
+ var J = (r) => {
2
2
  throw TypeError(r);
3
3
  };
4
- var W = (r, e, t) => e.has(r) || Y("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) ? Y("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);
4
+ var q = (r, e, t) => e.has(r) || J("Cannot " + t);
5
+ var d = (r, e, t) => (q(r, e, "read from private field"), t ? t.call(r) : e.get(r)), y = (r, e, t) => e.has(r) ? J("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(r) : e.set(r, t), w = (r, e, t, s) => (q(r, e, "write to private field"), s ? s.call(r, t) : e.set(r, t), t), m = (r, e, t) => (q(r, e, "access private method"), t);
6
6
  import { logger } from "@php-wasm/logger";
7
7
  import { dirname, joinPaths, Semaphore, createSpawnHandler, basename, normalizePath, AcquireTimeoutError, splitShellCommand } from "@php-wasm/util";
8
8
  import { parse, stringify } from "ini";
@@ -376,7 +376,7 @@ class PHPWorker {
376
376
  /** @inheritDoc */
377
377
  constructor(e, t) {
378
378
  y(this, v);
379
- this.absoluteUrl = "", this.documentRoot = "", this.chroot = null, g(this, v, /* @__PURE__ */ new Map()), this.onMessageListeners = [], _private.set(this, {
379
+ this.absoluteUrl = "", this.documentRoot = "", this.chroot = null, w(this, v, /* @__PURE__ */ new Map()), this.onMessageListeners = [], _private.set(this, {
380
380
  monitor: t
381
381
  }), e && this.__internal_setRequestHandler(e);
382
382
  }
@@ -404,7 +404,7 @@ class PHPWorker {
404
404
  * a warning.
405
405
  */
406
406
  __internal_getRequestHandler() {
407
- return _private.get(this).requestHandler;
407
+ return this.getRequestHandler();
408
408
  }
409
409
  async setPrimaryPHP(e) {
410
410
  _private.set(this, {
@@ -414,11 +414,11 @@ class PHPWorker {
414
414
  }
415
415
  /** @inheritDoc @php-wasm/universal!PHPRequestHandler.pathToInternalUrl */
416
416
  pathToInternalUrl(e) {
417
- return _private.get(this).requestHandler.pathToInternalUrl(e);
417
+ return this.getRequestHandler().pathToInternalUrl(e);
418
418
  }
419
419
  /** @inheritDoc @php-wasm/universal!PHPRequestHandler.internalUrlToPath */
420
420
  internalUrlToPath(e) {
421
- return _private.get(this).requestHandler.internalUrlToPath(e);
421
+ return this.getRequestHandler().internalUrlToPath(e);
422
422
  }
423
423
  /**
424
424
  * The onDownloadProgress event listener.
@@ -437,7 +437,7 @@ class PHPWorker {
437
437
  }
438
438
  /** @inheritDoc @php-wasm/universal!PHPRequestHandler.request */
439
439
  async request(e) {
440
- return await _private.get(this).requestHandler.request(e);
440
+ return await this.getRequestHandler().request(e);
441
441
  }
442
442
  /**
443
443
  * Handles a request with streaming support for large responses.
@@ -450,27 +450,33 @@ class PHPWorker {
450
450
  * @param request - PHP Request data.
451
451
  */
452
452
  async requestStreamed(e) {
453
- return await _private.get(this).requestHandler.requestStreamed(e);
453
+ return await this.getRequestHandler().requestStreamed(e);
454
454
  }
455
455
  /** @inheritDoc @php-wasm/universal!/PHP.run */
456
456
  async run(e) {
457
- const { php: t, reap: s } = await this.acquirePHPInstance();
457
+ const t = _private.get(this), s = t.php;
458
+ if (!t.requestHandler && !(s != null && s.requestHandler) && s)
459
+ return await s.run(e);
460
+ const { php: n, reap: i } = await this.acquirePHPInstance();
458
461
  try {
459
- return await t.run(e);
462
+ return await n.run(e);
460
463
  } finally {
461
- s();
464
+ i();
462
465
  }
463
466
  }
464
467
  /** @inheritDoc @php-wasm/universal!/PHP.cli */
465
468
  async cli(e, t) {
466
- const { php: s, reap: n } = await this.acquirePHPInstance();
467
- let i;
469
+ const s = _private.get(this), n = s.php;
470
+ if (!s.requestHandler && !(n != null && n.requestHandler) && n)
471
+ return await n.cli(e, t);
472
+ const { php: i, reap: o } = await this.acquirePHPInstance();
473
+ let a;
468
474
  try {
469
- i = await s.cli(e, t);
470
- } catch (o) {
471
- throw n(), o;
475
+ a = await i.cli(e, t);
476
+ } catch (c) {
477
+ throw o(), c;
472
478
  }
473
- return i.finished.finally(n), i;
479
+ return a.finished.finally(o), a;
474
480
  }
475
481
  /** @inheritDoc @php-wasm/universal!/PHP.chdir */
476
482
  chdir(e) {
@@ -484,7 +490,7 @@ class PHPWorker {
484
490
  * @returns A PHP instance with a consistent chroot.
485
491
  */
486
492
  async acquirePHPInstance() {
487
- const { php: e, reap: t } = await _private.get(this).requestHandler.instanceManager.acquirePHPInstance();
493
+ const { php: e, reap: t } = await this.getRequestHandler().instanceManager.acquirePHPInstance();
488
494
  return this.chroot !== null && e.chdir(this.chroot), this.registerWorkerListeners(e), { php: e, reap: t };
489
495
  }
490
496
  /** @inheritDoc @php-wasm/universal!/PHP.setSapiName */
@@ -545,7 +551,7 @@ class PHPWorker {
545
551
  }
546
552
  /** @inheritDoc @php-wasm/universal!/PHP.addEventListener */
547
553
  addEventListener(e, t) {
548
- u(this, v).has(e) || u(this, v).set(e, /* @__PURE__ */ new Set()), u(this, v).get(e).add(t);
554
+ d(this, v).has(e) || d(this, v).set(e, /* @__PURE__ */ new Set()), d(this, v).get(e).add(t);
549
555
  }
550
556
  /**
551
557
  * Removes an event listener for a PHP event.
@@ -554,10 +560,10 @@ class PHPWorker {
554
560
  */
555
561
  removeEventListener(e, t) {
556
562
  var s;
557
- (s = u(this, v).get(e)) == null || s.delete(t);
563
+ (s = d(this, v).get(e)) == null || s.delete(t);
558
564
  }
559
565
  dispatchEvent(e) {
560
- const t = u(this, v).get(e.type);
566
+ const t = d(this, v).get(e.type);
561
567
  if (t)
562
568
  for (const s of t)
563
569
  s(e);
@@ -576,7 +582,17 @@ class PHPWorker {
576
582
  }
577
583
  async [Symbol.asyncDispose]() {
578
584
  var e;
579
- await ((e = _private.get(this).requestHandler) == null ? void 0 : e[Symbol.asyncDispose]());
585
+ await ((e = this.getRequestHandler(!1)) == null ? void 0 : e[Symbol.asyncDispose]());
586
+ }
587
+ getRequestHandler(e = !0) {
588
+ var s;
589
+ const t = _private.get(this);
590
+ if (t.requestHandler)
591
+ return t.requestHandler;
592
+ if ((s = t.php) != null && s.requestHandler)
593
+ return this.__internal_setRequestHandler(t.php.requestHandler), t.php.requestHandler;
594
+ if (e)
595
+ throw new Error("PHPWorker is not connected to a request handler.");
580
596
  }
581
597
  }
582
598
  v = new WeakMap();
@@ -587,14 +603,14 @@ const RuntimeId = Symbol("RuntimeId"), loadedRuntimes = /* @__PURE__ */ new Map(
587
603
  let lastRuntimeId = 0;
588
604
  async function loadPHPRuntime(r, ...e) {
589
605
  const t = Object.assign({}, ...e), [s, n, i] = makePromise(), o = r.init(currentJsRuntime, {
590
- onAbort(c) {
591
- i(c), logger.error(c);
606
+ onAbort(l) {
607
+ i(l), logger.error(l);
592
608
  },
593
609
  ENV: {},
594
610
  // Emscripten sometimes prepends a '/' to the path, which
595
611
  // breaks vite dev mode. An identity `locateFile` function
596
612
  // fixes it.
597
- locateFile: (c) => c,
613
+ locateFile: (l) => l,
598
614
  ...t,
599
615
  noInitialRun: !0,
600
616
  onRuntimeInitialized() {
@@ -602,10 +618,12 @@ async function loadPHPRuntime(r, ...e) {
602
618
  }
603
619
  });
604
620
  await s;
605
- const a = ++lastRuntimeId;
606
- return o.FS, o.id = a, o.originalExit = o._exit, o._exit = function(c) {
607
- return o.outboundNetworkProxyServer && (o.outboundNetworkProxyServer.close(), o.outboundNetworkProxyServer.closeAllConnections()), loadedRuntimes.delete(a), o.originalExit(c);
608
- }, o[RuntimeId] = a, loadedRuntimes.set(a, o), a;
621
+ const a = t.phpWasmAsyncMode ?? r.phpWasmAsyncMode;
622
+ a && (o.phpWasmAsyncMode = a);
623
+ const c = ++lastRuntimeId;
624
+ return o.FS, o.id = c, o.originalExit = o._exit, o._exit = function(l) {
625
+ return o.outboundNetworkProxyServer && (o.outboundNetworkProxyServer.close(), o.outboundNetworkProxyServer.closeAllConnections()), loadedRuntimes.delete(c), o.originalExit(l);
626
+ }, o[RuntimeId] = c, loadedRuntimes.set(c, o), c;
609
627
  }
610
628
  function popLoadedRuntime(r, {
611
629
  dangerouslyKeepTheRuntimeInTheMap: e = !1
@@ -644,8 +662,8 @@ const currentJsRuntime = function() {
644
662
  201: "Created",
645
663
  200: "OK"
646
664
  };
647
- var N, O;
648
- const D = class D {
665
+ var O, U;
666
+ const W = class W {
649
667
  constructor(e, t, s, n) {
650
668
  /**
651
669
  * Headers stream that doesn't get locked when the consumer
@@ -654,14 +672,14 @@ const D = class D {
654
672
  * Both streams must be readable when the StreamedPHPResponse is transferred
655
673
  * from the worker thread into the service worker.
656
674
  */
657
- y(this, N);
675
+ y(this, O);
658
676
  /**
659
677
  * Headers stream reserved for internal parsing.
660
678
  */
661
- y(this, O);
679
+ y(this, U);
662
680
  this.cachedParsedHeaders = null, this.cachedStdoutBytes = null, this.cachedStderrText = null;
663
681
  const [i, o] = e.tee();
664
- g(this, N, i), g(this, O, o), this.stdout = t, this.stderr = s, this.exitCode = n;
682
+ w(this, O, i), w(this, U, o), this.stdout = t, this.stderr = s, this.exitCode = n;
665
683
  }
666
684
  /**
667
685
  * Creates a StreamedPHPResponse from a buffered PHPResponse.
@@ -690,7 +708,7 @@ const D = class D {
690
708
  ), a.close();
691
709
  }
692
710
  });
693
- return new D(
711
+ return new W(
694
712
  i,
695
713
  t,
696
714
  o,
@@ -702,7 +720,7 @@ const D = class D {
702
720
  * Shorthand for `StreamedPHPResponse.fromPHPResponse(PHPResponse.forHttpCode(...))`.
703
721
  */
704
722
  static forHttpCode(e, t = "") {
705
- return D.fromPHPResponse(
723
+ return W.fromPHPResponse(
706
724
  PHPResponse.forHttpCode(e, t)
707
725
  );
708
726
  }
@@ -711,7 +729,7 @@ const D = class D {
711
729
  * For parsed headers, use the `headers` property instead.
712
730
  */
713
731
  getHeadersStream() {
714
- return u(this, N);
732
+ return d(this, O);
715
733
  }
716
734
  /**
717
735
  * True if the response is successful (HTTP status code 200-399),
@@ -772,12 +790,12 @@ const D = class D {
772
790
  }
773
791
  async getParsedHeaders() {
774
792
  return this.cachedParsedHeaders || (this.cachedParsedHeaders = parseHeadersStream(
775
- u(this, O)
793
+ d(this, U)
776
794
  )), await this.cachedParsedHeaders;
777
795
  }
778
796
  };
779
- N = new WeakMap(), O = new WeakMap();
780
- let StreamedPHPResponse = D;
797
+ O = new WeakMap(), U = new WeakMap();
798
+ let StreamedPHPResponse = W;
781
799
  async function parseHeadersStream(r) {
782
800
  const e = await streamToText(r);
783
801
  let t;
@@ -1051,7 +1069,7 @@ class PHPExecutionFailureError extends Error {
1051
1069
  }
1052
1070
  }
1053
1071
  const PHP_INI_PATH = "/internal/shared/php.ini", AUTO_PREPEND_SCRIPT = "/internal/shared/auto_prepend_file.php", OPCACHE_FILE_FOLDER = "/internal/shared/opcache";
1054
- var C, R, b, x, H, T, _, h, J, X, Q, K, Z, ee, te, re, $, se, q, z;
1072
+ var I, R, H, F, b, T, _, f, Y, X, Q, K, Z, ee, te, re, z, se, V, G;
1055
1073
  class PHP {
1056
1074
  /**
1057
1075
  * Initializes a PHP runtime.
@@ -1061,15 +1079,15 @@ class PHP {
1061
1079
  * @param requestHandlerOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
1062
1080
  */
1063
1081
  constructor(r) {
1064
- y(this, h);
1065
- y(this, C);
1082
+ y(this, f);
1083
+ y(this, I);
1066
1084
  y(this, R, !1);
1067
- y(this, b, null);
1068
- y(this, x, /* @__PURE__ */ new Map([
1085
+ y(this, H, null);
1086
+ y(this, F, /* @__PURE__ */ new Map([
1069
1087
  // Listen to all events
1070
1088
  ["*", /* @__PURE__ */ new Set()]
1071
1089
  ]));
1072
- y(this, H, []);
1090
+ y(this, b, []);
1073
1091
  y(this, T, {});
1074
1092
  y(this, _, {
1075
1093
  enabled: !1,
@@ -1079,7 +1097,7 @@ class PHP {
1079
1097
  requestsMade: 0
1080
1098
  });
1081
1099
  this.semaphore = new Semaphore({ concurrency: 1 }), r !== void 0 && this.initializeRuntime(r), this.addEventListener("request.error", (e) => {
1082
- e.source === "php-wasm" && (u(this, _).needsRotating = !0);
1100
+ e.source === "php-wasm" && (d(this, _).needsRotating = !0);
1083
1101
  });
1084
1102
  }
1085
1103
  /**
@@ -1088,7 +1106,7 @@ class PHP {
1088
1106
  * @param listener - The listener function to be called when the event is triggered.
1089
1107
  */
1090
1108
  addEventListener(r, e) {
1091
- u(this, x).has(r) || u(this, x).set(r, /* @__PURE__ */ new Set()), u(this, x).get(r).add(e);
1109
+ d(this, F).has(r) || d(this, F).set(r, /* @__PURE__ */ new Set()), d(this, F).get(r).add(e);
1092
1110
  }
1093
1111
  /**
1094
1112
  * Removes an event listener for a PHP event.
@@ -1097,12 +1115,12 @@ class PHP {
1097
1115
  */
1098
1116
  removeEventListener(r, e) {
1099
1117
  var t;
1100
- (t = u(this, x).get(r)) == null || t.delete(e);
1118
+ (t = d(this, F).get(r)) == null || t.delete(e);
1101
1119
  }
1102
1120
  dispatchEvent(r) {
1103
1121
  const e = [
1104
- ...u(this, x).get(r.type) || [],
1105
- ...u(this, x).get("*") || []
1122
+ ...d(this, F).get(r.type) || [],
1123
+ ...d(this, F).get("*") || []
1106
1124
  ];
1107
1125
  if (e)
1108
1126
  for (const t of e)
@@ -1148,8 +1166,8 @@ class PHP {
1148
1166
  * @param listener Callback function to handle the message.
1149
1167
  */
1150
1168
  onMessage(r) {
1151
- return u(this, H).push(r), async () => {
1152
- g(this, H, u(this, H).filter(
1169
+ return d(this, b).push(r), async () => {
1170
+ w(this, b, d(this, b).filter(
1153
1171
  (e) => e !== r
1154
1172
  ));
1155
1173
  };
@@ -1243,13 +1261,13 @@ class PHP {
1243
1261
  }
1244
1262
  `
1245
1263
  ), e.onMessage = async (t) => {
1246
- for (const s of u(this, H)) {
1264
+ for (const s of d(this, b)) {
1247
1265
  const n = await s(t);
1248
1266
  if (n)
1249
1267
  return n;
1250
1268
  }
1251
1269
  return "";
1252
- }, g(this, b, improveWASMErrorReporting(e)), this.dispatchEvent({
1270
+ }, w(this, H, improveWASMErrorReporting(e)), this.dispatchEvent({
1253
1271
  type: "runtime.initialized"
1254
1272
  });
1255
1273
  }
@@ -1264,7 +1282,7 @@ class PHP {
1264
1282
  throw new Error(
1265
1283
  "Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?"
1266
1284
  );
1267
- g(this, C, r);
1285
+ w(this, I, r);
1268
1286
  }
1269
1287
  /**
1270
1288
  * Changes the current working directory in the PHP filesystem.
@@ -1486,8 +1504,8 @@ class PHP {
1486
1504
  async runStream(r) {
1487
1505
  const e = await this.semaphore.acquire();
1488
1506
  let t;
1489
- const s = m(this, h, z).call(this, async () => {
1490
- if (u(this, R) || (await this[__private__dont__use].ccall(
1507
+ const s = m(this, f, G).call(this, async () => {
1508
+ if (d(this, R) || (await this[__private__dont__use].ccall(
1491
1509
  "php_wasm_init",
1492
1510
  null,
1493
1511
  [],
@@ -1495,26 +1513,26 @@ class PHP {
1495
1513
  {
1496
1514
  isAsync: !0
1497
1515
  }
1498
- ), g(this, R, !0)), r.scriptPath && !this.fileExists(r.scriptPath))
1516
+ ), w(this, R, !0)), r.scriptPath && !this.fileExists(r.scriptPath))
1499
1517
  throw new Error(
1500
1518
  `The script path "${r.scriptPath}" does not exist.`
1501
1519
  );
1502
- m(this, h, X).call(this, r.relativeUri || ""), m(this, h, ee).call(this, r.method || "GET");
1503
- const i = normalizeHeaders(r.headers || {}), o = i.host || "example.com:443", a = m(this, h, Z).call(this, o, r.protocol || "http");
1504
- if (m(this, h, Q).call(this, o), m(this, h, K).call(this, a), m(this, h, te).call(this, i), r.body && (t = m(this, h, re).call(this, r.body)), typeof r.code == "string")
1505
- this.writeFile("/internal/eval.php", r.code), m(this, h, $).call(this, "/internal/eval.php");
1520
+ m(this, f, X).call(this, r.relativeUri || ""), m(this, f, ee).call(this, r.method || "GET");
1521
+ const i = normalizeHeaders(r.headers || {}), o = i.host || "example.com:443", a = m(this, f, Z).call(this, o, r.protocol || "http");
1522
+ if (m(this, f, Q).call(this, o), m(this, f, K).call(this, a), m(this, f, te).call(this, i), r.body && (t = m(this, f, re).call(this, r.body)), typeof r.code == "string")
1523
+ this.writeFile("/internal/eval.php", r.code), m(this, f, z).call(this, "/internal/eval.php");
1506
1524
  else if (typeof r.scriptPath == "string")
1507
- m(this, h, $).call(this, r.scriptPath || "");
1525
+ m(this, f, z).call(this, r.scriptPath || "");
1508
1526
  else
1509
1527
  throw new TypeError(
1510
1528
  "The request object must have either a `code` or a `scriptPath` property."
1511
1529
  );
1512
- const c = m(this, h, J).call(this, r.$_SERVER, i, a);
1513
- for (const d in c)
1514
- m(this, h, se).call(this, d, c[d]);
1530
+ const c = m(this, f, Y).call(this, r.$_SERVER, i, a);
1531
+ for (const u in c)
1532
+ m(this, f, se).call(this, u, c[u]);
1515
1533
  const l = r.env || {};
1516
- for (const d in l)
1517
- m(this, h, q).call(this, d, l[d]);
1534
+ for (const u in l)
1535
+ m(this, f, V).call(this, u, l[u]);
1518
1536
  return await this[__private__dont__use].ccall(
1519
1537
  "wasm_sapi_handle_request",
1520
1538
  NUMBER,
@@ -1752,21 +1770,21 @@ class PHP {
1752
1770
  * or an internal crash.
1753
1771
  */
1754
1772
  enableRuntimeRotation(r) {
1755
- g(this, _, {
1756
- ...u(this, _),
1773
+ w(this, _, {
1774
+ ...d(this, _),
1757
1775
  enabled: !0,
1758
1776
  recreateRuntime: r.recreateRuntime,
1759
1777
  maxRequests: r.maxRequests ?? 400
1760
1778
  });
1761
1779
  }
1762
1780
  async rotateRuntime() {
1763
- if (!u(this, _).enabled)
1781
+ if (!d(this, _).enabled)
1764
1782
  throw new Error(
1765
1783
  "Runtime rotation is not enabled. Call enableRuntimeRotation() first."
1766
1784
  );
1767
1785
  await this.hotSwapPHPRuntime(
1768
- await u(this, _).recreateRuntime()
1769
- ), u(this, _).requestsMade = 0, u(this, _).needsRotating = !1;
1786
+ await d(this, _).recreateRuntime()
1787
+ ), d(this, _).requestsMade = 0, d(this, _).needsRotating = !1;
1770
1788
  }
1771
1789
  /**
1772
1790
  * Hot-swaps the PHP runtime for a new one without
@@ -1777,13 +1795,13 @@ class PHP {
1777
1795
  async hotSwapPHPRuntime(r) {
1778
1796
  const e = this[__private__dont__use].FS, t = this.listFiles("/").map((c) => `/${c}`), s = this[__private__dont__use].spawnProcess, n = e.cwd();
1779
1797
  e.chdir("/");
1780
- const i = Object.entries(u(this, T)).map(
1798
+ const i = Object.entries(d(this, T)).map(
1781
1799
  ([c, l]) => ({
1782
1800
  mountHandler: l.mountHandler,
1783
1801
  vfsPath: c
1784
1802
  })
1785
1803
  ), o = Object.values(
1786
- u(this, T)
1804
+ d(this, T)
1787
1805
  ).reverse();
1788
1806
  for (const c of o)
1789
1807
  await c.unmount();
@@ -1791,7 +1809,7 @@ class PHP {
1791
1809
  this.exit();
1792
1810
  } catch {
1793
1811
  }
1794
- this.initializeRuntime(r), s && (this[__private__dont__use].spawnProcess = s), u(this, C) && this.setSapiName(u(this, C));
1812
+ this.initializeRuntime(r), s && (this[__private__dont__use].spawnProcess = s), d(this, I) && this.setSapiName(d(this, I));
1795
1813
  const a = this[__private__dont__use].FS;
1796
1814
  for (const c of t)
1797
1815
  c && c !== "/request" && copyMEMFSNodes(e, a, c);
@@ -1826,11 +1844,11 @@ class PHP {
1826
1844
  try {
1827
1845
  await t();
1828
1846
  } finally {
1829
- delete u(this, T)[r];
1847
+ delete d(this, T)[r];
1830
1848
  }
1831
1849
  }
1832
1850
  };
1833
- return u(this, T)[r] = s, () => s.unmount();
1851
+ return d(this, T)[r] = s, () => s.unmount();
1834
1852
  }
1835
1853
  /**
1836
1854
  * Starts a PHP CLI session with given arguments.
@@ -1848,12 +1866,12 @@ class PHP {
1848
1866
  async cli(r, e = {}) {
1849
1867
  if (basename(r[0] ?? "") !== "php")
1850
1868
  return this.subProcess(r, e);
1851
- u(this, R) && (u(this, _).needsRotating = !0);
1869
+ d(this, R) && (d(this, _).needsRotating = !0);
1852
1870
  const t = await this.semaphore.acquire();
1853
- return await m(this, h, z).call(this, () => {
1871
+ return await m(this, f, G).call(this, () => {
1854
1872
  const s = e.env || {};
1855
1873
  for (const [n, i] of Object.entries(s))
1856
- m(this, h, q).call(this, n, i);
1874
+ m(this, f, V).call(this, n, i);
1857
1875
  r = [r[0], "-c", PHP_INI_PATH, ...r.slice(1)];
1858
1876
  for (const n of r)
1859
1877
  this[__private__dont__use].ccall(
@@ -1866,7 +1884,7 @@ class PHP {
1866
1884
  async: !0
1867
1885
  });
1868
1886
  }).then((s) => (s.exitCode.finally(t), s)).finally(() => {
1869
- u(this, _).needsRotating = !0;
1887
+ d(this, _).needsRotating = !0;
1870
1888
  });
1871
1889
  }
1872
1890
  /**
@@ -1948,13 +1966,13 @@ class PHP {
1948
1966
  this[__private__dont__use]._exit(r);
1949
1967
  } catch {
1950
1968
  }
1951
- g(this, R, !1), g(this, b, null), this[__private__dont__use] && (delete this[__private__dont__use].onMessage, delete this[__private__dont__use]);
1969
+ w(this, R, !1), w(this, H, null), this[__private__dont__use] && (delete this[__private__dont__use].onMessage, delete this[__private__dont__use]);
1952
1970
  }
1953
1971
  [Symbol.dispose]() {
1954
1972
  this.exit(0);
1955
1973
  }
1956
1974
  }
1957
- C = new WeakMap(), R = new WeakMap(), b = new WeakMap(), x = new WeakMap(), H = new WeakMap(), T = new WeakMap(), _ = new WeakMap(), h = new WeakSet(), /**
1975
+ I = new WeakMap(), R = new WeakMap(), H = new WeakMap(), F = new WeakMap(), b = new WeakMap(), T = new WeakMap(), _ = new WeakMap(), f = new WeakSet(), /**
1958
1976
  * Prepares the $_SERVER entries for the PHP runtime.
1959
1977
  *
1960
1978
  * @param defaults Default entries to include in $_SERVER.
@@ -1963,7 +1981,7 @@ C = new WeakMap(), R = new WeakMap(), b = new WeakMap(), x = new WeakMap(), H =
1963
1981
  * was provided.
1964
1982
  * @returns Computed $_SERVER entries.
1965
1983
  */
1966
- J = function(r, e, t) {
1984
+ Y = function(r, e, t) {
1967
1985
  const s = {
1968
1986
  ...r || {}
1969
1987
  };
@@ -2055,7 +2073,7 @@ J = function(r, e, t) {
2055
2073
  [NUMBER],
2056
2074
  [t]
2057
2075
  ), s;
2058
- }, $ = function(r) {
2076
+ }, z = function(r) {
2059
2077
  this[__private__dont__use].ccall(
2060
2078
  "wasm_set_path_translated",
2061
2079
  null,
@@ -2069,87 +2087,87 @@ J = function(r, e, t) {
2069
2087
  [STRING, STRING],
2070
2088
  [r, e]
2071
2089
  );
2072
- }, q = function(r, e) {
2090
+ }, V = function(r, e) {
2073
2091
  this[__private__dont__use].ccall(
2074
2092
  "wasm_add_ENV_entry",
2075
2093
  null,
2076
2094
  [STRING, STRING],
2077
2095
  [r, e]
2078
2096
  );
2079
- }, z = async function(r) {
2080
- u(this, _).enabled && u(this, _).needsRotating && await this.rotateRuntime(), ++u(this, _).requestsMade, u(this, _).requestsMade >= u(this, _).maxRequests && (u(this, _).needsRotating = !0);
2097
+ }, G = async function(r) {
2098
+ d(this, _).enabled && d(this, _).needsRotating && await this.rotateRuntime(), ++d(this, _).requestsMade, d(this, _).requestsMade >= d(this, _).maxRequests && (d(this, _).needsRotating = !0);
2081
2099
  const e = this[__private__dont__use], t = await createInvertedReadableStream();
2082
- e.onHeaders = (p) => {
2083
- a || s || t.controller.enqueue(p.slice());
2100
+ e.onHeaders = (h) => {
2101
+ a || s || t.controller.enqueue(h.slice());
2084
2102
  };
2085
2103
  let s = !1;
2086
2104
  const n = () => {
2087
2105
  s || (s = !0, t.controller.close());
2088
2106
  }, i = await createInvertedReadableStream();
2089
- e.onStdout = (p) => {
2090
- n(), !a && i.controller.enqueue(p.slice());
2107
+ e.onStdout = (h) => {
2108
+ n(), !a && i.controller.enqueue(h.slice());
2091
2109
  };
2092
2110
  const o = await createInvertedReadableStream();
2093
- e.onStderr = (p) => {
2094
- a || o.controller.enqueue(p.slice());
2111
+ e.onStderr = (h) => {
2112
+ a || o.controller.enqueue(h.slice());
2095
2113
  };
2096
2114
  let a = !1, c;
2097
- const d = (async () => {
2098
- var p;
2115
+ const u = (async () => {
2116
+ var h;
2099
2117
  try {
2100
2118
  return await Promise.race([
2101
2119
  r(),
2102
- new Promise((w, F) => {
2103
- var V;
2104
- c = (G) => {
2105
- isExitCode(G.error) || F(G.error);
2106
- }, (V = u(this, b)) == null || V.addEventListener(
2120
+ new Promise((g, S) => {
2121
+ var $;
2122
+ c = (N) => {
2123
+ isExitCode(N.error) || S(N.error);
2124
+ }, ($ = d(this, H)) == null || $.addEventListener(
2107
2125
  "error",
2108
2126
  c,
2109
2127
  { once: !0 }
2110
2128
  );
2111
2129
  })
2112
2130
  ]);
2113
- } catch (f) {
2114
- if (isExitCode(f))
2115
- return f.status;
2116
- safeStreamError$1(i.controller, f), safeStreamError$1(o.controller, f), safeStreamError$1(t.controller, f), a = !0;
2117
- for (const w in this)
2118
- typeof this[w] == "function" && (this[w] = () => {
2131
+ } catch (p) {
2132
+ if (isExitCode(p))
2133
+ return p.status;
2134
+ safeStreamError$1(i.controller, p), safeStreamError$1(o.controller, p), safeStreamError$1(t.controller, p), a = !0;
2135
+ for (const g in this)
2136
+ typeof this[g] == "function" && (this[g] = () => {
2119
2137
  throw new Error(
2120
2138
  "PHP runtime has crashed – see the earlier error for details."
2121
2139
  );
2122
2140
  });
2123
- throw this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify(), f;
2141
+ throw this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify(), p;
2124
2142
  } finally {
2125
- a || (safeStreamClose$1(i.controller), safeStreamClose$1(o.controller), n(), a = !0), (p = u(this, b)) == null || p.removeEventListener(
2143
+ a || (safeStreamClose$1(i.controller), safeStreamClose$1(o.controller), n(), a = !0), (h = d(this, H)) == null || h.removeEventListener(
2126
2144
  "error",
2127
2145
  c
2128
2146
  );
2129
2147
  }
2130
2148
  })().then(
2131
- (p) => (p !== 0 && this.dispatchEvent({
2149
+ (h) => (h !== 0 && this.dispatchEvent({
2132
2150
  type: "request.error",
2133
2151
  error: new Error(
2134
- `PHP.run() failed with exit code ${p}.`
2152
+ `PHP.run() failed with exit code ${h}.`
2135
2153
  ),
2136
2154
  // Distinguish between PHP request and PHP-wasm errors
2137
2155
  source: "php-wasm"
2138
- }), p),
2139
- (p) => {
2140
- const f = p.source ?? "php-wasm";
2156
+ }), h),
2157
+ (h) => {
2158
+ const p = h.source ?? "php-wasm";
2141
2159
  throw this.dispatchEvent({
2142
2160
  type: "request.error",
2143
- error: p,
2144
- source: f
2145
- }), p;
2161
+ error: h,
2162
+ source: p
2163
+ }), h;
2146
2164
  }
2147
2165
  );
2148
2166
  return new StreamedPHPResponse(
2149
2167
  t.stream,
2150
2168
  i.stream,
2151
2169
  o.stream,
2152
- d
2170
+ u
2153
2171
  );
2154
2172
  };
2155
2173
  function normalizeHeaders(r) {
@@ -2640,7 +2658,7 @@ const _default = "application/octet-stream", asx = "video/x-ms-asf", atom = "app
2640
2658
  xspf,
2641
2659
  zip
2642
2660
  };
2643
- var S, I, U, L, M, E, A, k, j, P, ne, B, ie, oe, ae;
2661
+ var x, C, j, L, M, E, A, k, D, P, ne, B, ie, oe, ae;
2644
2662
  class PHPRequestHandler {
2645
2663
  /**
2646
2664
  * The request handler needs to decide whether to serve a static asset or
@@ -2655,23 +2673,23 @@ class PHPRequestHandler {
2655
2673
  */
2656
2674
  constructor(e) {
2657
2675
  y(this, P);
2658
- y(this, S);
2659
- y(this, I);
2660
- y(this, U);
2676
+ y(this, x);
2677
+ y(this, C);
2678
+ y(this, j);
2661
2679
  y(this, L);
2662
2680
  y(this, M);
2663
2681
  y(this, E);
2664
2682
  y(this, A);
2665
2683
  y(this, k);
2666
- y(this, j);
2684
+ y(this, D);
2667
2685
  const {
2668
2686
  documentRoot: t = "/www/",
2669
2687
  absoluteUrl: s = typeof location == "object" ? location.href : DEFAULT_BASE_URL,
2670
2688
  rewriteRules: n = [],
2671
2689
  pathAliases: i = [],
2672
2690
  getFileNotFoundAction: o = () => ({ type: "404" })
2673
- } = e, a = (d) => {
2674
- d.isDir(t) || d.mkdir(t), d.chdir(t), d.requestHandler = this;
2691
+ } = e, a = (u) => {
2692
+ u.isDir(t) || u.mkdir(t), u.chdir(t), u.requestHandler = this;
2675
2693
  };
2676
2694
  if (e.php)
2677
2695
  a(e.php), this.instanceManager = new SinglePHPInstanceManager({
@@ -2679,12 +2697,12 @@ class PHPRequestHandler {
2679
2697
  });
2680
2698
  else if (e.phpFactory)
2681
2699
  this.instanceManager = new PHPProcessManager({
2682
- phpFactory: async (d) => {
2683
- const p = await e.phpFactory({
2684
- ...d,
2700
+ phpFactory: async (u) => {
2701
+ const h = await e.phpFactory({
2702
+ ...u,
2685
2703
  requestHandler: this
2686
2704
  });
2687
- return a(p), p;
2705
+ return a(h), h;
2688
2706
  },
2689
2707
  maxPhpInstances: e.maxPhpInstances
2690
2708
  });
@@ -2692,18 +2710,18 @@ class PHPRequestHandler {
2692
2710
  throw new Error(
2693
2711
  "Either php or phpFactory must be provided in the configuration."
2694
2712
  );
2695
- g(this, k, e.cookieStore === void 0 ? new HttpCookieStore() : e.cookieStore), g(this, S, t);
2713
+ w(this, k, e.cookieStore === void 0 ? new HttpCookieStore() : e.cookieStore), w(this, x, t);
2696
2714
  const c = new URL(s);
2697
- g(this, U, c.hostname), g(this, L, c.port ? Number(c.port) : c.protocol === "https:" ? 443 : 80), g(this, I, (c.protocol || "").replace(":", ""));
2698
- const l = u(this, L) !== 443 && u(this, L) !== 80;
2699
- g(this, M, [
2700
- u(this, U),
2701
- l ? `:${u(this, L)}` : ""
2702
- ].join("")), g(this, E, c.pathname.replace(/\/+$/, "")), g(this, A, [
2703
- `${u(this, I)}://`,
2704
- u(this, M),
2705
- u(this, E)
2706
- ].join("")), this.rewriteRules = n, g(this, j, i), this.getFileNotFoundAction = o;
2715
+ w(this, j, c.hostname), w(this, L, c.port ? Number(c.port) : c.protocol === "https:" ? 443 : 80), w(this, C, (c.protocol || "").replace(":", ""));
2716
+ const l = d(this, L) !== 443 && d(this, L) !== 80;
2717
+ w(this, M, [
2718
+ d(this, j),
2719
+ l ? `:${d(this, L)}` : ""
2720
+ ].join("")), w(this, E, c.pathname.replace(/\/+$/, "")), w(this, A, [
2721
+ `${d(this, C)}://`,
2722
+ d(this, M),
2723
+ d(this, E)
2724
+ ].join("")), this.rewriteRules = n, w(this, D, i), this.getFileNotFoundAction = o;
2707
2725
  }
2708
2726
  async getPrimaryPhp() {
2709
2727
  return await this.instanceManager.getPrimaryPhp();
@@ -2727,20 +2745,20 @@ class PHPRequestHandler {
2727
2745
  */
2728
2746
  internalUrlToPath(e) {
2729
2747
  const t = new URL(e, "https://playground.internal");
2730
- return t.pathname.startsWith(u(this, E)) && (t.pathname = t.pathname.slice(u(this, E).length)), toRelativeUrl(t);
2748
+ return t.pathname.startsWith(d(this, E)) && (t.pathname = t.pathname.slice(d(this, E).length)), toRelativeUrl(t);
2731
2749
  }
2732
2750
  /**
2733
2751
  * The absolute URL of this PHPRequestHandler instance.
2734
2752
  */
2735
2753
  get absoluteUrl() {
2736
- return u(this, A);
2754
+ return d(this, A);
2737
2755
  }
2738
2756
  /**
2739
2757
  * The directory in the PHP filesystem where the server will look
2740
2758
  * for the files to serve. Default: `/var/www`.
2741
2759
  */
2742
2760
  get documentRoot() {
2743
- return u(this, S);
2761
+ return d(this, x);
2744
2762
  }
2745
2763
  /**
2746
2764
  * Serves the request – either by serving a static file, or by
@@ -2822,7 +2840,7 @@ class PHPRequestHandler {
2822
2840
  * before using it as a filesystem path.
2823
2841
  */
2824
2842
  decodeURIComponent(n.pathname),
2825
- u(this, E)
2843
+ d(this, E)
2826
2844
  );
2827
2845
  let a = m(this, P, B).call(this, o);
2828
2846
  if (i.isDir(a)) {
@@ -2867,7 +2885,7 @@ class PHPRequestHandler {
2867
2885
  c.response
2868
2886
  );
2869
2887
  case "internal-redirect":
2870
- a = joinPaths(u(this, S), c.uri);
2888
+ a = joinPaths(d(this, x), c.uri);
2871
2889
  break;
2872
2890
  case "404":
2873
2891
  return StreamedPHPResponse.forHttpCode(404);
@@ -2972,11 +2990,11 @@ class PHPRequestHandler {
2972
2990
  prepare_$_SERVER_superglobal(e, t, s) {
2973
2991
  const n = {
2974
2992
  REMOTE_ADDR: "127.0.0.1",
2975
- DOCUMENT_ROOT: u(this, S),
2976
- HTTPS: u(this, A).startsWith("https://") ? "on" : ""
2993
+ DOCUMENT_ROOT: d(this, x),
2994
+ HTTPS: d(this, A).startsWith("https://") ? "on" : ""
2977
2995
  };
2978
- return n.REQUEST_URI = e.pathname + e.search, s.startsWith(u(this, S)) && (n.SCRIPT_NAME = s.substring(
2979
- u(this, S).length
2996
+ return n.REQUEST_URI = e.pathname + e.search, s.startsWith(d(this, x)) && (n.SCRIPT_NAME = s.substring(
2997
+ d(this, x).length
2980
2998
  ), n.PHP_SELF = t.pathname, n.REQUEST_URI.startsWith(n.SCRIPT_NAME) && (n.PATH_INFO = n.REQUEST_URI.substring(
2981
2999
  n.SCRIPT_NAME.length
2982
3000
  ), n.PATH_INFO.includes("?") && (n.PATH_INFO = n.PATH_INFO.substring(
@@ -2988,7 +3006,7 @@ class PHPRequestHandler {
2988
3006
  await this.instanceManager[Symbol.asyncDispose]();
2989
3007
  }
2990
3008
  }
2991
- S = new WeakMap(), I = new WeakMap(), U = new WeakMap(), L = new WeakMap(), M = new WeakMap(), E = new WeakMap(), A = new WeakMap(), k = new WeakMap(), j = new WeakMap(), P = new WeakSet(), /**
3009
+ x = new WeakMap(), C = new WeakMap(), j = new WeakMap(), L = new WeakMap(), M = new WeakMap(), E = new WeakMap(), A = new WeakMap(), k = new WeakMap(), D = new WeakMap(), P = new WeakSet(), /**
2992
3010
  * Apply the rewrite rules to the original request URL.
2993
3011
  *
2994
3012
  * @param originalRequestUrl - The original request URL.
@@ -2997,12 +3015,12 @@ S = new WeakMap(), I = new WeakMap(), U = new WeakMap(), L = new WeakMap(), M =
2997
3015
  ne = function(e) {
2998
3016
  const t = removePathPrefix(
2999
3017
  decodeURIComponent(e.pathname),
3000
- u(this, E)
3018
+ d(this, E)
3001
3019
  ), s = applyRewriteRules(
3002
3020
  t,
3003
3021
  this.rewriteRules
3004
3022
  ), n = new URL(
3005
- joinPaths(u(this, E), s),
3023
+ joinPaths(d(this, E), s),
3006
3024
  e.toString()
3007
3025
  );
3008
3026
  for (const [i, o] of e.searchParams.entries())
@@ -3018,12 +3036,12 @@ ne = function(e) {
3018
3036
  * @returns The resolved filesystem path
3019
3037
  */
3020
3038
  B = function(e) {
3021
- for (const t of u(this, j))
3039
+ for (const t of d(this, D))
3022
3040
  if (e === t.urlPrefix || e.startsWith(t.urlPrefix + "/")) {
3023
3041
  const s = e.slice(t.urlPrefix.length);
3024
3042
  return joinPaths(t.fsPath, s);
3025
3043
  }
3026
- return joinPaths(u(this, S), e);
3044
+ return joinPaths(d(this, x), e);
3027
3045
  }, /**
3028
3046
  * Serves a static file from the PHP filesystem.
3029
3047
  *
@@ -3064,22 +3082,22 @@ ie = function(e, t) {
3064
3082
  }, ae = async function(e, t, s, n, i) {
3065
3083
  let o = "GET";
3066
3084
  const a = {
3067
- host: u(this, M),
3085
+ host: d(this, M),
3068
3086
  ...normalizeHeaders(t.headers || {})
3069
3087
  };
3070
- u(this, k) && (a.cookie = u(this, k).getCookieRequestHeader());
3088
+ d(this, k) && (a.cookie = d(this, k).getCookieRequestHeader());
3071
3089
  let c = t.body;
3072
3090
  if (typeof c == "object" && !(c instanceof Uint8Array)) {
3073
3091
  o = "POST";
3074
- const { bytes: d, contentType: p } = await encodeAsMultipart(c);
3075
- c = d, a["content-type"] = p;
3092
+ const { bytes: u, contentType: h } = await encodeAsMultipart(c);
3093
+ c = u, a["content-type"] = h;
3076
3094
  }
3077
3095
  const l = await e.runStream({
3078
3096
  relativeUri: ensurePathPrefix(
3079
3097
  toRelativeUrl(new URL(n.toString())),
3080
- u(this, E)
3098
+ d(this, E)
3081
3099
  ),
3082
- protocol: u(this, I),
3100
+ protocol: d(this, C),
3083
3101
  method: t.method || o,
3084
3102
  $_SERVER: this.prepare_$_SERVER_superglobal(
3085
3103
  s,
@@ -3090,10 +3108,10 @@ ie = function(e, t) {
3090
3108
  scriptPath: i,
3091
3109
  headers: a
3092
3110
  });
3093
- if (u(this, k)) {
3094
- const d = await l.headers;
3095
- u(this, k).rememberCookiesFromResponseHeaders(
3096
- d
3111
+ if (d(this, k)) {
3112
+ const u = await l.headers;
3113
+ d(this, k).rememberCookiesFromResponseHeaders(
3114
+ u
3097
3115
  );
3098
3116
  }
3099
3117
  return l;
@@ -3134,6 +3152,200 @@ async function writeFiles(r, e, t, { rmRoot: s = !1 } = {}) {
3134
3152
  await r.fileExists(dirname(o)) || await r.mkdir(dirname(o)), i instanceof Uint8Array || typeof i == "string" ? await r.writeFile(o, i) : await writeFiles(r, o, i);
3135
3153
  }
3136
3154
  }
3155
+ const PHP_EXTENSIONS_DIR = "/internal/shared/extensions";
3156
+ async function resolvePHPExtension(r) {
3157
+ const e = await resolvePHPExtensionSource(
3158
+ r,
3159
+ r.fetch ?? globalThis.fetch
3160
+ );
3161
+ return buildResolvedPHPExtension({
3162
+ name: r.name ?? e.name,
3163
+ soBytes: e.soBytes,
3164
+ loadWithIniDirective: r.loadWithIniDirective,
3165
+ iniEntries: r.iniEntries,
3166
+ extraFiles: r.extraFiles,
3167
+ env: r.env,
3168
+ extensionDir: r.extensionDir
3169
+ });
3170
+ }
3171
+ function withResolvedPHPExtensions(r, e) {
3172
+ if (!e.length)
3173
+ return r;
3174
+ const t = {
3175
+ ...r.ENV
3176
+ };
3177
+ for (const s of e) {
3178
+ Object.assign(t, s.env);
3179
+ const n = t.PHP_INI_SCAN_DIR, i = n ? n.split(":") : [];
3180
+ t.PHP_INI_SCAN_DIR = !n || !i.includes(s.extensionDir) ? [...i, s.extensionDir].join(":") : n;
3181
+ }
3182
+ return {
3183
+ ...r,
3184
+ ENV: t,
3185
+ onRuntimeInitialized: (s) => {
3186
+ var n;
3187
+ (n = r.onRuntimeInitialized) == null || n.call(r, s);
3188
+ for (const i of e)
3189
+ installPHPExtensionFilesSync(s.FS, i);
3190
+ }
3191
+ };
3192
+ }
3193
+ function buildResolvedPHPExtension(r) {
3194
+ const e = r.extensionDir ?? PHP_EXTENSIONS_DIR, t = r.name;
3195
+ if (!/^[a-zA-Z0-9_-]+$/.test(t))
3196
+ throw new Error(
3197
+ `Invalid PHP extension name ${JSON.stringify(
3198
+ t
3199
+ )}. Extension names are used to build VFS file names and ini paths, so they may only contain [a-zA-Z0-9_-].`
3200
+ );
3201
+ const s = r.loadWithIniDirective ?? "extension", n = joinPaths(e, `${t}.so`), i = joinPaths(e, `${t}.ini`), o = [
3202
+ `${s}=${n}`,
3203
+ ...Object.entries(r.iniEntries ?? {}).map(
3204
+ ([c, l]) => `${c}=${l}`
3205
+ )
3206
+ ].join(`
3207
+ `), a = r.extraFiles ? {
3208
+ ...r.extraFiles,
3209
+ targetPath: r.extraFiles.targetPath ?? joinPaths(e, `${t}-assets`)
3210
+ } : void 0;
3211
+ return {
3212
+ soPath: n,
3213
+ soBytes: toUint8Array(r.soBytes),
3214
+ iniPath: i,
3215
+ iniContent: o,
3216
+ extraFiles: a,
3217
+ env: r.env,
3218
+ extensionDir: e
3219
+ };
3220
+ }
3221
+ function installPHPExtensionFilesSync(r, e) {
3222
+ const t = "soPath" in e ? e : buildResolvedPHPExtension(e);
3223
+ return FSHelpers.fileExists(r, t.extensionDir) || r.mkdirTree(t.extensionDir), r.writeFile(t.soPath, t.soBytes), r.writeFile(t.iniPath, t.iniContent), t.extraFiles && writeFileTreeSync(
3224
+ r,
3225
+ t.extraFiles.targetPath,
3226
+ t.extraFiles.files
3227
+ ), t;
3228
+ }
3229
+ async function resolvePHPExtensionSource(r, e) {
3230
+ const t = r.source;
3231
+ if (t.format === "so") {
3232
+ const h = r.name ?? t.name;
3233
+ if (!h)
3234
+ throw new Error(
3235
+ "name is required when loading an extension from direct bytes."
3236
+ );
3237
+ return t.sha256 && await assertSha256(t.bytes, t.sha256, h), { name: h, soBytes: toUint8Array(t.bytes) };
3238
+ }
3239
+ if (t.format === "url") {
3240
+ let h;
3241
+ try {
3242
+ h = new URL(String(t.url));
3243
+ } catch {
3244
+ throw new Error(
3245
+ `source.url must be an absolute URL when loading a PHP extension from a direct URL. Received: ${String(
3246
+ t.url
3247
+ )}`
3248
+ );
3249
+ }
3250
+ const p = r.name ?? t.name ?? (() => {
3251
+ const N = h.pathname.split("/").pop() ?? "";
3252
+ return N.endsWith(".so") ? N.slice(0, -3) : void 0;
3253
+ })();
3254
+ if (!p)
3255
+ throw new Error(
3256
+ "name is required when loading an extension from a direct URL."
3257
+ );
3258
+ if (!e)
3259
+ throw new Error(
3260
+ "resolvePHPExtension() requires a fetch implementation."
3261
+ );
3262
+ const g = await e(h);
3263
+ if (!g.ok)
3264
+ throw new Error(
3265
+ `Failed to fetch ${String(h)}: ${g.status}`
3266
+ );
3267
+ const S = new Uint8Array(await g.arrayBuffer());
3268
+ return t.sha256 && await assertSha256(S, t.sha256, String(h)), { name: p, soBytes: S };
3269
+ }
3270
+ const s = "manifestUrl" in t ? new URL(String(t.manifestUrl)) : void 0;
3271
+ let n;
3272
+ if ("manifest" in t)
3273
+ n = t.manifest;
3274
+ else {
3275
+ if (!e)
3276
+ throw new Error(
3277
+ "resolvePHPExtension() requires a fetch implementation."
3278
+ );
3279
+ const h = await e(s);
3280
+ if (!h.ok)
3281
+ throw new Error(
3282
+ `Failed to fetch ${String(s)}: ${h.status}`
3283
+ );
3284
+ n = await h.json();
3285
+ }
3286
+ if (!n || typeof n != "object")
3287
+ throw new Error("Extension manifest must be an object.");
3288
+ const i = n;
3289
+ if (typeof i.name != "string" || !i.name)
3290
+ throw new Error("Extension manifest must include a name.");
3291
+ if (!Array.isArray(i.artifacts))
3292
+ throw new Error("Extension manifest must include an artifacts array.");
3293
+ for (const h of i.artifacts) {
3294
+ if (!h || typeof h.phpVersion != "string" || typeof h.file != "string")
3295
+ throw new Error("Extension manifest contains an invalid artifact.");
3296
+ if ("asyncMode" in h)
3297
+ throw new Error(
3298
+ "Extension manifests do not use asyncMode. External PHP extensions require JSPI."
3299
+ );
3300
+ }
3301
+ const o = "baseUrl" in t && t.baseUrl ? new URL(String(t.baseUrl)) : s, a = i.artifacts.find(
3302
+ (h) => h.phpVersion === r.phpVersion
3303
+ );
3304
+ if (!a)
3305
+ throw new Error(
3306
+ `No extension artifact found for PHP ${r.phpVersion}.`
3307
+ );
3308
+ if (!o)
3309
+ throw new Error(
3310
+ "Manifest artifacts require a manifest URL or baseUrl so relative files can be resolved."
3311
+ );
3312
+ const c = new URL(a.file, o);
3313
+ if (!e)
3314
+ throw new Error(
3315
+ "resolvePHPExtension() requires a fetch implementation."
3316
+ );
3317
+ const l = await e(c);
3318
+ if (!l.ok)
3319
+ throw new Error(
3320
+ `Failed to fetch ${String(c)}: ${l.status}`
3321
+ );
3322
+ const u = new Uint8Array(await l.arrayBuffer());
3323
+ return a.sha256 && await assertSha256(u, a.sha256, a.file), {
3324
+ name: i.name,
3325
+ soBytes: u
3326
+ };
3327
+ }
3328
+ function writeFileTreeSync(r, e, t) {
3329
+ FSHelpers.fileExists(r, e) || r.mkdirTree(e);
3330
+ for (const [s, n] of Object.entries(t)) {
3331
+ const i = joinPaths(e, s), o = dirname(i);
3332
+ FSHelpers.fileExists(r, o) || r.mkdirTree(o), n instanceof Uint8Array || typeof n == "string" ? r.writeFile(i, n) : writeFileTreeSync(r, i, n);
3333
+ }
3334
+ }
3335
+ async function assertSha256(r, e, t) {
3336
+ var o;
3337
+ const s = (o = globalThis.crypto) == null ? void 0 : o.subtle;
3338
+ if (!s)
3339
+ throw new Error(
3340
+ `Cannot verify ${t}: crypto.subtle is not available.`
3341
+ );
3342
+ const n = await s.digest("SHA-256", toUint8Array(r));
3343
+ if (Array.from(new Uint8Array(n)).map((a) => a.toString(16).padStart(2, "0")).join("") !== e)
3344
+ throw new Error(`SHA-256 mismatch for ${t}.`);
3345
+ }
3346
+ function toUint8Array(r) {
3347
+ return r instanceof Uint8Array ? r : new Uint8Array(r);
3348
+ }
3137
3349
  function isLegacyPhpInstance(r) {
3138
3350
  var n;
3139
3351
  const e = Object.getOwnPropertySymbols(r)[0], t = r[e], s = (n = t == null ? void 0 : t.phpVersion) == null ? void 0 : n.major;
@@ -3146,25 +3358,25 @@ function ensureProxyFSHasMmapSupport(r) {
3146
3358
  throw new n.ErrnoError(19);
3147
3359
  if (a !== 0)
3148
3360
  throw new n.ErrnoError(22);
3149
- const d = t.malloc(o);
3150
- if (!d)
3361
+ const u = t.malloc(o);
3362
+ if (!u)
3151
3363
  throw new n.ErrnoError(48);
3152
- const p = t.HEAPU8.subarray(d, d + o);
3153
- let f = 0;
3154
- for (; f < o; ) {
3155
- const w = i.stream_ops.read(
3364
+ const h = t.HEAPU8.subarray(u, u + o);
3365
+ let p = 0;
3366
+ for (; p < o; ) {
3367
+ const g = i.stream_ops.read(
3156
3368
  i,
3369
+ h,
3157
3370
  p,
3158
- f,
3159
- o - f,
3160
- f
3371
+ o - p,
3372
+ p
3161
3373
  );
3162
- if (w <= 0) break;
3163
- f += w;
3374
+ if (g <= 0) break;
3375
+ p += g;
3164
3376
  }
3165
- if (f !== o)
3166
- throw t.free(d), new n.ErrnoError(5);
3167
- return { ptr: d, allocated: !0 };
3377
+ if (p !== o)
3378
+ throw t.free(u), new n.ErrnoError(5);
3379
+ return { ptr: u, allocated: !0 };
3168
3380
  }, s.stream_ops.msync = function(i, o, a, c, l) {
3169
3381
  return l & 2 || i.stream_ops.write(
3170
3382
  i,
@@ -3372,10 +3584,10 @@ class NodeSABSyncReceiveMessageTransport {
3372
3584
  ), Atomics.wait(i, 0, 0, 5e3) === "timed-out")
3373
3585
  throw new Error("Timeout waiting for response");
3374
3586
  for (; ; ) {
3375
- const d = NodeSABSyncReceiveMessageTransport.receiveMessageOnPort(e);
3376
- if (((l = d.message) == null ? void 0 : l.id) === o)
3377
- return d.message;
3378
- if (!d)
3587
+ const u = NodeSABSyncReceiveMessageTransport.receiveMessageOnPort(e);
3588
+ if (((l = u.message) == null ? void 0 : l.id) === o)
3589
+ return u.message;
3590
+ if (!u)
3379
3591
  throw new Error("No response received");
3380
3592
  }
3381
3593
  }
@@ -3453,51 +3665,51 @@ function expose(r, e = globalThis, t = ["*"], s) {
3453
3665
  path: [],
3454
3666
  ...i.data
3455
3667
  }, l = (i.data.argumentList || []).map(fromWireValue);
3456
- let d;
3668
+ let u;
3457
3669
  try {
3458
- const p = c.slice(0, -1).reduce((w, F) => w[F], r), f = c.reduce((w, F) => w[F], r);
3670
+ const h = c.slice(0, -1).reduce((g, S) => g[S], r), p = c.reduce((g, S) => g[S], r);
3459
3671
  switch (a) {
3460
3672
  case MessageType.GET:
3461
- d = f;
3673
+ u = p;
3462
3674
  break;
3463
3675
  case MessageType.SET:
3464
- p[c.slice(-1)[0]] = fromWireValue(
3676
+ h[c.slice(-1)[0]] = fromWireValue(
3465
3677
  i.data.value
3466
- ), d = !0;
3678
+ ), u = !0;
3467
3679
  break;
3468
3680
  case MessageType.APPLY:
3469
- d = f.apply(p, l);
3681
+ u = p.apply(h, l);
3470
3682
  break;
3471
3683
  case MessageType.CONSTRUCT:
3472
3684
  {
3473
- const w = new f(...l);
3474
- d = proxy(w);
3685
+ const g = new p(...l);
3686
+ u = proxy(g);
3475
3687
  }
3476
3688
  break;
3477
3689
  case MessageType.ENDPOINT:
3478
3690
  {
3479
- const { port1: w, port2: F } = new MessageChannel();
3480
- expose(r, F), d = transfer(w, [w]);
3691
+ const { port1: g, port2: S } = new MessageChannel();
3692
+ expose(r, S), u = transfer(g, [g]);
3481
3693
  }
3482
3694
  break;
3483
3695
  case MessageType.RELEASE:
3484
- d = void 0;
3696
+ u = void 0;
3485
3697
  break;
3486
3698
  default:
3487
3699
  return;
3488
3700
  }
3489
- } catch (p) {
3490
- d = { value: p, [throwMarker]: 0 };
3701
+ } catch (h) {
3702
+ u = { value: h, [throwMarker]: 0 };
3491
3703
  }
3492
- Promise.resolve(d).catch((p) => ({ value: p, [throwMarker]: 0 })).then((p) => {
3493
- const [f, w] = toWireValue(p);
3494
- e.postMessage({ ...f, id: o }, w), a === MessageType.RELEASE && (e.removeEventListener("message", n), closeEndPoint(e), finalizer in r && typeof r[finalizer] == "function" && r[finalizer]());
3704
+ Promise.resolve(u).catch((h) => ({ value: h, [throwMarker]: 0 })).then((h) => {
3705
+ const [p, g] = toWireValue(h);
3706
+ e.postMessage({ ...p, id: o }, g), a === MessageType.RELEASE && (e.removeEventListener("message", n), closeEndPoint(e), finalizer in r && typeof r[finalizer] == "function" && r[finalizer]());
3495
3707
  }).catch(() => {
3496
- const [p, f] = toWireValue({
3708
+ const [h, p] = toWireValue({
3497
3709
  value: new TypeError("Unserializable return value"),
3498
3710
  [throwMarker]: 0
3499
3711
  });
3500
- e.postMessage({ ...p, id: o }, f);
3712
+ e.postMessage({ ...h, id: o }, p);
3501
3713
  }).finally(() => {
3502
3714
  s == null || s(i);
3503
3715
  });
@@ -3568,16 +3780,16 @@ function createProxy(r, e, t = [], s = function() {
3568
3780
  },
3569
3781
  set(o, a, c) {
3570
3782
  throwIfProxyReleased(n);
3571
- const [l, d] = toWireValue(c);
3783
+ const [l, u] = toWireValue(c);
3572
3784
  return requestResponseMessage(
3573
3785
  r,
3574
3786
  e,
3575
3787
  {
3576
3788
  type: MessageType.SET,
3577
- path: [...t, a].map((p) => p.toString()),
3789
+ path: [...t, a].map((h) => h.toString()),
3578
3790
  value: l
3579
3791
  },
3580
- d
3792
+ u
3581
3793
  ).then(fromWireValue);
3582
3794
  },
3583
3795
  apply(o, a, c) {
@@ -3589,16 +3801,16 @@ function createProxy(r, e, t = [], s = function() {
3589
3801
  }).then(fromWireValue);
3590
3802
  if (l === "bind")
3591
3803
  return createProxy(r, e, t.slice(0, -1));
3592
- const [d, p] = processArguments(c);
3804
+ const [u, h] = processArguments(c);
3593
3805
  return requestResponseMessage(
3594
3806
  r,
3595
3807
  e,
3596
3808
  {
3597
3809
  type: MessageType.APPLY,
3598
- path: t.map((f) => f.toString()),
3599
- argumentList: d
3810
+ path: t.map((p) => p.toString()),
3811
+ argumentList: u
3600
3812
  },
3601
- p
3813
+ h
3602
3814
  ).then(fromWireValue);
3603
3815
  },
3604
3816
  construct(o, a) {
@@ -3609,7 +3821,7 @@ function createProxy(r, e, t = [], s = function() {
3609
3821
  e,
3610
3822
  {
3611
3823
  type: MessageType.CONSTRUCT,
3612
- path: t.map((d) => d.toString()),
3824
+ path: t.map((u) => u.toString()),
3613
3825
  argumentList: c
3614
3826
  },
3615
3827
  l
@@ -3809,19 +4021,19 @@ const errorProperties = [
3809
4021
  useToJSON: o,
3810
4022
  serialize: a
3811
4023
  });
3812
- for (const [l, d] of Object.entries(r)) {
3813
- if (d && d instanceof Uint8Array && d.constructor.name === "Buffer") {
4024
+ for (const [l, u] of Object.entries(r)) {
4025
+ if (u && u instanceof Uint8Array && u.constructor.name === "Buffer") {
3814
4026
  t[l] = "[object Buffer]";
3815
4027
  continue;
3816
4028
  }
3817
- if (d !== null && typeof d == "object" && typeof d.pipe == "function") {
4029
+ if (u !== null && typeof u == "object" && typeof u.pipe == "function") {
3818
4030
  t[l] = "[object Stream]";
3819
4031
  continue;
3820
4032
  }
3821
- if (typeof d != "function") {
3822
- if (!d || typeof d != "object") {
4033
+ if (typeof u != "function") {
4034
+ if (!u || typeof u != "object") {
3823
4035
  try {
3824
- t[l] = d;
4036
+ t[l] = u;
3825
4037
  } catch {
3826
4038
  }
3827
4039
  continue;
@@ -3834,10 +4046,10 @@ const errorProperties = [
3834
4046
  }
3835
4047
  }
3836
4048
  if (a || t instanceof Error)
3837
- for (const { property: l, enumerable: d } of errorProperties)
4049
+ for (const { property: l, enumerable: u } of errorProperties)
3838
4050
  r[l] !== void 0 && r[l] !== null && Object.defineProperty(t, l, {
3839
4051
  value: isErrorLike(r[l]) || Array.isArray(r[l]) ? c(r[l]) : r[l],
3840
- enumerable: s ? !0 : d,
4052
+ enumerable: s ? !0 : u,
3841
4053
  configurable: !0,
3842
4054
  writable: !0
3843
4055
  });
@@ -4782,18 +4994,25 @@ function createObjectPoolProxy(r) {
4782
4994
  }
4783
4995
  function i(o) {
4784
4996
  return s().then((a) => {
4785
- let c;
4997
+ const c = (u) => {
4998
+ const h = u == null ? void 0 : u.finished;
4999
+ return h && typeof h.then == "function" ? Promise.resolve(h).then(
5000
+ () => n(a),
5001
+ () => n(a)
5002
+ ) : n(a), u;
5003
+ };
5004
+ let l;
4786
5005
  try {
4787
- c = o(a);
4788
- } catch (l) {
4789
- throw n(a), l;
5006
+ l = o(a);
5007
+ } catch (u) {
5008
+ throw n(a), u;
4790
5009
  }
4791
- return c != null && typeof c.then == "function" ? c.then(
4792
- (l) => (n(a), l),
4793
- (l) => {
4794
- throw n(a), l;
5010
+ return l != null && typeof l.then == "function" ? l.then(
5011
+ (u) => c(u),
5012
+ (u) => {
5013
+ throw n(a), u;
4795
5014
  }
4796
- ) : (n(a), c);
5015
+ ) : c(l);
4797
5016
  });
4798
5017
  }
4799
5018
  return new Proxy({}, {
@@ -4803,14 +5022,14 @@ function createObjectPoolProxy(r) {
4803
5022
  if (a !== "then")
4804
5023
  return new Proxy(function() {
4805
5024
  }, {
4806
- apply(c, l, d) {
4807
- return i((p) => p[a](...d));
5025
+ apply(c, l, u) {
5026
+ return i((h) => h[a](...u));
4808
5027
  },
4809
5028
  get(c, l) {
4810
5029
  if (l === "then")
4811
- return (d, p) => i((f) => f[a]).then(
4812
- d,
4813
- p
5030
+ return (u, h) => i((p) => p[a]).then(
5031
+ u,
5032
+ h
4814
5033
  );
4815
5034
  }
4816
5035
  });
@@ -4857,6 +5076,7 @@ export {
4857
5076
  PHPRequestHandler,
4858
5077
  PHPResponse,
4859
5078
  PHPWorker,
5079
+ PHP_EXTENSIONS_DIR,
4860
5080
  ProcessIdAllocator,
4861
5081
  SinglePHPInstanceManager,
4862
5082
  StreamedPHPResponse,
@@ -4874,6 +5094,7 @@ export {
4874
5094
  exposeSyncAPI,
4875
5095
  getPhpIniEntries,
4876
5096
  inferMimeType,
5097
+ installPHPExtensionFilesSync,
4877
5098
  isExitCode,
4878
5099
  isLegacyPHPVersion,
4879
5100
  isPathToSharedFS,
@@ -4887,12 +5108,14 @@ export {
4887
5108
  proxyFileSystem,
4888
5109
  releaseApiProxy,
4889
5110
  removePathPrefix,
5111
+ resolvePHPExtension,
4890
5112
  rotatePHPRuntime,
4891
5113
  sandboxedSpawnHandlerFactory,
4892
5114
  setPhpIniEntries,
4893
5115
  streamToPort,
4894
5116
  toRelativeUrl,
4895
5117
  withPHPIniValues,
5118
+ withResolvedPHPExtensions,
4896
5119
  writeFiles,
4897
5120
  writeFilesStreamToPhp
4898
5121
  };