Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/chatty-dolphins-complain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: ensure unowned deriveds correctly get re-linked to the graph
27 changes: 17 additions & 10 deletions packages/svelte/src/internal/client/runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,29 +205,36 @@ export function check_dirtiness(reaction) {
reaction.f ^= DISCONNECTED;
}

var unowned_dirty = false;

for (i = 0; i < dependencies.length; i++) {
var dependency = dependencies[i];

if (check_dirtiness(/** @type {Derived} */ (dependency))) {
if (!unowned_dirty && check_dirtiness(/** @type {Derived} */ (dependency))) {
update_derived(/** @type {Derived} */ (dependency));
}

var version_mismatch = dependency.version > reaction.version;

// If we are working with an unowned signal as part of an effect (due to !skip_reaction)
// and the version hasn't changed, we still need to check that this reaction
// is linked to the dependency source – otherwise future updates will not be caught.
if (
is_unowned &&
active_effect !== null &&
!skip_reaction &&
!dependency?.reactions?.includes(reaction)
) {
(dependency.reactions ??= []).push(reaction);
}
if (is_unowned && active_effect !== null && !skip_reaction) {
if (!dependency?.reactions?.includes(reaction)) {
(dependency.reactions ??= []).push(reaction);
}

if (dependency.version > reaction.version) {
if (version_mismatch) {
unowned_dirty = true;
}
} else if (version_mismatch) {
return true;
}
}

if (unowned_dirty) {
return true;
}
}

// Unowned signals should never be marked as clean unless they
Expand Down
33 changes: 33 additions & 0 deletions packages/svelte/tests/signals/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -781,4 +781,37 @@ describe('signals', () => {
assert.equal($.get(count), 0n);
};
});

test('unowned deriveds correctly re-attach to their source', () => {
const log: any[] = [];

return () => {
const a = state(0);
const b = state(0);
const c = derived(() => {
$.get(a);
return $.get(b);
});

$.get(c);

set(a, 1);

const destroy = effect_root(() => {
render_effect(() => {
log.push($.get(c));
});
});

assert.deepEqual(log, [0]);

set(b, 1);

flushSync();

assert.deepEqual(log, [0, 1]);

destroy();
};
});
});
Loading