Problem
bootPlaygroundRemote() implements goTo() by attaching a one-shot iframe load listener, assigning the new URL, and awaiting that listener without a timeout or cancellation path. If the browser never emits load, the Comlink call remains pending forever.
This also prevents a completed Blueprint from resolving because the Blueprint v1 runner calls goTo() in its final landing-page redirect.
Reproduction evidence
A self-hosted WordPress Build preview produced this deterministic sequence:
- Playground connected successfully.
- A nine-step static-import Blueprint validated.
- Every step completed successfully, including plugin installation and all import PHP steps.
- The final landing-page
goTo() never resolved.
- The outer 60-second preview budget expired with the nested WordPress iframe still at
about:blank.
The same target flow passed consistently after bounding iframe navigation, removing the listener on timeout, cancelling the stuck navigation with about:blank, and allowing the caller’s direct-path recovery to proceed. Two fresh-browser downstream runs then passed cold import and repeated OPFS target switching.
Root cause
packages/playground/remote/src/lib/boot-playground-remote.ts creates navigationComplete from only the iframe load event. There is no rejection path when that event is lost or navigation stalls.
Expected behavior
Iframe navigation should have a bounded failure path that removes the listener and cancels the stuck navigation. Callers can then retry or recover instead of waiting forever.
Proposed patch
The verified patch and focused tests are available at:
trunk...chubes4:wordpress-playground:fix/4223-rest-cache-query-alias
Commit: ba3a84ad2
AI assistance
OpenAI gpt-5.6-sol via OpenCode assisted with investigation, implementation, tests, and downstream verification; all changes were reviewed by Chris Huber.
Problem
bootPlaygroundRemote()implementsgoTo()by attaching a one-shot iframeloadlistener, assigning the new URL, and awaiting that listener without a timeout or cancellation path. If the browser never emitsload, the Comlink call remains pending forever.This also prevents a completed Blueprint from resolving because the Blueprint v1 runner calls
goTo()in its final landing-page redirect.Reproduction evidence
A self-hosted WordPress Build preview produced this deterministic sequence:
goTo()never resolved.about:blank.The same target flow passed consistently after bounding iframe navigation, removing the listener on timeout, cancelling the stuck navigation with
about:blank, and allowing the caller’s direct-path recovery to proceed. Two fresh-browser downstream runs then passed cold import and repeated OPFS target switching.Root cause
packages/playground/remote/src/lib/boot-playground-remote.tscreatesnavigationCompletefrom only the iframeloadevent. There is no rejection path when that event is lost or navigation stalls.Expected behavior
Iframe navigation should have a bounded failure path that removes the listener and cancels the stuck navigation. Callers can then retry or recover instead of waiting forever.
Proposed patch
The verified patch and focused tests are available at:
trunk...chubes4:wordpress-playground:fix/4223-rest-cache-query-alias
Commit:
ba3a84ad2AI assistance
OpenAI gpt-5.6-sol via OpenCode assisted with investigation, implementation, tests, and downstream verification; all changes were reviewed by Chris Huber.