From b199f83071c32165d7e860fe9d261ecd952cc751 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Mon, 9 Feb 2026 21:29:46 -0500 Subject: [PATCH] feat: allow deriveds to reference their own values --- .changeset/honest-dingos-bake.md | 5 +++ .../internal/client/reactivity/deriveds.js | 42 +++---------------- .../svelte/src/internal/client/runtime.js | 4 ++ .../samples/derived-fn-recursive/_config.js | 21 ---------- .../samples/derived-fn-recursive/main.svelte | 11 ----- 5 files changed, 15 insertions(+), 68 deletions(-) create mode 100644 .changeset/honest-dingos-bake.md delete mode 100644 packages/svelte/tests/runtime-runes/samples/derived-fn-recursive/_config.js delete mode 100644 packages/svelte/tests/runtime-runes/samples/derived-fn-recursive/main.svelte diff --git a/.changeset/honest-dingos-bake.md b/.changeset/honest-dingos-bake.md new file mode 100644 index 0000000000..7b94115ff9 --- /dev/null +++ b/.changeset/honest-dingos-bake.md @@ -0,0 +1,5 @@ +--- +'svelte': minor +--- + +feat: allow deriveds to reference their own values diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index bb732bdd1e..1a90e02cd3 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -283,13 +283,6 @@ export function destroy_derived_effects(derived) { } } -/** - * The currently updating deriveds, used to detect infinite recursion - * in dev mode and provide a nicer error than 'too much recursion' - * @type {Derived[]} - */ -let stack = []; - /** * @param {Derived} derived * @returns {Effect | null} @@ -313,40 +306,17 @@ function get_derived_parent_effect(derived) { * @returns {T} */ export function execute_derived(derived) { - var value; var prev_active_effect = active_effect; set_active_effect(get_derived_parent_effect(derived)); - if (DEV) { - let prev_eager_effects = eager_effects; - set_eager_effects(new Set()); - try { - if (includes.call(stack, derived)) { - e.derived_references_self(); - } - - stack.push(derived); - - derived.f &= ~WAS_MARKED; - destroy_derived_effects(derived); - value = update_reaction(derived); - } finally { - set_active_effect(prev_active_effect); - set_eager_effects(prev_eager_effects); - stack.pop(); - } - } else { - try { - derived.f &= ~WAS_MARKED; - destroy_derived_effects(derived); - value = update_reaction(derived); - } finally { - set_active_effect(prev_active_effect); - } + try { + derived.f &= ~WAS_MARKED; + destroy_derived_effects(derived); + return update_reaction(derived); + } finally { + set_active_effect(prev_active_effect); } - - return value; } /** diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 70eeabb789..28e067b33b 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -618,6 +618,10 @@ export function get(signal) { if (is_derived) { var derived = /** @type {Derived} */ (signal); + if ((derived.f & REACTION_IS_UPDATING) !== 0) { + return derived.v === UNINITIALIZED ? undefined : derived.v; + } + if (is_destroying_effect) { var value = derived.v; diff --git a/packages/svelte/tests/runtime-runes/samples/derived-fn-recursive/_config.js b/packages/svelte/tests/runtime-runes/samples/derived-fn-recursive/_config.js deleted file mode 100644 index ae38cafd69..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/derived-fn-recursive/_config.js +++ /dev/null @@ -1,21 +0,0 @@ -import { flushSync } from 'svelte'; -import { test } from '../../test'; - -export default test({ - html: `\n0`, - - mode: ['client'], - - test({ assert, target }) { - const btn = target.querySelector('button'); - - btn?.click(); - - assert.throws( - flushSync, - 'derived_references_self\nA derived value cannot reference itself recursively' - ); - - assert.htmlEqual(target.innerHTML, `\n0`); - } -}); diff --git a/packages/svelte/tests/runtime-runes/samples/derived-fn-recursive/main.svelte b/packages/svelte/tests/runtime-runes/samples/derived-fn-recursive/main.svelte deleted file mode 100644 index 4ccb5e2d47..0000000000 --- a/packages/svelte/tests/runtime-runes/samples/derived-fn-recursive/main.svelte +++ /dev/null @@ -1,11 +0,0 @@ - - - - -{even}