fix: abort and reschedule effect processing after state change in user effect

#16280

Closing issue

Pull request

Merged
R
Rich-Harris
Jul 2, 2025, 12:54 AM

Fixes . It's a real edge case, hence the convoluted nature of the test, but it's possible for a state change in one effect to cause a subsequent already-scheduled effect to run even though the second effect would be destroyed if the effect tree was being processed from the root.

The solution, I think, is to abort the processing of effects if a state change occurs. We can schedule the remaining effects and start again from the top; this will ensure that any dirty branches (i.e. a now-falsy if containing an effect with a now-broken reference) are updated before their children. Within each flush of the effect tree, predictable order is preserved.

We need to distinguish between user effects and non-user effects, since element bindings can result in state changes, and these should not cause flushing to be aborted (they are guaranteed to run before the effects that depend on the changed state, so this is not a problem).

Before submitting the PR, please make sure you do the following

  • It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
  • Prefix your PR title with feat:, fix:, chore:, or docs:.
  • This message body should clearly illustrate what problems it solves.
  • Ideally, include a test that fails without this PR but passes with it.
  • If this PR changes code within packages/svelte/src, add a changeset (npx changeset).

Tests and linting

  • Run the tests with pnpm test and lint the project with pnpm lint

Info

Merged at Jul 7, 2025, 3:46 PM
Merged by Rich-Harris
Assignees None
Reviewers None
Labels None
Milestone None