diff --git a/.changeset/big-months-shout.md b/.changeset/big-months-shout.md
deleted file mode 100644
index 3d8ca0045e..0000000000
--- a/.changeset/big-months-shout.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-chore: drop dead code that make TSGO fail
diff --git a/.changeset/common-ways-deny.md b/.changeset/common-ways-deny.md
deleted file mode 100644
index 75e9375965..0000000000
--- a/.changeset/common-ways-deny.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: don't (re)connect deriveds when read inside branch/root effects
diff --git a/.changeset/curly-wasps-hide.md b/.changeset/curly-wasps-hide.md
deleted file mode 100644
index 7e55d77ba0..0000000000
--- a/.changeset/curly-wasps-hide.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: skip unnecessary derived effect in earlier batch
diff --git a/.changeset/dull-oranges-fry.md b/.changeset/dull-oranges-fry.md
deleted file mode 100644
index 0efcc6fa2d..0000000000
--- a/.changeset/dull-oranges-fry.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: avoid declaration tag warning in event handlers
diff --git a/.changeset/rich-jokes-attack.md b/.changeset/rich-jokes-attack.md
deleted file mode 100644
index 46e7d2d8c8..0000000000
--- a/.changeset/rich-jokes-attack.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: correctly transform declaration tags during SSR
diff --git a/.changeset/shiny-keys-dance.md b/.changeset/shiny-keys-dance.md
deleted file mode 100644
index 20cf754212..0000000000
--- a/.changeset/shiny-keys-dance.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: transform computed keys in keyed `{#each}` destructuring patterns
diff --git a/.changeset/tame-donkeys-jump.md b/.changeset/tame-donkeys-jump.md
deleted file mode 100644
index aae38910db..0000000000
--- a/.changeset/tame-donkeys-jump.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: chain preprocessor sourcemaps with an empty `sources[0]` instead of dropping them
diff --git a/.changeset/young-doodles-beam.md b/.changeset/young-doodles-beam.md
deleted file mode 100644
index b68f55d241..0000000000
--- a/.changeset/young-doodles-beam.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-'svelte': patch
----
-
-fix: don't treat declaration tags as parts inside each blocks
diff --git a/packages/svelte/CHANGELOG.md b/packages/svelte/CHANGELOG.md
index 80b61facb0..0f26b571d3 100644
--- a/packages/svelte/CHANGELOG.md
+++ b/packages/svelte/CHANGELOG.md
@@ -1,5 +1,39 @@
# svelte
+## 5.56.6
+
+### Patch Changes
+
+- perf: skip unnecessary blocker analysis when compiling components without top-level await ([#18548](https://github.com/sveltejs/svelte/pull/18548))
+
+- fix: rerun derived that had an abort controller on reconnection ([#18551](https://github.com/sveltejs/svelte/pull/18551))
+
+## 5.56.5
+
+### Patch Changes
+
+- chore: drop dead code that make TSGO fail ([#18496](https://github.com/sveltejs/svelte/pull/18496))
+
+- fix: don't (re)connect deriveds when read inside branch/root effects ([#18527](https://github.com/sveltejs/svelte/pull/18527))
+
+- fix: skip unnecessary derived effect in earlier batch ([#18525](https://github.com/sveltejs/svelte/pull/18525))
+
+- fix: avoid declaration tag warning in event handlers ([#18500](https://github.com/sveltejs/svelte/pull/18500))
+
+- fix: abort deriveds own AbortSignal when it disconnects ([#18400](https://github.com/sveltejs/svelte/pull/18400))
+
+- fix: ensure `$state.eager()` is correctly transormed for SSR output ([#18530](https://github.com/sveltejs/svelte/pull/18530))
+
+- fix: correctly transform declaration tags during SSR ([#18492](https://github.com/sveltejs/svelte/pull/18492))
+
+- fix: transform computed keys in keyed `{#each}` destructuring patterns ([#18521](https://github.com/sveltejs/svelte/pull/18521))
+
+- fix: chain preprocessor sourcemaps with an empty `sources[0]` instead of dropping them ([#18518](https://github.com/sveltejs/svelte/pull/18518))
+
+- fix: clear previous_task reference after abort in Tween to prevent memory leak on interrupted tweens ([#18541](https://github.com/sveltejs/svelte/pull/18541))
+
+- fix: don't treat declaration tags as parts inside each blocks ([#18507](https://github.com/sveltejs/svelte/pull/18507))
+
## 5.56.4
### Patch Changes
diff --git a/packages/svelte/package.json b/packages/svelte/package.json
index 34fa68c8a7..855ba92a8d 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.4",
+ "version": "5.56.6",
"type": "module",
"types": "./types/index.d.ts",
"engines": {
diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js
index ef20049697..67e9030188 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/index.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/index.js
@@ -1221,6 +1221,10 @@ function calculate_blockers(instance, analysis) {
}
}
+ // With no top-level await, no binding can have a blocker and function tracing
+ // cannot affect the output.
+ if (!awaited) return;
+
flush_sync_group();
for (const fn of functions) {
diff --git a/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js b/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js
index 8525fb6366..ac78f55da9 100644
--- a/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js
+++ b/packages/svelte/src/compiler/phases/3-transform/server/visitors/CallExpression.js
@@ -46,7 +46,7 @@ export function CallExpression(node, context) {
}
if (rune === '$state.eager') {
- return node.arguments[0];
+ return context.visit(node.arguments[0]);
}
if (rune === '$state.snapshot') {
diff --git a/packages/svelte/src/internal/client/reactivity/deriveds.js b/packages/svelte/src/internal/client/reactivity/deriveds.js
index 7f4a31d39d..e4488f89df 100644
--- a/packages/svelte/src/internal/client/reactivity/deriveds.js
+++ b/packages/svelte/src/internal/client/reactivity/deriveds.js
@@ -27,6 +27,7 @@ import {
skipped_deps,
new_deps
} from '../runtime.js';
+import { without_reactive_context } from '../dom/elements/bindings/shared.js';
import { equals, safe_equals } from './equality.js';
import * as e from '../errors.js';
import * as w from '../warnings.js';
@@ -454,14 +455,18 @@ export function freeze_derived_effects(derived) {
// if the effect has a teardown function or abort signal, call it
if (e.teardown || e.ac) {
e.teardown?.();
- e.ac?.abort(STALE_REACTION);
+ if (e.ac !== null) {
+ without_reactive_context(() => {
+ /** @type {AbortController} */ (e.ac).abort(STALE_REACTION);
+ e.ac = null;
+ });
+ }
// make it a noop so it doesn't get called again if the derived
// is unfrozen. we don't set it to `null`, because the existence
// of a teardown function is what determines whether the
// effect runs again during unfreezing (but not for teardown-only effects)
if (e.fn !== null) e.teardown = noop;
- e.ac = null;
remove_reactions(e, 0);
destroy_effect_children(e);
diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js
index fc5d3d80b6..ac7383d866 100644
--- a/packages/svelte/src/internal/client/runtime.js
+++ b/packages/svelte/src/internal/client/runtime.js
@@ -424,6 +424,16 @@ function remove_reaction(signal, dependency) {
update_derived_status(derived);
}
+ // Call abort controller, noone's listening to this derived anymore
+ if (derived.ac !== null) {
+ without_reactive_context(() => {
+ /** @type {AbortController} */ (derived.ac).abort(STALE_REACTION);
+ derived.ac = null;
+ // ensure it reruns right away next time instead of potentially returning a rejected promise as its value
+ set_signal_status(derived, DIRTY);
+ });
+ }
+
// freeze any effects inside this derived
freeze_derived_effects(derived);
diff --git a/packages/svelte/src/motion/tweened.js b/packages/svelte/src/motion/tweened.js
index a24148d075..460db0df64 100644
--- a/packages/svelte/src/motion/tweened.js
+++ b/packages/svelte/src/motion/tweened.js
@@ -275,6 +275,7 @@ export class Tween {
}
previous_task?.abort();
+ previous_task = null;
}
const elapsed = now - start;
diff --git a/packages/svelte/src/version.js b/packages/svelte/src/version.js
index ef468a2f79..05d88ef904 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.4';
+export const VERSION = '5.56.6';
export const PUBLIC_VERSION = '5';
diff --git a/packages/svelte/tests/runtime-runes/samples/abort-signal-derived-destroy/Child.svelte b/packages/svelte/tests/runtime-runes/samples/abort-signal-derived-destroy/Child.svelte
new file mode 100644
index 0000000000..5a837e5ea4
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/abort-signal-derived-destroy/Child.svelte
@@ -0,0 +1,20 @@
+
+
+{der}
diff --git a/packages/svelte/tests/runtime-runes/samples/abort-signal-derived-destroy/_config.js b/packages/svelte/tests/runtime-runes/samples/abort-signal-derived-destroy/_config.js
new file mode 100644
index 0000000000..3c6ec98fe6
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/abort-signal-derived-destroy/_config.js
@@ -0,0 +1,14 @@
+import { ok, test } from '../../test';
+import { flushSync } from 'svelte';
+
+export default test({
+ async test({ assert, target, errors }) {
+ const btn = target.querySelector('button');
+
+ flushSync(() => {
+ btn?.click();
+ });
+ assert.htmlEqual(target.innerHTML, '1 ');
+ assert.deepEqual(errors, []);
+ }
+});
diff --git a/packages/svelte/tests/runtime-runes/samples/abort-signal-derived-destroy/main.svelte b/packages/svelte/tests/runtime-runes/samples/abort-signal-derived-destroy/main.svelte
new file mode 100644
index 0000000000..57c467a80c
--- /dev/null
+++ b/packages/svelte/tests/runtime-runes/samples/abort-signal-derived-destroy/main.svelte
@@ -0,0 +1,14 @@
+
+
+{aborted}
+
+
+
+{#if count % 2 === 0}
+
{await push(a)} {await push(b)} {d}
diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-not-overfiring/_config.js b/packages/svelte/tests/runtime-runes/samples/async-derived-not-overfiring/_config.js new file mode 100644 index 0000000000..b959ba5407 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-derived-not-overfiring/_config.js @@ -0,0 +1,35 @@ +import { tick } from 'svelte'; +import { test } from '../../test'; + +export default test({ + skip: true, // TODO fix + async test({ assert, target, logs }) { + await tick(); + + const [a, b, log, resolve] = target.querySelectorAll('button'); + const [div] = target.querySelectorAll('div'); + + assert.deepEqual(logs, ['e1 0', 'e2 0']); + logs.length = 0; + + a.click(); + await tick(); + assert.htmlEqual(div.innerHTML, '0
0
0
'); + + b.click(); + await tick(); + assert.htmlEqual(div.innerHTML, '0
1
1
'); + + log.click(); + await tick(); + assert.deepEqual(logs, ['e1 1', 'e2 1', 'runs 2']); // ideally it's only 2 runs, one or two more would also be acceptable but not the 8 that it's today + logs.length = 0; + + resolve.click(); + await tick(); + log.click(); + await tick(); + assert.htmlEqual(div.innerHTML, '1
2
2
'); + assert.deepEqual(logs, ['e1 2', 'e2 2', 'runs 3']); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/async-derived-not-overfiring/main.svelte b/packages/svelte/tests/runtime-runes/samples/async-derived-not-overfiring/main.svelte new file mode 100644 index 0000000000..784932ab5d --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/async-derived-not-overfiring/main.svelte @@ -0,0 +1,29 @@ + + + + + + + +{await push(a)}
+{d}
+{d}
+{await push(d)} {b}
diff --git a/packages/svelte/tests/server-side-rendering/samples/state-eager/_expected.html b/packages/svelte/tests/server-side-rendering/samples/state-eager/_expected.html new file mode 100644 index 0000000000..9d3ea2f5b4 --- /dev/null +++ b/packages/svelte/tests/server-side-rendering/samples/state-eager/_expected.html @@ -0,0 +1,2 @@ +