mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 02:48:50 +00:00
## Summary Fixes an issue where compiled standalone binaries included an extra executable name argument in `process.argv`, breaking code that uses `node:util.parseArgs()` with `process.argv.slice(2)`. ## Problem When running a compiled binary, `process.argv` incorrectly included the executable name as a third argument: ```bash ./my-app # process.argv = ["bun", "/$bunfs/root/my-app", "./my-app"] # BUG ``` This caused `parseArgs()` to fail with "Unexpected argument" errors, breaking previously valid code. ## Solution Fixed the `offset_for_passthrough` calculation in `cli.zig` to always skip the executable name for standalone binaries, ensuring `process.argv` only contains the runtime name and script path: ```bash ./my-app # process.argv = ["bun", "/$bunfs/root/my-app"] # FIXED ``` ## Test plan - [x] Added regression test in `test/regression/issue/22157.test.ts` - [x] Verified existing exec-argv functionality still works correctly - [x] Manual testing confirms the fix resolves the parseArgs issue Fixes #22157 🤖 Generated with [Claude Code](https://claude.ai/code) --------- Co-authored-by: Claude Bot <claude-bot@bun.sh> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Michael H <git@riskymh.dev> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
101 lines
2.8 KiB
TypeScript
101 lines
2.8 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { bunEnv, bunExe, tempDirWithFiles } from "harness";
|
|
|
|
// Regression test for https://github.com/oven-sh/bun/issues/22157
|
|
// Compiled binaries were including executable name in process.argv
|
|
test("issue 22157: compiled binary should not include executable name in process.argv", async () => {
|
|
const dir = tempDirWithFiles("22157-basic", {
|
|
"index.js": /* js */ `
|
|
import { parseArgs } from "node:util"
|
|
|
|
console.log(JSON.stringify(process.argv));
|
|
|
|
// This should work - no extra executable name should cause parseArgs to throw
|
|
parseArgs({
|
|
args: process.argv.slice(2),
|
|
});
|
|
|
|
console.log("SUCCESS");
|
|
`,
|
|
});
|
|
|
|
// Compile the binary
|
|
await using compileProc = Bun.spawn({
|
|
cmd: [bunExe(), "build", "--compile", "--outfile=test-binary", "./index.js"],
|
|
cwd: dir,
|
|
env: bunEnv,
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
});
|
|
|
|
await compileProc.exited;
|
|
|
|
// Run the compiled binary - should not throw
|
|
await using runProc = Bun.spawn({
|
|
cmd: ["./test-binary"],
|
|
cwd: dir,
|
|
env: bunEnv,
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
});
|
|
|
|
const [stdout, exitCode] = await Promise.all([runProc.stdout.text(), runProc.exited]);
|
|
|
|
expect(exitCode).toBe(0);
|
|
expect(stdout).toContain("SUCCESS");
|
|
|
|
// Verify process.argv structure
|
|
const argvMatch = stdout.match(/\[.*?\]/);
|
|
expect(argvMatch).toBeTruthy();
|
|
|
|
const processArgv = JSON.parse(argvMatch![0]);
|
|
expect(processArgv).toHaveLength(2);
|
|
expect(processArgv[0]).toBe("bun");
|
|
// Windows uses "B:/~BUN/root/", Unix uses "/$bunfs/root/"
|
|
expect(processArgv[1]).toMatch(/(\$bunfs|~BUN).*root/);
|
|
});
|
|
|
|
test("issue 22157: compiled binary with user args should pass them correctly", async () => {
|
|
const dir = tempDirWithFiles("22157-args", {
|
|
"index.js": /* js */ `
|
|
console.log(JSON.stringify(process.argv));
|
|
|
|
// Expect: ["bun", "/$bunfs/root/..." or "B:/~BUN/root/...", "arg1", "arg2"]
|
|
if (process.argv.length !== 4) {
|
|
console.error("Expected 4 argv items, got", process.argv.length);
|
|
process.exit(1);
|
|
}
|
|
|
|
if (process.argv[2] !== "arg1" || process.argv[3] !== "arg2") {
|
|
console.error("User args not correct");
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log("SUCCESS");
|
|
`,
|
|
});
|
|
|
|
await using compileProc = Bun.spawn({
|
|
cmd: [bunExe(), "build", "--compile", "--outfile=test-binary", "./index.js"],
|
|
cwd: dir,
|
|
env: bunEnv,
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
});
|
|
|
|
await compileProc.exited;
|
|
|
|
await using runProc = Bun.spawn({
|
|
cmd: ["./test-binary", "arg1", "arg2"],
|
|
cwd: dir,
|
|
env: bunEnv,
|
|
stdout: "pipe",
|
|
stderr: "pipe",
|
|
});
|
|
|
|
const [stdout, exitCode] = await Promise.all([runProc.stdout.text(), runProc.exited]);
|
|
|
|
expect(exitCode).toBe(0);
|
|
expect(stdout).toContain("SUCCESS");
|
|
});
|