fix(shell): handle ".", "", "./" in cwd() by using process.cwd() (#26461)

## Summary
- Fix `$`...`.cwd(".")` causing ENOENT error with path ending in
"undefined"
- The same fix applies to `.cwd("")` and `.cwd("./")`
- Falls back to `process.cwd()` when `defaultCwd` is undefined

Closes #26460

## Test plan
- [x] Added regression test in `test/regression/issue/26460.test.ts`
- [x] Verified test fails with `USE_SYSTEM_BUN=1` (reproduces the bug)
- [x] Verified test passes with `bun bd test` (fix works)

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

Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
robobun
2026-01-26 16:04:45 -08:00
committed by GitHub
parent bd63fb9ef6
commit ba426210c2
2 changed files with 105 additions and 2 deletions

View File

@@ -149,7 +149,7 @@ export function createBunShellTemplateFunction(createShellInterpreter_, createPa
cwd(newCwd?: string): this { cwd(newCwd?: string): this {
this.#throwIfRunning(); this.#throwIfRunning();
if (typeof newCwd === "undefined" || newCwd === "." || newCwd === "" || newCwd === "./") { if (typeof newCwd === "undefined" || newCwd === "." || newCwd === "" || newCwd === "./") {
newCwd = defaultCwd; newCwd = defaultCwd ?? process.cwd();
} }
this.#args!.setCwd(newCwd); this.#args!.setCwd(newCwd);
return this; return this;
@@ -277,7 +277,7 @@ export function createBunShellTemplateFunction(createShellInterpreter_, createPa
cwd(newCwd: string | undefined) { cwd(newCwd: string | undefined) {
if (typeof newCwd === "undefined" || typeof newCwd === "string") { if (typeof newCwd === "undefined" || typeof newCwd === "string") {
if (newCwd === "." || newCwd === "" || newCwd === "./") { if (newCwd === "." || newCwd === "" || newCwd === "./") {
newCwd = defaultCwd; newCwd = defaultCwd ?? process.cwd();
} }
this[cwdSymbol] = newCwd; this[cwdSymbol] = newCwd;

View File

@@ -0,0 +1,103 @@
import { expect, test } from "bun:test";
import { bunEnv, bunExe, tempDir } from "harness";
// Regression test for https://github.com/oven-sh/bun/issues/26460
// Using $`...`.cwd(".") should work and use the current working directory
test("shell cwd('.') should use current working directory", async () => {
using dir = tempDir("shell-cwd-dot", {
"test.js": `
import { $ } from "bun";
const result = await $\`pwd\`.cwd(".").text();
console.log(result.trim());
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "test.js"],
env: bunEnv,
cwd: String(dir),
stdout: "pipe",
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stderr).toBe("");
expect(stdout.trim()).toBe(String(dir));
expect(exitCode).toBe(0);
});
test("shell cwd('') should use current working directory", async () => {
using dir = tempDir("shell-cwd-empty", {
"test.js": `
import { $ } from "bun";
const result = await $\`pwd\`.cwd("").text();
console.log(result.trim());
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "test.js"],
env: bunEnv,
cwd: String(dir),
stdout: "pipe",
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stderr).toBe("");
expect(stdout.trim()).toBe(String(dir));
expect(exitCode).toBe(0);
});
test("shell cwd('./') should use current working directory", async () => {
using dir = tempDir("shell-cwd-dotslash", {
"test.js": `
import { $ } from "bun";
const result = await $\`pwd\`.cwd("./").text();
console.log(result.trim());
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "test.js"],
env: bunEnv,
cwd: String(dir),
stdout: "pipe",
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stderr).toBe("");
expect(stdout.trim()).toBe(String(dir));
expect(exitCode).toBe(0);
});
test("Shell prototype cwd('.') should use current working directory", async () => {
using dir = tempDir("shell-proto-cwd-dot", {
"test.js": `
import { $ } from "bun";
const shell = new $.Shell();
shell.cwd(".");
const result = await shell\`pwd\`.text();
console.log(result.trim());
`,
});
await using proc = Bun.spawn({
cmd: [bunExe(), "test.js"],
env: bunEnv,
cwd: String(dir),
stdout: "pipe",
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stderr).toBe("");
expect(stdout.trim()).toBe(String(dir));
expect(exitCode).toBe(0);
});