Skip to content

Commit a38ea02

Browse files
authored
fix: don't mark deriveds as clean if updating during teardown (#15997)
1 parent 4875cd6 commit a38ea02

File tree

4 files changed

+52
-5
lines changed

4 files changed

+52
-5
lines changed

.changeset/old-insects-divide.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: don't mark deriveds as clean if updating during teardown

packages/svelte/src/internal/client/reactivity/deriveds.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import {
99
update_reaction,
1010
increment_write_version,
1111
set_active_effect,
12-
push_reaction_value
12+
push_reaction_value,
13+
is_destroying_effect
1314
} from '../runtime.js';
1415
import { equals, safe_equals } from './equality.js';
1516
import * as e from '../errors.js';
@@ -172,13 +173,18 @@ export function execute_derived(derived) {
172173
*/
173174
export function update_derived(derived) {
174175
var value = execute_derived(derived);
175-
var status =
176-
(skip_reaction || (derived.f & UNOWNED) !== 0) && derived.deps !== null ? MAYBE_DIRTY : CLEAN;
177-
178-
set_signal_status(derived, status);
179176

180177
if (!derived.equals(value)) {
181178
derived.v = value;
182179
derived.wv = increment_write_version();
183180
}
181+
182+
// don't mark derived clean if we're reading it inside a
183+
// cleanup function, or it will cache a stale value
184+
if (is_destroying_effect) return;
185+
186+
var status =
187+
(skip_reaction || (derived.f & UNOWNED) !== 0) && derived.deps !== null ? MAYBE_DIRTY : CLEAN;
188+
189+
set_signal_status(derived, status);
184190
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { test } from '../../test';
2+
import { flushSync } from 'svelte';
3+
4+
export default test({
5+
html: `<button>toggle (false)</button>`,
6+
7+
async test({ assert, target, logs }) {
8+
assert.deepEqual(logs, ['up', { foo: false, bar: false }]);
9+
10+
const button = target.querySelector('button');
11+
12+
flushSync(() => button?.click());
13+
assert.deepEqual(logs, [
14+
'up',
15+
{ foo: false, bar: false },
16+
'down',
17+
{ foo: false, bar: false },
18+
'up',
19+
{ foo: true, bar: true }
20+
]);
21+
}
22+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script>
2+
let foo = $state(false)
3+
let bar = $derived(foo)
4+
5+
$effect(() => {
6+
console.log('up', { foo, bar });
7+
8+
return () =>{
9+
console.log('down', { foo, bar });
10+
};
11+
});
12+
</script>
13+
14+
<button onclick={() => foo = !foo}>toggle ({foo})</button>

0 commit comments

Comments
 (0)