fix: only abort effect flushing if it causes an existing effect to be scheduled

pull/16623/head
Rich Harris 1 month ago
parent 2e02868ef1
commit 66396f391e

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: only abort effect flushing if it causes an existing effect to be scheduled

@ -28,7 +28,7 @@ import * as e from '../errors.js';
import { flush_tasks } from '../dom/task.js';
import { DEV } from 'esm-env';
import { invoke_error_boundary } from '../error-handling.js';
import { old_values } from './sources.js';
import { old_values, schedule_version } from './sources.js';
import { unlink_effect } from './effects.js';
import { unset_context } from './async.js';
@ -598,7 +598,7 @@ function flush_queued_effects(effects) {
var effect = effects[i++];
if ((effect.f & (DESTROYED | INERT)) === 0 && is_dirty(effect)) {
var n = current_batch ? current_batch.current.size : 0;
var sv = schedule_version;
update_effect(effect);
@ -619,13 +619,9 @@ function flush_queued_effects(effects) {
}
}
// if state is written in a user effect, abort and re-schedule, lest we run
// effects that should be removed as a result of the state change
if (
current_batch !== null &&
current_batch.current.size > n &&
(effect.f & USER_EFFECT) !== 0
) {
// if an effect is invalidated by a user effect, abort and re-schedule, lest we
// run effects that should be removed as a result of the state change
if (schedule_version > sv && (effect.f & USER_EFFECT) !== 0) {
break;
}
}

@ -299,6 +299,11 @@ export function increment(source) {
set(source, source.v + 1);
}
/**
* We increment this value when an effect is scheduled as a result of a state change
*/
export let schedule_version = 0;
/**
* @param {Value} signal
* @param {number} status should be DIRTY or MAYBE_DIRTY
@ -334,6 +339,7 @@ function mark_reactions(signal, status) {
if ((flags & DERIVED) !== 0) {
mark_reactions(/** @type {Derived} */ (reaction), MAYBE_DIRTY);
} else if (not_dirty) {
schedule_version += 1;
schedule_effect(/** @type {Effect} */ (reaction));
}
}

Loading…
Cancel
Save