[2026-09-09] eagle: work/projects/cpm-web-extension-breakage-findings.md

This commit is contained in:
Alexey Martemyanov
2026-09-09 18:52:50 +06:00
parent 211d313870
commit fb91c4d429
@@ -12,6 +12,8 @@ tags:
> Investigation summary as of 2026-09-08. This note distinguishes confirmed code paths from hypotheses that still need production evidence. > Investigation summary as of 2026-09-08. This note distinguishes confirmed code paths from hypotheses that still need production evidence.
> >
> **2026-09-10: one production cause CONFIRMED** — closing a window while shared pinned tabs exist makes WebKit forget those tabs (`didCloseWindow` → `didCloseTab`/`forgetTab` for every tab the closing window reports, and DDG reports shared pinned tabs from every window). CPM dies in the pinned tabs only; new tabs work; new window / Fire / extension reload repairs. See "✅ CONFIRMED" section near the end. Everything WebKit-internal below (retained failed view, dead worker, listener gating) remains unconfirmed on shipping WebKit.
>
> **Updated 2026-09-09 after source and shipping-WebKit validation** (WebKit trunk `0c7e7ad97b`, see [[cpm-web-extension-breakage-validation]] for file:line evidence). The retained-failed-view state is real but **self-heals via the 30 s idle eviction**. The source-level dead-worker state matches "stuck across all tabs", but neither critical memory pressure nor Network-process termination reproduced it on the tested macOS 26.x build. No permanent all-tabs production trigger is currently confirmed. `removeAllUserScripts()` is explicitly implemented as `RemoveWebExtensions::No` and does not remove CPM's WebExtension scripts. > **Updated 2026-09-09 after source and shipping-WebKit validation** (WebKit trunk `0c7e7ad97b`, see [[cpm-web-extension-breakage-validation]] for file:line evidence). The retained-failed-view state is real but **self-heals via the 30 s idle eviction**. The source-level dead-worker state matches "stuck across all tabs", but neither critical memory pressure nor Network-process termination reproduced it on the tested macOS 26.x build. No permanent all-tabs production trigger is currently confirmed. `removeAllUserScripts()` is explicitly implemented as `RemoveWebExtensions::No` and does not remove CPM's WebExtension scripts.
## Executive summary ## Executive summary
@@ -994,9 +996,13 @@ Manual test: `removeAllUserScripts()` on a tab's controller leaves CPM working.
`pinTab`/`unpinTab`, `moveTab(at:to:at:)` between windows, drag-out `moveToNewWindow`, `suspendTab`/`materialize` (`TabCollectionViewModel.swift:864-878, 885-897, 734-757`, `TabBarViewController.swift:1508-1524`, `TabCollection.swift:255-283`) all either suppress open/close or emit the correct pair. No path found that leaves a live tab unknown to WebKit. `pinTab`/`unpinTab`, `moveTab(at:to:at:)` between windows, drag-out `moveToNewWindow`, `suspendTab`/`materialize` (`TabCollectionViewModel.swift:864-878, 885-897, 734-757`, `TabBarViewController.swift:1508-1524`, `TabCollection.swift:255-283`) all either suppress open/close or emit the correct pair. No path found that leaves a live tab unknown to WebKit.
## Traced production path: closing a window forgets shared pinned tabs in WebKit (2026-09-10) ## ✅ CONFIRMED: closing a window forgets shared pinned tabs in WebKit (2026-09-10)
Fits every reported fact: dogfood users, several tabs at once, page reload does not help, Fire / extension reload fixes it, a new window also fixes it. Reproduced manually by Alex on 2026-09-10. Scope as observed: **only the pinned tab(s) lose CPM**; a newly opened tab works (it goes through `didOpenTab`). Fits the dogfood reports: several (pinned) tabs at once, page reload does not help, Fire / extension reload fixes it, opening a new window also fixes it.
Same class, second instance: **Merge All Windows** (`MainMenuActions.swift:1670-1695`) closes the source windows via `WindowsManager.closeWindows(except:)` after moving their tabs; in shared-pinned mode each closing window still reports the shared pinned tabs in `tabs(for:)` → same `didCloseTab`/`forgetTab` on tabs that stay open in the remaining window.
General rule: any `didCloseWindow` while another window still displays the same `Tab` objects (shared pinned tabs) forgets them in WebKit. Fire's `.window`/`.allWindows` burns and pinned-mode migrations are safe because they close+reopen or `replaceTab` (→ `didReplaceTab`) every pinned tab.
### Chain ### Chain