Skip to content
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

fix(upgrade): fix memory leaks when the component is destroyed #39921

Closed
wants to merge 1 commit into from
Closed

fix(upgrade): fix memory leaks when the component is destroyed #39921

wants to merge 1 commit into from

Conversation

arturovt
Copy link
Contributor

@arturovt arturovt commented Dec 1, 2020

PR Checklist

PR Type

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • angular.io application / infrastructure changes
  • Other... Please describe:

What is the current behavior?

Issue Number: #39911

Does this PR introduce a breaking change?

  • Yes
  • No

@google-cla google-cla bot added the cla: yes label Dec 1, 2020
@pullapprove pullapprove bot requested a review from petebacondarwin Dec 1, 2020
@ngbot ngbot bot added this to the needsTriage milestone Dec 1, 2020
@arturovt arturovt changed the title fix(upgrade): fix memory leak caused by $$$angularInjectorController fix(upgrade): fix memory leaks when the component is destroyed Dec 2, 2020
@pullapprove pullapprove bot requested a review from gkalpak Dec 2, 2020
Currently we're storing the real injector on the element inside the
`ParentInjectorPromise` and its `resolve()` method. This causes a memory leak
if we don't remove the reference when the component is destroyed.

We also setup the `$destroy` listener and never release it, the problem
is that this listener captures `this`, as long as there is a reference,
`this` will not be GC'd.

PR Close #39911
@gkalpak
Copy link
Member

@gkalpak gkalpak commented Dec 2, 2020

@arturovt, is this PR ready for review (I've noticed you have been pushing new commits recently)?

@arturovt
Copy link
Contributor Author

@arturovt arturovt commented Dec 2, 2020

@arturovt, is this PR ready for review (I've noticed you have been pushing new commits recently)?

Yep, you can start reviewing.

Copy link
Member

@petebacondarwin petebacondarwin left a comment

LGTM but it has been a while since I look at ngUpgrade code.
@gkalpak will probably have more to say :-)

@arturovt
Copy link
Contributor Author

@arturovt arturovt commented Dec 2, 2020

@petebacondarwin @gkalpak gentlemen just for your information:
this is BEFORE applying these changes

before




this is AFTER

after

Basically, the DowngradeComponentAdapter (and all its resources) are released.

gkalpak added a commit to gkalpak/angular that referenced this issue Dec 3, 2020
Previously, due to the way the AngularJS and Angular clean-up processes
interfere with each other when removing an AngularJS element that
contains a downgraded Angular component, the data associated with the
host element of the downgraded component was not removed. This data was
kept in an internal AngularJS cache, which prevented the element and
component instance from being garbage-collected, leading to memory
leaks.

This commit fixes this by ensuring the element data is explicitly
removed when cleaning up a downgraded component.

NOTE:
This is essentially the equivalent of angular#26209 but for downgraded (instead
of upgraded) components.

Fixes angular#39911
Closes angular#39921
gkalpak added a commit to gkalpak/angular that referenced this issue Dec 3, 2020
Previously, due to the way the AngularJS and Angular clean-up processes
interfere with each other when removing an AngularJS element that
contains a downgraded Angular component, the data associated with the
host element of the downgraded component was not removed. This data was
kept in an internal AngularJS cache, which prevented the element and
component instance from being garbage-collected, leading to memory
leaks.

This commit fixes this by ensuring the element data is explicitly
removed when cleaning up a downgraded component.

NOTE:
This is essentially the equivalent of angular#26209 but for downgraded (instead
of upgraded) components.

Fixes angular#39911
Closes angular#39921
gkalpak added a commit to gkalpak/angular that referenced this issue Dec 3, 2020
Previously, due to the way the AngularJS and Angular clean-up processes
interfere with each other when removing an AngularJS element that
contains a downgraded Angular component, the data associated with the
host element of the downgraded component was not removed. This data was
kept in an internal AngularJS cache, which prevented the element and
component instance from being garbage-collected, leading to memory
leaks.

This commit fixes this by ensuring the element data is explicitly
removed when cleaning up a downgraded component.

NOTE:
This is essentially the equivalent of angular#26209 but for downgraded (instead
of upgraded) components.

Fixes angular#39911
Closes angular#39921
gkalpak added a commit to gkalpak/angular that referenced this issue Dec 3, 2020
Previously, due to the way the AngularJS and Angular clean-up processes
interfere with each other when removing an AngularJS element that
contains a downgraded Angular component, the data associated with the
host element of the downgraded component was not removed. This data was
kept in an internal AngularJS cache, which prevented the element and
component instance from being garbage-collected, leading to memory
leaks.

This commit fixes this by ensuring the element data is explicitly
removed when cleaning up a downgraded component.

NOTE:
This is essentially the equivalent of angular#26209 but for downgraded (instead
of upgraded) components.

Fixes angular#39911
Closes angular#39921
gkalpak added a commit to gkalpak/angular that referenced this issue Dec 3, 2020
Previously, due to the way the AngularJS and Angular clean-up processes
interfere with each other when removing an AngularJS element that
contains a downgraded Angular component, the data associated with the
host element of the downgraded component was not removed. This data was
kept in an internal AngularJS cache, which prevented the element and
component instance from being garbage-collected, leading to memory
leaks.

This commit fixes this by ensuring the element data is explicitly
removed when cleaning up a downgraded component.

NOTE:
This is essentially the equivalent of angular#26209 but for downgraded (instead
of upgraded) components.

Fixes angular#39911
Closes angular#39921
@gkalpak
Copy link
Member

@gkalpak gkalpak commented Dec 3, 2020

Thx for working on this, @arturovt 👍

While reviewing your PR, it thought it was "suspicious" that we had to clean up stuff that would normally be cleaned up automatically. So I dug deeper to understand why it wasn't being clean up.

In a nutshell, it happens because (under some circumstances) Angular will remove the component host element from the DOM before AngularJS has a chance to clean it up. See here for more details.

Based on the above, I have created #39965 with an alternative fix, which I think is simpler and more consistent with how things would work in a pure AngularJS app. I would appreciate it if you could take a look and let me know what you think?

BTW, you can also grab the build artifacts from my PR (see here for more info) and use them in a sample app in order to verify the fix.

@arturovt
Copy link
Contributor Author

@arturovt arturovt commented Dec 4, 2020

@gkalpak

I've played with your changes and it seems to work (the adapter is released successfully). Nice job!

@gkalpak
Copy link
Member

@gkalpak gkalpak commented Dec 5, 2020

Awesome! Thx for checking, @arturovt ❤️

gkalpak added a commit to gkalpak/angular that referenced this issue Dec 7, 2020
Previously, due to the way the AngularJS and Angular clean-up processes
interfere with each other when removing an AngularJS element that
contains a downgraded Angular component, the data associated with the
host element of the downgraded component was not removed. This data was
kept in an internal AngularJS cache, which prevented the element and
component instance from being garbage-collected, leading to memory
leaks.

This commit fixes this by ensuring the element data is explicitly
removed when cleaning up a downgraded component.

NOTE:
This is essentially the equivalent of angular#26209 but for downgraded (instead
of upgraded) components.

Fixes angular#39911
Closes angular#39921
mhevery pushed a commit that referenced this issue Dec 8, 2020
…39965)

Previously, due to the way the AngularJS and Angular clean-up processes
interfere with each other when removing an AngularJS element that
contains a downgraded Angular component, the data associated with the
host element of the downgraded component was not removed. This data was
kept in an internal AngularJS cache, which prevented the element and
component instance from being garbage-collected, leading to memory
leaks.

This commit fixes this by ensuring the element data is explicitly
removed when cleaning up a downgraded component.

NOTE:
This is essentially the equivalent of #26209 but for downgraded (instead
of upgraded) components.

Fixes #39911
Closes #39921

PR Close #39965
@mhevery mhevery closed this in 6dc43a4 Dec 8, 2020
@arturovt arturovt deleted the fix/39911 branch Dec 13, 2020
twerske pushed a commit to twerske/angular that referenced this issue Jan 5, 2021
…ngular#39965)

Previously, due to the way the AngularJS and Angular clean-up processes
interfere with each other when removing an AngularJS element that
contains a downgraded Angular component, the data associated with the
host element of the downgraded component was not removed. This data was
kept in an internal AngularJS cache, which prevented the element and
component instance from being garbage-collected, leading to memory
leaks.

This commit fixes this by ensuring the element data is explicitly
removed when cleaning up a downgraded component.

NOTE:
This is essentially the equivalent of angular#26209 but for downgraded (instead
of upgraded) components.

Fixes angular#39911
Closes angular#39921

PR Close angular#39965
@angular-automatic-lock-bot
Copy link

@angular-automatic-lock-bot angular-automatic-lock-bot bot commented Jan 13, 2021

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jan 13, 2021
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.

None yet

4 participants