diff --git a/src/cli/run_command.zig b/src/cli/run_command.zig index 2d099b25dd..956dd9f851 100644 --- a/src/cli/run_command.zig +++ b/src/cli/run_command.zig @@ -1053,9 +1053,6 @@ pub const RunCommand = struct { bun.copy(u8, path_buf[dir_slice.len..], base); path_buf[dir_slice.len + base.len] = 0; const slice = path_buf[0 .. dir_slice.len + base.len :0]; - if (Environment.isWindows) { - @panic("TODO"); - } if (!(bun.sys.isExecutableFilePath(slice))) continue; // we need to dupe because the string pay point to a pointer that only exists in the current scope _ = try results.getOrPut(this_transpiler.fs.filename_store.append(@TypeOf(base), base) catch continue); diff --git a/src/sys.zig b/src/sys.zig index c9aff7d40d..a2b860fed3 100644 --- a/src/sys.zig +++ b/src/sys.zig @@ -3430,29 +3430,23 @@ pub fn isExecutableFileOSPath(path: bun.OSPathSliceZ) bool { if (comptime Environment.isWindows) { // Rationale: `GetBinaryTypeW` does not work on .cmd files. - // Windows does not have executable permission like posix does, instead we - // can just look at the file extension to determine executable status. - @compileError("Do not use isExecutableFilePath on Windows"); + // SaferiIsExecutableFileType works on .cmd files. + // The following file name extensions are examples of executable file types. This is not a complete list. + // .bat + // .cmd + // .com + // .exe + // .js + // .lnk + // .pif + // .pl + // .shs + // .url + // .vbs + // The security policy Microsoft Management Console (MMC) snap-in (Secpol.msc) controls which extensions are considered executable file types. - // var out: windows.DWORD = 0; - // const rc = kernel32.GetBinaryTypeW(path, &out); - - // const result = if (rc == windows.FALSE) - // false - // else switch (out) { - // kernel32.SCS_32BIT_BINARY, - // kernel32.SCS_64BIT_BINARY, - // kernel32.SCS_DOS_BINARY, - // kernel32.SCS_OS216_BINARY, - // kernel32.SCS_PIF_BINARY, - // kernel32.SCS_POSIX_BINARY, - // => true, - // else => false, - // }; - - // log("GetBinaryTypeW({f}) = {d}. isExecutable={}", .{ bun.fmt.utf16(path), out, result }); - - // return result; + // we pass false to include .exe files (see https://learn.microsoft.com/en-us/windows/win32/api/winsafer/nf-winsafer-saferiisexecutablefiletype) + return bun.windows.SaferiIsExecutableFileType(path, w.FALSE) != w.FALSE; } @compileError("TODO: isExecutablePath"); diff --git a/src/windows.zig b/src/windows.zig index d358b7a5ad..a909b11858 100644 --- a/src/windows.zig +++ b/src/windows.zig @@ -150,7 +150,7 @@ pub extern "kernel32" fn SetCurrentDirectoryW( ) callconv(.winapi) win32.BOOL; pub const SetCurrentDirectory = SetCurrentDirectoryW; pub extern "ntdll" fn RtlNtStatusToDosError(win32.NTSTATUS) callconv(.winapi) Win32Error; - +pub extern "advapi32" fn SaferiIsExecutableFileType(szFullPathname: win32.LPCWSTR, bFromShellExecute: win32.BOOLEAN) callconv(.winapi) win32.BOOL; // This was originally copied from Zig's standard library /// Codes are from https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d pub const Win32Error = enum(u16) { diff --git a/test/cli/bun.test.ts b/test/cli/bun.test.ts index c6dd62858f..cf2b66794c 100644 --- a/test/cli/bun.test.ts +++ b/test/cli/bun.test.ts @@ -59,7 +59,16 @@ describe("bun", () => { ); }); }); - + describe("getcompletes", () => { + test("getcompletes should not panic and should not be empty", () => { + const { stdout, exitCode } = spawnSync({ + cmd: [bunExe(), "getcompletes"], + env: bunEnv, + }); + expect(exitCode).toBe(0); + expect(stdout.toString()).not.toBeEmpty(); + }); + }); describe("test command line arguments", () => { test("test --config, issue #4128", () => { const path = `${tmpdir()}/bunfig-${Date.now()}.toml`;