fix: handle stale Navigation API entries in Safari Private Browsing#185
Merged
Conversation
Adds __simulateInterceptedNavigation(url, { privateBrowsing }) that
drives the full navigate -> commit -> handler -> navigatesuccess
lifecycle in unit tests, with an opt-in flag to simulate the WebKit
Private Browsing bug where currentEntry stays stale and
currententrychange does not fire.
…owsing Works around a WebKit bug where intercepted navigations commit but navigation.currentEntry.url/.id stay stale and currententrychange does not fire. Captures event.destination.url scoped to entry.id, prefers it in getSnapshot, and listens to navigatesuccess as a fallback notifier. Composite loader cache keys (entry.id + url) keep loader behavior consistent across both modes. Upstream bug: https://bugs.webkit.org/show_bug.cgi?id=314976
uhyo
approved these changes
May 19, 2026
Owner
uhyo
left a comment
There was a problem hiding this comment.
Thank you! Look good as a workaround. Good job also filling an upstream bug and including the link in the comments 😃
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.
Closes #184
Summary
Works around a WebKit Navigation API bug in Safari Private Browsing where an intercepted navigation commits, but
navigation.currentEntry.url/.idremain stale andcurrententrychangedoes not fire.Upstream bug: https://bugs.webkit.org/show_bug.cgi?id=314976
User-visible symptom: after clicking a link in Safari Private Browsing, the URL bar updates but the rendered route stays on the previous page until reload.
Approach
This keeps the workaround contained inside the Navigation API adapter:
event.destination.urlduring intercepted navigations.navigatesuccessas a fallback signal for the buggy Safari Private Browsing path.entry.id + urlso same-URL navigations still run loaders correctly.The adapter still avoids reading
location.href.Limitations
This fixes URL-based routing in Safari Private Browsing.
State that depends on
navigation.currentEntry.getState()can still be stale in this browser mode because WebKit leavescurrentEntryitself stale. In practice, this meansuseRouteStateremains limited until the upstream browser bug is fixed.There is also a small Safari Private Browsing cache cleanup limitation: dispose-time cleanup may miss composite loader cache keys because
entry.urlis stale. The cache can grow by unique URL during the tab session and is released when the tab closes. Correctness is unaffected.Tests
Added regression coverage in
NavigationAPIAdapter.privateBrowsing.test.tsfor:currentEntryis stalenavigatesuccessfallback notificationsManually verified in macOS Safari Private Browsing using the example app.
before.mov
after.mov