feat: allow deriveds to reference their own values

allow-recursive-derived
Rich Harris 17 hours ago
parent 35c845e35d
commit b199f83071

@ -0,0 +1,5 @@
---
'svelte': minor
---
feat: allow deriveds to reference their own values

@ -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;
}
/**

@ -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;

@ -1,21 +0,0 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
html: `<button>increment</button>\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, `<button>increment</button>\n0`);
}
});

@ -1,11 +0,0 @@
<script>
let count = $state(0);
let even = $derived.by(() => {
return count > 0 ? even : 0;
})
</script>
<button onclick={() => count++}>increment</button>
{even}
Loading…
Cancel
Save