Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
269439871d fix(bunx): ensure bun is in PATH on Windows for child processes
On Windows, when running `bunx <package>`, child processes spawned by
the package couldn't find `bun` in PATH. This happened when:
1. Node.js was installed and in PATH
2. Bun was installed but not in system PATH (common with installers)

The issue was that `configurePathForRun` only added the bun-node
directory (containing bun.exe) to PATH when either:
- `--bun` flag was explicitly passed, or
- Node.js was not found in PATH

This fix ensures that on Windows, bunx always adds bun to PATH,
allowing child processes (like SvelteKit's `sv create`) to spawn
`bun install` or other bun commands successfully.

Fixes #25151

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 10:11:24 +00:00
2 changed files with 86 additions and 1 deletions

View File

@@ -394,7 +394,11 @@ pub const BunxCommand = struct {
&this_transpiler,
&ORIGINAL_PATH,
root_dir_info.abs_path,
ctx.debug.run_in_bun,
// On Windows, always ensure bun is in PATH for bunx.
// This is needed because child processes spawned by bunx packages
// (e.g., `sv create` from SvelteKit) may need to invoke `bun` and
// would fail if bun isn't in PATH. See: https://github.com/oven-sh/bun/issues/25151
if (Environment.isWindows) true else ctx.debug.run_in_bun,
);
this_transpiler.env.map.put("npm_command", "exec") catch unreachable;
this_transpiler.env.map.put("npm_lifecycle_event", "bunx") catch unreachable;

View File

@@ -792,3 +792,84 @@ console.log("EXECUTED: multi-tool-alt (alternate binary)");
});
});
});
// Regression test for https://github.com/oven-sh/bun/issues/25151
// On Windows, child processes spawned by bunx packages couldn't find `bun` in PATH
it("bunx child processes can spawn bun", async () => {
// Create a package that spawns `bun --version` as a child process
const tempDir = tmpdirSync();
const packageDir = join(tempDir, "package");
await Bun.$`mkdir -p ${packageDir}/bin`;
// Create package.json
await writeFile(
join(packageDir, "package.json"),
JSON.stringify({
name: "spawn-bun-test",
version: "1.0.0",
bin: {
"spawn-bun-test": "./bin/spawn-bun.js",
},
}),
);
// Create a binary that spawns bun
await writeFile(
join(packageDir, "bin", "spawn-bun.js"),
`#!/usr/bin/env node
const { spawnSync } = require("child_process");
const result = spawnSync(${isWindows ? '"bun.exe"' : '"bun"'}, ["--version"], { encoding: "utf-8" });
if (result.error) {
console.error("ERROR:", result.error.message);
process.exit(1);
}
console.log("BUN_VERSION:" + result.stdout.trim());
process.exit(result.status);
`,
);
// Make the binary executable
if (!isWindows) {
await Bun.$`chmod +x ${packageDir}/bin/spawn-bun.js`;
}
// Install the package locally
await writeFile(
join(x_dir, "package.json"),
JSON.stringify({
dependencies: {
"spawn-bun-test": packageDir,
},
}),
);
const { exited: installFinished } = spawn({
cmd: [bunExe(), "install"],
cwd: x_dir,
env,
});
expect(await installFinished).toBe(0);
// Run the package via bunx - it should be able to spawn bun
const subprocess = spawn({
cmd: [bunExe(), "x", "spawn-bun-test"],
cwd: x_dir,
stdout: "pipe",
stderr: "pipe",
env,
});
const [stderr, stdout, exited] = await Promise.all([
subprocess.stderr.text(),
subprocess.stdout.text(),
subprocess.exited,
]);
// Should successfully spawn bun and get its version
// We just verify that bun was found and executed successfully -
// the exact version may differ from the test runner's version
expect(stdout).toContain("BUN_VERSION:");
expect(stdout).toMatch(/BUN_VERSION:\d+\.\d+\.\d+/);
expect(stderr).not.toContain("ERROR:");
expect(exited).toBe(0);
});