diff --git a/.changeset/honest-rabbits-glow.md b/.changeset/honest-rabbits-glow.md new file mode 100644 index 0000000000..92494aeb09 --- /dev/null +++ b/.changeset/honest-rabbits-glow.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: cleanup `each` items in legacy mode diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index 954dcb2214..4c3971e903 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -32,7 +32,12 @@ import { pause_effect, resume_effect } from '../../reactivity/effects.js'; -import { source, mutable_source, internal_set } from '../../reactivity/sources.js'; +import { + source, + mutable_source, + internal_set, + remove_from_legacy_sources +} from '../../reactivity/sources.js'; import { array_from, is_array } from '../../../shared/utils.js'; import { INERT } from '#client/constants'; import { queue_micro_task } from '../task.js'; @@ -549,7 +554,16 @@ function create_item( current_each_item = item; try { - item.e = branch(() => render_fn(anchor, v, i, get_collection), hydrating); + item.e = branch(() => { + render_fn(anchor, v, i, get_collection); + // we only need to clean this up if the item is reactive and mutable + // because that's when we add the source to the context preventing garbage collection of it + if (reactive && mutable) { + return () => { + remove_from_legacy_sources(item.v); + }; + } + }, hydrating); item.e.prev = prev && prev.e; item.e.next = next && next.e; diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index 40a3e4e77f..bf2c30747e 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -112,6 +112,15 @@ export function mutable_source(initial_value, immutable = false) { return s; } +/** + * @param {Source} source + */ +export function remove_from_legacy_sources(source) { + if (component_context?.l?.s) { + component_context.l.s = component_context.l.s.filter((s) => s !== source); + } +} + /** * @template V * @param {Value} source