diff --git a/documentation/docs/98-reference/.generated/client-warnings.md b/documentation/docs/98-reference/.generated/client-warnings.md index b49d4aae8d..60cb02a1ee 100644 --- a/documentation/docs/98-reference/.generated/client-warnings.md +++ b/documentation/docs/98-reference/.generated/client-warnings.md @@ -37,15 +37,41 @@ function add() { ### await_reactivity_loss ``` -Detected reactivity loss +Detected reactivity loss when reading `%name%`. This happens when state is read in an async function after an earlier `await` ``` -TODO +Svelte's signal-based reactivity works by tracking which bits of state are read when a template or `$derived(...)` expression executes. If an expression contains an `await`, Svelte transforms it such that any state _after_ the `await` is also tracked — in other words, in a case like this... + +```js +let total = $derived(await a + b); +``` + +...both `a` and `b` are tracked, even though `b` is only read once `a` has resolved, after the initial execution. + +This does _not_ apply to an `await` that is not 'visible' inside the expression. In a case like this... + +```js +async function sum() { + return await a + b; +} + +let total = $derived(await sum()); +``` + +...`total` will depend on `a` (which is read immediately) but not `b` (which is not). The solution is to pass the values into the function: + +```js +async function sum(a, b) { + return await a + b; +} + +let total = $derived(await sum(a, b)); +``` ### await_waterfall ``` -An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app. +An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app ``` TODO diff --git a/packages/svelte/messages/client-warnings/warnings.md b/packages/svelte/messages/client-warnings/warnings.md index 0a6af616c3..e4390318eb 100644 --- a/packages/svelte/messages/client-warnings/warnings.md +++ b/packages/svelte/messages/client-warnings/warnings.md @@ -32,13 +32,39 @@ function add() { ## await_reactivity_loss -> Detected reactivity loss +> Detected reactivity loss when reading `%name%`. This happens when state is read in an async function after an earlier `await` -TODO +Svelte's signal-based reactivity works by tracking which bits of state are read when a template or `$derived(...)` expression executes. If an expression contains an `await`, Svelte transforms it such that any state _after_ the `await` is also tracked — in other words, in a case like this... + +```js +let total = $derived(await a + b); +``` + +...both `a` and `b` are tracked, even though `b` is only read once `a` has resolved, after the initial execution. + +This does _not_ apply to an `await` that is not 'visible' inside the expression. In a case like this... + +```js +async function sum() { + return await a + b; +} + +let total = $derived(await sum()); +``` + +...`total` will depend on `a` (which is read immediately) but not `b` (which is not). The solution is to pass the values into the function: + +```js +async function sum(a, b) { + return await a + b; +} + +let total = $derived(await sum(a, b)); +``` ## await_waterfall -> An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app. +> An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app TODO diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index d450165c7b..d9c8cfa00d 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -875,7 +875,10 @@ export function get(signal) { var was_read = from_async_derived.deps !== null && from_async_derived.deps.includes(signal); if (!tracking && !was_read) { - w.await_reactivity_loss(); + w.await_reactivity_loss(/** @type {string} */ (signal.label)); + + // eslint-disable-next-line no-console + console.warn(get_stack('TracedAt')); } } diff --git a/packages/svelte/src/internal/client/warnings.js b/packages/svelte/src/internal/client/warnings.js index 48639a4f4f..902b471d8b 100644 --- a/packages/svelte/src/internal/client/warnings.js +++ b/packages/svelte/src/internal/client/warnings.js @@ -19,23 +19,24 @@ export function assignment_value_stale(property, location) { } /** - * Detected reactivity loss + * Detected reactivity loss when reading `%name%`. This happens when state is read in an async function after an earlier `await` + * @param {string} name */ -export function await_reactivity_loss() { +export function await_reactivity_loss(name) { if (DEV) { - console.warn(`%c[svelte] await_reactivity_loss\n%cDetected reactivity loss\nhttps://svelte.dev/e/await_reactivity_loss`, bold, normal); + console.warn(`%c[svelte] await_reactivity_loss\n%cDetected reactivity loss when reading \`${name}\`. This happens when state is read in an async function after an earlier \`await\`\nhttps://svelte.dev/e/await_reactivity_loss`, bold, normal); } else { console.warn(`https://svelte.dev/e/await_reactivity_loss`); } } /** - * An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app. + * An async value (%location%) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app * @param {string} location */ export function await_waterfall(location) { if (DEV) { - console.warn(`%c[svelte] await_waterfall\n%cAn async value (${location}) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app.\nhttps://svelte.dev/e/await_waterfall`, bold, normal); + console.warn(`%c[svelte] await_waterfall\n%cAn async value (${location}) was not read immediately after it resolved. This often indicates an unnecessary waterfall, which can slow down your app\nhttps://svelte.dev/e/await_waterfall`, bold, normal); } else { console.warn(`https://svelte.dev/e/await_waterfall`); }