diff --git a/package.json b/package.json index 0159474d3b..4f5a11143b 100644 --- a/package.json +++ b/package.json @@ -5,9 +5,6 @@ "private": true, "type": "module", "license": "MIT", - "engines": { - "pnpm": "^9.0.0" - }, "repository": { "type": "git", "url": "git+https://github.com/sveltejs/svelte.git" diff --git a/packages/svelte/src/internal/client/constants.js b/packages/svelte/src/internal/client/constants.js index d087948b5e..543f812e79 100644 --- a/packages/svelte/src/internal/client/constants.js +++ b/packages/svelte/src/internal/client/constants.js @@ -5,16 +5,17 @@ export const BLOCK_EFFECT = 1 << 4; export const BRANCH_EFFECT = 1 << 5; export const ROOT_EFFECT = 1 << 6; export const UNOWNED = 1 << 7; -export const CLEAN = 1 << 8; -export const DIRTY = 1 << 9; -export const MAYBE_DIRTY = 1 << 10; -export const INERT = 1 << 11; -export const DESTROYED = 1 << 12; -export const EFFECT_RAN = 1 << 13; +export const DISCONNECTED = 1 << 8; +export const CLEAN = 1 << 9; +export const DIRTY = 1 << 10; +export const MAYBE_DIRTY = 1 << 11; +export const INERT = 1 << 12; +export const DESTROYED = 1 << 13; +export const EFFECT_RAN = 1 << 14; /** 'Transparent' effects do not create a transition boundary */ -export const EFFECT_TRANSPARENT = 1 << 14; +export const EFFECT_TRANSPARENT = 1 << 15; /** Svelte 4 legacy mode props need to be handled with deriveds and be recognized elsewhere, hence the dedicated flag */ -export const LEGACY_DERIVED_PROP = 1 << 15; +export const LEGACY_DERIVED_PROP = 1 << 16; export const STATE_SYMBOL = Symbol('$state'); export const LOADING_ATTR_SYMBOL = Symbol(''); diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index 22d2e5306a..c3f5945a7a 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -16,7 +16,8 @@ import { STATE_SYMBOL, BLOCK_EFFECT, ROOT_EFFECT, - LEGACY_DERIVED_PROP + LEGACY_DERIVED_PROP, + DISCONNECTED } from './constants.js'; import { flush_tasks } from './dom/task.js'; import { add_owner } from './dev/ownership.js'; @@ -197,6 +198,7 @@ export function check_dirtiness(reaction) { if (is_dirty && !is_unowned) { return true; } + var is_disconnected = (reaction.f & DISCONNECTED) !== 0; if ((flags & MAYBE_DIRTY) !== 0 || (is_dirty && is_unowned)) { var dependencies = reaction.deps; @@ -239,7 +241,7 @@ export function check_dirtiness(reaction) { } else if ((reaction.f & DIRTY) !== 0) { // `signal` might now be dirty, as a result of calling `check_dirtiness` and/or `update_derived` return true; - } else if ((reaction.f & DERIVED) !== 0) { + } else if (is_disconnected) { // It might be that the derived was was dereferenced from its dependencies but has now come alive again. // In thise case, we need to re-attach it to the graph and mark it dirty if any of its dependencies have // changed since. @@ -261,6 +263,9 @@ export function check_dirtiness(reaction) { if (!is_unowned) { set_signal_status(reaction, CLEAN); } + if (is_disconnected) { + reaction.f ^= DISCONNECTED; + } } return is_dirty; @@ -441,6 +446,11 @@ function remove_reaction(signal, dependency) { // allowing it to either reconnect in the future, or be GC'd by the VM. if (reactions_length === 0 && (dependency.f & DERIVED) !== 0) { set_signal_status(dependency, MAYBE_DIRTY); + // If we are working with a derived that is owned by an effect, then mark it as being + // disconnected. + if ((dependency.f & (UNOWNED | DISCONNECTED)) === 0) { + dependency.f ^= DISCONNECTED; + } remove_reactions(/** @type {import('#client').Derived} **/ (dependency), 0); } }