Lines 826-866javascript
829function findBrowserRunner() {
830 // bun's global-install node_modules root has real dependency resolution (npm-style
831 // node_modules tree), so a bin.js found there is safe to invoke directly.
832 const bunGlobalRoots = [
833 path.join(os.homedir(), '.bun', 'install', 'global', 'node_modules', BROWSER_RUNNER_BIN, 'bin.js'),
835 for (const binJs of bunGlobalRoots) {
836 if (fs.existsSync(binJs)) { patchPlaywriterTimeoutBug(binJs); return { cmd: process.execPath, baseArgs: [binJs], shell: false }; }
838 // `~/.bun/install/cache/<pkg>@version` is bun's *content-addressed package cache*, not an
839 // installed tree -- it has no node_modules of its own, so invoking its bin.js directly with
840 // plain node/bun fails to resolve the package's own dependencies (e.g. "Cannot find package
841 // 'hono'"). Only `bun x` (or an npm-global install) sets up real dependency resolution, so
842 // prefer that over the cached bin.js. `bun x` still ultimately runs the same content-addressed
843 // cache copy (symlinked node_modules alongside it), so patch every cached copy proactively --
844 // there is no separate resolved-tree location to target for the `bun x` path specifically.
845 patchAllCachedPlaywriterCopies();
846 const whichCmd = process.platform === 'win32' ? 'where' : 'which';
847 const bunR = spawnSync(whichCmd, ['bun'], { encoding: 'utf-8', shell: true });
848 if (bunR.status === 0 && bunR.stdout.trim()) {
849 // `bun x <pkg>@latest` re-resolves the `@latest` tag against the npm registry on every
850 // single invocation, even when a resolved copy already sits in bun's own content-addressed
851 // cache (~/.bun/install/cache/<pkg>@<version>) from a prior run -- a redundant network
852 // round-trip per browser-verb dispatch. Observed on Windows to occasionally never return
853 // (hangs past "Resolved, downloaded and extracted" with no further output or error), which
854 // wedges every subsequent browser dispatch behind a 30s+ spawnSync timeout for no benefit,
855 // since the pinned exact version was already available locally. Prefer `bun x <pkg>@<exact
856 // cached version>` when a cached copy exists -- this still goes through `bun x`'s real
857 // dependency-tree resolution (the reason `bun x` is preferred over the raw cached bin.js
858 // above), it just skips the registry round-trip for the tag lookup itself.
859 const cachedVersion = findCachedBunRunnerVersion();
860 const pkgSpec = cachedVersion ? `${BROWSER_RUNNER_BIN}@${cachedVersion}` : `${BROWSER_RUNNER_BIN}@latest`;
861 // bun is a real native binary (resolved to its actual path via `where`/`which` just above), so
862 // it can be spawned directly without an intermediate shell. shell:true here was forcing every
863 // browser-verb -e script argument through cmd.exe's argv parsing on Windows, which treats an
864 // unescaped `&` (extremely common in real target URLs, e.g. `?singleplayer&world=...` query
865 // strings) as a command separator EVEN INSIDE A QUOTED ARGUMENT -- silently truncating the
866 // script/URL mid-string, corrupting the executed code (observed live: "await page.goto(\"http: