fix: ensure unowned deriveds can add themselves as reactions while connected

Fixes #15829 and potentially #15853
pull/16249/head
Simon Holthausen 3 months ago
parent da2feafe67
commit c6af159ec2

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: ensure unowned deriveds can add themselves as reactions while connected

@ -294,7 +294,12 @@ export function update_reaction(reaction) {
reaction.deps = deps = new_deps;
}
if (!skip_reaction) {
if (
!skip_reaction ||
// Deriveds that already have reactions can cleanup, so we still add them as reactions
((flags & DERIVED) !== 0 &&
/** @type {import('#client').Derived} */ (reaction).reactions !== null)
) {
for (i = skipped_deps; i < deps.length; i++) {
(deps[i].reactions ??= []).push(reaction);
}

@ -112,6 +112,50 @@ describe('signals', () => {
};
});
test('unowned deriveds are not added as reactions but trigger effects', () => {
var obj = state(undefined);
class C1 {
#v = state(0);
get v() {
return $.get(this.#v);
}
set v(v: number) {
set(this.#v, v);
}
}
return () => {
console.log('1');
let d = derived(() => $.get(obj)?.v || '-');
const log: number[] = [];
assert.equal($.get(d), '-');
console.log('2');
let destroy = effect_root(() => {
render_effect(() => {
log.push($.get(d));
});
});
console.log('3');
set(obj, new C1());
flushSync();
console.log('4');
assert.equal($.get(d), '-');
$.get(obj)!.v = 1;
flushSync();
console.log('5');
assert.equal($.get(d), 1);
assert.deepEqual(log, ['-', 1]);
destroy();
// ensure we're not leaking reactions
assert.equal(obj.reactions, null);
assert.equal(d.reactions, null);
};
});
test('derived from state', () => {
const log: number[] = [];

Loading…
Cancel
Save