From 615d233506dfb254b4171bc566ab9a54e800981a Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Fri, 4 Mar 2022 10:30:36 +0100 Subject: [PATCH] fix(multiple): memory leak when forcing focus When we force focus on an element, we were adding a couple of event listeners that were never removed. --- src/cdk-experimental/dialog/dialog-container.ts | 10 ++++++++-- src/material/bottom-sheet/bottom-sheet-container.ts | 10 ++++++++-- src/material/dialog/dialog-container.ts | 10 ++++++++-- src/material/sidenav/drawer.ts | 10 ++++++++-- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/cdk-experimental/dialog/dialog-container.ts b/src/cdk-experimental/dialog/dialog-container.ts index aa7744418b8b..c56745417f37 100644 --- a/src/cdk-experimental/dialog/dialog-container.ts +++ b/src/cdk-experimental/dialog/dialog-container.ts @@ -245,8 +245,14 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy { element.tabIndex = -1; // The tabindex attribute should be removed to avoid navigating to that element again this._ngZone.runOutsideAngular(() => { - element.addEventListener('blur', () => element.removeAttribute('tabindex')); - element.addEventListener('mousedown', () => element.removeAttribute('tabindex')); + const callback = () => { + element.removeEventListener('blur', callback); + element.removeEventListener('mousedown', callback); + element.removeAttribute('tabindex'); + }; + + element.addEventListener('blur', callback); + element.addEventListener('mousedown', callback); }); } element.focus(options); diff --git a/src/material/bottom-sheet/bottom-sheet-container.ts b/src/material/bottom-sheet/bottom-sheet-container.ts index 88ef5a94c9d6..390d63885277 100644 --- a/src/material/bottom-sheet/bottom-sheet-container.ts +++ b/src/material/bottom-sheet/bottom-sheet-container.ts @@ -210,8 +210,14 @@ export class MatBottomSheetContainer extends BasePortalOutlet implements OnDestr element.tabIndex = -1; // The tabindex attribute should be removed to avoid navigating to that element again this._ngZone.runOutsideAngular(() => { - element.addEventListener('blur', () => element.removeAttribute('tabindex')); - element.addEventListener('mousedown', () => element.removeAttribute('tabindex')); + const callback = () => { + element.removeEventListener('blur', callback); + element.removeEventListener('mousedown', callback); + element.removeAttribute('tabindex'); + }; + + element.addEventListener('blur', callback); + element.addEventListener('mousedown', callback); }); } element.focus(options); diff --git a/src/material/dialog/dialog-container.ts b/src/material/dialog/dialog-container.ts index 6dd376913045..23cc6b3519bb 100644 --- a/src/material/dialog/dialog-container.ts +++ b/src/material/dialog/dialog-container.ts @@ -171,8 +171,14 @@ export abstract class _MatDialogContainerBase extends BasePortalOutlet { element.tabIndex = -1; // The tabindex attribute should be removed to avoid navigating to that element again this._ngZone.runOutsideAngular(() => { - element.addEventListener('blur', () => element.removeAttribute('tabindex')); - element.addEventListener('mousedown', () => element.removeAttribute('tabindex')); + const callback = () => { + element.removeEventListener('blur', callback); + element.removeEventListener('mousedown', callback); + element.removeAttribute('tabindex'); + }; + + element.addEventListener('blur', callback); + element.addEventListener('mousedown', callback); }); } element.focus(options); diff --git a/src/material/sidenav/drawer.ts b/src/material/sidenav/drawer.ts index 068c16a8d5eb..f225b20f68ed 100644 --- a/src/material/sidenav/drawer.ts +++ b/src/material/sidenav/drawer.ts @@ -388,8 +388,14 @@ export class MatDrawer implements AfterViewInit, AfterContentChecked, OnDestroy element.tabIndex = -1; // The tabindex attribute should be removed to avoid navigating to that element again this._ngZone.runOutsideAngular(() => { - element.addEventListener('blur', () => element.removeAttribute('tabindex')); - element.addEventListener('mousedown', () => element.removeAttribute('tabindex')); + const callback = () => { + element.removeEventListener('blur', callback); + element.removeEventListener('mousedown', callback); + element.removeAttribute('tabindex'); + }; + + element.addEventListener('blur', callback); + element.addEventListener('mousedown', callback); }); } element.focus(options);