From 0e0c922cc5a0b53164579fe6ba5e8705229c696b Mon Sep 17 00:00:00 2001 From: soldforaloss Date: Fri, 10 Jul 2026 15:30:57 -0700 Subject: [PATCH] fix: preserve current Node for node.exe env wrappers (#103907) * fix: preserve current Node for node.exe env wrappers * fix(scripts): preserve Windows Node aliases * chore: keep contributor PR release-note only --------- Co-authored-by: Peter Steinberger --- scripts/run-with-env.mjs | 15 ++++++++++++--- test/scripts/run-with-env.test.ts | 31 +++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/scripts/run-with-env.mjs b/scripts/run-with-env.mjs index 3d152e91c57..ad348777261 100644 --- a/scripts/run-with-env.mjs +++ b/scripts/run-with-env.mjs @@ -48,10 +48,19 @@ export function parseRunWithEnvArgs(argv) { } /** - * Resolves node to the current executable so wrapper and child use the same runtime. + * Resolves bare Node command names to the current executable so wrapper and child use the same + * runtime. Windows command lookup is case-insensitive; explicit paths remain caller-owned. */ -export function resolveSpawnCommand(command, args, execPath = process.execPath) { - if (command === "node") { +export function resolveSpawnCommand( + command, + args, + execPath = process.execPath, + platform = process.platform, +) { + const normalizedCommand = platform === "win32" ? command.toLowerCase() : command; + const isNodeCommand = + normalizedCommand === "node" || (platform === "win32" && normalizedCommand === "node.exe"); + if (isNodeCommand) { return { command: execPath, args, diff --git a/test/scripts/run-with-env.test.ts b/test/scripts/run-with-env.test.ts index 7635dc91538..5caa83200c8 100644 --- a/test/scripts/run-with-env.test.ts +++ b/test/scripts/run-with-env.test.ts @@ -143,10 +143,33 @@ describe("run-with-env", () => { expect(result.stderr).toContain("invalid environment assignment"); }); - it("uses the current Node executable for node commands", () => { - expect(resolveSpawnCommand("node", ["scripts/run-vitest.mjs"], "node.exe")).toEqual({ - command: "node.exe", - args: ["scripts/run-vitest.mjs"], + it("uses the current Node executable for bare Node command names", () => { + const args = ["scripts/run-vitest.mjs"]; + expect(resolveSpawnCommand("node", args, "/usr/bin/node", "linux")).toEqual({ + command: "/usr/bin/node", + args, + }); + for (const command of ["node", "NODE", "node.exe", "Node.Exe"]) { + expect(resolveSpawnCommand(command, args, "C:\\Node24\\node.exe", "win32")).toEqual({ + command: "C:\\Node24\\node.exe", + args, + }); + } + }); + + it("preserves platform-specific and explicitly pathed commands", () => { + const args = ["scripts/run-vitest.mjs"]; + for (const command of ["NODE", "node.exe", "C:\\Tools\\node.exe"]) { + expect(resolveSpawnCommand(command, args, "/usr/bin/node", "linux")).toEqual({ + command, + args, + }); + } + expect( + resolveSpawnCommand("C:\\Tools\\node.exe", args, "C:\\Node24\\node.exe", "win32"), + ).toEqual({ + command: "C:\\Tools\\node.exe", + args, }); });