Skip to content

Commit 9ddff21

Browse files
committed
Merge remote-tracking branch 'origin/main' into state-onchange
2 parents cfd8ef2 + 6c9717a commit 9ddff21

File tree

773 files changed

+20157
-5133
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

773 files changed

+20157
-5133
lines changed

.github/workflows/ci.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ jobs:
2828
os: ubuntu-latest
2929
- node-version: 22
3030
os: ubuntu-latest
31+
- node-version: 24
32+
os: ubuntu-latest
3133

3234
steps:
3335
- uses: actions/checkout@v4
@@ -41,6 +43,23 @@ jobs:
4143
- run: pnpm test
4244
env:
4345
CI: true
46+
TestNoAsync:
47+
permissions: {}
48+
runs-on: ubuntu-latest
49+
timeout-minutes: 10
50+
steps:
51+
- uses: actions/checkout@v4
52+
- uses: pnpm/action-setup@v4
53+
- uses: actions/setup-node@v4
54+
with:
55+
node-version: 22
56+
cache: pnpm
57+
- run: pnpm install --frozen-lockfile
58+
- run: pnpm playwright install chromium
59+
- run: pnpm test runtime-runes
60+
env:
61+
CI: true
62+
SVELTE_NO_ASYNC: true
4463
Lint:
4564
permissions: {}
4665
runs-on: ubuntu-latest

.github/workflows/ecosystem-ci-trigger.yml

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,17 @@ jobs:
88
trigger:
99
runs-on: ubuntu-latest
1010
if: github.repository == 'sveltejs/svelte' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/ecosystem-ci run')
11+
permissions:
12+
issues: write # to add / delete reactions
13+
pull-requests: write # to read PR data, and to add labels
14+
actions: read # to check workflow status
15+
contents: read # to clone the repo
1116
steps:
12-
- uses: GitHubSecurityLab/actions-permissions/monitor@v1
13-
- uses: actions/github-script@v6
17+
- name: monitor action permissions
18+
uses: GitHubSecurityLab/actions-permissions/monitor@v1
19+
- name: check user authorization # user needs triage permission
20+
uses: actions/github-script@v7
21+
id: check-permissions
1422
with:
1523
script: |
1624
const user = context.payload.sender.login
@@ -29,24 +37,26 @@ jobs:
2937
}
3038
3139
if (hasTriagePermission) {
32-
console.log('Allowed')
40+
console.log('User is allowed. Adding +1 reaction.')
3341
await github.rest.reactions.createForIssueComment({
3442
owner: context.repo.owner,
3543
repo: context.repo.repo,
3644
comment_id: context.payload.comment.id,
3745
content: '+1',
3846
})
3947
} else {
40-
console.log('Not allowed')
48+
console.log('User is not allowed. Adding -1 reaction.')
4149
await github.rest.reactions.createForIssueComment({
4250
owner: context.repo.owner,
4351
repo: context.repo.repo,
4452
comment_id: context.payload.comment.id,
4553
content: '-1',
4654
})
47-
throw new Error('not allowed')
55+
throw new Error('User does not have the necessary permissions.')
4856
}
49-
- uses: actions/github-script@v6
57+
58+
- name: Get PR Data
59+
uses: actions/github-script@v7
5060
id: get-pr-data
5161
with:
5262
script: |
@@ -59,21 +69,27 @@ jobs:
5969
return {
6070
num: context.issue.number,
6171
branchName: pr.head.ref,
72+
commit: pr.head.sha,
6273
repo: pr.head.repo.full_name
6374
}
64-
- id: generate-token
65-
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92 #keep pinned for security reasons, currently 1.8.0
75+
76+
- name: Generate Token
77+
id: generate-token
78+
uses: actions/create-github-app-token@v2
6679
with:
67-
app_id: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_ID }}
68-
private_key: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_PRIVATE_KEY }}
69-
repository: '${{ github.repository_owner }}/svelte-ecosystem-ci'
70-
- uses: actions/github-script@v6
80+
app-id: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_ID }}
81+
private-key: ${{ secrets.ECOSYSTEM_CI_GITHUB_APP_PRIVATE_KEY }}
82+
repositories: |
83+
svelte
84+
svelte-ecosystem-ci
85+
86+
- name: Trigger Downstream Workflow
87+
uses: actions/github-script@v7
7188
id: trigger
7289
env:
7390
COMMENT: ${{ github.event.comment.body }}
7491
with:
7592
github-token: ${{ steps.generate-token.outputs.token }}
76-
result-encoding: string
7793
script: |
7894
const comment = process.env.COMMENT.trim()
7995
const prData = ${{ steps.get-pr-data.outputs.result }}
@@ -89,6 +105,7 @@ jobs:
89105
prNumber: '' + prData.num,
90106
branchName: prData.branchName,
91107
repo: prData.repo,
108+
commit: prData.commit,
92109
suite: suite === '' ? '-' : suite
93110
}
94111
})

.prettierignore

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ packages/**/config/*.js
77

88
# packages/svelte
99
packages/svelte/messages/**/*.md
10+
packages/svelte/scripts/_bundle.js
1011
packages/svelte/src/compiler/errors.js
1112
packages/svelte/src/compiler/warnings.js
1213
packages/svelte/src/internal/client/errors.js
@@ -25,17 +26,7 @@ packages/svelte/tests/hydration/samples/*/_expected.html
2526
packages/svelte/tests/hydration/samples/*/_override.html
2627
packages/svelte/types
2728
packages/svelte/compiler/index.js
28-
playgrounds/sandbox/input/**.svelte
29-
playgrounds/sandbox/output
30-
31-
# sites/svelte.dev
32-
sites/svelte.dev/static/svelte-app.json
33-
sites/svelte.dev/scripts/svelte-app/
34-
sites/svelte.dev/src/routes/_components/Supporters/contributors.jpg
35-
sites/svelte.dev/src/routes/_components/Supporters/contributors.js
36-
sites/svelte.dev/src/routes/_components/Supporters/donors.jpg
37-
sites/svelte.dev/src/routes/_components/Supporters/donors.js
38-
sites/svelte.dev/src/lib/generated
29+
playgrounds/sandbox/src/*
3930

4031
**/node_modules
4132
**/.svelte-kit

.prettierrc

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,6 @@
1717
"useTabs": false,
1818
"tabWidth": 2
1919
}
20-
},
21-
{
22-
"files": ["sites/svelte-5-preview/src/routes/docs/content/**/*.md"],
23-
"options": {
24-
"printWidth": 60
25-
}
2620
}
2721
]
2822
}

.vscode/settings.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
11
{
2-
"search.exclude": {
3-
"sites/svelte-5-preview/static/*": true
4-
},
52
"typescript.tsdk": "node_modules/typescript/lib"
63
}

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ Test samples are kept in `/test/xxx/samples` folder.
105105
pnpm test validator
106106
```
107107

108-
1. To filter tests _within_ a test suite, use `pnpm test <suite-name> -- -t <test-name>`, for example:
108+
1. To filter tests _within_ a test suite, use `pnpm test <suite-name> -t <test-name>`, for example:
109109

110110
```bash
111-
pnpm test validator -- -t a11y-alt-text
111+
pnpm test validator -t a11y-alt-text
112112
```
113113

114114
(You can also do `FILTER=<test-name> pnpm test <suite-name>` which removes other tests rather than simply skipping them — this will result in faster and more compact test results, but it's non-idiomatic. Choose your fighter.)

benchmarking/compare/index.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,23 +67,37 @@ for (let i = 0; i < results[0].length; i += 1) {
6767
for (const metric of ['time', 'gc_time']) {
6868
const times = results.map((result) => +result[i][metric]);
6969
let min = Infinity;
70+
let max = -Infinity;
7071
let min_index = -1;
7172

7273
for (let b = 0; b < times.length; b += 1) {
73-
if (times[b] < min) {
74-
min = times[b];
74+
const time = times[b];
75+
76+
if (time < min) {
77+
min = time;
7578
min_index = b;
7679
}
80+
81+
if (time > max) {
82+
max = time;
83+
}
7784
}
7885

7986
if (min !== 0) {
80-
console.group(`${metric}: fastest is ${branches[min_index]}`);
87+
console.group(`${metric}: fastest is ${char(min_index)} (${branches[min_index]})`);
8188
times.forEach((time, b) => {
82-
console.log(`${branches[b]}: ${time.toFixed(2)}ms (${((time / min) * 100).toFixed(2)}%)`);
89+
const SIZE = 20;
90+
const n = Math.round(SIZE * (time / max));
91+
92+
console.log(`${char(b)}: ${'◼'.repeat(n)}${' '.repeat(SIZE - n)} ${time.toFixed(2)}ms`);
8393
});
8494
console.groupEnd();
8595
}
8696
}
8797

8898
console.groupEnd();
8999
}
100+
101+
function char(i) {
102+
return String.fromCharCode(97 + i);
103+
}

documentation/docs/02-runes/02-$state.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,7 @@ Unlike other frameworks you may have encountered, there is no API for interactin
2020

2121
If `$state` is used with an array or a simple object, the result is a deeply reactive _state proxy_. [Proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) allow Svelte to run code when you read or write properties, including via methods like `array.push(...)`, triggering granular updates.
2222

23-
> [!NOTE] Classes like `Set` and `Map` will not be proxied, but Svelte provides reactive implementations for various built-ins like these that can be imported from [`svelte/reactivity`](./svelte-reactivity).
24-
25-
State is proxified recursively until Svelte finds something other than an array or simple object. In a case like this...
23+
State is proxified recursively until Svelte finds something other than an array or simple object (like a class or an object created with `Object.create`). In a case like this...
2624

2725
```js
2826
let todos = $state([
@@ -52,7 +50,7 @@ todos.push({
5250
});
5351
```
5452

55-
> [!NOTE] When you update properties of proxies, the original object is _not_ mutated.
53+
> [!NOTE] When you update properties of proxies, the original object is _not_ mutated. If you need to use your own proxy handlers in a state proxy, [you should wrap the object _after_ wrapping it in `$state`](https://svelte.dev/playground/hello-world?version=latest#H4sIAAAAAAAACpWR3WoDIRCFX2UqhWyIJL3erAulL9C7XnQLMe5ksbUqOpsfln33YuyGFNJC8UKdc2bOhw7Myk9kJXsJ0nttO9jcR5KEG9AWJDwHdzwxznbaYGTl68Do5JM_FRifuh-9X8Y9Gkq1rYx4q66cJbQUWcmqqIL2VDe2IYMEbvuOikBADi-GJDSkXG-phId0G-frye2DO2psQYDFQ0Ys8gQO350dUkEydEg82T0GOs0nsSG9g2IqgxACZueo2ZUlpdvoDC6N64qsg1QKY8T2bpZp8gpIfbCQ85Zn50Ud82HkeY83uDjspenxv3jXcSDyjPWf9L1vJf0GH666J-jLu1ery4dV257IWXBWGa0-xFDMQdTTn2ScxWKsn86ROsLwQxqrVR5QM84Ij8TKFD2-cUZSm4O2LSt30kQcvwCgCmfZnAIAAA==).
5654
5755
Note that if you destructure a reactive value, the references are not reactive — as in normal JavaScript, they are evaluated at the point of destructuring:
5856

@@ -67,16 +65,15 @@ todos[0].done = !todos[0].done;
6765

6866
### Classes
6967

70-
You can also use `$state` in class fields (whether public or private):
68+
Class instances are not proxied. Instead, you can use `$state` in class fields (whether public or private), or as the first assignment to a property immediately inside the `constructor`:
7169

7270
```js
7371
// @errors: 7006 2554
7472
class Todo {
7573
done = $state(false);
76-
text = $state();
7774

7875
constructor(text) {
79-
this.text = text;
76+
this.text = $state(text);
8077
}
8178

8279
reset() {
@@ -110,10 +107,9 @@ You can either use an inline function...
110107
// @errors: 7006 2554
111108
class Todo {
112109
done = $state(false);
113-
text = $state();
114110

115111
constructor(text) {
116-
this.text = text;
112+
this.text = $state(text);
117113
}
118114

119115
+++reset = () => {+++
@@ -123,6 +119,10 @@ class Todo {
123119
}
124120
```
125121

122+
### Built-in classes
123+
124+
Svelte provides reactive implementations of built-in classes like `Set`, `Map`, `Date` and `URL` that can be imported from [`svelte/reactivity`](svelte-reactivity).
125+
126126
## `$state.raw`
127127

128128
In cases where you don't want objects and arrays to be deeply reactive you can use `$state.raw`.
@@ -163,6 +163,8 @@ let count = $state(0, {
163163

164164
> The `onchange` function is [untracked](svelte#untrack).
165165
166+
As with `$state`, you can declare class fields using `$state.raw`.
167+
166168
## `$state.snapshot`
167169

168170
To take a static snapshot of a deeply reactive `$state` proxy, use `$state.snapshot`:

documentation/docs/02-runes/03-$derived.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,27 @@ let selected = $derived(items[index]);
9494

9595
...you can change (or `bind:` to) properties of `selected` and it will affect the underlying `items` array. If `items` was _not_ deeply reactive, mutating `selected` would have no effect.
9696

97+
## Destructuring
98+
99+
If you use destructuring with a `$derived` declaration, the resulting variables will all be reactive — this...
100+
101+
```js
102+
function stuff() { return { a: 1, b: 2, c: 3 } }
103+
// ---cut---
104+
let { a, b, c } = $derived(stuff());
105+
```
106+
107+
...is roughly equivalent to this:
108+
109+
```js
110+
function stuff() { return { a: 1, b: 2, c: 3 } }
111+
// ---cut---
112+
let _stuff = $derived(stuff());
113+
let a = $derived(_stuff.a);
114+
let b = $derived(_stuff.b);
115+
let c = $derived(_stuff.c);
116+
```
117+
97118
## Update propagation
98119

99120
Svelte uses something called _push-pull reactivity_ — when state is updated, everything that depends on the state (whether directly or indirectly) is immediately notified of the change (the 'push'), but derived values are not re-evaluated until they are actually read (the 'pull').

0 commit comments

Comments
 (0)