Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix($animate): avoid memory leak with $animate.enabled(element, enabled) #16649

Closed

Conversation

gkalpak
Copy link
Member

@gkalpak gkalpak commented Jul 27, 2018

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Bug fix (memory leak).

What is the current behavior? (You can also link to an open issue here)
When disabling/enabling animations on a specific element (via $animate.enabled(element, enabled)), the element is added in a map to track its state.

Currently, the element is never removed from the map, causing AngularJS to hold on to the element even after it is removed from the DOM, thus preventing it from being garbage collected.

See #16637.

What is the new behavior (if this is a feature change)?
The element is removed from the map on $destroy, making it eligible for garbage collection (if there are no references to it).

Does this PR introduce a breaking change?
Maybe... (bar probably not really)

Please check if the PR fulfills these requirements

  • The commit message follows our guidelines
  • Fix/Feature: Docs have been added/updated
  • Fix/Feature: Tests have been added; existing tests pass

Other information:
Fixes #16637.

…led)`

When disabling/enabling animations on a specific element (via
`$animate.enabled(element, enabled)`), the element is added in a map to
track its state. Previously, the element was never removed from the map,
causing AngularJS to hold on to the element even after it is removed
from the DOM, thus preventing it from being garbage collected.

This commit fixes it by removing the element from the map on `$destroy`.

Fixes angular#16637.
@gkalpak
Copy link
Member Author

gkalpak commented Jul 27, 2018

It crossed my mind that this migth be a breaking change, because previously removing and re-inserting an element let it retain its "animations enabled" status.

But generally a lot of things will break if you remove an element (via .remove()), since all data and event listeners are removed as well (from a jqLite/jQuery perspective, not native ones).

The proper method if you want to temporarily remove an element from the DOM is .detach() (which retains data and listeners).

An alternative would be to attach the "animations enabled" status on the element itself (directly, not via .data() for the same reasons).

I lean towards not considering this a breaking change, though 😅 WDYT?

@gkalpak gkalpak added this to the 1.7.x milestone Jul 27, 2018
@gkalpak gkalpak self-assigned this Jul 27, 2018
@Narretz
Copy link
Contributor

Narretz commented Jul 27, 2018

I don't think it's a breaking change. It was an interesting side-effect but if somebody relied on this behavior I don't think it's many people.

@gkalpak
Copy link
Member Author

gkalpak commented Jul 27, 2018

There was a bug (when using jQuery) 😁 Pushed a fixup commit.
I'll merge as soon as CI is green(-ish).

@gkalpak gkalpak closed this in c133ef8 Jul 27, 2018
gkalpak added a commit that referenced this pull request Jul 27, 2018
…led)`

When disabling/enabling animations on a specific element (via
`$animate.enabled(element, enabled)`), the element is added in a map to
track its state. Previously, the element was never removed from the map,
causing AngularJS to hold on to the element even after it is removed
from the DOM, thus preventing it from being garbage collected.

This commit fixes it by removing the element from the map on `$destroy`.

Fixes #16637.

Closes #16649
@gkalpak gkalpak deleted the fix-animate-disabled-element-cleanup branch July 27, 2018 17:49
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ngAnimate: memory leak in disabledElementsLookup Map
4 participants