Skip to content

Fix web context-menu client lifecycle in SelectableRegion - #189587

Merged
auto-submit[bot] merged 4 commits into
flutter:masterfrom
davidmigloz:fix-web-context-menu-client-lifecycle
Jul 29, 2026
Merged

auto-submit[bot] merged 4 commits into
flutter:masterfrom
davidmigloz:fix-web-context-menu-client-lifecycle

Conversation

@davidmigloz

@davidmigloz davidmigloz commented Jul 16, 2026 •

Copy link
Copy Markdown
Contributor

On web, PlatformSelectableRegionContextMenu._activeClient — the static SelectionContainerDelegate that the right-click mousedown listener reads — can end up pointing at a detached or disposed delegate, because of three lifecycle defects:

  1. detach has an inverted condition — if (_activeClient != client) { _activeClient = null; }. Detaching the active client leaves it registered, while detaching an unrelated client wipes another region's registration.
  2. SelectableRegionState._handleFocusChanged calls attach unconditionally at the end of the method, so a region that just lost focus is immediately re-registered.
  3. SelectableRegionState.dispose never detaches, so the static can keep pointing at a disposed delegate.

Together these produce a crash on web when the user right-clicks during a route transition: the listener calls getTransformTo(null) on the stale delegate and hits "getTransformTo cannot be called before SelectionContainer is laid out" (selection_container.dart:303). We hit this in a production web app.

This PR flips the detach condition, moves the re-attach into the focused branch, and detaches in dispose before disposing the delegate. It also adds a @visibleForTesting debugActiveClient getter, mirroring the existing debugOverrideRegisterViewFactory pattern, since the delegate is otherwise unobservable from tests. Three new browser tests in selectable_region_context_menu_test.dart isolate the defects; each is red before the fix and green after it.

A follow-up commit hardens the detach paths against BrowserContextMenu.enabled changing at runtime. Attach stays gated on the full dynamic check, but the focus-loss and dispose detach paths now gate on kIsWeb alone, so a delegate attached while the menu was enabled is still detached after the menu is disabled. This is safe because detach is identity-selective: calling it for a never-attached delegate is a no-op. Two more browser tests cover unfocus and disposal after BrowserContextMenu.disableContextMenu(), bringing it to five lifecycle tests, each red before its fix and green after.

Fixes #189575

Pre-launch Checklist

@github-actions github-actions Bot added the framework flutter/packages/flutter repository. See also f: labels. label Jul 16, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the platform selection context menu lifecycle by fixing the detach logic on Web to only clear the active client when it matches the detaching client, detaching the client upon disposal of SelectableRegion, and adding associated tests. Feedback identifies a logic error in SelectableRegionState where changing an if statement to else if prevents the context menu from attaching when the region gains focus.

Comment thread packages/flutter/lib/src/widgets/selectable_region.dart

@Renzo-Olivares Renzo-Olivares left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the fix @davidmigloz! Mostly LGTM besides some suggestions for added tests.

@Renzo-Olivares Renzo-Olivares added the CICD Run CI/CD label Jul 22, 2026
Three defects in the web SelectableRegion context-menu client
registration allowed the static active client to go stale or be
wiped incorrectly:

1. PlatformSelectableRegionContextMenu.detach compared the client
   with != instead of ==, so detaching the active client left it
   attached while detaching an unrelated client wiped the real one.
2. SelectableRegionState._handleFocusChanged unconditionally called
   attach at the end of the method, re-attaching a region even when
   it had just lost focus.
3. SelectableRegionState.dispose never detached from the context
   menu before disposing its delegate, letting the static reference
   outlive the delegate and crash on the next right-click.

Adds a debugActiveClient test hook (mirroring the existing
debugOverrideRegisterViewFactory/debugResetRegistry pattern) and
three browser-platform widget tests covering each defect.
_webContextMenuEnabled re-evaluates BrowserContextMenu.enabled on every
call, so if the browser context menu is disabled after a delegate
attached, the focus-loss and dispose detach calls were skipped,
leaving the static active-client pointer stale (possibly dangling
after the delegate is disposed). Detach is now gated on kIsWeb alone;
attach sites stay gated on the full dynamic flag, and detach is a
no-op for a delegate that isn't the active client.
@davidmigloz
davidmigloz force-pushed the fix-web-context-menu-client-lifecycle branch from d2d4cdb to 72542e5 Compare July 22, 2026 08:04
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Jul 22, 2026
@davidmigloz

Copy link
Copy Markdown
Contributor Author

@Renzo-Olivares test added! thanks for the review

Renzo-Olivares
Renzo-Olivares previously approved these changes Jul 22, 2026

@Renzo-Olivares Renzo-Olivares left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you for the contribution @davidmigloz!

@Renzo-Olivares Renzo-Olivares added CICD Run CI/CD and removed CICD Run CI/CD labels Jul 22, 2026

@Renzo-Olivares Renzo-Olivares left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RE-LGTM

@Renzo-Olivares
Renzo-Olivares requested a review from chunhtai July 28, 2026 21:32

@chunhtai chunhtai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@chunhtai chunhtai added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 29, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Jul 29, 2026
Merged via the queue into flutter:master with commit 9d98366 Jul 29, 2026
27 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jul 29, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Aug 8, 2026
…12393)

Manual roll requested by [email protected]

flutter/flutter@2a230d1...2757a77

2026-07-29 [email protected] Roll Skia from 3ae9e364d30b to 0f35bba4945c (2 revisions) (flutter/flutter#190215)
2026-07-29 [email protected] [web] Fix deferred loading with wasm (flutter/flutter#190140)
2026-07-29 [email protected] Roll Dart SDK from 1bbaacba6a5a to 43f7de5f4977 (1 revision) (flutter/flutter#190211)
2026-07-29 [email protected] Roll Skia from 119cae396625 to 3ae9e364d30b (6 revisions) (flutter/flutter#190208)
2026-07-29 [email protected] [Win32] Ignore mouse move events without capture when dragging (flutter/flutter#190029)
2026-07-29 [email protected] Roll Dart SDK from 49c637261348 to 1bbaacba6a5a (7 revisions) (flutter/flutter#190196)
2026-07-29 [email protected] Roll Skia from 30ad01017a46 to 119cae396625 (2 revisions) (flutter/flutter#190183)
2026-07-29 [email protected] Fix NestedScrollView example crash when switching tabs on desktop (flutter/flutter#186993)
2026-07-29 [email protected] Roll Fuchsia Linux SDK from OZkZC_2CZ_G5rbMIS... to J8rVTlBnjnUpuHYk3... (flutter/flutter#190174)
2026-07-29 [email protected] Update widget location tracking to use the new generalized api (flutter/flutter#189725)
2026-07-29 [email protected] Avoid unnecessary work in `BoxDecoration` and `RenderPhysicalModel` (flutter/flutter#187891)
2026-07-29 [email protected] Fix web context-menu client lifecycle in SelectableRegion (flutter/flutter#189587)
2026-07-29 [email protected] Roll Skia from 70733f74d415 to 30ad01017a46 (2 revisions) (flutter/flutter#190173)
2026-07-29 [email protected] Manual roll of Dart from 28e63ac22d8d to 49c637261348 (flutter/flutter#190158)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SelectableRegion web: right-click during a route transition crashes with 'getTransformTo cannot be called before SelectionContainer is laid out'

3 participants