mirror of
https://github.com/stablyai/orca.git
synced 2026-10-24 00:04:01 +00:00
fix(pty): read the incarnation through the shared guard, not truthiness
A malformed incarnation is evidence of nothing, so it must read as "unknown" rather than as a value that disagrees with every well-formed one — otherwise a non-string on the payload would discard the very exits the buffer exists to deliver. Route both the record and the comparison through the existing isPtyIncarnationId guard.
This commit is contained in:
@@ -276,6 +276,20 @@ describe('pre-handler PTY buffer', () => {
|
||||
expect(hasPreHandlerPtyExit(RECYCLED_PTY_ID)).toBe(true)
|
||||
})
|
||||
|
||||
// A malformed incarnation is evidence of nothing. Treating it as a value that disagrees with
|
||||
// everything would discard the very exits the buffer exists to deliver.
|
||||
it('treats a malformed incarnation as unknown rather than as a disagreement', () => {
|
||||
bufferPreHandlerPtyExit(RECYCLED_PTY_ID, 4, { not: 'a string' })
|
||||
discardPreHandlerPtyExitFromForeignIncarnation(RECYCLED_PTY_ID, FRESH_INCARNATION_ID)
|
||||
expect(hasPreHandlerPtyExit(RECYCLED_PTY_ID)).toBe(true)
|
||||
drainPreHandlerPtyExit(RECYCLED_PTY_ID, vi.fn())
|
||||
|
||||
clearConsumedPreHandlerPtyExit(RECYCLED_PTY_ID)
|
||||
bufferPreHandlerPtyExit(RECYCLED_PTY_ID, 5, PRIOR_INCARNATION_ID)
|
||||
discardPreHandlerPtyExitFromForeignIncarnation(RECYCLED_PTY_ID, 42)
|
||||
expect(hasPreHandlerPtyExit(RECYCLED_PTY_ID)).toBe(true)
|
||||
})
|
||||
|
||||
it('re-admits exits for a recycled id whose prior incarnation was consumed', () => {
|
||||
consumePreHandlerPtyState(RECYCLED_PTY_ID)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { isPtyIncarnationId } from '../../../../shared/pty-incarnation'
|
||||
import { clampUtf8Tail } from './pty-eager-buffer-clamp'
|
||||
import type { PtyDataMeta } from './pty-dispatcher'
|
||||
|
||||
@@ -81,9 +82,11 @@ function reserveBoundedPtySlot<V>(map: Map<string, V>, ptyId: string, cap: numbe
|
||||
* existing id, and re-owning incarnation X is still proof that W's exit was not theirs. */
|
||||
export function discardPreHandlerPtyExitFromForeignIncarnation(
|
||||
ptyId: string,
|
||||
incarnationId: string | undefined
|
||||
incarnationId: unknown
|
||||
): void {
|
||||
if (!incarnationId) {
|
||||
// Why the shared guard and not a truthiness check: anything that is not a well-formed incarnation
|
||||
// is evidence of nothing, and must read as "unknown" rather than disagree with everything.
|
||||
if (!isPtyIncarnationId(incarnationId)) {
|
||||
return
|
||||
}
|
||||
const exit = preHandlerPtyExit.get(ptyId)
|
||||
@@ -164,7 +167,11 @@ export function replayPreHandlerPtyData(ptyId: string, observer: (data: string)
|
||||
}
|
||||
}
|
||||
|
||||
export function bufferPreHandlerPtyExit(ptyId: string, code: number, incarnationId?: string): void {
|
||||
export function bufferPreHandlerPtyExit(
|
||||
ptyId: string,
|
||||
code: number,
|
||||
incarnationId?: unknown
|
||||
): void {
|
||||
if (consumedPreHandlerPtyExits.has(ptyId) || discardedPreHandlerPtyStates.has(ptyId)) {
|
||||
return
|
||||
}
|
||||
@@ -172,7 +179,8 @@ export function bufferPreHandlerPtyExit(ptyId: string, code: number, incarnation
|
||||
preHandlerPtyExit.set(ptyId, {
|
||||
code,
|
||||
sequence: nextPreHandlerPtySequence(),
|
||||
...(incarnationId ? { incarnationId } : {})
|
||||
// Record only a well-formed incarnation; a malformed one must not become evidence.
|
||||
...(isPtyIncarnationId(incarnationId) ? { incarnationId } : {})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user