Skip to content

Commit a14bdfe

Browse files
JeanMechedylhunn
authored andcommitted
fix(animations): Ensure elements are removed from the cache after leave animation. (#50929)
This commit fixes a memory leak. `_namespaceLookup` was cleared before the call to `processLeaveNode()` which was using the lookup. Without that lookup `clearElementCache()` wasn't called thus keeping a reference to the element. Fixes #24197 & #50533 PR Close #50929
1 parent 5828eb9 commit a14bdfe

File tree

2 files changed

+15
-27
lines changed

2 files changed

+15
-27
lines changed

packages/animations/browser/src/render/transition_animation_engine.ts

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -508,14 +508,6 @@ export class AnimationTransitionNamespace {
508508
this.players.forEach(p => p.destroy());
509509
this._signalRemovalForInnerTriggers(this.hostElement, context);
510510
}
511-
512-
elementContainsData(element: any): boolean {
513-
let containsData = false;
514-
if (this._elementListeners.has(element)) containsData = true;
515-
containsData =
516-
(this._queue.find(entry => entry.element === element) ? true : false) || containsData;
517-
return containsData;
518-
}
519511
}
520512

521513
export interface QueuedTransition {
@@ -640,19 +632,18 @@ export class TransitionAnimationEngine {
640632

641633
destroy(namespaceId: string, context: any) {
642634
if (!namespaceId) return;
635+
this.afterFlush(() => {});
643636

644-
const ns = this._fetchNamespace(namespaceId);
645-
646-
this.afterFlush(() => {
637+
this.afterFlushAnimationsDone(() => {
638+
const ns = this._fetchNamespace(namespaceId);
647639
this.namespacesByHostElement.delete(ns.hostElement);
648-
delete this._namespaceLookup[namespaceId];
649640
const index = this._namespaceList.indexOf(ns);
650641
if (index >= 0) {
651642
this._namespaceList.splice(index, 1);
652643
}
644+
ns.destroy(context);
645+
delete this._namespaceLookup[namespaceId];
653646
});
654-
655-
this.afterFlushAnimationsDone(() => ns.destroy(context));
656647
}
657648

658649
private _fetchNamespace(id: string) {
@@ -1314,16 +1305,6 @@ export class TransitionAnimationEngine {
13141305
return rootPlayers;
13151306
}
13161307

1317-
elementContainsData(namespaceId: string, element: any) {
1318-
let containsData = false;
1319-
const details = element[REMOVAL_FLAG] as ElementAnimationState;
1320-
if (details && details.setForRemoval) containsData = true;
1321-
if (this.playersByElement.has(element)) containsData = true;
1322-
if (this.playersByQueriedElement.has(element)) containsData = true;
1323-
if (this.statesByElement.has(element)) containsData = true;
1324-
return this._fetchNamespace(namespaceId).elementContainsData(element) || containsData;
1325-
}
1326-
13271308
afterFlush(callback: () => any) {
13281309
this._flushFns.push(callback);
13291310
}

packages/animations/browser/test/render/transition_animation_engine_spec.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,20 @@ describe('TransitionAnimationEngine', () => {
113113
registerTrigger(element, engine, trig);
114114
setProperty(element, engine, 'myTrigger', 'value');
115115
engine.flush();
116+
expect(engine.statesByElement.has(element))
117+
.toBe(true, 'Expected element data to be defined.');
118+
expect(engine.playersByElement.has(element))
119+
.toBe(true, 'Expected element data to be defined.');
116120

117-
expect(engine.elementContainsData(DEFAULT_NAMESPACE_ID, element)).toBeTruthy();
118-
121+
engine.destroy(DEFAULT_NAMESPACE_ID, null);
119122
engine.removeNode(DEFAULT_NAMESPACE_ID, element, true);
120123
engine.flush();
124+
engine.players[0].finish();
121125

122-
expect(engine.elementContainsData(DEFAULT_NAMESPACE_ID, element)).toBeTruthy();
126+
expect(engine.statesByElement.has(element))
127+
.toBe(false, 'Expected element data to be undefined.');
128+
expect(engine.playersByElement.has(element))
129+
.toBe(false, 'Expected element data to be undefined.');
123130
});
124131

125132
it('should create and recreate a namespace for a host element with the same component source',

0 commit comments

Comments
 (0)