mirror of
https://github.com/stablyai/orca.git
synced 2026-10-16 00:03:09 +00:00
fix: clean up command runner capture listeners
This commit is contained in:
@@ -112,6 +112,10 @@ describe('commandExecFileAsync Windows command shims', () => {
|
||||
expect.objectContaining({ stdio: 'ignore', windowsHide: true })
|
||||
)
|
||||
expect(command.kill).not.toHaveBeenCalled()
|
||||
expect(command.stdout.listenerCount('data')).toBe(0)
|
||||
expect(command.stderr.listenerCount('data')).toBe(0)
|
||||
expect(command.listenerCount('error')).toBe(0)
|
||||
expect(command.listenerCount('close')).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -137,6 +141,30 @@ describe('commandExecFileAsync Windows command shims', () => {
|
||||
expect.objectContaining({ stdio: 'ignore', windowsHide: true })
|
||||
)
|
||||
expect(command.kill).not.toHaveBeenCalled()
|
||||
expect(command.stdout.listenerCount('data')).toBe(0)
|
||||
expect(command.stderr.listenerCount('data')).toBe(0)
|
||||
expect(command.listenerCount('error')).toBe(0)
|
||||
expect(command.listenerCount('close')).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
it('removes listeners after successful Windows .cmd shim executions', async () => {
|
||||
await withPlatform('win32', async () => {
|
||||
const command = createMockChildProcess(1234)
|
||||
spawnMock.mockReturnValue(command)
|
||||
|
||||
const promise = commandExecFileAsync('C:\\tools\\pnpm.cmd', ['--version'], {
|
||||
cwd: 'C:\\repo'
|
||||
})
|
||||
command.stdout.emit('data', Buffer.from('9.1.0\n'))
|
||||
command.stderr.emit('data', Buffer.from('notice\n'))
|
||||
command.emit('close', 0)
|
||||
|
||||
await expect(promise).resolves.toEqual({ stdout: '9.1.0\n', stderr: 'notice\n' })
|
||||
expect(command.stdout.listenerCount('data')).toBe(0)
|
||||
expect(command.stderr.listenerCount('data')).toBe(0)
|
||||
expect(command.listenerCount('error')).toBe(0)
|
||||
expect(command.listenerCount('close')).toBe(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
+25
-11
@@ -296,15 +296,23 @@ async function spawnCommandCapture(
|
||||
killSpawnedCommandTree(child)
|
||||
finish(createAbortError())
|
||||
}
|
||||
const cleanupListeners = (): void => {
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
timer = null
|
||||
}
|
||||
options.signal?.removeEventListener('abort', onAbort)
|
||||
child.stdout?.off('data', onStdoutData)
|
||||
child.stderr?.off('data', onStderrData)
|
||||
child.off('error', onError)
|
||||
child.off('close', onClose)
|
||||
}
|
||||
const finish = (error: Error | null): void => {
|
||||
if (settled) {
|
||||
return
|
||||
}
|
||||
settled = true
|
||||
if (timer) {
|
||||
clearTimeout(timer)
|
||||
}
|
||||
options.signal?.removeEventListener('abort', onAbort)
|
||||
cleanupListeners()
|
||||
if (error) {
|
||||
reject(Object.assign(error, { stdout, stderr }))
|
||||
return
|
||||
@@ -318,7 +326,7 @@ async function spawnCommandCapture(
|
||||
}, options.timeout)
|
||||
: null
|
||||
options.signal?.addEventListener('abort', onAbort, { once: true })
|
||||
child.stdout?.on('data', (chunk: Buffer) => {
|
||||
function onStdoutData(chunk: Buffer): void {
|
||||
stdoutBytes += chunk.byteLength
|
||||
if (options.maxBuffer && stdoutBytes > options.maxBuffer) {
|
||||
killSpawnedCommandTree(child)
|
||||
@@ -326,8 +334,8 @@ async function spawnCommandCapture(
|
||||
return
|
||||
}
|
||||
stdout += chunk.toString(options.encoding ?? 'utf-8')
|
||||
})
|
||||
child.stderr?.on('data', (chunk: Buffer) => {
|
||||
}
|
||||
function onStderrData(chunk: Buffer): void {
|
||||
stderrBytes += chunk.byteLength
|
||||
if (options.maxBuffer && stderrBytes > options.maxBuffer) {
|
||||
killSpawnedCommandTree(child)
|
||||
@@ -335,15 +343,21 @@ async function spawnCommandCapture(
|
||||
return
|
||||
}
|
||||
stderr += chunk.toString(options.encoding ?? 'utf-8')
|
||||
})
|
||||
child.on('error', finish)
|
||||
child.on('close', (code) => {
|
||||
}
|
||||
function onError(error: Error): void {
|
||||
finish(error)
|
||||
}
|
||||
function onClose(code: number | null): void {
|
||||
if (code === 0) {
|
||||
finish(null)
|
||||
return
|
||||
}
|
||||
finish(new Error(`${command} exited with ${code}.`))
|
||||
})
|
||||
}
|
||||
child.stdout?.on('data', onStdoutData)
|
||||
child.stderr?.on('data', onStderrData)
|
||||
child.on('error', onError)
|
||||
child.on('close', onClose)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user