From 66359d58156122855812c99f9ac8590bfe7a90dc Mon Sep 17 00:00:00 2001 From: "7. Sun" Date: Thu, 29 Jan 2026 16:50:25 +0000 Subject: [PATCH] fix: clean up all event listeners in +layout.svelte onMount (#20913) Extract anonymous touch event handlers into named functions and add proper cleanup for all event listeners (message, touchstart, touchmove, touchend, visibilitychange) in the onMount return function. Previously only the resize listener was being cleaned up, causing memory leaks during navigation and hot-reloads. --- src/routes/+layout.svelte | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 25c14101c..a1a7adfa8 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -629,12 +629,12 @@ return nav && (el === nav || nav.contains(el)); } - document.addEventListener('touchstart', (e) => { + const touchstartHandler = (e) => { if (!isNavOrDescendant(e.target)) return; touchstartY = e.touches[0].clientY; - }); + }; - document.addEventListener('touchmove', (e) => { + const touchmoveHandler = (e) => { if (!isNavOrDescendant(e.target)) return; const touchY = e.touches[0].clientY; const touchDiff = touchY - touchstartY; @@ -642,15 +642,19 @@ showRefresh = true; e.preventDefault(); } - }); + }; - document.addEventListener('touchend', (e) => { + const touchendHandler = (e) => { if (!isNavOrDescendant(e.target)) return; if (showRefresh) { showRefresh = false; location.reload(); } - }); + }; + + document.addEventListener('touchstart', touchstartHandler); + document.addEventListener('touchmove', touchmoveHandler, { passive: false }); + document.addEventListener('touchend', touchendHandler); if (typeof window !== 'undefined') { if (window.applyTheme) { @@ -842,11 +846,15 @@ return () => { window.removeEventListener('resize', onResize); + window.removeEventListener('message', windowMessageEventHandler); + document.removeEventListener('touchstart', touchstartHandler); + document.removeEventListener('touchmove', touchmoveHandler); + document.removeEventListener('touchend', touchendHandler); + document.removeEventListener('visibilitychange', handleVisibilityChange); }; }); onDestroy(() => { - window.removeEventListener('message', windowMessageEventHandler); bc.close(); });