From bb491f12294a874995f8b75a82d11d53e30d34d5 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Sat, 19 Oct 2024 13:12:45 +0100 Subject: [PATCH] fix: avoid chromium issue with dispatching blur on element removal (#13694) * fix: avoid chromium issue with dispatching blur on element removal * fix: avoid chromium issue with dispatching blur on element removal * fix: avoid chromium issue with dispatching blur on element removal * active effect too * try/finally --- .changeset/seven-dancers-brush.md | 5 ++++ .../src/internal/client/reactivity/effects.js | 26 ++++++++++++++----- 2 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 .changeset/seven-dancers-brush.md diff --git a/.changeset/seven-dancers-brush.md b/.changeset/seven-dancers-brush.md new file mode 100644 index 0000000000..8f0bcd6940 --- /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 73286861d2..d044b79efc 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;