From 743b2a93fefcea92cf6852ccf5ea975a6afbe990 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 9 Jul 2025 09:00:54 -0400 Subject: [PATCH] use update_version instead of WeakRef in SvelteSet/SvelteMap --- packages/svelte/src/internal/client/runtime.js | 6 +++++- packages/svelte/src/reactivity/map.js | 13 +++++-------- packages/svelte/src/reactivity/set.js | 13 ++++--------- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index fce6c78b56e4..38ca0dff5c8d 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -132,6 +132,8 @@ let write_version = 1; /** @type {number} Used to version each read of a source of derived to avoid duplicating depedencies inside a reaction */ let read_version = 0; +export let update_version = read_version; + // If we are working with a get() chain that has no active container, // to prevent memory leaks, we skip adding the reaction. export let skip_reaction = false; @@ -265,6 +267,7 @@ export function update_reaction(reaction) { var previous_reaction_sources = source_ownership; var previous_component_context = component_context; var previous_untracking = untracking; + var previous_update_version = update_version; var flags = reaction.f; @@ -278,7 +281,7 @@ export function update_reaction(reaction) { source_ownership = null; set_component_context(reaction.ctx); untracking = false; - read_version++; + update_version = ++read_version; reaction.f |= EFFECT_IS_UPDATING; @@ -366,6 +369,7 @@ export function update_reaction(reaction) { source_ownership = previous_reaction_sources; set_component_context(previous_component_context); untracking = previous_untracking; + update_version = previous_update_version; reaction.f ^= EFFECT_IS_UPDATING; } diff --git a/packages/svelte/src/reactivity/map.js b/packages/svelte/src/reactivity/map.js index 35946c5b088e..93668fa01a13 100644 --- a/packages/svelte/src/reactivity/map.js +++ b/packages/svelte/src/reactivity/map.js @@ -2,7 +2,7 @@ import { DEV } from 'esm-env'; import { set, source, state } from '../internal/client/reactivity/sources.js'; import { label, tag } from '../internal/client/dev/tracing.js'; -import { active_reaction, get } from '../internal/client/runtime.js'; +import { active_reaction, get, update_version } from '../internal/client/runtime.js'; import { increment } from './utils.js'; import { teardown } from '../internal/client/reactivity/effects.js'; @@ -57,8 +57,7 @@ export class SvelteMap extends Map { #sources = new Map(); #version = state(0); #size = state(0); - /**@type {WeakRef | null} */ - #initial_reaction = null; + #update_version = -1; /** * @param {Iterable | null | undefined} [value] @@ -67,10 +66,7 @@ export class SvelteMap extends Map { super(); if (active_reaction !== null) { - // we use a WeakRef (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef) - // so that if this Map is somehow stored outside of the active reaction, - // it will not prevent the reaction from being garbage collected. - this.#initial_reaction = new WeakRef(active_reaction); + this.#update_version = update_version; } if (DEV) { @@ -99,9 +95,10 @@ export class SvelteMap extends Map { * @returns {Source} */ #source(value) { - if (this.#initial_reaction !== null && this.#initial_reaction.deref() === active_reaction) { + if (update_version === this.#update_version) { return state(value); } + return source(value); } diff --git a/packages/svelte/src/reactivity/set.js b/packages/svelte/src/reactivity/set.js index 66c015114238..5a236222c0fd 100644 --- a/packages/svelte/src/reactivity/set.js +++ b/packages/svelte/src/reactivity/set.js @@ -2,7 +2,7 @@ import { DEV } from 'esm-env'; import { source, set, state } from '../internal/client/reactivity/sources.js'; import { label, tag } from '../internal/client/dev/tracing.js'; -import { active_reaction, get } from '../internal/client/runtime.js'; +import { active_reaction, get, update_version } from '../internal/client/runtime.js'; import { increment } from './utils.js'; import { teardown } from '../internal/client/reactivity/effects.js'; @@ -51,9 +51,7 @@ export class SvelteSet extends Set { #sources = new Map(); #version = state(0); #size = state(0); - - /**@type {WeakRef | null}*/ - #initial_reaction = null; + #update_version = -1; /** * @param {Iterable | null | undefined} [value] @@ -62,10 +60,7 @@ export class SvelteSet extends Set { super(); if (active_reaction !== null) { - // we use a WeakRef (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef) - // so that if this Map is somehow stored outside of the active reaction, - // it will not prevent the reaction from being garbage collected. - this.#initial_reaction = new WeakRef(active_reaction); + this.#update_version = update_version; } if (DEV) { @@ -96,7 +91,7 @@ export class SvelteSet extends Set { * @returns {Source} */ #source(value) { - if (this.#initial_reaction !== null && this.#initial_reaction.deref() === active_reaction) { + if (this.#update_version === update_version) { return state(value); } return source(value);