fix: don't rebase just-created batches
#18117
Pull request
Merged
D
dummdidumm Apr 15, 2026, 10:37 AMIt'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
currentMap in batch B - batch A commits after processing batch B (
next_batchetc 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:
- 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 - we capture derived values in
previous_batchif 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 #18097
🚀 2
Info
Merged at Apr 29, 2026, 8:47 PM
Merged by Rich-Harris
Assignees None
Reviewers None
Labels None
Milestone None
C
changeset-bot[bot] Apr 15, 2026, 10:37 AM🦋 Changeset detected
Latest commit: 242ea7d
The changes in this PR will be included in the next version bump.
This PR includes changesets to release 1 package
| Name | Type |
|---|---|
| svelte | Patch |
Not sure what this means? Click here to learn what changesets are.
Click here if you're a maintainer who wants to add another changeset to this PR
S
svelte-docs-bot[bot] Apr 15, 2026, 10:38 AM G
github-actions[bot] Apr 15, 2026, 10:38 AMpnpm add https://pkg.pr.new/svelte@18117Pull request opened 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 #18097
fix case where writing to previous_batch-only results in pending derived value showing up
• Apr 20, 2026, 8:57 PMPull request merged Apr 29, 2026, 8:47 PM
Total -18 +313
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 ;)