diff --git a/work/projects/cpm-web-extension-breakage-findings.md b/work/projects/cpm-web-extension-breakage-findings.md index e0fda9da..d58addaa 100644 --- a/work/projects/cpm-web-extension-breakage-findings.md +++ b/work/projects/cpm-web-extension-breakage-findings.md @@ -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. > +> **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. ## 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. -## 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