Add timeout for shell-utils to prevent hangs. (#16667)

This commit is contained in:
Jacob Richman
2026-01-14 16:48:02 -08:00
committed by GitHub
parent 4b2e9f7954
commit ae198029bc
2 changed files with 57 additions and 3 deletions

View File

@@ -44,6 +44,16 @@ vi.mock('shell-quote', () => ({
quote: mockQuote,
}));
const mockDebugLogger = vi.hoisted(() => ({
error: vi.fn(),
debug: vi.fn(),
log: vi.fn(),
warn: vi.fn(),
}));
vi.mock('./debugLogger.js', () => ({
debugLogger: mockDebugLogger,
}));
const isWindowsRuntime = process.platform === 'win32';
const describeWindowsOnly = isWindowsRuntime ? describe : describe.skip;
@@ -161,6 +171,28 @@ describe('getCommandRoots', () => {
const roots = shellUtils.getCommandRoots('ls -la');
expect(roots).toEqual([]);
});
it('should handle bash parser timeouts', () => {
const nowSpy = vi.spyOn(performance, 'now');
// Mock performance.now() to trigger timeout:
// 1st call: start time = 0. deadline = 0 + 1000ms.
// 2nd call (and onwards): inside progressCallback, return 2000ms.
nowSpy.mockReturnValueOnce(0).mockReturnValue(2000);
// Use a very complex command to ensure progressCallback is triggered at least once
const complexCommand =
'ls -la && ' + Array(100).fill('echo "hello"').join(' && ');
const roots = getCommandRoots(complexCommand);
expect(roots).toEqual([]);
expect(nowSpy).toHaveBeenCalled();
expect(mockDebugLogger.error).toHaveBeenCalledWith(
'Bash command parsing timed out for command:',
complexCommand,
);
nowSpy.mockRestore();
});
});
describe('hasRedirection', () => {