From 084bb17dddb3a562391dff4678cf897dbd0eb491 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 19 Feb 2024 13:43:10 +0100 Subject: [PATCH 1/7] fix: prevent stale values after invalidation current was not updated after invalidation, which resulted in the previous values getting used on next navigation fixes #11446 --- .changeset/angry-gorillas-peel.md | 5 ++++ packages/kit/src/runtime/client/client.js | 16 ++++++------- .../invalidate-then-goto/+layout.server.js | 7 ++++++ .../invalidate-then-goto/+page.server.js | 7 ++++++ .../invalidate-then-goto/+page.svelte | 23 +++++++++++++++++++ .../kit/test/apps/basics/test/client.test.js | 23 +++++++++++++++++++ 6 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 .changeset/angry-gorillas-peel.md create mode 100644 packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+layout.server.js create mode 100644 packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.server.js create mode 100644 packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.svelte diff --git a/.changeset/angry-gorillas-peel.md b/.changeset/angry-gorillas-peel.md new file mode 100644 index 000000000000..f4642f4135f8 --- /dev/null +++ b/.changeset/angry-gorillas-peel.md @@ -0,0 +1,5 @@ +--- +"@sveltejs/kit": patch +--- + +fix: prevent stale values after invalidation diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index ce5c39dd3960..d0992675f6ef 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -312,16 +312,16 @@ async function _invalidate() { if (navigation_result) { if (navigation_result.type === 'redirect') { - await _goto(new URL(navigation_result.location, current.url).href, {}, 1, nav_token); - } else { - if (navigation_result.props.page !== undefined) { - page = navigation_result.props.page; - } - root.$set(navigation_result.props); + return _goto(new URL(navigation_result.location, current.url).href, {}, 1, nav_token); } - } - invalidated.length = 0; + if (navigation_result.props.page) { + page = navigation_result.props.page; + } + current = navigation_result.state; + invalidated.length = 0; + root.$set(navigation_result.props); + } } /** @param {number} index */ diff --git a/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+layout.server.js b/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+layout.server.js new file mode 100644 index 000000000000..29e1a9268f69 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+layout.server.js @@ -0,0 +1,7 @@ +/** @type {import('./$types').PageLoad} */ +export function load({ depends }) { + depends('invalidate-depends:goto'); + return { + layoutDate: new Date().getTime() + }; +} diff --git a/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.server.js b/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.server.js new file mode 100644 index 000000000000..760dfa2954d7 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.server.js @@ -0,0 +1,7 @@ +/** @type {import('./$types').PageLoad} */ +export function load({ url }) { + url.searchParams.get('x'); + return { + pageDate: new Date().getTime() + }; +} diff --git a/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.svelte b/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.svelte new file mode 100644 index 000000000000..887e7b8d5a57 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.svelte @@ -0,0 +1,23 @@ + + +

{data.layoutDate}

+

{data.pageDate}

+ + diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js index 21a5546bc978..cb27848d31ad 100644 --- a/packages/kit/test/apps/basics/test/client.test.js +++ b/packages/kit/test/apps/basics/test/client.test.js @@ -594,6 +594,29 @@ test.describe('Invalidation', () => { await page.locator('button').click(); await expect(page.getByText('updated')).toBeVisible(); }); + + test('goto after invalidation does not reset state', async ({ page }) => { + await page.goto('/load/invalidation/invalidate-then-goto'); + const layout = await page.textContent('p.layout'); + const _page = await page.textContent('p.page'); + expect(layout).toBeDefined(); + expect(_page).toBeDefined(); + + await page.click('button.invalidate'); + await page.evaluate(() => window.promise); + const next_layout_1 = await page.textContent('p.layout'); + const next_page_1 = await page.textContent('p.page'); + expect(next_layout_1).not.toBe(layout); + expect(next_page_1).toBe(_page); + + await page.click('button.goto'); + await page.evaluate(() => window.promise); + const next_layout_2 = await page.textContent('p.layout'); + const next_page_2 = await page.textContent('p.page'); + expect(next_layout_2).toBe(next_layout_1); + expect(next_layout_2).not.toBe(layout); + expect(next_page_2).not.toBe(next_page_1); + }); }); test.describe('data-sveltekit attributes', () => { From 7c50947d6f1fec28ac1a2e2b2515914f710d2eee Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 19 Feb 2024 14:15:07 +0100 Subject: [PATCH 2/7] same for force_invalidation, fixes #10123 --- packages/kit/src/runtime/client/client.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index d0992675f6ef..7bba5eb5af2a 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -320,6 +320,7 @@ async function _invalidate() { } current = navigation_result.state; invalidated.length = 0; + force_invalidation = false; root.$set(navigation_result.props); } } From 9aca13fb83fab83ef0ac9e0013fa2dc202fda5d4 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 19 Feb 2024 14:15:54 +0100 Subject: [PATCH 3/7] fix --- .../load/invalidation/invalidate-then-goto/+layout.server.js | 2 +- .../load/invalidation/invalidate-then-goto/+page.server.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+layout.server.js b/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+layout.server.js index 29e1a9268f69..07aab9465aca 100644 --- a/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+layout.server.js +++ b/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+layout.server.js @@ -1,4 +1,4 @@ -/** @type {import('./$types').PageLoad} */ +/** @type {import('./$types').LayoutServerLoad} */ export function load({ depends }) { depends('invalidate-depends:goto'); return { diff --git a/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.server.js b/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.server.js index 760dfa2954d7..ec11392c4c35 100644 --- a/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.server.js +++ b/packages/kit/test/apps/basics/src/routes/load/invalidation/invalidate-then-goto/+page.server.js @@ -1,4 +1,4 @@ -/** @type {import('./$types').PageLoad} */ +/** @type {import('./$types').PageServerLoad} */ export function load({ url }) { url.searchParams.get('x'); return { From be4bc78ee79e5c2638681deb999162827edd021e Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 19 Feb 2024 17:54:19 +0100 Subject: [PATCH 4/7] deduplicate --- packages/kit/src/runtime/client/client.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 7bba5eb5af2a..6f32f6c357f9 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -319,12 +319,16 @@ async function _invalidate() { page = navigation_result.props.page; } current = navigation_result.state; - invalidated.length = 0; - force_invalidation = false; + reset_invalidation(); root.$set(navigation_result.props); } } +function reset_invalidation() { + invalidated.length = 0; + force_invalidation = false; +} + /** @param {number} index */ function capture_snapshot(index) { if (components.some((c) => c?.snapshot)) { @@ -1282,8 +1286,7 @@ async function navigate({ // reset invalidation only after a finished navigation. If there are redirects or // additional invalidations, they should get the same invalidation treatment - invalidated.length = 0; - force_invalidation = false; + reset_invalidation(); updating = true; From 52271adf3a9305cb3c8b036b24b97b385504c213 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Mon, 19 Feb 2024 17:57:04 +0100 Subject: [PATCH 5/7] tweak --- packages/kit/src/runtime/client/client.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 6f32f6c357f9..c27b59c27ee2 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -308,20 +308,18 @@ async function _invalidate() { const nav_token = (token = {}); const navigation_result = intent && (await load_route(intent)); - if (nav_token !== token) return; + if (!navigation_result || nav_token !== token) return; - if (navigation_result) { - if (navigation_result.type === 'redirect') { - return _goto(new URL(navigation_result.location, current.url).href, {}, 1, nav_token); - } + if (navigation_result.type === 'redirect') { + return _goto(new URL(navigation_result.location, current.url).href, {}, 1, nav_token); + } - if (navigation_result.props.page) { - page = navigation_result.props.page; - } - current = navigation_result.state; - reset_invalidation(); - root.$set(navigation_result.props); + if (navigation_result.props.page) { + page = navigation_result.props.page; } + current = navigation_result.state; + reset_invalidation(); + root.$set(navigation_result.props); } function reset_invalidation() { From 3170f3c5ccd50734d1b60f8eb4cb4f8b4697609a Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Wed, 21 Feb 2024 14:01:25 +0100 Subject: [PATCH 6/7] document get_navigation_intent --- packages/kit/src/runtime/client/client.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index c27b59c27ee2..dd400677931f 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -1095,6 +1095,9 @@ async function load_root_error_page({ status, error, url, route }) { } /** + * Resolve the full info (which route, params, etc.) for a client-side navigation from the URL, + * taking the reroute hook into account. If this isn't a client-side-navigation (or the URL is undefined), + * returns undefined. * @param {URL | undefined} url * @param {boolean} invalidating */ From fa16b331f2f8b3e36e8e63b65f6b26f191d3aa6c Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Wed, 21 Feb 2024 17:03:17 +0100 Subject: [PATCH 7/7] Update packages/kit/test/apps/basics/test/client.test.js Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com> --- packages/kit/test/apps/basics/test/client.test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js index cb27848d31ad..2ae2b2818b74 100644 --- a/packages/kit/test/apps/basics/test/client.test.js +++ b/packages/kit/test/apps/basics/test/client.test.js @@ -614,7 +614,6 @@ test.describe('Invalidation', () => { const next_layout_2 = await page.textContent('p.layout'); const next_page_2 = await page.textContent('p.page'); expect(next_layout_2).toBe(next_layout_1); - expect(next_layout_2).not.toBe(layout); expect(next_page_2).not.toBe(next_page_1); }); });