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
pull/15713/head
Paolo Ricciuti 5 months ago committed by GitHub
parent 708f541ad8
commit 966ccfbe74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: set deriveds as `CLEAN` if they are assigned to

@ -131,7 +131,7 @@ function get_derived_parent_effect(derived) {
* @param {Derived} derived
* @returns {T}
*/
function execute_derived(derived) {
export function execute_derived(derived) {
var value;
var prev_active_effect = active_effect;

@ -28,14 +28,14 @@ import {
UNOWNED,
MAYBE_DIRTY,
BLOCK_EFFECT,
ROOT_EFFECT,
EFFECT_IS_UPDATING
ROOT_EFFECT
} from '../constants.js';
import * as e from '../errors.js';
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
import { get_stack } from '../dev/tracing.js';
import { component_context, is_runes } from '../context.js';
import { proxy } from '../proxy.js';
import { execute_derived } from './deriveds.js';
export let inspect_effects = new Set();
export const old_values = new Map();
@ -172,6 +172,14 @@ export function internal_set(source, value) {
}
}
if ((source.f & DERIVED) !== 0) {
// 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
if ((source.f & DIRTY) !== 0) {
execute_derived(/** @type {Derived} */ (source));
}
set_signal_status(source, (source.f & UNOWNED) === 0 ? CLEAN : MAYBE_DIRTY);
}
mark_reactions(source, DIRTY);
// It's possible that the current reaction might not have up-to-date dependencies

@ -27,7 +27,7 @@ import {
} from './constants.js';
import { flush_tasks } from './dom/task.js';
import { internal_set, old_values } from './reactivity/sources.js';
import { destroy_derived_effects, update_derived } from './reactivity/deriveds.js';
import { destroy_derived_effects, execute_derived, update_derived } from './reactivity/deriveds.js';
import * as e from './errors.js';
import { FILENAME } from '../../constants.js';
import { tracing_mode_flag } from '../flags/index.js';

@ -1080,6 +1080,38 @@ describe('signals', () => {
};
});
test("deriveds set after they are DIRTY doesn't get updated on get", () => {
return () => {
const a = state(0);
const b = derived(() => $.get(a));
set(b, 1);
assert.equal($.get(b), 1);
set(a, 2);
assert.equal($.get(b), 2);
set(b, 3);
assert.equal($.get(b), 3);
};
});
test("unowned deriveds set after they are DIRTY doesn't get updated on get", () => {
return () => {
const a = state(0);
const b = derived(() => $.get(a));
const c = derived(() => $.get(b));
set(b, 1);
assert.equal($.get(c), 1);
set(a, 2);
assert.equal($.get(b), 2);
assert.equal($.get(c), 2);
};
});
test('deriveds containing effects work correctly when used with untrack', () => {
return () => {
let a = render_effect(() => {});

Loading…
Cancel
Save