Skip to content

Conversation

@dummdidumm
Copy link
Member

@dummdidumm dummdidumm commented Feb 2, 2026

fixes #17595

When an if/key/etc block has an expression that depends on an async blocker (e.g., is inside a component with top level await), the compiler incorrectly treats the expression as async - even when the expression itself contains no await.

This causes the expression to be added to $.async's expressions array, which wraps it in an async_derived. This is not only unnecessary but also buggy: it breaks the direct reactive connection between the source and its dependent effects, causing inconsistent effect executions.

The fix is to only add expressions to $.async's expressions array when they actually contain an await.

...however, you'll notice that for now this will fail one test. This is due to an unrelated bug which is fixed by #17605 (separate PR merging into this one for easier review).

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

fixes #17595

When an if/key/etc block has an expression that depends on an async blocker (e.g., is inside a component with top level `await`), the compiler incorrectly treats the expression as async - even when the expression itself contains no `await`.

This causes the expression to be added to `$.async`'s `expressions` array, which wraps it in an `async_derived`. This is not only unnecessary but also buggy: it breaks the direct reactive connection between the source and its dependent effects, causing inconsistent effect executions.

The fix is to only add expressions to `$.async`'s `expressions` array when they actually contain an `await`.
@changeset-bot
Copy link

changeset-bot bot commented Feb 2, 2026

🦋 Changeset detected

Latest commit: 5d140a5

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

@github-actions
Copy link
Contributor

github-actions bot commented Feb 2, 2026

Playground

pnpm add https://pkg.pr.new/svelte@17604

* fix: reschedule effects inside unskipped branches

When a branch is speculatively marked for destruction (condition temporarily falsy), its child effects are reset to `CLEAN` to prevent them running in a doomed branch (as of #17581). However, if the branch survives (condition becomes truthy again), those effects remain `CLEAN` and never run - the source was already marked dirty before the reset, so no new dirty marking occurs.

The fix is to change `skipped_effects` from a `Set` to a `Map` that tracks which child effects were dirty/maybe_dirty before being reset. When a branch is unskipped (survives), restore their status and reschedule them.

* update comment

* lint

* make skipped_effects private

* actually while we're at it let's use a more descriptive name

* prettier

---------

Co-authored-by: Rich Harris <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Async derived in child re-evaluates with undefined props on unmount when parent has async derived

3 participants