From 51baf1c1af4f02e2a8b009a87d932437f164b612 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 4 Jun 2026 22:28:18 +0200 Subject: [PATCH 1/4] Version Packages (#18357) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## svelte@5.56.2 ### Patch Changes - fix: properly track effect end node for async sibling component ([#18371](https://github.com/sveltejs/svelte/pull/18371)) - fix: prevent false-positive reactivity loss warning ([#18373](https://github.com/sveltejs/svelte/pull/18373)) - chore: bump esrap dependency ([#18372](https://github.com/sveltejs/svelte/pull/18372)) - fix: ignore declaration tags for animation directive ([#18366](https://github.com/sveltejs/svelte/pull/18366)) - fix: reject pending async deriveds on discard ([#18308](https://github.com/sveltejs/svelte/pull/18308)) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/async-hydration-orphan-nodes.md | 5 ----- .changeset/rare-donkeys-repair.md | 5 ----- .changeset/soft-moments-exist.md | 5 ----- .changeset/tangy-keys-drop.md | 5 ----- .changeset/warm-cougars-behave.md | 5 ----- packages/svelte/CHANGELOG.md | 14 ++++++++++++++ packages/svelte/package.json | 2 +- packages/svelte/src/version.js | 2 +- 8 files changed, 16 insertions(+), 27 deletions(-) delete mode 100644 .changeset/async-hydration-orphan-nodes.md delete mode 100644 .changeset/rare-donkeys-repair.md delete mode 100644 .changeset/soft-moments-exist.md delete mode 100644 .changeset/tangy-keys-drop.md delete mode 100644 .changeset/warm-cougars-behave.md diff --git a/.changeset/async-hydration-orphan-nodes.md b/.changeset/async-hydration-orphan-nodes.md deleted file mode 100644 index 4c35d6b74e..0000000000 --- a/.changeset/async-hydration-orphan-nodes.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: properly track effect end node for async sibling component \ No newline at end of file diff --git a/.changeset/rare-donkeys-repair.md b/.changeset/rare-donkeys-repair.md deleted file mode 100644 index bd22c564db..0000000000 --- a/.changeset/rare-donkeys-repair.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: prevent false-positive reactivity loss warning diff --git a/.changeset/soft-moments-exist.md b/.changeset/soft-moments-exist.md deleted file mode 100644 index 71a3148afa..0000000000 --- a/.changeset/soft-moments-exist.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -chore: bump esrap dependency diff --git a/.changeset/tangy-keys-drop.md b/.changeset/tangy-keys-drop.md deleted file mode 100644 index 38f0c10543..0000000000 --- a/.changeset/tangy-keys-drop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: ignore declaration tags for animation directive diff --git a/.changeset/warm-cougars-behave.md b/.changeset/warm-cougars-behave.md deleted file mode 100644 index 15e32f7436..0000000000 --- a/.changeset/warm-cougars-behave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'svelte': patch ---- - -fix: reject pending async deriveds on discard diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index a8a94bc691..6d36f7b456 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,19 @@ # svelte +## 5.56.2 + +### Patch Changes + +- fix: properly track effect end node for async sibling component ([#18371](https://github.com/sveltejs/svelte/pull/18371)) + +- fix: prevent false-positive reactivity loss warning ([#18373](https://github.com/sveltejs/svelte/pull/18373)) + +- chore: bump esrap dependency ([#18372](https://github.com/sveltejs/svelte/pull/18372)) + +- fix: ignore declaration tags for animation directive ([#18366](https://github.com/sveltejs/svelte/pull/18366)) + +- fix: reject pending async deriveds on discard ([#18308](https://github.com/sveltejs/svelte/pull/18308)) + ## 5.56.1 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 45bb45c695..a098b2689f 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -2,7 +2,7 @@ "name": "svelte", "description": "Cybernetically enhanced web apps", "license": "MIT", - "version": "5.56.1", + "version": "5.56.2", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index 210d48461e..94d9a26dd9 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -4,5 +4,5 @@ * The current version, as set in package.json. * @type {string} */ -export const VERSION = '5.56.1'; +export const VERSION = '5.56.2'; export const PUBLIC_VERSION = '5'; From 3d83c9abe606415c2ceee215c76582ea9bcfa7b1 Mon Sep 17 00:00:00 2001 From: sijie-Z <1683039482@qq.com> Date: Fri, 5 Jun 2026 21:35:31 +0800 Subject: [PATCH 2/4] fix: add bigint to Primitive type for $state.snapshot (#18388) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes #18385 ## Problem `$state.snapshot` infers BigInt properties as `never` because `bigint` is missing from the `Primitive` type definition. BigInt is a valid JavaScript primitive and is supported by `structuredClone`. ## Solution Added `bigint` to the `Primitive` type in both `packages/svelte/src/ambient.d.ts` and `packages/svelte/types/index.d.ts`. ## Before ```ts const object = $state({ number: 1n }); const snapshot = $state.snapshot(object); // snapshot.number is inferred as never ❌ After const object = $state({ number: 1n }); const snapshot = $state.snapshot(object); // snapshot.number is correctly inferred as bigint ✅ Tests and linting - [x] This is a type-only change, no runtime behavior affected --------- Co-authored-by: Rich Harris --- .changeset/some-parts-watch.md | 5 +++++ packages/svelte/src/ambient.d.ts | 2 +- packages/svelte/types/index.d.ts | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/some-parts-watch.md diff --git a/.changeset/some-parts-watch.md b/.changeset/some-parts-watch.md new file mode 100644 index 0000000000..7d19a32f22 --- /dev/null +++ b/.changeset/some-parts-watch.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: type BigInts in `$state.snapshot(...)` return values diff --git a/packages/svelte/src/ambient.d.ts b/packages/svelte/src/ambient.d.ts index bbbc86c997..ed0a004fa1 100644 --- a/packages/svelte/src/ambient.d.ts +++ b/packages/svelte/src/ambient.d.ts @@ -24,7 +24,7 @@ declare function $state(initial: T): T; declare function $state(): T | undefined; declare namespace $state { - type Primitive = string | number | boolean | null | undefined; + type Primitive = string | number | bigint | boolean | null | undefined; type TypedArray = | Int8Array diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 1c3795be80..5f41fabf60 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -3229,7 +3229,7 @@ declare function $state(initial: T): T; declare function $state(): T | undefined; declare namespace $state { - type Primitive = string | number | boolean | null | undefined; + type Primitive = string | number | bigint | boolean | null | undefined; type TypedArray = | Int8Array From 71a6515bd648202b2795a80e68e7c9c7ac9ad4ee Mon Sep 17 00:00:00 2001 From: sijie-Z <1683039482@qq.com> Date: Sat, 6 Jun 2026 03:17:49 +0800 Subject: [PATCH 3/4] fix: check boundary exists before calling error handler in async derived (#18384) fixes #18383 I traced the issue to `packages/svelte/src/internal/client/error-handling.js`, specifically the `invoke_error_boundary` function. The problem is at line 56 where `effect.b.error(error)` is called without checking if `effect.b` exists. What happens is: when an async `$derived` rejects inside a ``, the error is handled correctly the first time. But if the boundary is destroyed before the rejection fully settles (e.g. component unmounts), a subsequent settle tries to call `effect.b.error()` on a destroyed boundary where `effect.b` is `null`, causing a `TypeError`. The fix adds a null check for `effect.b` before calling `error()`. If the boundary has been destroyed, we skip it and continue bubbling up to the parent boundary. This way the error still gets handled properly instead of crashing. This could also be tested by creating a component with an async `$derived` that rejects after the component unmounts, but I wanted to get the fix up first for review. --------- Co-authored-by: Rich Harris --- .changeset/fix-boundary-null.md | 5 ++++ .../src/internal/client/error-handling.js | 6 ++++- packages/svelte/src/internal/client/index.js | 1 - .../async-error-boundary-4/Child.svelte | 6 +++++ .../samples/async-error-boundary-4/_config.js | 13 +++++++++ .../async-error-boundary-4/main.svelte | 27 +++++++++++++++++++ 6 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 .changeset/fix-boundary-null.md create mode 100644 packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/Child.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/main.svelte diff --git a/.changeset/fix-boundary-null.md b/.changeset/fix-boundary-null.md new file mode 100644 index 0000000000..c87a47ce34 --- /dev/null +++ b/.changeset/fix-boundary-null.md @@ -0,0 +1,5 @@ +--- +"svelte": patch +--- + +fix: ignore errors that occur in destroyed effects diff --git a/packages/svelte/src/internal/client/error-handling.js b/packages/svelte/src/internal/client/error-handling.js index 5d16759266..7c404dd933 100644 --- a/packages/svelte/src/internal/client/error-handling.js +++ b/packages/svelte/src/internal/client/error-handling.js @@ -3,7 +3,7 @@ import { DEV } from 'esm-env'; import { FILENAME } from '../../constants.js'; import { is_firefox } from './dom/operations.js'; -import { ERROR_VALUE, BOUNDARY_EFFECT, REACTION_RAN, EFFECT } from './constants.js'; +import { ERROR_VALUE, BOUNDARY_EFFECT, REACTION_RAN, EFFECT, DESTROYED } from './constants.js'; import { define_property, get_descriptor } from '../shared/utils.js'; import { active_effect, active_reaction } from './runtime.js'; @@ -45,6 +45,10 @@ export function handle_error(error) { * @param {Effect | null} effect */ export function invoke_error_boundary(error, effect) { + if (effect !== null && (effect.f & DESTROYED) !== 0) { + return; + } + while (effect !== null) { if ((effect.f & BOUNDARY_EFFECT) !== 0) { if ((effect.f & REACTION_RAN) === 0) { diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js index 988998d067..fa6f9dda39 100644 --- a/packages/svelte/src/internal/client/index.js +++ b/packages/svelte/src/internal/client/index.js @@ -180,4 +180,3 @@ export { } from '../shared/validate.js'; export { strict_equals, equals } from './dev/equality.js'; export { log_if_contains_state } from './dev/console-log.js'; -export { invoke_error_boundary } from './error-handling.js'; diff --git a/packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/Child.svelte b/packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/Child.svelte new file mode 100644 index 0000000000..8bfc51bb7a --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/Child.svelte @@ -0,0 +1,6 @@ + + +

{model.title}

diff --git a/packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/_config.js b/packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/_config.js new file mode 100644 index 0000000000..a3cda2f865 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/_config.js @@ -0,0 +1,13 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, target }) { + const [button] = target.querySelectorAll('button'); + + button.click(); + await tick(); + + assert.htmlEqual(target.innerHTML, '

error was contained

'); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/main.svelte new file mode 100644 index 0000000000..3b5f51742a --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-error-boundary-4/main.svelte @@ -0,0 +1,27 @@ + + + + + + {#if open} + + + + {#snippet pending()} +

loading…

+ {/snippet} + + {#snippet failed()} +

error was contained

+ {/snippet} +
+ {/if} + + {#snippet failed()} +

error escaped containment

+ {/snippet} +
From a9f48540e236d326714a1148b9d61cf785c0f98a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 7 Jun 2026 14:25:58 -0400 Subject: [PATCH 4/4] Version Packages (#18389) This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## svelte@5.56.3 ### Patch Changes - fix: ignore errors that occur in destroyed effects ([#18384](https://github.com/sveltejs/svelte/pull/18384)) - fix: type BigInts in `$state.snapshot(...)` return values ([#18388](https://github.com/sveltejs/svelte/pull/18388)) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- .changeset/fix-boundary-null.md | 5 ----- .changeset/some-parts-watch.md | 5 ----- packages/svelte/CHANGELOG.md | 8 ++++++++ packages/svelte/package.json | 2 +- packages/svelte/src/version.js | 2 +- 5 files changed, 10 insertions(+), 12 deletions(-) delete mode 100644 .changeset/fix-boundary-null.md delete mode 100644 .changeset/some-parts-watch.md diff --git a/.changeset/fix-boundary-null.md b/.changeset/fix-boundary-null.md deleted file mode 100644 index c87a47ce34..0000000000 --- a/.changeset/fix-boundary-null.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"svelte": patch ---- - -fix: ignore errors that occur in destroyed effects diff --git a/.changeset/some-parts-watch.md b/.changeset/some-parts-watch.md deleted file mode 100644 index 7d19a32f22..0000000000 --- a/.changeset/some-parts-watch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"svelte": patch ---- - -fix: type BigInts in `$state.snapshot(...)` return values diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md index 6d36f7b456..02dd84ddff 100644 --- a/packages/svelte/CHANGELOG.md +++ b/packages/svelte/CHANGELOG.md @@ -1,5 +1,13 @@ # svelte +## 5.56.3 + +### Patch Changes + +- fix: ignore errors that occur in destroyed effects ([#18384](https://github.com/sveltejs/svelte/pull/18384)) + +- fix: type BigInts in `$state.snapshot(...)` return values ([#18388](https://github.com/sveltejs/svelte/pull/18388)) + ## 5.56.2 ### Patch Changes diff --git a/packages/svelte/package.json b/packages/svelte/package.json index a098b2689f..6bca1bd4a8 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -2,7 +2,7 @@ "name": "svelte", "description": "Cybernetically enhanced web apps", "license": "MIT", - "version": "5.56.2", + "version": "5.56.3", "type": "module", "types": "./types/index.d.ts", "engines": { diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js index 94d9a26dd9..b6d4236ff8 100644 --- a/packages/svelte/src/version.js +++ b/packages/svelte/src/version.js @@ -4,5 +4,5 @@ * The current version, as set in package.json. * @type {string} */ -export const VERSION = '5.56.2'; +export const VERSION = '5.56.3'; export const PUBLIC_VERSION = '5';