From 70ccabfa159494b1267bbbcde9880326c614c33b Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 15 Aug 2024 22:50:10 +0800 Subject: [PATCH 1/9] add error type --- packages/kit/src/runtime/client/client.js | 11 ++++++++++- packages/kit/types/index.d.ts | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index f91728bccc2c..91a131b7492d 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -1780,7 +1780,7 @@ export function invalidateAll() { * Returns a Promise that resolves with the result of running the new route's `load` functions once the preload is complete. * * @param {string} href Page to preload - * @returns {Promise<{ type: 'loaded'; status: number; data: Record } | { type: 'redirect'; location: string }>} + * @returns {Promise<{ type: 'loaded'; status: number; data: Record } | { type: 'redirect'; location: string } | { type: 'error'; status: number; error: App.Error }>} */ export async function preloadData(href) { if (!BROWSER) { @@ -1803,6 +1803,15 @@ export async function preloadData(href) { } const { status, data } = result.props.page ?? page; + + if (result.type === 'loaded' && result.state.error) { + return { + type: 'error', + status, + error: result.state.error + }; + } + return { type: result.type, status, data }; } diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index e3bf549b2407..7371f7fab120 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -2107,6 +2107,10 @@ declare module '$app/navigation' { } | { type: 'redirect'; location: string; + } | { + type: 'error'; + status: number; + error: App.Error; }>; /** * Programmatically imports the code for routes that haven't yet been fetched. From deb31deb7ddba271c77b1c661045ca4b317de977 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 15 Aug 2024 23:03:50 +0800 Subject: [PATCH 2/9] don't return status since it's always 200 --- packages/kit/src/runtime/client/client.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 91a131b7492d..57bba26f844b 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -1780,7 +1780,7 @@ export function invalidateAll() { * Returns a Promise that resolves with the result of running the new route's `load` functions once the preload is complete. * * @param {string} href Page to preload - * @returns {Promise<{ type: 'loaded'; status: number; data: Record } | { type: 'redirect'; location: string } | { type: 'error'; status: number; error: App.Error }>} + * @returns {Promise<{ type: 'loaded'; status: number; data: Record } | { type: 'redirect'; location: string } | { type: 'error'; error: App.Error }>} */ export async function preloadData(href) { if (!BROWSER) { @@ -1807,7 +1807,6 @@ export async function preloadData(href) { if (result.type === 'loaded' && result.state.error) { return { type: 'error', - status, error: result.state.error }; } From 7e01a9253c6cc90a5aa25a0683d35d74e9323587 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 15 Aug 2024 23:04:15 +0800 Subject: [PATCH 3/9] prettier --- packages/kit/src/runtime/client/client.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 57bba26f844b..ce42c381e96c 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -1802,8 +1802,6 @@ export async function preloadData(href) { }; } - const { status, data } = result.props.page ?? page; - if (result.type === 'loaded' && result.state.error) { return { type: 'error', @@ -1811,6 +1809,7 @@ export async function preloadData(href) { }; } + const { status, data } = result.props.page ?? page; return { type: result.type, status, data }; } From 28a97ddf7e404d7e1e1d5818e1be48b6e99be7f2 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Thu, 15 Aug 2024 23:37:05 +0800 Subject: [PATCH 4/9] add status --- packages/kit/src/runtime/client/client.js | 31 +++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index ce42c381e96c..6a09160e79dc 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -814,10 +814,10 @@ function diff_search_params(old_url, new_url) { } /** - * @param {Omit & { error: App.Error }} opts + * @param {Omit & { error: App.Error; status: number }} opts * @returns {import('./types.js').NavigationFinished} */ -function preload_error({ error, url, route, params }) { +function preload_error({ error, status, url, route, params }) { return { type: 'loaded', state: { @@ -827,7 +827,16 @@ function preload_error({ error, url, route, params }) { params, branch: [] }, - props: { page, constructors: [] } + props: { + page: { + ...page, + url, + params, + status, + error + }, + constructors: [] + } }; } @@ -888,12 +897,14 @@ async function load_route({ id, invalidating, url, params, route, preload }) { } catch (error) { const handled_error = await handle_error(error, { url, params, route: { id } }); + const status = get_status(error); + if (preload_tokens.has(preload)) { - return preload_error({ error: handled_error, url, params, route }); + return preload_error({ error: handled_error, status, url, params, route }); } return load_root_error_page({ - status: get_status(error), + status, error: handled_error, url, route @@ -977,16 +988,18 @@ async function load_route({ id, invalidating, url, params, route, preload }) { }; } + let status = get_status(err); + if (preload_tokens.has(preload)) { return preload_error({ error: await handle_error(err, { params, url, route: { id: route.id } }), + status, url, params, route }); } - let status = get_status(err); /** @type {App.Error} */ let error; @@ -1780,7 +1793,7 @@ export function invalidateAll() { * Returns a Promise that resolves with the result of running the new route's `load` functions once the preload is complete. * * @param {string} href Page to preload - * @returns {Promise<{ type: 'loaded'; status: number; data: Record } | { type: 'redirect'; location: string } | { type: 'error'; error: App.Error }>} + * @returns {Promise<{ type: 'loaded'; status: number; data: Record } | { type: 'redirect'; location: string } | { type: 'error'; status: number; error: App.Error }>} */ export async function preloadData(href) { if (!BROWSER) { @@ -1802,14 +1815,16 @@ export async function preloadData(href) { }; } + const { status, data } = result.props.page ?? page; + if (result.type === 'loaded' && result.state.error) { return { type: 'error', + status, error: result.state.error }; } - const { status, data } = result.props.page ?? page; return { type: result.type, status, data }; } From ca0632bfdb0136824994e4a66674555bccaa4e74 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Fri, 16 Aug 2024 00:06:34 +0800 Subject: [PATCH 5/9] add comment --- packages/kit/src/runtime/client/client.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 6a09160e79dc..8155c639001c 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -828,12 +828,11 @@ function preload_error({ error, status, url, route, params }) { branch: [] }, props: { + // we skipped loading the error page, so we need to use the current page's + // page store, but we still pass the updated status to the preloadData function page: { ...page, - url, - params, - status, - error + status }, constructors: [] } From c3de1c60dd4a23dbcf568c37e6e304466a1eed73 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Fri, 16 Aug 2024 00:07:21 +0800 Subject: [PATCH 6/9] prettier --- 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 8155c639001c..065189da6f86 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -828,8 +828,8 @@ function preload_error({ error, status, url, route, params }) { branch: [] }, props: { - // we skipped loading the error page, so we need to use the current page's - // page store, but we still pass the updated status to the preloadData function + // we skipped loading the error page, so we need to use the current page + // store, but we still pass the updated status to the preloadData function page: { ...page, status From 2a83dace208159a3ac9a8edc65f2004aace53802 Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Fri, 16 Aug 2024 21:17:04 +0800 Subject: [PATCH 7/9] return status for redirects --- packages/kit/src/runtime/client/client.js | 4 +++- packages/kit/src/runtime/client/types.d.ts | 3 ++- packages/kit/src/runtime/server/data/index.js | 1 + packages/kit/src/runtime/server/page/index.js | 1 + packages/kit/src/types/internal.d.ts | 1 + packages/kit/types/index.d.ts | 6 +++--- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index 065189da6f86..c6540c18db24 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -983,6 +983,7 @@ async function load_route({ id, invalidating, url, params, route, preload }) { if (err instanceof Redirect) { return { type: 'redirect', + status: err.status, location: err.location }; } @@ -1792,7 +1793,7 @@ export function invalidateAll() { * Returns a Promise that resolves with the result of running the new route's `load` functions once the preload is complete. * * @param {string} href Page to preload - * @returns {Promise<{ type: 'loaded'; status: number; data: Record } | { type: 'redirect'; location: string } | { type: 'error'; status: number; error: App.Error }>} + * @returns {Promise<({ type: 'loaded'; data: Record } | { type: 'redirect'; location: string } | { type: 'error'; error: App.Error }) & { status: number; }>} */ export async function preloadData(href) { if (!BROWSER) { @@ -1810,6 +1811,7 @@ export async function preloadData(href) { if (result.type === 'redirect') { return { type: result.type, + status: result.status, location: result.location }; } diff --git a/packages/kit/src/runtime/client/types.d.ts b/packages/kit/src/runtime/client/types.d.ts index 50a78a049f1c..de7702c253e6 100644 --- a/packages/kit/src/runtime/client/types.d.ts +++ b/packages/kit/src/runtime/client/types.d.ts @@ -46,6 +46,7 @@ export type NavigationResult = NavigationRedirect | NavigationFinished; export type NavigationRedirect = { type: 'redirect'; + status: number; location: string; }; @@ -54,7 +55,7 @@ export type NavigationFinished = { state: NavigationState; props: { constructors: Array; - components?: Array; + components?: SvelteComponent[]; page: Page; form?: Record | null; [key: `data_${number}`]: Record; diff --git a/packages/kit/src/runtime/server/data/index.js b/packages/kit/src/runtime/server/data/index.js index b278ee31873b..299f92301c94 100644 --- a/packages/kit/src/runtime/server/data/index.js +++ b/packages/kit/src/runtime/server/data/index.js @@ -178,6 +178,7 @@ function json_response(json, status = 200) { export function redirect_json_response(redirect) { return json_response({ type: 'redirect', + status: redirect.status, location: redirect.location }); } diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js index 3424c5fcdce5..a314b6af18dc 100644 --- a/packages/kit/src/runtime/server/page/index.js +++ b/packages/kit/src/runtime/server/page/index.js @@ -208,6 +208,7 @@ export async function render_page(event, page, options, manifest, state, resolve if (state.prerendering && should_prerender_data) { const body = JSON.stringify({ type: 'redirect', + status: err.status, location: err.location }); diff --git a/packages/kit/src/types/internal.d.ts b/packages/kit/src/types/internal.d.ts index c9dbb51ce007..ccaf5ec0725d 100644 --- a/packages/kit/src/types/internal.d.ts +++ b/packages/kit/src/types/internal.d.ts @@ -220,6 +220,7 @@ export interface RouteData { export type ServerRedirectNode = { type: 'redirect'; + status: number; location: string; }; diff --git a/packages/kit/types/index.d.ts b/packages/kit/types/index.d.ts index 7371f7fab120..b0bfdce84ff0 100644 --- a/packages/kit/types/index.d.ts +++ b/packages/kit/types/index.d.ts @@ -2100,17 +2100,17 @@ declare module '$app/navigation' { * * @param href Page to preload * */ - export function preloadData(href: string): Promise<{ + export function preloadData(href: string): Promise<({ type: 'loaded'; - status: number; data: Record; } | { type: 'redirect'; location: string; } | { type: 'error'; - status: number; error: App.Error; + }) & { + status: number; }>; /** * Programmatically imports the code for routes that haven't yet been fetched. From 36b6542c19abe7031675d00f7b355381ae754f3d Mon Sep 17 00:00:00 2001 From: Tee Ming Date: Fri, 16 Aug 2024 21:29:49 +0800 Subject: [PATCH 8/9] fix test --- packages/kit/test/prerendering/basics/test/tests.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/kit/test/prerendering/basics/test/tests.spec.js b/packages/kit/test/prerendering/basics/test/tests.spec.js index 4b87d683d2b6..945a053bac66 100644 --- a/packages/kit/test/prerendering/basics/test/tests.spec.js +++ b/packages/kit/test/prerendering/basics/test/tests.spec.js @@ -32,6 +32,7 @@ test('renders a server-side redirect', () => { expect(data).toEqual({ type: 'redirect', + status: 301, location: 'https://example.com/redirected' }); }); From ac9460b2df504a7bb00e982b36781af1ec14155f Mon Sep 17 00:00:00 2001 From: Chew Tee Ming Date: Mon, 25 Nov 2024 12:19:45 +0800 Subject: [PATCH 9/9] add test and changeset --- .changeset/modern-dodos-hang.md | 5 +++++ .../routing/preloading/error/+page.svelte | 21 +++++++++++++++++++ .../routing/preloading/error/[id]/+page.js | 11 ++++++++++ .../preloading/error/[id]/+page.svelte | 0 .../basics/test/cross-platform/client.test.js | 12 +++++++++++ 5 files changed, 49 insertions(+) create mode 100644 .changeset/modern-dodos-hang.md create mode 100644 packages/kit/test/apps/basics/src/routes/routing/preloading/error/+page.svelte create mode 100644 packages/kit/test/apps/basics/src/routes/routing/preloading/error/[id]/+page.js create mode 100644 packages/kit/test/apps/basics/src/routes/routing/preloading/error/[id]/+page.svelte diff --git a/.changeset/modern-dodos-hang.md b/.changeset/modern-dodos-hang.md new file mode 100644 index 000000000000..20d094ff853f --- /dev/null +++ b/.changeset/modern-dodos-hang.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': major +--- + +feat: add error result type to `preloadData` diff --git a/packages/kit/test/apps/basics/src/routes/routing/preloading/error/+page.svelte b/packages/kit/test/apps/basics/src/routes/routing/preloading/error/+page.svelte new file mode 100644 index 000000000000..e5772e7ec5d0 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/routing/preloading/error/+page.svelte @@ -0,0 +1,21 @@ + + + + + + +

{data.type} {data.status} {data.error?.message}

diff --git a/packages/kit/test/apps/basics/src/routes/routing/preloading/error/[id]/+page.js b/packages/kit/test/apps/basics/src/routes/routing/preloading/error/[id]/+page.js new file mode 100644 index 000000000000..bedc745a9574 --- /dev/null +++ b/packages/kit/test/apps/basics/src/routes/routing/preloading/error/[id]/+page.js @@ -0,0 +1,11 @@ +import { error } from '@sveltejs/kit'; + +export function load({ params }) { + if (params.id === '404') { + error(404, { message: 'Not found' }); + } + + if (params.id === '500') { + throw new Error('Oopsie'); + } +} diff --git a/packages/kit/test/apps/basics/src/routes/routing/preloading/error/[id]/+page.svelte b/packages/kit/test/apps/basics/src/routes/routing/preloading/error/[id]/+page.svelte new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/kit/test/apps/basics/test/cross-platform/client.test.js b/packages/kit/test/apps/basics/test/cross-platform/client.test.js index 71338a8422ce..2b50dbd466a7 100644 --- a/packages/kit/test/apps/basics/test/cross-platform/client.test.js +++ b/packages/kit/test/apps/basics/test/cross-platform/client.test.js @@ -667,6 +667,18 @@ test.describe('Prefetching', () => { await app.goto('/routing/preloading/preload-error'); await expect(page.locator('p')).toHaveText('hello'); }); + + test('preloads errors', async ({ page }) => { + await page.goto('/routing/preloading/error'); + + await expect(page.locator('p')).toHaveText('undefined undefined undefined'); + + page.locator('button', { hasText: '404' }).click(); + await expect(page.locator('p')).toHaveText('error 404 Not found'); + + page.locator('button', { hasText: '500' }).click(); + await expect(page.locator('p')).toHaveText('error 500 Oopsie (500 Internal Error)'); + }); }); test.describe('Routing', () => {