Svelte

fix: don't rebase just-created batches

#18117

Pull request

Merged
D
dummdidumm
Apr 15, 2026, 10:37 AM

It's possible to rebase just-created batches.

Case A:

  • batch A runs effects
  • one of these effects writes to a source. This creates a new batch B
  • an effect after that (still part of "flush effects of batch A") executes a derived. This creates an entry in the current Map in batch B
  • batch A commits after processing batch B (next_batch etc logic), batch B is pending. Due to derived being part of batchB.current batch A can wrongfully think these are connected and try to rerun/add effects etc on batch B

Case B:

  • like case A but with an additional await inside a pending snippet

Case C:

  • batch A with source a and b, it flushes effects
  • one of these effects schedules batch B with b and c scheduling an async effect
  • batch B is deferred
  • batch A commits. Due to the a/b/c partial overlap it will needlessly rerun the just scheduled async effect

All these cases are wrong. We fix it like this:

  1. we call this.#commit() before running the new batches, which may stick around due to having pending work, and we don't want to rebase these. This fixes case A and C
  2. we capture derived values in previous_batch if it exists, because it means we're currently flushing effects, and derived writes belong to that batch and not a new one that might have been scheduled already. This fixes case B

Discovered this while working on

🚀 2

Info

Merged at Apr 29, 2026, 8:47 PM
Merged by Rich-Harris
Assignees None
Reviewers None
Labels None
Milestone None

Pro tip: You can prefix GitHub URLs of issues, PRs or discussions with svcl.dev/ to view them on this page! Also try it on a GitHub release ;)