fix(pty): close overlapping-arm and cancellation blockers

Overlapping recovery/ordinary arms now classify unknown instead of
last-write-wins, and cancelOrdinary is implemented rather than merely
declared on the interface.

Removes 186 duplicated test blocks left by a stuck commit-retry loop
(201 it() blocks, 15 unique). Marks two tests as todo: both asserted
that an abandoned ordinary arm yields unknown from a call sequence
identical to an existing test expecting ordinary, so they were
unsatisfiable without a veto signal.

Mutants: overlap poisoning removed -> 3 tests red; cancelOrdinary
no-op -> 2 tests red. 2/2 killed.
This commit is contained in:
Jinwoo-H
2026-08-07 18:03:21 -04:00
parent 5e283b7038
commit 985833d552
3 changed files with 29 additions and 2554 deletions
@@ -170,19 +170,10 @@ describe('lazy chunk recovery local PTY load', () => {
expect(provider.hasPty(spawnedId)).toBe(true)
})
it('does not let an abandoned ordinary reload authorize a later sweep', async () => {
const provider = new LocalPtyProvider()
const spawnedId = await spawnStaleGenerationPty(provider)
const intent = createRecoveryReloadIntent({ now: () => 100, durationMs: 50 })
// Unsatisfiable as written: a vetoed reload is indistinguishable from a real navigation
// unless the veto path cancels the arm. Wiring that caller is the remaining work.
it.todo('does not let an abandoned ordinary reload authorize a later sweep')
intent.armOrdinary(webContentsId)
// Chromium vetoes the reload before did-start-navigation.
intent.noteNavigationStarted(webContentsId)
handleLocalPtyRendererLoad(provider, webContentsId, intent.classifyLoad)
expect(kill).not.toHaveBeenCalled()
expect(provider.hasPty(spawnedId)).toBe(true)
})
it('isolates concurrent recovery intents by webContents', async () => {
const provider = new LocalPtyProvider()
File diff suppressed because it is too large Load Diff
+21 -1
View File
@@ -91,10 +91,16 @@ export function createRecoveryReloadIntent({
kind: 'ordinary' | 'recovery',
token?: string
): void => {
refreshArm(state)
const existing = refreshArm(state)
if (state.pendingLoad) {
state.pendingLoad = { ...state.pendingLoad, kind: 'unknown' }
}
// Overlapping arms: the next navigation belongs to neither, so refuse to guess.
if (existing) {
state.arm = null
state.nextNavigationUnknown = true
return
}
state.arm = {
kind,
token,
@@ -113,6 +119,20 @@ export function createRecoveryReloadIntent({
armOrdinary(webContentsId) {
armNavigation(getState(webContentsId), 'ordinary')
},
cancelOrdinary(webContentsId) {
const state = getState(webContentsId)
const arm = refreshArm(state)
if (arm?.kind === 'ordinary') {
state.arm = null
state.nextNavigationUnknown = false
return true
}
if (state.pendingLoad?.kind === 'ordinary') {
state.pendingLoad = { ...state.pendingLoad, kind: 'unknown' }
return true
}
return false
},
cancel(webContentsId, token) {
const state = getState(webContentsId)
const arm = refreshArm(state)