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

fix(jqLite): make removeData() not remove event handlers #16512

Merged
merged 1 commit into from
Apr 3, 2018

Conversation

mgol
Copy link
Member

@mgol mgol commented Mar 26, 2018

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

Bug fix but a breaking change as well.

What is the current behavior? (You can also link to an open issue here)

removeData() invoked on an element removes its event handlers as well.

What is the new behavior (if this is a feature change)?

removeData() removes just user-set data, not internal data storage used for event handling. This aligns jqLite with jQuery.

Does this PR introduce a breaking change?

Yes.

Please check if the PR fulfills these requirements

  • The commit message follows our guidelines
  • Fix/Feature: Docs have been added/updated (the current behavior is not documented)
  • Fix/Feature: Tests have been added; existing tests pass

Other information:

Fixes #15869

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.

No specs for cleanData() 😱
Also, in the commit message, I think you should change angular.element.cleanData([elem]) to angular.element.cleanData(elem).

function isEmptyObject(obj) {
var name;

for (name in obj) {
Copy link
Member

Choose a reason for hiding this comment

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

Do we really care about inherited properties here?

Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -615,6 +633,7 @@ forEach({
cleanData: function jqLiteCleanData(nodes) {
for (var i = 0, ii = nodes.length; i < ii; i++) {
jqLiteRemoveData(nodes[i]);
jqLiteOff(nodes[i]);
Copy link
Member

Choose a reason for hiding this comment

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

AFAICT, $destroy handlers will not be removed, which means that the expandoStore will never be completely empty and removed.

Copy link
Member Author

Choose a reason for hiding this comment

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

This should be handled in the cleanData patch that used to be applied to jQuery only and that I moved to apply to jqLite as well.

});


it('should allow to set data after removeData() with event handlers present', function() {
Copy link
Member

Choose a reason for hiding this comment

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

What about "with event handlers not present"?

@mgol
Copy link
Member Author

mgol commented Mar 27, 2018

No specs for cleanData() 😱

Good point. Although this method is still not officially documented in jQuery although it seems we'd like to change it.

Also, in the commit message, I think you should change angular.element.cleanData([elem]) to angular.element.cleanData(elem).

The confusion comes from the fact jqLite code refes to bare DOM nodes as element. cleanData accepts an array-like of bare DOM nodes, not just jqLite objects so in this context elem is the correct choice as you noticed.

@gkalpak
Copy link
Member

gkalpak commented Mar 27, 2018

BTW, should this also be changd to cleanData()?

@mgol
Copy link
Member Author

mgol commented Mar 27, 2018

BTW, should this also be changd to cleanData()?

Perhaps. .empty() will already call it for all descendants and .removeData() will remove user data on body so the only thing left are event handlers on body. But we're already not clearing handlers on window & document so it's not a full cleanup.

mgol added a commit that referenced this pull request Mar 28, 2018
This commit removes the resetting of `angular.element.cache` in some tests;
this was desynchronizing jqLite.cache & the local jqCache variable and since
some parts of the code use one of them and some the other one, it was breaking
JQLite._data. `angular.element.cache` doesn't even exist when jQuery 2+ is used.

Closes #16515
Refs #16512
mgol added a commit that referenced this pull request Mar 28, 2018
This commit removes the resetting of `angular.element.cache` in some tests;
this was desynchronizing jqLite.cache & the local jqCache variable and since
some parts of the code use one of them and some the other one, it was breaking
JQLite._data. `angular.element.cache` doesn't even exist when jQuery 2+ is used.

Closes #16515
Refs #16512
});
jqLite.cleanData(selected);

browserTrigger(a, 'click');
Copy link
Member

Choose a reason for hiding this comment

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

Did you mean b? 😁

Copy link
Member Author

Choose a reason for hiding this comment

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

Good eye. :)


jqLite.cleanData(selected);

browserTrigger(a, 'click');
Copy link
Member

Choose a reason for hiding this comment

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

Did you mean b? 😁

expect(jqLite(c).data('prop')).toBeUndefined();
});

it('should remove user data & event handlers on cleanData()', function() {
Copy link
Member

Choose a reason for hiding this comment

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

This description belongs to the test above and vice versa.

@mgol
Copy link
Member Author

mgol commented Mar 28, 2018

PR updated once again.

This change aligns jqLite with jQuery.

Fixes angular#15869

BREAKING CHANGE:

Before this commit `removeData()` invoked on an element removed its event
handlers as well. If you want to trigger a full cleanup of an element, change:

```js
elem.removeData();
```

to:

```js
angular.element.cleanData(elem);
```

In most cases, though, cleaning up after an element is supposed to be done
only when it's removed from the DOM as well; in such cases the following:

```js
elem.remove();
```

will remove event handlers as well.
@mgol mgol merged commit b7d396b into angular:master Apr 3, 2018
@mgol mgol deleted the remove-data branch April 3, 2018 19: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.

jqLite#removeData shouldn't touch the event handlers' storage
4 participants