Merge pull request #1829 from code-yeongyu/fix/issue-1805-lsp-windows-binary

fix(lsp): remove unreliable Windows binary availability check
This commit is contained in:
YeonGyu-Kim
2026-02-14 15:01:35 +09:00
committed by GitHub
2 changed files with 38 additions and 26 deletions

View File

@@ -0,0 +1,37 @@
import { mkdtempSync, rmSync } from "node:fs"
import { tmpdir } from "node:os"
import { join } from "node:path"
import { describe, expect, it, spyOn } from "bun:test"
describe("spawnProcess", () => {
it("proceeds to node spawn on Windows when command is available", async () => {
//#given
const originalPlatform = process.platform
const rootDir = mkdtempSync(join(tmpdir(), "lsp-process-test-"))
const childProcess = await import("node:child_process")
const nodeSpawnSpy = spyOn(childProcess, "spawn")
try {
Object.defineProperty(process, "platform", { value: "win32" })
const { spawnProcess } = await import("./lsp-process")
//#when
let result: ReturnType<typeof spawnProcess> | null = null
expect(() => {
result = spawnProcess(["node", "--version"], {
cwd: rootDir,
env: process.env,
})
}).not.toThrow(/Binary 'node' not found/)
//#then
expect(nodeSpawnSpy).toHaveBeenCalled()
expect(result).not.toBeNull()
} finally {
Object.defineProperty(process, "platform", { value: originalPlatform })
nodeSpawnSpy.mockRestore()
rmSync(rootDir, { recursive: true, force: true })
}
})
})

View File

@@ -1,5 +1,5 @@
import { spawn as bunSpawn } from "bun"
import { spawn as nodeSpawn, spawnSync, type ChildProcess } from "node:child_process"
import { spawn as nodeSpawn, type ChildProcess } from "node:child_process"
import { existsSync, statSync } from "fs"
import { log } from "../../shared/logger"
// Bun spawn segfaults on Windows (oven-sh/bun#25798) — unfixed as of v1.3.8+
@@ -21,24 +21,6 @@ export function validateCwd(cwd: string): { valid: boolean; error?: string } {
return { valid: false, error: `Cannot access working directory: ${cwd} (${err instanceof Error ? err.message : String(err)})` }
}
}
function isBinaryAvailableOnWindows(command: string): boolean {
if (process.platform !== "win32") return true
if (command.includes("/") || command.includes("\\")) {
return existsSync(command)
}
try {
const result = spawnSync("where", [command], {
shell: true,
windowsHide: true,
timeout: 5000,
})
return result.status === 0
} catch {
return true
}
}
interface StreamReader {
read(): Promise<{ done: boolean; value: Uint8Array | undefined }>
}
@@ -158,13 +140,6 @@ export function spawnProcess(
}
if (shouldUseNodeSpawn()) {
const [cmd, ...args] = command
if (!isBinaryAvailableOnWindows(cmd)) {
throw new Error(
`[LSP] Binary '${cmd}' not found on Windows. ` +
`Ensure the LSP server is installed and available in PATH. ` +
`For npm packages, try: npm install -g ${cmd}`
)
}
log("[LSP] Using Node.js child_process on Windows to avoid Bun spawn segfault")
const proc = nodeSpawn(cmd, args, {
cwd: options.cwd,