Skip to content

fix: Windows support — Node.js server fallback for Playwright#194

Open
sozairali wants to merge 1 commit intogarrytan:mainfrom
sozairali:fix/windows-node-fallback
Open

fix: Windows support — Node.js server fallback for Playwright#194
sozairali wants to merge 1 commit intogarrytan:mainfrom
sozairali:fix/windows-node-fallback

Conversation

@sozairali
Copy link

Summary

  • /browse is completely non-functional on Windows due to two Bun bugs:
    • oven-sh/bun#4253child_process.spawn with stdio: ["pipe"] broken on Windows (Playwright can't launch Chromium)
    • oven-sh/bun#9911 — WebSocket client broken on Windows (Playwright can't connect() to a separately-launched Chromium either)
  • On Windows, the CLI now spawns node server-node.mjs instead of bun run server.ts. The Node server is transpiled from the same source with a Bun API polyfill (Bun.servehttp.createServer, Bun.spawnSyncchild_process.spawnSync, etc.)
  • macOS/Linux behavior is completely unchanged
  • Also fixes resolveServerScript() which excluded Windows paths (startsWith('/') fails for drive letters like C:\)

What's included

File Change Rationale
browse/src/cli.ts Detect Windows, resolve Node server bundle, spawn node instead of bun The CLI is the entry point that decides how to launch the server. Since Bun can't run Playwright on Windows at all (neither pipes nor WebSocket work), the server must run under Node. The CLI is the right place for this routing decision — it already handles server lifecycle. Also fixes a pre-existing bug where resolveServerScript() used startsWith('/') to detect dev mode, which excluded Windows paths like C:\....
browse/src/bun-polyfill.cjs Polyfills Bun.serve, Bun.spawn, Bun.spawnSync, Bun.sleep for Node The transpiled server code still calls Bun APIs (Bun.serve(), etc.) since it's generated from the same source. Rather than maintaining a separate Node fork of the server, this shim lets the same code run on both runtimes. Written as .cjs so it can be require()'d before the ESM server bundle executes. Only covers the 4 APIs the server actually uses — not a general-purpose Bun polyfill.
browse/scripts/build-node-server.sh Build script: transpile + post-process + inject polyfill header Automates producing server-node.mjs from the same source as the Bun server. Uses bun build --target=node for transpilation, then sed to handle two things that can't be polyfilled at runtime: import.meta.dir (Bun-only, replaced with a __dirname equivalent) and bun:sqlite (macOS-only cookie import, stubbed out since it's irrelevant on Windows). Runs as part of bun run build so the Node bundle stays in sync with the Bun binary.
package.json Add Node server build to bun run build Ensures the Node server bundle is always rebuilt alongside the Bun binary. Without this, the Node bundle could go stale after source changes.
setup Windows: verify Chromium via Node (not Bun), require Node.js, clear error messages The existing ensure_playwright_browser function tries to launch Chromium via Bun to verify it works — on Windows this hangs forever. Changed to use Node for the verification on Windows. Also added a Node.js requirement check with an actionable error message, since Node is now a runtime dependency on Windows.

This is a workaround

When Bun fixes their Windows pipe/WebSocket handling, the entire Node fallback can be deleted — one IS_WINDOWS check removed and everything goes back to running on Bun everywhere.

Test plan

Tested on Windows 11 (Git Bash, Bun 1.3.11, Node 22.16.0):

  • bun run dev goto https://example.com — navigates successfully
  • bun run dev text — returns page content
  • bun run dev snapshot -i — returns interactive elements with @refs
  • bun run dev fill @e1 "query" + click @e2 — form interaction works
  • bun run dev console --errors — error monitoring works
  • bun run dev network — network log works
  • Multi-command session against persistent server — state preserved between commands
  • Tested against live site (lantbot.ozairali.com) — full chat interaction worked end-to-end
  • Verify macOS/Linux is unaffected (no IS_WINDOWS code path taken)

🤖 Generated with Claude Code

…nch Playwright

Bun on Windows has broken subprocess pipe handling (oven-sh/bun#4253)
and broken WebSocket client (oven-sh/bun#9911), which prevents
Playwright from launching or connecting to Chromium. This makes
/browse completely non-functional on Windows.

On Windows, the CLI now spawns `node server-node.mjs` instead of
`bun run server.ts`. The Node server bundle is transpiled from the
same source with a Bun API polyfill (Bun.serve → http.createServer,
Bun.spawnSync → child_process.spawnSync, etc.).

macOS/Linux behavior is completely unchanged.

Also fixes resolveServerScript() which excluded Windows paths
(checked for startsWith('/') but Windows uses drive letters like C:\).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant