fix(animations): leaking detached nodes when parent has a leave transition (#34409)
In the TransitionAnimationEngine we keep track of the existing elements with animations and we clear the cached data when they're removed. We also have some logic where we transition away the child elements when a parent is removed, however in that case we never cleared the cached element data which resulted in a memory leak. The leak is particularly visible in Material where whenever there's an animated overlay with a component inside of it that has an animation, the child component would always be retained in memory. Fixes #25744. PR Close #34409
This commit is contained in:
@ -142,6 +142,40 @@ const DEFAULT_NAMESPACE_ID = 'id';
|
||||
.duration)
|
||||
.toEqual(1234);
|
||||
});
|
||||
|
||||
it('should clear child node data when a parent node with leave transition is removed', () => {
|
||||
const engine = makeEngine();
|
||||
const child = document.createElement('div');
|
||||
const parentTrigger = trigger('parent', [
|
||||
transition(':leave', [style({height: '0px'}), animate(1000, style({height: '100px'}))])
|
||||
]);
|
||||
const childTrigger = trigger(
|
||||
'child',
|
||||
[transition(':enter', [style({opacity: '0'}), animate(1000, style({opacity: '1'}))])]);
|
||||
|
||||
registerTrigger(element, engine, parentTrigger);
|
||||
registerTrigger(child, engine, childTrigger);
|
||||
|
||||
element.appendChild(child);
|
||||
engine.insertNode(DEFAULT_NAMESPACE_ID, child, element, true);
|
||||
|
||||
setProperty(element, engine, 'parent', 'value');
|
||||
setProperty(child, engine, 'child', 'visible');
|
||||
engine.flush();
|
||||
|
||||
expect(engine.statesByElement.has(element))
|
||||
.toBe(true, 'Expected parent data to be defined.');
|
||||
expect(engine.statesByElement.has(child)).toBe(true, 'Expected child data to be defined.');
|
||||
|
||||
engine.removeNode(DEFAULT_NAMESPACE_ID, element, true, true);
|
||||
engine.flush();
|
||||
engine.players[0].finish();
|
||||
|
||||
expect(engine.statesByElement.has(element))
|
||||
.toBe(false, 'Expected parent data to be cleared.');
|
||||
expect(engine.statesByElement.has(child)).toBe(false, 'Expected child data to be cleared.');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('event listeners', () => {
|
||||
|
Reference in New Issue
Block a user