From 085cfc18c82ab5d45f7d09760bb30f07f98af22f Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 21 Nov 2024 10:24:52 +0000 Subject: [PATCH 1/4] fix: ensure spread attribute events are attached synchronously --- .changeset/rich-worms-burn.md | 5 +++++ .../internal/client/dom/elements/attributes.js | 16 +++++----------- .../samples/event-spread-timing/_config.js | 7 +++++++ .../samples/event-spread-timing/main.svelte | 7 +++++++ 4 files changed, 24 insertions(+), 11 deletions(-) create mode 100644 .changeset/rich-worms-burn.md create mode 100644 packages/svelte/tests/runtime-runes/samples/event-spread-timing/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/event-spread-timing/main.svelte diff --git a/.changeset/rich-worms-burn.md b/.changeset/rich-worms-burn.md new file mode 100644 index 000000000000..8ca82f497598 --- /dev/null +++ b/.changeset/rich-worms-burn.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure spread attribute events are attached synchronously diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js index 545cab20f84c..eff953cbed55 100644 --- a/packages/svelte/src/internal/client/dom/elements/attributes.js +++ b/packages/svelte/src/internal/client/dom/elements/attributes.js @@ -13,6 +13,7 @@ import { set_active_effect, set_active_reaction } from '../../runtime.js'; +import { destroy_effect, effect } from '../../reactivity/effects.js'; /** * The value/checked attribute in the template actually corresponds to the defaultValue property, so we need @@ -325,17 +326,10 @@ export function set_attributes( } } - // On the first run, ensure that events are added after bindings so - // that their listeners fire after the binding listeners - if (!prev) { - queue_micro_task(() => { - if (!element.isConnected) return; - for (const [key, value, evt] of events) { - if (current[key] === value) { - evt(); - } - } - }); + for (const [key, value, evt] of events) { + if (current[key] === value) { + evt(); + } } return current; diff --git a/packages/svelte/tests/runtime-runes/samples/event-spread-timing/_config.js b/packages/svelte/tests/runtime-runes/samples/event-spread-timing/_config.js new file mode 100644 index 000000000000..bde384b51b8e --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-spread-timing/_config.js @@ -0,0 +1,7 @@ +import { test } from '../../test'; + +export default test({ + test({ assert, logs }) { + assert.deepEqual(logs, ['onfocus']); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/event-spread-timing/main.svelte b/packages/svelte/tests/runtime-runes/samples/event-spread-timing/main.svelte new file mode 100644 index 000000000000..bb04abce8379 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/event-spread-timing/main.svelte @@ -0,0 +1,7 @@ + + + console.log("onfocus")} use:focus /> From 86e9543e07ae63444b1f34c238ef71cd81c47544 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Thu, 21 Nov 2024 10:26:52 +0000 Subject: [PATCH 2/4] fix: ensure spread attribute events are attached synchronously --- packages/svelte/src/internal/client/dom/elements/attributes.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js index eff953cbed55..bfb7e15a3f0f 100644 --- a/packages/svelte/src/internal/client/dom/elements/attributes.js +++ b/packages/svelte/src/internal/client/dom/elements/attributes.js @@ -5,7 +5,7 @@ import { create_event, delegate } from './events.js'; import { add_form_reset_listener, autofocus } from './misc.js'; import * as w from '../../warnings.js'; import { LOADING_ATTR_SYMBOL } from '../../constants.js'; -import { queue_idle_task, queue_micro_task } from '../task.js'; +import { queue_idle_task } from '../task.js'; import { is_capture_event, is_delegated, normalize_attribute } from '../../../../utils.js'; import { active_effect, @@ -13,7 +13,6 @@ import { set_active_effect, set_active_reaction } from '../../runtime.js'; -import { destroy_effect, effect } from '../../reactivity/effects.js'; /** * The value/checked attribute in the template actually corresponds to the defaultValue property, so we need From d50c994b2a9e2c0b4003b8af7c13705282a4e7f8 Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:53:46 +0100 Subject: [PATCH 3/4] Update .changeset/rich-worms-burn.md Co-authored-by: Rich Harris --- .changeset/rich-worms-burn.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/rich-worms-burn.md b/.changeset/rich-worms-burn.md index 8ca82f497598..8ec3af516abe 100644 --- a/.changeset/rich-worms-burn.md +++ b/.changeset/rich-worms-burn.md @@ -2,4 +2,4 @@ 'svelte': patch --- -fix: ensure spread attribute events are attached synchronously +fix: attach spread attribute events synchronously From 33b54348cc17fdcaeeb06c36526893537e4ed4ed Mon Sep 17 00:00:00 2001 From: Simon H <5968653+dummdidumm@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:57:18 +0100 Subject: [PATCH 4/4] simplify --- .../internal/client/dom/elements/attributes.js | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js index bfb7e15a3f0f..d927af543ff2 100644 --- a/packages/svelte/src/internal/client/dom/elements/attributes.js +++ b/packages/svelte/src/internal/client/dom/elements/attributes.js @@ -209,8 +209,6 @@ export function set_attributes( // @ts-expect-error var attributes = /** @type {Record} **/ (element.__attributes ??= {}); - /** @type {Array<[string, any, () => void]>} */ - var events = []; // since key is captured we use const for (const key in next) { @@ -277,15 +275,7 @@ export function set_attributes( current[key].call(this, evt); } - if (!prev) { - events.push([ - key, - value, - () => (current[event_handle_key] = create_event(event_name, element, handle, opts)) - ]); - } else { - current[event_handle_key] = create_event(event_name, element, handle, opts); - } + current[event_handle_key] = create_event(event_name, element, handle, opts); } else { // @ts-ignore element[`__${event_name}`] = value; @@ -325,12 +315,6 @@ export function set_attributes( } } - for (const [key, value, evt] of events) { - if (current[key] === value) { - evt(); - } - } - return current; }