Skip to content

Commit cbe9d8c

Browse files
authored
Merge branch 'main' into fix-ssr-boundary-in-async
2 parents 9ab8a8b + 4eb432e commit cbe9d8c

File tree

93 files changed

+1942
-884
lines changed

Some content is hidden

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

93 files changed

+1942
-884
lines changed

.changeset/short-banks-yell.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.changeset/small-geckos-camp.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"svelte": patch
3+
---
4+
5+
feat: experimental `fork` API

.changeset/witty-seas-learn.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

documentation/docs/02-runes/07-$inspect.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ The `$inspect` rune is roughly equivalent to `console.log`, with the exception t
1818
<input bind:value={message} />
1919
```
2020

21+
On updates, a stack trace will be printed, making it easy to find the origin of a state change (unless you're in the playground, due to technical limitations).
22+
2123
## $inspect(...).with
2224

2325
`$inspect` returns a property `with`, which you can invoke with a callback, which will then be invoked instead of `console.log`. The first argument to the callback is either `"init"` or `"update"`; subsequent arguments are the values passed to `$inspect` ([demo](/playground/untitled#H4sIAAAAAAAACkVQ24qDMBD9lSEUqlTqPlsj7ON-w7pQG8c2VCchmVSK-O-bKMs-DefKYRYx6BG9qL4XQd2EohKf1opC8Nsm4F84MkbsTXAqMbVXTltuWmp5RAZlAjFIOHjuGLOP_BKVqB00eYuKs82Qn2fNjyxLtcWeyUE2sCRry3qATQIpJRyD7WPVMf9TW-7xFu53dBcoSzAOrsqQNyOe2XUKr0Xi5kcMvdDB2wSYO-I9vKazplV1-T-d6ltgNgSG1KjVUy7ZtmdbdjqtzRcphxMS1-XubOITJtPrQWMvKnYB15_1F7KKadA_AQAA)):
@@ -36,13 +38,6 @@ The `$inspect` rune is roughly equivalent to `console.log`, with the exception t
3638
<button onclick={() => count++}>Increment</button>
3739
```
3840

39-
A convenient way to find the origin of some change is to pass `console.trace` to `with`:
40-
41-
```js
42-
// @errors: 2304
43-
$inspect(stuff).with(console.trace);
44-
```
45-
4641
## $inspect.trace(...)
4742

4843
This rune, added in 5.14, causes the surrounding function to be _traced_ in development. Any time the function re-runs as part of an [effect]($effect) or a [derived]($derived), information will be printed to the console about which pieces of reactive state caused the effect to fire.

documentation/docs/03-template-syntax/19-await-expressions.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,54 @@ If a `<svelte:boundary>` with a `pending` snippet is encountered during SSR, tha
135135

136136
> [!NOTE] In the future, we plan to add a streaming implementation that renders the content in the background.
137137
138+
## Forking
139+
140+
The [`fork(...)`](svelte#fork) API, added in 5.42, makes it possible to run `await` expressions that you _expect_ to happen in the near future. This is mainly intended for frameworks like SvelteKit to implement preloading when (for example) users signal an intent to navigate.
141+
142+
```svelte
143+
<script>
144+
import { fork } from 'svelte';
145+
import Menu from './Menu.svelte';
146+
147+
let open = $state(false);
148+
149+
/** @type {import('svelte').Fork | null} */
150+
let pending = null;
151+
152+
function preload() {
153+
pending ??= fork(() => {
154+
open = true;
155+
});
156+
}
157+
158+
function discard() {
159+
pending?.discard();
160+
pending = null;
161+
}
162+
</script>
163+
164+
<button
165+
onfocusin={preload}
166+
onfocusout={discard}
167+
onpointerenter={preload}
168+
onpointerleave={discard}
169+
onclick={() => {
170+
pending?.commit();
171+
pending = null;
172+
173+
// in case `pending` didn't exist
174+
// (if it did, this is a no-op)
175+
open = true;
176+
}}
177+
>open menu</button>
178+
179+
{#if open}
180+
<!-- any async work inside this component will start
181+
as soon as the fork is created -->
182+
<Menu onclose={() => open = false} />
183+
{/if}
184+
```
185+
138186
## Caveats
139187

140188
As an experimental feature, the details of how `await` is handled (and related APIs like `$effect.pending()`) are subject to breaking changes outside of a semver major release, though we intend to keep such changes to a bare minimum.

documentation/docs/98-reference/.generated/client-errors.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ $effect(() => {
130130

131131
Often when encountering this issue, the value in question shouldn't be state (for example, if you are pushing to a `logs` array in an effect, make `logs` a normal array rather than `$state([])`). In the rare cases where you really _do_ need to write to state in an effect — [which you should avoid]($effect#When-not-to-use-$effect) — you can read the state with [untrack](svelte#untrack) to avoid adding it as a dependency.
132132

133+
### experimental_async_fork
134+
135+
```
136+
Cannot use `fork(...)` unless the `experimental.async` compiler option is `true`
137+
```
138+
133139
### flush_sync_in_effect
134140

135141
```
@@ -140,6 +146,18 @@ The `flushSync()` function can be used to flush any pending effects synchronousl
140146

141147
This restriction only applies when using the `experimental.async` option, which will be active by default in Svelte 6.
142148

149+
### fork_discarded
150+
151+
```
152+
Cannot commit a fork that was already committed or discarded
153+
```
154+
155+
### fork_timing
156+
157+
```
158+
Cannot create a fork inside an effect or when state changes are pending
159+
```
160+
143161
### get_abort_signal_outside_reaction
144162

145163
```

packages/svelte/CHANGELOG.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,37 @@
11
# svelte
22

3+
## 5.41.4
4+
5+
### Patch Changes
6+
7+
- fix: take into account static blocks when determining transition locality ([#17018](https://github.com/sveltejs/svelte/pull/17018))
8+
9+
- fix: coordinate mount of snippets with await expressions ([#17021](https://github.com/sveltejs/svelte/pull/17021))
10+
11+
- fix: better optimization of await expressions ([#17025](https://github.com/sveltejs/svelte/pull/17025))
12+
13+
- fix: flush pending changes after rendering `failed` snippet ([#16995](https://github.com/sveltejs/svelte/pull/16995))
14+
15+
## 5.41.3
16+
17+
### Patch Changes
18+
19+
- chore: exclude vite optimized deps from stack traces ([#17008](https://github.com/sveltejs/svelte/pull/17008))
20+
21+
- perf: skip repeatedly traversing the same derived ([#17016](https://github.com/sveltejs/svelte/pull/17016))
22+
23+
## 5.41.2
24+
25+
### Patch Changes
26+
27+
- fix: keep batches alive until all async work is complete ([#16971](https://github.com/sveltejs/svelte/pull/16971))
28+
29+
- fix: don't preserve reactivity context across function boundaries ([#17002](https://github.com/sveltejs/svelte/pull/17002))
30+
31+
- fix: make `$inspect` logs come from the callsite ([#17001](https://github.com/sveltejs/svelte/pull/17001))
32+
33+
- fix: ensure guards (eg. if, each, key) run before their contents ([#16930](https://github.com/sveltejs/svelte/pull/16930))
34+
335
## 5.41.1
436

537
### Patch Changes

packages/svelte/messages/client-errors/errors.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ $effect(() => {
100100

101101
Often when encountering this issue, the value in question shouldn't be state (for example, if you are pushing to a `logs` array in an effect, make `logs` a normal array rather than `$state([])`). In the rare cases where you really _do_ need to write to state in an effect — [which you should avoid]($effect#When-not-to-use-$effect) — you can read the state with [untrack](svelte#untrack) to avoid adding it as a dependency.
102102

103+
## experimental_async_fork
104+
105+
> Cannot use `fork(...)` unless the `experimental.async` compiler option is `true`
106+
103107
## flush_sync_in_effect
104108

105109
> Cannot use `flushSync` inside an effect
@@ -108,6 +112,14 @@ The `flushSync()` function can be used to flush any pending effects synchronousl
108112

109113
This restriction only applies when using the `experimental.async` option, which will be active by default in Svelte 6.
110114

115+
## fork_discarded
116+
117+
> Cannot commit a fork that was already committed or discarded
118+
119+
## fork_timing
120+
121+
> Cannot create a fork inside an effect or when state changes are pending
122+
111123
## get_abort_signal_outside_reaction
112124

113125
> `getAbortSignal()` can only be called inside an effect or derived

packages/svelte/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "svelte",
33
"description": "Cybernetically enhanced web apps",
44
"license": "MIT",
5-
"version": "5.41.1",
5+
"version": "5.41.4",
66
"type": "module",
77
"types": "./types/index.d.ts",
88
"engines": {

packages/svelte/src/compiler/phases/2-analyze/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { walk } from 'zimmerframe';
66
import { parse } from '../1-parse/acorn.js';
77
import * as e from '../../errors.js';
88
import * as w from '../../warnings.js';
9-
import { extract_identifiers } from '../../utils/ast.js';
9+
import { extract_identifiers, has_await_expression } from '../../utils/ast.js';
1010
import * as b from '#compiler/builders';
1111
import { Scope, ScopeRoot, create_scopes, get_rune, set_scope } from '../scope.js';
1212
import check_graph_for_cycles from './utils/check_graph_for_cycles.js';

0 commit comments

Comments
 (0)