fix(cmux-next pages): a provider's state sent inside subscribe reaches the page

Merged
LA
7d ago
+72-4

Summary

A page provider that sends its current state from inside subscribe lost that state. The agent activity, icon picker and update surface pages showed nothing until their next change.

PageRouter.subscribe holds the events a provider sends while subscribe runs, and flushes them once after the reply that names the subscription (20066e187f32). #24617 (4abd40495883, "replay agent page events across bridge gaps") rewrote that guard for providers that send only after the reply (eventsAfterSubscribeReply). The rewrite inverted the guard:

  • events held during subscribe were released and thrown away. AgentActivityPageProvider, IconPickerProvider and UpdateSurfaceIsland call onEvent inside subscribe, so their first state never reached the page;
  • with nothing held, events sent after the reply were caught and delivered one main turn late.

The guard is now guard early.isHolding, !provider.eventsAfterSubscribeReply. Nothing held: release at once. Held: flush once after the reply. Providers with eventsAfterSubscribeReply (the agent page) are unchanged.

Thanks to #24617 for the bridge-gap replay; this restores the early-event path it changed. The same bug is on perf/chrome-parity and is fixed there in cp/fix-tip-page-script-batch-crash (green proof 74b81ea13b25c872967366ac: PageRouterEarlyEventsTests, PageRouterFrozenDeliveryTests and PageScriptPipelineBatchTests pass).

Changelog

Fixed: The agent activity, icon picker and update surface pages show their current state when they open, not only after their next change.

Testing

Regression test PageRouterEarlyEventsTests (red commit 24e468d2150 first, fix dfce1618e15):

  • cmux-ci run --class light --script scripts/ci/package-test-lane.sh --arg suite --arg Packages/macOS/CmuxNext --arg PageRouterEarlyEventsTests (through proof-step.py):
  • Compile: cmux-ci compile-check --app --package CmuxNext --recipe-version 2 at dfce1618e15 (fleet 21a81b1382d0303c8db082c1): passed.

Observed / Not run

Observed: the two fleet runs and the compile above; scripts/cmux-next/prepush-gate.py clean.
Not run: the full CmuxNextPagesTests target, and a live app check of the three pages in a tagged build.

Proof

No capture: the fix is in the page router's event delivery; no view or look changes. The fleet tests above are the proof.

Follow-up (review note, not in this PR): the throw and closed paths of subscribe never call early.release(), so a provider that keeps onEvent after cancel would keep growing the held list. Fixed in #27500 (red 13 allocations over an empty loop for 10 000 events, green 0, in Debug and in a Release build).

Review (independent subagent, correctness first): SHIP at dfce1618e15b7e7daa03036fe226203cbd718aa9

Checklist

  • Behavior changes have added or updated tests (PageRouterEarlyEventsTests)
  • Reviewed with a subagent before merge; verdict above. No user-facing strings change, so no localization audit applies.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Fixes the pages' initial state being dropped on open, so the agent activity, icon picker, and update surface pages now show their current state immediately instead of only after the next change.

A previous rewrite of the guard in PageRouter.subscribe inverted it and discarded the events a provider sends while subscribe runs; that path is restored with guard early.isHolding, !provider.eventsAfterSubscribeReply, while the bridge-gap replay for providers that send after the reply is unchanged.

  • Adds regression tests PageRouterEarlyEventsTests covering both the held-state flush and a post-reply event delivered in its own turn.