From 77f01fdc97dd1b5f00f6634d0dbfc0168a0b29bd Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Tue, 17 Sep 2024 17:14:17 +0100 Subject: [PATCH] fix: ensure the if block condition is wrapped in a derived --- .changeset/dirty-worms-type.md | 5 +++++ .../svelte/src/internal/client/dom/blocks/if.js | 14 ++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) create mode 100644 .changeset/dirty-worms-type.md diff --git a/.changeset/dirty-worms-type.md b/.changeset/dirty-worms-type.md new file mode 100644 index 0000000000..231c934b5a --- /dev/null +++ b/.changeset/dirty-worms-type.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure the if block condition is wrapped in a derived diff --git a/packages/svelte/src/internal/client/dom/blocks/if.js b/packages/svelte/src/internal/client/dom/blocks/if.js index 4d8e9412d3..480ea804cd 100644 --- a/packages/svelte/src/internal/client/dom/blocks/if.js +++ b/packages/svelte/src/internal/client/dom/blocks/if.js @@ -10,6 +10,8 @@ import { } from '../hydration.js'; import { block, branch, pause_effect, resume_effect } from '../../reactivity/effects.js'; import { HYDRATION_START_ELSE } from '../../../../constants.js'; +import { get } from '../../runtime.js'; +import { derived } from '../../reactivity/deriveds.js'; /** * @param {TemplateNode} node @@ -32,15 +34,18 @@ export function if_block(node, get_condition, consequent_fn, alternate_fn = null /** @type {Effect | null} */ var alternate_effect = null; - /** @type {boolean | null} */ - var condition = null; + var derived_condition = derived(() => !!get_condition()); var flags = elseif ? EFFECT_TRANSPARENT : 0; block(() => { - if (condition === (condition = !!get_condition())) return; + // We use a derived here to ensure stability of any depedencies that are captured when we read `get_condition`. + // This is mainly because the current block effect's dependencies are only applied _after_ the effect has finished + // running, however as we're sync calling `destroy_effect` via `pause_effect` below, it might mean that our + // dependencies get lost. By having a derived already having run, those dependencies won't be affected by this + var condition = get(derived_condition); - /** Whether or not there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out */ + // Whether or not there was a hydration mismatch. Needs to be a `let` or else it isn't treeshaken out let mismatch = false; if (hydrating) { @@ -80,6 +85,7 @@ export function if_block(node, get_condition, consequent_fn, alternate_fn = null pause_effect(consequent_effect, () => { consequent_effect = null; }); + } }