Skip to content

Commit 966ccfb

Browse files
fix: set deriveds as CLEAN if they are assigned to (#15592)
* fix: set deriveds as `CLEAN` if they are assigned to * chore: remove only * chore: remove unnecessary typecast * fix: set unowned as `MAYBE_DIRTY` instead of `CLEAN` * fix: visit the derived function when to update the dependencies even when it's reassigned * fix: use `execute_derived` instead of `update_reaction` * fix: execute deriveds eagerly when they are set if DIRTY
1 parent 708f541 commit 966ccfb

File tree

5 files changed

+49
-4
lines changed

5 files changed

+49
-4
lines changed

Diff for: .changeset/nervous-kids-shake.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: set deriveds as `CLEAN` if they are assigned to

Diff for: packages/svelte/src/internal/client/reactivity/deriveds.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ function get_derived_parent_effect(derived) {
131131
* @param {Derived} derived
132132
* @returns {T}
133133
*/
134-
function execute_derived(derived) {
134+
export function execute_derived(derived) {
135135
var value;
136136
var prev_active_effect = active_effect;
137137

Diff for: packages/svelte/src/internal/client/reactivity/sources.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ import {
2828
UNOWNED,
2929
MAYBE_DIRTY,
3030
BLOCK_EFFECT,
31-
ROOT_EFFECT,
32-
EFFECT_IS_UPDATING
31+
ROOT_EFFECT
3332
} from '../constants.js';
3433
import * as e from '../errors.js';
3534
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
3635
import { get_stack } from '../dev/tracing.js';
3736
import { component_context, is_runes } from '../context.js';
3837
import { proxy } from '../proxy.js';
38+
import { execute_derived } from './deriveds.js';
3939

4040
export let inspect_effects = new Set();
4141
export const old_values = new Map();
@@ -172,6 +172,14 @@ export function internal_set(source, value) {
172172
}
173173
}
174174

175+
if ((source.f & DERIVED) !== 0) {
176+
// if we are assigning to a dirty derived we set it to clean/maybe dirty but we also eagerly execute it to track the dependencies
177+
if ((source.f & DIRTY) !== 0) {
178+
execute_derived(/** @type {Derived} */ (source));
179+
}
180+
set_signal_status(source, (source.f & UNOWNED) === 0 ? CLEAN : MAYBE_DIRTY);
181+
}
182+
175183
mark_reactions(source, DIRTY);
176184

177185
// It's possible that the current reaction might not have up-to-date dependencies

Diff for: packages/svelte/src/internal/client/runtime.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
} from './constants.js';
2828
import { flush_tasks } from './dom/task.js';
2929
import { internal_set, old_values } from './reactivity/sources.js';
30-
import { destroy_derived_effects, update_derived } from './reactivity/deriveds.js';
30+
import { destroy_derived_effects, execute_derived, update_derived } from './reactivity/deriveds.js';
3131
import * as e from './errors.js';
3232
import { FILENAME } from '../../constants.js';
3333
import { tracing_mode_flag } from '../flags/index.js';

Diff for: packages/svelte/tests/signals/test.ts

+32
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,38 @@ describe('signals', () => {
10801080
};
10811081
});
10821082

1083+
test("deriveds set after they are DIRTY doesn't get updated on get", () => {
1084+
return () => {
1085+
const a = state(0);
1086+
const b = derived(() => $.get(a));
1087+
1088+
set(b, 1);
1089+
assert.equal($.get(b), 1);
1090+
1091+
set(a, 2);
1092+
assert.equal($.get(b), 2);
1093+
set(b, 3);
1094+
1095+
assert.equal($.get(b), 3);
1096+
};
1097+
});
1098+
1099+
test("unowned deriveds set after they are DIRTY doesn't get updated on get", () => {
1100+
return () => {
1101+
const a = state(0);
1102+
const b = derived(() => $.get(a));
1103+
const c = derived(() => $.get(b));
1104+
1105+
set(b, 1);
1106+
assert.equal($.get(c), 1);
1107+
1108+
set(a, 2);
1109+
1110+
assert.equal($.get(b), 2);
1111+
assert.equal($.get(c), 2);
1112+
};
1113+
});
1114+
10831115
test('deriveds containing effects work correctly when used with untrack', () => {
10841116
return () => {
10851117
let a = render_effect(() => {});

0 commit comments

Comments
 (0)