Skip to content

Commit fc4dd2d

Browse files
authored
fix: lazily connect derievds (in deriveds) to their parent (#15129)
1 parent 3f8ce21 commit fc4dd2d

File tree

4 files changed

+46
-14
lines changed

4 files changed

+46
-14
lines changed

.changeset/few-beans-bow.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: lazily connect derievds (in deriveds) to their parent

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,6 @@ export function derived(fn) {
6868
signal.created = get_stack('CreatedAt');
6969
}
7070

71-
if (parent_derived !== null) {
72-
(parent_derived.children ??= []).push(signal);
73-
}
74-
7571
return signal;
7672
}
7773

packages/svelte/src/internal/client/runtime.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -957,26 +957,30 @@ export function get(signal) {
957957
new_deps.push(signal);
958958
}
959959
}
960-
} else if (is_derived && /** @type {Derived} */ (signal).deps === null) {
960+
}
961+
962+
if (
963+
is_derived &&
964+
/** @type {Derived} */ (signal).deps === null &&
965+
(active_reaction === null || untracking || (active_reaction.f & DERIVED) !== 0)
966+
) {
961967
var derived = /** @type {Derived} */ (signal);
962968
var parent = derived.parent;
963-
var target = derived;
964969

965-
while (parent !== null) {
966-
// Attach the derived to the nearest parent effect, if there are deriveds
967-
// in between then we also need to attach them too
970+
if (parent !== null) {
971+
// Attach the derived to the nearest parent effect or derived
968972
if ((parent.f & DERIVED) !== 0) {
969973
var parent_derived = /** @type {Derived} */ (parent);
970974

971-
target = parent_derived;
972-
parent = parent_derived.parent;
975+
if (!parent_derived.children?.includes(derived)) {
976+
(parent_derived.children ??= []).push(derived);
977+
}
973978
} else {
974979
var parent_effect = /** @type {Effect} */ (parent);
975980

976-
if (!parent_effect.deriveds?.includes(target)) {
977-
(parent_effect.deriveds ??= []).push(target);
981+
if (!parent_effect.deriveds?.includes(derived)) {
982+
(parent_effect.deriveds ??= []).push(derived);
978983
}
979-
break;
980984
}
981985
}
982986
}

packages/svelte/tests/signals/test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,33 @@ describe('signals', () => {
803803
};
804804
});
805805

806+
test('nested deriveds do not connect inside parent deriveds if unused', () => {
807+
return () => {
808+
let a = render_effect(() => {});
809+
let b: Derived<void> | undefined;
810+
811+
const destroy = effect_root(() => {
812+
a = render_effect(() => {
813+
$.untrack(() => {
814+
b = derived(() => {
815+
derived(() => {});
816+
derived(() => {});
817+
derived(() => {});
818+
});
819+
$.get(b);
820+
});
821+
});
822+
});
823+
824+
assert.deepEqual(a.deriveds?.length, 1);
825+
assert.deepEqual(b?.children, null);
826+
827+
destroy();
828+
829+
assert.deepEqual(a.deriveds, null);
830+
};
831+
});
832+
806833
test('deriveds containing effects work correctly when used with untrack', () => {
807834
return () => {
808835
let a = render_effect(() => {});

0 commit comments

Comments
 (0)