Skip to content

fix(google-maps): avoid event listener leaks if inputs change #17664

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions src/google-maps/google-map/google-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {

private _googleMapChanges!: Observable<google.maps.Map>;

private readonly _listeners: google.maps.MapsEventListener[] = [];
private _listeners: google.maps.MapsEventListener[] = [];

private readonly _options = new BehaviorSubject<google.maps.MapOptions>(DEFAULT_OPTIONS);
private readonly _center =
Expand Down Expand Up @@ -235,9 +235,7 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
ngOnDestroy() {
this._destroy.next();
this._destroy.complete();
for (let listener of this._listeners) {
listener.remove();
}
this._clearListeners();
}

/**
Expand Down Expand Up @@ -438,6 +436,9 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
}

private _initializeEventHandlers() {
// Ensure that we don't leak if called multiple times.
this._clearListeners();

const eventHandlers = new Map<string, EventEmitter<void>>([
['bounds_changed', this.boundsChanged],
['center_changed', this.centerChanged],
Expand Down Expand Up @@ -482,4 +483,13 @@ export class GoogleMap implements OnChanges, OnInit, OnDestroy {
}));
}
}

/** Clears all currently-registered event listeners. */
private _clearListeners() {
for (let listener of this._listeners) {
listener.remove();
}

this._listeners = [];
}
}
14 changes: 13 additions & 1 deletion src/google-maps/map-info-window/map-info-window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export class MapInfoWindow implements OnInit, OnDestroy {
private readonly _position =
new BehaviorSubject<google.maps.LatLngLiteral|google.maps.LatLng|undefined>(undefined);

private readonly _listeners: google.maps.MapsEventListener[] = [];
private _listeners: google.maps.MapsEventListener[] = [];

private readonly _destroy = new Subject<void>();

Expand Down Expand Up @@ -167,6 +167,9 @@ export class MapInfoWindow implements OnInit, OnDestroy {
}

private _initializeEventHandlers() {
// Ensure that we don't leak if called multiple times.
this._clearListeners();

const eventHandlers = new Map<string, EventEmitter<void>>([
['closeclick', this.closeclick],
['content_changed', this.contentChanged],
Expand All @@ -182,4 +185,13 @@ export class MapInfoWindow implements OnInit, OnDestroy {
}
});
}

/** Clears all currently-registered event listeners. */
private _clearListeners() {
for (let listener of this._listeners) {
listener.remove();
}

this._listeners = [];
}
}
18 changes: 14 additions & 4 deletions src/google-maps/map-marker/map-marker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export class MapMarker implements OnInit, OnDestroy {

private readonly _destroy = new Subject<void>();

private readonly _listeners: google.maps.MapsEventListener[] = [];
private _listeners: google.maps.MapsEventListener[] = [];

_marker?: google.maps.Marker;

Expand All @@ -230,9 +230,7 @@ export class MapMarker implements OnInit, OnDestroy {
ngOnDestroy() {
this._destroy.next();
this._destroy.complete();
for (let listener of this._listeners) {
listener.remove();
}
this._clearListeners();
if (this._marker) {
this._marker.setMap(null);
}
Expand Down Expand Up @@ -390,6 +388,9 @@ export class MapMarker implements OnInit, OnDestroy {
}

private _initializeEventHandlers() {
// Ensure that we don't leak if called multiple times.
this._clearListeners();

const eventHandlers = new Map<string, EventEmitter<void>>([
['animation_changed', this.animationChanged],
['clickable_changed', this.clickableChanged],
Expand Down Expand Up @@ -433,4 +434,13 @@ export class MapMarker implements OnInit, OnDestroy {
}
});
}

/** Clears all currently-registered event listeners. */
private _clearListeners() {
for (let listener of this._listeners) {
listener.remove();
}

this._listeners = [];
}
}