Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sveltejs/svelte
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: svelte@5.23.0
Choose a base ref
...
head repository: sveltejs/svelte
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: svelte@5.23.1
Choose a head ref
  • 13 commits
  • 38 files changed
  • 12 contributors

Commits on Mar 12, 2025

  1. fix: add files and group properties to HTMLInputAttributes (#15492)

    Fixes #14579
    Although this isn't 100% correct because there's no `group` attribute, there's no better way to make people have components' props just be `HTMLInputAttributes` and allow them to reference `group`
    dvcol authored Mar 12, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    b27ca42 View commit details

Commits on Mar 13, 2025

  1. fix: ensure transient writes to tracked parent effects works as expec…

    …ted (#15506)
    
    * ix: ensure transient writes to tracked parent effects works as expected
    
    * lint
    
    * format test
    
    * tweak changeset
    
    ---------
    
    Co-authored-by: Rich Harris <rich.harris@vercel.com>
    trueadm and Rich-Harris authored Mar 13, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    5d3aa2b View commit details

Commits on Mar 14, 2025

  1. fix: replace undefined with void 0 to avoid edge case (#15511)

    * replace 'undefined' with 'void 0'
    
    * lint
    
    * YALF
    
    * reuse expression
    
    * oops
    
    ---------
    
    Co-authored-by: Rich Harris <rich.harris@vercel.com>
    Ocean-OS and Rich-Harris authored Mar 14, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    489f463 View commit details
  2. docs: Update 99-faq.md (#15510)

    sacrosanctic authored Mar 14, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    dab1a1b View commit details
  3. chore: reuse expression nodes (#15513)

    Rich-Harris authored Mar 14, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    18d71fd View commit details
  4. chore: don't distribute unused types definitions (#15473)

    hopefully helps with #15182, also makes the package smaller
    
    ---------
    
    Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
    benmccann and dummdidumm authored Mar 14, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    e74fbcb View commit details
  5. fix: Allow global-like pseudo-selectors refinement (#15313)

    For instance, specifying a tree-structural pseudo-class to
    `::view-transition-new` should still constitute a valid global-like
    selector.
    
    Fixes #15312
    
    ---------
    
    Co-authored-by: Simon H <5968653+dummdidumm@users.noreply.github.com>
    ccjmne and dummdidumm authored Mar 14, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    f227cfc View commit details
  6. fix: correctly match :has()'s selector during css pruning (#15277)

    Fixes #14072
    
    `:has()` was matching only against descendants or siblings, but not sibling's descendants. This makes the logic be able to go forward or backwards, simplifying a lot of cases along the way.
    7nik authored Mar 14, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    8e9a21e View commit details
  7. docs: add docs on state_unsafe_mutation error (#14932)

    closes #14752
    dummdidumm authored Mar 14, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    aaeda65 View commit details

Commits on Mar 15, 2025

  1. rune_invalid_arguments_length (#15516)

    adiguba authored Mar 15, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    32ee6c1 View commit details

Commits on Mar 16, 2025

  1. updated -> to → in v5-migration-guide (#15526)

    garikAsplund authored Mar 16, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    f30d75a View commit details
  2. chore: tweak migration doc diff blocks (#15527)

    Rich-Harris authored Mar 16, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    e5881ea View commit details

Commits on Mar 17, 2025

  1. Version Packages (#15501)

    Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
    github-actions[bot] authored Mar 17, 2025

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    74917ae View commit details
Showing with 521 additions and 344 deletions.
  1. +20 −19 documentation/docs/07-misc/07-v5-migration-guide.md
  2. +1 −1 documentation/docs/07-misc/99-faq.md
  3. +24 −0 documentation/docs/98-reference/.generated/client-errors.md
  4. +18 −0 packages/svelte/CHANGELOG.md
  5. +2 −0 packages/svelte/elements.d.ts
  6. +24 −0 packages/svelte/messages/client-errors/errors.md
  7. +3 −2 packages/svelte/package.json
  8. +7 −1 packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js
  9. +210 −217 packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js
  10. +1 −1 packages/svelte/src/compiler/phases/2-analyze/visitors/CallExpression.js
  11. +1 −1 packages/svelte/src/compiler/phases/3-transform/client/transform-client.js
  12. +1 −1 packages/svelte/src/compiler/phases/3-transform/client/visitors/AnimateDirective.js
  13. +1 −1 packages/svelte/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js
  14. +2 −2 packages/svelte/src/compiler/phases/3-transform/client/visitors/BinaryExpression.js
  15. +1 −3 packages/svelte/src/compiler/phases/3-transform/client/visitors/IfBlock.js
  16. +1 −1 packages/svelte/src/compiler/phases/3-transform/client/visitors/RegularElement.js
  17. +1 −1 packages/svelte/src/compiler/phases/3-transform/client/visitors/SlotElement.js
  18. +1 −2 packages/svelte/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js
  19. +2 −2 packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/element.js
  20. +2 −2 packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js
  21. +1 −1 packages/svelte/src/compiler/phases/3-transform/server/visitors/SlotElement.js
  22. +2 −3 packages/svelte/src/compiler/phases/3-transform/server/visitors/VariableDeclaration.js
  23. +4 −2 packages/svelte/src/compiler/utils/builders.js
  24. +8 −0 packages/svelte/src/internal/client/runtime.js
  25. +1 −1 packages/svelte/src/version.js
  26. +8 −0 packages/svelte/tests/compiler-errors/samples/runes-wrong-state-raw-args/_config.js
  27. +3 −0 packages/svelte/tests/compiler-errors/samples/runes-wrong-state-raw-args/main.svelte
  28. +1 −0 packages/svelte/tests/compiler-errors/samples/runes-wrong-state-raw-args/main.svelte.js
  29. +88 −60 packages/svelte/tests/css/samples/has/_config.js
  30. +13 −0 packages/svelte/tests/css/samples/has/expected.css
  31. +21 −0 packages/svelte/tests/css/samples/has/input.svelte
  32. +1 −16 packages/svelte/tests/css/samples/render-tag-loop/_config.js
  33. +6 −3 packages/svelte/tests/css/samples/render-tag-loop/expected.css
  34. +9 −1 packages/svelte/tests/css/samples/render-tag-loop/input.svelte
  35. +6 −0 packages/svelte/tests/css/samples/view-transition/expected.css
  36. +6 −0 packages/svelte/tests/css/samples/view-transition/input.svelte
  37. +7 −0 packages/svelte/tests/runtime-runes/samples/untracked-write-pre/_config.js
  38. +13 −0 packages/svelte/tests/runtime-runes/samples/untracked-write-pre/main.svelte
39 changes: 20 additions & 19 deletions documentation/docs/07-misc/07-v5-migration-guide.md
Original file line number Diff line number Diff line change
@@ -10,13 +10,13 @@ You don't have to migrate to the new syntax right away - Svelte 5 still supports

At the heart of Svelte 5 is the new runes API. Runes are basically compiler instructions that inform Svelte about reactivity. Syntactically, runes are functions starting with a dollar-sign.

### let -> $state
### let $state

In Svelte 4, a `let` declaration at the top level of a component was implicitly reactive. In Svelte 5, things are more explicit: a variable is reactive when created using the `$state` rune. Let's migrate the counter to runes mode by wrapping the counter in `$state`:

```svelte
<script>
let count = +++$state(+++0+++)+++;
let count = +++$state(0)+++;
</script>
```

@@ -25,14 +25,14 @@ Nothing else changes. `count` is still the number itself, and you read and write
> [!DETAILS] Why we did this
> `let` being implicitly reactive at the top level worked great, but it meant that reactivity was constrained - a `let` declaration anywhere else was not reactive. This forced you to resort to using stores when refactoring code out of the top level of components for reuse. This meant you had to learn an entirely separate reactivity model, and the result often wasn't as nice to work with. Because reactivity is more explicit in Svelte 5, you can keep using the same API outside the top level of components. Head to [the tutorial](/tutorial) to learn more.
### $: -> $derived/$effect
### $: $derived/$effect

In Svelte 4, a `$:` statement at the top level of a component could be used to declare a derivation, i.e. state that is entirely defined through a computation of other state. In Svelte 5, this is achieved using the `$derived` rune:

```svelte
<script>
let count = +++$state(+++0+++)+++;
---$:--- +++const+++ double = +++$derived(+++count * 2+++)+++;
let count = $state(0);
---$:--- +++const+++ double = +++$derived(count * 2)+++;
</script>
```

@@ -42,7 +42,8 @@ A `$:` statement could also be used to create side effects. In Svelte 5, this is

```svelte
<script>
let count = +++$state(+++0+++)+++;
let count = $state(0);
---$:---+++$effect(() =>+++ {
if (count > 5) {
alert('Count is too high!');
@@ -73,14 +74,14 @@ Note that [when `$effect` runs is different]($effect#Understanding-dependencies)
> - executing dependencies as needed and therefore being immune to ordering problems
> - being TypeScript-friendly
### export let -> $props
### export let $props

In Svelte 4, properties of a component were declared using `export let`. Each property was one declaration. In Svelte 5, all properties are declared through the `$props` rune, through destructuring:

```svelte
<script>
---export let optional = 'unset';
export let required;---
---export let optional = 'unset';---
---export let required;---
+++let { optional = 'unset', required } = $props();+++
</script>
```
@@ -105,8 +106,8 @@ In Svelte 5, the `$props` rune makes this straightforward without any additional

```svelte
<script>
---let klass = '';
export { klass as class};---
---let klass = '';---
---export { klass as class};---
+++let { class: klass, ...rest } = $props();+++
</script>
<button class={klass} {...---$$restProps---+++rest+++}>click me</button>
@@ -192,9 +193,9 @@ This function is deprecated in Svelte 5. Instead, components should accept _call
```svelte
<!--- file: Pump.svelte --->
<script>
---import { createEventDispatcher } from 'svelte';
const dispatch = createEventDispatcher();
---
---import { createEventDispatcher } from 'svelte';---
---const dispatch = createEventDispatcher();---
+++let { inflate, deflate } = $props();+++
let power = $state(5);
</script>
@@ -466,11 +467,11 @@ By now you should have a pretty good understanding of the before/after and how t
We thought the same, which is why we provide a migration script to do most of the migration automatically. You can upgrade your project by using `npx sv migrate svelte-5`. This will do the following things:

- bump core dependencies in your `package.json`
- migrate to runes (`let` -> `$state` etc)
- migrate to event attributes for DOM elements (`on:click` -> `onclick`)
- migrate slot creations to render tags (`<slot />` -> `{@render children()}`)
- migrate slot usages to snippets (`<div slot="x">...</div>` -> `{#snippet x()}<div>...</div>{/snippet}`)
- migrate obvious component creations (`new Component(...)` -> `mount(Component, ...)`)
- migrate to runes (`let` `$state` etc)
- migrate to event attributes for DOM elements (`on:click` `onclick`)
- migrate slot creations to render tags (`<slot />` `{@render children()}`)
- migrate slot usages to snippets (`<div slot="x">...</div>` `{#snippet x()}<div>...</div>{/snippet}`)
- migrate obvious component creations (`new Component(...)` `mount(Component, ...)`)

You can also migrate a single component in VS Code through the `Migrate Component to Svelte 5 Syntax` command, or in our Playground through the `Migrate` button.

2 changes: 1 addition & 1 deletion documentation/docs/07-misc/99-faq.md
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@ It will show up on hover.
- You can use markdown here.
- You can also use code blocks here.
- Usage:
```tsx
```svelte
<main name="Arethra">
```
-->
24 changes: 24 additions & 0 deletions documentation/docs/98-reference/.generated/client-errors.md
Original file line number Diff line number Diff line change
@@ -133,3 +133,27 @@ Reading state that was created inside the same derived is forbidden. Consider us
```
Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
```

This error is thrown in a situation like this:

```svelte
<script>
let count = $state(0);
let multiple = $derived.by(() => {
const result = count * 2;
if (result > 10) {
count = 0;
}
return result;
});
</script>
<button onclick={() => count++}>{count} / {multiple}</button>
```

Here, the `$derived` updates `count`, which is `$state` and therefore forbidden to do. It is forbidden because the reactive graph could become unstable as a result, leading to subtle bugs, like values being stale or effects firing in the wrong order. To prevent this, Svelte errors when detecting an update to a `$state` variable.

To fix this:
- See if it's possible to refactor your `$derived` such that the update becomes unnecessary
- Think about why you need to update `$state` inside a `$derived` in the first place. Maybe it's because you're using `bind:`, which leads you down a bad code path, and separating input and output path (by splitting it up to an attribute and an event, or by using [Function bindings](bind#Function-bindings)) makes it possible avoid the update
- If it's unavoidable, you may need to use an [`$effect`]($effect) instead. This could include splitting parts of the `$derived` into an [`$effect`]($effect) which does the updates
18 changes: 18 additions & 0 deletions packages/svelte/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# svelte

## 5.23.1

### Patch Changes

- fix: invalidate parent effects when child effects update parent dependencies ([#15506](https://github.com/sveltejs/svelte/pull/15506))

- fix: correctly match `:has()` selector during css pruning ([#15277](https://github.com/sveltejs/svelte/pull/15277))

- fix: replace `undefined` with `void 0` to avoid edge case ([#15511](https://github.com/sveltejs/svelte/pull/15511))

- fix: allow global-like pseudo-selectors refinement ([#15313](https://github.com/sveltejs/svelte/pull/15313))

- chore: don't distribute unused types definitions ([#15473](https://github.com/sveltejs/svelte/pull/15473))

- fix: add `files` and `group` to HTMLInputAttributes in elements.d.ts ([#15492](https://github.com/sveltejs/svelte/pull/15492))

- fix: throw rune_invalid_arguments_length when $state.raw() is used with more than 1 arg ([#15516](https://github.com/sveltejs/svelte/pull/15516))

## 5.23.0

### Minor Changes
2 changes: 2 additions & 0 deletions packages/svelte/elements.d.ts
Original file line number Diff line number Diff line change
@@ -1076,6 +1076,7 @@ export interface HTMLInputAttributes extends HTMLAttributes<HTMLInputElement> {
checked?: boolean | undefined | null;
dirname?: string | undefined | null;
disabled?: boolean | undefined | null;
files?: FileList | undefined | null;
form?: string | undefined | null;
formaction?: string | undefined | null;
formenctype?:
@@ -1087,6 +1088,7 @@ export interface HTMLInputAttributes extends HTMLAttributes<HTMLInputElement> {
formmethod?: 'dialog' | 'get' | 'post' | 'DIALOG' | 'GET' | 'POST' | undefined | null;
formnovalidate?: boolean | undefined | null;
formtarget?: string | undefined | null;
group?: any | undefined | null;
height?: number | string | undefined | null;
indeterminate?: boolean | undefined | null;
list?: string | undefined | null;
24 changes: 24 additions & 0 deletions packages/svelte/messages/client-errors/errors.md
Original file line number Diff line number Diff line change
@@ -87,3 +87,27 @@ See the [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-long
## state_unsafe_mutation

> Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
This error is thrown in a situation like this:

```svelte
<script>
let count = $state(0);
let multiple = $derived.by(() => {
const result = count * 2;
if (result > 10) {
count = 0;
}
return result;
});
</script>
<button onclick={() => count++}>{count} / {multiple}</button>
```

Here, the `$derived` updates `count`, which is `$state` and therefore forbidden to do. It is forbidden because the reactive graph could become unstable as a result, leading to subtle bugs, like values being stale or effects firing in the wrong order. To prevent this, Svelte errors when detecting an update to a `$state` variable.

To fix this:
- See if it's possible to refactor your `$derived` such that the update becomes unnecessary
- Think about why you need to update `$state` inside a `$derived` in the first place. Maybe it's because you're using `bind:`, which leads you down a bad code path, and separating input and output path (by splitting it up to an attribute and an event, or by using [Function bindings](bind#Function-bindings)) makes it possible avoid the update
- If it's unavoidable, you may need to use an [`$effect`]($effect) instead. This could include splitting parts of the `$derived` into an [`$effect`]($effect) which does the updates
5 changes: 3 additions & 2 deletions packages/svelte/package.json
Original file line number Diff line number Diff line change
@@ -2,18 +2,19 @@
"name": "svelte",
"description": "Cybernetically enhanced web apps",
"license": "MIT",
"version": "5.23.0",
"version": "5.23.1",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
"node": ">=18"
},
"files": [
"*.d.ts",
"src",
"!src/**/*.test.*",
"!src/**/*.d.ts",
"types",
"compiler",
"*.d.ts",
"README.md"
],
"module": "src/index-client.js",
Original file line number Diff line number Diff line change
@@ -133,7 +133,13 @@ const css_visitors = {

node.metadata.is_global = node.selectors.length >= 1 && is_global(node);

if (node.selectors.length === 1) {
if (
node.selectors.length >= 1 &&
node.selectors.every(
(selector) =>
selector.type === 'PseudoClassSelector' || selector.type === 'PseudoElementSelector'
)
) {
const first = node.selectors[0];
node.metadata.is_global_like ||=
(first.type === 'PseudoClassSelector' && first.name === 'host') ||
Loading