* fix: consider static attributes that are inlined in the template
* fix: use `is_inlinable_expression`
* fix: move check for inlinable expression as last
* fix: simplify and correct
* chore: accept single node in `is_inlinable_expression`
* chore: update comment
* chore: add snapshots for non static nodes
Previously, we were applying an explicit nesting selector to the start of a relative selector chain only when starting the traversal. Prepending the selector is important because it ensures we traverse upwards to the parent rule when the current selectors all matched and there's still more to do. But we forgot to do the prepend for parent rules, which meant that if we were nested two levels deep, we would stop too early. This fix ensures we prepend in that case, too.
Fixes#14178
fixes#14168
This reverts the whole "selectors inside `:not` are scoped" logic. Scoping is done so that styles don't bleed. But within `:not`,everything is reversed, which means scoping the selectors now means they are more likely to bleed. That is the opposite of what we want to achieve, therefore we should just leave those selectors alone.
The exception are `:not` selectors with descendant selectors, as that means "look up the tree" and we need to scope all ancestor elements in that case.
If the contents of a `:not` selector don't match, then it's actually a match for `:not` because it's inverted. Therefore, we need to scope such elements. We're also making sure that contents of `:not` that never match actually count as a used (because the result is negated), and as such the contents of `:not` that always match are actually marked as unused.
Fixes#13974
`<a>` tags are valid in both the SVG and HTML namespace. If there's no parent, we therefore have to look downwards to see if it's the parent of a SVG or HTML element.
fixes#7807fixes#13793
We didn't account for the `$props` rune being writtin in a way that makes some props unknown, and they would only be visible through the `customElement.props` definition. This changes the iteration to account for that and also adds a note to the documentation that you need to list out the properties explicitly.
fixes#13785
Fixes#13848.
When we set custom element attributes/props, we should be doing so without the current effect/reaction active. Otherwise, the custom element lifecycle might attach effects/dependencies to the wrong reaction and all manner of things can incorrectly occur
---------
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
We originally didn't extend from `Error` anymore because its fields are of no real value to us, and has problems with serialization in a worker context.
Turns out this was a mistake, because various build tools rely on errors being thrown as something that extends Error, else they try to wrap it in their own error.
We therefore revert that change while still trying to preserve most of the advantages of not extending `Error`, namely nuking the useless stack trace and making sure the message is enumerable.
When CSS is externalized we rightfully rely on the following tooling chain to properly minify CSS. When we inject the CSS however, that tooling won't be able to do that, so we gotta do it ourselves.
This PR brings back most of that logic that existed in Svelte 4. Fixes#13716
Only count down after timeout, else we would reach 0 before our own render effect reruns, but reach 1 again when the tick callback of the prior teardown runs. That would mean we re-subcribe unnecessarily and create a memory leak because the old subscription is never cleaned up.
* fix: add empty stack to `CompileDiagnostic` to show error on build
* chore: generate types
* chore: make stack optional to make TS happy
* chore: generate types -.-"
* chore: add comment
* fix: ensure value is correctly set to zero on the progress element
* fix: ensure value is correctly set to zero on the progress element
* fix: ensure value is correctly set to zero on the progress element
* chore: highlight swallowed errors from await blocks in DEV
* chore: highlight swallowed errors from await blocks in DEV
* chore: highlight swallowed errors from await blocks in DEV
* lint
* feedback
* feedback
* add test
* Update packages/svelte/tests/runtime-runes/samples/await-no-catch-error/main.svelte
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* fix: ensure SVG element attributes have case preserved
* fix: ensure SVG element attributes have case preserved
* fix: ensure SVG element attributes have case preserved
* fix: enable bound store props in runes mode components
* add some JSDoc, since it could be a headscratcher for future us
* make it clear that this is specifically about bindings
* skip intermediate value
* tweak other names too
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: internally wrap store subscribe in untrack
* lint
* Update packages/svelte/src/store/utils.js
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* Version Packages
* Update packages/svelte/CHANGELOG.md
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Closes#13493.
This PR allows the usage of getContext() inside $derived runes. Previously, you could use it, but only on init and not updates – and this inconsistency was unnecessary. We can make it work just like we do in other places.
I resisted this previously because it felt a bit wasteful, but I now think that there's really no way around this: Instead of only going upwards the tree while matching, for `:has` we go _down_ the tree to see what matches. More specifically, we're collecting the children of the current element and then check if one of those does match the selectors inside `:has`.
This makes the way the code works easier to reason about and also removes some boolean tracking we had to add for the previous approach.
Fixes#13779
Fixes#13717
There are two parts to this:
1. the parent selectors weren't passed along for the check inside `:has`, which in case of a leading combinator would mean it would always count as unused
2. In case if a selector like `x > y:has(z)`, the prior logic would correctly determine that for element `z` there's a match for the `:has` selector, by first checking its contents and then walking up the tree. But after it did that, it would try to walk up the tree once more, which is a) wasteful b) buggy because the tree walking mechanism would no longer be adjusted for the `:has` special case, resulting in false negatives. To fix that, the `:has` will return a new value from the function, signaling that it already fully checked the upper selectors, and so the function calling it will skip doing that.
- detect store mutations and not use `$derived` in that case, fixes#13723
- better detect `let x` that can be folded into `$derived`, fixes#13727
---------
Co-authored-by: ComputerGuy <63362464+Ocean-OS@users.noreply.github.com>
- correctly assign children snippet to default slot, fixes#13067
- allow `svelte:fragment` without `let:` directives to be rendered by `@render children()`, fixes#13066
* fix: avoid chromium issue with dispatching blur on element removal
* fix: avoid chromium issue with dispatching blur on element removal
* fix: avoid chromium issue with dispatching blur on element removal
* active effect too
* try/finally
* fix: moving deriveds during migration deletes part of the inserted code
* fix: use update instead of remove
* Update .changeset/cool-apes-confess.md
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
The other part of #13395
This implements scoping for selectors inside `:not(...)`. The approach is almot the same as for `:is/where(...)`.
This is a breaking change because people could've used `:not(.unknown)` with `.unknown` not appearing in the HTML, and so they need to do `:not(:global(.unknown))` instead.
While implementing it I also discovered a few bugs, which are fixed in this PR:
- `foo :is(bar baz)` wasn't properly handled. This selector can mean `foo bar baz` but it can also mean `bar foo baz` (super weird, but it is what it is). Since our current algorithm isn't suited for handling this, we just assume it matches and scope it. Worst case is we missed a prune
- `bar` in `:global(foo):is(bar)` was always marked as unused, even if it matched
The main part of #13395
This implements scoping for selectors inside `:has(...)`. The approach is to first descend into the contents of a `:has(...)` selector, then in case of a match, try to match the rest of the selector ignoring the `:has(...)` part. In other words, `.x:has(y)` is essentially treated as `x y` with `y` being matched first, then walking up the selector chain taking into account combinators.
This is a breaking change because people could've used `:has(.unknown)` with `.unknown` not appearing in the HTML, and so they need to do `:has(:global(.unknown))` instead
* fix: ensure effects destroy owned deriveds upon teardown
* add test
* make old test work
* tune
* tune
* Update packages/svelte/src/internal/client/runtime.js
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* do no rerun the each block when array change from empty to empty
* rename empty yo was_empty
* add test
* fix nullable array on SSR
* format
* rewrite
* chore: add changeset
---------
Co-authored-by: Paolo Ricciuti <ricciutipaolo@gmail.com>
- make sure to not overfire before/afterUpdate
- make sure to not fire mutable sources when they were mutated
- only show deprecation warning when in runes mode to not clutter up console (this is in line with how we made it in other places)
fixes#13454
* fix: ensure set_text applies coercion to objects before diff
* lint
* feedback
* Update packages/svelte/src/internal/client/render.js
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
fixes#13270 by resetting the has_call boolean to false to style/class attributes, which means we're not creating a separate template effect for the attribute, instead they're added to the common template effect in which style/class directives are also added to later
Fix a bug where play/pause events may never be added to the media element. Also simplifies the logic by making it an effect instead of a render effect
---------
Co-authored-by: Simon Holthausen <simon.holthausen@vercel.com>
* feat: migrate `svelte:self`
* chore: regenerate types
* fix: special case `<svelte:self></svelte:self>`
* chore: add special case to tests
* chore: add no filename test
* chore: better migration task message
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* chore: make filename an options object to futureproof it
* chore: simplify open tag `svelte:self`
* chore: simplify migration comment test
* chore: generate types
* chore: apply smart suggestion
* chore: changeset
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* feat: enable snippets to fill slots
This allows people to use snippets to fill slots. It is implemented in the same way the default slot interop is already implemented, by passing a boolean to the hidden `$$slots` object, and using that at runtime to determine the correct outcome. The impact on bundle size is neglible.
By enabling this, we can enhance our migration script to always transform slot usages (including `let:x` etc) to snippets. This wasn't possible before because we couldn't be sure if the other side was transformed to using render tags at the same time. This will be part of #13419. This is important because currently the migration script is transforming `<slot />` creations inside components, but since it's not touching its usage points the migration will make your app end up in a broken state which you have to finish by hand.
This is a reduced alternative to, and closes#11619, which was also enabling the other way around, but that is a) not as necessary and b) more likely to confuse people / break, because it only works if your render function has 0-1 arguments.
* unused
* ditto - annotation is redundant
* couple of drive-by consistency tweaks
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: allow combinator at start of nested CSS selector
Solved by moving the combinator positioning validation into the analysis phase
Fixes#13433
* highlight the combinator, not the start of the combinator
* fix
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* feat: fix accessors and support migration of accessors
* fix: exclude slots
* fix: remove call to proxy for accessors props
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* chore: add test for accessors
* chore: fix lint
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
* feat: allow migration of `svelte:component`
* chore: simplify a lot (thanks @dummdidumm)
* chore: update output
* chore: use `next()` and `snip` instead of walking the AST
* fix: migrate nested `svelte:component`
* Update .changeset/good-vans-bake.md
---------
Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
Fixes#13390
There's pruning logic in a different place where all unused selectors are commented out. If all selectors are unused, the whole prelude is commented out, resulting in invalid syntax. This is a case that shouldn't happen, therefore simplify the whole "is used" logic to only look at the prelude.
* fix: migrate events to be more inline with svelte 4
* fix: use function instead of action
* chore: generate types
* re-export event modifier substitutes
* chore: replace map with object
* fix: handle nullish values
* fix: use bubbler for delegated events
* chore: generate types
* chore: deprecate legacy stuff
* chore: damn type generations
* fix: implement bubble on props strategy
* chore: revert bubble as prop init but keep fix for restProps
* fix: use `passive` and `nonpassive` actions for `passive` and `nonpassive` modifiers
* chore: i swear i will setup a commit hook for generating types
* chore: update output
* tweak passive/nonpassive types to make them more compact and show up as deprecated
* make terminology more consistent with other places
* eat local, shop local, declare local
* unify name replacement stuff
* remove errant newline
* ensure modifier order is stable and matches svelte 4
* fix
* compute indent once
* joining without newlines seems to work better in common cases
* replace passive/nonpassive handlers in situ
* unused
* simplify
* simplify, remove errant spaces
* only import handlers when necessary
* changeset
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: set strings as attributes, non-strings as properties if property exists
* simplify
* remove draggable from list, no longer needed
* in fact we dont need the lookup at all
* lint
* beef up test
* correctly SSR translate attribute
* fix: flip not accounting for scaled lengths
* zoom is uniform, one calculation will do
* stash width/height multipliers
* use var
* scale-first appears to work better?
* more robust zoom calculation
* changeset
---------
Co-authored-by: Etai Nadler <75544136+etainad008@users.noreply.github.com>
This was done previously to align with browser behavior, but the browser behavior actually only makes them passive on window/document/body. Since wheel events are not delegated, we can revert their passive-by-default setting. Closes#13318
For touchstart/touchmove we're not changing it because these events are delegated, which means they happen a lot more often on a target higher up the tree, which may cause jank.
#13225 did not fully fix the described issue: As soon as you have a child component, that child component's anchor will not be in the right ownerDocument yet, and so the logic falls down.
To fix that, we would need to move the ownerDocument check into the microtask - and that map check was mainly done to avoid just that. So instead I opted to simplify the code and just remove the map checks. According to my benchmarking (https://jsbench.me/3hm17l0bxl/1) this has no impact on performance assuming that you'll have cache hits roughly half the time - and even if you'd have much more cache hits, the performance loss is microscopic. Given that the default mode is to not inject styles, this will not be common anyway, so I favor removing that map.
* feat: provide guidance in browser console when logging `$state` objects
Wrap console.log/warn/error statements in DEV mode with a check whether or not they contain state objects. Closes#13123
This is an alternative or enhancement to #13070. Alternative if we deem it the better solution. Enhancement because it's not as robust as a custom formatter: We only check the top level of each entry (though we could maybe traverse a few levels), and if you're logging class instances, snapshot currently stops at the boundaries there and so you don't get snapshotted values for these (arguably this is a more general problem of $inspect and $state.snapshot), whereas with custom formatter it doesn't matter at which level you come across it.
* lint
* use normal warning mechanism, so we can link to docs etc
* add a few more methods
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>
* fix: separate `template_effect` for dynamic class/style directive with dynamic attributes
* fix: only move to `init` if it `has_call`
* fix: initialize spread `needs_isolation` based on if there are directives with `has_call`
* fix: revert splitting templates and generate deriveds instead
* small tweaks
---------
Co-authored-by: Rich Harris <rich.harris@vercel.com>