Skip to content

Commit 99e3cc7

Browse files
committed
chore: improve code size of transitions
1 parent 6f3dc04 commit 99e3cc7

File tree

2 files changed

+118
-125
lines changed

2 files changed

+118
-125
lines changed

packages/svelte/src/internal/client/render.js

Lines changed: 10 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,10 @@ import {
5252
flushSync,
5353
expose,
5454
safe_not_equal,
55-
managed_pre_effect,
5655
current_block,
5756
set_signal_value,
5857
source,
5958
managed_effect,
60-
mark_subtree_inert,
6159
safe_equal,
6260
push,
6361
current_component_context,
@@ -72,7 +70,7 @@ import {
7270
} from './hydration.js';
7371
import { array_from, define_property, get_descriptor, get_descriptors, is_array } from './utils.js';
7472
import { is_promise } from '../common.js';
75-
import { bind_transition } from './transitions.js';
73+
import { bind_transition, remove_in_transitions, trigger_transitions } from './transitions.js';
7674

7775
/** @type {Set<string>} */
7876
const all_registerd_events = new Set();
@@ -81,7 +79,7 @@ const all_registerd_events = new Set();
8179
const root_event_handles = new Set();
8280

8381
/** @returns {Text} */
84-
function empty() {
82+
export function empty() {
8583
return document.createTextNode('');
8684
}
8785

@@ -1369,11 +1367,7 @@ function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) {
13691367
consequent_transitions.add(transition);
13701368
transition.finished(() => {
13711369
consequent_transitions.delete(transition);
1372-
for (let other of consequent_transitions) {
1373-
if (other.direction === 'in') {
1374-
consequent_transitions.delete(other);
1375-
}
1376-
}
1370+
remove_in_transitions(consequent_transitions);
13771371
if (consequent_transitions.size === 0) {
13781372
execute_effect(consequent_effect);
13791373
}
@@ -1382,11 +1376,7 @@ function if_block(anchor_node, condition_fn, consequent_fn, alternate_fn) {
13821376
alternate_transitions.add(transition);
13831377
transition.finished(() => {
13841378
alternate_transitions.delete(transition);
1385-
for (let other of alternate_transitions) {
1386-
if (other.direction === 'in') {
1387-
alternate_transitions.delete(other);
1388-
}
1389-
}
1379+
remove_in_transitions(alternate_transitions);
13901380
if (alternate_transitions.size === 0) {
13911381
execute_effect(alternate_effect);
13921382
}
@@ -1674,11 +1664,7 @@ export function component(anchor_node, component_fn, render_fn) {
16741664
transitions.add(transition);
16751665
transition.finished(() => {
16761666
transitions.delete(transition);
1677-
for (let other of transitions) {
1678-
if (other.direction === 'in') {
1679-
transitions.delete(other);
1680-
}
1681-
}
1667+
remove_in_transitions(transitions);
16821668
if (transitions.size === 0) {
16831669
if (render.effect !== null) {
16841670
if (render.dom !== null) {
@@ -1805,11 +1791,7 @@ function await_block(anchor_node, input, pending_fn, then_fn, catch_fn) {
18051791
transitions.add(transition);
18061792
transition.finished(() => {
18071793
transitions.delete(transition);
1808-
for (let other of transitions) {
1809-
if (other.direction === 'in') {
1810-
transitions.delete(other);
1811-
}
1812-
}
1794+
remove_in_transitions(transitions);
18131795
if (transitions.size === 0) {
18141796
if (render.effect !== null) {
18151797
if (render.dom !== null) {
@@ -1863,6 +1845,7 @@ function await_block(anchor_node, input, pending_fn, then_fn, catch_fn) {
18631845
return;
18641846
}
18651847
const transitions = render.transitions;
1848+
remove_in_transitions(transitions);
18661849
if (transitions.size === 0) {
18671850
if (render.dom !== null) {
18681851
remove(render.dom);
@@ -1967,11 +1950,7 @@ export function key(anchor_node, key, render_fn) {
19671950
transitions.add(transition);
19681951
transition.finished(() => {
19691952
transitions.delete(transition);
1970-
for (let other of transitions) {
1971-
if (other.direction === 'in') {
1972-
transitions.delete(other);
1973-
}
1974-
}
1953+
remove_in_transitions(transitions);
19751954
if (transitions.size === 0) {
19761955
if (render.effect !== null) {
19771956
if (render.dom !== null) {
@@ -2012,6 +1991,7 @@ export function key(anchor_node, key, render_fn) {
20121991
return;
20131992
}
20141993
const transitions = render.transitions;
1994+
remove_in_transitions(transitions);
20151995
if (transitions.size === 0) {
20161996
if (render.dom !== null) {
20171997
remove(render.dom);
@@ -2139,96 +2119,6 @@ export function destroy_each_item_block(
21392119
}
21402120
}
21412121

2142-
/**
2143-
* @this {import('./types.js').EachItemBlock}
2144-
* @param {import('./types.js').Transition} transition
2145-
* @returns {void}
2146-
*/
2147-
function each_item_transition(transition) {
2148-
const block = this;
2149-
const each_block = block.parent;
2150-
const is_controlled = (each_block.flags & EACH_IS_CONTROLLED) !== 0;
2151-
// Disable optimization
2152-
if (is_controlled) {
2153-
const anchor = empty();
2154-
each_block.flags ^= EACH_IS_CONTROLLED;
2155-
append_child(/** @type {Element} */ (each_block.anchor), anchor);
2156-
each_block.anchor = anchor;
2157-
}
2158-
if (transition.direction === 'key' && (each_block.flags & EACH_IS_ANIMATED) === 0) {
2159-
each_block.flags |= EACH_IS_ANIMATED;
2160-
}
2161-
let transitions = block.transitions;
2162-
if (transitions === null) {
2163-
block.transitions = transitions = new Set();
2164-
}
2165-
transition.finished(() => {
2166-
if (transitions !== null) {
2167-
transitions.delete(transition);
2168-
if (transition.direction !== 'key') {
2169-
for (let other of transitions) {
2170-
if (other.direction === 'key' || other.direction === 'in') {
2171-
transitions.delete(other);
2172-
}
2173-
}
2174-
if (transitions.size === 0) {
2175-
block.transitions = null;
2176-
destroy_each_item_block(block, null, true);
2177-
}
2178-
}
2179-
}
2180-
});
2181-
transitions.add(transition);
2182-
}
2183-
2184-
/**
2185-
* @param {Set<import('./types.js').Transition>} transitions
2186-
* @param {'in' | 'out' | 'key'} target_direction
2187-
* @param {DOMRect} [from]
2188-
* @returns {void}
2189-
*/
2190-
export function trigger_transitions(transitions, target_direction, from) {
2191-
/** @type {Array<() => void>} */
2192-
const outros = [];
2193-
for (const transition of transitions) {
2194-
const direction = transition.direction;
2195-
if (target_direction === 'in') {
2196-
if (direction === 'in' || direction === 'both') {
2197-
if (direction === 'in') {
2198-
transition.cancel();
2199-
}
2200-
transition.in();
2201-
} else {
2202-
transition.cancel();
2203-
}
2204-
transition.dom.inert = false;
2205-
mark_subtree_inert(transition.effect, false);
2206-
} else if (target_direction === 'key') {
2207-
if (direction === 'key') {
2208-
transition.payload = transition.init(/** @type {DOMRect} */ (from));
2209-
transition.in();
2210-
}
2211-
} else {
2212-
if (direction === 'out' || direction === 'both') {
2213-
transition.payload = transition.init();
2214-
outros.push(transition.out);
2215-
}
2216-
transition.dom.inert = true;
2217-
mark_subtree_inert(transition.effect, true);
2218-
}
2219-
}
2220-
if (outros.length > 0) {
2221-
// Defer the outros to a microtask
2222-
const e = managed_pre_effect(() => {
2223-
destroy_signal(e);
2224-
const e2 = managed_effect(() => {
2225-
destroy_signal(e2);
2226-
outros.forEach(/** @param {any} o */ (o) => o());
2227-
});
2228-
}, false);
2229-
}
2230-
}
2231-
22322122
/**
22332123
* @template V
22342124
* @param {V} item
@@ -2242,7 +2132,6 @@ export function each_item_block(item, key, index, render_fn, flags) {
22422132
const item_value = (flags & EACH_ITEM_REACTIVE) === 0 ? item : source(item);
22432133
const index_value = (flags & EACH_INDEX_REACTIVE) === 0 ? index : source(index);
22442134
const block = create_each_item_block(item_value, index_value, key);
2245-
block.transition = each_item_transition;
22462135
const effect = render_effect(
22472136
/** @param {import('./types.js').EachItemBlock} block */
22482137
(block) => {
@@ -2290,11 +2179,7 @@ function each(anchor_node, collection, flags, key_fn, render_fn, fallback_fn, re
22902179
transitions.add(transition);
22912180
transition.finished(() => {
22922181
transitions.delete(transition);
2293-
for (let other of transitions) {
2294-
if (other.direction === 'in') {
2295-
transitions.delete(other);
2296-
}
2297-
}
2182+
remove_in_transitions(transitions);
22982183
if (transitions.size === 0) {
22992184
if (fallback.effect !== null) {
23002185
if (fallback.dom !== null) {

packages/svelte/src/internal/client/transitions.js

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { EACH_IS_ANIMATED, EACH_IS_CONTROLLED } from '../../constants.js';
12
import {
23
AWAIT_BLOCK,
34
DYNAMIC_COMPONENT_BLOCK,
@@ -7,12 +8,16 @@ import {
78
KEY_BLOCK,
89
ROOT_BLOCK
910
} from './block.js';
11+
import { append_child } from './operations.js';
12+
import { destroy_each_item_block, empty } from './render.js';
1013
import {
1114
current_block,
1215
current_effect,
1316
destroy_signal,
1417
effect,
18+
managed_effect,
1519
managed_pre_effect,
20+
mark_subtree_inert,
1621
untrack
1722
} from './runtime.js';
1823
import { raf } from './timing.js';
@@ -414,6 +419,8 @@ export function bind_transition(dom, transition_fn, props_fn, direction, global)
414419
while (transition_block !== null) {
415420
if (is_transition_block(transition_block)) {
416421
if (transition_block.type === EACH_ITEM_BLOCK) {
422+
// Lazily apply the each block transition
423+
transition_block.transition = each_item_transition;
417424
transition_block = transition_block.parent;
418425
} else if (transition_block.type === AWAIT_BLOCK && transition_block.pending) {
419426
skip_intro = false;
@@ -496,3 +503,104 @@ export function bind_transition(dom, transition_fn, props_fn, direction, global)
496503
});
497504
}
498505
}
506+
507+
/**
508+
* @param {Set<import('./types.js').Transition>} transitions
509+
*/
510+
export function remove_in_transitions(transitions) {
511+
for (let other of transitions) {
512+
if (other.direction === 'in') {
513+
transitions.delete(other);
514+
}
515+
}
516+
}
517+
518+
/**
519+
* @param {Set<import('./types.js').Transition>} transitions
520+
* @param {'in' | 'out' | 'key'} target_direction
521+
* @param {DOMRect} [from]
522+
* @returns {void}
523+
*/
524+
export function trigger_transitions(transitions, target_direction, from) {
525+
/** @type {Array<() => void>} */
526+
const outros = [];
527+
for (const transition of transitions) {
528+
const direction = transition.direction;
529+
if (target_direction === 'in') {
530+
if (direction === 'in' || direction === 'both') {
531+
if (direction === 'in') {
532+
transition.cancel();
533+
}
534+
transition.in();
535+
} else {
536+
transition.cancel();
537+
}
538+
transition.dom.inert = false;
539+
mark_subtree_inert(transition.effect, false);
540+
} else if (target_direction === 'key') {
541+
if (direction === 'key') {
542+
transition.payload = transition.init(/** @type {DOMRect} */ (from));
543+
transition.in();
544+
}
545+
} else {
546+
if (direction === 'out' || direction === 'both') {
547+
transition.payload = transition.init();
548+
outros.push(transition.out);
549+
}
550+
transition.dom.inert = true;
551+
mark_subtree_inert(transition.effect, true);
552+
}
553+
}
554+
if (outros.length > 0) {
555+
// Defer the outros to a microtask
556+
const e = managed_pre_effect(() => {
557+
destroy_signal(e);
558+
const e2 = managed_effect(() => {
559+
destroy_signal(e2);
560+
outros.forEach(/** @param {any} o */ (o) => o());
561+
});
562+
}, false);
563+
}
564+
}
565+
566+
/**
567+
* @this {import('./types.js').EachItemBlock}
568+
* @param {import('./types.js').Transition} transition
569+
* @returns {void}
570+
*/
571+
function each_item_transition(transition) {
572+
const block = this;
573+
const each_block = block.parent;
574+
const is_controlled = (each_block.flags & EACH_IS_CONTROLLED) !== 0;
575+
// Disable optimization
576+
if (is_controlled) {
577+
const anchor = empty();
578+
each_block.flags ^= EACH_IS_CONTROLLED;
579+
append_child(/** @type {Element} */ (each_block.anchor), anchor);
580+
each_block.anchor = anchor;
581+
}
582+
if (transition.direction === 'key' && (each_block.flags & EACH_IS_ANIMATED) === 0) {
583+
each_block.flags |= EACH_IS_ANIMATED;
584+
}
585+
let transitions = block.transitions;
586+
if (transitions === null) {
587+
block.transitions = transitions = new Set();
588+
}
589+
transition.finished(() => {
590+
if (transitions !== null) {
591+
transitions.delete(transition);
592+
if (transition.direction !== 'key') {
593+
for (let other of transitions) {
594+
if (other.direction === 'key' || other.direction === 'in') {
595+
transitions.delete(other);
596+
}
597+
}
598+
if (transitions.size === 0) {
599+
block.transitions = null;
600+
destroy_each_item_block(block, null, true);
601+
}
602+
}
603+
}
604+
});
605+
transitions.add(transition);
606+
}

0 commit comments

Comments
 (0)