From 0dccec912c362c1ff8efc2938cc4a1547e2fcc97 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 8 Feb 2023 22:00:40 -0500 Subject: [PATCH 1/2] print useful errors when subscribing to stores during SSR --- .changeset/large-toes-fetch.md | 5 +++++ packages/kit/src/runtime/app/stores.js | 21 ++++++++++++++++++--- packages/kit/types/ambient.d.ts | 8 +++++++- 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 .changeset/large-toes-fetch.md diff --git a/.changeset/large-toes-fetch.md b/.changeset/large-toes-fetch.md new file mode 100644 index 000000000000..1eedcb65e0ae --- /dev/null +++ b/.changeset/large-toes-fetch.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: better error message when accessing built-in stores on the server diff --git a/packages/kit/src/runtime/app/stores.js b/packages/kit/src/runtime/app/stores.js index 5c79a7ad3f94..67727a119d82 100644 --- a/packages/kit/src/runtime/app/stores.js +++ b/packages/kit/src/runtime/app/stores.js @@ -23,7 +23,7 @@ export const getStores = () => { export const page = { /** @param {(value: any) => void} fn */ subscribe(fn) { - const store = getStores().page; + const store = __SVELTEKIT_DEV__ ? get_store('page') : getStores().page; return store.subscribe(fn); } }; @@ -31,7 +31,7 @@ export const page = { /** @type {typeof import('$app/stores').navigating} */ export const navigating = { subscribe(fn) { - const store = getStores().navigating; + const store = __SVELTEKIT_DEV__ ? get_store('navigating') : getStores().navigating; return store.subscribe(fn); } }; @@ -39,7 +39,7 @@ export const navigating = { /** @type {typeof import('$app/stores').updated} */ export const updated = { subscribe(fn) { - const store = getStores().updated; + const store = __SVELTEKIT_DEV__ ? get_store('updated') : getStores().updated; if (browser) { updated.check = store.check; @@ -55,3 +55,18 @@ export const updated = { ); } }; + +/** + * @template {keyof ReturnType} Name + * @param {Name} name + * @returns {ReturnType[Name]} + */ +function get_store(name) { + try { + return getStores()[name]; + } catch (e) { + throw new Error( + `Cannot subscribe to '${name}' store on the server outside of a Svelte component, as it is bound to the current request via component context. This prevents state from leaking between users.` + ); + } +} diff --git a/packages/kit/types/ambient.d.ts b/packages/kit/types/ambient.d.ts index 606475b4c380..5573b72ce59d 100644 --- a/packages/kit/types/ambient.d.ts +++ b/packages/kit/types/ambient.d.ts @@ -292,16 +292,22 @@ declare module '$app/stores' { /** * A readable store whose value contains page data. + * + * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. */ export const page: Readable; /** * A readable store. * When navigating starts, its value is a `Navigation` object with `from`, `to`, `type` and (if `type === 'popstate'`) `delta` properties. * When navigating finishes, its value reverts to `null`. + * + * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. */ export const navigating: Readable; /** - * A readable store whose initial value is `false`. If [`version.pollInterval`](https://kit.svelte.dev/docs/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling. + * A readable store whose initial value is `false`. If [`version.pollInterval`](https://kit.svelte.dev/docs/configuration#version) is a non-zero value, SvelteKit will poll for new versions of the app and update the store value to `true` when it detects one. `updated.check()` will force an immediate check, regardless of polling. + * + * On the server, this store can only be subscribed to during component initialization. In the browser, it can be subscribed to at any time. */ export const updated: Readable & { check(): Promise }; From 8d5cd5d85955e9a8133fd44eca283d093f2e375e Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Thu, 9 Feb 2023 09:07:44 +0100 Subject: [PATCH 2/2] changeset --- .changeset/large-toes-fetch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/large-toes-fetch.md b/.changeset/large-toes-fetch.md index 1eedcb65e0ae..f9695953cbf7 100644 --- a/.changeset/large-toes-fetch.md +++ b/.changeset/large-toes-fetch.md @@ -2,4 +2,4 @@ '@sveltejs/kit': patch --- -fix: better error message when accessing built-in stores on the server +fix: print useful error when subscribing to SvelteKit's stores at the wrong time during SSR