diff --git a/src/cli.zig b/src/cli.zig index e2a62330cc..5f6f7026cc 100644 --- a/src/cli.zig +++ b/src/cli.zig @@ -690,13 +690,26 @@ pub const Command = struct { const original_argv_len = bun.argv.len; var argv_list = std.array_list.Managed([:0]const u8).fromOwnedSlice(bun.default_allocator, bun.argv); try bun.appendOptionsEnv(graph.compile_exec_argv, &argv_list, bun.default_allocator); - bun.argv = argv_list.items; + + // Store the full argv including user arguments + const full_argv = argv_list.items; + const num_exec_argv_options = full_argv.len -| original_argv_len; // Calculate offset: skip executable name + all exec argv options - offset_for_passthrough = if (bun.argv.len > 1) 1 + (bun.argv.len -| original_argv_len) else 0; + offset_for_passthrough = if (full_argv.len > 1) 1 + num_exec_argv_options else 0; + + // Temporarily set bun.argv to only include executable name + exec_argv options. + // This prevents user arguments like --version/--help from being intercepted + // by Bun's argument parser (they should be passed through to user code). + bun.argv = full_argv[0..@min(1 + num_exec_argv_options, full_argv.len)]; // Handle actual options to parse. - break :brk try Command.init(allocator, log, .AutoCommand); + const result = try Command.init(allocator, log, .AutoCommand); + + // Restore full argv so passthrough calculation works correctly + bun.argv = full_argv; + + break :brk result; } context_data = .{ diff --git a/test/bundler/compile-argv.test.ts b/test/bundler/compile-argv.test.ts index 6d7ea8d20f..50b32fa5fb 100644 --- a/test/bundler/compile-argv.test.ts +++ b/test/bundler/compile-argv.test.ts @@ -175,4 +175,105 @@ describe("bundler", () => { stdout: /SUCCESS: user arguments properly passed with exec argv present/, }, }); + + // Test that --version and --help flags are passed through to user code (issue #26082) + // When compile-exec-argv is used, user flags like --version should NOT be intercepted by Bun + itBundled("compile/CompileExecArgvVersionHelpPassthrough", { + compile: { + execArgv: ["--smol"], + }, + backend: "cli", + files: { + "/entry.ts": /* js */ ` + // Test that --version and --help are passed through to user code, not intercepted by Bun + const args = process.argv.slice(2); + console.log("User args:", JSON.stringify(args)); + + if (args.includes("--version")) { + console.log("APP_VERSION:1.0.0"); + } else if (args.includes("-v")) { + console.log("APP_VERSION:1.0.0"); + } else if (args.includes("--help")) { + console.log("APP_HELP:This is my app help"); + } else if (args.includes("-h")) { + console.log("APP_HELP:This is my app help"); + } else { + console.log("NO_FLAG_MATCHED"); + } + `, + }, + run: { + args: ["--version"], + stdout: /APP_VERSION:1\.0\.0/, + }, + }); + + // Test with -v short flag + itBundled("compile/CompileExecArgvShortVersionPassthrough", { + compile: { + execArgv: ["--smol"], + }, + backend: "cli", + files: { + "/entry.ts": /* js */ ` + const args = process.argv.slice(2); + if (args.includes("-v")) { + console.log("APP_VERSION:1.0.0"); + } else { + console.log("FAIL: -v not found in args:", args); + process.exit(1); + } + `, + }, + run: { + args: ["-v"], + stdout: /APP_VERSION:1\.0\.0/, + }, + }); + + // Test with --help flag + itBundled("compile/CompileExecArgvHelpPassthrough", { + compile: { + execArgv: ["--smol"], + }, + backend: "cli", + files: { + "/entry.ts": /* js */ ` + const args = process.argv.slice(2); + if (args.includes("--help")) { + console.log("APP_HELP:my custom help"); + } else { + console.log("FAIL: --help not found in args:", args); + process.exit(1); + } + `, + }, + run: { + args: ["--help"], + stdout: /APP_HELP:my custom help/, + }, + }); + + // Test with -h short flag + itBundled("compile/CompileExecArgvShortHelpPassthrough", { + compile: { + execArgv: ["--smol"], + }, + backend: "cli", + files: { + "/entry.ts": /* js */ ` + const args = process.argv.slice(2); + if (args.includes("-h")) { + console.log("APP_HELP:my custom help"); + } else { + console.log("FAIL: -h not found in args:", args); + process.exit(1); + } + `, + }, + run: { + args: ["-h"], + stdout: /APP_HELP:my custom help/, + }, + }); });