Skip to content

fix(frame): make check and subscribe one step in the navigation waits - #3388

Closed
Yury Semikhatsky (yury-s) wants to merge 2 commits into
dispatch-lockfrom
fix-3364-one-step
Closed

Yury Semikhatsky (yury-s) wants to merge 2 commits into
dispatch-lockfrom
fix-3364-one-step

Conversation

@yury-s

@yury-s Yury Semikhatsky (yury-s) commented Oct 16, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Load states become one TaskCompletionSource per WaitUntilState: a completed slot means the state is present, a pending one that it is not, and WaitForLoadStateAsync and WaitForNavigationAsync await the current slot. There is no check to interleave with a subscription, and the torn read of the List<WaitUntilState> is gone.
  • WaitForURLAsync keeps the JS shape. It reads Url and a navigation count under Connection.DispatchLock, runs the matcher outside the lock because it can be a user predicate, and subscribes to Navigated under the lock only if the count has not moved, otherwise it matches again. OnNavigated updates Url, bumps the count and snapshots the handlers under the same lock.
  • A second test blocks inside the predicate on a call whose reply follows a frameAttached message; it passes on main and would deadlock if the matcher ran under the lock.
  • Regression test from [Bug]: WaitForURLAsync can lose the event it is waiting for — its check-then-subscribe races with the thread that delivers events #3364: fails on main in 2 of 3 fresh test hosts, passes 3 of 3 here.

Stacked on #3387, which adds the lock. Replaces #3384. Load-state waits now resume on the thread pool rather than inline on the reader thread, which three tests in #3386 currently pin.

Fixes #3364

Load states are one TaskCompletionSource per WaitUntilState that the
pump completes, so WaitForLoadStateAsync and WaitForNavigationAsync
await the current slot instead of checking a list and then subscribing.
WaitForURLAsync matches Url and subscribes under the dispatch lock that
OnNavigated takes to update Url.

Fixes: #3364
The matcher can be a user predicate, and a predicate that blocks on a
Playwright call deadlocked while the lock was held: the pump waits for
the lock at the next frame, page or worker message, so the reply never
arrives. Read Url and a navigation count under the lock, match outside
it, and subscribe under the lock only if no navigation landed since,
otherwise match again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant