From 845c91f28b8961c6aaca844383b1469856075d98 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 7 Feb 2024 11:20:23 +0100 Subject: [PATCH 01/11] Added `invalidateAll` method --- packages/kit/test/ambient.d.ts | 1 + packages/kit/test/setup.js | 2 ++ packages/kit/test/utils.d.ts | 1 + packages/kit/test/utils.js | 5 +++++ 4 files changed, 9 insertions(+) diff --git a/packages/kit/test/ambient.d.ts b/packages/kit/test/ambient.d.ts index 998e04686eaa..9806d6d777a9 100644 --- a/packages/kit/test/ambient.d.ts +++ b/packages/kit/test/ambient.d.ts @@ -13,6 +13,7 @@ declare global { ) => Promise; const invalidate: (url: string) => Promise; + const invalidateAll: () => Promise; const preloadData: (url: string) => Promise; const beforeNavigate: (fn: (url: URL) => void | boolean) => void; const afterNavigate: (fn: () => void) => void; diff --git a/packages/kit/test/setup.js b/packages/kit/test/setup.js index d6d34f54a815..87743436438e 100644 --- a/packages/kit/test/setup.js +++ b/packages/kit/test/setup.js @@ -1,6 +1,7 @@ import { goto, invalidate, + invalidateAll, preloadCode, preloadData, beforeNavigate, @@ -14,6 +15,7 @@ export function setup() { Object.assign(window, { goto, invalidate, + invalidateAll, preloadCode, preloadData, beforeNavigate, diff --git a/packages/kit/test/utils.d.ts b/packages/kit/test/utils.d.ts index 6ba3c0b8d89f..63e5545aba1c 100644 --- a/packages/kit/test/utils.d.ts +++ b/packages/kit/test/utils.d.ts @@ -15,6 +15,7 @@ export const test: TestType< app: { goto(url: string, opts?: { replaceState?: boolean }): Promise; invalidate(url: string): Promise; + invalidateAll(): Promise; beforeNavigate(url: URL): void | boolean; afterNavigate(url: URL): void; preloadCode(...urls: string[]): Promise; diff --git a/packages/kit/test/utils.js b/packages/kit/test/utils.js index 05b88c9ce0c6..926e92699f55 100644 --- a/packages/kit/test/utils.js +++ b/packages/kit/test/utils.js @@ -26,6 +26,11 @@ export const test = base.extend({ */ invalidate: (url) => page.evaluate((/** @type {string} */ url) => invalidate(url), url), + /** + * @returns {Promise} + */ + invalidateAll: () => page.evaluate(() => invalidateAll()), + /** * @param {(url: URL) => void | boolean | Promise} fn * @returns {Promise} From eab536ffabebeb039875e249225ee9c65434bb60 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 7 Feb 2024 11:20:48 +0100 Subject: [PATCH 02/11] Test --- packages/kit/test/apps/basics/test/client.test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/kit/test/apps/basics/test/client.test.js b/packages/kit/test/apps/basics/test/client.test.js index 21a5546bc978..1b5eeef87fa2 100644 --- a/packages/kit/test/apps/basics/test/client.test.js +++ b/packages/kit/test/apps/basics/test/client.test.js @@ -1000,6 +1000,13 @@ test.describe('Shallow routing', () => { await expect(page.locator('p')).toHaveText('active: true'); }); + test('Preserve state when invalidating', async ({ page, app }) => { + await page.goto('/shallow-routing/push-state'); + await page.locator('[data-id="one"]').click(); + await app.invalidateAll(); + await expect(page.locator('p')).toHaveText('active: true'); + }); + test('Replaces state on the current URL', async ({ baseURL, page, clicknav }) => { await page.goto('/shallow-routing/replace-state/b'); await clicknav('[href="/shallow-routing/replace-state"]'); From 7b03ede41ab737ee0b832216018e1c8ec042053e Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 7 Feb 2024 11:20:54 +0100 Subject: [PATCH 03/11] Fix --- 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 8caf64c2618c..56db433bf523 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -312,6 +312,7 @@ async function _invalidate() { await _goto(new URL(navigation_result.location, current.url).href, {}, 1, nav_token); } else { if (navigation_result.props.page !== undefined) { + navigation_result.props.page.state = page.state; page = navigation_result.props.page; } root.$set(navigation_result.props); From f7b8a0dcc59b2be493f9ff3b02846ac8eee36724 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 7 Feb 2024 11:30:44 +0100 Subject: [PATCH 04/11] Changeset --- .changeset/wild-mugs-check.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/wild-mugs-check.md diff --git a/.changeset/wild-mugs-check.md b/.changeset/wild-mugs-check.md new file mode 100644 index 000000000000..b5b41cb7cda1 --- /dev/null +++ b/.changeset/wild-mugs-check.md @@ -0,0 +1,5 @@ +--- +"@sveltejs/kit": patch +--- + +fix: preserve state when invalidating From 77c8ec4f00081a4c51c84f2812f4eefc89d91eca Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 6 Mar 2024 18:30:22 +0100 Subject: [PATCH 05/11] Revert "Fix" This reverts commit 7b03ede41ab737ee0b832216018e1c8ec042053e. --- packages/kit/src/runtime/client/client.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 56db433bf523..8caf64c2618c 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -312,7 +312,6 @@ async function _invalidate() { await _goto(new URL(navigation_result.location, current.url).href, {}, 1, nav_token); } else { if (navigation_result.props.page !== undefined) { - navigation_result.props.page.state = page.state; page = navigation_result.props.page; } root.$set(navigation_result.props); From 82b5ad9ef5b5bf9f914ca7d51922d1779e00dae1 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 6 Mar 2024 18:39:44 +0100 Subject: [PATCH 06/11] Fix --- packages/kit/src/runtime/client/client.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index dd400677931f..08e09678f723 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -448,6 +448,7 @@ function initialize(result, target) { * error: App.Error | null; * route: import('types').CSRRoute | null; * form?: Record | null; + * state?: App.PageData | null; * }} opts */ async function get_navigation_result_from_branch({ @@ -457,7 +458,8 @@ async function get_navigation_result_from_branch({ status, error, route, - form + form, + state }) { /** @type {import('types').TrailingSlash} */ let slash = 'never'; @@ -534,7 +536,7 @@ async function get_navigation_result_from_branch({ route: { id: route?.id ?? null }, - state: {}, + state: state ?? {}, status, url: new URL(url), form: form ?? null, @@ -992,7 +994,8 @@ async function load_route({ id, invalidating, url, params, route }) { error: null, route, // Reset `form` on navigation, but not invalidation - form: invalidating ? undefined : null + form: invalidating ? undefined : null, + state: invalidating ? page.state : null }); } From 82a6ecdef7f4bb27075fd8aee934170158297ced Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Tue, 8 Oct 2024 10:41:18 +0200 Subject: [PATCH 07/11] Apply suggestions from code review --- packages/kit/src/runtime/client/client.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index fd93a9b9fa0c..6e191ffe9607 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -470,7 +470,7 @@ function initialize(result, target, hydrate) { * state?: App.PageData | null; * }} opts */ -async function get_navigation_result_from_branch({ +function get_navigation_result_from_branch({ url, params, branch, @@ -1045,7 +1045,7 @@ async function load_route({ id, invalidating, url, params, route, preload }) { status: 200, error: null, route, - // Reset `form` on navigation, but not invalidation + // Reset `form`/`state` on navigation, but not invalidation form: invalidating ? undefined : null, state: invalidating ? page.state : null }); From b719d922cd3bd195579bfd003e003d7966718e0c Mon Sep 17 00:00:00 2001 From: Patrick Date: Tue, 5 Aug 2025 21:38:43 +0200 Subject: [PATCH 08/11] use `reset_page_state` arg --- packages/kit/src/runtime/client/client.js | 29 ++++++++--------------- packages/kit/test/utils.js | 2 +- packages/kit/types/index.d.ts | 1 + 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index cc6ebd746cf9..8f3cb5e57ec0 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -565,19 +565,9 @@ function initialize(result, target, hydrate) { * error: App.Error | null; * route: import('types').CSRRoute | null; * form?: Record | null; - * state?: App.PageData | null; * }} opts */ -function get_navigation_result_from_branch({ - url, - params, - branch, - status, - error, - route, - form, - state -}) { +function get_navigation_result_from_branch({ url, params, branch, status, error, route, form }) { /** @type {import('types').TrailingSlash} */ let slash = 'never'; @@ -652,7 +642,7 @@ function get_navigation_result_from_branch({ route: { id: route?.id ?? null }, - state: state ?? {}, + state: {}, status, url: new URL(url), form: form ?? null, @@ -1173,9 +1163,8 @@ async function load_route({ id, invalidating, url, params, route, preload }) { status: 200, error: null, route, - // Reset `form`/`state` on navigation, but not invalidation - form: invalidating ? undefined : null, - state: invalidating ? page.state : null + // Reset `form` on navigation, but not invalidation + form: invalidating ? undefined : null }); } @@ -2012,16 +2001,17 @@ export function goto(url, opts = {}) { * invalidate((url) => url.pathname === '/path'); * ``` * @param {string | URL | ((url: URL) => boolean)} resource The invalidated URL + * @param {{ resetPageState?: boolean }} [options] * @returns {Promise} */ -export function invalidate(resource) { +export function invalidate(resource, { resetPageState = false } = {}) { if (!BROWSER) { throw new Error('Cannot call invalidate(...) on the server'); } push_invalidated(resource); - return _invalidate(); + return _invalidate(true, resetPageState); } /** @@ -2038,15 +2028,16 @@ function push_invalidated(resource) { /** * Causes all `load` functions belonging to the currently active page to re-run. Returns a `Promise` that resolves when the page is subsequently updated. + * @param {{ resetPageState?: boolean }} [options] * @returns {Promise} */ -export function invalidateAll() { +export function invalidateAll({ resetPageState = false } = {}) { if (!BROWSER) { throw new Error('Cannot call invalidateAll() on the server'); } force_invalidation = true; - return _invalidate(); + return _invalidate(true, resetPageState); } /** diff --git a/packages/kit/test/utils.js b/packages/kit/test/utils.js index 8b60d538f91a..08c5161b43bd 100644 --- a/packages/kit/test/utils.js +++ b/packages/kit/test/utils.js @@ -14,7 +14,7 @@ export const test = base.extend({ invalidate: (url) => page.evaluate((url) => invalidate(url), url), - invalidateAll: () => page.evaluate(() => invalidateAll()), + invalidateAll: () => page.evaluate(() => invalidateAll()), beforeNavigate: (fn) => page.evaluate((fn) => beforeNavigate(fn), fn), diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 5458c54e9715..0162a7906576 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -2476,6 +2476,7 @@ declare module '$app/navigation' { export function invalidate(resource: string | URL | ((url: URL) => boolean)): Promise; /** * Causes all `load` functions belonging to the currently active page to re-run. Returns a `Promise` that resolves when the page is subsequently updated. + * @param * */ export function invalidateAll(): Promise; /** From d463ccfc87205ea23bc5ab9ca21ecc06ded7e704 Mon Sep 17 00:00:00 2001 From: Patrick Date: Tue, 5 Aug 2025 21:44:05 +0200 Subject: [PATCH 09/11] generate types --- packages/kit/types/index.d.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 0162a7906576..4540e7846c59 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -2473,12 +2473,15 @@ declare module '$app/navigation' { * ``` * @param resource The invalidated URL * */ - export function invalidate(resource: string | URL | ((url: URL) => boolean)): Promise; + export function invalidate(resource: string | URL | ((url: URL) => boolean), { resetPageState }?: { + resetPageState?: boolean; + }): Promise; /** * Causes all `load` functions belonging to the currently active page to re-run. Returns a `Promise` that resolves when the page is subsequently updated. - * @param * */ - export function invalidateAll(): Promise; + export function invalidateAll({ resetPageState }?: { + resetPageState?: boolean; + }): Promise; /** * Causes all currently active remote functions to refresh, and all `load` functions belonging to the currently active page to re-run (unless disabled via the option argument). * Returns a `Promise` that resolves when the page is subsequently updated. From 9a3bd1bb76a637b881d83a1d1c86fd21c288c67e Mon Sep 17 00:00:00 2001 From: Patrick Date: Tue, 5 Aug 2025 21:49:47 +0200 Subject: [PATCH 10/11] Update test utils --- packages/kit/test/ambient.d.ts | 4 ++-- packages/kit/test/utils.d.ts | 4 ++-- packages/kit/test/utils.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/kit/test/ambient.d.ts b/packages/kit/test/ambient.d.ts index a9f7761197ca..906553e9a49c 100644 --- a/packages/kit/test/ambient.d.ts +++ b/packages/kit/test/ambient.d.ts @@ -14,8 +14,8 @@ declare global { } ) => Promise; - const invalidate: (url: string) => Promise; - const invalidateAll: () => Promise; + const invalidate: (url: string, opts?: { resetPageState?: boolean }) => Promise; + const invalidateAll: (opts?: { resetPageState?: boolean }) => Promise; const preloadData: (url: string) => Promise; const beforeNavigate: (fn: (navigation: BeforeNavigate) => void | boolean) => void; const afterNavigate: (fn: (navigation: AfterNavigate) => void) => void; diff --git a/packages/kit/test/utils.d.ts b/packages/kit/test/utils.d.ts index db9eae5e59f5..109b80021baa 100644 --- a/packages/kit/test/utils.d.ts +++ b/packages/kit/test/utils.d.ts @@ -16,8 +16,8 @@ export const test: TestType< PlaywrightTestOptions & { app: { goto(url: string, opts?: { replaceState?: boolean }): Promise; - invalidate(url: string): Promise; - invalidateAll(): Promise; + invalidate(url: string, opts?: { resetPageState?: boolean }): Promise; + invalidateAll(opts?: { resetPageState?: boolean }): Promise; beforeNavigate(fn: (navigation: BeforeNavigate) => void | boolean): void; afterNavigate(fn: (navigation: AfterNavigate) => void): void; preloadCode(pathname: string): Promise; diff --git a/packages/kit/test/utils.js b/packages/kit/test/utils.js index 08c5161b43bd..da2d972bc952 100644 --- a/packages/kit/test/utils.js +++ b/packages/kit/test/utils.js @@ -12,9 +12,9 @@ export const test = base.extend({ void use({ goto: (url, opts) => page.evaluate(({ url, opts }) => goto(url, opts), { url, opts }), - invalidate: (url) => page.evaluate((url) => invalidate(url), url), + invalidate: (url, opts) => page.evaluate((url) => invalidate(url, opts), url), - invalidateAll: () => page.evaluate(() => invalidateAll()), + invalidateAll: (opts) => page.evaluate(() => invalidateAll(opts)), beforeNavigate: (fn) => page.evaluate((fn) => beforeNavigate(fn), fn), From ba171826ab6f7a7fb3e62bee669c7ffd4c03d5e6 Mon Sep 17 00:00:00 2001 From: Patrick Date: Tue, 5 Aug 2025 22:12:09 +0200 Subject: [PATCH 11/11] Satisfy linter --- .../apps/basics/src/routes/actions/update-form/+page.svelte | 2 +- .../basics/src/routes/shallow-routing/push-state/+page.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/kit/test/apps/basics/src/routes/actions/update-form/+page.svelte b/packages/kit/test/apps/basics/src/routes/actions/update-form/+page.svelte index fd69b8b08794..608fa9bc9332 100644 --- a/packages/kit/test/apps/basics/src/routes/actions/update-form/+page.svelte +++ b/packages/kit/test/apps/basics/src/routes/actions/update-form/+page.svelte @@ -20,7 +20,7 @@
{JSON.stringify(form)}
- + To enhance diff --git a/packages/kit/test/apps/basics/src/routes/shallow-routing/push-state/+page.svelte b/packages/kit/test/apps/basics/src/routes/shallow-routing/push-state/+page.svelte index 528e15c59e04..72d9ad41919b 100644 --- a/packages/kit/test/apps/basics/src/routes/shallow-routing/push-state/+page.svelte +++ b/packages/kit/test/apps/basics/src/routes/shallow-routing/push-state/+page.svelte @@ -17,7 +17,7 @@ - +

active: {page.state.active ?? false}

{data.now}