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