fix: prevent derives without dependencies from ever re-running (#17445)

* fix: prevent derives without dependencies from ever re-running

* tweak

Co-authored-by: David Roizenman <hmnd@users.noreply.github.com>
pull/17456/head
Rich Harris 1 month ago
parent f8bdadc1bf
commit 286b40c452

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: prevent derives without dependencies from ever re-running

@ -9,7 +9,8 @@ import {
STALE_REACTION,
ASYNC,
WAS_MARKED,
DESTROYED
DESTROYED,
CLEAN
} from '#client/constants';
import {
active_reaction,
@ -33,7 +34,7 @@ import { UNINITIALIZED } from '../../../constants.js';
import { batch_values, current_batch } from './batch.js';
import { unset_context } from './async.js';
import { deferred } from '../../shared/utils.js';
import { update_derived_status } from './status.js';
import { set_signal_status, update_derived_status } from './status.js';
/** @type {Effect | null} */
export let current_async_effect = null;
@ -356,15 +357,21 @@ export function update_derived(derived) {
var value = execute_derived(derived);
if (!derived.equals(value)) {
derived.wv = increment_write_version();
// in a fork, we don't update the underlying value, just `batch_values`.
// the underlying value will be updated when the fork is committed.
// otherwise, the next time we get here after a 'real world' state
// change, `derived.equals` may incorrectly return `true`
if (!current_batch?.is_fork) {
if (!current_batch?.is_fork || derived.deps === null) {
derived.v = value;
}
derived.wv = increment_write_version();
// deriveds without dependencies should never be recomputed
if (derived.deps === null) {
set_signal_status(derived, CLEAN);
return;
}
}
}
// don't mark derived clean if we're reading it inside a

@ -0,0 +1,22 @@
import { tick } from 'svelte';
import { test } from '../../test';
export default test({
skip_no_async: true,
async test({ assert, target }) {
const [fork] = target.querySelectorAll('button');
fork.click();
await tick();
const [, increment] = target.querySelectorAll('button');
const p = target.querySelector('p');
assert.equal(p?.textContent, '0');
increment.click();
await tick();
assert.equal(p?.textContent, '1');
}
});

@ -0,0 +1,23 @@
<script>
import { fork } from 'svelte';
class Counter {
count = $state(0);
}
let condition = $state(false);
let counter = $derived(new Counter());
</script>
<button onclick={() => {
fork(() => {
condition = true;
}).commit();
}}>fork</button>
{#if condition}
<button onclick={() => {
counter.count++;
}}>click</button>
<p>{counter.count}</p>
{/if}
Loading…
Cancel
Save