diff --git a/.changeset/gold-eels-lay.md b/.changeset/gold-eels-lay.md new file mode 100644 index 0000000000..ef6ceb4dab --- /dev/null +++ b/.changeset/gold-eels-lay.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: depend on reads of deriveds created within reaction (async mode) diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js index 299251a2dc..11405a8e66 100644 --- a/packages/svelte/src/internal/client/reactivity/deriveds.js +++ b/packages/svelte/src/internal/client/reactivity/deriveds.js @@ -29,7 +29,7 @@ import * as w from '../warnings.js'; import { async_effect, destroy_effect } from './effects.js'; import { inspect_effects, internal_set, set_inspect_effects, source } from './sources.js'; import { get_stack } from '../dev/tracing.js'; -import { tracing_mode_flag } from '../../flags/index.js'; +import { async_mode_flag, tracing_mode_flag } from '../../flags/index.js'; import { Boundary } from '../dom/blocks/boundary.js'; import { component_context } from '../context.js'; import { UNINITIALIZED } from '../../../constants.js'; @@ -231,7 +231,7 @@ export function async_derived(fn, location) { export function user_derived(fn) { const d = derived(fn); - push_reaction_value(d); + if (!async_mode_flag) push_reaction_value(d); return d; } diff --git a/packages/svelte/tests/runtime-runes/samples/derived-in-expression/_config.js b/packages/svelte/tests/runtime-runes/samples/derived-in-expression/_config.js new file mode 100644 index 0000000000..73428e0ff2 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/derived-in-expression/_config.js @@ -0,0 +1,74 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + // In non-async mode we're not reacting to deriveds read in the same context they're defined in + skip_no_async: true, + test({ assert, target, logs }) { + const [a, b] = target.querySelectorAll('button'); + + flushSync(() => a?.click()); + assert.htmlEqual( + target.innerHTML, + ` + + +
1/0
a?.click()); + assert.htmlEqual( + target.innerHTML, + ` + + +2/0
b?.click()); + assert.htmlEqual( + target.innerHTML, + ` + + +2/1
b?.click()); + assert.htmlEqual( + target.innerHTML, + ` + + +2/2
+ let object = $state.raw({ a: 0, b: 0 }); + + function a() { + console.log('a'); + return object.a; + } + + function b() { + console.log('b'); + let double = $derived(object.b) + return double; + } + + $effect(() => { + object.a; + console.log('effect a'); + }) + + $effect(() => { + const b = $derived(object.b); + b; + console.log('effect b'); + }) + + + + + +{a()}/{b()}
diff --git a/packages/svelte/tests/runtime-runes/samples/untrack-own-deriveds/_config.js b/packages/svelte/tests/runtime-runes/samples/untrack-own-deriveds/_config.js index b728c3c0be..b5233b01e8 100644 --- a/packages/svelte/tests/runtime-runes/samples/untrack-own-deriveds/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/untrack-own-deriveds/_config.js @@ -13,10 +13,11 @@ export default test({ target.innerHTML, ` -1/2
1/2 +1/2
` ); - assert.deepEqual(logs, [0, 0]); + assert.deepEqual(logs, [0, 0, 0, 0]); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/untrack-own-deriveds/main.svelte b/packages/svelte/tests/runtime-runes/samples/untrack-own-deriveds/main.svelte index bbad2cdf4a..c0dd86993a 100644 --- a/packages/svelte/tests/runtime-runes/samples/untrack-own-deriveds/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/untrack-own-deriveds/main.svelte @@ -17,10 +17,14 @@ $effect(() => { foo = new Foo(); }); + + let bar = $derived(new Foo()); - + {#if foo}{foo.value}/{foo.double}
{/if} + +{bar.value}/{bar.double}