Skip to content

Commit fda0165

Browse files
authored
fix: correctly set the URL when navigating during a navigation (#14004)
fixes #12809 This PR ensures that the correct navigation results are computed if the user tries to navigate during an ongoing navigation. The root cause of the issue is that the page_changed value is evaluated incorrectly when we try navigating to a page we're already navigating to. This is because the current.url is updated to the new page before navigation is completed. Therefore, if we click the same link while navigation is pending (due to a lengthy onNavigate execution), the router will think we're already on the page we're navigating to and return the wrong navigation result. We fix this by updating current.url only after all onNavigate callbacks have completed.
1 parent f192a9b commit fda0165

File tree

4 files changed

+30
-9
lines changed

4 files changed

+30
-9
lines changed

.changeset/shiny-groups-relax.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
fix: correctly set URL when navigating during an ongoing navigation

packages/kit/src/runtime/client/client.js

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -537,8 +537,7 @@ function get_navigation_result_from_branch({ url, params, branch, status, error,
537537
}
538538

539539
url.pathname = normalize_path(url.pathname, slash);
540-
541-
// eslint-disable-next-line
540+
// eslint-disable-next-line no-self-assign
542541
url.search = url.search; // turn `/?` into `/`
543542

544543
/** @type {import('./types.js').NavigationFinished} */
@@ -1563,13 +1562,6 @@ async function navigate({
15631562
navigation_result.props.page.state = state;
15641563

15651564
if (started) {
1566-
current = navigation_result.state;
1567-
1568-
// reset url before updating page store
1569-
if (navigation_result.props.page) {
1570-
navigation_result.props.page.url = url;
1571-
}
1572-
15731565
const after_navigate = (
15741566
await Promise.all(
15751567
Array.from(on_navigate_callbacks, (fn) =>
@@ -1592,6 +1584,13 @@ async function navigate({
15921584
});
15931585
}
15941586

1587+
current = navigation_result.state;
1588+
1589+
// reset url before updating page store
1590+
if (navigation_result.props.page) {
1591+
navigation_result.props.page.url = url;
1592+
}
1593+
15951594
root.$set(navigation_result.props);
15961595
update(navigation_result.props.page);
15971596
has_navigated = true;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
import { onNavigate } from '$app/navigation';
3+
4+
onNavigate(() => new Promise((resolve) => setTimeout(resolve, 3000)));
5+
</script>
6+
7+
<a href="/routing">Go to routing</a>

packages/kit/test/apps/basics/test/client.test.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,3 +1634,13 @@ test.describe('binding_property_non_reactive warn', () => {
16341634
expect(is_warning_thrown).toBeFalsy();
16351635
});
16361636
});
1637+
1638+
test.describe('routing', () => {
1639+
test('navigating while navigation is in progress sets the correct URL', async ({ page }) => {
1640+
await page.goto('/routing/long-navigation');
1641+
await page.click('a[href="/routing"]');
1642+
await page.click('a[href="/routing"]');
1643+
await expect(page.locator('h1')).toHaveText('Great success!');
1644+
await expect(page).toHaveURL((url) => url.pathname === '/routing');
1645+
});
1646+
});

0 commit comments

Comments
 (0)