This repository has been archived by the owner on Apr 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 27.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(jqLite): stop patching individual jQuery methods
Currently Angular monkey-patches a few jQuery methods that remove elements from the DOM. Since methods like .remove() have multiple signatures that can change what's actually removed, Angular needs to carefully repeat them in its patching or it can break apps using jQuery correctly. Such a strategy is also not future-safe. Instead of patching individual methods on the prototype, it's better to hook into jQuery.cleanData and trigger custom events there. This should be safe as e.g. jQuery UI needs it and uses it. It'll also be future-safe. The only drawback is that $destroy is no longer triggered when using $detach but: 1. Angular doesn't use this method, jqLite doesn't implement it. 2. Detached elements can be re-attached keeping all their events & data so it makes sense that $destroy is not triggered on them. 3. The approach from this commit is so much safer that any issues with .detach() working differently are outweighed by the robustness of the code. BREAKING CHANGE: the $destroy event is no longer triggered when using the jQuery detach() method. If you want to destroy Angular data attached to the element, use remove().
- Loading branch information
Showing
3 changed files
with
15 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be ported to the 1.2x branch? The current monkeypatching in that branch is giving me problems with jquery 1.8.x on IE9
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dmaj7no5th What problems, can you report them? @IgorMinar would have to decide but we generally don't backport refactorings that aren't bug fixes. If it indeed fixes a bug you experience, this may be an incentive.
You can try to cherry-pick this commit onto the
v1.2.x
branch, create a package vianpm i && grunt
and see if it helps. Such info would be useful.d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specifically, using ngRoute. On route changes, when ngRoute cleans up the old view, it calls element.remove(). Somewhere within the mutation patch above (removed in this commit), IE9 throws a "Access is Denied" error. Using angular 1.2.16 with jQuery 1.8.3. Commenting out the monkeypatch makes the routeChange work without error.
I'll see if I can reproduce in a clean app and report an issue
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you upgrade to jquery 1.10.x? We don't test against 1.8.3.
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@IgorMinar
That's true, though we officialy state jQuery 1.7 or higher is required and I don't think we can just say we support only the latest version since not all projects can update in this pace.
Also, why 1.10.x and not 1.11.1?
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dmaj7no5th Doesn't IE9 print any specific line where the problem arises? That would make it easier to figure out. Also, just tu make sure: are you running your app via a local file server and not just via opening static HTML files?
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upgrading jQuery doesn't fix the problem. After some more debugging it seems the problem goes away if I disable my CSS. I'm not using the ngAnimate module, nor do I have any CSS transitions enabled - but it appears something's going on with the CSS that's breaking ngRoute somehow, and due to that, IE9 won't let jQuery remove the DOM elements.
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The debugger doesn't give me any line numbers. I've been trying different settings in Internet Options, but all I can get out of it is "Permission Denied." Once the error occurrs, I have 2 ng-view divs in the DOM.
$('[ng-view]').remove() will throw the same "Permission Denied" error again and again once it occurs.
I'm grasping at straws with the debugger to find exactly what line it's happening on without much luck
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was any decision made about porting this into the 1.2.x branch? I have a directive that uses detach to relocate an element in the DOM and it worked in version 1.2.12, before the $destroy method was corrected. If this change could be ported into 1.2.x and the detach() didn't trigger the $destroy at all it would work again.
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@IgorMinar I think we should backport this fix to 1.2.x. This is technically a breaking change but the current behavior is just a bug as it doesn't align with the jQuery meaning of detach. There seem to be enough people affected by past tightening up leaks that hit
.detach()
that it IMO makes sense to fix them with this patch.An alternative approach would be to just modify the jQuery patch in Angular 1.2 to not trigger
$destroy
when using.detach()
without switching to thecleanData
cleaner way from Angular 1.3.Anyway, IMO we should do one of these things. I prefer the former but it's your call.
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that a simpler patch might be appropriate, in the
jqLitePatchJQueryRemove
function if theremovePatch(param)
method was changed toremovePatch(param, keepData)
andkeepData
was used to either exit the function immediately or just prevent the the$destroy
from triggering that should fix it.d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rwlogel Care to submit a PR? :) Link to it from here.
Maybe it's indeed a better way to not change the whole patch in a patch release if a simpler fix exists.
d71dbb1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rwlogel Do you want to tackle it?