diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index bd0cc314cf..ee07a342a8 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -1,3 +1,4 @@ +/** @import { ComponentContext } from '#client' */ /** @import { Derived, Source } from './types.js' */ import { DEV } from 'esm-env'; import { @@ -5,7 +6,8 @@ import { PROPS_IS_IMMUTABLE, PROPS_IS_LAZY_INITIAL, PROPS_IS_RUNES, - PROPS_IS_UPDATED + PROPS_IS_UPDATED, + UNINITIALIZED } from '../../../constants.js'; import { get_descriptor, is_function } from '../../shared/utils.js'; import { set, source, update } from './sources.js'; diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index c217ac2722..b9a7d9c8a4 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -40,6 +40,7 @@ import { } from './context.js'; import { handle_error, invoke_error_boundary } from './error-handling.js'; import { snapshot } from '../shared/clone.js'; +import { UNINITIALIZED } from '../../constants.js'; let is_flushing = false; @@ -818,7 +819,13 @@ export function get(signal) { if (is_derived) { derived = /** @type {Derived} */ (signal); - var value = (derived.f & CLEAN) !== 0 ? execute_derived(derived) : derived.v; + var value = derived.v; + + // if the derived is dirty, or depends on the values that just changed, re-execute + if ((derived.f & CLEAN) !== 0 || depends_on_old_values(derived)) { + value = execute_derived(derived); + } + old_values.set(derived, value); return value; @@ -828,6 +835,24 @@ export function get(signal) { return signal.v; } +/** @param {Derived} derived */ +function depends_on_old_values(derived) { + if (derived.v === UNINITIALIZED) return true; // we don't know, so assume the worst + if (derived.deps === null) return false; + + for (const dep of derived.deps) { + if (old_values.has(dep)) { + return true; + } + + if ((dep.f & DERIVED) !== 0 && depends_on_old_values(/** @type {Derived} */ (dep))) { + return true; + } + } + + return false; +} + /** * Like `get`, but checks for `undefined`. Used for `var` declarations because they can be accessed before being declared * @template V