Last 12 weeks · 585 commits
4 of 6 standards met
closes https://github.com/sveltejs/kit/issues/17249 WIP Please don't delete this checklist! Before submitting the PR, please make sure you do the following: [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs [ ] This message body should clearly illustrate what problems it solves. [ ] Ideally, include a test that fails without this PR but passes with it. Tests [ ] Run the tests with and lint the project with and Changesets [ ] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running and following the prompts. Changesets that add features should be and those that fix bugs should be . Please prefix changeset messages with , , or . Edits [ ] Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.
checks once its route has loaded, then awaits callbacks and commits without checking again. When a callback returns a promise (the view transition recipe from the docs holds the navigation until the transition's update callback runs), a newer navigation can start during that wait, and the superseded one still sets and applies its render tree when its callbacks settle. This adds the same token check after the callbacks as the one after load. With , has already taken the preload fork out of at that point, so nothing else can reach it. The new abort path therefore discards the fork itself, the same way does. Functions returned by must also not outlive an aborted navigation, or they run when the next navigation completes. used to register them before the check. It now returns them, and the caller registers them only if the navigation is still current. also receives them and removes them when it aborts, which covers a navigation superseded while its render settles. They stay registered before the commit, so they still run in the same order relative to other callbacks. Each registration wraps the returned functions in entries of its own. is a , so if two navigations' calls returned the same function object, removing the aborted navigation's registration would otherwise remove the newer navigation's too. A shallow has the same gap in : superseded while was pending, it still applied its page state and registered its functions. It now gets the same check. As with a full navigation aborted at that point, its history entry has already been pushed and stays; the check only stops the page update and the registration. On the newer navigation still commits afterwards, so the result is transient: the superseded page mounts, renders and runs its effects, and its return value is registered as an callback, just before the newest navigation replaces it. On 2.x (2.70.3, ) the same gap leaves the wrong page in place. There, a navigation only sends the props whose node data differs from at load time. If a superseded navigation commits between a newer navigation's load and its commit, the newer navigation's props are diffed against a stale : it commits without for a page whose data didn't change relative to that . The URL then shows the newest route while the page keeps the superseded route's data. We hit this with rapid link clicks and Back under view transitions. I'm happy to open a backport against if that's wanted. No existing issue covers this. #12809 involved a pending too, but that was a different symptom. Test holds every navigation in . The test starts a navigation to , then a newer one back to , releases the superseded one first, and asserts that never renders and that only the committed navigation's return value runs. It fails on without the change (), fails without the registration change (the aborted navigation's function runs), and passes 20/20 in dev and build with both. A second case runs the same sequence with a shallow as the superseded navigation. Without the change, the superseded navigation's state is applied (). In , which enables , preloads a page that subscribes to a store counting its subscribers. The navigation to that page is held in and superseded, and the test asserts that releasing it drops the count back to 0, meaning the fork was discarded. Without the discard it fails (), and it passes 20/20 in dev and build with it. Also in , holds a page's render with a top-level , and a newer navigation starts before it settles. The test asserts that only the newer navigation's return value runs. Without removing them on that abort it fails (the held navigation's function runs), and it passes 20/20 in dev and build with it. The page also returns one shared function object from every navigation, and the test asserts that the newer navigation still runs it. Without the per-registration entries, the aborted navigation's cleanup removes it. Please don't delete this checklist! Before submitting the PR, please make sure you do the following: [ ] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs [x] This message body should clearly illustrate what problems it solves. [x] Ideally, include a test that fails without this PR but passes with it. Tests [ ] Run the tests with and lint the project with and Ran , , , and in , and (all clean), plus the , and Playwright suites on Chromium in dev and build. , and build pass. In dev, a few and tests fail under the full suite's load, and they did so before this change too. They pass when rerun on their own. I didn't run the full . Changesets [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running and following the prompts. Changesets that add features should be and those that fix bugs should be . Please prefix changeset messages with , , or . Edits [x] Please ensure that 'Allow edits from maintainers' is checked. PRs without this option may be closed.
Describe the bug On iOS Safari, scrolling down a SvelteKit page, following an external link in the same tab, and going Back returns the page to the top instead of its previous scroll position. The same sequence restores correctly with JavaScript disabled in a fresh tab. This also occurred before #17244, when SvelteKit set to in a handler. In an iOS Web Inspector trace with JavaScript enabled, the article left at and returned at . Both and reported , so this was a back/forward-cache return. was at both events. SvelteKit's session-storage entry contained the saved scroll offset (approximately 7361 px). A separate probe did not fire during this navigation. Reproduction Live page: https://svelte.dev/blog/whats-new-in-svelte-september-2026 1. On iOS Safari, scroll to the bottom, tap on any external link, then use Back. The page returns to the top. 2. Repeat from a fresh tab with JavaScript disabled: the scroll position restores. Severity annoyance Additional Information The problem was also observed when the earlier Kit version reset scroll restoration to during . A Web Inspector CSS override of remained applied after returning and did not change the outcome. An experimental listener did run and set the mode to , but the page still returned to the top. Manually setting the mode to before following the external link did restore the position.
Repository: sveltejs/kit. Description: web development, streamlined Stars: 20831, Forks: 2340. Primary language: JavaScript. Languages: JavaScript (99%), TypeScript (0.8%), Svelte (0.1%), HTML (0.1%), Shell (0%). License: MIT. Homepage: https://svelte.dev/docs/kit Topics: svelte. Latest release: @sveltejs/kit@2.70.3 (1mo ago). Open PRs: 87, open issues: 719. Last activity: 51m ago. Community health: 75%. Top contributors: Rich-Harris, github-actions[bot], benmccann, teemingc, dummdidumm, renovate[bot], elliott-with-the-longest-name-on-github, Nic-Polumeyv, ignatiusmb, dominikg and others.