perf: avoid re-traversing the effect tree after `$:` assignments

avoid-legacy-pre-effect-reschedule
Rich Harris 2 days ago
parent 25a1c5368b
commit 2a78280e9e

@ -0,0 +1,5 @@
---
'svelte': patch
---
perf: avoid re-traversing the effect tree after `$:` assignments

@ -23,6 +23,7 @@ import { async_mode_flag } from '../../flags/index.js';
import { deferred, define_property, includes } from '../../shared/utils.js';
import {
active_effect,
active_reaction,
get,
increment_write_version,
is_dirty,
@ -860,7 +861,7 @@ export function schedule_effect(signal) {
// in sync mode, render effects run during traversal. in an extreme edge case
// they can be made dirty after they have already been visited, in which
// case we shouldn't bail out
if (async_mode_flag || (signal.f & RENDER_EFFECT) === 0) {
if (async_mode_flag || active_reaction === null || (active_reaction.f & DERIVED) === 0) {
return;
}
}

@ -10,7 +10,8 @@ import {
set_active_reaction,
set_is_destroying_effect,
untrack,
untracking
untracking,
set_active_effect
} from '../runtime.js';
import {
DIRTY,
@ -316,7 +317,19 @@ export function legacy_pre_effect(deps, fn) {
if (token.ran) return;
token.ran = true;
untrack(fn);
var effect = /** @type {Effect} */ (active_effect);
// here, we lie: by setting `active_effect` to be the parent branch, any writes
// that happen inside `fn` will _not_ cause an unnecessary reschedule, because
// the affected effects will be children of `active_effect`. this is safe
// because these effects are known to run in the correct order
try {
set_active_effect(effect.parent);
untrack(fn);
} finally {
set_active_effect(effect);
}
});
}

Loading…
Cancel
Save