@wp-playground/cli 3.0.18 → 3.0.19
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/blueprints-v1/blueprints-v1-handler.d.ts +2 -3
- package/blueprints-v1/worker-thread-v1.d.ts +5 -4
- package/blueprints-v2/blueprints-v2-handler.d.ts +2 -2
- package/blueprints-v2/worker-thread-v2.d.ts +2 -2
- package/cli.cjs +1 -1
- package/cli.js +1 -1
- package/index.cjs +1 -1
- package/index.js +1 -1
- package/load-balancer.d.ts +1 -0
- package/package.json +12 -12
- package/run-cli-4UcAoCNX.cjs +46 -0
- package/run-cli-4UcAoCNX.cjs.map +1 -0
- package/{run-cli-BBfr5tmj.js → run-cli-fhMEvo2X.js} +350 -326
- package/run-cli-fhMEvo2X.js.map +1 -0
- package/worker-thread-v1.cjs +2 -2
- package/worker-thread-v1.cjs.map +1 -1
- package/worker-thread-v1.js +65 -63
- package/worker-thread-v1.js.map +1 -1
- package/worker-thread-v2.cjs +5 -5
- package/worker-thread-v2.cjs.map +1 -1
- package/worker-thread-v2.js +7 -7
- package/worker-thread-v2.js.map +1 -1
- package/xdebug-path-mappings.d.ts +2 -0
- package/run-cli-BBfr5tmj.js.map +0 -1
- package/run-cli-Dz_ghzvE.cjs +0 -46
- package/run-cli-Dz_ghzvE.cjs.map +0 -1
package/worker-thread-v1.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import { loadNodeRuntime as R } from "@php-wasm/node";
|
|
2
2
|
import { EmscriptenDownloadMonitor as q } from "@php-wasm/progress";
|
|
3
|
-
import { exposeAPI as v, PHPWorker as E, consumeAPI as L, consumeAPISync as
|
|
4
|
-
import { sprintf as
|
|
5
|
-
import { RecommendedPHPVersion as
|
|
3
|
+
import { exposeAPI as v, PHPWorker as E, consumeAPI as L, consumeAPISync as O, sandboxedSpawnHandlerFactory as _ } from "@php-wasm/universal";
|
|
4
|
+
import { sprintf as x } from "@php-wasm/util";
|
|
5
|
+
import { RecommendedPHPVersion as A } from "@wp-playground/common";
|
|
6
6
|
import { bootWordPressAndRequestHandler as C, bootRequestHandler as D } from "@wp-playground/wordpress";
|
|
7
7
|
import { rootCertificates as F } from "tls";
|
|
8
8
|
import { jspi as B } from "wasm-feature-detect";
|
|
9
|
-
import { MessageChannel as
|
|
9
|
+
import { MessageChannel as U, parentPort as j } from "worker_threads";
|
|
10
10
|
import { m as s } from "./mounts-D1_eXSTw.js";
|
|
11
|
-
import { logger as
|
|
11
|
+
import { logger as G } from "@php-wasm/logger";
|
|
12
12
|
function I(c, e, ...a) {
|
|
13
13
|
console.log(
|
|
14
14
|
performance.now().toFixed(6).padStart(15, "0"),
|
|
15
15
|
c.toString().padStart(16, "0"),
|
|
16
|
-
|
|
16
|
+
x(e, ...a)
|
|
17
17
|
);
|
|
18
18
|
}
|
|
19
|
-
class
|
|
19
|
+
class N extends E {
|
|
20
20
|
constructor(e) {
|
|
21
21
|
super(void 0, e), this.booted = !1;
|
|
22
22
|
}
|
|
@@ -30,31 +30,31 @@ class U extends E {
|
|
|
30
30
|
* @see phpwasm-emscripten-library-file-locking-for-node.js
|
|
31
31
|
*/
|
|
32
32
|
async useFileLockManager(e) {
|
|
33
|
-
await B() ? this.fileLockManager = L(e) : this.fileLockManager = await
|
|
33
|
+
await B() ? this.fileLockManager = L(e) : this.fileLockManager = await O(e);
|
|
34
34
|
}
|
|
35
|
-
async
|
|
35
|
+
async bootAndSetUpInitialWorker({
|
|
36
36
|
siteUrl: e,
|
|
37
37
|
mountsBeforeWpInstall: a,
|
|
38
38
|
mountsAfterWpInstall: l,
|
|
39
|
-
phpVersion: n =
|
|
40
|
-
wordPressZip:
|
|
41
|
-
sqliteIntegrationPluginZip:
|
|
39
|
+
phpVersion: n = A,
|
|
40
|
+
wordPressZip: p,
|
|
41
|
+
sqliteIntegrationPluginZip: d,
|
|
42
42
|
firstProcessId: i,
|
|
43
|
-
processIdSpaceLength:
|
|
44
|
-
dataSqlPath:
|
|
45
|
-
followSymlinks:
|
|
46
|
-
trace:
|
|
47
|
-
internalCookieStore:
|
|
48
|
-
withXdebug:
|
|
49
|
-
nativeInternalDirPath:
|
|
43
|
+
processIdSpaceLength: w,
|
|
44
|
+
dataSqlPath: P,
|
|
45
|
+
followSymlinks: u,
|
|
46
|
+
trace: r,
|
|
47
|
+
internalCookieStore: f,
|
|
48
|
+
withXdebug: o,
|
|
49
|
+
nativeInternalDirPath: y
|
|
50
50
|
}) {
|
|
51
51
|
if (this.booted)
|
|
52
52
|
throw new Error("Playground already booted");
|
|
53
53
|
this.booted = !0;
|
|
54
|
-
let
|
|
55
|
-
const W = i +
|
|
54
|
+
let t = i;
|
|
55
|
+
const W = i + w - 1;
|
|
56
56
|
try {
|
|
57
|
-
const
|
|
57
|
+
const m = {
|
|
58
58
|
WP_DEBUG: !0,
|
|
59
59
|
WP_DEBUG_LOG: !0,
|
|
60
60
|
WP_DEBUG_DISPLAY: !1
|
|
@@ -63,21 +63,21 @@ class U extends E {
|
|
|
63
63
|
const H = await C({
|
|
64
64
|
siteUrl: e,
|
|
65
65
|
createPhpRuntime: async () => {
|
|
66
|
-
const h =
|
|
67
|
-
return
|
|
66
|
+
const h = t;
|
|
67
|
+
return t < W ? t++ : t = i, await R(n, {
|
|
68
68
|
emscriptenOptions: {
|
|
69
69
|
fileLockManager: this.fileLockManager,
|
|
70
70
|
processId: h,
|
|
71
|
-
trace:
|
|
72
|
-
phpWasmInitOptions: { nativeInternalDirPath:
|
|
71
|
+
trace: r ? I : void 0,
|
|
72
|
+
phpWasmInitOptions: { nativeInternalDirPath: y }
|
|
73
73
|
},
|
|
74
|
-
followSymlinks:
|
|
75
|
-
withXdebug:
|
|
74
|
+
followSymlinks: u,
|
|
75
|
+
withXdebug: o
|
|
76
76
|
});
|
|
77
77
|
},
|
|
78
|
-
wordPressZip:
|
|
79
|
-
sqliteIntegrationPluginZip:
|
|
80
|
-
[
|
|
78
|
+
wordPressZip: p !== void 0 ? new File([p], "wordpress.zip") : void 0,
|
|
79
|
+
sqliteIntegrationPluginZip: d !== void 0 ? new File(
|
|
80
|
+
[d],
|
|
81
81
|
"sqlite-integration-plugin.zip"
|
|
82
82
|
) : void 0,
|
|
83
83
|
sapiName: "cli",
|
|
@@ -85,14 +85,14 @@ class U extends E {
|
|
|
85
85
|
"/internal/shared/ca-bundle.crt": F.join(`
|
|
86
86
|
`)
|
|
87
87
|
},
|
|
88
|
-
constants:
|
|
88
|
+
constants: m,
|
|
89
89
|
phpIniEntries: {
|
|
90
90
|
"openssl.cafile": "/internal/shared/ca-bundle.crt",
|
|
91
91
|
allow_url_fopen: "1",
|
|
92
92
|
disable_functions: ""
|
|
93
93
|
},
|
|
94
|
-
cookieStore:
|
|
95
|
-
dataSqlPath:
|
|
94
|
+
cookieStore: f ? void 0 : !1,
|
|
95
|
+
dataSqlPath: P,
|
|
96
96
|
spawnHandler: _,
|
|
97
97
|
async onPHPInstanceCreated(h) {
|
|
98
98
|
await s(h, a), b && await s(h, l);
|
|
@@ -100,60 +100,62 @@ class U extends E {
|
|
|
100
100
|
});
|
|
101
101
|
this.__internal_setRequestHandler(H), b = !0;
|
|
102
102
|
const k = await H.getPrimaryPhp();
|
|
103
|
-
await this.setPrimaryPHP(k), await s(k, l),
|
|
104
|
-
} catch (
|
|
105
|
-
throw
|
|
103
|
+
await this.setPrimaryPHP(k), await s(k, l), M();
|
|
104
|
+
} catch (m) {
|
|
105
|
+
throw S(m), m;
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
|
-
async
|
|
108
|
+
async bootWorker(e) {
|
|
109
109
|
await this.bootRequestHandler(e);
|
|
110
110
|
}
|
|
111
111
|
async bootRequestHandler({
|
|
112
112
|
siteUrl: e,
|
|
113
|
-
|
|
113
|
+
followSymlinks: a,
|
|
114
114
|
phpVersion: l,
|
|
115
115
|
firstProcessId: n,
|
|
116
|
-
processIdSpaceLength:
|
|
117
|
-
trace:
|
|
116
|
+
processIdSpaceLength: p,
|
|
117
|
+
trace: d,
|
|
118
118
|
nativeInternalDirPath: i,
|
|
119
|
-
mountsBeforeWpInstall:
|
|
120
|
-
mountsAfterWpInstall:
|
|
119
|
+
mountsBeforeWpInstall: w,
|
|
120
|
+
mountsAfterWpInstall: P,
|
|
121
|
+
withXdebug: u
|
|
121
122
|
}) {
|
|
122
123
|
if (this.booted)
|
|
123
124
|
throw new Error("Playground already booted");
|
|
124
125
|
this.booted = !0;
|
|
125
|
-
let
|
|
126
|
-
const f = n +
|
|
126
|
+
let r = n;
|
|
127
|
+
const f = n + p - 1;
|
|
127
128
|
try {
|
|
128
|
-
const
|
|
129
|
+
const o = await D({
|
|
129
130
|
siteUrl: e,
|
|
130
131
|
createPhpRuntime: async () => {
|
|
131
|
-
const
|
|
132
|
-
return
|
|
132
|
+
const t = r;
|
|
133
|
+
return r < f ? r++ : r = n, await R(l, {
|
|
133
134
|
emscriptenOptions: {
|
|
134
135
|
fileLockManager: this.fileLockManager,
|
|
135
|
-
processId:
|
|
136
|
-
trace:
|
|
136
|
+
processId: t,
|
|
137
|
+
trace: d ? I : void 0,
|
|
137
138
|
ENV: {
|
|
138
139
|
DOCROOT: "/wordpress"
|
|
139
140
|
},
|
|
140
141
|
phpWasmInitOptions: { nativeInternalDirPath: i }
|
|
141
142
|
},
|
|
142
|
-
followSymlinks: a
|
|
143
|
+
followSymlinks: a,
|
|
144
|
+
withXdebug: u
|
|
143
145
|
});
|
|
144
146
|
},
|
|
145
|
-
onPHPInstanceCreated: async (
|
|
146
|
-
await s(
|
|
147
|
+
onPHPInstanceCreated: async (t) => {
|
|
148
|
+
await s(t, w), await s(t, P);
|
|
147
149
|
},
|
|
148
150
|
sapiName: "cli",
|
|
149
151
|
cookieStore: !1,
|
|
150
152
|
spawnHandler: _
|
|
151
153
|
});
|
|
152
|
-
this.__internal_setRequestHandler(
|
|
153
|
-
const y = await
|
|
154
|
-
await this.setPrimaryPHP(y),
|
|
155
|
-
} catch (
|
|
156
|
-
throw
|
|
154
|
+
this.__internal_setRequestHandler(o);
|
|
155
|
+
const y = await o.getPrimaryPhp();
|
|
156
|
+
await this.setPrimaryPHP(y), M();
|
|
157
|
+
} catch (o) {
|
|
158
|
+
throw S(o), o;
|
|
157
159
|
}
|
|
158
160
|
}
|
|
159
161
|
// Provide a named disposal method that can be invoked via comlink.
|
|
@@ -162,14 +164,14 @@ class U extends E {
|
|
|
162
164
|
}
|
|
163
165
|
}
|
|
164
166
|
process.on("unhandledRejection", (c) => {
|
|
165
|
-
|
|
167
|
+
G.error("Unhandled rejection:", c);
|
|
166
168
|
});
|
|
167
|
-
const g = new
|
|
168
|
-
new
|
|
169
|
+
const g = new U(), [M, S] = v(
|
|
170
|
+
new N(new q()),
|
|
169
171
|
void 0,
|
|
170
172
|
g.port1
|
|
171
173
|
);
|
|
172
|
-
|
|
174
|
+
j?.postMessage(
|
|
173
175
|
{
|
|
174
176
|
command: "worker-script-initialized",
|
|
175
177
|
phpPort: g.port2
|
|
@@ -177,6 +179,6 @@ G?.postMessage(
|
|
|
177
179
|
[g.port2]
|
|
178
180
|
);
|
|
179
181
|
export {
|
|
180
|
-
|
|
182
|
+
N as PlaygroundCliBlueprintV1Worker
|
|
181
183
|
};
|
|
182
184
|
//# sourceMappingURL=worker-thread-v1.js.map
|
package/worker-thread-v1.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-thread-v1.js","sources":["../../../../packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import type { FileLockManager } from '@php-wasm/node';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport {\n\tbootRequestHandler,\n\tbootWordPressAndRequestHandler,\n} from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { jspi } from 'wasm-feature-detect';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\nimport { logger } from '@php-wasm/logger';\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport type WorkerBootOptions = {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\tfollowSymlinks: boolean;\n\ttrace: boolean;\n\t/**\n\t * When true, Playground will not send cookies to the client but will manage\n\t * them internally. This can be useful in environments that can't store cookies,\n\t * e.g. VS Code WebView.\n\t *\n\t * Default: false.\n\t */\n\tinternalCookieStore?: boolean;\n\twithXdebug?: boolean;\n\tnativeInternalDirPath: string;\n};\n\nexport type PrimaryWorkerBootOptions = WorkerBootOptions & {\n\twpVersion?: string;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tdataSqlPath?: string;\n};\n\ninterface WorkerBootRequestHandlerOptions {\n\tsiteUrl: string;\n\tallow?: string;\n\tphpVersion: SupportedPHPVersion;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbooted = false;\n\tfileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAsPrimaryWorker({\n\t\tsiteUrl,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\tphpVersion: php = RecommendedPHPVersion,\n\t\twordPressZip,\n\t\tsqliteIntegrationPluginZip,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\tdataSqlPath,\n\t\tfollowSymlinks,\n\t\ttrace,\n\t\tinternalCookieStore,\n\t\twithXdebug,\n\t\tnativeInternalDirPath,\n\t}: PrimaryWorkerBootOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\n\t\ttry {\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\t\t\tlet wordpressBooted = false;\n\t\t\tconst requestHandler = await bootWordPressAndRequestHandler({\n\t\t\t\tsiteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(php, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t )\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\tcookieStore: internalCookieStore ? undefined : false,\n\t\t\t\tdataSqlPath,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\n\t\t\t\tasync onPHPInstanceCreated(php) {\n\t\t\t\t\tawait mountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\tif (wordpressBooted) {\n\t\t\t\t\t\tawait mountResources(php, mountsAfterWpInstall);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\t\t\twordpressBooted = true;\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\t// The primary PHP instance is persistent, so we need to apply\n\t\t\t// post-install mounts now that WordPress has been booted.\n\t\t\t// All secondary PHP instances created after WP boot will get\n\t\t\t// these mounts automatically.\n\t\t\tawait mountResources(primaryPhp, mountsAfterWpInstall);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync bootAsSecondaryWorker(args: WorkerBootOptions) {\n\t\tawait this.bootRequestHandler(args);\n\t}\n\n\tasync bootRequestHandler({\n\t\tsiteUrl,\n\t\tallow,\n\t\tphpVersion,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t}: WorkerBootRequestHandlerOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\n\t\ttry {\n\t\t\tconst requestHandler = await bootRequestHandler({\n\t\t\t\tsiteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t\tENV: {\n\t\t\t\t\t\t\t\tDOCROOT: '/wordpress',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tonPHPInstanceCreated: async (php) => {\n\t\t\t\t\tawait mountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\tawait mountResources(php, mountsAfterWpInstall);\n\t\t\t\t},\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcookieStore: false,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV1Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort?.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","siteUrl","mountsBeforeWpInstall","mountsAfterWpInstall","php","RecommendedPHPVersion","wordPressZip","sqliteIntegrationPluginZip","firstProcessId","processIdSpaceLength","dataSqlPath","followSymlinks","trace","internalCookieStore","withXdebug","nativeInternalDirPath","nextProcessId","lastProcessId","constants","wordpressBooted","requestHandler","bootWordPressAndRequestHandler","loadNodeRuntime","rootCertificates","sandboxedSpawnHandlerFactory","mountResources","primaryPhp","setApiReady","e","setAPIError","allow","phpVersion","bootRequestHandler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"worker-thread-v1.js","sources":["../../../../packages/playground/cli/src/blueprints-v1/worker-thread-v1.ts"],"sourcesContent":["import type { FileLockManager } from '@php-wasm/node';\nimport { loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type { RemoteAPI, SupportedPHPVersion } from '@php-wasm/universal';\nimport {\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport { RecommendedPHPVersion } from '@wp-playground/common';\nimport {\n\tbootRequestHandler,\n\tbootWordPressAndRequestHandler,\n} from '@wp-playground/wordpress';\nimport { rootCertificates } from 'tls';\nimport { jspi } from 'wasm-feature-detect';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport { mountResources } from '../mounts';\nimport { logger } from '@php-wasm/logger';\n\nexport interface Mount {\n\thostPath: string;\n\tvfsPath: string;\n}\n\nexport type WorkerBootOptions = {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\tfollowSymlinks: boolean;\n\ttrace: boolean;\n\t/**\n\t * When true, Playground will not send cookies to the client but will manage\n\t * them internally. This can be useful in environments that can't store cookies,\n\t * e.g. VS Code WebView.\n\t *\n\t * Default: false.\n\t */\n\tinternalCookieStore?: boolean;\n\twithXdebug?: boolean;\n\tnativeInternalDirPath: string;\n};\n\nexport type PrimaryWorkerBootOptions = WorkerBootOptions & {\n\twpVersion?: string;\n\twordPressZip?: ArrayBuffer;\n\tsqliteIntegrationPluginZip?: ArrayBuffer;\n\tdataSqlPath?: string;\n};\n\ninterface WorkerBootRequestHandlerOptions {\n\tsiteUrl: string;\n\tfollowSymlinks: boolean;\n\tphpVersion: SupportedPHPVersion;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\tmountsBeforeWpInstall: Array<Mount>;\n\tmountsAfterWpInstall: Array<Mount>;\n\twithXdebug?: boolean;\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\nexport class PlaygroundCliBlueprintV1Worker extends PHPWorker {\n\tbooted = false;\n\tfileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAndSetUpInitialWorker({\n\t\tsiteUrl,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\tphpVersion: php = RecommendedPHPVersion,\n\t\twordPressZip,\n\t\tsqliteIntegrationPluginZip,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\tdataSqlPath,\n\t\tfollowSymlinks,\n\t\ttrace,\n\t\tinternalCookieStore,\n\t\twithXdebug,\n\t\tnativeInternalDirPath,\n\t}: PrimaryWorkerBootOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\n\t\ttry {\n\t\t\tconst constants: Record<string, string | number | boolean | null> =\n\t\t\t\t{\n\t\t\t\t\tWP_DEBUG: true,\n\t\t\t\t\tWP_DEBUG_LOG: true,\n\t\t\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t\t\t};\n\t\t\tlet wordpressBooted = false;\n\t\t\tconst requestHandler = await bootWordPressAndRequestHandler({\n\t\t\t\tsiteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(php, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\twordPressZip:\n\t\t\t\t\twordPressZip !== undefined\n\t\t\t\t\t\t? new File([wordPressZip], 'wordpress.zip')\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsqliteIntegrationPluginZip:\n\t\t\t\t\tsqliteIntegrationPluginZip !== undefined\n\t\t\t\t\t\t? new File(\n\t\t\t\t\t\t\t\t[sqliteIntegrationPluginZip],\n\t\t\t\t\t\t\t\t'sqlite-integration-plugin.zip'\n\t\t\t\t\t\t )\n\t\t\t\t\t\t: undefined,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles: {\n\t\t\t\t\t'/internal/shared/ca-bundle.crt':\n\t\t\t\t\t\trootCertificates.join('\\n'),\n\t\t\t\t},\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries: {\n\t\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t\t\tallow_url_fopen: '1',\n\t\t\t\t\tdisable_functions: '',\n\t\t\t\t},\n\t\t\t\tcookieStore: internalCookieStore ? undefined : false,\n\t\t\t\tdataSqlPath,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\n\t\t\t\tasync onPHPInstanceCreated(php) {\n\t\t\t\t\tawait mountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\tif (wordpressBooted) {\n\t\t\t\t\t\tawait mountResources(php, mountsAfterWpInstall);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\t\t\twordpressBooted = true;\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\t// The primary PHP instance is persistent, so we need to apply\n\t\t\t// post-install mounts now that WordPress has been booted.\n\t\t\t// All secondary PHP instances created after WP boot will get\n\t\t\t// these mounts automatically.\n\t\t\tawait mountResources(primaryPhp, mountsAfterWpInstall);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\tasync bootWorker(args: WorkerBootOptions) {\n\t\tawait this.bootRequestHandler(args);\n\t}\n\n\tasync bootRequestHandler({\n\t\tsiteUrl,\n\t\tfollowSymlinks,\n\t\tphpVersion,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\tmountsBeforeWpInstall,\n\t\tmountsAfterWpInstall,\n\t\twithXdebug,\n\t}: WorkerBootRequestHandlerOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\n\t\ttry {\n\t\t\tconst requestHandler = await bootRequestHandler({\n\t\t\t\tsiteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t\tENV: {\n\t\t\t\t\t\t\t\tDOCROOT: '/wordpress',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks,\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tonPHPInstanceCreated: async (php) => {\n\t\t\t\t\tawait mountResources(php, mountsBeforeWpInstall);\n\t\t\t\t\tawait mountResources(php, mountsAfterWpInstall);\n\t\t\t\t},\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcookieStore: false,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV1Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort?.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["tracePhpWasm","processId","format","args","sprintf","PlaygroundCliBlueprintV1Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","siteUrl","mountsBeforeWpInstall","mountsAfterWpInstall","php","RecommendedPHPVersion","wordPressZip","sqliteIntegrationPluginZip","firstProcessId","processIdSpaceLength","dataSqlPath","followSymlinks","trace","internalCookieStore","withXdebug","nativeInternalDirPath","nextProcessId","lastProcessId","constants","wordpressBooted","requestHandler","bootWordPressAndRequestHandler","loadNodeRuntime","rootCertificates","sandboxedSpawnHandlerFactory","mountResources","primaryPhp","setApiReady","e","setAPIError","phpVersion","bootRequestHandler","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
|
package/worker-thread-v2.cjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const W=require("@php-wasm/logger"),y=require("@php-wasm/node"),x=require("@php-wasm/progress"),u=require("@php-wasm/universal"),k=require("@php-wasm/util"),
|
|
2
|
-
`),process.exit(1)}}function
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const W=require("@php-wasm/logger"),y=require("@php-wasm/node"),x=require("@php-wasm/progress"),u=require("@php-wasm/universal"),k=require("@php-wasm/util"),I=require("@wp-playground/blueprints"),M=require("@wp-playground/wordpress"),_=require("fs"),m=require("path"),$=require("tls"),T=require("worker_threads"),S=require("wasm-feature-detect");async function h(s,e){for(const r of e)try{s.mkdir(r.vfsPath),await s.mount(r.vfsPath,y.createNodeFsMountHandler(r.hostPath))}catch{i.stderr(`\x1B[31m\x1B[1mError mounting path ${r.hostPath} at ${r.vfsPath}\x1B[0m
|
|
2
|
+
`),process.exit(1)}}function A(s,e,...r){console.log(performance.now().toFixed(6).padStart(15,"0"),s.toString().padStart(16,"0"),k.sprintf(e,...r))}Object.defineProperty(process.stdout,"isTTY",{value:!0});Object.defineProperty(process.stderr,"isTTY",{value:!0});const i={lastWriteWasProgress:!1,progress(s){process.stdout.isTTY?(i.lastWriteWasProgress||process.stdout.write(`
|
|
3
3
|
`),process.stdout.write("\r\x1B[K"+s),i.lastWriteWasProgress=!0):console.log(s)},stdout(s){i.lastWriteWasProgress&&(process.stdout.write(`
|
|
4
4
|
`),i.lastWriteWasProgress=!1),process.stdout.write(s)},stderr(s){i.lastWriteWasProgress&&(process.stdout.write(`
|
|
5
|
-
`),i.lastWriteWasProgress=!1),process.stderr.write(s)}};class R extends u.PHPWorker{constructor(e){super(void 0,e),this.booted=!1,this.blueprintTargetResolved=!1,this.phpInstancesThatNeedMountsAfterTargetResolved=new Set}async useFileLockManager(e){await
|
|
6
|
-
`)},constants:r,phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt"},onPHPInstanceCreated:async o=>{await h(o,e["mount-before-install"]||[]),this.blueprintTargetResolved?await h(o,e.mount||[]):(this.phpInstancesThatNeedMountsAfterTargetResolved.add(o),o.addEventListener("runtime.beforeExit",()=>{this.phpInstancesThatNeedMountsAfterTargetResolved.delete(o)}))}};await this.bootRequestHandler(p);const w=this.__internal_getPHP();if(e.mode==="mount-only"){await h(w,e.mount||[]);return}await this.runBlueprintV2(e)}async
|
|
5
|
+
`),i.lastWriteWasProgress=!1),process.stderr.write(s)}};class R extends u.PHPWorker{constructor(e){super(void 0,e),this.booted=!1,this.blueprintTargetResolved=!1,this.phpInstancesThatNeedMountsAfterTargetResolved=new Set}async useFileLockManager(e){await S.jspi()?this.fileLockManager=u.consumeAPI(e):this.fileLockManager=await u.consumeAPISync(e)}async bootAndSetUpInitialWorker(e){const r={WP_DEBUG:!0,WP_DEBUG_LOG:!0,WP_DEBUG_DISPLAY:!1},p={...e,createFiles:{"/internal/shared/ca-bundle.crt":$.rootCertificates.join(`
|
|
6
|
+
`)},constants:r,phpIniEntries:{"openssl.cafile":"/internal/shared/ca-bundle.crt"},onPHPInstanceCreated:async o=>{await h(o,e["mount-before-install"]||[]),this.blueprintTargetResolved?await h(o,e.mount||[]):(this.phpInstancesThatNeedMountsAfterTargetResolved.add(o),o.addEventListener("runtime.beforeExit",()=>{this.phpInstancesThatNeedMountsAfterTargetResolved.delete(o)}))}};await this.bootRequestHandler(p);const w=this.__internal_getPHP();if(e.mode==="mount-only"){await h(w,e.mount||[]);return}await this.runBlueprintV2(e)}async bootWorker(e){await this.bootRequestHandler({...e,onPHPInstanceCreated:async r=>{await h(r,e.mountsBeforeWpInstall||[]),await h(r,e.mountsAfterWpInstall||[])}})}async runBlueprintV2(e){const r=this.__internal_getRequestHandler(),{php:p,reap:w}=await r.processManager.acquirePHPInstance({considerPrimary:!1}),o=this.__internal_getPHP();let f=()=>{};if(typeof e.blueprint=="string"){const n=m.resolve(process.cwd(),e.blueprint);_.existsSync(n)&&(o.mkdir("/internal/shared/cwd"),f=await o.mount("/internal/shared/cwd",y.createNodeFsMountHandler(m.dirname(n))),e.blueprint=m.join("/internal/shared/cwd",m.basename(e.blueprint)))}try{const l=["mode","db-engine","db-host","db-user","db-pass","db-name","db-path","truncate-new-site-directory","allow"].filter(t=>t in e).map(t=>`--${t}=${e[t]}`);l.push(`--site-url=${e.siteUrl}`);const c=await I.runBlueprintV2({php:p,blueprint:e.blueprint,blueprintOverrides:{additionalSteps:e["additional-blueprint-steps"],wordpressVersion:e.wp},cliArgs:l,onMessage:async t=>{switch(t.type){case"blueprint.target_resolved":{if(!this.blueprintTargetResolved){this.blueprintTargetResolved=!0;for(const a of this.phpInstancesThatNeedMountsAfterTargetResolved)this.phpInstancesThatNeedMountsAfterTargetResolved.delete(a),await h(a,e.mount||[])}break}case"blueprint.progress":{const a=`${t.caption.trim()} – ${t.progress.toFixed(2)}%`;i.progress(a);break}case"blueprint.error":{const a="\x1B[31m",b="\x1B[1m",d="\x1B[0m";e.debug&&t.details?i.stderr(`${a}${b}Fatal error:${d} Uncaught ${t.details.exception}: ${t.details.message}
|
|
7
7
|
at ${t.details.file}:${t.details.line}
|
|
8
8
|
`+(t.details.trace?t.details.trace+`
|
|
9
9
|
`:"")):i.stderr(`${a}${b}Error:${d} ${t.message}
|
|
10
|
-
`);break}}}});if(e.debug&&(c.stdout.pipeTo(new WritableStream({write(t){process.stdout.write(t)}})),c.stderr.pipeTo(new WritableStream({write(t){process.stderr.write(t)}}))),await c.finished,await c.exitCode!==0){const t=await u.PHPResponse.fromStreamedResponse(c);throw new u.PHPExecutionFailureError(`PHP.run() failed with exit code ${t.exitCode}.`,t,"request")}}catch(n){let l="";try{l=p.readFileAsText(W.errorLogPath)}catch{}throw n.phpLogs=l,n}finally{w(),f()}}async bootRequestHandler({siteUrl:e,allow:r,phpVersion:p,createFiles:w,constants:o,phpIniEntries:f,firstProcessId:n,processIdSpaceLength:l,trace:c,nativeInternalDirPath:t,withXdebug:a,onPHPInstanceCreated:b}){if(this.booted)throw new Error("Playground already booted");this.booted=!0;let d=n;const q=n+l-1;try{const P=await
|
|
10
|
+
`);break}}}});if(e.debug&&(c.stdout.pipeTo(new WritableStream({write(t){process.stdout.write(t)}})),c.stderr.pipeTo(new WritableStream({write(t){process.stderr.write(t)}}))),await c.finished,await c.exitCode!==0){const t=await u.PHPResponse.fromStreamedResponse(c);throw new u.PHPExecutionFailureError(`PHP.run() failed with exit code ${t.exitCode}.`,t,"request")}}catch(n){let l="";try{l=p.readFileAsText(W.errorLogPath)}catch{}throw n.phpLogs=l,n}finally{w(),f()}}async bootRequestHandler({siteUrl:e,allow:r,phpVersion:p,createFiles:w,constants:o,phpIniEntries:f,firstProcessId:n,processIdSpaceLength:l,trace:c,nativeInternalDirPath:t,withXdebug:a,onPHPInstanceCreated:b}){if(this.booted)throw new Error("Playground already booted");this.booted=!0;let d=n;const q=n+l-1;try{const P=await M.bootRequestHandler({siteUrl:e,createPhpRuntime:async()=>{const H=d;return d<q?d++:d=n,await y.loadNodeRuntime(p,{emscriptenOptions:{fileLockManager:this.fileLockManager,processId:H,trace:c?A:void 0,ENV:{DOCROOT:"/wordpress"},phpWasmInitOptions:{nativeInternalDirPath:t}},followSymlinks:r?.includes("follow-symlinks"),withXdebug:a})},onPHPInstanceCreated:b,sapiName:"cli",createFiles:w,constants:o,phpIniEntries:f,cookieStore:!1,spawnHandler:u.sandboxedSpawnHandlerFactory});this.__internal_setRequestHandler(P);const v=await P.getPrimaryPhp();await this.setPrimaryPHP(v),B()}catch(P){throw E(P),P}}async dispose(){await this[Symbol.asyncDispose]()}}process.on("unhandledRejection",s=>{W.logger.error("Unhandled rejection:",s)});const g=new T.MessageChannel,[B,E]=u.exposeAPI(new R(new x.EmscriptenDownloadMonitor),void 0,g.port1);T.parentPort?.postMessage({command:"worker-script-initialized",phpPort:g.port2},[g.port2]);exports.PlaygroundCliBlueprintV2Worker=R;
|
|
11
11
|
//# sourceMappingURL=worker-thread-v2.cjs.map
|
package/worker-thread-v2.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker-thread-v2.cjs","sources":["../../../../packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts"],"sourcesContent":["import { errorLogPath, logger } from '@php-wasm/logger';\nimport type { FileLockManager } from '@php-wasm/node';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type {\n\tPHP,\n\tFileTree,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n} from '@php-wasm/universal';\nimport {\n\tPHPExecutionFailureError,\n\tPHPResponse,\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport {\n\ttype BlueprintMessage,\n\trunBlueprintV2,\n\ttype BlueprintV1Declaration,\n} from '@wp-playground/blueprints';\nimport {\n\ttype ParsedBlueprintV2String,\n\ttype RawBlueprintV2Data,\n} from '@wp-playground/blueprints';\nimport { bootRequestHandler } from '@wp-playground/wordpress';\nimport { existsSync } from 'fs';\nimport path from 'path';\nimport { rootCertificates } from 'tls';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport type { Mount } from '../mounts';\nimport { jspi } from 'wasm-feature-detect';\nimport { type RunCLIArgs } from '../run-cli';\nimport type {\n\tPhpIniOptions,\n\tPHPInstanceCreatedHook,\n} from '@wp-playground/wordpress';\n\nasync function mountResources(php: PHP, mounts: Mount[]) {\n\tfor (const mount of mounts) {\n\t\ttry {\n\t\t\tphp.mkdir(mount.vfsPath);\n\t\t\tawait php.mount(\n\t\t\t\tmount.vfsPath,\n\t\t\t\tcreateNodeFsMountHandler(mount.hostPath)\n\t\t\t);\n\t\t} catch {\n\t\t\toutput.stderr(\n\t\t\t\t`\\x1b[31m\\x1b[1mError mounting path ${mount.hostPath} at ${mount.vfsPath}\\x1b[0m\\n`\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\n/**\n * Force TTY status to preserve ANSI control codes in the output.\n *\n * This script is spawned as `new Worker()` and process.stdout and process.stderr are\n * WritableWorkerStdio objects. By default, they strip ANSI control codes from the output\n * causing every progress bar update to be printed in a new line instead of updating the\n * same line.\n */\nObject.defineProperty(process.stdout, 'isTTY', { value: true });\nObject.defineProperty(process.stderr, 'isTTY', { value: true });\n\n/**\n * Output writer that ensures that progress bars are not printed on the same line as other output.\n */\nconst output = {\n\tlastWriteWasProgress: false,\n\tprogress(data: string) {\n\t\tif (!process.stdout.isTTY) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(data);\n\t\t} else {\n\t\t\tif (!output.lastWriteWasProgress) {\n\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t}\n\t\t\tprocess.stdout.write('\\r\\x1b[K' + data);\n\t\t\toutput.lastWriteWasProgress = true;\n\t\t}\n\t},\n\tstdout(data: string) {\n\t\tif (output.lastWriteWasProgress) {\n\t\t\tprocess.stdout.write('\\n');\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stdout.write(data);\n\t},\n\tstderr(data: string) {\n\t\tif (output.lastWriteWasProgress) {\n\t\t\tprocess.stdout.write('\\n');\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stderr.write(data);\n\t},\n};\n\nexport type PrimaryWorkerBootArgs = RunCLIArgs & {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n\tnativeInternalDirPath: string;\n};\n\ntype WorkerRunBlueprintArgs = RunCLIArgs & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n};\n\nexport type SecondaryWorkerBootArgs = {\n\tsiteUrl: string;\n\tallow?: string;\n\tphpVersion: SupportedPHPVersion;\n\tphpIniEntries?: PhpIniOptions;\n\tconstants?: Record<string, string | number | boolean | null>;\n\tcreateFiles?: FileTree;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\twithXdebug?: boolean;\n\tmountsBeforeWpInstall?: Array<Mount>;\n\tmountsAfterWpInstall?: Array<Mount>;\n};\n\nexport type WorkerBootRequestHandlerOptions = Omit<\n\tSecondaryWorkerBootArgs,\n\t'mountsBeforeWpInstall' | 'mountsAfterWpInstall'\n> & {\n\tonPHPInstanceCreated: PHPInstanceCreatedHook;\n};\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tblueprintTargetResolved = false;\n\tphpInstancesThatNeedMountsAfterTargetResolved = new Set<PHP>();\n\tfileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAsPrimaryWorker(args: PrimaryWorkerBootArgs) {\n\t\tconst constants = {\n\t\t\tWP_DEBUG: true,\n\t\t\tWP_DEBUG_LOG: true,\n\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t};\n\t\tconst requestHandlerOptions: WorkerBootRequestHandlerOptions = {\n\t\t\t...args,\n\t\t\tcreateFiles: {\n\t\t\t\t'/internal/shared/ca-bundle.crt': rootCertificates.join('\\n'),\n\t\t\t},\n\t\t\tconstants,\n\t\t\tphpIniEntries: {\n\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t},\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args['mount-before-install'] || []);\n\t\t\t\tif (this.blueprintTargetResolved) {\n\t\t\t\t\tawait mountResources(php, args.mount || []);\n\t\t\t\t} else {\n\t\t\t\t\t// NOTE: Today (2025-09-11), during boot with a plugin auto-mount,\n\t\t\t\t\t// the Blueprint runner fails unless post-resolution mounts are\n\t\t\t\t\t// added to existing PHP instances. So we track them here so they\n\t\t\t\t\t// can be mounted at the necessary time.\n\t\t\t\t\t// Only plugin auto-mounts seem to need this, so perhaps there\n\t\t\t\t\t// is a change we can make to the Blueprint runner so such\n\t\t\t\t\t// a dance is unnecessary.\n\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.add(php);\n\t\t\t\t\tphp.addEventListener('runtime.beforeExit', () => {\n\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\tphp\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t\tawait this.bootRequestHandler(requestHandlerOptions);\n\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\n\t\tif (args.mode === 'mount-only') {\n\t\t\tawait mountResources(primaryPhp, args.mount || []);\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.runBlueprintV2(args);\n\t}\n\n\tasync bootAsSecondaryWorker(args: SecondaryWorkerBootArgs) {\n\t\tawait this.bootRequestHandler({\n\t\t\t...args,\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args.mountsBeforeWpInstall || []);\n\t\t\t\tawait mountResources(php, args.mountsAfterWpInstall || []);\n\t\t\t},\n\t\t});\n\t}\n\n\tasync runBlueprintV2(args: WorkerRunBlueprintArgs) {\n\t\tconst requestHandler = this.__internal_getRequestHandler()!;\n\t\tconst { php, reap } =\n\t\t\tawait requestHandler.processManager.acquirePHPInstance({\n\t\t\t\tconsiderPrimary: false,\n\t\t\t});\n\n\t\t// Mount the current working directory to the PHP runtime for the purposes of\n\t\t// Blueprint resolution.\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\t\tlet unmountCwd = () => {};\n\t\tif (typeof args.blueprint === 'string') {\n\t\t\tconst blueprintPath = path.resolve(process.cwd(), args.blueprint);\n\t\t\tif (existsSync(blueprintPath)) {\n\t\t\t\tprimaryPhp.mkdir('/internal/shared/cwd');\n\t\t\t\tunmountCwd = await primaryPhp.mount(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tcreateNodeFsMountHandler(path.dirname(blueprintPath))\n\t\t\t\t);\n\t\t\t\targs.blueprint = path.join(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tpath.basename(args.blueprint)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst cliArgsToPass: (keyof WorkerRunBlueprintArgs)[] = [\n\t\t\t\t'mode',\n\t\t\t\t'db-engine',\n\t\t\t\t'db-host',\n\t\t\t\t'db-user',\n\t\t\t\t'db-pass',\n\t\t\t\t'db-name',\n\t\t\t\t'db-path',\n\t\t\t\t'truncate-new-site-directory',\n\t\t\t\t'allow',\n\t\t\t];\n\t\t\tconst cliArgs = cliArgsToPass\n\t\t\t\t.filter((arg) => arg in args)\n\t\t\t\t.map((arg) => `--${arg}=${args[arg]}`);\n\t\t\tcliArgs.push(`--site-url=${args.siteUrl}`);\n\n\t\t\tconst streamedResponse = await runBlueprintV2({\n\t\t\t\tphp,\n\t\t\t\tblueprint: args.blueprint,\n\t\t\t\tblueprintOverrides: {\n\t\t\t\t\tadditionalSteps: args['additional-blueprint-steps'],\n\t\t\t\t\twordpressVersion: args.wp,\n\t\t\t\t},\n\t\t\t\tcliArgs,\n\t\t\t\tonMessage: async (message: BlueprintMessage) => {\n\t\t\t\t\tswitch (message.type) {\n\t\t\t\t\t\tcase 'blueprint.target_resolved': {\n\t\t\t\t\t\t\tif (!this.blueprintTargetResolved) {\n\t\t\t\t\t\t\t\tthis.blueprintTargetResolved = true;\n\t\t\t\t\t\t\t\tfor (const php of this\n\t\t\t\t\t\t\t\t\t.phpInstancesThatNeedMountsAfterTargetResolved) {\n\t\t\t\t\t\t\t\t\t// console.log('mounting resources for php', php);\n\t\t\t\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\t\t\t\tphp\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tawait mountResources(php, args.mount || []);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.progress': {\n\t\t\t\t\t\t\tconst progressMessage = `${message.caption.trim()} – ${message.progress.toFixed(\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t)}%`;\n\t\t\t\t\t\t\toutput.progress(progressMessage);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.error': {\n\t\t\t\t\t\t\tconst red = '\\x1b[31m';\n\t\t\t\t\t\t\tconst bold = '\\x1b[1m';\n\t\t\t\t\t\t\tconst reset = '\\x1b[0m';\n\t\t\t\t\t\t\tif (args.debug && message.details) {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Fatal error:${reset} Uncaught ${message.details.exception}: ${message.details.message}\\n` +\n\t\t\t\t\t\t\t\t\t\t` at ${message.details.file}:${message.details.line}\\n` +\n\t\t\t\t\t\t\t\t\t\t(message.details.trace\n\t\t\t\t\t\t\t\t\t\t\t? message.details.trace + '\\n'\n\t\t\t\t\t\t\t\t\t\t\t: '')\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Error:${reset} ${message.message}\\n`\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\t\t\t/**\n\t\t\t * When we're debugging, every bit of information matters – let's immediately output\n\t\t\t * everything we get from the PHP output streams.\n\t\t\t */\n\t\t\tif (args.debug) {\n\t\t\t\tstreamedResponse!.stdout.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stdout.write(chunk);\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tstreamedResponse!.stderr.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stderr.write(chunk);\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait streamedResponse!.finished;\n\t\t\tif ((await streamedResponse!.exitCode) !== 0) {\n\t\t\t\t// exitCode != 1 means the blueprint execution failed. Let's throw an error.\n\t\t\t\t// and clean up.\n\t\t\t\tconst syncResponse = await PHPResponse.fromStreamedResponse(\n\t\t\t\t\tstreamedResponse\n\t\t\t\t);\n\t\t\t\tthrow new PHPExecutionFailureError(\n\t\t\t\t\t`PHP.run() failed with exit code ${syncResponse.exitCode}.`,\n\t\t\t\t\tsyncResponse,\n\t\t\t\t\t'request'\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Capture the PHP error log details to provide more context for debugging.\n\t\t\tlet phpLogs = '';\n\t\t\ttry {\n\t\t\t\t// @TODO: Don't assume errorLogPath starts with /wordpress/\n\t\t\t\t// ...or maybe we can assume that in Playground CLI?\n\t\t\t\tphpLogs = php.readFileAsText(errorLogPath);\n\t\t\t} catch {\n\t\t\t\t// Ignore errors reading the PHP error log.\n\t\t\t}\n\t\t\t(error as any).phpLogs = phpLogs;\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\treap();\n\t\t\tunmountCwd();\n\t\t}\n\t}\n\n\tasync bootRequestHandler({\n\t\tsiteUrl,\n\t\tallow,\n\t\tphpVersion,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\n\t\tonPHPInstanceCreated,\n\t}: WorkerBootRequestHandlerOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\n\t\ttry {\n\t\t\tconst requestHandler = await bootRequestHandler({\n\t\t\t\tsiteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t\tENV: {\n\t\t\t\t\t\t\t\tDOCROOT: '/wordpress',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tonPHPInstanceCreated,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles,\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries,\n\t\t\t\tcookieStore: false,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV2Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort?.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["mountResources","php","mounts","mount","createNodeFsMountHandler","output","tracePhpWasm","processId","format","args","sprintf","data","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","constants","requestHandlerOptions","rootCertificates","primaryPhp","requestHandler","reap","unmountCwd","blueprintPath","path","existsSync","cliArgs","arg","streamedResponse","runBlueprintV2","message","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","phpVersion","createFiles","phpIniEntries","firstProcessId","processIdSpaceLength","trace","nativeInternalDirPath","withXdebug","onPHPInstanceCreated","nextProcessId","lastProcessId","bootRequestHandler","loadNodeRuntime","sandboxedSpawnHandlerFactory","setApiReady","e","setAPIError","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"worker-thread-v2.cjs","sources":["../../../../packages/playground/cli/src/blueprints-v2/worker-thread-v2.ts"],"sourcesContent":["import { errorLogPath, logger } from '@php-wasm/logger';\nimport type { FileLockManager } from '@php-wasm/node';\nimport { createNodeFsMountHandler, loadNodeRuntime } from '@php-wasm/node';\nimport { EmscriptenDownloadMonitor } from '@php-wasm/progress';\nimport type {\n\tPHP,\n\tFileTree,\n\tRemoteAPI,\n\tSupportedPHPVersion,\n} from '@php-wasm/universal';\nimport {\n\tPHPExecutionFailureError,\n\tPHPResponse,\n\tPHPWorker,\n\tconsumeAPI,\n\tconsumeAPISync,\n\texposeAPI,\n\tsandboxedSpawnHandlerFactory,\n} from '@php-wasm/universal';\nimport { sprintf } from '@php-wasm/util';\nimport {\n\ttype BlueprintMessage,\n\trunBlueprintV2,\n\ttype BlueprintV1Declaration,\n} from '@wp-playground/blueprints';\nimport {\n\ttype ParsedBlueprintV2String,\n\ttype RawBlueprintV2Data,\n} from '@wp-playground/blueprints';\nimport { bootRequestHandler } from '@wp-playground/wordpress';\nimport { existsSync } from 'fs';\nimport path from 'path';\nimport { rootCertificates } from 'tls';\nimport { MessageChannel, type MessagePort, parentPort } from 'worker_threads';\nimport type { Mount } from '../mounts';\nimport { jspi } from 'wasm-feature-detect';\nimport { type RunCLIArgs } from '../run-cli';\nimport type {\n\tPhpIniOptions,\n\tPHPInstanceCreatedHook,\n} from '@wp-playground/wordpress';\n\nasync function mountResources(php: PHP, mounts: Mount[]) {\n\tfor (const mount of mounts) {\n\t\ttry {\n\t\t\tphp.mkdir(mount.vfsPath);\n\t\t\tawait php.mount(\n\t\t\t\tmount.vfsPath,\n\t\t\t\tcreateNodeFsMountHandler(mount.hostPath)\n\t\t\t);\n\t\t} catch {\n\t\t\toutput.stderr(\n\t\t\t\t`\\x1b[31m\\x1b[1mError mounting path ${mount.hostPath} at ${mount.vfsPath}\\x1b[0m\\n`\n\t\t\t);\n\t\t\tprocess.exit(1);\n\t\t}\n\t}\n}\n\n/**\n * Print trace messages from PHP-WASM.\n *\n * @param {number} processId - The process ID.\n * @param {string} format - The format string.\n * @param {...any} args - The arguments.\n */\nfunction tracePhpWasm(processId: number, format: string, ...args: any[]) {\n\t// eslint-disable-next-line no-console\n\tconsole.log(\n\t\tperformance.now().toFixed(6).padStart(15, '0'),\n\t\tprocessId.toString().padStart(16, '0'),\n\t\tsprintf(format, ...args)\n\t);\n}\n\n/**\n * Force TTY status to preserve ANSI control codes in the output.\n *\n * This script is spawned as `new Worker()` and process.stdout and process.stderr are\n * WritableWorkerStdio objects. By default, they strip ANSI control codes from the output\n * causing every progress bar update to be printed in a new line instead of updating the\n * same line.\n */\nObject.defineProperty(process.stdout, 'isTTY', { value: true });\nObject.defineProperty(process.stderr, 'isTTY', { value: true });\n\n/**\n * Output writer that ensures that progress bars are not printed on the same line as other output.\n */\nconst output = {\n\tlastWriteWasProgress: false,\n\tprogress(data: string) {\n\t\tif (!process.stdout.isTTY) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.log(data);\n\t\t} else {\n\t\t\tif (!output.lastWriteWasProgress) {\n\t\t\t\tprocess.stdout.write('\\n');\n\t\t\t}\n\t\t\tprocess.stdout.write('\\r\\x1b[K' + data);\n\t\t\toutput.lastWriteWasProgress = true;\n\t\t}\n\t},\n\tstdout(data: string) {\n\t\tif (output.lastWriteWasProgress) {\n\t\t\tprocess.stdout.write('\\n');\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stdout.write(data);\n\t},\n\tstderr(data: string) {\n\t\tif (output.lastWriteWasProgress) {\n\t\t\tprocess.stdout.write('\\n');\n\t\t\toutput.lastWriteWasProgress = false;\n\t\t}\n\t\tprocess.stderr.write(data);\n\t},\n};\n\nexport type PrimaryWorkerBootArgs = RunCLIArgs & {\n\tphpVersion: SupportedPHPVersion;\n\tsiteUrl: string;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n\tnativeInternalDirPath: string;\n};\n\ntype WorkerRunBlueprintArgs = RunCLIArgs & {\n\tsiteUrl: string;\n\tblueprint:\n\t\t| RawBlueprintV2Data\n\t\t| ParsedBlueprintV2String\n\t\t| BlueprintV1Declaration;\n};\n\nexport type SecondaryWorkerBootArgs = {\n\tsiteUrl: string;\n\tallow?: string;\n\tphpVersion: SupportedPHPVersion;\n\tphpIniEntries?: PhpIniOptions;\n\tconstants?: Record<string, string | number | boolean | null>;\n\tcreateFiles?: FileTree;\n\tfirstProcessId: number;\n\tprocessIdSpaceLength: number;\n\ttrace: boolean;\n\tnativeInternalDirPath: string;\n\twithXdebug?: boolean;\n\tmountsBeforeWpInstall?: Array<Mount>;\n\tmountsAfterWpInstall?: Array<Mount>;\n};\n\nexport type WorkerBootRequestHandlerOptions = Omit<\n\tSecondaryWorkerBootArgs,\n\t'mountsBeforeWpInstall' | 'mountsAfterWpInstall'\n> & {\n\tonPHPInstanceCreated: PHPInstanceCreatedHook;\n};\n\nexport class PlaygroundCliBlueprintV2Worker extends PHPWorker {\n\tbooted = false;\n\tblueprintTargetResolved = false;\n\tphpInstancesThatNeedMountsAfterTargetResolved = new Set<PHP>();\n\tfileLockManager: RemoteAPI<FileLockManager> | FileLockManager | undefined;\n\n\tconstructor(monitor: EmscriptenDownloadMonitor) {\n\t\tsuper(undefined, monitor);\n\t}\n\n\t/**\n\t * Call this method before boot() to use file locking.\n\t *\n\t * This method is separate from boot() to simplify the related Comlink.transferHandlers\n\t * setup – if an argument is a MessagePort, we're transferring it, not copying it.\n\t *\n\t * @see comlink-sync.ts\n\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t */\n\tasync useFileLockManager(port: MessagePort) {\n\t\tif (await jspi()) {\n\t\t\t/**\n\t\t\t * If JSPI is available, php.js supports both synchronous and asynchronous locking syscalls.\n\t\t\t * Web browsers, however, only support asynchronous message passing so let's use the\n\t\t\t * asynchronous API. Every method call will return a promise.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = consumeAPI<FileLockManager>(port);\n\t\t} else {\n\t\t\t/**\n\t\t\t * If JSPI is not available, php.js only supports synchronous locking syscalls.\n\t\t\t * Let's use the synchronous API. Every method call will block this thread\n\t\t\t * until the result is available.\n\t\t\t *\n\t\t\t * @see comlink-sync.ts\n\t\t\t * @see phpwasm-emscripten-library-file-locking-for-node.js\n\t\t\t */\n\t\t\tthis.fileLockManager = await consumeAPISync<FileLockManager>(port);\n\t\t}\n\t}\n\n\tasync bootAndSetUpInitialWorker(args: PrimaryWorkerBootArgs) {\n\t\tconst constants = {\n\t\t\tWP_DEBUG: true,\n\t\t\tWP_DEBUG_LOG: true,\n\t\t\tWP_DEBUG_DISPLAY: false,\n\t\t};\n\t\tconst requestHandlerOptions: WorkerBootRequestHandlerOptions = {\n\t\t\t...args,\n\t\t\tcreateFiles: {\n\t\t\t\t'/internal/shared/ca-bundle.crt': rootCertificates.join('\\n'),\n\t\t\t},\n\t\t\tconstants,\n\t\t\tphpIniEntries: {\n\t\t\t\t'openssl.cafile': '/internal/shared/ca-bundle.crt',\n\t\t\t},\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args['mount-before-install'] || []);\n\t\t\t\tif (this.blueprintTargetResolved) {\n\t\t\t\t\tawait mountResources(php, args.mount || []);\n\t\t\t\t} else {\n\t\t\t\t\t// NOTE: Today (2025-09-11), during boot with a plugin auto-mount,\n\t\t\t\t\t// the Blueprint runner fails unless post-resolution mounts are\n\t\t\t\t\t// added to existing PHP instances. So we track them here so they\n\t\t\t\t\t// can be mounted at the necessary time.\n\t\t\t\t\t// Only plugin auto-mounts seem to need this, so perhaps there\n\t\t\t\t\t// is a change we can make to the Blueprint runner so such\n\t\t\t\t\t// a dance is unnecessary.\n\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.add(php);\n\t\t\t\t\tphp.addEventListener('runtime.beforeExit', () => {\n\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\tphp\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t\tawait this.bootRequestHandler(requestHandlerOptions);\n\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\n\t\tif (args.mode === 'mount-only') {\n\t\t\tawait mountResources(primaryPhp, args.mount || []);\n\t\t\treturn;\n\t\t}\n\n\t\tawait this.runBlueprintV2(args);\n\t}\n\n\tasync bootWorker(args: SecondaryWorkerBootArgs) {\n\t\tawait this.bootRequestHandler({\n\t\t\t...args,\n\t\t\tonPHPInstanceCreated: async (php: PHP) => {\n\t\t\t\tawait mountResources(php, args.mountsBeforeWpInstall || []);\n\t\t\t\tawait mountResources(php, args.mountsAfterWpInstall || []);\n\t\t\t},\n\t\t});\n\t}\n\n\tasync runBlueprintV2(args: WorkerRunBlueprintArgs) {\n\t\tconst requestHandler = this.__internal_getRequestHandler()!;\n\t\tconst { php, reap } =\n\t\t\tawait requestHandler.processManager.acquirePHPInstance({\n\t\t\t\tconsiderPrimary: false,\n\t\t\t});\n\n\t\t// Mount the current working directory to the PHP runtime for the purposes of\n\t\t// Blueprint resolution.\n\t\tconst primaryPhp = this.__internal_getPHP()!;\n\t\tlet unmountCwd = () => {};\n\t\tif (typeof args.blueprint === 'string') {\n\t\t\tconst blueprintPath = path.resolve(process.cwd(), args.blueprint);\n\t\t\tif (existsSync(blueprintPath)) {\n\t\t\t\tprimaryPhp.mkdir('/internal/shared/cwd');\n\t\t\t\tunmountCwd = await primaryPhp.mount(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tcreateNodeFsMountHandler(path.dirname(blueprintPath))\n\t\t\t\t);\n\t\t\t\targs.blueprint = path.join(\n\t\t\t\t\t'/internal/shared/cwd',\n\t\t\t\t\tpath.basename(args.blueprint)\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\ttry {\n\t\t\tconst cliArgsToPass: (keyof WorkerRunBlueprintArgs)[] = [\n\t\t\t\t'mode',\n\t\t\t\t'db-engine',\n\t\t\t\t'db-host',\n\t\t\t\t'db-user',\n\t\t\t\t'db-pass',\n\t\t\t\t'db-name',\n\t\t\t\t'db-path',\n\t\t\t\t'truncate-new-site-directory',\n\t\t\t\t'allow',\n\t\t\t];\n\t\t\tconst cliArgs = cliArgsToPass\n\t\t\t\t.filter((arg) => arg in args)\n\t\t\t\t.map((arg) => `--${arg}=${args[arg]}`);\n\t\t\tcliArgs.push(`--site-url=${args.siteUrl}`);\n\n\t\t\tconst streamedResponse = await runBlueprintV2({\n\t\t\t\tphp,\n\t\t\t\tblueprint: args.blueprint,\n\t\t\t\tblueprintOverrides: {\n\t\t\t\t\tadditionalSteps: args['additional-blueprint-steps'],\n\t\t\t\t\twordpressVersion: args.wp,\n\t\t\t\t},\n\t\t\t\tcliArgs,\n\t\t\t\tonMessage: async (message: BlueprintMessage) => {\n\t\t\t\t\tswitch (message.type) {\n\t\t\t\t\t\tcase 'blueprint.target_resolved': {\n\t\t\t\t\t\t\tif (!this.blueprintTargetResolved) {\n\t\t\t\t\t\t\t\tthis.blueprintTargetResolved = true;\n\t\t\t\t\t\t\t\tfor (const php of this\n\t\t\t\t\t\t\t\t\t.phpInstancesThatNeedMountsAfterTargetResolved) {\n\t\t\t\t\t\t\t\t\t// console.log('mounting resources for php', php);\n\t\t\t\t\t\t\t\t\tthis.phpInstancesThatNeedMountsAfterTargetResolved.delete(\n\t\t\t\t\t\t\t\t\t\tphp\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\tawait mountResources(php, args.mount || []);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.progress': {\n\t\t\t\t\t\t\tconst progressMessage = `${message.caption.trim()} – ${message.progress.toFixed(\n\t\t\t\t\t\t\t\t2\n\t\t\t\t\t\t\t)}%`;\n\t\t\t\t\t\t\toutput.progress(progressMessage);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase 'blueprint.error': {\n\t\t\t\t\t\t\tconst red = '\\x1b[31m';\n\t\t\t\t\t\t\tconst bold = '\\x1b[1m';\n\t\t\t\t\t\t\tconst reset = '\\x1b[0m';\n\t\t\t\t\t\t\tif (args.debug && message.details) {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Fatal error:${reset} Uncaught ${message.details.exception}: ${message.details.message}\\n` +\n\t\t\t\t\t\t\t\t\t\t` at ${message.details.file}:${message.details.line}\\n` +\n\t\t\t\t\t\t\t\t\t\t(message.details.trace\n\t\t\t\t\t\t\t\t\t\t\t? message.details.trace + '\\n'\n\t\t\t\t\t\t\t\t\t\t\t: '')\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\toutput.stderr(\n\t\t\t\t\t\t\t\t\t`${red}${bold}Error:${reset} ${message.message}\\n`\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t});\n\t\t\t/**\n\t\t\t * When we're debugging, every bit of information matters – let's immediately output\n\t\t\t * everything we get from the PHP output streams.\n\t\t\t */\n\t\t\tif (args.debug) {\n\t\t\t\tstreamedResponse!.stdout.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stdout.write(chunk);\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t\tstreamedResponse!.stderr.pipeTo(\n\t\t\t\t\tnew WritableStream({\n\t\t\t\t\t\twrite(chunk) {\n\t\t\t\t\t\t\tprocess.stderr.write(chunk);\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait streamedResponse!.finished;\n\t\t\tif ((await streamedResponse!.exitCode) !== 0) {\n\t\t\t\t// exitCode != 1 means the blueprint execution failed. Let's throw an error.\n\t\t\t\t// and clean up.\n\t\t\t\tconst syncResponse = await PHPResponse.fromStreamedResponse(\n\t\t\t\t\tstreamedResponse\n\t\t\t\t);\n\t\t\t\tthrow new PHPExecutionFailureError(\n\t\t\t\t\t`PHP.run() failed with exit code ${syncResponse.exitCode}.`,\n\t\t\t\t\tsyncResponse,\n\t\t\t\t\t'request'\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Capture the PHP error log details to provide more context for debugging.\n\t\t\tlet phpLogs = '';\n\t\t\ttry {\n\t\t\t\t// @TODO: Don't assume errorLogPath starts with /wordpress/\n\t\t\t\t// ...or maybe we can assume that in Playground CLI?\n\t\t\t\tphpLogs = php.readFileAsText(errorLogPath);\n\t\t\t} catch {\n\t\t\t\t// Ignore errors reading the PHP error log.\n\t\t\t}\n\t\t\t(error as any).phpLogs = phpLogs;\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\treap();\n\t\t\tunmountCwd();\n\t\t}\n\t}\n\n\tasync bootRequestHandler({\n\t\tsiteUrl,\n\t\tallow,\n\t\tphpVersion,\n\t\tcreateFiles,\n\t\tconstants,\n\t\tphpIniEntries,\n\t\tfirstProcessId,\n\t\tprocessIdSpaceLength,\n\t\ttrace,\n\t\tnativeInternalDirPath,\n\t\twithXdebug,\n\t\tonPHPInstanceCreated,\n\t}: WorkerBootRequestHandlerOptions) {\n\t\tif (this.booted) {\n\t\t\tthrow new Error('Playground already booted');\n\t\t}\n\t\tthis.booted = true;\n\n\t\tlet nextProcessId = firstProcessId;\n\t\tconst lastProcessId = firstProcessId + processIdSpaceLength - 1;\n\n\t\ttry {\n\t\t\tconst requestHandler = await bootRequestHandler({\n\t\t\t\tsiteUrl,\n\t\t\t\tcreatePhpRuntime: async () => {\n\t\t\t\t\tconst processId = nextProcessId;\n\n\t\t\t\t\tif (nextProcessId < lastProcessId) {\n\t\t\t\t\t\tnextProcessId++;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// We've reached the end of the process ID space. Start over.\n\t\t\t\t\t\tnextProcessId = firstProcessId;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn await loadNodeRuntime(phpVersion, {\n\t\t\t\t\t\temscriptenOptions: {\n\t\t\t\t\t\t\tfileLockManager: this.fileLockManager!,\n\t\t\t\t\t\t\tprocessId,\n\t\t\t\t\t\t\ttrace: trace ? tracePhpWasm : undefined,\n\t\t\t\t\t\t\tENV: {\n\t\t\t\t\t\t\t\tDOCROOT: '/wordpress',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tphpWasmInitOptions: { nativeInternalDirPath },\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfollowSymlinks: allow?.includes('follow-symlinks'),\n\t\t\t\t\t\twithXdebug,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tonPHPInstanceCreated,\n\t\t\t\tsapiName: 'cli',\n\t\t\t\tcreateFiles,\n\t\t\t\tconstants,\n\t\t\t\tphpIniEntries,\n\t\t\t\tcookieStore: false,\n\t\t\t\tspawnHandler: sandboxedSpawnHandlerFactory,\n\t\t\t});\n\t\t\tthis.__internal_setRequestHandler(requestHandler);\n\n\t\t\tconst primaryPhp = await requestHandler.getPrimaryPhp();\n\t\t\tawait this.setPrimaryPHP(primaryPhp);\n\n\t\t\tsetApiReady();\n\t\t} catch (e) {\n\t\t\tsetAPIError(e as Error);\n\t\t\tthrow e;\n\t\t}\n\t}\n\n\t// Provide a named disposal method that can be invoked via comlink.\n\tasync dispose() {\n\t\tawait this[Symbol.asyncDispose]();\n\t}\n}\n\nprocess.on('unhandledRejection', (e: any) => {\n\tlogger.error('Unhandled rejection:', e);\n});\n\nconst phpChannel = new MessageChannel();\n\nconst [setApiReady, setAPIError] = exposeAPI(\n\tnew PlaygroundCliBlueprintV2Worker(new EmscriptenDownloadMonitor()),\n\tundefined,\n\tphpChannel.port1\n);\n\nparentPort?.postMessage(\n\t{\n\t\tcommand: 'worker-script-initialized',\n\t\tphpPort: phpChannel.port2,\n\t},\n\t[phpChannel.port2 as any]\n);\n"],"names":["mountResources","php","mounts","mount","createNodeFsMountHandler","output","tracePhpWasm","processId","format","args","sprintf","data","PlaygroundCliBlueprintV2Worker","PHPWorker","monitor","port","jspi","consumeAPI","consumeAPISync","constants","requestHandlerOptions","rootCertificates","primaryPhp","requestHandler","reap","unmountCwd","blueprintPath","path","existsSync","cliArgs","arg","streamedResponse","runBlueprintV2","message","progressMessage","red","bold","reset","chunk","syncResponse","PHPResponse","PHPExecutionFailureError","error","phpLogs","errorLogPath","siteUrl","allow","phpVersion","createFiles","phpIniEntries","firstProcessId","processIdSpaceLength","trace","nativeInternalDirPath","withXdebug","onPHPInstanceCreated","nextProcessId","lastProcessId","bootRequestHandler","loadNodeRuntime","sandboxedSpawnHandlerFactory","setApiReady","e","setAPIError","logger","phpChannel","MessageChannel","exposeAPI","EmscriptenDownloadMonitor","parentPort"],"mappings":"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"}
|
package/worker-thread-v2.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { logger as R, errorLogPath as x } from "@php-wasm/logger";
|
|
2
2
|
import { createNodeFsMountHandler as y, loadNodeRuntime as H } from "@php-wasm/node";
|
|
3
3
|
import { EmscriptenDownloadMonitor as v } from "@php-wasm/progress";
|
|
4
|
-
import { exposeAPI as
|
|
4
|
+
import { exposeAPI as I, PHPWorker as $, consumeAPI as k, consumeAPISync as _, PHPResponse as A, PHPExecutionFailureError as M, sandboxedSpawnHandlerFactory as S } from "@php-wasm/universal";
|
|
5
5
|
import { sprintf as B } from "@php-wasm/util";
|
|
6
6
|
import { runBlueprintV2 as E } from "@wp-playground/blueprints";
|
|
7
7
|
import { bootRequestHandler as q } from "@wp-playground/wordpress";
|
|
@@ -48,7 +48,7 @@ const i = {
|
|
|
48
48
|
`), i.lastWriteWasProgress = !1), process.stderr.write(s);
|
|
49
49
|
}
|
|
50
50
|
};
|
|
51
|
-
class D extends
|
|
51
|
+
class D extends $ {
|
|
52
52
|
constructor(e) {
|
|
53
53
|
super(void 0, e), this.booted = !1, this.blueprintTargetResolved = !1, this.phpInstancesThatNeedMountsAfterTargetResolved = /* @__PURE__ */ new Set();
|
|
54
54
|
}
|
|
@@ -62,9 +62,9 @@ class D extends k {
|
|
|
62
62
|
* @see phpwasm-emscripten-library-file-locking-for-node.js
|
|
63
63
|
*/
|
|
64
64
|
async useFileLockManager(e) {
|
|
65
|
-
await N() ? this.fileLockManager =
|
|
65
|
+
await N() ? this.fileLockManager = k(e) : this.fileLockManager = await _(e);
|
|
66
66
|
}
|
|
67
|
-
async
|
|
67
|
+
async bootAndSetUpInitialWorker(e) {
|
|
68
68
|
const r = {
|
|
69
69
|
WP_DEBUG: !0,
|
|
70
70
|
WP_DEBUG_LOG: !0,
|
|
@@ -95,7 +95,7 @@ class D extends k {
|
|
|
95
95
|
}
|
|
96
96
|
await this.runBlueprintV2(e);
|
|
97
97
|
}
|
|
98
|
-
async
|
|
98
|
+
async bootWorker(e) {
|
|
99
99
|
await this.bootRequestHandler({
|
|
100
100
|
...e,
|
|
101
101
|
onPHPInstanceCreated: async (r) => {
|
|
@@ -188,7 +188,7 @@ class D extends k {
|
|
|
188
188
|
}
|
|
189
189
|
})
|
|
190
190
|
)), await d.finished, await d.exitCode !== 0) {
|
|
191
|
-
const t = await
|
|
191
|
+
const t = await A.fromStreamedResponse(
|
|
192
192
|
d
|
|
193
193
|
);
|
|
194
194
|
throw new M(
|
|
@@ -269,7 +269,7 @@ class D extends k {
|
|
|
269
269
|
process.on("unhandledRejection", (s) => {
|
|
270
270
|
R.error("Unhandled rejection:", s);
|
|
271
271
|
});
|
|
272
|
-
const b = new O(), [U, V] =
|
|
272
|
+
const b = new O(), [U, V] = I(
|
|
273
273
|
new D(new v()),
|
|
274
274
|
void 0,
|
|
275
275
|
b.port1
|