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

revert + fix($rootScope): fix potential memory leak when removing scope listeners #16358

Merged
merged 3 commits into from
Dec 13, 2017

Conversation

jbedard
Copy link
Collaborator

@jbedard jbedard commented Dec 5, 2017

This reverts the 1.7 change, cherry-picks the 1.6 version that had no breaking changes, and adds some tests to prevent such a breaking change again in the future.

See #16293 (comment) for the reason to revert the breaking change.

Copy link
Member

@gkalpak gkalpak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One test nit. Otherwise LGTM 👍
(EDIT: As soon as Travis is happy 😁)

}));


it('should allow recursive $emit/$broadcast between parent/child', inject(function($rootScope) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this test demonstrates recursive emitting/broadcasting.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How so? It does at least one recursive $broadcast + one $emit within $broadcast...

I'm sure we could think of better or more interesting tests though. Let me know if you have any specific ones you think should be added.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it does root.$broadcast inside root.$broadcast (which we don't care about in this test) and child.$emit inside root.$broadcast, so in a way it is recursive. But it doesn't test for root.$broadcast inside child.$emit, for example.

In order to test both root.$broadcast --> child.$emit and child.$emit --> root.$broadcast, I would change it to something like:

var child = $rootScope.$new();
var calls = '';

$rootScope.$on('evt', function($event, arg0) {
  calls += 'r';  // For "root".
  if (arg0 === 'fromChild') {
    $rootScope.$broadcast('evt', 'fromRoot2');
  }
});

child.$on('evt', function($event, arg0) {
  calls += 'c';  // For "child".
  if (arg0 === 'fromRoot1') {
    child.$emit('evt', 'fromChild');
  }
});

$rootScope.$broadcast('evt', 'fromRoot1');
expect(calls).toBe('rccrrc');

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated to use your test

@Narretz
Copy link
Contributor

Narretz commented Dec 12, 2017

Acording to the guidelines, the commit message should start with "revert: ..." but I don't think that's consequential. Imo, we should support the default git Revert, too. Doesn't matter though.

What I find a bit strange is that the Revert commit comes after the commit with the different fix. I think it's easier to understand if their position is reversed.

@jbedard
Copy link
Collaborator Author

jbedard commented Dec 12, 2017

I think github is showing them based on the commit date, and the cherry-picked commit has a date in august while the revert is more recent? I'm sure I reverted first, otherwise I would have had a lot of conflicts...

@petebacondarwin
Copy link
Contributor

Also, the changez tool expects reverts to take the Angular format. It uses it to ensure that we don't include reverted commits in the changelog.

@jbedard
Copy link
Collaborator Author

jbedard commented Dec 12, 2017

What's the angular format for reverts though?

@gkalpak
Copy link
Member

gkalpak commented Dec 12, 2017

For type(scope): subject it is revert: type(scope): subject.

@Narretz
Copy link
Contributor

Narretz commented Dec 12, 2017

Yeah, the commits are correctly ordered when viewed locally. Strange.

The commit message header of the revert commit should look like this:

revert: fix($rootScope): fix potential memory leak when removing scope listeners

When removing listeners they are removed from the array but the array size
is not changed until the event is fired again. If the event is never fired
but listeners are added/removed then the array will continue growing.

By changing the listener removal to `delete` the array entry instead of setting
it to `null` browsers can potentially deallocate the memory for the entry.

Fixes angular#16135
Closes angular#16161
@Narretz Narretz merged commit 5c38fb7 into angular:master Dec 13, 2017
@Narretz
Copy link
Contributor

Narretz commented Dec 13, 2017

Merged! Thanks @jbedard

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants