Merge in data_nocollide branch. Fixes #6968, improves unit testing framework checks for leaky stuff.
This commit is contained in:
commit
e78d3a7e2d
21 changed files with 556 additions and 242 deletions
|
@ -133,11 +133,11 @@ jQuery.fn.extend({
|
|||
} else if ( type === "undefined" || type === "boolean" ) {
|
||||
if ( this.className ) {
|
||||
// store className if set
|
||||
jQuery.data( this, "__className__", this.className );
|
||||
jQuery._data( this, "__className__", this.className );
|
||||
}
|
||||
|
||||
// toggle whole className
|
||||
this.className = this.className || value === false ? "" : jQuery.data( this, "__className__" ) || "";
|
||||
this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
191
src/data.js
191
src/data.js
|
@ -1,7 +1,6 @@
|
|||
(function( jQuery ) {
|
||||
|
||||
var windowData = {},
|
||||
rbrace = /^(?:\{.*\}|\[.*\])$/;
|
||||
var rbrace = /^(?:\{.*\}|\[.*\])$/;
|
||||
|
||||
jQuery.extend({
|
||||
cache: {},
|
||||
|
@ -23,108 +22,168 @@ jQuery.extend({
|
|||
},
|
||||
|
||||
hasData: function( elem ) {
|
||||
if ( elem.nodeType ) {
|
||||
elem = jQuery.cache[ elem[jQuery.expando] ];
|
||||
}
|
||||
elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
|
||||
|
||||
return !!elem && !jQuery.isEmptyObject(elem);
|
||||
},
|
||||
|
||||
data: function( elem, name, data ) {
|
||||
data: function( elem, name, data, pvt /* Internal Use Only */ ) {
|
||||
if ( !jQuery.acceptData( elem ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
elem = elem == window ?
|
||||
windowData :
|
||||
elem;
|
||||
var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
|
||||
|
||||
var isNode = elem.nodeType,
|
||||
id = isNode ? elem[ jQuery.expando ] : null,
|
||||
cache = jQuery.cache, thisCache;
|
||||
// We have to handle DOM nodes and JS objects differently because IE6-7
|
||||
// can't GC object references properly across the DOM-JS boundary
|
||||
isNode = elem.nodeType,
|
||||
|
||||
if ( isNode && !id && typeof name === "string" && data === undefined ) {
|
||||
// Only DOM nodes need the global jQuery cache; JS object data is
|
||||
// attached directly to the object so GC can occur automatically
|
||||
cache = isNode ? jQuery.cache : elem,
|
||||
|
||||
// Only defining an ID for JS objects if its cache already exists allows
|
||||
// the code to shortcut on the same path as a DOM node with no cache
|
||||
id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
|
||||
|
||||
// Avoid doing any more work than we need to when trying to get data on an
|
||||
// object that has no data at all
|
||||
if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the data from the object directly
|
||||
if ( !isNode ) {
|
||||
cache = elem;
|
||||
|
||||
// Compute a unique ID for the element
|
||||
} else if ( !id ) {
|
||||
elem[ jQuery.expando ] = id = ++jQuery.uuid;
|
||||
if ( !id ) {
|
||||
// Only DOM nodes need a new unique ID for each element since their data
|
||||
// ends up in the global cache
|
||||
if ( isNode ) {
|
||||
elem[ jQuery.expando ] = id = ++jQuery.uuid;
|
||||
} else {
|
||||
id = jQuery.expando;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid generating a new cache unless none exists and we
|
||||
// want to manipulate it.
|
||||
if ( typeof name === "object" ) {
|
||||
if ( isNode ) {
|
||||
cache[ id ] = jQuery.extend(cache[ id ], name);
|
||||
|
||||
} else {
|
||||
jQuery.extend( cache, name );
|
||||
}
|
||||
|
||||
} else if ( isNode && !cache[ id ] ) {
|
||||
if ( !cache[ id ] ) {
|
||||
cache[ id ] = {};
|
||||
}
|
||||
|
||||
thisCache = isNode ? cache[ id ] : cache;
|
||||
// An object can be passed to jQuery.data instead of a key/value pair; this gets
|
||||
// shallow copied over onto the existing cache
|
||||
if ( typeof name === "object" ) {
|
||||
if ( pvt ) {
|
||||
cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
|
||||
} else {
|
||||
cache[ id ] = jQuery.extend(cache[ id ], name);
|
||||
}
|
||||
}
|
||||
|
||||
thisCache = cache[ id ];
|
||||
|
||||
// Internal jQuery data is stored in a separate object inside the object's data
|
||||
// cache in order to avoid key collisions between internal data and user-defined
|
||||
// data
|
||||
if ( pvt ) {
|
||||
if ( !thisCache[ internalKey ] ) {
|
||||
thisCache[ internalKey ] = {};
|
||||
}
|
||||
|
||||
thisCache = thisCache[ internalKey ];
|
||||
}
|
||||
|
||||
// Prevent overriding the named cache with undefined values
|
||||
if ( data !== undefined ) {
|
||||
thisCache[ name ] = data;
|
||||
}
|
||||
|
||||
return typeof name === "string" ? thisCache[ name ] : thisCache;
|
||||
// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
|
||||
// not attempt to inspect the internal events object using jQuery.data, as this
|
||||
// internal data object is undocumented and subject to change.
|
||||
if ( name === "events" && !thisCache[name] ) {
|
||||
return thisCache[ internalKey ] && thisCache[ internalKey ].events;
|
||||
}
|
||||
|
||||
return getByName ? thisCache[ name ] : thisCache;
|
||||
},
|
||||
|
||||
removeData: function( elem, name ) {
|
||||
removeData: function( elem, name, pvt /* Internal Use Only */ ) {
|
||||
if ( !jQuery.acceptData( elem ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
elem = elem == window ?
|
||||
windowData :
|
||||
elem;
|
||||
var internalKey = jQuery.expando, isNode = elem.nodeType,
|
||||
|
||||
var isNode = elem.nodeType,
|
||||
id = isNode ? elem[ jQuery.expando ] : elem,
|
||||
cache = jQuery.cache,
|
||||
thisCache = isNode ? cache[ id ] : id;
|
||||
// See jQuery.data for more information
|
||||
cache = isNode ? jQuery.cache : elem,
|
||||
|
||||
// See jQuery.data for more information
|
||||
id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
|
||||
|
||||
// If there is already no cache entry for this object, there is no
|
||||
// purpose in continuing
|
||||
if ( !cache[ id ] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we want to remove a specific section of the element's data
|
||||
if ( name ) {
|
||||
var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
|
||||
|
||||
if ( thisCache ) {
|
||||
// Remove the section of cache data
|
||||
delete thisCache[ name ];
|
||||
|
||||
// If we've removed all the data, remove the element's cache
|
||||
if ( isNode && jQuery.isEmptyObject(thisCache) ) {
|
||||
jQuery.removeData( elem );
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we want to remove all of the element's data
|
||||
} else {
|
||||
if ( isNode && jQuery.support.deleteExpando ) {
|
||||
delete elem[ jQuery.expando ];
|
||||
|
||||
} else if ( elem.removeAttribute ) {
|
||||
elem.removeAttribute( jQuery.expando );
|
||||
|
||||
// Completely remove the data cache
|
||||
} else if ( isNode ) {
|
||||
delete cache[ id ];
|
||||
|
||||
// Remove all fields from the object
|
||||
} else {
|
||||
for ( var n in elem ) {
|
||||
delete elem[ n ];
|
||||
// If there is no data left in the cache, we want to continue
|
||||
// and let the cache object itself get destroyed
|
||||
if ( !jQuery.isEmptyObject(thisCache) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// See jQuery.data for more information
|
||||
if ( pvt ) {
|
||||
delete cache[ id ][ internalKey ];
|
||||
|
||||
// Don't destroy the parent cache unless the internal data object
|
||||
// had been the only thing left in it
|
||||
if ( !jQuery.isEmptyObject(cache[ id ]) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var internalCache = cache[ id ][ internalKey ];
|
||||
|
||||
// Browsers that fail expando deletion also refuse to delete expandos on
|
||||
// the window, but it will allow it on all other JS objects; other browsers
|
||||
// don't care
|
||||
if ( jQuery.support.deleteExpando || cache != window ) {
|
||||
delete cache[ id ];
|
||||
} else {
|
||||
cache[ id ] = null;
|
||||
}
|
||||
|
||||
// We destroyed the entire user cache at once because it's faster than
|
||||
// iterating through each key, but we need to continue to persist internal
|
||||
// data if it existed
|
||||
if ( internalCache ) {
|
||||
cache[ id ] = {};
|
||||
cache[ id ][ internalKey ] = internalCache;
|
||||
|
||||
// Otherwise, we need to eliminate the expando on the node to avoid
|
||||
// false lookups in the cache for entries that no longer exist
|
||||
} else if ( isNode ) {
|
||||
// IE does not allow us to delete expando properties from nodes,
|
||||
// nor does it have a removeAttribute function on Document nodes;
|
||||
// we must handle all of these cases
|
||||
if ( jQuery.support.deleteExpando ) {
|
||||
delete elem[ jQuery.expando ];
|
||||
} else if ( elem.removeAttribute ) {
|
||||
elem.removeAttribute( jQuery.expando );
|
||||
} else {
|
||||
elem[ jQuery.expando ] = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// For internal use only.
|
||||
_data: function( elem, name, data ) {
|
||||
return jQuery.data( elem, name, data, true );
|
||||
},
|
||||
|
||||
// A method for determining if a DOM node can handle the data expando
|
||||
|
|
10
src/effects.js
vendored
10
src/effects.js
vendored
|
@ -27,7 +27,7 @@ jQuery.fn.extend({
|
|||
|
||||
// Reset the inline display of this element to learn if it is
|
||||
// being hidden by cascaded rules or not
|
||||
if ( !jQuery.data(elem, "olddisplay") && display === "none" ) {
|
||||
if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
|
||||
display = elem.style.display = "";
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ jQuery.fn.extend({
|
|||
// in a stylesheet to whatever the default browser style is
|
||||
// for such an element
|
||||
if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
|
||||
jQuery.data(elem, "olddisplay", defaultDisplay(elem.nodeName));
|
||||
jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ jQuery.fn.extend({
|
|||
display = elem.style.display;
|
||||
|
||||
if ( display === "" || display === "none" ) {
|
||||
elem.style.display = jQuery.data(elem, "olddisplay") || "";
|
||||
elem.style.display = jQuery._data(elem, "olddisplay") || "";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -62,8 +62,8 @@ jQuery.fn.extend({
|
|||
for ( var i = 0, j = this.length; i < j; i++ ) {
|
||||
var display = jQuery.css( this[i], "display" );
|
||||
|
||||
if ( display !== "none" && !jQuery.data( this[i], "olddisplay" ) ) {
|
||||
jQuery.data( this[i], "olddisplay", display );
|
||||
if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
|
||||
jQuery._data( this[i], "olddisplay", display );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
46
src/event.js
46
src/event.js
|
@ -8,7 +8,8 @@ var rnamespaces = /\.(.*)$/,
|
|||
fcleanup = function( nm ) {
|
||||
return nm.replace(rescape, "\\$&");
|
||||
},
|
||||
focusCounts = { focusin: 0, focusout: 0 };
|
||||
focusCounts = { focusin: 0, focusout: 0 },
|
||||
eventKey = "events";
|
||||
|
||||
/*
|
||||
* A number of helper functions used for managing events.
|
||||
|
@ -50,7 +51,7 @@ jQuery.event = {
|
|||
}
|
||||
|
||||
// Init the element's event structure
|
||||
var elemData = jQuery.data( elem );
|
||||
var elemData = jQuery._data( elem );
|
||||
|
||||
// If no elemData is found then we must be trying to bind to one of the
|
||||
// banned noData elements
|
||||
|
@ -58,10 +59,7 @@ jQuery.event = {
|
|||
return;
|
||||
}
|
||||
|
||||
// Use a key less likely to result in collisions for plain JS objects.
|
||||
// Fixes bug #7150.
|
||||
var eventKey = elem.nodeType ? "events" : "__events__",
|
||||
events = elemData[ eventKey ],
|
||||
var events = elemData[ eventKey ],
|
||||
eventHandle = elemData.handle;
|
||||
|
||||
if ( typeof events === "function" ) {
|
||||
|
@ -177,8 +175,7 @@ jQuery.event = {
|
|||
}
|
||||
|
||||
var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
|
||||
eventKey = elem.nodeType ? "events" : "__events__",
|
||||
elemData = jQuery.data( elem ),
|
||||
elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
|
||||
events = elemData && elemData[ eventKey ];
|
||||
|
||||
if ( !elemData || !events ) {
|
||||
|
@ -290,10 +287,10 @@ jQuery.event = {
|
|||
delete elemData.handle;
|
||||
|
||||
if ( typeof elemData === "function" ) {
|
||||
jQuery.removeData( elem, eventKey );
|
||||
jQuery.removeData( elem, eventKey, true );
|
||||
|
||||
} else if ( jQuery.isEmptyObject( elemData ) ) {
|
||||
jQuery.removeData( elem );
|
||||
jQuery.removeData( elem, undefined, true );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -325,9 +322,16 @@ jQuery.event = {
|
|||
|
||||
// Only trigger if we've ever bound an event for it
|
||||
if ( jQuery.event.global[ type ] ) {
|
||||
// XXX This code smells terrible. event.js should not be directly
|
||||
// inspecting the data cache
|
||||
jQuery.each( jQuery.cache, function() {
|
||||
if ( this.events && this.events[type] ) {
|
||||
jQuery.event.trigger( event, data, this.handle.elem );
|
||||
// internalKey variable is just used to make it easier to find
|
||||
// and potentially change this stuff later; currently it just
|
||||
// points to jQuery.expando
|
||||
var internalKey = jQuery.expando,
|
||||
internalCache = this[ internalKey ];
|
||||
if ( internalCache && internalCache.events && internalCache.events[type] ) {
|
||||
jQuery.event.trigger( event, data, internalCache.handle.elem );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -353,8 +357,8 @@ jQuery.event = {
|
|||
|
||||
// Trigger the event, it is assumed that "handle" is a function
|
||||
var handle = elem.nodeType ?
|
||||
jQuery.data( elem, "handle" ) :
|
||||
(jQuery.data( elem, "__events__" ) || {}).handle;
|
||||
jQuery._data( elem, "handle" ) :
|
||||
(jQuery._data( elem, eventKey ) || {}).handle;
|
||||
|
||||
if ( handle ) {
|
||||
handle.apply( elem, data );
|
||||
|
@ -432,7 +436,7 @@ jQuery.event = {
|
|||
|
||||
event.namespace = event.namespace || namespace_sort.join(".");
|
||||
|
||||
events = jQuery.data(this, this.nodeType ? "events" : "__events__");
|
||||
events = jQuery._data(this, eventKey);
|
||||
|
||||
if ( typeof events === "function" ) {
|
||||
events = events.events;
|
||||
|
@ -787,12 +791,12 @@ if ( !jQuery.support.changeBubbles ) {
|
|||
return;
|
||||
}
|
||||
|
||||
data = jQuery.data( elem, "_change_data" );
|
||||
data = jQuery._data( elem, "_change_data" );
|
||||
val = getVal(elem);
|
||||
|
||||
// the current data will be also retrieved by beforeactivate
|
||||
if ( e.type !== "focusout" || elem.type !== "radio" ) {
|
||||
jQuery.data( elem, "_change_data", val );
|
||||
jQuery._data( elem, "_change_data", val );
|
||||
}
|
||||
|
||||
if ( data === undefined || val === data ) {
|
||||
|
@ -837,7 +841,7 @@ if ( !jQuery.support.changeBubbles ) {
|
|||
// information
|
||||
beforeactivate: function( e ) {
|
||||
var elem = e.target;
|
||||
jQuery.data( elem, "_change_data", getVal(elem) );
|
||||
jQuery._data( elem, "_change_data", getVal(elem) );
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -986,8 +990,8 @@ jQuery.fn.extend({
|
|||
|
||||
return this.click( jQuery.proxy( fn, function( event ) {
|
||||
// Figure out which function to execute
|
||||
var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
|
||||
jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
|
||||
var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
|
||||
jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );
|
||||
|
||||
// Make sure that clicks stop
|
||||
event.preventDefault();
|
||||
|
@ -1075,7 +1079,7 @@ function liveHandler( event ) {
|
|||
var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
|
||||
elems = [],
|
||||
selectors = [],
|
||||
events = jQuery.data( this, this.nodeType ? "events" : "__events__" );
|
||||
events = jQuery._data( this, eventKey );
|
||||
|
||||
if ( typeof events === "function" ) {
|
||||
events = events.events;
|
||||
|
|
|
@ -346,7 +346,7 @@ jQuery.fn.extend({
|
|||
table ?
|
||||
root(this[i], first) :
|
||||
this[i],
|
||||
i > 0 || results.cacheable || this.length > 1 ?
|
||||
i > 0 || results.cacheable || (this.length > 1 && i > 0) ?
|
||||
jQuery(fragment).clone(true)[0] :
|
||||
fragment
|
||||
);
|
||||
|
@ -381,17 +381,24 @@ function cloneCopyEvent(orig, ret) {
|
|||
throw "Cloned data mismatch";
|
||||
}
|
||||
|
||||
var oldData = jQuery.data( orig[nodeIndex] ),
|
||||
curData = jQuery.data( this, oldData ),
|
||||
events = oldData && oldData.events;
|
||||
var internalKey = jQuery.expando,
|
||||
oldData = jQuery.data( orig[nodeIndex] ),
|
||||
curData = jQuery.data( this, oldData );
|
||||
|
||||
if ( events ) {
|
||||
delete curData.handle;
|
||||
curData.events = {};
|
||||
// Switch to use the internal data object, if it exists, for the next
|
||||
// stage of data copying
|
||||
if ( (oldData = oldData[ internalKey ]) ) {
|
||||
var events = oldData.events;
|
||||
curData = curData[ internalKey ] = jQuery.extend({}, oldData);
|
||||
|
||||
for ( var type in events ) {
|
||||
for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
|
||||
jQuery.event.add( this, type, events[ type ][ i ], events[ type ][ i ].data );
|
||||
if ( events ) {
|
||||
delete curData.handle;
|
||||
curData.events = {};
|
||||
|
||||
for ( var type in events ) {
|
||||
for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
|
||||
jQuery.event.add( this, type, events[ type ][ i ], events[ type ][ i ].data );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -608,8 +615,7 @@ jQuery.extend({
|
|||
},
|
||||
|
||||
cleanData: function( elems ) {
|
||||
var data, id, cache = jQuery.cache,
|
||||
special = jQuery.event.special,
|
||||
var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
|
||||
deleteExpando = jQuery.support.deleteExpando;
|
||||
|
||||
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
|
||||
|
@ -620,13 +626,14 @@ jQuery.extend({
|
|||
id = elem[ jQuery.expando ];
|
||||
|
||||
if ( id ) {
|
||||
data = cache[ id ];
|
||||
data = cache[ id ] && cache[ id ][ internalKey ];
|
||||
|
||||
if ( data && data.events ) {
|
||||
for ( var type in data.events ) {
|
||||
if ( special[ type ] ) {
|
||||
jQuery.event.remove( elem, type );
|
||||
|
||||
// This is a shortcut to avoid jQuery.event.remove's overhead
|
||||
} else {
|
||||
jQuery.removeEvent( elem, type, data.handle );
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ jQuery.extend({
|
|||
}
|
||||
|
||||
type = (type || "fx") + "queue";
|
||||
var q = jQuery.data( elem, type );
|
||||
var q = jQuery._data( elem, type );
|
||||
|
||||
// Speed up dequeue by getting out quickly if this is just a lookup
|
||||
if ( !data ) {
|
||||
|
@ -15,7 +15,7 @@ jQuery.extend({
|
|||
}
|
||||
|
||||
if ( !q || jQuery.isArray(data) ) {
|
||||
q = jQuery.data( elem, type, jQuery.makeArray(data) );
|
||||
q = jQuery._data( elem, type, jQuery.makeArray(data) );
|
||||
|
||||
} else {
|
||||
q.push( data );
|
||||
|
@ -46,6 +46,10 @@ jQuery.extend({
|
|||
jQuery.dequeue(elem, type);
|
||||
});
|
||||
}
|
||||
|
||||
if ( !queue.length ) {
|
||||
jQuery.removeData( elem, type + "queue", true );
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue