55 * Use of this source code is governed by an MIT-style license that can be
66 * found in the LICENSE file at https://angular.io/license
77 */
8-
98import { Platform , supportsPassiveEventListeners } from '@angular/cdk/platform' ;
109import {
1110 Directive ,
@@ -56,7 +55,13 @@ export class FocusMonitor implements OnDestroy {
5655 private _lastTouchTarget : EventTarget | null ;
5756
5857 /** The timeout id of the touch timeout, used to cancel timeout later. */
59- private _touchTimeout : number ;
58+ private _touchTimeoutId : number ;
59+
60+ /** The timeout id of the window focus timeout. */
61+ private _windowFocusTimeoutId : number ;
62+
63+ /** The timeout id of the origin clearing timeout. */
64+ private _originTimeoutId : number ;
6065
6166 /** Map of elements being monitored to their info. */
6267 private _elementInfo = new Map < HTMLElement , MonitoredElementInfo > ( ) ;
@@ -187,18 +192,18 @@ export class FocusMonitor implements OnDestroy {
187192 // we can't rely on the trick used above (setting timeout of 0ms). Instead we wait 650ms to
188193 // see if a focus happens.
189194 let documentTouchstartListener = ( event : TouchEvent ) => {
190- if ( this . _touchTimeout != null ) {
191- clearTimeout ( this . _touchTimeout ) ;
195+ if ( this . _touchTimeoutId != null ) {
196+ clearTimeout ( this . _touchTimeoutId ) ;
192197 }
193198 this . _lastTouchTarget = event . target ;
194- this . _touchTimeout = setTimeout ( ( ) => this . _lastTouchTarget = null , TOUCH_BUFFER_MS ) ;
199+ this . _touchTimeoutId = setTimeout ( ( ) => this . _lastTouchTarget = null , TOUCH_BUFFER_MS ) ;
195200 } ;
196201
197202 // Make a note of when the window regains focus, so we can restore the origin info for the
198203 // focused element.
199204 let windowFocusListener = ( ) => {
200205 this . _windowFocused = true ;
201- setTimeout ( ( ) => this . _windowFocused = false , 0 ) ;
206+ this . _windowFocusTimeoutId = setTimeout ( ( ) => this . _windowFocused = false , 0 ) ;
202207 } ;
203208
204209 // Note: we listen to events in the capture phase so we can detect them even if the user stops
@@ -217,6 +222,11 @@ export class FocusMonitor implements OnDestroy {
217222 document . removeEventListener ( 'touchstart' , documentTouchstartListener ,
218223 supportsPassiveEventListeners ( ) ? ( { passive : true , capture : true } as any ) : true ) ;
219224 window . removeEventListener ( 'focus' , windowFocusListener ) ;
225+
226+ // Clear timeouts for all potentially pending timeouts to prevent the leaks.
227+ clearTimeout ( this . _windowFocusTimeoutId ) ;
228+ clearTimeout ( this . _touchTimeoutId ) ;
229+ clearTimeout ( this . _originTimeoutId ) ;
220230 } ;
221231 }
222232
@@ -251,7 +261,7 @@ export class FocusMonitor implements OnDestroy {
251261 */
252262 private _setOriginForCurrentEventQueue ( origin : FocusOrigin ) : void {
253263 this . _origin = origin ;
254- setTimeout ( ( ) => this . _origin = null , 0 ) ;
264+ this . _originTimeoutId = setTimeout ( ( ) => this . _origin = null , 0 ) ;
255265 }
256266
257267 /**
0 commit comments