@php-wasm/universal 3.0.21 → 3.0.29
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.cjs +6 -6
- package/index.cjs.map +1 -1
- package/index.js +199 -136
- package/index.js.map +1 -1
- package/lib/fs-helpers.d.ts +2 -1
- package/lib/index.d.ts +10 -2
- package/lib/load-php-runtime.d.ts +34 -1
- package/lib/php-instance-manager.d.ts +38 -0
- package/lib/php-process-manager.d.ts +3 -6
- package/lib/php-request-handler.d.ts +19 -18
- package/lib/php.d.ts +2 -1
- package/lib/sandboxed-spawn-handler-factory.d.ts +7 -2
- package/lib/single-php-instance-manager.d.ts +34 -0
- package/lib/supported-php-versions.d.ts +2 -2
- package/package.json +9 -9
package/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var O = (t, e, r) => e.has(t) || B("Cannot " + r);
|
|
|
5
5
|
var u = (t, e, r) => (O(t, e, "read from private field"), r ? r.call(t) : e.get(t)), y = (t, e, r) => e.has(t) ? B("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, r), w = (t, e, r, s) => (O(t, e, "write to private field"), s ? s.call(t, r) : e.set(t, r), r), f = (t, e, r) => (O(t, e, "access private method"), r);
|
|
6
6
|
import "@php-wasm/node-polyfills";
|
|
7
7
|
import { logger } from "@php-wasm/logger";
|
|
8
|
-
import { dirname, joinPaths, Semaphore, createSpawnHandler, basename, normalizePath, AcquireTimeoutError } from "@php-wasm/util";
|
|
8
|
+
import { dirname, joinPaths, Semaphore, createSpawnHandler, basename, normalizePath, AcquireTimeoutError, splitShellCommand } from "@php-wasm/util";
|
|
9
9
|
import { parse, stringify } from "ini";
|
|
10
10
|
import { StreamedFile } from "@php-wasm/stream-compression";
|
|
11
11
|
class ErrnoError extends Error {
|
|
@@ -363,12 +363,12 @@ FSHelpers.copyRecursive = rethrowFileSystemError(
|
|
|
363
363
|
'Could not copy files from "{path}"'
|
|
364
364
|
)(FSHelpers.copyRecursive);
|
|
365
365
|
const _private = /* @__PURE__ */ new WeakMap();
|
|
366
|
-
var
|
|
366
|
+
var x;
|
|
367
367
|
class PHPWorker {
|
|
368
368
|
/** @inheritDoc */
|
|
369
369
|
constructor(e, r) {
|
|
370
|
-
y(this,
|
|
371
|
-
this.absoluteUrl = "", this.documentRoot = "", this.chroot = null, w(this,
|
|
370
|
+
y(this, x);
|
|
371
|
+
this.absoluteUrl = "", this.documentRoot = "", this.chroot = null, w(this, x, /* @__PURE__ */ new Map()), this.onMessageListeners = [], _private.set(this, {
|
|
372
372
|
monitor: r
|
|
373
373
|
}), e && this.__internal_setRequestHandler(e);
|
|
374
374
|
}
|
|
@@ -463,7 +463,7 @@ class PHPWorker {
|
|
|
463
463
|
* @returns A PHP instance with a consistent chroot.
|
|
464
464
|
*/
|
|
465
465
|
async acquirePHPInstance() {
|
|
466
|
-
const { php: e, reap: r } = await _private.get(this).requestHandler.
|
|
466
|
+
const { php: e, reap: r } = await _private.get(this).requestHandler.instanceManager.acquirePHPInstance();
|
|
467
467
|
return this.chroot !== null && e.chdir(this.chroot), this.registerWorkerListeners(e), { php: e, reap: r };
|
|
468
468
|
}
|
|
469
469
|
/** @inheritDoc @php-wasm/universal!/PHP.setSapiName */
|
|
@@ -524,7 +524,7 @@ class PHPWorker {
|
|
|
524
524
|
}
|
|
525
525
|
/** @inheritDoc @php-wasm/universal!/PHP.addEventListener */
|
|
526
526
|
addEventListener(e, r) {
|
|
527
|
-
u(this,
|
|
527
|
+
u(this, x).has(e) || u(this, x).set(e, /* @__PURE__ */ new Set()), u(this, x).get(e).add(r);
|
|
528
528
|
}
|
|
529
529
|
/**
|
|
530
530
|
* Removes an event listener for a PHP event.
|
|
@@ -533,10 +533,10 @@ class PHPWorker {
|
|
|
533
533
|
*/
|
|
534
534
|
removeEventListener(e, r) {
|
|
535
535
|
var s;
|
|
536
|
-
(s = u(this,
|
|
536
|
+
(s = u(this, x).get(e)) == null || s.delete(r);
|
|
537
537
|
}
|
|
538
538
|
dispatchEvent(e) {
|
|
539
|
-
const r = u(this,
|
|
539
|
+
const r = u(this, x).get(e.type);
|
|
540
540
|
if (r)
|
|
541
541
|
for (const s of r)
|
|
542
542
|
s(e);
|
|
@@ -558,7 +558,7 @@ class PHPWorker {
|
|
|
558
558
|
await ((e = _private.get(this).requestHandler) == null ? void 0 : e[Symbol.asyncDispose]());
|
|
559
559
|
}
|
|
560
560
|
}
|
|
561
|
-
|
|
561
|
+
x = new WeakMap();
|
|
562
562
|
function isExitCode(t) {
|
|
563
563
|
return t instanceof Error ? (t == null ? void 0 : t.name) === "ExitStatus" && "status" in t : !1;
|
|
564
564
|
}
|
|
@@ -586,8 +586,19 @@ async function loadPHPRuntime(t, ...e) {
|
|
|
586
586
|
return o.outboundNetworkProxyServer && (o.outboundNetworkProxyServer.close(), o.outboundNetworkProxyServer.closeAllConnections()), loadedRuntimes.delete(a), o.originalExit(c);
|
|
587
587
|
}, o[RuntimeId] = a, loadedRuntimes.set(a, o), a;
|
|
588
588
|
}
|
|
589
|
-
function
|
|
590
|
-
|
|
589
|
+
function popLoadedRuntime(t, {
|
|
590
|
+
dangerouslyKeepTheRuntimeInTheMap: e = !1
|
|
591
|
+
} = {}) {
|
|
592
|
+
var s;
|
|
593
|
+
const r = loadedRuntimes.get(t);
|
|
594
|
+
if (!r)
|
|
595
|
+
throw new Error(`Runtime with id ${t} not found`);
|
|
596
|
+
if (e) {
|
|
597
|
+
if (!((s = process == null ? void 0 : process.env) != null && s.TEST))
|
|
598
|
+
throw new Error("Cannot pop runtime in non-test environment");
|
|
599
|
+
return r;
|
|
600
|
+
}
|
|
601
|
+
return loadedRuntimes.delete(t), r;
|
|
591
602
|
}
|
|
592
603
|
const currentJsRuntime = function() {
|
|
593
604
|
var t;
|
|
@@ -950,7 +961,7 @@ class PHPExecutionFailureError extends Error {
|
|
|
950
961
|
}
|
|
951
962
|
}
|
|
952
963
|
const PHP_INI_PATH = "/internal/shared/php.ini", AUTO_PREPEND_SCRIPT = "/internal/shared/auto_prepend_file.php", OPCACHE_FILE_FOLDER = "/internal/shared/opcache";
|
|
953
|
-
var M, H, T, v, F, k, _, h, z, $, V, G, J, Y, Q, K, U, X,
|
|
964
|
+
var M, H, T, v, F, k, _, h, z, $, V, G, J, Y, Q, K, U, X, q, j;
|
|
954
965
|
class PHP {
|
|
955
966
|
/**
|
|
956
967
|
* Initializes a PHP runtime.
|
|
@@ -1075,7 +1086,7 @@ class PHP {
|
|
|
1075
1086
|
initializeRuntime(t) {
|
|
1076
1087
|
if (this[__private__dont__use])
|
|
1077
1088
|
throw new Error("PHP runtime already initialized.");
|
|
1078
|
-
const e =
|
|
1089
|
+
const e = popLoadedRuntime(t);
|
|
1079
1090
|
if (!e)
|
|
1080
1091
|
throw new Error("Invalid PHP runtime id.");
|
|
1081
1092
|
if (this[__private__dont__use] = e, this[__private__dont__use].ccall(
|
|
@@ -1276,9 +1287,7 @@ class PHP {
|
|
|
1276
1287
|
* @param request - PHP runtime options.
|
|
1277
1288
|
*/
|
|
1278
1289
|
async run(t) {
|
|
1279
|
-
const e = await this.runStream(t), r = await PHPResponse.fromStreamedResponse(
|
|
1280
|
-
e
|
|
1281
|
-
);
|
|
1290
|
+
const e = await this.runStream(t), r = await PHPResponse.fromStreamedResponse(e);
|
|
1282
1291
|
if (r.exitCode !== 0)
|
|
1283
1292
|
throw new PHPExecutionFailureError(
|
|
1284
1293
|
`PHP.run() failed with exit code ${r.exitCode}.
|
|
@@ -1387,7 +1396,7 @@ class PHP {
|
|
|
1387
1396
|
async runStream(t) {
|
|
1388
1397
|
const e = await this.semaphore.acquire();
|
|
1389
1398
|
let r;
|
|
1390
|
-
const s = f(this, h,
|
|
1399
|
+
const s = f(this, h, j).call(this, async () => {
|
|
1391
1400
|
if (u(this, H) || (await this[__private__dont__use].ccall(
|
|
1392
1401
|
"php_wasm_init",
|
|
1393
1402
|
null,
|
|
@@ -1411,11 +1420,11 @@ class PHP {
|
|
|
1411
1420
|
"The request object must have either a `code` or a `scriptPath` property."
|
|
1412
1421
|
);
|
|
1413
1422
|
const c = f(this, h, z).call(this, t.$_SERVER, i, a);
|
|
1414
|
-
for (const
|
|
1415
|
-
f(this, h, X).call(this,
|
|
1423
|
+
for (const p in c)
|
|
1424
|
+
f(this, h, X).call(this, p, c[p]);
|
|
1416
1425
|
const l = t.env || {};
|
|
1417
|
-
for (const
|
|
1418
|
-
f(this, h,
|
|
1426
|
+
for (const p in l)
|
|
1427
|
+
f(this, h, q).call(this, p, l[p]);
|
|
1419
1428
|
return await this[__private__dont__use].ccall(
|
|
1420
1429
|
"wasm_sapi_handle_request",
|
|
1421
1430
|
NUMBER,
|
|
@@ -1734,10 +1743,10 @@ class PHP {
|
|
|
1734
1743
|
return this.subProcess(t, e);
|
|
1735
1744
|
u(this, H) && (u(this, _).needsRotating = !0);
|
|
1736
1745
|
const r = await this.semaphore.acquire();
|
|
1737
|
-
return await f(this, h,
|
|
1746
|
+
return await f(this, h, j).call(this, () => {
|
|
1738
1747
|
const s = e.env || {};
|
|
1739
1748
|
for (const [n, i] of Object.entries(s))
|
|
1740
|
-
f(this, h,
|
|
1749
|
+
f(this, h, q).call(this, n, i);
|
|
1741
1750
|
t = [t[0], "-c", PHP_INI_PATH, ...t.slice(1)];
|
|
1742
1751
|
for (const n of t)
|
|
1743
1752
|
this[__private__dont__use].ccall(
|
|
@@ -1943,41 +1952,41 @@ z = function(t, e, r) {
|
|
|
1943
1952
|
[STRING, STRING],
|
|
1944
1953
|
[t, e]
|
|
1945
1954
|
);
|
|
1946
|
-
},
|
|
1955
|
+
}, q = function(t, e) {
|
|
1947
1956
|
this[__private__dont__use].ccall(
|
|
1948
1957
|
"wasm_add_ENV_entry",
|
|
1949
1958
|
null,
|
|
1950
1959
|
[STRING, STRING],
|
|
1951
1960
|
[t, e]
|
|
1952
1961
|
);
|
|
1953
|
-
},
|
|
1962
|
+
}, j = async function(t) {
|
|
1954
1963
|
u(this, _).enabled && u(this, _).needsRotating && await this.rotateRuntime(), ++u(this, _).requestsMade, u(this, _).requestsMade >= u(this, _).maxRequests && (u(this, _).needsRotating = !0);
|
|
1955
1964
|
const e = this[__private__dont__use], r = await createInvertedReadableStream();
|
|
1956
|
-
e.onHeaders = (
|
|
1957
|
-
a || s || r.controller.enqueue(
|
|
1965
|
+
e.onHeaders = (d) => {
|
|
1966
|
+
a || s || r.controller.enqueue(d.slice());
|
|
1958
1967
|
};
|
|
1959
1968
|
let s = !1;
|
|
1960
1969
|
const n = () => {
|
|
1961
1970
|
s || (s = !0, r.controller.close());
|
|
1962
1971
|
}, i = await createInvertedReadableStream();
|
|
1963
|
-
e.onStdout = (
|
|
1964
|
-
n(), !a && i.controller.enqueue(
|
|
1972
|
+
e.onStdout = (d) => {
|
|
1973
|
+
n(), !a && i.controller.enqueue(d.slice());
|
|
1965
1974
|
};
|
|
1966
1975
|
const o = await createInvertedReadableStream();
|
|
1967
|
-
e.onStderr = (
|
|
1968
|
-
a || o.controller.enqueue(
|
|
1976
|
+
e.onStderr = (d) => {
|
|
1977
|
+
a || o.controller.enqueue(d.slice());
|
|
1969
1978
|
};
|
|
1970
1979
|
let a = !1, c;
|
|
1971
|
-
const
|
|
1972
|
-
var
|
|
1980
|
+
const p = (async () => {
|
|
1981
|
+
var d;
|
|
1973
1982
|
try {
|
|
1974
1983
|
return await Promise.race([
|
|
1975
1984
|
t(),
|
|
1976
|
-
new Promise((
|
|
1977
|
-
var
|
|
1985
|
+
new Promise((P, b) => {
|
|
1986
|
+
var D;
|
|
1978
1987
|
c = (W) => {
|
|
1979
1988
|
isExitCode(W.error) || b(W.error);
|
|
1980
|
-
}, (
|
|
1989
|
+
}, (D = u(this, T)) == null || D.addEventListener(
|
|
1981
1990
|
"error",
|
|
1982
1991
|
c,
|
|
1983
1992
|
{ once: !0 }
|
|
@@ -1988,42 +1997,42 @@ z = function(t, e, r) {
|
|
|
1988
1997
|
if (isExitCode(m))
|
|
1989
1998
|
return m.status;
|
|
1990
1999
|
i.controller.error(m), o.controller.error(m), r.controller.error(m), a = !0;
|
|
1991
|
-
for (const
|
|
1992
|
-
typeof this[
|
|
2000
|
+
for (const P in this)
|
|
2001
|
+
typeof this[P] == "function" && (this[P] = () => {
|
|
1993
2002
|
throw new Error(
|
|
1994
2003
|
"PHP runtime has crashed – see the earlier error for details."
|
|
1995
2004
|
);
|
|
1996
2005
|
});
|
|
1997
2006
|
throw this.functionsMaybeMissingFromAsyncify = getFunctionsMaybeMissingFromAsyncify(), m;
|
|
1998
2007
|
} finally {
|
|
1999
|
-
a || (i.controller.close(), o.controller.close(), n(), a = !0), (
|
|
2008
|
+
a || (i.controller.close(), o.controller.close(), n(), a = !0), (d = u(this, T)) == null || d.removeEventListener(
|
|
2000
2009
|
"error",
|
|
2001
2010
|
c
|
|
2002
2011
|
);
|
|
2003
2012
|
}
|
|
2004
2013
|
})().then(
|
|
2005
|
-
(
|
|
2014
|
+
(d) => (d !== 0 && this.dispatchEvent({
|
|
2006
2015
|
type: "request.error",
|
|
2007
2016
|
error: new Error(
|
|
2008
|
-
`PHP.run() failed with exit code ${
|
|
2017
|
+
`PHP.run() failed with exit code ${d}.`
|
|
2009
2018
|
),
|
|
2010
2019
|
// Distinguish between PHP request and PHP-wasm errors
|
|
2011
2020
|
source: "php-wasm"
|
|
2012
|
-
}),
|
|
2013
|
-
(
|
|
2014
|
-
const m =
|
|
2021
|
+
}), d),
|
|
2022
|
+
(d) => {
|
|
2023
|
+
const m = d.source ?? "php-wasm";
|
|
2015
2024
|
throw this.dispatchEvent({
|
|
2016
2025
|
type: "request.error",
|
|
2017
|
-
error:
|
|
2026
|
+
error: d,
|
|
2018
2027
|
source: m
|
|
2019
|
-
}),
|
|
2028
|
+
}), d;
|
|
2020
2029
|
}
|
|
2021
2030
|
);
|
|
2022
2031
|
return new StreamedPHPResponse(
|
|
2023
2032
|
r.stream,
|
|
2024
2033
|
i.stream,
|
|
2025
2034
|
o.stream,
|
|
2026
|
-
|
|
2035
|
+
p
|
|
2027
2036
|
);
|
|
2028
2037
|
};
|
|
2029
2038
|
function normalizeHeaders(t) {
|
|
@@ -2067,8 +2076,8 @@ const getNodeType = (t, e) => {
|
|
|
2067
2076
|
try {
|
|
2068
2077
|
return "contents" in t.lookupPath(e, { follow: !0 }).node ? "memfs" : (
|
|
2069
2078
|
/**
|
|
2070
|
-
|
|
2071
|
-
|
|
2079
|
+
* Could be NODEFS, PROXYFS, etc.
|
|
2080
|
+
*/
|
|
2072
2081
|
"not-memfs"
|
|
2073
2082
|
);
|
|
2074
2083
|
} catch {
|
|
@@ -2218,6 +2227,34 @@ function writeFilesStreamToPhp(t, e) {
|
|
|
2218
2227
|
}
|
|
2219
2228
|
});
|
|
2220
2229
|
}
|
|
2230
|
+
class SinglePHPInstanceManager {
|
|
2231
|
+
constructor(e) {
|
|
2232
|
+
if (this.isAcquired = !1, !e.php && !e.phpFactory)
|
|
2233
|
+
throw new Error(
|
|
2234
|
+
"SinglePHPInstanceManager requires either php or phpFactory"
|
|
2235
|
+
);
|
|
2236
|
+
this.php = e.php, this.phpFactory = e.phpFactory;
|
|
2237
|
+
}
|
|
2238
|
+
async getPrimaryPhp() {
|
|
2239
|
+
return this.php ? this.php : (this.phpPromise || (this.phpPromise = this.phpFactory().then((e) => (this.php = e, this.phpPromise = void 0, e))), this.phpPromise);
|
|
2240
|
+
}
|
|
2241
|
+
async acquirePHPInstance() {
|
|
2242
|
+
if (this.isAcquired)
|
|
2243
|
+
throw new Error(
|
|
2244
|
+
"The PHP instance already acquired. SinglePHPInstanceManager cannot spawn another PHP instance since, by definition, it only manages a single PHP instance."
|
|
2245
|
+
);
|
|
2246
|
+
const e = await this.getPrimaryPhp();
|
|
2247
|
+
return this.isAcquired = !0, {
|
|
2248
|
+
php: e,
|
|
2249
|
+
reap: () => {
|
|
2250
|
+
this.isAcquired = !1;
|
|
2251
|
+
}
|
|
2252
|
+
};
|
|
2253
|
+
}
|
|
2254
|
+
async [Symbol.asyncDispose]() {
|
|
2255
|
+
this.php && this.php.exit();
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2221
2258
|
class MaxPhpInstancesError extends Error {
|
|
2222
2259
|
constructor(e) {
|
|
2223
2260
|
super(
|
|
@@ -2343,6 +2380,7 @@ class PHPProcessManager {
|
|
|
2343
2380
|
}
|
|
2344
2381
|
}
|
|
2345
2382
|
const SupportedPHPVersions = [
|
|
2383
|
+
"8.5",
|
|
2346
2384
|
"8.4",
|
|
2347
2385
|
"8.3",
|
|
2348
2386
|
"8.2",
|
|
@@ -2480,7 +2518,7 @@ const _default = "application/octet-stream", asx = "video/x-ms-asf", atom = "app
|
|
|
2480
2518
|
xspf,
|
|
2481
2519
|
zip
|
|
2482
2520
|
};
|
|
2483
|
-
var
|
|
2521
|
+
var g, I, L, C, A, E, N, R, S, Z, ee, te, re;
|
|
2484
2522
|
class PHPRequestHandler {
|
|
2485
2523
|
/**
|
|
2486
2524
|
* The request handler needs to decide whether to serve a static asset or
|
|
@@ -2494,8 +2532,8 @@ class PHPRequestHandler {
|
|
|
2494
2532
|
* @param config - Request Handler configuration.
|
|
2495
2533
|
*/
|
|
2496
2534
|
constructor(e) {
|
|
2497
|
-
y(this,
|
|
2498
|
-
y(this,
|
|
2535
|
+
y(this, S);
|
|
2536
|
+
y(this, g);
|
|
2499
2537
|
y(this, I);
|
|
2500
2538
|
y(this, L);
|
|
2501
2539
|
y(this, C);
|
|
@@ -2508,31 +2546,43 @@ class PHPRequestHandler {
|
|
|
2508
2546
|
absoluteUrl: s = typeof location == "object" ? location.href : DEFAULT_BASE_URL,
|
|
2509
2547
|
rewriteRules: n = [],
|
|
2510
2548
|
getFileNotFoundAction: i = () => ({ type: "404" })
|
|
2511
|
-
} = e
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2549
|
+
} = e, o = (l) => {
|
|
2550
|
+
l.isDir(r) || l.mkdir(r), l.chdir(r), l.requestHandler = this;
|
|
2551
|
+
};
|
|
2552
|
+
if (e.php)
|
|
2553
|
+
o(e.php), this.instanceManager = new SinglePHPInstanceManager({
|
|
2554
|
+
php: e.php
|
|
2555
|
+
});
|
|
2556
|
+
else if (e.phpFactory)
|
|
2557
|
+
this.instanceManager = new PHPProcessManager({
|
|
2558
|
+
phpFactory: async (l) => {
|
|
2559
|
+
const p = await e.phpFactory({
|
|
2560
|
+
...l,
|
|
2561
|
+
requestHandler: this
|
|
2562
|
+
});
|
|
2563
|
+
return o(p), p;
|
|
2564
|
+
},
|
|
2565
|
+
maxPhpInstances: e.maxPhpInstances
|
|
2566
|
+
});
|
|
2567
|
+
else
|
|
2568
|
+
throw new Error(
|
|
2569
|
+
"Either php or phpFactory must be provided in the configuration."
|
|
2570
|
+
);
|
|
2571
|
+
w(this, R, e.cookieStore === void 0 ? new HttpCookieStore() : e.cookieStore), w(this, g, r);
|
|
2572
|
+
const a = new URL(s);
|
|
2573
|
+
w(this, L, a.hostname), w(this, C, a.port ? Number(a.port) : a.protocol === "https:" ? 443 : 80), w(this, I, (a.protocol || "").replace(":", ""));
|
|
2574
|
+
const c = u(this, C) !== 443 && u(this, C) !== 80;
|
|
2525
2575
|
w(this, A, [
|
|
2526
2576
|
u(this, L),
|
|
2527
|
-
|
|
2528
|
-
].join("")), w(this, E,
|
|
2577
|
+
c ? `:${u(this, C)}` : ""
|
|
2578
|
+
].join("")), w(this, E, a.pathname.replace(/\/+$/, "")), w(this, N, [
|
|
2529
2579
|
`${u(this, I)}://`,
|
|
2530
2580
|
u(this, A),
|
|
2531
2581
|
u(this, E)
|
|
2532
2582
|
].join("")), this.rewriteRules = n, this.getFileNotFoundAction = i;
|
|
2533
2583
|
}
|
|
2534
2584
|
async getPrimaryPhp() {
|
|
2535
|
-
return await this.
|
|
2585
|
+
return await this.instanceManager.getPrimaryPhp();
|
|
2536
2586
|
}
|
|
2537
2587
|
/**
|
|
2538
2588
|
* Converts a path to an absolute URL based at the PHPRequestHandler
|
|
@@ -2566,7 +2616,7 @@ class PHPRequestHandler {
|
|
|
2566
2616
|
* for the files to serve. Default: `/var/www`.
|
|
2567
2617
|
*/
|
|
2568
2618
|
get documentRoot() {
|
|
2569
|
-
return u(this,
|
|
2619
|
+
return u(this, g);
|
|
2570
2620
|
}
|
|
2571
2621
|
/**
|
|
2572
2622
|
* Serves the request – either by serving a static file, or by
|
|
@@ -2617,13 +2667,13 @@ class PHPRequestHandler {
|
|
|
2617
2667
|
* @param request - PHP Request data.
|
|
2618
2668
|
*/
|
|
2619
2669
|
async request(e) {
|
|
2620
|
-
const r =
|
|
2670
|
+
const r = looksLikeAbsoluteUrl(e.url), s = new URL(
|
|
2621
2671
|
// Remove the hash part of the URL as it's not meant for the server.
|
|
2622
2672
|
e.url.split("#")[0],
|
|
2623
2673
|
r ? void 0 : DEFAULT_BASE_URL
|
|
2624
|
-
), n = f(this,
|
|
2674
|
+
), n = f(this, S, Z).call(this, s), i = await this.getPrimaryPhp();
|
|
2625
2675
|
let o = joinPaths(
|
|
2626
|
-
u(this,
|
|
2676
|
+
u(this, g),
|
|
2627
2677
|
/**
|
|
2628
2678
|
* Turn a URL such as `https://playground/scope:my-site/wp-admin/index.php`
|
|
2629
2679
|
* into a site-relative path, such as `/wp-admin/index.php`.
|
|
@@ -2659,10 +2709,10 @@ class PHPRequestHandler {
|
|
|
2659
2709
|
let a = n.pathname;
|
|
2660
2710
|
for (; a.startsWith("/") && a !== dirname(a); ) {
|
|
2661
2711
|
a = dirname(a);
|
|
2662
|
-
const c = joinPaths(u(this,
|
|
2712
|
+
const c = joinPaths(u(this, g), a);
|
|
2663
2713
|
if (i.isFile(c) && // Only run partial path resolution for PHP files.
|
|
2664
2714
|
c.endsWith(".php")) {
|
|
2665
|
-
o = joinPaths(u(this,
|
|
2715
|
+
o = joinPaths(u(this, g), a);
|
|
2666
2716
|
break;
|
|
2667
2717
|
}
|
|
2668
2718
|
}
|
|
@@ -2675,7 +2725,7 @@ class PHPRequestHandler {
|
|
|
2675
2725
|
case "response":
|
|
2676
2726
|
return a.response;
|
|
2677
2727
|
case "internal-redirect":
|
|
2678
|
-
o = joinPaths(u(this,
|
|
2728
|
+
o = joinPaths(u(this, g), a.uri);
|
|
2679
2729
|
break;
|
|
2680
2730
|
case "404":
|
|
2681
2731
|
return PHPResponse.forHttpCode(404);
|
|
@@ -2687,7 +2737,7 @@ class PHPRequestHandler {
|
|
|
2687
2737
|
}
|
|
2688
2738
|
if (i.isFile(o))
|
|
2689
2739
|
if (o.endsWith(".php")) {
|
|
2690
|
-
const a = await f(this,
|
|
2740
|
+
const a = await f(this, S, te).call(this, e, s, n, o);
|
|
2691
2741
|
return a.ok() && a.exitCode !== 0 ? new PHPResponse(
|
|
2692
2742
|
500,
|
|
2693
2743
|
a.headers,
|
|
@@ -2696,7 +2746,7 @@ class PHPRequestHandler {
|
|
|
2696
2746
|
a.exitCode
|
|
2697
2747
|
) : a;
|
|
2698
2748
|
} else
|
|
2699
|
-
return f(this,
|
|
2749
|
+
return f(this, S, ee).call(this, i, o);
|
|
2700
2750
|
else
|
|
2701
2751
|
return PHPResponse.forHttpCode(404);
|
|
2702
2752
|
}
|
|
@@ -2791,11 +2841,11 @@ class PHPRequestHandler {
|
|
|
2791
2841
|
prepare_$_SERVER_superglobal(e, r, s) {
|
|
2792
2842
|
const n = {
|
|
2793
2843
|
REMOTE_ADDR: "127.0.0.1",
|
|
2794
|
-
DOCUMENT_ROOT: u(this,
|
|
2844
|
+
DOCUMENT_ROOT: u(this, g),
|
|
2795
2845
|
HTTPS: u(this, N).startsWith("https://") ? "on" : ""
|
|
2796
2846
|
};
|
|
2797
|
-
return n.REQUEST_URI = e.pathname + e.search, s.startsWith(u(this,
|
|
2798
|
-
u(this,
|
|
2847
|
+
return n.REQUEST_URI = e.pathname + e.search, s.startsWith(u(this, g)) && (n.SCRIPT_NAME = s.substring(
|
|
2848
|
+
u(this, g).length
|
|
2799
2849
|
), n.PHP_SELF = r.pathname, n.REQUEST_URI.startsWith(n.SCRIPT_NAME) && (n.PATH_INFO = n.REQUEST_URI.substring(
|
|
2800
2850
|
n.SCRIPT_NAME.length
|
|
2801
2851
|
), n.PATH_INFO.includes("?") && (n.PATH_INFO = n.PATH_INFO.substring(
|
|
@@ -2804,10 +2854,10 @@ class PHPRequestHandler {
|
|
|
2804
2854
|
)))), n.QUERY_STRING = r.search.substring(1), n;
|
|
2805
2855
|
}
|
|
2806
2856
|
async [Symbol.asyncDispose]() {
|
|
2807
|
-
await this.
|
|
2857
|
+
await this.instanceManager[Symbol.asyncDispose]();
|
|
2808
2858
|
}
|
|
2809
2859
|
}
|
|
2810
|
-
|
|
2860
|
+
g = new WeakMap(), I = new WeakMap(), L = new WeakMap(), C = new WeakMap(), A = new WeakMap(), E = new WeakMap(), N = new WeakMap(), R = new WeakMap(), S = new WeakSet(), /**
|
|
2811
2861
|
* Apply the rewrite rules to the original request URL.
|
|
2812
2862
|
*
|
|
2813
2863
|
* @param originalRequestUrl - The original request URL.
|
|
@@ -2851,14 +2901,14 @@ ee = function(e, r) {
|
|
|
2851
2901
|
}, te = async function(e, r, s, n) {
|
|
2852
2902
|
let i;
|
|
2853
2903
|
try {
|
|
2854
|
-
i = await this.
|
|
2904
|
+
i = await this.instanceManager.acquirePHPInstance({
|
|
2855
2905
|
considerPrimary: !0
|
|
2856
2906
|
});
|
|
2857
2907
|
} catch (o) {
|
|
2858
2908
|
return o instanceof MaxPhpInstancesError ? PHPResponse.forHttpCode(502) : PHPResponse.forHttpCode(500);
|
|
2859
2909
|
}
|
|
2860
2910
|
try {
|
|
2861
|
-
return await f(this,
|
|
2911
|
+
return await f(this, S, re).call(this, i.php, e, r, s, n);
|
|
2862
2912
|
} finally {
|
|
2863
2913
|
i.reap();
|
|
2864
2914
|
}
|
|
@@ -2872,8 +2922,8 @@ ee = function(e, r) {
|
|
|
2872
2922
|
let c = r.body;
|
|
2873
2923
|
if (typeof c == "object" && !(c instanceof Uint8Array)) {
|
|
2874
2924
|
o = "POST";
|
|
2875
|
-
const { bytes: l, contentType:
|
|
2876
|
-
c = l, a["content-type"] =
|
|
2925
|
+
const { bytes: l, contentType: p } = await encodeAsMultipart(c);
|
|
2926
|
+
c = l, a["content-type"] = p;
|
|
2877
2927
|
}
|
|
2878
2928
|
try {
|
|
2879
2929
|
const l = await e.run({
|
|
@@ -2896,9 +2946,9 @@ ee = function(e, r) {
|
|
|
2896
2946
|
l.headers
|
|
2897
2947
|
), l;
|
|
2898
2948
|
} catch (l) {
|
|
2899
|
-
const
|
|
2900
|
-
if (
|
|
2901
|
-
return
|
|
2949
|
+
const p = l;
|
|
2950
|
+
if (p != null && p.response)
|
|
2951
|
+
return p.response;
|
|
2902
2952
|
throw l;
|
|
2903
2953
|
}
|
|
2904
2954
|
};
|
|
@@ -2914,6 +2964,13 @@ function applyRewriteRules(t, e) {
|
|
|
2914
2964
|
}
|
|
2915
2965
|
return t;
|
|
2916
2966
|
}
|
|
2967
|
+
function looksLikeAbsoluteUrl(t) {
|
|
2968
|
+
try {
|
|
2969
|
+
return new URL(t), !0;
|
|
2970
|
+
} catch {
|
|
2971
|
+
return !1;
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2917
2974
|
function rotatePHPRuntime({
|
|
2918
2975
|
php: t,
|
|
2919
2976
|
recreateRuntime: e,
|
|
@@ -2952,7 +3009,7 @@ function isPathToSharedFS(t, e) {
|
|
|
2952
3009
|
}
|
|
2953
3010
|
function sandboxedSpawnHandlerFactory(t) {
|
|
2954
3011
|
return createSpawnHandler(async function(e, r, s) {
|
|
2955
|
-
r.notifySpawn(), e[0] === "exec" && e.shift(), (e[0].endsWith(".php") || e[0].endsWith(".phar")) && e.unshift("php");
|
|
3012
|
+
r.notifySpawn(), (e == null ? void 0 : e[0]) === "/bin/sh" && (e == null ? void 0 : e[1]) === "-c" && typeof e[2] == "string" && (e = splitShellCommand(e[2])), e[0] === "exec" && e.shift(), (e[0].endsWith(".php") || e[0].endsWith(".phar")) && e.unshift("php");
|
|
2956
3013
|
const n = e[0].split("/").pop();
|
|
2957
3014
|
if (e[0] === "/usr/bin/env" && e[1] === "stty" && e[2] === "size")
|
|
2958
3015
|
r.stdout("18 140"), r.exit(0);
|
|
@@ -2972,12 +3029,16 @@ function sandboxedSpawnHandlerFactory(t) {
|
|
|
2972
3029
|
r.exit(127);
|
|
2973
3030
|
return;
|
|
2974
3031
|
}
|
|
2975
|
-
|
|
2976
|
-
|
|
2977
|
-
|
|
3032
|
+
if (!t) {
|
|
3033
|
+
logger.warn(
|
|
3034
|
+
"Tried to spawn a PHP subprocess, but the sandboxed spawn handler was created without a getPHPInstance function."
|
|
3035
|
+
), r.exit(127);
|
|
3036
|
+
return;
|
|
3037
|
+
}
|
|
3038
|
+
const { php: i, reap: o } = await t();
|
|
2978
3039
|
try {
|
|
2979
|
-
s.cwd && i.chdir(s.cwd);
|
|
2980
|
-
const a = i.cwd();
|
|
3040
|
+
s.cwd && await i.chdir(s.cwd);
|
|
3041
|
+
const a = await i.cwd();
|
|
2981
3042
|
switch (n) {
|
|
2982
3043
|
case "php": {
|
|
2983
3044
|
const c = await i.cli(e, {
|
|
@@ -3006,7 +3067,7 @@ function sandboxedSpawnHandlerFactory(t) {
|
|
|
3006
3067
|
break;
|
|
3007
3068
|
}
|
|
3008
3069
|
case "ls": {
|
|
3009
|
-
const c = i.listFiles(e[1] ?? a);
|
|
3070
|
+
const c = await i.listFiles(e[1] ?? a);
|
|
3010
3071
|
for (const l of c)
|
|
3011
3072
|
r.stdout(l + `
|
|
3012
3073
|
`);
|
|
@@ -3112,10 +3173,10 @@ class NodeSABSyncReceiveMessageTransport {
|
|
|
3112
3173
|
), Atomics.wait(i, 0, 0, 5e3) === "timed-out")
|
|
3113
3174
|
throw new Error("Timeout waiting for response");
|
|
3114
3175
|
for (; ; ) {
|
|
3115
|
-
const
|
|
3116
|
-
if (((l =
|
|
3117
|
-
return
|
|
3118
|
-
if (!
|
|
3176
|
+
const p = NodeSABSyncReceiveMessageTransport.receiveMessageOnPort(e);
|
|
3177
|
+
if (((l = p.message) == null ? void 0 : l.id) === o)
|
|
3178
|
+
return p.message;
|
|
3179
|
+
if (!p)
|
|
3119
3180
|
throw new Error("No response received");
|
|
3120
3181
|
}
|
|
3121
3182
|
}
|
|
@@ -3193,51 +3254,51 @@ function expose(t, e = globalThis, r = ["*"], s) {
|
|
|
3193
3254
|
path: [],
|
|
3194
3255
|
...i.data
|
|
3195
3256
|
}, l = (i.data.argumentList || []).map(fromWireValue);
|
|
3196
|
-
let
|
|
3257
|
+
let p;
|
|
3197
3258
|
try {
|
|
3198
|
-
const
|
|
3259
|
+
const d = c.slice(0, -1).reduce((P, b) => P[b], t), m = c.reduce((P, b) => P[b], t);
|
|
3199
3260
|
switch (a) {
|
|
3200
3261
|
case MessageType.GET:
|
|
3201
|
-
|
|
3262
|
+
p = m;
|
|
3202
3263
|
break;
|
|
3203
3264
|
case MessageType.SET:
|
|
3204
|
-
|
|
3265
|
+
d[c.slice(-1)[0]] = fromWireValue(
|
|
3205
3266
|
i.data.value
|
|
3206
|
-
),
|
|
3267
|
+
), p = !0;
|
|
3207
3268
|
break;
|
|
3208
3269
|
case MessageType.APPLY:
|
|
3209
|
-
|
|
3270
|
+
p = m.apply(d, l);
|
|
3210
3271
|
break;
|
|
3211
3272
|
case MessageType.CONSTRUCT:
|
|
3212
3273
|
{
|
|
3213
|
-
const
|
|
3214
|
-
|
|
3274
|
+
const P = new m(...l);
|
|
3275
|
+
p = proxy(P);
|
|
3215
3276
|
}
|
|
3216
3277
|
break;
|
|
3217
3278
|
case MessageType.ENDPOINT:
|
|
3218
3279
|
{
|
|
3219
|
-
const { port1:
|
|
3220
|
-
expose(t, b),
|
|
3280
|
+
const { port1: P, port2: b } = new MessageChannel();
|
|
3281
|
+
expose(t, b), p = transfer(P, [P]);
|
|
3221
3282
|
}
|
|
3222
3283
|
break;
|
|
3223
3284
|
case MessageType.RELEASE:
|
|
3224
|
-
|
|
3285
|
+
p = void 0;
|
|
3225
3286
|
break;
|
|
3226
3287
|
default:
|
|
3227
3288
|
return;
|
|
3228
3289
|
}
|
|
3229
|
-
} catch (
|
|
3230
|
-
|
|
3290
|
+
} catch (d) {
|
|
3291
|
+
p = { value: d, [throwMarker]: 0 };
|
|
3231
3292
|
}
|
|
3232
|
-
Promise.resolve(
|
|
3233
|
-
const [m,
|
|
3234
|
-
e.postMessage({ ...m, id: o },
|
|
3293
|
+
Promise.resolve(p).catch((d) => ({ value: d, [throwMarker]: 0 })).then((d) => {
|
|
3294
|
+
const [m, P] = toWireValue(d);
|
|
3295
|
+
e.postMessage({ ...m, id: o }, P), a === MessageType.RELEASE && (e.removeEventListener("message", n), closeEndPoint(e), finalizer in t && typeof t[finalizer] == "function" && t[finalizer]());
|
|
3235
3296
|
}).catch(() => {
|
|
3236
|
-
const [
|
|
3297
|
+
const [d, m] = toWireValue({
|
|
3237
3298
|
value: new TypeError("Unserializable return value"),
|
|
3238
3299
|
[throwMarker]: 0
|
|
3239
3300
|
});
|
|
3240
|
-
e.postMessage({ ...
|
|
3301
|
+
e.postMessage({ ...d, id: o }, m);
|
|
3241
3302
|
}).finally(() => {
|
|
3242
3303
|
s == null || s(i);
|
|
3243
3304
|
});
|
|
@@ -3308,16 +3369,16 @@ function createProxy(t, e, r = [], s = function() {
|
|
|
3308
3369
|
},
|
|
3309
3370
|
set(o, a, c) {
|
|
3310
3371
|
throwIfProxyReleased(n);
|
|
3311
|
-
const [l,
|
|
3372
|
+
const [l, p] = toWireValue(c);
|
|
3312
3373
|
return requestResponseMessage(
|
|
3313
3374
|
t,
|
|
3314
3375
|
e,
|
|
3315
3376
|
{
|
|
3316
3377
|
type: MessageType.SET,
|
|
3317
|
-
path: [...r, a].map((
|
|
3378
|
+
path: [...r, a].map((d) => d.toString()),
|
|
3318
3379
|
value: l
|
|
3319
3380
|
},
|
|
3320
|
-
|
|
3381
|
+
p
|
|
3321
3382
|
).then(fromWireValue);
|
|
3322
3383
|
},
|
|
3323
3384
|
apply(o, a, c) {
|
|
@@ -3329,16 +3390,16 @@ function createProxy(t, e, r = [], s = function() {
|
|
|
3329
3390
|
}).then(fromWireValue);
|
|
3330
3391
|
if (l === "bind")
|
|
3331
3392
|
return createProxy(t, e, r.slice(0, -1));
|
|
3332
|
-
const [
|
|
3393
|
+
const [p, d] = processArguments(c);
|
|
3333
3394
|
return requestResponseMessage(
|
|
3334
3395
|
t,
|
|
3335
3396
|
e,
|
|
3336
3397
|
{
|
|
3337
3398
|
type: MessageType.APPLY,
|
|
3338
3399
|
path: r.map((m) => m.toString()),
|
|
3339
|
-
argumentList:
|
|
3400
|
+
argumentList: p
|
|
3340
3401
|
},
|
|
3341
|
-
|
|
3402
|
+
d
|
|
3342
3403
|
).then(fromWireValue);
|
|
3343
3404
|
},
|
|
3344
3405
|
construct(o, a) {
|
|
@@ -3349,7 +3410,7 @@ function createProxy(t, e, r = [], s = function() {
|
|
|
3349
3410
|
e,
|
|
3350
3411
|
{
|
|
3351
3412
|
type: MessageType.CONSTRUCT,
|
|
3352
|
-
path: r.map((
|
|
3413
|
+
path: r.map((p) => p.toString()),
|
|
3353
3414
|
argumentList: c
|
|
3354
3415
|
},
|
|
3355
3416
|
l
|
|
@@ -3520,19 +3581,19 @@ const errorProperties = [
|
|
|
3520
3581
|
useToJSON: o,
|
|
3521
3582
|
serialize: a
|
|
3522
3583
|
});
|
|
3523
|
-
for (const [l,
|
|
3524
|
-
if (
|
|
3584
|
+
for (const [l, p] of Object.entries(t)) {
|
|
3585
|
+
if (p && p instanceof Uint8Array && p.constructor.name === "Buffer") {
|
|
3525
3586
|
r[l] = "[object Buffer]";
|
|
3526
3587
|
continue;
|
|
3527
3588
|
}
|
|
3528
|
-
if (
|
|
3589
|
+
if (p !== null && typeof p == "object" && typeof p.pipe == "function") {
|
|
3529
3590
|
r[l] = "[object Stream]";
|
|
3530
3591
|
continue;
|
|
3531
3592
|
}
|
|
3532
|
-
if (typeof
|
|
3533
|
-
if (!
|
|
3593
|
+
if (typeof p != "function") {
|
|
3594
|
+
if (!p || typeof p != "object") {
|
|
3534
3595
|
try {
|
|
3535
|
-
r[l] =
|
|
3596
|
+
r[l] = p;
|
|
3536
3597
|
} catch {
|
|
3537
3598
|
}
|
|
3538
3599
|
continue;
|
|
@@ -3545,10 +3606,10 @@ const errorProperties = [
|
|
|
3545
3606
|
}
|
|
3546
3607
|
}
|
|
3547
3608
|
if (a || r instanceof Error)
|
|
3548
|
-
for (const { property: l, enumerable:
|
|
3609
|
+
for (const { property: l, enumerable: p } of errorProperties)
|
|
3549
3610
|
t[l] !== void 0 && t[l] !== null && Object.defineProperty(r, l, {
|
|
3550
3611
|
value: isErrorLike(t[l]) || Array.isArray(t[l]) ? c(t[l]) : t[l],
|
|
3551
|
-
enumerable: s ? !0 :
|
|
3612
|
+
enumerable: s ? !0 : p,
|
|
3552
3613
|
configurable: !0,
|
|
3553
3614
|
writable: !0
|
|
3554
3615
|
});
|
|
@@ -3667,7 +3728,8 @@ function setupTransferHandlers() {
|
|
|
3667
3728
|
}), transferHandlers.set("PHPResponse", {
|
|
3668
3729
|
canHandle: (r) => typeof r == "object" && r !== null && "headers" in r && "bytes" in r && "errors" in r && "exitCode" in r && "httpStatusCode" in r,
|
|
3669
3730
|
serialize(r) {
|
|
3670
|
-
|
|
3731
|
+
const s = r.toRawData(), n = [];
|
|
3732
|
+
return s.bytes.buffer.byteLength > 0 && n.push(s.bytes.buffer), [s, n];
|
|
3671
3733
|
},
|
|
3672
3734
|
deserialize(r) {
|
|
3673
3735
|
return PHPResponse.fromRawData(r);
|
|
@@ -3922,6 +3984,7 @@ export {
|
|
|
3922
3984
|
PHPRequestHandler,
|
|
3923
3985
|
PHPResponse,
|
|
3924
3986
|
PHPWorker,
|
|
3987
|
+
SinglePHPInstanceManager,
|
|
3925
3988
|
StreamedPHPResponse,
|
|
3926
3989
|
SupportedPHPVersions,
|
|
3927
3990
|
SupportedPHPVersionsList,
|
|
@@ -3933,13 +3996,13 @@ export {
|
|
|
3933
3996
|
ensurePathPrefix,
|
|
3934
3997
|
exposeAPI,
|
|
3935
3998
|
exposeSyncAPI,
|
|
3936
|
-
getLoadedRuntime,
|
|
3937
3999
|
getPhpIniEntries,
|
|
3938
4000
|
inferMimeType,
|
|
3939
4001
|
isExitCode,
|
|
3940
4002
|
isPathToSharedFS,
|
|
3941
4003
|
iteratePhpFiles as iterateFiles,
|
|
3942
4004
|
loadPHPRuntime,
|
|
4005
|
+
popLoadedRuntime,
|
|
3943
4006
|
prettyPrintFullStackTrace,
|
|
3944
4007
|
printDebugDetails,
|
|
3945
4008
|
printResponseDebugDetails,
|