From 9b8cd13e58a2cebd19d0974dc9a52e52edfec20a Mon Sep 17 00:00:00 2001 From: arturovt Date: Fri, 8 Sep 2023 21:35:55 +0300 Subject: [PATCH] fix(animations): remove `finish` listener once player is destroyed This commit removes the `finish` listener from the Animation object once the animation is finished, effectively resolving a memory leak. Previously, the `finish` listener captured `this`, which prevented `this` from being garbage collected. --- .../src/render/web_animations/web_animations_player.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/animations/browser/src/render/web_animations/web_animations_player.ts b/packages/animations/browser/src/render/web_animations/web_animations_player.ts index ca87588f3c04..2da91dc6fb64 100644 --- a/packages/animations/browser/src/render/web_animations/web_animations_player.ts +++ b/packages/animations/browser/src/render/web_animations/web_animations_player.ts @@ -65,7 +65,14 @@ export class WebAnimationsPlayer implements AnimationPlayer { // @ts-expect-error overwriting a readonly property this.domPlayer = this._triggerWebAnimation(this.element, keyframes, this.options); this._finalKeyframe = keyframes.length ? keyframes[keyframes.length - 1] : new Map(); - this.domPlayer.addEventListener('finish', () => this._onFinish()); + const onFinish = () => this._onFinish(); + this.domPlayer.addEventListener('finish', onFinish); + this.onDestroy(() => { + // We must remove the `finish` event listener once an animation has completed all its + // iterations. This action is necessary to prevent a memory leak since the listener captures + // `this`, creating a closure that prevents `this` from being garbage collected. + this.domPlayer.removeEventListener('finish', onFinish); + }); } private _preparePlayerBeforeStart() {