Skip to content

Commit 72029ea

Browse files
committed
Narrow Playground worker terminalization
1 parent 19b21c8 commit 72029ea

3 files changed

Lines changed: 38 additions & 20 deletions

File tree

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
diff --git a/node_modules/@wp-playground/cli/worker-thread-v1.js b/node_modules/@wp-playground/cli/worker-thread-v1.js
2-
index 93b7099..63e96bc 100644
2+
index 93b7099..65f76be 100644
33
--- a/node_modules/@wp-playground/cli/worker-thread-v1.js
44
+++ b/node_modules/@wp-playground/cli/worker-thread-v1.js
5-
@@ -157,6 +157,7 @@ async function C(r, e) {
5+
@@ -157,6 +157,8 @@ async function C(r, e) {
66
}
77
process.on("unhandledRejection", (r) => {
88
S.error("Unhandled rejection:", r);
9-
+ throw r;
9+
+ if (r instanceof WebAssembly.RuntimeError && String(r.stack).includes("php.wasm"))
10+
+ throw r;
1011
});
1112
const i = new _(), [c, p] = y(
1213
new F(new f()),
1314
diff --git a/node_modules/@wp-playground/cli/worker-thread-v2.js b/node_modules/@wp-playground/cli/worker-thread-v2.js
14-
index fb79a59..5d09b1f 100644
15+
index fb79a59..77ddb67 100644
1516
--- a/node_modules/@wp-playground/cli/worker-thread-v2.js
1617
+++ b/node_modules/@wp-playground/cli/worker-thread-v2.js
17-
@@ -168,6 +168,7 @@ async function j(r, e) {
18+
@@ -168,6 +168,8 @@ async function j(r, e) {
1819
}
1920
process.on("unhandledRejection", (r) => {
2021
E.error("Unhandled rejection:", r);
21-
+ throw r;
22+
+ if (r instanceof WebAssembly.RuntimeError && String(r.stack).includes("php.wasm"))
23+
+ throw r;
2224
});
2325
const i = new m(), [h, u] = k(
2426
new L(new b()),

patches/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ and browser asset path before that upstream change can be merged and released.
99
Remove this patch and the package override after a published Playground package
1010
contains the same change.
1111

12-
`@wp-playground+cli+3.1.46.patch` makes blueprint worker threads rethrow
13-
unhandled runtime rejections after logging them. The released CLI otherwise
14-
keeps a poisoned PHP-WASM worker alive and leaves the parent request pending
15-
until the recipe timeout. Remove the patch after the Playground CLI ships the
16-
same worker terminalization behavior.
12+
`@wp-playground+cli+3.1.46.patch` makes blueprint worker threads rethrow fatal
13+
`WebAssembly.RuntimeError` rejections originating from `php.wasm` after logging
14+
them. Other unhandled rejections retain the released CLI's log-only behavior.
15+
Without this narrow terminalization, a poisoned PHP-WASM worker remains alive
16+
and leaves the parent request pending until the recipe timeout. Remove the patch
17+
after the Playground CLI ships the same worker terminalization behavior.

tests/playground-worker-runtime-rejection.test.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@ const preloadPath = join(root, "reject-on-command.mjs")
1111
await writeFile(preloadPath, `
1212
import { parentPort } from "node:worker_threads"
1313
parentPort?.on("message", (message) => {
14-
if (message !== "wp-codebox-trigger-runtime-rejection") return
15-
const error = new WebAssembly.RuntimeError("null function or function signature mismatch")
16-
error.stack = "RuntimeError: null function or function signature mismatch\\n at php.wasm.zif_mysqli_poll (wasm://wasm/php.wasm-05996276:wasm-function[12986]:0x9949a8)"
17-
Promise.reject(error)
14+
if (message === "wp-codebox-trigger-non-wasm-rejection") {
15+
Promise.reject(new Error("ordinary worker rejection"))
16+
setTimeout(() => parentPort?.postMessage("wp-codebox-worker-survived"), 25)
17+
}
18+
if (message === "wp-codebox-trigger-php-wasm-rejection") {
19+
const error = new WebAssembly.RuntimeError("null function or function signature mismatch")
20+
error.stack = "RuntimeError: null function or function signature mismatch\\n at php.wasm.zif_mysqli_poll (wasm://wasm/php.wasm-05996276:wasm-function[12986]:0x9949a8)"
21+
Promise.reject(error)
22+
}
1823
})
1924
`, "utf8")
2025

@@ -33,26 +38,36 @@ async function assertWorkerTerminates(version: string): Promise<void> {
3338
})
3439

3540
let workerError: Error | undefined
41+
let initialized = false
42+
let survivedOrdinaryRejection = false
3643
const exitCode = await Promise.race([
3744
new Promise<number>((resolveExit) => {
3845
worker.once("message", (message: { command?: unknown; phpPort?: { close?: () => void } }) => {
3946
if (message?.command !== "worker-script-initialized") return
47+
initialized = true
4048
message.phpPort?.close?.()
41-
worker.postMessage("wp-codebox-trigger-runtime-rejection")
49+
worker.postMessage("wp-codebox-trigger-non-wasm-rejection")
50+
})
51+
worker.on("message", (message: unknown) => {
52+
if (message !== "wp-codebox-worker-survived") return
53+
survivedOrdinaryRejection = true
54+
worker.postMessage("wp-codebox-trigger-php-wasm-rejection")
4255
})
4356
worker.once("error", (error) => {
4457
workerError = error
4558
})
4659
worker.once("exit", resolveExit)
4760
}),
4861
new Promise<never>((_resolve, reject) => {
49-
setTimeout(() => reject(new Error(`Playground ${version} worker remained alive after an unhandled runtime rejection`)), 3_000).unref()
62+
setTimeout(() => reject(new Error(`Playground ${version} worker remained alive after a fatal PHP-WASM rejection`)), 3_000).unref()
5063
}),
5164
]).finally(() => worker.terminate())
5265

53-
assert.notEqual(exitCode, 0, `Playground ${version} worker must exit nonzero after an unhandled runtime rejection`)
54-
assert.ok(workerError, `Playground ${version} worker must propagate its unhandled runtime rejection`)
66+
assert.ok(initialized, `Playground ${version} worker must initialize before the rejection checks`)
67+
assert.ok(survivedOrdinaryRejection, `Playground ${version} worker must preserve ordinary unhandled rejection behavior`)
68+
assert.notEqual(exitCode, 0, `Playground ${version} worker must exit nonzero after a fatal PHP-WASM rejection`)
69+
assert.ok(workerError, `Playground ${version} worker must propagate its fatal PHP-WASM rejection`)
5570
assert.match(workerError.message, /null function or function signature mismatch/)
5671
}
5772

58-
console.log("playground worker runtime rejection terminalization ok")
73+
console.log("playground PHP-WASM worker rejection terminalization ok")

0 commit comments

Comments
 (0)