fix(devtools): handle pointercancel when dragging the indicator - #98506
Merged
Conversation
`useDrag` listened for pointermove/pointerup but not pointercancel. When the user agent cancels a gesture, no pointerup arrives, so cancel() never ran: the state machine stayed in 'drag' and the window listeners were never removed. The next pointerup anywhere on the page then reached cancel() and called releasePointerCapture() on a pointer that no longer existed, throwing NotFoundError. Register pointercancel alongside pointerup, remove it in the same cleanup, and only release pointer capture that is still held. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
Tests PassedCommit: aa250c6 |
icyJoseph
marked this pull request as ready for review
September 10, 2026 14:56
Replays the two-gesture sequence from #98468: pointerdown, a move past the drag threshold, pointercancel, then a later move and up. Asserts no uncaught error and that the indicator stops following the pointer. Pointer capture is owned by the user agent and cannot be driven from script, so the three capture methods are stubbed to the post-cancel behaviour a real browser exhibits: capture no longer held, and releasing it throws NotFoundError. With the fix reverted this is the only failing test in the directory, and it fails with the error string from the issue. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
icyJoseph
marked this pull request as draft
September 10, 2026 15:03
icyJoseph
marked this pull request as ready for review
September 10, 2026 15:15
eps1lon
approved these changes
Sep 10, 2026
It now handles pointercancel as well as pointerup, so the old name no longer described what it does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
eps1lon
approved these changes
Sep 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #98468
Claude explanation of the fix
useDraglistened forpointermoveandpointerup, but neverpointercancel.When a user agent cancels a gesture — a browser or system gesture takes over, a second finger arrives — it fires
pointercanceland nopointerup, implicitly releasing pointer capture as it does. Socancel()never ran: the state machine stayed{ state: 'drag' }andcleanup.currentwas never invoked, leaving thepointermove/pointeruplisteners onwindow.The next
pointerupanywhere on the page then hit those orphaned listeners, reachedcancel()with the state still'drag', and calledreleasePointerCapture()on a pointer that no longer existed — the reportedNotFoundError. Each cancelled drag also leaked another listener pair.This registers
pointercancelalongsidepointerupand removes it in the same cleanup, so the machine unwinds when a gesture is cancelled; and it releases pointer capture only whenhasPointerCapture()says it is still held, which is preferable totry/catchswallowing genuine faults too.Note
touch-action: none(#97723) removed the common touch trigger, but not the defect: on canary a forcedtouchCancelstill throws.Screen.Recording.2026-09-10.at.17.04.00.mov
Fixed version
Screen.Recording.2026-09-10.at.17.05.11.mov
Browser checks
Screen.Recording.2026-09-10.at.17.13.07.mov
🤖 Generated with Claude Code