* 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
* 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>
* 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>
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>
* fix: make onintrostart respect delay parameter
Fixes#14009
The onintrostart event now fires after the delay period completes,
rather than immediately when the transition is initiated. This ensures
that the event accurately reflects when the intro animation actually
starts.
Changes:
- Added on_start callback parameter to animate() function
- Dispatch introstart event after delay animation finishes
- Handle edge case where duration is 0 but delay > 0
* fix: format code with prettier
* add (failing) tests
* fix
* changeset
* missed a spot
* fix
---------
Co-authored-by: Miner <miner@example.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: mark parent effect as dirty on error boundary initialization
This change ensures that if an error occurs while a parent effect is still initializing, the parent effect is marked as dirty and scheduled to re-run. This addresses scenarios where state updates in the onerror handler do not trigger a re-evaluation of the condition, improving error handling in Svelte components.
* chore: add changeset for #17553
* fix: run boundary callbacks in a microtask, in case they result in the boundary's destruction
---------
Co-authored-by: frozenflux2 <snowflake30518@gmail.com>
* fix: each block breaking with effects interspersed among items
* test sample with interspersed non-branch effects
* Apply suggestion from @Rich-Harris
* use $effect.pre in sample instead
---------
Co-authored-by: Rich Harris <hello@rich-harris.dev>
* fix: handle falsy dynamic components in SSR
Closes#17408
Adds a dynamic check for the component in the SSR.
Changes:
- Modified server-side component renderer to use b.maybe_call for dynamic components
- Added SSR test case for falsy component values
* fix types
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: avoid using dev-mode array.includes wrapper on internal array checks
* use includes rather than index_of
* unused imports
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* add samples for async readable freeze
* test updating without changing reference too
* fix: treat block effects as maybe dirty in revive()
* even simpler - put block effects in maybe_dirty_effects
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
PR #17461 added the `wait` function to `reactivity/async.js` and modified the compiler to generate `$.wait()` calls, but forgot to export it from `index.js`.
This causes a runtime error when using `await` inside `$derived()` with `experimental.async: true`:
```
TypeError: $.wait is not a function
```
Fixes#17529
* fix: batch resolution of async work
Co-authored-by: David Roizenman <hmnd@users.noreply.github.com>
* fix
* drive-by tidy up — Batch.enqueue is (apparently?) a useless wrapper around queue_micro_task
* 99% sure it's impossible for is_flushing to be true inside a queued task
* add some comments
* return early, reduce indentation
---------
Co-authored-by: David Roizenman <hmnd@users.noreply.github.com>
* perf: use Set for new_deps to avoid O(n) includes check
* fix: only call revive() when batch is no longer deferred
* fix: avoid unnecessary async tracking when blockers are already settled
* add changeset
* only record promises as settled after cleanup is complete
* don't flush when already flushing
* skip settled blockers more aggressively
* batch decrement and pending count updates to reduce flush pressure
* extract new_deps changes to a separate PR
* remove changeset that applies to the other branch
* mark promises as settled as they settle — at the end is too late to do any good
* remove unnecessary microtask
* extract batch changes to separate PR
* this too
* avoid assigning to parameter
* wrong promise added to settled_promises due to reassignment
* WIP
* WIP
* fix
* unused
* oops
* bad import
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: handle non-string values in svelte:element this attribute
* chore: add changeset
* fix(review): throw error in DEV for invalid svelte:element tag, ignore in PROD
* chore: remove unused expected.html from test
* fix(review): refine validate.js logic
* fix(review): use else if (string) logic in server/index.js
* fix(review): swap validation order in compiler, revert runtime changes
* test: move reproduction to runtime-legacy per review
* Apply suggestion from @7nik
---------
Co-authored-by: tensorworker <tensorworker@proton.me>
Co-authored-by: 7nik <kfiiranet@gmail.com>
* feat: export from
* changeset
* fix: Errors
* set_source, so state is correct if an error occurs
* simplify
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* feat: customizable select
* fix: treat inner of options as separate templates
* fix: add hydration comment
* fix: clear with textContent
* fix: mark rich content option as dynamic and allow optgroup
* fix: allow select with rich content and rename
* chore: revert tests
* fix: recursively check rich options
* chore: change name of template
* fix: mark boundary as dynamic
* chore: add snapshot tests
* chore: include comprehensive hydration test
* fix: consider `selectedelement` as ancestor of `option` elements
* fix: make `:has` work with `selectedcontent`
* chore: failing test for css
* fix: also return parent for adjacent_only
* fix: move hydration marker at the end
* chore: apply suggestions from code review
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: treat text elements in select and optgroup as rich
* fix hydration
* colocate code
* drop the element, it's cleaner
* rename module
* update test
* Update .changeset/chubby-dingos-laugh.md
* fix a11y warning that occurs when button only contains selectedcontent
* remove unused parameter
* last part is redundant
* simplify
* unnecessary, the constraints overlap
* this is taken care of during analysis
* simplify
* tweak
* tweak
* tweak
* fix/tweak
* tweak
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* add test sample
* add test for sveltejs/kit#15059
* fix: reconnect deriveds inside branch effects
* add changeset
* fix: derived with no deps always set as MAYBE_DIRTY
fixes#17342
* add test for #17342
* additional changeset
* refactor: extract setting derived status to helper, apply to sources.js
* add test case for #17352
* fix: reconnect child deriveds when evaluating connected parent derived
fixes#17352
* fix import order causing Cannot read properties of undefined on dev load
* remove duplicate iteration over deps
* minor style tweaks
* oops, fix merge
* use update_derived_status, so that we never set a dep-less derived MAYBE_DIRTY
* tweak
* reaction.deps cannot be null for a MAYBE_DIRTY derived
* make it such that reactions without deps are never MAYBE_DIRTY
* since we no longer need to check reaction.deps === null, we can revert this bit
* more explicit check
* tidy up
* more
* gah whoops
* move import
* simplify test
* make dep-less derived behaviour more explicit, move it above is_destroying_effect handling
* remove test - this is adequately covered by #17445
* replace tricky unit test with component-based test
* remove incorrect test
* remove the BRANCH_EFFECT stuff
* tidy up
* DRY
* tweak, add explanatory comment
* tweak
* explanatory comment
* remove changeset
* update changeset
---------
Co-authored-by: Tee Ming <chewteeming01@gmail.com>
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* feat: type `currentTarget` in `on` function
* `EventTarget &` is redundant, `Element` already extends `EventTarget`
* no need for optional chaining
* add currentTarget for other overloads
* update changeset
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: prevent infinite loop when HMRing a component with an `await`
* update test
* fix
* reintroduce old logic to fix ever-growing stack of block effects
* update snapshot
* tweak names for clarity, simplify `update` slightly
---------
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
* fix: set Root start/end to null when fragment contains only whitespace
* format
* always set root.start to 0 and root.end to template.length
* Update .changeset/fruity-knives-ring.md
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
Co-authored-by: Rich Harris <hello@rich-harris.dev>