diff --git a/.changeset/strange-rocks-beam.md b/.changeset/strange-rocks-beam.md new file mode 100644 index 000000000000..9895a6aa6b98 --- /dev/null +++ b/.changeset/strange-rocks-beam.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure more bindings run without active context diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/shared.js b/packages/svelte/src/internal/client/dom/elements/bindings/shared.js index aa083776a5bc..cf683104f057 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/shared.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/shared.js @@ -12,10 +12,14 @@ import { add_form_reset_listener } from '../misc.js'; * then listens to the given events until the render effect context is destroyed * @param {EventTarget} target * @param {Array} events - * @param {(event?: Event) => void} handler + * @param {(event?: Event) => void} event_handler * @param {any} call_handler_immediately */ -export function listen(target, events, handler, call_handler_immediately = true) { +export function listen(target, events, event_handler, call_handler_immediately = true) { + // Just like user-defined events, our internal events shouldn't have any reactive context + /** @type {typeof event_handler} */ + const handler = (e) => without_reactive_context(() => event_handler(e)); + if (call_handler_immediately) { handler(); } @@ -32,6 +36,9 @@ export function listen(target, events, handler, call_handler_immediately = true) } /** + * Runs a function without a reactive context. + * This is important for events which should "start fresh" and not inherit + * context that accidentally happens to be active at the time of the event. * @template T * @param {() => T} fn */ diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/window.js b/packages/svelte/src/internal/client/dom/elements/bindings/window.js index 2f7e44c5d988..4b8116107760 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/window.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/window.js @@ -62,5 +62,5 @@ export function bind_window_scroll(type, get, set = get) { * @param {(size: number) => void} set */ export function bind_window_size(type, set) { - listen(window, ['resize'], () => without_reactive_context(() => set(window[type]))); + listen(window, ['resize'], () => set(window[type])); } diff --git a/packages/svelte/tests/runtime-runes/samples/effect-tracking-binding-set/_config.js b/packages/svelte/tests/runtime-runes/samples/effect-tracking-binding-set/_config.js index aebbfec832f6..64965e79ec5b 100644 --- a/packages/svelte/tests/runtime-runes/samples/effect-tracking-binding-set/_config.js +++ b/packages/svelte/tests/runtime-runes/samples/effect-tracking-binding-set/_config.js @@ -2,6 +2,6 @@ import { test } from '../../test'; export default test({ test({ assert, logs }) { - assert.deepEqual(logs, [false]); + assert.deepEqual(logs, ['bind:activeElement false', 'bind:value false']); } }); diff --git a/packages/svelte/tests/runtime-runes/samples/effect-tracking-binding-set/main.svelte b/packages/svelte/tests/runtime-runes/samples/effect-tracking-binding-set/main.svelte index f21ecfdce6cb..fd9f12c08e0b 100644 --- a/packages/svelte/tests/runtime-runes/samples/effect-tracking-binding-set/main.svelte +++ b/packages/svelte/tests/runtime-runes/samples/effect-tracking-binding-set/main.svelte @@ -1,24 +1,29 @@ - + +