Skip to content

Commit 117082b

Browse files
authored
fix: improve handling of unowned derived signals (#10842)
1 parent 1fc4173 commit 117082b

File tree

4 files changed

+85
-1
lines changed

4 files changed

+85
-1
lines changed

.changeset/olive-mice-fix.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: improve handling of unowned derived signals

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function derived(fn) {
4141
/** @type {import('#client').DerivedDebug} */ (signal).inspect = new Set();
4242
}
4343

44-
if (current_reaction !== null) {
44+
if (current_reaction !== null && (current_reaction.f & DERIVED) !== 0) {
4545
if (current_reaction.deriveds === null) {
4646
current_reaction.deriveds = [signal];
4747
} else {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target }) {
6+
let [btn1, btn2] = target.querySelectorAll('button');
7+
8+
flushSync(() => {
9+
btn1.click();
10+
});
11+
12+
flushSync(() => {
13+
btn2.click();
14+
});
15+
16+
assert.htmlEqual(
17+
target.innerHTML,
18+
`<button>Activate</button><button>Toggle</button>\nneighba\nneighba`
19+
);
20+
21+
flushSync(() => {
22+
btn2.click();
23+
});
24+
25+
assert.htmlEqual(
26+
target.innerHTML,
27+
`<button>Activate</button><button>Toggle</button>\nzeeba\nzeeba`
28+
);
29+
}
30+
});
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<script>
2+
import { untrack } from 'svelte';
3+
4+
class Model {
5+
data = $state();
6+
7+
constructor(data) {
8+
this.data = data;
9+
}
10+
11+
name = $derived(this.data?.name);
12+
source = $derived(this.data?.source);
13+
14+
toggle() {
15+
this.data.name = this.data.name === 'zeeba' ? 'neighba' : 'zeeba';
16+
}
17+
}
18+
19+
let model = $state(new Model({ name: 'zeeba', source: 'initial' }));
20+
21+
let setModel = (source) => {
22+
let next = new Model({ name: 'zeeba', source });
23+
model = next;
24+
}
25+
26+
let needsSet = $state(false);
27+
28+
$effect(() => {
29+
if(needsSet) {
30+
setModel('effect');
31+
untrack(() => {
32+
needsSet = false;
33+
});
34+
}
35+
});
36+
37+
let setWithEffect = () => {
38+
needsSet = true;
39+
};
40+
41+
let toggle = () => {
42+
model.toggle();
43+
}
44+
</script>
45+
46+
<button onclick={setWithEffect}>Activate</button>
47+
<button onclick={toggle}>Toggle</button>
48+
{model.name}
49+
{model.data.name}

0 commit comments

Comments
 (0)