This was actually several bugs:
- We used `scopes` for the blockers, that's actually the template
scopes, should be `instance.scopes` instead
- We missed setting the scope for `touch`
- We didn't take return statements into account when calculating
blockers. We cannot know when/if something within the return statement
is called, so we gotta assume it is and touch everything transitively
from it
Combined this fixes#17667 (and possibly other cases not showing up in
the issue tracker yet)
Initially I just thought "ok I guess we have to traverse into functions,
too" but then I thought that feels too unoptimized and came up with the
return-statement-inspection, at which point I discovered the other bugs.
### Before submitting the PR, please make sure you do the following
- [x] 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
- [x] Prefix your PR title with `feat:`, `fix:`, `chore:`, or `docs:`.
- [x] This message body should clearly illustrate what problems it
solves.
- [x] Ideally, include a test that fails without this PR but passes with
it.
- [x] If this PR changes code within `packages/svelte/src`, add a
changeset (`npx changeset`).
### Tests and linting
- [x] Run the tests with `pnpm test` and lint the project with `pnpm
lint`
* chore: update ESLint to v10
Update eslint and related plugins/configs. Bump CI lint job to Node 24
(ESLint 10 requires ^20.19.0 || ^22.13.0 || >=24). Replace removed
Linter.FlatConfig type with Linter.Config.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address new `no-useless-assignment` violations from ESLint 10
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* dedupe
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* fix: reduce if block nesting
This reduces if block nesting similar to how we did it in #15250 (which got lost during the `await` feature introduction): If the if expression doesn't contain an await expression or is not dependent on a blocker that is not already resolved, then we can avoid creating a separate `$.if()` statement. The one trade-off is that we'll do re-invocations for all the conditions leading up to the condition that matches. Therefore non-simple if expressions are wrapper in `$.derived` to avoid excessive recomputations.
closes#17659 (~320 markers in prod mode possible now; less in dev because of our "wrap this component with devtime info" method)
helps with #15200
* tweak
* feedback
If the render tag is wrapped in `$.async`, that `$.async` call already contains surrounding markers, so we must not add our own to avoid hydration mismatches. Related to #17641, fixes#17225
* add xhtml tests
* unused
* tweak
* more tests
* tweak
* we don't need to actually check the HTML - if it's malformed in SSR or mount, it will throw
* same here
* unused, so we can revert this
* and this
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* docs: wrap JSDoc URLs in @see and @link tags
* fix: move curly brace to end of URL
* chore: add changeset
* add link text
* regenerate
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: allow NaN in key blocks
* lol whoops
* Update packages/svelte/src/internal/client/dom/blocks/key.js
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* treat menu element like ul/ol for a11y role checks
The <menu> element has the same implicit role (list) as <ul> and <ol>,
so it should receive the same treatment in a11y checks:
- Allow <menu role="list"> without redundant role warning (CSS
list-style:none can remove semantics, role restores them)
- Allow <menu> with interactive roles like menu, menubar, radiogroup,
tablist, tree, treegrid (same exceptions as ul/ol)
Fixes#8529
* changeset
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Remove `onwheel` and `onmousewheel` from the list of passive events
in the v5 migration guide. Since #13322, only `ontouchstart` and
`ontouchmove` are passive by default, matching the basic-markup docs.
Closes#17430
* fix: exit resolved async blocks on correct node when hydrating
* expand test + fix
* tweak, add note to self
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
This is basically #17611, minus #17640, plus #17639. We need to add the $.next() call after render tags as well as components; rather than duplicating the logic, we can use is_standalone to determine when this is necessary (since this is what prevents $.append(...) from being used).
Fixes#17261Fixes#17608
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
creates a few abstractions in the compiler code around common "if-else" scenarios, as well as introducing a new runtime render helper
---------
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
The store invalidation detection in each blocks only checked for
Identifier and MemberExpression AST node types. This caused bind:
on iteration variables to silently fail when the expression used
logical operators (e.g. `{#each $store.items ?? [] as item}`).
Use expression metadata dependencies instead of AST type checking
to find store_sub bindings, which correctly handles all expression
shapes.
Fixes#14625
* fix: emit `each_key_duplicate` error in production
* fix: preserve key
* Update packages/svelte/src/internal/client/dom/blocks/each.js
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* Update packages/svelte/src/internal/client/dom/blocks/each.js
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: ensure keys are validated
* fix silly test name
* fix: cover other case of duplicate keys
* emit error on hydration
* ensure the error is handled
* drop useless tests
* unused
* finish merge
* add lost check back
* chore: bump playwright (#17565)
* chore: bump playwright
* maybe this will help somehow?
* err whatever
* fix
* chore: allow testing in production env 2 (#17590)
* Revert "chore: allow testing in production env (#16840)"
This reverts commit ffd65e90fe.
* new approach
* fix: handle renderer.run rejections (#17591)
* fix: handle renderer run rejections
* add test
* changeset
* simplify
* explanatory comment
---------
Co-authored-by: Antonio Bennett <abennett@mabelslabels.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: only create async functions in SSR output when necessary (#17593)
* fix: only create async functions in SSR output when necessary
* actually...
* simplify generated code a bit more
* simplify
* fix: merge consecutive text nodes during hydration for large text content (#17587)
* fix: merge consecutive text nodes during hydration for large text content
Fixes#17582
Browsers automatically split text nodes exceeding 65536 characters into
multiple consecutive text nodes during HTML parsing. This causes hydration
mismatches when Svelte expects a single text node.
The fix merges consecutive text nodes during hydration by:
- Detecting when the current node is a text node
- Finding all consecutive text node siblings
- Merging their content into the first text node
- Removing the extra text nodes
This restores correct hydration behavior for large text content.
* add test, fix
* fix
* fix
* changeset
---------
Co-authored-by: Miner <miner@example.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* Version Packages (#17585)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* Revert "drop useless tests"
This reverts commit 65f77ef840.
* update tests
* fix test
* we don't need to expose this function any more
* figured it out... we cant have errors during reconcile
* simplify
* tweak
* unused
* revert no-longer-needed change
* unused
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
Co-authored-by: Antonio Bennett <31296212+Antonio-Bennett@users.noreply.github.com>
Co-authored-by: Antonio Bennett <abennett@mabelslabels.com>
Co-authored-by: FORMI <239411042+Richman018@users.noreply.github.com>
Co-authored-by: Miner <miner@example.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
* Remove SvelteKit data attributes from elements.d.ts
Removed SvelteKit specific data attributes from elements.d.ts.
* Remove SvelteKit data attributes from elements.d.ts
Removed SvelteKit data attributes from elements.d.ts.
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
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`.
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.
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: merge consecutive text nodes during hydration for large text content
Fixes#17582
Browsers automatically split text nodes exceeding 65536 characters into
multiple consecutive text nodes during HTML parsing. This causes hydration
mismatches when Svelte expects a single text node.
The fix merges consecutive text nodes during hydration by:
- Detecting when the current node is a text node
- Finding all consecutive text node siblings
- Merging their content into the first text node
- Removing the extra text nodes
This restores correct hydration behavior for large text content.
* add test, fix
* fix
* fix
* changeset
---------
Co-authored-by: Miner <miner@example.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: prevent reactivity loss during fork
fixes#17197, fixes#17304, fixes#17301, fixes#17309
* add samples
* add changeset
* fix var casing in tests
* don't remove reactions during fork
* add sample for derived dep tracking in fork
* fix sample type check error
* set derived.v on first eval in fork
* add sample for derived.v remaining UNINITIALIZED
* lost current_batch import in runtime.js
* Delete how
* Update packages/svelte/src/internal/client/reactivity/deriveds.js
* delete test in favour of #17577
* extract runtime.js changes into separate PR
* alternative approach
* revert
* clear skipped branches when deferring
* fix
* fix
* changeset
* rename test
* update test
* unused test
---------
Co-authored-by: David Roizenman <david@hmnd.io>
Co-authored-by: Paolo Ricciuti <ricciutipaolo@gmail.com>
Co-authored-by: Tee Ming <chewteeming01@gmail.com>