diff --git a/src/normalize.ts b/src/normalize.ts index 619eb99..2931f29 100644 --- a/src/normalize.ts +++ b/src/normalize.ts @@ -11,7 +11,7 @@ import {getPathFromEnv} from './env.js'; // See http://www.robvanderwoude.com/escapechars.php const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g; -const shebangRegExp = /^#!\s*(.+)$/; +const shebangRegExp = /^#!\s*(.+)/; const isWindowsExecutableRegExp = /\.(?:com|exe)$/i; const isNodeModulesCmdRegExp = /node_modules[\\/]\.bin[\\/][^\\/]+\.cmd$/i; const isWindows = process.platform === 'win32'; diff --git a/src/test/normalize_test.ts b/src/test/normalize_test.ts index fbc36ba..cd52bbc 100644 --- a/src/test/normalize_test.ts +++ b/src/test/normalize_test.ts @@ -7,7 +7,7 @@ import {fileURLToPath} from 'node:url'; const isWindows = os.platform() === 'win32'; const fixturesPath = path.join( path.dirname(fileURLToPath(import.meta.url)), - '../test/fixtures' + '../../test/fixtures' ); const cwd = process.cwd(); @@ -61,6 +61,16 @@ describe('normalizeSpawnCommand', () => { }); }); + test('detects shebang and rewrites command to interpreter', () => { + const scriptPath = path.join(fixturesPath, 'shebang_script.js'); + const normalized = normalizeSpawnCommand(scriptPath, []); + + // where resolves to where.exe (always a .exe in System32, never a + // shim), so the cmd.exe wrapping branch is skipped + expect(normalized.command).toBe('where'); + expect(normalized.args).toEqual([scriptPath]); + }); + test('handles relative commands without extension', () => { const relativePath = path.relative( cwd, diff --git a/test/fixtures/shebang_script.js b/test/fixtures/shebang_script.js new file mode 100644 index 0000000..a3763eb --- /dev/null +++ b/test/fixtures/shebang_script.js @@ -0,0 +1,2 @@ +#!where +not a real script, just used to verify shebang parsing