diff --git a/.changeset/seven-dancers-brush.md b/.changeset/seven-dancers-brush.md new file mode 100644 index 000000000000..8f0bcd694005 --- /dev/null +++ b/.changeset/seven-dancers-brush.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: avoid chromium issue with dispatching blur on element removal diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 73286861d2b5..d044b79efc3c 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -16,7 +16,8 @@ import { set_is_destroying_effect, set_is_flushing_effect, set_signal_status, - untrack + untrack, + set_active_effect } from '../runtime.js'; import { DIRTY, @@ -375,13 +376,26 @@ export function destroy_effect(effect, remove_dom = true) { /** @type {TemplateNode | null} */ var node = effect.nodes_start; var end = effect.nodes_end; + var previous_reaction = active_reaction; + var previous_effect = active_effect; - while (node !== null) { - /** @type {TemplateNode | null} */ - var next = node === end ? null : /** @type {TemplateNode} */ (get_next_sibling(node)); + // Really we only need to do this in Chromium because of https://chromestatus.com/feature/5128696823545856, + // as removal of the DOM can cause sync `blur` events to fire, which can cause logic to run inside + // the current `active_reaction`, which isn't what we want at all. Additionally, the blur event handler + // might create a derived or effect and they will be incorrectly attached to the wrong thing + set_active_reaction(null); + set_active_effect(null); + try { + while (node !== null) { + /** @type {TemplateNode | null} */ + var next = node === end ? null : /** @type {TemplateNode} */ (get_next_sibling(node)); - node.remove(); - node = next; + node.remove(); + node = next; + } + } finally { + set_active_reaction(previous_reaction); + set_active_effect(previous_effect); } removed = true;