diff --git a/packages/svelte/src/internal/client/dom/blocks/if.js b/packages/svelte/src/internal/client/dom/blocks/if.js index 771b225da0..d4414b0761 100644 --- a/packages/svelte/src/internal/client/dom/blocks/if.js +++ b/packages/svelte/src/internal/client/dom/blocks/if.js @@ -6,8 +6,7 @@ import { } from '../../hydration.js'; import { remove } from '../../reconciler.js'; import { pause_effect, render_effect, resume_effect } from '../../reactivity/computations.js'; -import { current_effect } from '../../runtime.js'; -import { BRANCH_EFFECT, RENDER_EFFECT } from '../../constants.js'; +import { BRANCH_EFFECT } from '../../constants.js'; /** * @param {Comment} anchor_node diff --git a/packages/svelte/src/internal/client/reactivity/computations.js b/packages/svelte/src/internal/client/reactivity/computations.js index 6d0fc00f53..01171fd214 100644 --- a/packages/svelte/src/internal/client/reactivity/computations.js +++ b/packages/svelte/src/internal/client/reactivity/computations.js @@ -45,7 +45,8 @@ function create_computation_signal(flags, value, block) { v: value, w: 0, x: null, - y: null + y: null, + parent: current_effect }; if (DEV) { @@ -264,16 +265,10 @@ export function derived_safe_equal(fn) { * @param {() => void} done */ export function pause_effect(effect, done) { - if ((effect.f & INERT) !== 0) return; - - if ((effect.f & DERIVED) === 0 && typeof effect.v === 'function') { - effect.v(); - } - /** @type {import('../types.js').TransitionObject[]} */ const transitions = []; - pause_children(effect, transitions); + pause_children(effect, transitions, true); let remaining = transitions.length; @@ -297,17 +292,27 @@ export function pause_effect(effect, done) { /** * @param {import('../types.js').BlockEffect} effect * @param {import('../types.js').TransitionObject[]} transitions + * @param {boolean} local */ -function pause_children(effect, transitions) { +function pause_children(effect, transitions, local) { + if ((effect.f & INERT) !== 0) return; effect.f |= INERT; + if ((effect.f & DERIVED) === 0 && typeof effect.v === 'function') { + effect.v(); + } + if (effect.out) { - transitions.push(...effect.out); // TODO differentiate between global and local + for (const transition of effect.out) { + if (transition.global || local) { + transitions.push(transition); + } + } } if (effect.r) { for (const child of effect.r) { - pause_children(child, transitions); + pause_children(child, transitions, false); } } } @@ -339,13 +344,21 @@ export function destroy_effect(effect) { * @param {import('../types.js').BlockEffect} effect */ export function resume_effect(effect) { + resume_children(effect, true); +} + +/** + * @param {import('../types.js').BlockEffect} effect + * @param {boolean} local + */ +function resume_children(effect, local) { if ((effect.f & DERIVED) === 0 && (effect.f & MANAGED) === 0) { execute_effect(/** @type {import('../types.js').EffectSignal} */ (effect)); } if (effect.r) { for (const child of effect.r) { - resume_effect(child); + resume_children(child, false); } } @@ -353,7 +366,9 @@ export function resume_effect(effect) { if (effect.in) { for (const transition of effect.in) { - transition.to(1); + if (transition.global || local) { + transition.to(1); + } } } } diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index c8bbdb1088..152b5840e3 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -579,6 +579,9 @@ export function schedule_effect(signal, sync) { } } } + + // temporary, we need to neaten up the types + signal.ran = true; } /** diff --git a/packages/svelte/src/internal/client/transitions.js b/packages/svelte/src/internal/client/transitions.js index 182e8bc843..5235e75272 100644 --- a/packages/svelte/src/internal/client/transitions.js +++ b/packages/svelte/src/internal/client/transitions.js @@ -358,7 +358,12 @@ export function bind_transition(element, get_fn, get_params, direction, global) if (direction === 'in' || direction === 'both') { (effect.in ??= []).push(transition); - if (run_transitions) { + // if this is a local transition, we only want to run it if the parent (block) effect's + // parent (branch) effect is where the state change happened. we can determine that by + // looking at whether the branch effect is currently initializing + const should_run = run_transitions && (global || effect.parent.ran); + + if (should_run) { user_effect(() => { untrack(() => transition.to(1)); }); diff --git a/packages/svelte/src/internal/client/types.d.ts b/packages/svelte/src/internal/client/types.d.ts index 8a99241847..3e886475e3 100644 --- a/packages/svelte/src/internal/client/types.d.ts +++ b/packages/svelte/src/internal/client/types.d.ts @@ -116,12 +116,14 @@ export type ComputationSignal = { l: number; /** write version: used for unowned signals to track if their depdendencies are dirty or not **/ w: number; + parent: Signal | null; }; export type BlockEffect = ComputationSignal & { in?: TransitionObject[]; out?: TransitionObject[]; dom?: TemplateNode | Array; + ran?: boolean; }; export type Signal = SourceSignal | ComputationSignal;