From c587356f9652935015028bb78c67eb575de3867f Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 01:48:58 +0200 Subject: [PATCH 01/11] test --- packages/kit/test/apps/async/package.json | 24 ++++++++++++++++++ .../kit/test/apps/async/playwright.config.js | 1 + packages/kit/test/apps/async/src/app.html | 12 +++++++++ .../test/apps/async/src/routes/+layout.svelte | 9 +++++++ .../test/apps/async/src/routes/+page.svelte | 1 + .../src/routes/after_navigate/+page.svelte | 10 ++++++++ .../kit/test/apps/async/static/favicon.png | Bin 0 -> 1571 bytes packages/kit/test/apps/async/svelte.config.js | 11 ++++++++ packages/kit/test/apps/async/test/test.js | 14 ++++++++++ packages/kit/test/apps/async/tsconfig.json | 10 ++++++++ packages/kit/test/apps/async/vite.config.js | 21 +++++++++++++++ pnpm-lock.yaml | 21 +++++++++++++++ 12 files changed, 134 insertions(+) create mode 100644 packages/kit/test/apps/async/package.json create mode 100644 packages/kit/test/apps/async/playwright.config.js create mode 100644 packages/kit/test/apps/async/src/app.html create mode 100644 packages/kit/test/apps/async/src/routes/+layout.svelte create mode 100644 packages/kit/test/apps/async/src/routes/+page.svelte create mode 100644 packages/kit/test/apps/async/src/routes/after_navigate/+page.svelte create mode 100644 packages/kit/test/apps/async/static/favicon.png create mode 100644 packages/kit/test/apps/async/svelte.config.js create mode 100644 packages/kit/test/apps/async/test/test.js create mode 100644 packages/kit/test/apps/async/tsconfig.json create mode 100644 packages/kit/test/apps/async/vite.config.js diff --git a/packages/kit/test/apps/async/package.json b/packages/kit/test/apps/async/package.json new file mode 100644 index 000000000000..4fc2f1636248 --- /dev/null +++ b/packages/kit/test/apps/async/package.json @@ -0,0 +1,24 @@ +{ + "name": "test-async", + "private": true, + "version": "0.0.1", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "prepare": "svelte-kit sync", + "check": "svelte-kit sync && tsc && svelte-check", + "test": "pnpm test:dev && pnpm test:build", + "test:dev": "DEV=true playwright test", + "test:build": "playwright test" + }, + "devDependencies": { + "@sveltejs/kit": "workspace:^", + "@sveltejs/vite-plugin-svelte": "catalog:", + "svelte": "catalog:", + "svelte-check": "catalog:", + "typescript": "^5.5.4", + "vite": "catalog:" + }, + "type": "module" +} diff --git a/packages/kit/test/apps/async/playwright.config.js b/packages/kit/test/apps/async/playwright.config.js new file mode 100644 index 000000000000..33d36b651014 --- /dev/null +++ b/packages/kit/test/apps/async/playwright.config.js @@ -0,0 +1 @@ +export { config as default } from '../../utils.js'; diff --git a/packages/kit/test/apps/async/src/app.html b/packages/kit/test/apps/async/src/app.html new file mode 100644 index 000000000000..79d946ed86a3 --- /dev/null +++ b/packages/kit/test/apps/async/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/kit/test/apps/async/src/routes/+layout.svelte b/packages/kit/test/apps/async/src/routes/+layout.svelte new file mode 100644 index 000000000000..18102623b5bc --- /dev/null +++ b/packages/kit/test/apps/async/src/routes/+layout.svelte @@ -0,0 +1,9 @@ + + +{@render children()} diff --git a/packages/kit/test/apps/async/src/routes/+page.svelte b/packages/kit/test/apps/async/src/routes/+page.svelte new file mode 100644 index 000000000000..0a88878c34c2 --- /dev/null +++ b/packages/kit/test/apps/async/src/routes/+page.svelte @@ -0,0 +1 @@ +

home

diff --git a/packages/kit/test/apps/async/src/routes/after_navigate/+page.svelte b/packages/kit/test/apps/async/src/routes/after_navigate/+page.svelte new file mode 100644 index 000000000000..2e7d06b97444 --- /dev/null +++ b/packages/kit/test/apps/async/src/routes/after_navigate/+page.svelte @@ -0,0 +1,10 @@ + + +
{runs}
diff --git a/packages/kit/test/apps/async/static/favicon.png b/packages/kit/test/apps/async/static/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..825b9e65af7c104cfb07089bb28659393b4f2097 GIT binary patch literal 1571 zcmV+;2Hg3HP)Px)-AP12RCwC$UE6KzI1p6{F2N z1VK2vi|pOpn{~#djwYcWXTI_im_u^TJgMZ4JMOsSj!0ma>B?-(Hr@X&W@|R-$}W@Z zgj#$x=!~7LGqHW?IO8+*oE1MyDp!G=L0#^lUx?;!fXv@l^6SvTnf^ac{5OurzC#ZMYc20lI%HhX816AYVs1T3heS1*WaWH z%;x>)-J}YB5#CLzU@GBR6sXYrD>Vw(Fmt#|JP;+}<#6b63Ike{Fuo!?M{yEffez;| zp!PfsuaC)>h>-AdbnwN13g*1LowNjT5?+lFVd#9$!8Z9HA|$*6dQ8EHLu}U|obW6f z2%uGv?vr=KNq7YYa2Roj;|zooo<)lf=&2yxM@e`kM$CmCR#x>gI>I|*Ubr({5Y^rb zghxQU22N}F51}^yfDSt786oMTc!W&V;d?76)9KXX1 z+6Okem(d}YXmmOiZq$!IPk5t8nnS{%?+vDFz3BevmFNgpIod~R{>@#@5x9zJKEHLHv!gHeK~n)Ld!M8DB|Kfe%~123&Hz1Z(86nU7*G5chmyDe ziV7$pB7pJ=96hpxHv9rCR29%bLOXlKU<_13_M8x)6;P8E1Kz6G<&P?$P^%c!M5`2` zfY2zg;VK5~^>TJGQzc+33-n~gKt{{of8GzUkWmU110IgI0DLxRIM>0US|TsM=L|@F z0Bun8U!cRB7-2apz=y-7*UxOxz@Z0)@QM)9wSGki1AZ38ceG7Q72z5`i;i=J`ILzL z@iUO?SBBG-0cQuo+an4TsLy-g-x;8P4UVwk|D8{W@U1Zi z!M)+jqy@nQ$p?5tsHp-6J304Q={v-B>66$P0IDx&YT(`IcZ~bZfmn11#rXd7<5s}y zBi9eim&zQc0Dk|2>$bs0PnLmDfMP5lcXRY&cvJ=zKxI^f0%-d$tD!`LBf9^jMSYUA zI8U?CWdY@}cRq6{5~y+)#h1!*-HcGW@+gZ4B};0OnC~`xQOyH19z*TA!!BJ%9s0V3F?CAJ{hTd#*tf+ur-W9MOURF-@B77_-OshsY}6 zOXRY=5%C^*26z?l)1=$bz30!so5tfABdSYzO+H=CpV~aaUefmjvfZ3Ttu9W&W3Iu6 zROlh0MFA5h;my}8lB0tAV-Rvc2Zs_CCSJnx@d`**$idgy-iMob4dJWWw|21b4NB=LfsYp0Aeh{Ov)yztQi;eL4y5 zMi>8^SzKqk8~k?UiQK^^-5d8c%bV?$F8%X~czyiaKCI2=UH !javaScriptEnabled); + +test.describe.configure({ mode: 'parallel' }); + +test('afterNavigate runs after hydration', async ({ page }) => { + await page.goto('/after_navigate'); + + expect(await page.innerText('pre')).toBe('1'); +}); diff --git a/packages/kit/test/apps/async/tsconfig.json b/packages/kit/test/apps/async/tsconfig.json new file mode 100644 index 000000000000..1d665886266b --- /dev/null +++ b/packages/kit/test/apps/async/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "noEmit": true, + "resolveJsonModule": true + }, + "extends": "./.svelte-kit/tsconfig.json" +} diff --git a/packages/kit/test/apps/async/vite.config.js b/packages/kit/test/apps/async/vite.config.js new file mode 100644 index 000000000000..9640847b2704 --- /dev/null +++ b/packages/kit/test/apps/async/vite.config.js @@ -0,0 +1,21 @@ +import * as path from 'node:path'; +import { sveltekit } from '@sveltejs/kit/vite'; + +/** @type {import('vite').UserConfig} */ +const config = { + build: { + minify: false + }, + clearScreen: false, + plugins: [sveltekit()], + server: { + fs: { + allow: [path.resolve('../../../src')] + } + }, + optimizeDeps: { + exclude: ['svelte'] + } +}; + +export default config; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6d795ceb63e6..0cf25f2c8c00 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -612,6 +612,27 @@ importers: specifier: 'catalog:' version: 6.3.6(@types/node@18.19.119)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) + packages/kit/test/apps/async: + devDependencies: + '@sveltejs/kit': + specifier: workspace:^ + version: link:../../.. + '@sveltejs/vite-plugin-svelte': + specifier: 'catalog:' + version: 6.0.0-next.3(svelte@5.39.8)(vite@6.3.6(@types/node@18.19.119)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0)) + svelte: + specifier: 'catalog:' + version: 5.39.8 + svelte-check: + specifier: 'catalog:' + version: 4.1.1(picomatch@4.0.3)(svelte@5.39.8)(typescript@5.8.3) + typescript: + specifier: ^5.5.4 + version: 5.8.3 + vite: + specifier: 'catalog:' + version: 6.3.6(@types/node@18.19.119)(jiti@2.4.2)(lightningcss@1.30.1)(yaml@2.8.0) + packages/kit/test/apps/basics: devDependencies: '@opentelemetry/api': From 466bf4e3bc00f8f28bcc1cbbca992ab280dd0157 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 01:49:05 +0200 Subject: [PATCH 02/11] fix --- packages/kit/src/runtime/client/client.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 4e79a1300d16..24f194b2d327 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -545,7 +545,7 @@ async function _preload_code(url) { * @param {HTMLElement} target * @param {boolean} hydrate */ -function initialize(result, target, hydrate) { +async function initialize(result, target, hydrate) { if (DEV && result.state.error && document.querySelector('vite-error-overlay')) return; current = result.state; @@ -579,6 +579,7 @@ function initialize(result, target, hydrate) { complete: Promise.resolve() }; + await Promise.resolve(); after_navigate_callbacks.forEach((fn) => fn(navigation)); } From f4ad4a6832b71cedd42245c7c3cb631fb2826f2d Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 02:00:26 +0200 Subject: [PATCH 03/11] changeset --- .changeset/ten-rats-spend.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/ten-rats-spend.md diff --git a/.changeset/ten-rats-spend.md b/.changeset/ten-rats-spend.md new file mode 100644 index 000000000000..b565a4b03539 --- /dev/null +++ b/.changeset/ten-rats-spend.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: `afterNavigate` callback not running after hydration when experimental async is enabled From ef554532c13830dac19e4c9568c571259c6dd1f1 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 02:08:33 +0200 Subject: [PATCH 04/11] lint --- packages/kit/src/runtime/client/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 24f194b2d327..87131c042550 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -579,7 +579,7 @@ async function initialize(result, target, hydrate) { complete: Promise.resolve() }; - await Promise.resolve(); + void await Promise.resolve(); after_navigate_callbacks.forEach((fn) => fn(navigation)); } From 4fda011b5ae3f08fa8ccf344161ff1eb862e7945 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 02:18:41 +0200 Subject: [PATCH 05/11] format --- packages/kit/src/runtime/client/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 87131c042550..ebd8395325d8 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -579,7 +579,7 @@ async function initialize(result, target, hydrate) { complete: Promise.resolve() }; - void await Promise.resolve(); + void (await Promise.resolve()); after_navigate_callbacks.forEach((fn) => fn(navigation)); } From d6bb7de955588a64ce6ad0d92b63a7947af36fa0 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 04:47:51 +0200 Subject: [PATCH 06/11] move awaiting to fix snapshot restore after reload --- packages/kit/src/runtime/client/client.js | 3 ++- .../apps/async/src/routes/snapshot/+page.svelte | 14 ++++++++++++++ packages/kit/test/apps/async/test/test.js | 6 ++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 packages/kit/test/apps/async/src/routes/snapshot/+page.svelte diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index ebd8395325d8..3e2736f7fd47 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -563,6 +563,8 @@ async function initialize(result, target, hydrate) { sync: false }); + void (await Promise.resolve()); + restore_snapshot(current_navigation_index); if (hydrate) { @@ -579,7 +581,6 @@ async function initialize(result, target, hydrate) { complete: Promise.resolve() }; - void (await Promise.resolve()); after_navigate_callbacks.forEach((fn) => fn(navigation)); } diff --git a/packages/kit/test/apps/async/src/routes/snapshot/+page.svelte b/packages/kit/test/apps/async/src/routes/snapshot/+page.svelte new file mode 100644 index 000000000000..160079383b48 --- /dev/null +++ b/packages/kit/test/apps/async/src/routes/snapshot/+page.svelte @@ -0,0 +1,14 @@ + + +
{JSON.stringify(restored)}
diff --git a/packages/kit/test/apps/async/test/test.js b/packages/kit/test/apps/async/test/test.js index 68aa4d241880..579f3b8b08cf 100644 --- a/packages/kit/test/apps/async/test/test.js +++ b/packages/kit/test/apps/async/test/test.js @@ -12,3 +12,9 @@ test('afterNavigate runs after hydration', async ({ page }) => { expect(await page.innerText('pre')).toBe('1'); }); + +test('snapshot are restored after reload', async ({ page }) => { + await page.goto('/snapshot'); + await page.reload(); + expect(await page.innerText('pre')).toBe('{"restored":"yes"}'); +}); From eb56912d31f801baf5679af1a00900df145ed46e Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 04:49:57 +0200 Subject: [PATCH 07/11] Update .changeset/ten-rats-spend.md --- .changeset/ten-rats-spend.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.changeset/ten-rats-spend.md b/.changeset/ten-rats-spend.md index b565a4b03539..8e5a0b35b408 100644 --- a/.changeset/ten-rats-spend.md +++ b/.changeset/ten-rats-spend.md @@ -3,3 +3,4 @@ --- fix: `afterNavigate` callback not running after hydration when experimental async is enabled +fix: Snapshot `restore` method not called after reload when experimental async is enabled From 8c91629e68d9749a2323ffcbe69ad13a17e3dcb7 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 07:25:07 +0200 Subject: [PATCH 08/11] await initialize --- 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 3e2736f7fd47..ad8766a30cb9 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -1693,7 +1693,7 @@ async function navigate({ update(navigation_result.props.page); has_navigated = true; } else { - initialize(navigation_result, target, false); + await initialize(navigation_result, target, false); } const { activeElement } = document; @@ -2796,7 +2796,7 @@ async function _hydrate( result.props.page.state = {}; } - initialize(result, target, hydrate); + await initialize(result, target, hydrate); } /** From 6f470457ee2490c7f468d68dc98b74acebd3fa56 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 07:25:27 +0200 Subject: [PATCH 09/11] comment --- 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 ad8766a30cb9..a87dbaa6f281 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -563,6 +563,7 @@ async function initialize(result, target, hydrate) { sync: false }); + // wait a microtask in case svelte async is enabled which leads to component script blocks to run async void (await Promise.resolve()); restore_snapshot(current_navigation_index); From 7f77132cf684f197e55888531ffb7c1f9fcd3506 Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 07:25:33 +0200 Subject: [PATCH 10/11] typo --- packages/kit/test/apps/async/test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kit/test/apps/async/test/test.js b/packages/kit/test/apps/async/test/test.js index 579f3b8b08cf..3fce3a062373 100644 --- a/packages/kit/test/apps/async/test/test.js +++ b/packages/kit/test/apps/async/test/test.js @@ -13,7 +13,7 @@ test('afterNavigate runs after hydration', async ({ page }) => { expect(await page.innerText('pre')).toBe('1'); }); -test('snapshot are restored after reload', async ({ page }) => { +test('snapshots are restored after reload', async ({ page }) => { await page.goto('/snapshot'); await page.reload(); expect(await page.innerText('pre')).toBe('{"restored":"yes"}'); From d64ed3d59c1c44e5d18cc6c683a64b663962e70c Mon Sep 17 00:00:00 2001 From: Patrick Date: Wed, 8 Oct 2025 07:28:11 +0200 Subject: [PATCH 11/11] comment --- packages/kit/src/runtime/client/client.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index a87dbaa6f281..0d1af16000b7 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -563,7 +563,8 @@ async function initialize(result, target, hydrate) { sync: false }); - // wait a microtask in case svelte async is enabled which leads to component script blocks to run async + // Wait for a microtask in case svelte experimental async is enabled, + // which causes component script blocks to run asynchronously void (await Promise.resolve()); restore_snapshot(current_navigation_index);