diff --git a/.changeset/forty-dots-punch.md b/.changeset/forty-dots-punch.md new file mode 100644 index 000000000000..913c626f2140 --- /dev/null +++ b/.changeset/forty-dots-punch.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: enable redirects from queries diff --git a/packages/kit/src/runtime/client/remote-functions/query.svelte.js b/packages/kit/src/runtime/client/remote-functions/query.svelte.js index b7be26ef39eb..4cc9e9e156d4 100644 --- a/packages/kit/src/runtime/client/remote-functions/query.svelte.js +++ b/packages/kit/src/runtime/client/remote-functions/query.svelte.js @@ -83,9 +83,7 @@ export function query_batch(id) { } if (result.type === 'redirect') { - // TODO double-check this await goto(result.location); - await new Promise((r) => setTimeout(r, 100)); throw new Redirect(307, result.location); } diff --git a/packages/kit/src/runtime/client/remote-functions/shared.svelte.js b/packages/kit/src/runtime/client/remote-functions/shared.svelte.js index 7d94374f40b1..08d195c5f3d8 100644 --- a/packages/kit/src/runtime/client/remote-functions/shared.svelte.js +++ b/packages/kit/src/runtime/client/remote-functions/shared.svelte.js @@ -21,13 +21,7 @@ export async function remote_request(url) { const result = /** @type {RemoteFunctionResponse} */ (await response.json()); if (result.type === 'redirect') { - // resource_cache.delete(cache_key); - // version++; - // await goto(result.location); - // /** @type {Query} */ (resource).refresh(); - // TODO double-check this await goto(result.location); - await new Promise((r) => setTimeout(r, 100)); throw new Redirect(307, result.location); } diff --git a/packages/kit/src/runtime/server/remote.js b/packages/kit/src/runtime/server/remote.js index cbd843af6c72..d2cd2f192d18 100644 --- a/packages/kit/src/runtime/server/remote.js +++ b/packages/kit/src/runtime/server/remote.js @@ -117,8 +117,8 @@ async function handle_remote_call_internal(event, state, options, manifest, id) } const form_data = await event.request.formData(); - form_client_refreshes = JSON.parse( - /** @type {string} */ (form_data.get('sveltekit:remote_refreshes')) ?? '[]' + form_client_refreshes = /** @type {string[]} */ ( + JSON.parse(/** @type {string} */ (form_data.get('sveltekit:remote_refreshes')) ?? '[]') ); form_data.delete('sveltekit:remote_refreshes'); @@ -129,7 +129,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id) /** @type {RemoteFunctionResponse} */ ({ type: 'result', result: stringify(data, transport), - refreshes: await serialize_refreshes(/** @type {string[]} */ (form_client_refreshes)) + refreshes: await serialize_refreshes(form_client_refreshes) }) ); } @@ -194,7 +194,7 @@ async function handle_remote_call_internal(event, state, options, manifest, id) * @param {string[]} client_refreshes */ async function serialize_refreshes(client_refreshes) { - const refreshes = /** @type {Record>} */ (state.refreshes); + const refreshes = state.refreshes ?? {}; for (const key of client_refreshes) { if (refreshes[key] !== undefined) continue; diff --git a/packages/kit/test/apps/basics/src/routes/remote/query-redirect/+page.svelte b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/+page.svelte new file mode 100644 index 000000000000..2cf96c388267 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/+page.svelte @@ -0,0 +1,2 @@ +from page +from layout diff --git a/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-common-layout/+layout.svelte b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-common-layout/+layout.svelte new file mode 100644 index 000000000000..dbfd19f02d29 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-common-layout/+layout.svelte @@ -0,0 +1,13 @@ + + + +{#await layoutRedirect(page.url.pathname) then path} +

on page {path} (== {page.url.pathname})

+{/await} + +{@render children()} diff --git a/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-common-layout/+page.svelte b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-common-layout/+page.svelte new file mode 100644 index 000000000000..9d65b32980e5 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-common-layout/+page.svelte @@ -0,0 +1 @@ +

should never see this

diff --git a/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-common-layout/redirected/+page.svelte b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-common-layout/redirected/+page.svelte new file mode 100644 index 000000000000..a0164f2662b3 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-common-layout/redirected/+page.svelte @@ -0,0 +1 @@ +

redirected

diff --git a/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-page/+page.svelte b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-page/+page.svelte new file mode 100644 index 000000000000..fa4783f66c60 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/from-page/+page.svelte @@ -0,0 +1,8 @@ + + + +{#await pageRedirect() then _} +

should never see this

+{/await} diff --git a/packages/kit/test/apps/basics/src/routes/remote/query-redirect/redirect.remote.js b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/redirect.remote.js new file mode 100644 index 000000000000..e399ff56554b --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/redirect.remote.js @@ -0,0 +1,14 @@ +import { query } from '$app/server'; +import { redirect } from '@sveltejs/kit'; + +export const layoutRedirect = query('unchecked', (path) => { + if (path !== '/remote/query-redirect/from-common-layout/redirected') { + redirect(307, '/remote/query-redirect/from-common-layout/redirected'); + } + + return path; +}); + +export const pageRedirect = query(() => { + redirect(307, '/remote/query-redirect/redirected'); +}); diff --git a/packages/kit/test/apps/basics/src/routes/remote/query-redirect/redirected/+page.svelte b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/redirected/+page.svelte new file mode 100644 index 000000000000..a0164f2662b3 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/remote/query-redirect/redirected/+page.svelte @@ -0,0 +1 @@ +

redirected

diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js index 36c6ed0ad9d8..6b11c9b15483 100644 --- a/packages/kit/test/apps/basics/test/test.js +++ b/packages/kit/test/apps/basics/test/test.js @@ -1600,6 +1600,30 @@ test.describe('remote functions', () => { } }); + test('query redirects on page load (query in common layout)', async ({ + page, + javaScriptEnabled + }) => { + // TODO remove once async SSR exists + if (!javaScriptEnabled) return; + + await page.goto('/remote/query-redirect'); + await page.click('a[href="/remote/query-redirect/from-common-layout"]'); + await expect(page.locator('#redirected')).toHaveText('redirected'); + await expect(page.locator('#layout-query')).toHaveText( + 'on page /remote/query-redirect/from-common-layout/redirected (== /remote/query-redirect/from-common-layout/redirected)' + ); + }); + + test('query redirects on page load (query on page)', async ({ page, javaScriptEnabled }) => { + // TODO remove once async SSR exists + if (!javaScriptEnabled) return; + + await page.goto('/remote/query-redirect'); + await page.click('a[href="/remote/query-redirect/from-page"]'); + await expect(page.locator('#redirected')).toHaveText('redirected'); + }); + test('form works', async ({ page }) => { await page.goto('/remote/form'); await page.fill('#input-task', 'hi');