@php-wasm/universal 1.2.2 → 2.0.0

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,18 @@
1
- var W = (t) => {
1
+ var q = (t) => {
2
2
  throw TypeError(t);
3
3
  };
4
- var q = (t, e, r) => e.has(t) || W("Cannot " + r);
5
- var u = (t, e, r) => (q(t, e, "read from private field"), r ? r.call(t) : e.get(t)), y = (t, e, r) => e.has(t) ? W("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, r), g = (t, e, r, s) => (q(t, e, "write to private field"), s ? s.call(t, r) : e.set(t, r), r), m = (t, e, r) => (q(t, e, "access private method"), r);
4
+ var N = (t, e, r) => e.has(t) || q("Cannot " + r);
5
+ var u = (t, e, r) => (N(t, e, "read from private field"), r ? r.call(t) : e.get(t)), _ = (t, e, r) => e.has(t) ? q("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, r), f = (t, e, r, s) => (N(t, e, "write to private field"), s ? s.call(t, r) : e.set(t, r), r), m = (t, e, r) => (N(t, e, "access private method"), r);
6
6
  import "@php-wasm/node-polyfills";
7
7
  import { logger } from "@php-wasm/logger";
8
8
  import { dirname, joinPaths, Semaphore, createSpawnHandler, normalizePath, AcquireTimeoutError } from "@php-wasm/util";
9
9
  import { parse, stringify } from "ini";
10
10
  import { StreamedFile } from "@php-wasm/stream-compression";
11
+ class ErrnoError extends Error {
12
+ constructor(e, r, s) {
13
+ super(r, s), this.name = "ErrnoError", this.errno = e;
14
+ }
15
+ }
11
16
  const FileErrorCodes = {
12
17
  0: "No error occurred. System call completed successfully.",
13
18
  1: "Argument list too long.",
@@ -101,9 +106,13 @@ function rethrowFileSystemError(t = "") {
101
106
  const i = typeof n == "object" ? n == null ? void 0 : n.errno : null;
102
107
  if (i in FileErrorCodes) {
103
108
  const o = FileErrorCodes[i], a = typeof s[1] == "string" ? s[1] : null, c = a !== null ? t.replaceAll("{path}", a) : t;
104
- throw new Error(`${c}: ${o}`, {
105
- cause: n
106
- });
109
+ throw new ErrnoError(
110
+ i,
111
+ `${c}: ${o}`,
112
+ {
113
+ cause: n
114
+ }
115
+ );
107
116
  }
108
117
  throw n;
109
118
  }
@@ -184,9 +193,12 @@ class FSHelpers {
184
193
  * @param options Options for the removal.
185
194
  */
186
195
  static rmdir(e, r, s = { recursive: !0 }) {
187
- s != null && s.recursive && FSHelpers.listFiles(e, r).forEach((n) => {
188
- const i = `${r}/${n}`;
189
- FSHelpers.isDir(e, i) ? FSHelpers.rmdir(e, i, s) : FSHelpers.unlink(e, i);
196
+ const n = e.lookupPath(r, { follow: !1 });
197
+ if ((n == null ? void 0 : n.node.mount.mountpoint) === r)
198
+ throw new ErrnoError(10);
199
+ s != null && s.recursive && FSHelpers.listFiles(e, r).forEach((i) => {
200
+ const o = `${r}/${i}`;
201
+ FSHelpers.isDir(e, o) ? FSHelpers.rmdir(e, o, s) : FSHelpers.unlink(e, o);
190
202
  }), e.getPath(e.lookupPath(r).node) === e.cwd() && e.chdir(joinPaths(e.cwd(), "..")), e.rmdir(r);
191
203
  }
192
204
  /**
@@ -311,8 +323,7 @@ class FSHelpers {
311
323
  joinPaths(r, o),
312
324
  joinPaths(s, o)
313
325
  );
314
- } else
315
- e.writeFile(s, e.readFile(r));
326
+ } else e.isLink(n.mode) ? e.symlink(e.readlink(r), s) : e.writeFile(s, e.readFile(r));
316
327
  }
317
328
  }
318
329
  FSHelpers.readFileAsText = rethrowFileSystemError('Could not read "{path}"')(
@@ -375,6 +386,16 @@ class PHPWorker {
375
386
  __internal_getPHP() {
376
387
  return _private.get(this).php;
377
388
  }
389
+ /**
390
+ * @internal
391
+ * @deprecated
392
+ * Do not use this method directly in the code consuming
393
+ * the web API. It will change or even be removed without
394
+ * a warning.
395
+ */
396
+ __internal_getRequestHandler() {
397
+ return _private.get(this).requestHandler;
398
+ }
378
399
  async setPrimaryPHP(e) {
379
400
  _private.set(this, {
380
401
  ..._private.get(this),
@@ -747,10 +768,8 @@ function improveWASMErrorReporting(t) {
747
768
  (i = t.lastAsyncifyStackSource) == null ? void 0 : i.stack
748
769
  );
749
770
  if (e.hasListeners()) {
750
- const c = new ErrorEvent("error", {
751
- error: o,
752
- message: a
753
- });
771
+ o.message = a;
772
+ const c = new ErrorEvent("error", { error: o });
754
773
  throw e.dispatchEvent(c), o;
755
774
  }
756
775
  throw (!isExitCode(o) || o.status !== 0) && showCriticalErrorBox(a), o;
@@ -769,7 +788,7 @@ function clarifyErrorMessage(t, e) {
769
788
  e || (r += `
770
789
 
771
790
  This stack trace is lacking. For a better one initialize
772
- the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
791
+ the PHP runtime with debug: true, e.g. loadNodeRuntime('8.1', { emscriptenOptions: { debug: true } }).
773
792
 
774
793
  `);
775
794
  const s = new Set(
@@ -787,7 +806,8 @@ the PHP runtime with { debug: true }, e.g. PHPNode.load('8.1', { debug: true }).
787
806
  for (const i of s)
788
807
  r += ` * ${i}
789
808
  `;
790
- return r;
809
+ return r += `Original error message: ${t.message}
810
+ `, r;
791
811
  }
792
812
  return t.message;
793
813
  }
@@ -851,8 +871,8 @@ class PHPExecutionFailureError extends Error {
851
871
  super(e), this.response = r, this.source = s;
852
872
  }
853
873
  }
854
- const PHP_INI_PATH = "/internal/shared/php.ini", AUTO_PREPEND_SCRIPT = "/internal/shared/auto_prepend_file.php";
855
- var A, P, T, E, F, M, p, B, j, $, V, G, Y, J, K, X, O, Q, z, D;
874
+ const PHP_INI_PATH = "/internal/shared/php.ini", AUTO_PREPEND_SCRIPT = "/internal/shared/auto_prepend_file.php", OPCACHE_FILE_FOLDER = "/internal/shared/opcache";
875
+ var k, E, x, g, v, T, d, z, W, B, $, V, G, J, Y, K, L, X, O, U;
856
876
  class PHP {
857
877
  /**
858
878
  * Initializes a PHP runtime.
@@ -862,14 +882,14 @@ class PHP {
862
882
  * @param requestHandlerOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
863
883
  */
864
884
  constructor(t) {
865
- y(this, p);
866
- y(this, A);
867
- y(this, P, !1);
868
- y(this, T, null);
869
- y(this, E, /* @__PURE__ */ new Map());
870
- y(this, F, []);
871
- y(this, M, {});
872
- this.semaphore = new Semaphore({ concurrency: 1 }), t !== void 0 && this.initializeRuntime(t);
885
+ _(this, d);
886
+ _(this, k);
887
+ _(this, E);
888
+ _(this, x);
889
+ _(this, g);
890
+ _(this, v);
891
+ _(this, T);
892
+ f(this, E, !1), f(this, x, null), f(this, g, /* @__PURE__ */ new Map()), f(this, v, []), f(this, T, {}), this.cliCalled = !1, this.runStreamCalled = !1, this.semaphore = new Semaphore({ concurrency: 1 }), t !== void 0 && this.initializeRuntime(t);
873
893
  }
874
894
  /**
875
895
  * Adds an event listener for a PHP event.
@@ -877,7 +897,7 @@ class PHP {
877
897
  * @param listener - The listener function to be called when the event is triggered.
878
898
  */
879
899
  addEventListener(t, e) {
880
- u(this, E).has(t) || u(this, E).set(t, /* @__PURE__ */ new Set()), u(this, E).get(t).add(e);
900
+ u(this, g).has(t) || u(this, g).set(t, /* @__PURE__ */ new Set()), u(this, g).get(t).add(e);
881
901
  }
882
902
  /**
883
903
  * Removes an event listener for a PHP event.
@@ -886,10 +906,10 @@ class PHP {
886
906
  */
887
907
  removeEventListener(t, e) {
888
908
  var r;
889
- (r = u(this, E).get(t)) == null || r.delete(e);
909
+ (r = u(this, g).get(t)) == null || r.delete(e);
890
910
  }
891
911
  dispatchEvent(t) {
892
- const e = u(this, E).get(t.type);
912
+ const e = u(this, g).get(t.type);
893
913
  if (e)
894
914
  for (const r of e)
895
915
  r(t);
@@ -934,8 +954,8 @@ class PHP {
934
954
  * @param listener Callback function to handle the message.
935
955
  */
936
956
  onMessage(t) {
937
- return u(this, F).push(t), async () => {
938
- g(this, F, u(this, F).filter(
957
+ return u(this, v).push(t), async () => {
958
+ f(this, v, u(this, v).filter(
939
959
  (e) => e !== t
940
960
  ));
941
961
  };
@@ -965,35 +985,53 @@ class PHP {
965
985
  const e = getLoadedRuntime(t);
966
986
  if (!e)
967
987
  throw new Error("Invalid PHP runtime id.");
968
- this[__private__dont__use] = e, this[__private__dont__use].ccall(
988
+ if (this[__private__dont__use] = e, this[__private__dont__use].ccall(
969
989
  "wasm_set_phpini_path",
970
990
  null,
971
991
  ["string"],
972
992
  [PHP_INI_PATH]
973
- ), this.fileExists(PHP_INI_PATH) || this.writeFile(
974
- PHP_INI_PATH,
975
- [
976
- "auto_prepend_file=" + AUTO_PREPEND_SCRIPT,
977
- "memory_limit=256M",
978
- "ignore_repeated_errors = 1",
979
- "error_reporting = E_ALL",
980
- "display_errors = 1",
981
- "html_errors = 1",
982
- "display_startup_errors = On",
983
- "log_errors = 1",
984
- "always_populate_raw_post_data = -1",
985
- "upload_max_filesize = 2000M",
986
- "post_max_size = 2000M",
987
- "allow_url_fopen = On",
988
- "allow_url_include = Off",
989
- "session.save_path = /home/web_user",
990
- "implicit_flush = 1",
991
- "output_buffering = 0",
992
- "max_execution_time = 0",
993
- "max_input_time = -1"
994
- ].join(`
993
+ ), !this.fileExists(PHP_INI_PATH)) {
994
+ const r = [
995
+ // OPCache
996
+ "opcache.enable = 1",
997
+ "opcache.enable_cli = 1",
998
+ "opcache.jit = 0",
999
+ "opcache.interned_strings_buffer = 8",
1000
+ "opcache.max_accelerated_files = 1000",
1001
+ "opcache.memory_consumption = 64",
1002
+ "opcache.max_wasted_percentage = 5",
1003
+ "opcache.file_cache = " + OPCACHE_FILE_FOLDER,
1004
+ // Always enable the file cache.
1005
+ "opcache.file_cache_only = 1",
1006
+ "opcache.file_cache_consistency_checks = 1"
1007
+ ];
1008
+ this.fileExists(OPCACHE_FILE_FOLDER) || this.mkdir(OPCACHE_FILE_FOLDER), this.writeFile(
1009
+ PHP_INI_PATH,
1010
+ [
1011
+ "auto_prepend_file=" + AUTO_PREPEND_SCRIPT,
1012
+ "memory_limit=256M",
1013
+ "ignore_repeated_errors = 1",
1014
+ "error_reporting = E_ALL",
1015
+ "display_errors = 1",
1016
+ "html_errors = 1",
1017
+ "display_startup_errors = On",
1018
+ "log_errors = 1",
1019
+ "always_populate_raw_post_data = -1",
1020
+ "upload_max_filesize = 2000M",
1021
+ "post_max_size = 2000M",
1022
+ "allow_url_fopen = On",
1023
+ "allow_url_include = Off",
1024
+ "session.save_path = /home/web_user",
1025
+ "implicit_flush = 1",
1026
+ "output_buffering = 0",
1027
+ "max_execution_time = 0",
1028
+ "max_input_time = -1",
1029
+ ...r
1030
+ ].join(`
995
1031
  `)
996
- ), this.fileExists(AUTO_PREPEND_SCRIPT) || this.writeFile(
1032
+ );
1033
+ }
1034
+ this.fileExists(AUTO_PREPEND_SCRIPT) || this.writeFile(
997
1035
  AUTO_PREPEND_SCRIPT,
998
1036
  `<?php
999
1037
  // Define constants set via defineConstant() calls
@@ -1011,13 +1049,13 @@ class PHP {
1011
1049
  }
1012
1050
  `
1013
1051
  ), e.onMessage = async (r) => {
1014
- for (const s of u(this, F)) {
1052
+ for (const s of u(this, v)) {
1015
1053
  const n = await s(r);
1016
1054
  if (n)
1017
1055
  return n;
1018
1056
  }
1019
1057
  return "";
1020
- }, g(this, T, improveWASMErrorReporting(e)), this.dispatchEvent({
1058
+ }, f(this, x, improveWASMErrorReporting(e)), this.dispatchEvent({
1021
1059
  type: "runtime.initialized"
1022
1060
  });
1023
1061
  }
@@ -1032,7 +1070,7 @@ class PHP {
1032
1070
  throw new Error(
1033
1071
  "Could not set SAPI name. This can only be done before the PHP WASM module is initialized.Did you already dispatch any requests?"
1034
1072
  );
1035
- g(this, A, t);
1073
+ f(this, k, t);
1036
1074
  }
1037
1075
  /**
1038
1076
  * Changes the current working directory in the PHP filesystem.
@@ -1045,6 +1083,14 @@ class PHP {
1045
1083
  chdir(t) {
1046
1084
  this[__private__dont__use].FS.chdir(t);
1047
1085
  }
1086
+ /**
1087
+ * Changes the permissions of a file or directory.
1088
+ * @param path - The path to the file or directory.
1089
+ * @param mode - The new permissions.
1090
+ */
1091
+ chmod(t, e) {
1092
+ this[__private__dont__use].FS.chmod(t, e);
1093
+ }
1048
1094
  /**
1049
1095
  * Do not use. Use new PHPRequestHandler() instead.
1050
1096
  * @deprecated
@@ -1132,24 +1178,18 @@ class PHP {
1132
1178
  const e = await this.runStream(t), r = await PHPResponse.fromStreamedResponse(
1133
1179
  e
1134
1180
  );
1135
- if (r.exitCode !== 0) {
1136
- logger.warn("PHP.run() output was:", r.text);
1137
- const s = new PHPExecutionFailureError(
1138
- `PHP.run() failed with exit code ${r.exitCode} and the following output: ` + r.errors + `
1181
+ if (r.exitCode !== 0)
1182
+ throw new PHPExecutionFailureError(
1183
+ `PHP.run() failed with exit code ${r.exitCode}.
1139
1184
 
1140
- ` + r.text,
1185
+ === Stdout ===
1186
+ ${r.text}
1187
+
1188
+ === Stderr ===
1189
+ ${r.errors}`,
1141
1190
  r,
1142
1191
  "request"
1143
1192
  );
1144
- throw logger.error(s), this.dispatchEvent({
1145
- type: "request.error",
1146
- error: new Error(
1147
- "PHP.run() failed with exit code " + r.exitCode
1148
- ),
1149
- // Distinguish between PHP request and PHP-wasm errors
1150
- source: "request"
1151
- }), s;
1152
- }
1153
1193
  return r;
1154
1194
  }
1155
1195
  /**
@@ -1244,30 +1284,35 @@ class PHP {
1244
1284
  * @returns A StreamedPHPResponse object.
1245
1285
  */
1246
1286
  async runStream(t) {
1287
+ if (this.cliCalled)
1288
+ throw new Error(
1289
+ "php.runStream() can only be called if php.cli() was not called before. The two methods set a conflicting C-level global state."
1290
+ );
1291
+ this.runStreamCalled = !0;
1247
1292
  const e = await this.semaphore.acquire();
1248
1293
  let r;
1249
- const s = m(this, p, D).call(this, async () => {
1250
- if (u(this, P) || (await m(this, p, j).call(this), g(this, P, !0)), t.scriptPath && !this.fileExists(t.scriptPath))
1294
+ const s = m(this, d, U).call(this, async () => {
1295
+ if (u(this, E) || (await m(this, d, W).call(this), f(this, E, !0)), t.scriptPath && !this.fileExists(t.scriptPath))
1251
1296
  throw new Error(
1252
1297
  `The script path "${t.scriptPath}" does not exist.`
1253
1298
  );
1254
- m(this, p, $).call(this, t.relativeUri || ""), m(this, p, J).call(this, t.method || "GET");
1255
- const n = normalizeHeaders(t.headers || {}), i = n.host || "example.com:443", o = m(this, p, Y).call(this, i, t.protocol || "http");
1256
- if (m(this, p, V).call(this, i), m(this, p, G).call(this, o), m(this, p, K).call(this, n), t.body && (r = m(this, p, X).call(this, t.body)), typeof t.code == "string")
1257
- this.writeFile("/internal/eval.php", t.code), m(this, p, O).call(this, "/internal/eval.php");
1299
+ m(this, d, B).call(this, t.relativeUri || ""), m(this, d, J).call(this, t.method || "GET");
1300
+ const n = normalizeHeaders(t.headers || {}), i = n.host || "example.com:443", o = m(this, d, G).call(this, i, t.protocol || "http");
1301
+ if (m(this, d, $).call(this, i), m(this, d, V).call(this, o), m(this, d, Y).call(this, n), t.body && (r = m(this, d, K).call(this, t.body)), typeof t.code == "string")
1302
+ this.writeFile("/internal/eval.php", t.code), m(this, d, L).call(this, "/internal/eval.php");
1258
1303
  else if (typeof t.scriptPath == "string")
1259
- m(this, p, O).call(this, t.scriptPath || "");
1304
+ m(this, d, L).call(this, t.scriptPath || "");
1260
1305
  else
1261
1306
  throw new TypeError(
1262
1307
  "The request object must have either a `code` or a `scriptPath` property."
1263
1308
  );
1264
- const a = m(this, p, B).call(this, t.$_SERVER, n, o);
1309
+ const a = m(this, d, z).call(this, t.$_SERVER, n, o);
1265
1310
  for (const l in a)
1266
- m(this, p, Q).call(this, l, a[l]);
1311
+ m(this, d, X).call(this, l, a[l]);
1267
1312
  const c = t.env || {};
1268
1313
  for (const l in c)
1269
- m(this, p, z).call(this, l, c[l]);
1270
- return u(this, P) || (await m(this, p, j).call(this), g(this, P, !0)), await this[__private__dont__use].ccall(
1314
+ m(this, d, O).call(this, l, c[l]);
1315
+ return await this[__private__dont__use].ccall(
1271
1316
  "wasm_sapi_handle_request",
1272
1317
  NUMBER,
1273
1318
  [],
@@ -1276,12 +1321,12 @@ class PHP {
1276
1321
  );
1277
1322
  });
1278
1323
  return await s.catch((n) => {
1279
- this.dispatchEvent({
1324
+ throw this.dispatchEvent({
1280
1325
  type: "request.error",
1281
1326
  error: n,
1282
1327
  // Distinguish between PHP request and PHP-wasm errors
1283
1328
  source: n.source ?? "php-wasm"
1284
- });
1329
+ }), n;
1285
1330
  }).finally(() => {
1286
1331
  r && this[__private__dont__use].free(r);
1287
1332
  }).finally(() => {
@@ -1472,13 +1517,13 @@ class PHP {
1472
1517
  */
1473
1518
  async hotSwapPHPRuntime(t, e) {
1474
1519
  const r = this[__private__dont__use].FS, s = [];
1475
- for (const [n, i] of Object.entries(u(this, M)))
1520
+ for (const [n, i] of Object.entries(u(this, T)))
1476
1521
  s.push({ mountHandler: i.mountHandler, vfsPath: n }), await i.unmount();
1477
1522
  try {
1478
1523
  this.exit();
1479
1524
  } catch {
1480
1525
  }
1481
- this.initializeRuntime(t), u(this, A) && this.setSapiName(u(this, A)), copyFS(r, this[__private__dont__use].FS, "/internal"), e && copyFS(r, this[__private__dont__use].FS, e);
1526
+ this.initializeRuntime(t), u(this, k) && this.setSapiName(u(this, k)), copyFS(r, this[__private__dont__use].FS, "/internal"), e && copyFS(r, this[__private__dont__use].FS, e);
1482
1527
  for (const { mountHandler: n, vfsPath: i } of s)
1483
1528
  this.mkdir(i), await this.mount(i, n);
1484
1529
  }
@@ -1497,10 +1542,10 @@ class PHP {
1497
1542
  ), s = {
1498
1543
  mountHandler: e,
1499
1544
  unmount: async () => {
1500
- await r(), delete u(this, M)[t];
1545
+ await r(), delete u(this, T)[t];
1501
1546
  }
1502
1547
  };
1503
- return u(this, M)[t] = s, () => {
1548
+ return u(this, T)[t] = s, () => {
1504
1549
  s.unmount();
1505
1550
  };
1506
1551
  }
@@ -1518,9 +1563,18 @@ class PHP {
1518
1563
  * @returns The exit code of the CLI session.
1519
1564
  */
1520
1565
  async cli(t, e = {}) {
1566
+ if (this.cliCalled)
1567
+ throw new Error(
1568
+ "php.cli() can only be called once. The method sets a C-level global state that does not allow repeated calls."
1569
+ );
1570
+ if (this.runStreamCalled)
1571
+ throw new Error(
1572
+ "php.cli() can only be called if php.runStream() was not called before. The two methods set a conflicting C-level global state."
1573
+ );
1574
+ this.cliCalled = !0;
1521
1575
  const r = await this.semaphore.acquire(), s = e.env || {};
1522
1576
  for (const [n, i] of Object.entries(s))
1523
- m(this, p, z).call(this, n, i);
1577
+ m(this, d, O).call(this, n, i);
1524
1578
  t = [t[0], "-c", PHP_INI_PATH, ...t.slice(1)];
1525
1579
  for (const n of t)
1526
1580
  this[__private__dont__use].ccall(
@@ -1529,15 +1583,9 @@ class PHP {
1529
1583
  [STRING],
1530
1584
  [n]
1531
1585
  );
1532
- return await m(this, p, D).call(this, async () => await this[__private__dont__use].ccall(
1533
- "run_cli",
1534
- null,
1535
- [],
1536
- [],
1537
- {
1538
- async: !0
1539
- }
1540
- )).then((n) => (n.exitCode.finally(r), n));
1586
+ return await m(this, d, U).call(this, () => this[__private__dont__use].ccall("run_cli", null, [], [], {
1587
+ async: !0
1588
+ })).then((n) => (n.exitCode.finally(r), n));
1541
1589
  }
1542
1590
  setSkipShebang(t) {
1543
1591
  this[__private__dont__use].ccall(
@@ -1555,13 +1603,13 @@ class PHP {
1555
1603
  this[__private__dont__use]._exit(t);
1556
1604
  } catch {
1557
1605
  }
1558
- g(this, P, !1), g(this, T, null), this[__private__dont__use] && (delete this[__private__dont__use].onMessage, delete this[__private__dont__use]);
1606
+ f(this, E, !1), f(this, x, null), this[__private__dont__use] && (delete this[__private__dont__use].onMessage, delete this[__private__dont__use]);
1559
1607
  }
1560
1608
  [Symbol.dispose]() {
1561
- u(this, P) && this.exit(0);
1609
+ u(this, E) && this.exit(0);
1562
1610
  }
1563
1611
  }
1564
- A = new WeakMap(), P = new WeakMap(), T = new WeakMap(), E = new WeakMap(), F = new WeakMap(), M = new WeakMap(), p = new WeakSet(), /**
1612
+ k = new WeakMap(), E = new WeakMap(), x = new WeakMap(), g = new WeakMap(), v = new WeakMap(), T = new WeakMap(), d = new WeakSet(), /**
1565
1613
  * Prepares the $_SERVER entries for the PHP runtime.
1566
1614
  *
1567
1615
  * @param defaults Default entries to include in $_SERVER.
@@ -1570,7 +1618,7 @@ A = new WeakMap(), P = new WeakMap(), T = new WeakMap(), E = new WeakMap(), F =
1570
1618
  * was provided.
1571
1619
  * @returns Computed $_SERVER entries.
1572
1620
  */
1573
- B = function(t, e, r) {
1621
+ z = function(t, e, r) {
1574
1622
  const s = {
1575
1623
  ...t || {}
1576
1624
  };
@@ -1580,11 +1628,11 @@ B = function(t, e, r) {
1580
1628
  ["content-type", "content-length"].includes(n.toLowerCase()) && (i = ""), s[`${i}${n.toUpperCase().replace(/-/g, "_")}`] = e[n];
1581
1629
  }
1582
1630
  return s;
1583
- }, j = async function() {
1584
- await this[__private__dont__use].ccall("php_wasm_init", null, [], [], {
1585
- async: !0
1631
+ }, W = function() {
1632
+ return this[__private__dont__use].ccall("php_wasm_init", null, [], [], {
1633
+ isAsync: !0
1586
1634
  });
1587
- }, $ = function(t) {
1635
+ }, B = function(t) {
1588
1636
  this[__private__dont__use].ccall(
1589
1637
  "wasm_set_request_uri",
1590
1638
  null,
@@ -1598,21 +1646,21 @@ B = function(t, e, r) {
1598
1646
  [STRING],
1599
1647
  [e]
1600
1648
  );
1601
- }, V = function(t) {
1649
+ }, $ = function(t) {
1602
1650
  this[__private__dont__use].ccall(
1603
1651
  "wasm_set_request_host",
1604
1652
  null,
1605
1653
  [STRING],
1606
1654
  [t]
1607
1655
  );
1608
- }, G = function(t) {
1656
+ }, V = function(t) {
1609
1657
  this[__private__dont__use].ccall(
1610
1658
  "wasm_set_request_port",
1611
1659
  null,
1612
1660
  [NUMBER],
1613
1661
  [t]
1614
1662
  );
1615
- }, Y = function(t, e) {
1663
+ }, G = function(t, e) {
1616
1664
  let r;
1617
1665
  try {
1618
1666
  r = parseInt(new URL(t).port, 10);
@@ -1626,7 +1674,7 @@ B = function(t, e, r) {
1626
1674
  [STRING],
1627
1675
  [t]
1628
1676
  );
1629
- }, K = function(t) {
1677
+ }, Y = function(t) {
1630
1678
  t.cookie && this[__private__dont__use].ccall(
1631
1679
  "wasm_set_cookies",
1632
1680
  null,
@@ -1643,7 +1691,7 @@ B = function(t, e, r) {
1643
1691
  [NUMBER],
1644
1692
  [parseInt(t["content-length"], 10)]
1645
1693
  );
1646
- }, X = function(t) {
1694
+ }, K = function(t) {
1647
1695
  let e, r;
1648
1696
  typeof t == "string" ? (logger.warn(
1649
1697
  "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"
@@ -1666,80 +1714,73 @@ B = function(t, e, r) {
1666
1714
  [NUMBER],
1667
1715
  [r]
1668
1716
  ), s;
1669
- }, O = function(t) {
1717
+ }, L = function(t) {
1670
1718
  this[__private__dont__use].ccall(
1671
1719
  "wasm_set_path_translated",
1672
1720
  null,
1673
1721
  [STRING],
1674
1722
  [t]
1675
1723
  );
1676
- }, Q = function(t, e) {
1724
+ }, X = function(t, e) {
1677
1725
  this[__private__dont__use].ccall(
1678
1726
  "wasm_add_SERVER_entry",
1679
1727
  null,
1680
1728
  [STRING, STRING],
1681
1729
  [t, e]
1682
1730
  );
1683
- }, z = function(t, e) {
1731
+ }, O = function(t, e) {
1684
1732
  this[__private__dont__use].ccall(
1685
1733
  "wasm_add_ENV_entry",
1686
1734
  null,
1687
1735
  [STRING, STRING],
1688
1736
  [t, e]
1689
1737
  );
1690
- }, D = async function(t) {
1738
+ }, U = async function(t) {
1691
1739
  const e = this[__private__dont__use], r = await createInvertedReadableStream();
1692
- e.onHeaders = (d) => {
1693
- a || s || r.controller.enqueue(d.slice());
1740
+ e.onHeaders = (h) => {
1741
+ a || s || r.controller.enqueue(h.slice());
1694
1742
  };
1695
1743
  let s = !1;
1696
1744
  const n = () => {
1697
1745
  s || (s = !0, r.controller.close());
1698
1746
  }, i = await createInvertedReadableStream();
1699
- e.onStdout = (d) => {
1700
- n(), !a && i.controller.enqueue(d.slice());
1747
+ e.onStdout = (h) => {
1748
+ n(), !a && i.controller.enqueue(h.slice());
1701
1749
  };
1702
1750
  const o = await createInvertedReadableStream();
1703
- e.onStderr = (d) => {
1704
- a || o.controller.enqueue(d.slice());
1751
+ e.onStderr = (h) => {
1752
+ a || o.controller.enqueue(h.slice());
1705
1753
  };
1706
1754
  let a = !1, c;
1707
- const h = (async () => {
1708
- var d;
1755
+ const p = (async () => {
1756
+ var h;
1709
1757
  try {
1710
1758
  return await Promise.race([
1711
1759
  t(),
1712
- new Promise((_, w) => {
1713
- var k;
1714
- c = (v) => {
1715
- if (isExitCode(v.error) && v.error.status === 0)
1716
- _(v.error.status);
1717
- else {
1718
- const U = new Error("Rethrown");
1719
- U.cause = v.error, U.betterMessage = v.message, w(U);
1720
- }
1721
- }, (k = u(this, T)) == null || k.addEventListener(
1760
+ new Promise((w, b) => {
1761
+ var j;
1762
+ c = (D) => {
1763
+ isExitCode(D.error) || b(D.error);
1764
+ }, (j = u(this, x)) == null || j.addEventListener(
1722
1765
  "error",
1723
1766
  c,
1724
1767
  { once: !0 }
1725
1768
  );
1726
1769
  })
1727
1770
  ]);
1728
- } catch (f) {
1729
- if (isExitCode(f))
1730
- return f.status;
1731
- i.controller.error(f), o.controller.error(f), r.controller.error(f), a = !0;
1732
- for (const v in this)
1733
- typeof this[v] == "function" && (this[v] = () => {
1771
+ } catch (y) {
1772
+ if (isExitCode(y))
1773
+ return y.status;
1774
+ i.controller.error(y), o.controller.error(y), r.controller.error(y), a = !0;
1775
+ for (const w in this)
1776
+ typeof this[w] == "function" && (this[w] = () => {
1734
1777
  throw new Error(
1735
1778
  "PHP runtime has crashed – see the earlier error for details."
1736
1779
  );
1737
1780
  });
1738
- this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify();
1739
- const _ = f, w = "betterMessage" in _ ? _.betterMessage : _.message, k = new Error(w);
1740
- throw k.cause = _, logger.error(k), k;
1781
+ throw this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify(), y;
1741
1782
  } finally {
1742
- a || (i.controller.close(), o.controller.close(), n(), a = !0), (d = u(this, T)) == null || d.removeEventListener(
1783
+ a || (i.controller.close(), o.controller.close(), n(), a = !0), (h = u(this, x)) == null || h.removeEventListener(
1743
1784
  "error",
1744
1785
  c
1745
1786
  );
@@ -1749,7 +1790,7 @@ B = function(t, e, r) {
1749
1790
  r.stream,
1750
1791
  i.stream,
1751
1792
  o.stream,
1752
- h
1793
+ p
1753
1794
  );
1754
1795
  };
1755
1796
  function normalizeHeaders(t) {
@@ -1817,6 +1858,58 @@ async function withPHPIniValues(t, e, r) {
1817
1858
  await t.writeFile(PHP_INI_PATH, s);
1818
1859
  }
1819
1860
  }
1861
+ async function printDebugDetails(t, e) {
1862
+ e && printResponseDebugDetails(
1863
+ await PHPResponse.fromStreamedResponse(e)
1864
+ ), await prettyPrintFullStackTrace(t);
1865
+ }
1866
+ async function prettyPrintFullStackTrace(t) {
1867
+ let e = t, r = !0;
1868
+ for (; e; )
1869
+ r || process.stderr.write(`
1870
+ Caused by:
1871
+
1872
+ `), process.stderr.write(e.originalErrorClassName ?? e.name), process.stderr.write(": " + e.message + `
1873
+ `), process.stderr.write(
1874
+ (e.stack + "").split(`
1875
+ `).slice(1).join(`
1876
+ `)
1877
+ ), process.stderr.write(`
1878
+ `), e.response && printResponseDebugDetails(e.response), e.phpLogs && (process.stderr.write(`
1879
+
1880
+ ==== PHP error log ====
1881
+
1882
+ `), process.stderr.write(e.phpLogs)), e = e.cause, r = !1;
1883
+ process.stderr.write(`
1884
+ `);
1885
+ }
1886
+ function printResponseDebugDetails(t) {
1887
+ process.stderr.write(
1888
+ `
1889
+ exitCode=${t.exitCode} httpStatusCode=${t.httpStatusCode} `
1890
+ );
1891
+ const e = t.headers && Object.keys(t.headers).length > 0;
1892
+ e || process.stderr.write("responseHeaders=(empty) "), t.text || process.stderr.write("stdout=(empty) "), t.errors || process.stderr.write("stderr=(empty) "), process.stderr.write(`
1893
+ `), e && process.stderr.write(
1894
+ `
1895
+ ==== PHP response headers ====
1896
+
1897
+ ${JSON.stringify(
1898
+ t.headers,
1899
+ null,
1900
+ 2
1901
+ )}
1902
+
1903
+ `
1904
+ ), t.text && (process.stderr.write(`
1905
+ ==== PHP stdout ====
1906
+
1907
+ `), process.stderr.write(t.text)), t.errors && (process.stderr.write(`
1908
+ ==== PHP stderr ====
1909
+
1910
+ `), process.stderr.write(t.errors)), process.stderr.write(`
1911
+ `);
1912
+ }
1820
1913
  class HttpCookieStore {
1821
1914
  constructor() {
1822
1915
  this.cookies = {};
@@ -1940,7 +2033,7 @@ class PHPProcessManager {
1940
2033
  * and the waiting timeout is exceeded.
1941
2034
  */
1942
2035
  async acquirePHPInstance({
1943
- considerPrimary: e = !0
2036
+ considerPrimary: e = !1
1944
2037
  } = {}) {
1945
2038
  if (this.primaryPhp || await this.getPrimaryPhp(), this.primaryIdle && e)
1946
2039
  return this.primaryIdle = !1, {
@@ -1959,7 +2052,7 @@ class PHPProcessManager {
1959
2052
  * for PHP to spawn.
1960
2053
  */
1961
2054
  spawn(e) {
1962
- if (e.isPrimary && this.primaryPhpPromise && !this.primaryPhp)
2055
+ if (e.isPrimary && this.allInstances.length > 0)
1963
2056
  throw new Error(
1964
2057
  "Requested spawning a primary PHP instance when another primary instance already started spawning."
1965
2058
  );
@@ -2147,7 +2240,7 @@ const _default = "application/octet-stream", asx = "video/x-ms-asf", atom = "app
2147
2240
  xspf,
2148
2241
  zip
2149
2242
  };
2150
- var S, C, L, b, I, x, N, R, H, Z, ee, te;
2243
+ var S, C, M, F, I, P, A, R, H, Q, Z, ee;
2151
2244
  class PHPRequestHandler {
2152
2245
  /**
2153
2246
  * The request handler needs to decide whether to serve a static asset or
@@ -2161,15 +2254,15 @@ class PHPRequestHandler {
2161
2254
  * @param config - Request Handler configuration.
2162
2255
  */
2163
2256
  constructor(e) {
2164
- y(this, H);
2165
- y(this, S);
2166
- y(this, C);
2167
- y(this, L);
2168
- y(this, b);
2169
- y(this, I);
2170
- y(this, x);
2171
- y(this, N);
2172
- y(this, R);
2257
+ _(this, H);
2258
+ _(this, S);
2259
+ _(this, C);
2260
+ _(this, M);
2261
+ _(this, F);
2262
+ _(this, I);
2263
+ _(this, P);
2264
+ _(this, A);
2265
+ _(this, R);
2173
2266
  const {
2174
2267
  documentRoot: r = "/www/",
2175
2268
  absoluteUrl: s = typeof location == "object" ? location.href : DEFAULT_BASE_URL,
@@ -2185,17 +2278,17 @@ class PHPRequestHandler {
2185
2278
  return l.isDir(r) || l.mkdir(r), l.chdir(r), l.requestHandler = this, l;
2186
2279
  },
2187
2280
  maxPhpInstances: e.maxPhpInstances
2188
- }), g(this, R, e.cookieStore === void 0 ? new HttpCookieStore() : e.cookieStore), g(this, S, r);
2281
+ }), f(this, R, e.cookieStore === void 0 ? new HttpCookieStore() : e.cookieStore), f(this, S, r);
2189
2282
  const o = new URL(s);
2190
- g(this, L, o.hostname), g(this, b, o.port ? Number(o.port) : o.protocol === "https:" ? 443 : 80), g(this, C, (o.protocol || "").replace(":", ""));
2191
- const a = u(this, b) !== 443 && u(this, b) !== 80;
2192
- g(this, I, [
2193
- u(this, L),
2194
- a ? `:${u(this, b)}` : ""
2195
- ].join("")), g(this, x, o.pathname.replace(/\/+$/, "")), g(this, N, [
2283
+ f(this, M, o.hostname), f(this, F, o.port ? Number(o.port) : o.protocol === "https:" ? 443 : 80), f(this, C, (o.protocol || "").replace(":", ""));
2284
+ const a = u(this, F) !== 443 && u(this, F) !== 80;
2285
+ f(this, I, [
2286
+ u(this, M),
2287
+ a ? `:${u(this, F)}` : ""
2288
+ ].join("")), f(this, P, o.pathname.replace(/\/+$/, "")), f(this, A, [
2196
2289
  `${u(this, C)}://`,
2197
2290
  u(this, I),
2198
- u(this, x)
2291
+ u(this, P)
2199
2292
  ].join("")), this.rewriteRules = n, this.getFileNotFoundAction = i;
2200
2293
  }
2201
2294
  async getPrimaryPhp() {
@@ -2220,13 +2313,13 @@ class PHPRequestHandler {
2220
2313
  */
2221
2314
  internalUrlToPath(e) {
2222
2315
  const r = new URL(e);
2223
- return r.pathname.startsWith(u(this, x)) && (r.pathname = r.pathname.slice(u(this, x).length)), toRelativeUrl(r);
2316
+ return r.pathname.startsWith(u(this, P)) && (r.pathname = r.pathname.slice(u(this, P).length)), toRelativeUrl(r);
2224
2317
  }
2225
2318
  /**
2226
2319
  * The absolute URL of this PHPRequestHandler instance.
2227
2320
  */
2228
2321
  get absoluteUrl() {
2229
- return u(this, N);
2322
+ return u(this, A);
2230
2323
  }
2231
2324
  /**
2232
2325
  * The directory in the PHP filesystem where the server will look
@@ -2291,7 +2384,7 @@ class PHPRequestHandler {
2291
2384
  ), n = applyRewriteRules(
2292
2385
  removePathPrefix(
2293
2386
  decodeURIComponent(s.pathname),
2294
- u(this, x)
2387
+ u(this, P)
2295
2388
  ),
2296
2389
  this.rewriteRules
2297
2390
  ), i = await this.getPrimaryPhp();
@@ -2336,9 +2429,9 @@ class PHPRequestHandler {
2336
2429
  // Pass along URL with the #fragment filtered out
2337
2430
  url: s.toString()
2338
2431
  };
2339
- return m(this, H, ee).call(this, a, o);
2432
+ return m(this, H, Z).call(this, a, o);
2340
2433
  } else
2341
- return m(this, H, Z).call(this, i, o);
2434
+ return m(this, H, Q).call(this, i, o);
2342
2435
  else
2343
2436
  return PHPResponse.forHttpCode(404);
2344
2437
  }
@@ -2346,13 +2439,13 @@ class PHPRequestHandler {
2346
2439
  await this.processManager[Symbol.asyncDispose]();
2347
2440
  }
2348
2441
  }
2349
- S = new WeakMap(), C = new WeakMap(), L = new WeakMap(), b = new WeakMap(), I = new WeakMap(), x = new WeakMap(), N = new WeakMap(), R = new WeakMap(), H = new WeakSet(), /**
2442
+ S = new WeakMap(), C = new WeakMap(), M = new WeakMap(), F = new WeakMap(), I = new WeakMap(), P = new WeakMap(), A = new WeakMap(), R = new WeakMap(), H = new WeakSet(), /**
2350
2443
  * Serves a static file from the PHP filesystem.
2351
2444
  *
2352
2445
  * @param fsPath - Absolute path of the static file to serve.
2353
2446
  * @returns The response.
2354
2447
  */
2355
- Z = function(e, r) {
2448
+ Q = function(e, r) {
2356
2449
  const s = e.readFileAsBuffer(r);
2357
2450
  return new PHPResponse(
2358
2451
  200,
@@ -2367,7 +2460,7 @@ Z = function(e, r) {
2367
2460
  },
2368
2461
  s
2369
2462
  );
2370
- }, ee = async function(e, r) {
2463
+ }, Z = async function(e, r) {
2371
2464
  let s;
2372
2465
  try {
2373
2466
  s = await this.processManager.acquirePHPInstance({
@@ -2377,11 +2470,11 @@ Z = function(e, r) {
2377
2470
  return n instanceof MaxPhpInstancesError ? PHPResponse.forHttpCode(502) : PHPResponse.forHttpCode(500);
2378
2471
  }
2379
2472
  try {
2380
- return await m(this, H, te).call(this, s.php, e, r);
2473
+ return await m(this, H, ee).call(this, s.php, e, r);
2381
2474
  } finally {
2382
2475
  s.reap();
2383
2476
  }
2384
- }, te = async function(e, r, s) {
2477
+ }, ee = async function(e, r, s) {
2385
2478
  let n = "GET";
2386
2479
  const i = {
2387
2480
  host: u(this, I),
@@ -2398,14 +2491,14 @@ Z = function(e, r) {
2398
2491
  const a = await e.run({
2399
2492
  relativeUri: ensurePathPrefix(
2400
2493
  toRelativeUrl(new URL(r.url)),
2401
- u(this, x)
2494
+ u(this, P)
2402
2495
  ),
2403
2496
  protocol: u(this, C),
2404
2497
  method: r.method || n,
2405
2498
  $_SERVER: {
2406
2499
  REMOTE_ADDR: "127.0.0.1",
2407
2500
  DOCUMENT_ROOT: u(this, S),
2408
- HTTPS: u(this, N).startsWith("https://") ? "on" : ""
2501
+ HTTPS: u(this, A).startsWith("https://") ? "on" : ""
2409
2502
  },
2410
2503
  body: o,
2411
2504
  scriptPath: s,
@@ -2485,6 +2578,56 @@ function proxyFileSystem(t, e, r) {
2485
2578
  n
2486
2579
  );
2487
2580
  }
2581
+ function sandboxedSpawnHandlerFactory(t) {
2582
+ return createSpawnHandler(async function(e, r, s) {
2583
+ r.notifySpawn(), e[0] === "exec" && e.shift(), (e[0].endsWith(".php") || e[0].endsWith(".phar")) && e.unshift("php");
2584
+ const n = e[0].split("/").pop();
2585
+ if (e[0] === "/usr/bin/env" && e[1] === "stty" && e[2] === "size")
2586
+ r.stdout("18 140"), r.exit(0);
2587
+ else if (n === "tput" && e[1] === "cols")
2588
+ r.stdout("140"), r.exit(0);
2589
+ else if (n === "less")
2590
+ r.on("stdin", (i) => {
2591
+ r.stdout(i);
2592
+ }), r.exit(0);
2593
+ else if (n === "php") {
2594
+ const { php: i, reap: o } = await t.acquirePHPInstance({
2595
+ considerPrimary: !1
2596
+ });
2597
+ i.chdir(s.cwd);
2598
+ try {
2599
+ const a = await i.cli(e, {
2600
+ env: {
2601
+ ...s.env,
2602
+ SCRIPT_PATH: e[1],
2603
+ // Set SHELL_PIPE to 0 to ensure WP-CLI formats
2604
+ // the output as ASCII tables.
2605
+ // @see https://github.com/wp-cli/wp-cli/issues/1102
2606
+ SHELL_PIPE: "0"
2607
+ }
2608
+ });
2609
+ a.stdout.pipeTo(
2610
+ new WritableStream({
2611
+ write(c) {
2612
+ r.stdout(c);
2613
+ }
2614
+ })
2615
+ ), a.stderr.pipeTo(
2616
+ new WritableStream({
2617
+ write(c) {
2618
+ r.stderr(c);
2619
+ }
2620
+ })
2621
+ ), r.exit(await a.exitCode);
2622
+ } catch (a) {
2623
+ throw r.exit(1), a;
2624
+ } finally {
2625
+ o();
2626
+ }
2627
+ } else
2628
+ r.exit(1);
2629
+ });
2630
+ }
2488
2631
  function exposeSync(t, e, r, s = ["*"]) {
2489
2632
  return expose(t, e, s, r.afterResponseSent);
2490
2633
  }
@@ -2541,9 +2684,15 @@ function wrapSync(t, e) {
2541
2684
  }
2542
2685
  class NodeSABSyncReceiveMessageTransport {
2543
2686
  static async create() {
2544
- return NodeSABSyncReceiveMessageTransport.receiveMessageOnPort || (NodeSABSyncReceiveMessageTransport.receiveMessageOnPort = await import("./__vite-browser-external-l0sNRNKZ.js").then(
2545
- (e) => e.receiveMessageOnPort
2546
- )), new NodeSABSyncReceiveMessageTransport();
2687
+ if (!NodeSABSyncReceiveMessageTransport.receiveMessageOnPort)
2688
+ try {
2689
+ NodeSABSyncReceiveMessageTransport.receiveMessageOnPort = require("worker_threads").receiveMessageOnPort;
2690
+ } catch {
2691
+ NodeSABSyncReceiveMessageTransport.receiveMessageOnPort = await import("worker_threads").then(
2692
+ (e) => e.receiveMessageOnPort
2693
+ );
2694
+ }
2695
+ return new NodeSABSyncReceiveMessageTransport();
2547
2696
  }
2548
2697
  constructor() {
2549
2698
  }
@@ -2565,10 +2714,10 @@ class NodeSABSyncReceiveMessageTransport {
2565
2714
  ), Atomics.wait(i, 0, 0, 5e3) === "timed-out")
2566
2715
  throw new Error("Timeout waiting for response");
2567
2716
  for (; ; ) {
2568
- const h = NodeSABSyncReceiveMessageTransport.receiveMessageOnPort(e);
2569
- if (((l = h.message) == null ? void 0 : l.id) === o)
2570
- return h.message;
2571
- if (!h)
2717
+ const p = NodeSABSyncReceiveMessageTransport.receiveMessageOnPort(e);
2718
+ if (((l = p.message) == null ? void 0 : l.id) === o)
2719
+ return p.message;
2720
+ if (!p)
2572
2721
  throw new Error("No response received");
2573
2722
  }
2574
2723
  }
@@ -2605,7 +2754,7 @@ const WireValueType = {
2605
2754
  deserialize(t) {
2606
2755
  return t.start(), wrap(t);
2607
2756
  }
2608
- }, throwTransferHandler = {
2757
+ }, throwTransferHandler$1 = {
2609
2758
  canHandle: (t) => isObject(t) && throwMarker in t,
2610
2759
  serialize({ value: t }) {
2611
2760
  let e;
@@ -2626,7 +2775,7 @@ const WireValueType = {
2626
2775
  }
2627
2776
  }, transferHandlers = /* @__PURE__ */ new Map([
2628
2777
  ["proxy", proxyTransferHandler],
2629
- ["throw", throwTransferHandler]
2778
+ ["throw", throwTransferHandler$1]
2630
2779
  ]);
2631
2780
  function isAllowedOrigin(t, e) {
2632
2781
  for (const r of t)
@@ -2646,51 +2795,51 @@ function expose(t, e = globalThis, r = ["*"], s) {
2646
2795
  path: [],
2647
2796
  ...i.data
2648
2797
  }, l = (i.data.argumentList || []).map(fromWireValue);
2649
- let h;
2798
+ let p;
2650
2799
  try {
2651
- const d = c.slice(0, -1).reduce((_, w) => _[w], t), f = c.reduce((_, w) => _[w], t);
2800
+ const h = c.slice(0, -1).reduce((w, b) => w[b], t), y = c.reduce((w, b) => w[b], t);
2652
2801
  switch (a) {
2653
2802
  case MessageType.GET:
2654
- h = f;
2803
+ p = y;
2655
2804
  break;
2656
2805
  case MessageType.SET:
2657
- d[c.slice(-1)[0]] = fromWireValue(
2806
+ h[c.slice(-1)[0]] = fromWireValue(
2658
2807
  i.data.value
2659
- ), h = !0;
2808
+ ), p = !0;
2660
2809
  break;
2661
2810
  case MessageType.APPLY:
2662
- h = f.apply(d, l);
2811
+ p = y.apply(h, l);
2663
2812
  break;
2664
2813
  case MessageType.CONSTRUCT:
2665
2814
  {
2666
- const _ = new f(...l);
2667
- h = proxy(_);
2815
+ const w = new y(...l);
2816
+ p = proxy(w);
2668
2817
  }
2669
2818
  break;
2670
2819
  case MessageType.ENDPOINT:
2671
2820
  {
2672
- const { port1: _, port2: w } = new MessageChannel();
2673
- expose(t, w), h = transfer(_, [_]);
2821
+ const { port1: w, port2: b } = new MessageChannel();
2822
+ expose(t, b), p = transfer(w, [w]);
2674
2823
  }
2675
2824
  break;
2676
2825
  case MessageType.RELEASE:
2677
- h = void 0;
2826
+ p = void 0;
2678
2827
  break;
2679
2828
  default:
2680
2829
  return;
2681
2830
  }
2682
- } catch (d) {
2683
- h = { value: d, [throwMarker]: 0 };
2831
+ } catch (h) {
2832
+ p = { value: h, [throwMarker]: 0 };
2684
2833
  }
2685
- Promise.resolve(h).catch((d) => ({ value: d, [throwMarker]: 0 })).then((d) => {
2686
- const [f, _] = toWireValue(d);
2687
- e.postMessage({ ...f, id: o }, _), a === MessageType.RELEASE && (e.removeEventListener("message", n), closeEndPoint(e), finalizer in t && typeof t[finalizer] == "function" && t[finalizer]());
2834
+ Promise.resolve(p).catch((h) => ({ value: h, [throwMarker]: 0 })).then((h) => {
2835
+ const [y, w] = toWireValue(h);
2836
+ e.postMessage({ ...y, id: o }, w), a === MessageType.RELEASE && (e.removeEventListener("message", n), closeEndPoint(e), finalizer in t && typeof t[finalizer] == "function" && t[finalizer]());
2688
2837
  }).catch(() => {
2689
- const [d, f] = toWireValue({
2838
+ const [h, y] = toWireValue({
2690
2839
  value: new TypeError("Unserializable return value"),
2691
2840
  [throwMarker]: 0
2692
2841
  });
2693
- e.postMessage({ ...d, id: o }, f);
2842
+ e.postMessage({ ...h, id: o }, y);
2694
2843
  }).finally(() => {
2695
2844
  s == null || s(i);
2696
2845
  });
@@ -2761,16 +2910,16 @@ function createProxy(t, e, r = [], s = function() {
2761
2910
  },
2762
2911
  set(o, a, c) {
2763
2912
  throwIfProxyReleased(n);
2764
- const [l, h] = toWireValue(c);
2913
+ const [l, p] = toWireValue(c);
2765
2914
  return requestResponseMessage(
2766
2915
  t,
2767
2916
  e,
2768
2917
  {
2769
2918
  type: MessageType.SET,
2770
- path: [...r, a].map((d) => d.toString()),
2919
+ path: [...r, a].map((h) => h.toString()),
2771
2920
  value: l
2772
2921
  },
2773
- h
2922
+ p
2774
2923
  ).then(fromWireValue);
2775
2924
  },
2776
2925
  apply(o, a, c) {
@@ -2782,16 +2931,16 @@ function createProxy(t, e, r = [], s = function() {
2782
2931
  }).then(fromWireValue);
2783
2932
  if (l === "bind")
2784
2933
  return createProxy(t, e, r.slice(0, -1));
2785
- const [h, d] = processArguments(c);
2934
+ const [p, h] = processArguments(c);
2786
2935
  return requestResponseMessage(
2787
2936
  t,
2788
2937
  e,
2789
2938
  {
2790
2939
  type: MessageType.APPLY,
2791
- path: r.map((f) => f.toString()),
2792
- argumentList: h
2940
+ path: r.map((y) => y.toString()),
2941
+ argumentList: p
2793
2942
  },
2794
- d
2943
+ h
2795
2944
  ).then(fromWireValue);
2796
2945
  },
2797
2946
  construct(o, a) {
@@ -2802,7 +2951,7 @@ function createProxy(t, e, r = [], s = function() {
2802
2951
  e,
2803
2952
  {
2804
2953
  type: MessageType.CONSTRUCT,
2805
- path: r.map((h) => h.toString()),
2954
+ path: r.map((p) => p.toString()),
2806
2955
  argumentList: c
2807
2956
  },
2808
2957
  l
@@ -2889,6 +3038,153 @@ function nodeEndpoint(t) {
2889
3038
  start: t.start && t.start.bind(t)
2890
3039
  };
2891
3040
  }
3041
+ const list = [
3042
+ // Native ES errors https://262.ecma-international.org/12.0/#sec-well-known-intrinsic-objects
3043
+ Error,
3044
+ EvalError,
3045
+ RangeError,
3046
+ ReferenceError,
3047
+ SyntaxError,
3048
+ TypeError,
3049
+ URIError,
3050
+ AggregateError,
3051
+ // Built-in errors
3052
+ globalThis.DOMException,
3053
+ // Node-specific errors
3054
+ // https://nodejs.org/api/errors.html
3055
+ globalThis.AssertionError,
3056
+ globalThis.SystemError
3057
+ ].filter(Boolean).map((t) => [t.name, t]), errorConstructors = new Map(list);
3058
+ class NonError extends Error {
3059
+ constructor(e) {
3060
+ super(NonError._prepareSuperMessage(e)), this.name = "NonError";
3061
+ }
3062
+ static _prepareSuperMessage(e) {
3063
+ try {
3064
+ return JSON.stringify(e);
3065
+ } catch {
3066
+ return String(e);
3067
+ }
3068
+ }
3069
+ }
3070
+ const errorProperties = [
3071
+ {
3072
+ property: "name",
3073
+ enumerable: !1
3074
+ },
3075
+ {
3076
+ property: "message",
3077
+ enumerable: !1
3078
+ },
3079
+ {
3080
+ property: "stack",
3081
+ enumerable: !1
3082
+ },
3083
+ {
3084
+ property: "code",
3085
+ enumerable: !0
3086
+ },
3087
+ {
3088
+ property: "cause",
3089
+ enumerable: !1
3090
+ },
3091
+ {
3092
+ property: "errors",
3093
+ enumerable: !1
3094
+ }
3095
+ ], toJsonWasCalled = /* @__PURE__ */ new WeakSet(), toJSON = (t) => {
3096
+ toJsonWasCalled.add(t);
3097
+ const e = t.toJSON();
3098
+ return toJsonWasCalled.delete(t), e;
3099
+ }, newError = (t) => {
3100
+ const e = errorConstructors.get(t) ?? Error;
3101
+ return e === AggregateError ? new e([]) : new e();
3102
+ }, destroyCircular = ({
3103
+ from: t,
3104
+ seen: e,
3105
+ to: r,
3106
+ forceEnumerable: s,
3107
+ maxDepth: n,
3108
+ depth: i,
3109
+ useToJSON: o,
3110
+ serialize: a
3111
+ }) => {
3112
+ if (r || (Array.isArray(t) ? r = [] : !a && isErrorLike(t) ? r = newError(t.name) : r = {}), e.push(t), i >= n)
3113
+ return r;
3114
+ if (o && typeof t.toJSON == "function" && !toJsonWasCalled.has(t))
3115
+ return toJSON(t);
3116
+ const c = (l) => destroyCircular({
3117
+ from: l,
3118
+ seen: [...e],
3119
+ forceEnumerable: s,
3120
+ maxDepth: n,
3121
+ depth: i,
3122
+ useToJSON: o,
3123
+ serialize: a
3124
+ });
3125
+ for (const [l, p] of Object.entries(t)) {
3126
+ if (p && p instanceof Uint8Array && p.constructor.name === "Buffer") {
3127
+ r[l] = "[object Buffer]";
3128
+ continue;
3129
+ }
3130
+ if (p !== null && typeof p == "object" && typeof p.pipe == "function") {
3131
+ r[l] = "[object Stream]";
3132
+ continue;
3133
+ }
3134
+ if (typeof p != "function") {
3135
+ if (!p || typeof p != "object") {
3136
+ try {
3137
+ r[l] = p;
3138
+ } catch {
3139
+ }
3140
+ continue;
3141
+ }
3142
+ if (!e.includes(t[l])) {
3143
+ i++, r[l] = c(t[l]);
3144
+ continue;
3145
+ }
3146
+ r[l] = "[Circular]";
3147
+ }
3148
+ }
3149
+ if (a || r instanceof Error)
3150
+ for (const { property: l, enumerable: p } of errorProperties)
3151
+ t[l] !== void 0 && t[l] !== null && Object.defineProperty(r, l, {
3152
+ value: isErrorLike(t[l]) || Array.isArray(t[l]) ? c(t[l]) : t[l],
3153
+ enumerable: s ? !0 : p,
3154
+ configurable: !0,
3155
+ writable: !0
3156
+ });
3157
+ return r;
3158
+ };
3159
+ function serializeError(t, e = {}) {
3160
+ const { maxDepth: r = Number.POSITIVE_INFINITY, useToJSON: s = !0 } = e;
3161
+ return typeof t == "object" && t !== null ? destroyCircular({
3162
+ from: t,
3163
+ seen: [],
3164
+ forceEnumerable: !0,
3165
+ maxDepth: r,
3166
+ depth: 0,
3167
+ useToJSON: s,
3168
+ serialize: !0
3169
+ }) : typeof t == "function" ? `[Function: ${t.name || "anonymous"}]` : t;
3170
+ }
3171
+ function deserializeError(t, e = {}) {
3172
+ const { maxDepth: r = Number.POSITIVE_INFINITY } = e;
3173
+ return t instanceof Error ? t : isMinimumViableSerializedError(t) ? destroyCircular({
3174
+ from: t,
3175
+ seen: [],
3176
+ to: newError(t.name),
3177
+ maxDepth: r,
3178
+ depth: 0,
3179
+ serialize: !1
3180
+ }) : new NonError(t);
3181
+ }
3182
+ function isErrorLike(t) {
3183
+ return !!t && typeof t == "object" && typeof t.name == "string" && typeof t.message == "string" && typeof t.stack == "string";
3184
+ }
3185
+ function isMinimumViableSerializedError(t) {
3186
+ return !!t && typeof t == "object" && typeof t.message == "string" && !Array.isArray(t);
3187
+ }
2892
3188
  async function consumeAPISync(t) {
2893
3189
  setupTransferHandlers();
2894
3190
  const e = await NodeSABSyncReceiveMessageTransport.create();
@@ -2985,6 +3281,28 @@ function setupTransferHandlers() {
2985
3281
  return r.response && (s[0].value.response = r.response), r.source && (s[0].value.source = r.source), s;
2986
3282
  };
2987
3283
  }
3284
+ const throwTransferHandler = transferHandlers.get(
3285
+ "throw"
3286
+ ), throwTransferHandlerCustom = {
3287
+ canHandle: throwTransferHandler.canHandle,
3288
+ serialize: ({ value: t }) => {
3289
+ let e;
3290
+ return t instanceof Error ? (e = {
3291
+ isError: !0,
3292
+ value: serializeError(t)
3293
+ }, e.value.originalErrorClassName = t.constructor.name) : e = { isError: !1, value: t }, [e, []];
3294
+ },
3295
+ deserialize: (t) => {
3296
+ if (t.isError) {
3297
+ const e = deserializeError(t.value);
3298
+ throw new Error("Comlink method call failed", {
3299
+ cause: e
3300
+ });
3301
+ }
3302
+ throw t.value;
3303
+ }
3304
+ };
3305
+ transferHandlers.set("throw", throwTransferHandlerCustom);
2988
3306
  function proxyClone(t) {
2989
3307
  return new Proxy(t, {
2990
3308
  get(e, r) {
@@ -3030,9 +3348,13 @@ export {
3030
3348
  isExitCode,
3031
3349
  iteratePhpFiles as iterateFiles,
3032
3350
  loadPHPRuntime,
3351
+ prettyPrintFullStackTrace,
3352
+ printDebugDetails,
3353
+ printResponseDebugDetails,
3033
3354
  proxyFileSystem,
3034
3355
  removePathPrefix,
3035
3356
  rotatePHPRuntime,
3357
+ sandboxedSpawnHandlerFactory,
3036
3358
  setPhpIniEntries,
3037
3359
  toRelativeUrl,
3038
3360
  withPHPIniValues,