Skip to content

Commit 9c680f1

Browse files
authored
chore: optimise effects (#11569)
* optimise effects * tweak * don't allocate array unnecessarily * filter_flags appears to be unnecessary? * lint * tweak * simplify (#11570) * changeset
1 parent 5497b3d commit 9c680f1

File tree

3 files changed

+37
-77
lines changed

3 files changed

+37
-77
lines changed

.changeset/blue-waves-sneeze.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
chore: optimise effects

packages/svelte/src/internal/client/dom/legacy/lifecycle.js

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
1-
import { CLEAN } from '../../constants.js';
21
import { run, run_all } from '../../../shared/utils.js';
32
import { user_pre_effect, user_effect } from '../../reactivity/effects.js';
4-
import {
5-
current_component_context,
6-
current_effect,
7-
deep_read_state,
8-
flush_local_render_effects,
9-
get,
10-
untrack
11-
} from '../../runtime.js';
3+
import { current_component_context, deep_read_state, get, untrack } from '../../runtime.js';
124

135
/**
146
* Legacy-mode only: Call `onMount` callbacks and set up `beforeUpdate`/`afterUpdate` effects
@@ -26,13 +18,6 @@ export function init() {
2618
user_pre_effect(() => {
2719
observe_all(context);
2820
run_all(callbacks.b);
29-
// beforeUpdate might change state that affects rendering, ensure the render effects following from it
30-
// are batched up with the current run. Avoids for example child components rerunning when they're
31-
// now hidden because beforeUpdate did set an if block to false.
32-
const parent = current_effect?.parent;
33-
if (parent != null && (parent.f & CLEAN) === 0) {
34-
flush_local_render_effects(parent);
35-
}
3621
});
3722
}
3823

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

Lines changed: 31 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -521,9 +521,27 @@ function infinite_loop_guard() {
521521
*/
522522
function flush_queued_root_effects(root_effects) {
523523
infinite_loop_guard();
524-
for (var i = 0; i < root_effects.length; i++) {
525-
var signal = root_effects[i];
526-
flush_nested_effects(signal, RENDER_EFFECT | EFFECT);
524+
525+
var previously_flushing_effect = is_flushing_effect;
526+
is_flushing_effect = true;
527+
528+
try {
529+
for (var i = 0; i < root_effects.length; i++) {
530+
var effect = root_effects[i];
531+
532+
// When working with custom elements, the root effects might not have a root
533+
if (effect.first === null && (effect.f & BRANCH_EFFECT) === 0) {
534+
flush_queued_effects([effect]);
535+
} else {
536+
/** @type {import('#client').Effect[]} */
537+
var collected_effects = [];
538+
539+
process_effects(effect, collected_effects);
540+
flush_queued_effects(collected_effects);
541+
}
542+
}
543+
} finally {
544+
is_flushing_effect = previously_flushing_effect;
527545
}
528546
}
529547

@@ -592,12 +610,10 @@ export function schedule_effect(signal) {
592610
* effects to be flushed.
593611
*
594612
* @param {import('#client').Effect} effect
595-
* @param {number} filter_flags
596-
* @param {boolean} shallow
597613
* @param {import('#client').Effect[]} collected_effects
598614
* @returns {void}
599615
*/
600-
function process_effects(effect, filter_flags, shallow, collected_effects) {
616+
function process_effects(effect, collected_effects) {
601617
var current_effect = effect.first;
602618
var effects = [];
603619

@@ -621,13 +637,14 @@ function process_effects(effect, filter_flags, shallow, collected_effects) {
621637
// Child might have been mutated since running the effect
622638
child = current_effect.first;
623639
}
624-
if (!shallow && child !== null) {
640+
641+
if (child !== null) {
625642
current_effect = child;
626643
continue;
627644
}
628645
} else if ((flags & EFFECT) !== 0) {
629646
if (is_branch || is_clean) {
630-
if (!shallow && child !== null) {
647+
if (child !== null) {
631648
current_effect = child;
632649
continue;
633650
}
@@ -657,62 +674,15 @@ function process_effects(effect, filter_flags, shallow, collected_effects) {
657674
current_effect = sibling;
658675
}
659676

660-
if (effects.length > 0) {
661-
// We might be dealing with many effects here, far more than can be spread into
662-
// an array push call (callstack overflow). So let's deal with each effect in a loop.
663-
for (var i = 0; i < effects.length; i++) {
664-
if ((filter_flags & EFFECT) !== 0) {
665-
collected_effects.push(effects[i]);
666-
}
667-
if (!shallow) {
668-
process_effects(effects[i], filter_flags, false, collected_effects);
669-
}
670-
}
677+
// We might be dealing with many effects here, far more than can be spread into
678+
// an array push call (callstack overflow). So let's deal with each effect in a loop.
679+
for (var i = 0; i < effects.length; i++) {
680+
child = effects[i];
681+
collected_effects.push(child);
682+
process_effects(child, collected_effects);
671683
}
672684
}
673685

674-
/**
675-
*
676-
* This function recursively collects effects in topological order from the starting effect passed in.
677-
* Effects will be collected when they match the filtered bitwise flag passed in only. The collected
678-
* array will be populated with all the effects.
679-
*
680-
* @param {import('#client').Effect} effect
681-
* @param {number} filter_flags
682-
* @param {boolean} [shallow]
683-
* @returns {void}
684-
*/
685-
function flush_nested_effects(effect, filter_flags, shallow = false) {
686-
/** @type {import('#client').Effect[]} */
687-
var collected_effects = [];
688-
689-
var previously_flushing_effect = is_flushing_effect;
690-
is_flushing_effect = true;
691-
692-
try {
693-
// When working with custom elements, the root effects might not have a root
694-
if (effect.first === null && (effect.f & BRANCH_EFFECT) === 0) {
695-
flush_queued_effects([effect]);
696-
} else {
697-
process_effects(effect, filter_flags, shallow, collected_effects);
698-
flush_queued_effects(collected_effects);
699-
}
700-
} finally {
701-
is_flushing_effect = previously_flushing_effect;
702-
}
703-
}
704-
705-
/**
706-
* @param {import('#client').Effect} effect
707-
* @returns {void}
708-
*/
709-
export function flush_local_render_effects(effect) {
710-
infinite_loop_guard();
711-
// We are entering a new flush sequence, so ensure counter is reset.
712-
flush_count = 0;
713-
flush_nested_effects(effect, RENDER_EFFECT, true);
714-
}
715-
716686
/**
717687
* Internal version of `flushSync` with the option to not flush previous effects.
718688
* Returns the result of the passed function, if given.

0 commit comments

Comments
 (0)