Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/kind-deers-lay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

chore: more transition code-golfing
14 changes: 11 additions & 3 deletions packages/svelte/src/internal/client/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,14 @@ export function create_root_block(intro) {
/** @returns {import('./types.js').IfBlock} */
export function create_if_block() {
return {
// current
c: false,
// alternate transitions
a: null,
// alternate effect
ae: null,
// consequent transitions
c: null,
// consequent effect
ce: null,
// dom
d: null,
// effect
Expand All @@ -46,7 +52,9 @@ export function create_if_block() {
// transition
r: null,
// type
t: IF_BLOCK
t: IF_BLOCK,
// value
v: false
};
}

Expand Down
60 changes: 13 additions & 47 deletions packages/svelte/src/internal/client/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ import {
} from './hydration.js';
import { array_from, define_property, get_descriptor, get_descriptors, is_array } from './utils.js';
import { is_promise } from '../common.js';
import { bind_transition, remove_in_transitions, trigger_transitions } from './transitions.js';
import { bind_transition, trigger_transitions } from './transitions.js';

/** @type {Set<string>} */
const all_registerd_events = new Set();
Expand Down Expand Up @@ -1355,8 +1355,6 @@ export function slot(anchor_node, slot_fn, slot_props, fallback_fn) {
function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) {
const block = create_if_block();
hydrate_block_anchor(anchor_node);
const consequent_transitions = new Set();
const alternate_transitions = new Set();
const previous_hydration_fragment = current_hydration_fragment;

/** @type {null | import('./types.js').TemplateNode | Array<import('./types.js').TemplateNode>} */
Expand All @@ -1366,59 +1364,32 @@ function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) {
let has_mounted = false;
let has_mounted_branch = false;

block.r =
/**
* @param {import('./types.js').Transition} transition
* @returns {void}
*/
(transition) => {
// block.current
if (block.c) {
consequent_transitions.add(transition);
transition.f(() => {
consequent_transitions.delete(transition);
remove_in_transitions(consequent_transitions);
if (consequent_transitions.size === 0) {
execute_effect(consequent_effect);
}
});
} else {
alternate_transitions.add(transition);
transition.f(() => {
alternate_transitions.delete(transition);
remove_in_transitions(alternate_transitions);
if (alternate_transitions.size === 0) {
execute_effect(alternate_effect);
}
});
}
};
const if_effect = render_effect(
() => {
const result = !!condition_fn();
if (block.c !== result || !has_mounted) {
block.c = result;
if (block.v !== result || !has_mounted) {
block.v = result;
if (has_mounted) {
const consequent_transitions = block.c;
const alternate_transitions = block.a;
if (result) {
remove_in_transitions(alternate_transitions);
if (alternate_transitions.size === 0) {
if (alternate_transitions === null || alternate_transitions.size === 0) {
execute_effect(alternate_effect);
} else {
trigger_transitions(alternate_transitions, 'out');
}
if (consequent_transitions.size === 0) {
if (consequent_transitions === null || consequent_transitions.size === 0) {
execute_effect(consequent_effect);
} else {
trigger_transitions(consequent_transitions, 'in');
}
} else {
remove_in_transitions(consequent_transitions);
if (consequent_transitions.size === 0) {
if (consequent_transitions === null || consequent_transitions.size === 0) {
execute_effect(consequent_effect);
} else {
trigger_transitions(consequent_transitions, 'out');
}
if (alternate_transitions.size === 0) {
if (alternate_transitions === null || alternate_transitions.size === 0) {
execute_effect(alternate_effect);
} else {
trigger_transitions(alternate_transitions, 'in');
Expand Down Expand Up @@ -1455,7 +1426,7 @@ function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) {
remove(consequent_dom);
consequent_dom = null;
}
if (block.c) {
if (block.v) {
consequent_fn(anchor_node);
if (!has_mounted_branch) {
// Restore previous fragment so that Svelte continues to operate in hydration mode
Expand All @@ -1469,14 +1440,15 @@ function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) {
block,
true
);
block.ce = consequent_effect;
// Managed effect
const alternate_effect = render_effect(
() => {
if (alternate_dom !== null) {
remove(alternate_dom);
alternate_dom = null;
}
if (!block.c) {
if (!block.v) {
if (alternate_fn !== null) {
alternate_fn(anchor_node);
}
Expand All @@ -1492,6 +1464,7 @@ function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) {
block,
true
);
block.ae = alternate_effect;
push_destroy_fn(if_effect, () => {
if (consequent_dom !== null) {
remove(consequent_dom);
Expand Down Expand Up @@ -1676,7 +1649,6 @@ export function component(anchor_node, component_fn, render_fn) {
transitions.add(transition);
transition.f(() => {
transitions.delete(transition);
remove_in_transitions(transitions);
if (transitions.size === 0) {
if (render.e !== null) {
if (render.d !== null) {
Expand Down Expand Up @@ -1724,7 +1696,6 @@ export function component(anchor_node, component_fn, render_fn) {
return;
}
const transitions = render.s;
remove_in_transitions(transitions);
if (transitions.size === 0) {
if (render.d !== null) {
remove(render.d);
Expand Down Expand Up @@ -1804,7 +1775,6 @@ function await_block(anchor_node, input, pending_fn, then_fn, catch_fn) {
transitions.add(transition);
transition.f(() => {
transitions.delete(transition);
remove_in_transitions(transitions);
if (transitions.size === 0) {
if (render.e !== null) {
if (render.d !== null) {
Expand Down Expand Up @@ -1861,7 +1831,6 @@ function await_block(anchor_node, input, pending_fn, then_fn, catch_fn) {
return;
}
const transitions = render.s;
remove_in_transitions(transitions);
if (transitions.size === 0) {
if (render.d !== null) {
remove(render.d);
Expand Down Expand Up @@ -1966,7 +1935,6 @@ export function key(anchor_node, key, render_fn) {
transitions.add(transition);
transition.f(() => {
transitions.delete(transition);
remove_in_transitions(transitions);
if (transitions.size === 0) {
if (render.e !== null) {
if (render.d !== null) {
Expand Down Expand Up @@ -2007,7 +1975,6 @@ export function key(anchor_node, key, render_fn) {
return;
}
const transitions = render.s;
remove_in_transitions(transitions);
if (transitions.size === 0) {
if (render.d !== null) {
remove(render.d);
Expand Down Expand Up @@ -2195,7 +2162,6 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re
transitions.add(transition);
transition.f(() => {
transitions.delete(transition);
remove_in_transitions(transitions);
if (transitions.size === 0) {
if (fallback.e !== null) {
if (fallback.d !== null) {
Expand Down
74 changes: 52 additions & 22 deletions packages/svelte/src/internal/client/transitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
current_effect,
destroy_signal,
effect,
execute_effect,
managed_effect,
managed_pre_effect,
mark_subtree_inert,
Expand Down Expand Up @@ -418,7 +419,8 @@ export function bind_transition(dom, transition_fn, props_fn, direction, global)
const block = current_block;
const props = props_fn === null ? {} : props_fn();

let skip_intro = true;
let can_show_intro_on_mount = true;
let can_apply_lazy_transitions = false;

/** @type {import('./types.js').Block | null} */
let transition_block = block;
Expand All @@ -429,19 +431,22 @@ export function bind_transition(dom, transition_fn, props_fn, direction, global)
transition_block.r = each_item_transition;
transition_block = transition_block.p;
} else if (transition_block.t === AWAIT_BLOCK && transition_block.n /* pending */) {
skip_intro = false;
can_show_intro_on_mount = false;
} else if (transition_block.t === IF_BLOCK) {
transition_block.r = if_block_transition;
}
if (skip_intro) {
skip_intro = transition_block.e === null;
if (!can_apply_lazy_transitions && can_show_intro_on_mount) {
can_show_intro_on_mount = transition_block.e === null;
}
if (!skip_intro || !global) {
break;
if (!can_show_intro_on_mount || !global) {
can_apply_lazy_transitions = true;
}
} else if (
!can_apply_lazy_transitions &&
transition_block.t === ROOT_BLOCK &&
(transition_block.e !== null || transition_block.i)
) {
skip_intro = false;
can_show_intro_on_mount = false;
}
transition_block = transition_block.p;
}
Expand All @@ -467,7 +472,7 @@ export function bind_transition(dom, transition_fn, props_fn, direction, global)

transition = create_transition(dom, init, direction, transition_effect);
const is_intro = direction === 'in';
const show_intro = !skip_intro && (is_intro || direction === 'both');
const show_intro = !can_show_intro_on_mount && (is_intro || direction === 'both');

if (show_intro) {
transition.p = transition.i();
Expand All @@ -483,15 +488,15 @@ export function bind_transition(dom, transition_fn, props_fn, direction, global)

/** @type {import('./types.js').Block | null} */
let transition_block = block;
while (transition_block !== null) {
while (!is_intro && transition_block !== null) {
const parent = transition_block.p;
if (is_transition_block(transition_block)) {
if (transition_block.r !== null) {
transition_block.r(transition);
}
if (
parent === null ||
(!global && (transition_block.t !== IF_BLOCK || parent.t !== IF_BLOCK || parent.c))
(!global && (transition_block.t !== IF_BLOCK || parent.t !== IF_BLOCK || parent.v))
) {
break;
}
Expand All @@ -510,18 +515,6 @@ export function bind_transition(dom, transition_fn, props_fn, direction, global)
}
}

/**
* @param {Set<import('./types.js').Transition>} transitions
*/
export function remove_in_transitions(transitions) {
for (let transition of transitions) {
const direction = transition.r;
if (direction === 'in') {
transitions.delete(transition);
}
}
}

/**
* @param {Set<import('./types.js').Transition>} transitions
* @param {'in' | 'out' | 'key'} target_direction
Expand Down Expand Up @@ -567,6 +560,43 @@ export function trigger_transitions(transitions, target_direction, from) {
}
}

/**
* @this {import('./types.js').IfBlock}
* @param {import('./types.js').Transition} transition
* @returns {void}
*/
function if_block_transition(transition) {
const block = this;
// block.value === true
if (block.v) {
let consequent_transitions = block.c;
if (consequent_transitions === null) {
consequent_transitions = block.c = new Set();
}
consequent_transitions.add(transition);
transition.f(() => {
const c = /** @type {Set<import('./types.js').Transition>} */ (consequent_transitions);
c.delete(transition);
if (c.size === 0) {
execute_effect(/** @type {import('./types.js').EffectSignal} */ (block.ce));
}
});
} else {
let alternate_transitions = block.a;
if (alternate_transitions === null) {
alternate_transitions = block.a = new Set();
}
alternate_transitions.add(transition);
transition.f(() => {
const a = /** @type {Set<import('./types.js').Transition>} */ (alternate_transitions);
a.delete(transition);
if (a.size === 0) {
execute_effect(/** @type {import('./types.js').EffectSignal} */ (block.ae));
}
});
}
}

/**
* @this {import('./types.js').EachItemBlock}
* @param {import('./types.js').Transition} transition
Expand Down
16 changes: 12 additions & 4 deletions packages/svelte/src/internal/client/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,24 @@ export type RootBlock = {
};

export type IfBlock = {
/** current */
c: boolean;
/** value */
v: boolean;
/** dom */
d: null | TemplateNode | Array<TemplateNode>;
/** effect */
e: null | ComputationSignal;
e: null | EffectSignal;
/** parent */
p: Block;
/** transition */
r: null | ((transition: Transition) => void);
/** consequent transitions */
c: null | Set<Transition>;
/** alternate transitions */
a: null | Set<Transition>;
/** effect */
ce: null | EffectSignal;
/** effect */
ae: null | EffectSignal;
/** type */
t: typeof IF_BLOCK;
};
Expand All @@ -183,7 +191,7 @@ export type KeyBlock = {
/** dom */
d: null | TemplateNode | Array<TemplateNode>;
/** effect */
e: null | ComputationSignal;
e: null | EffectSignal;
/** parent */
p: Block;
/** transition */
Expand Down