Skip to content

Commit 3876b30

Browse files
authored
fix: ensure effect_tracking correctly handles tracking reactions (#14005)
* fix: ensure effect_tracking correctly handles tracking reactions * fix: ensure effect_tracking correctly handles tracking reactions
1 parent 777d059 commit 3876b30

File tree

5 files changed

+60
-2
lines changed

5 files changed

+60
-2
lines changed

.changeset/clean-badgers-battle.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: ensure effect_tracking correctly handles tracking reactions

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import {
1515
set_is_destroying_effect,
1616
set_is_flushing_effect,
1717
set_signal_status,
18-
untrack
18+
untrack,
19+
skip_reaction
1920
} from '../runtime.js';
2021
import {
2122
DIRTY,
@@ -167,7 +168,9 @@ export function effect_tracking() {
167168
return false;
168169
}
169170

170-
return (active_reaction.f & UNOWNED) === 0;
171+
// If it's skipped, that's because we're inside an unowned
172+
// that is not being tracked by another reaction
173+
return !skip_reaction;
171174
}
172175

173176
/**
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target, logs }) {
6+
let btn1 = target.querySelector('button');
7+
8+
btn1?.click();
9+
flushSync();
10+
11+
btn1?.click();
12+
flushSync();
13+
14+
btn1?.click();
15+
flushSync();
16+
17+
assert.deepEqual(logs, ['light', 'dark', 'light']);
18+
}
19+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<script>
2+
import { store, themeState } from './theme.svelte.js';
3+
4+
let i = 0;
5+
6+
const increment = () => {
7+
store.update(() => ({ theme: ++i % 2 == 0 ? 'dark' : 'light' }));
8+
}
9+
</script>
10+
11+
<button onclick={increment}>+</button>
12+
13+
{themeState.value.theme}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { fromStore, writable } from 'svelte/store';
2+
3+
export const store = writable({ theme: 'dark' });
4+
5+
class ThemeState {
6+
#storeState = fromStore(store);
7+
value = $derived(this.#storeState.current);
8+
9+
constructor() {
10+
$effect.root(() => {
11+
$effect(() => {
12+
console.log(this.value.theme);
13+
});
14+
});
15+
}
16+
}
17+
18+
export const themeState = new ThemeState();

0 commit comments

Comments
 (0)