fix(runtime): close async cleanup and framing races
This commit is contained in:
@@ -7,7 +7,7 @@ describe('TerminalSanitizer', () => {
|
||||
expect(sanitizer.push('red\x1b[3')).toEqual({ text: 'red', prompt: false })
|
||||
expect(sanitizer.push('1m text\x1b[0m\r\n')).toEqual({ text: ' text\n', prompt: false })
|
||||
expect(sanitizer.push('\x1b]133;')).toEqual({ text: '', prompt: false })
|
||||
expect(sanitizer.push('D;0\x07dsh> ')).toEqual({ text: 'dsh> ', prompt: true, promptText: true })
|
||||
expect(sanitizer.push('D;0\x07dsh> ')).toEqual({ text: 'dsh> ', prompt: true, promptTail: 'dsh> ' })
|
||||
})
|
||||
|
||||
it('drops unrelated OSC, short escapes, BEL, and incomplete trailing escape', () => {
|
||||
@@ -35,8 +35,8 @@ describe('TerminalSanitizer', () => {
|
||||
|
||||
it('reports printable prompt text that follows a marker in a later chunk', () => {
|
||||
const sanitizer = new TerminalSanitizer(64)
|
||||
expect(sanitizer.push('\x1b]133;D;0\x07')).toEqual({ text: '', prompt: true })
|
||||
expect(sanitizer.push('dsh> ')).toEqual({ text: 'dsh> ', prompt: false, promptText: true })
|
||||
expect(sanitizer.push('\x1b]133;D;0\x07')).toEqual({ text: '', prompt: true, promptTail: '' })
|
||||
expect(sanitizer.push('dsh> ')).toEqual({ text: 'dsh> ', prompt: false, promptTail: 'dsh> ' })
|
||||
})
|
||||
|
||||
it('bounds and discards unterminated control sequences through their terminators', () => {
|
||||
|
||||
@@ -268,6 +268,29 @@ describe('LocalPtySession readiness and output', () => {
|
||||
failedInternal.fail(new Error('ignored'))
|
||||
})
|
||||
|
||||
it('does not write a send canceled during asynchronous foreground inspection', async () => {
|
||||
vi.useFakeTimers()
|
||||
const terminal = new FakeTerminal()
|
||||
const inspector = new FakeInspector()
|
||||
const session = makeSession(terminal, inspector, config())
|
||||
await initialize(session, terminal)
|
||||
|
||||
const inspection = Promise.withResolvers<{ processGroupId: number; inputWaiting: boolean }>()
|
||||
terminal.inspectForeground = async () => await inspection.promise
|
||||
const controller = new AbortController()
|
||||
const operation = session.startSend({ text: 'must not execute', submit: true, signal: controller.signal })
|
||||
controller.abort()
|
||||
inspection.resolve({ processGroupId: 456, inputWaiting: false })
|
||||
await Promise.resolve()
|
||||
await Promise.resolve()
|
||||
|
||||
expect(terminal.writes).toEqual([])
|
||||
expect(inspector.groups).toContainEqual([456, 'SIGINT'])
|
||||
terminal.emitData('\x1b]133;D;130\x07dsh> ')
|
||||
await vi.advanceTimersByTimeAsync(10)
|
||||
await operation.done
|
||||
})
|
||||
|
||||
it('retains send ownership after timeout until an asynchronous provider write settles', async () => {
|
||||
vi.useFakeTimers()
|
||||
const terminal = new FakeTerminal()
|
||||
@@ -418,6 +441,27 @@ describe('LocalPtySession readiness and output', () => {
|
||||
expect(session.motd).toBe('dsh> ')
|
||||
})
|
||||
|
||||
it('does not attribute a delayed prior prompt to the current send', async () => {
|
||||
vi.useFakeTimers()
|
||||
const terminal = new FakeTerminal()
|
||||
const session = new LocalPtySession(terminal, config({ idleSilenceMs: 100, timeoutMs: 200 }))
|
||||
await initialize(session, terminal)
|
||||
|
||||
const operation = session.startSend({ text: "printf 'PID=%s\\n' \"$!\"", submit: true })
|
||||
let settled = false
|
||||
void operation.done.then(() => { settled = true })
|
||||
await Promise.resolve()
|
||||
await Promise.resolve()
|
||||
|
||||
terminal.emitData('\x1b]133;D;0\x07dsh> printf \'PID=%s\\n\' "$!"\r\n')
|
||||
await vi.advanceTimersByTimeAsync(20)
|
||||
expect(settled).toBe(false)
|
||||
|
||||
terminal.emitData('PID=123\r\n\x1b]133;D;0\x07dsh> ')
|
||||
await vi.advanceTimersByTimeAsync(10)
|
||||
expect(await operation.done).toMatchObject({ waitReason: 'stdin_read' })
|
||||
})
|
||||
|
||||
it('retains a prompt marker until the startup shell regains the foreground group', async () => {
|
||||
vi.useFakeTimers()
|
||||
const terminal = new FakeTerminal()
|
||||
|
||||
Reference in New Issue
Block a user