Side navigation
#11570 closed feature (migrated)
Opened April 09, 2012 03:44PM UTC
Closed October 20, 2014 11:50PM UTC
Move element cache to the element[expando] to avoid cleanup and reduce code.
Reported by: | john.david.dalton@gmail.com | Owned by: | rwaldron |
---|---|---|---|
Priority: | low | Milestone: | 1.12/2.2 |
Component: | data | Version: | git |
Keywords: | Cc: | rwaldron | |
Blocked by: | Blocking: |
Description
Soo way back in 2005 Dean Edwards proposed an event system that slapped the listeners on the actual element. This allowed cache to be destroyed once the element was GC'ed.
http://dean.edwards.name/weblog/2005/10/add-event2/
Over the weekend Peter Michaux proposed a similar solution:
https://twitter.com/#!/petermichaux/status/189012245483757568
I noticed that jQuery supports events on vanilla objects too so this change would align elements and objects.
The gist is that since jQuery is already adding an expando for a UID they can just use that property as the actual storage for the element.
Then all the code to recursively clean .removed'ed elements event/custom data could be removed as when the element is GC'ed that data is destroyed.
Attachments (0)
Change History (23)
Changed April 09, 2012 03:53PM UTC by comment:1
owner: | → rwaldron |
---|---|
status: | new → assigned |
Changed April 09, 2012 03:56PM UTC by comment:2
We may need to confirm the IE6 memory leak issue (or maybe not as that's really IE6 pre SP2) is handled (though if I remember correctly Dean Edwards 05 solution did *not* leak in IE).
Changed June 26, 2012 01:37PM UTC by comment:3
Once we exit the two-GC environment of oldIE we can implement this. However, we will still need to do the recursive crawl in at least some cases, to call any special event teardown hooks. We can probably optimize that significantly though, for example an expando flag that indicates whether there are any special events in use for each element.
Changed June 26, 2012 01:38PM UTC by comment:4
component: | unfiled → event |
---|---|
priority: | undecided → low |
Changed July 14, 2012 02:42AM UTC by comment:5
milestone: | None → 2.0 |
---|
Changed April 04, 2013 08:43PM UTC by comment:6
cc: | → rwaldron |
---|
@rwaldron, what should we do with this ticket?
Changed April 04, 2013 08:57PM UTC by comment:7
resolution: | → fixed |
---|---|
status: | assigned → closed |
Fixed in 2.0 Data rewrite, which can be read here: https://github.com/jquery/jquery/commits/master/src/data.js
Read backwards from 332a490573bbbd9e7df1381bde8f590240cb8679
Changed April 04, 2013 10:16PM UTC by comment:8
It looks like it's still relying on data objects internally, that will leak if not discarded via an explicit call when the element is no longer needed. Using the element itself as the object which holds the data object would avoid this (the gist of this issue).
Changed April 04, 2013 10:23PM UTC by comment:9
_comment0: | The current design in 2.x is designed to support a smooth transition to a WeakMap as soon as they are available in at least 3 browsers (I picked that number arbitrarily). \ \ Putting the data directly on the element would mean exposing jQuery's own interally used data (there are actually two sets of data for every object or element: user and private-interal), which we can't do. As long as user code does all of it's DOM manipulation via jQuery, then data will be correctly cleaned up (removed). → 1365114279380068 |
---|
The current design in 2.x is designed to support a smooth transition to a WeakMap as soon as they are available in at least 3 browsers (I picked that number arbitrarily).
Putting the data directly on the element would mean exposing jQuery's own interally used data (there are actually two sets of data for every object or element: user and private-interal), which we can't do. As long as user code does all of its DOM manipulation via jQuery, then data will be correctly cleaned up (removed).
Changed April 04, 2013 10:37PM UTC by comment:10
(there are actually two sets of data for every object or element: user and private-interal)
I know, the gist of this ticket was to suggest putting all element data (internal/user) on the element. That way there would be no need for the user to manually invoke a cleaning method. This would reduce the code needed for storing data and avoid memory leaks without burdening the dev with cleanup (which when overlooked, which is easy, can cause leaks that are not so easy to track down).
Changed April 04, 2013 10:53PM UTC by comment:11
Replying to [comment:10 jdalton]:
> (there are actually two sets of data for every object or element: user and private-interal) I know, the gist of this ticket was to suggest putting all element data (internal/user) on the element. That way there would be no need for the user to manually invoke a cleaning method. This would reduce the code needed for storing data and avoid memory leaks without burdening the dev with cleanup (which when overlooked, which is easy, can cause leaks that are not so easy to track down).
If user code can get at all of the jQuery-specific internal data, then we can't make any guarantees stability or reliability (http://bugs.jquery.com/ticket/11945, http://forum.jquery.com/topic/what-s-the-rationale-of-not-exposing-object-s-events-handlers-collections). Trust me, I wish it was that easy :(
I always appreciate your input and feedback, but in this case we can't expose the jQuery-specific internal data on "owner" object.
Related, but not directly... I'm not sure what you mean by "need for the user to manually invoke a cleaning method"? This happens automatically with jQuery dom manip methods (where appropriate). The only time it won't happen is if user code uses DOM APIs directly, which is out of scope for jQuery.
Changed April 04, 2013 11:15PM UTC by comment:12
@jdalton, for the general case we still need to call our jQuery.cleanData()
method in manipulation.js at least for situations like special events where we guarantee a teardown hook. Also consider our semantics for .remove()
which say that when you remove elements from the document it removes both the events and data, whereas .detach()
does not.
So we have to go through the loop part of the cleanData
code regardless, but perhaps attaching the data to the element would let us skip some steps? If it made a significant performance difference I'd be interested in seeing an implementation, even if it "exposed" data to some extent. In doing perf testing on web apps and sites it's not uncommon to see cleanData
high on the list, especially with MV* frameworks that update big DOM chunks.
Changed April 04, 2013 11:22PM UTC by comment:13
We could "patchwelcome" this ticket, but the patch would have to pass all of the existing data tests as-is.
Changed April 05, 2013 12:11AM UTC by comment:14
Related, but not directly... I'm not sure what you mean by "need for the user to manually invoke a cleaning method"?
I was thinking of devs having to use .remove()
and friends instead of say simply el.innerHTML=''
. You're correct though if they were diligent and used only lib API it is managed.
If user code can get at all of the jQuery-specific internal data, then we can't make any guarantees stability or reliability
As for exposing data, pre 2.0, jQuery.cache
existed so I'm not sure how that fits into the guarantees of stability or reliability.
As an aside, jQuery hasn't been a big user of hasOwnProperty
checks so couldn't someone manipulate the Object.prototype
and populate data values? Does that fit with stability/reliability guarantees?
Also I wanna +1 @dmethvin perf concern.
Changed April 05, 2013 12:38AM UTC by comment:15
As for exposing data, pre 2.0, jQuery.cache existed so I'm not sure how that fits into the guarantees of stability or reliability.
In jQuery 2.x there is no jQuery.cache for this very reason :)
As an aside, jQuery hasn't been a big user of hasOwnProperty checks so couldn't someone manipulate the Object.prototype and populate data values? Does that fit with stability/reliability guarantees?
Sure, but that falls under the official Won't Fix :D http://contribute.jquery.org/wont-fix/
Changed April 05, 2013 04:25AM UTC by comment:16
Sure, but that falls under the official Won't Fix :D
Yap, lots of things are out of scope, but that makes the "guarantee" more lip service than substance. So in this case I think it's more beneficial to store the data on the element instead.
With that said, I don't have time to investigate at the moment, so if resources are limited the issue can be noted for future reference.
Changed May 20, 2013 10:06PM UTC by comment:17
milestone: | 2.0 |
---|---|
resolution: | fixed |
status: | closed → reopened |
Changed June 03, 2013 01:53PM UTC by comment:18
milestone: | → 1.11/2.1 |
---|---|
status: | reopened → open |
Changed November 04, 2013 02:11PM UTC by comment:19
_comment0: | We discussed this in Amsterdam. jQuery UI currently depends on cleanData to hook its widget removal in: Whenever an element is removed that is a widget, it calls the destroy() method of the widget, for example to unbind event handlers from the document. \ \ Whatever the solution for this looks like needs to provide some alternative hook for jQuery UI. → 1383575653989533 |
---|
We discussed this in Amsterdam. jQuery UI currently depends on cleanData to hook its widget removal in: Whenever an element is removed that is a widget, it calls the destroy() method of the widget, for example to unbind event handlers from the document.
Whatever the solution for this looks like needs to provide some alternative hook for jQuery UI. See also #12213
Changed November 10, 2013 10:09PM UTC by comment:20
I've read the comments and it seems there's still an issue with teardown hooks not being invoked if an element is removed via raw DOM methods. Can we overcome this difficulty?
As for the safety guarantees, I mostly agree with jdalton; we're unable to provide complete protection anyway so if (!) it's possible for jQuery-created & handled elements to cooperate with native DOM methods I'm +1 on this one.
Changed December 16, 2013 04:57PM UTC by comment:21
milestone: | 1.11/2.1 → 1.next/2.next |
---|
I'm not worried about complete protection, we're mainly trying to avoid walking all the elements in the tree when we don't have to. If someone mingles jQuery with raw DOM methods to manipulate the document they will need to understand the consequences.
Changed March 03, 2014 03:46PM UTC by comment:22
component: | event → data |
---|---|
milestone: | 1.next/2.next → 1.12/2.2 |
Changed October 20, 2014 11:50PM UTC by comment:23
resolution: | → migrated |
---|---|
status: | open → closed |
Migrated to https://github.com/jquery/jquery/issues/1734
I think this is worth investigating and experimenting. I'm going to grab it and work with @jdalton on implementing