5 ], function( jQuery, rnotwhite ) {
9 // Old WebKit does not have Object.preventExtensions/freeze method,
10 // return new empty object instead with no [[set]] accessor
11 Object.defineProperty( this.cache = {}, 0, {
17 this.expando = jQuery.expando + Data.uid++;
21 Data.accepts = jQuery.acceptData;
24 key: function( owner ) {
25 // We can accept data for non-element nodes in modern browsers,
26 // but we should not, see #8335.
27 // Always return the key for a frozen object.
28 if ( !Data.accepts( owner ) ) {
33 // Check if the owner object already has a cache key
34 unlock = owner[ this.expando ];
40 // Secure it in a non-enumerable, non-writable property
42 descriptor[ this.expando ] = { value: unlock };
43 Object.defineProperties( owner, descriptor );
46 // Fallback to a less secure definition
48 descriptor[ this.expando ] = unlock;
49 jQuery.extend( owner, descriptor );
53 // Ensure the cache object
54 if ( !this.cache[ unlock ] ) {
55 this.cache[ unlock ] = {};
60 set: function( owner, data, value ) {
62 // There may be an unlock assigned to this node,
63 // if there is no entry for this "owner", create one inline
64 // and set the unlock as though an owner entry had always existed
65 unlock = this.key( owner ),
66 cache = this.cache[ unlock ];
68 // Handle: [ owner, key, value ] args
69 if ( typeof data === "string" ) {
70 cache[ data ] = value;
72 // Handle: [ owner, { properties } ] args
74 // Fresh assignments by object are shallow copied
75 if ( jQuery.isEmptyObject( cache ) ) {
76 jQuery.extend( this.cache[ unlock ], data );
77 // Otherwise, copy the properties one-by-one to the cache object
79 for ( prop in data ) {
80 cache[ prop ] = data[ prop ];
86 get: function( owner, key ) {
87 // Either a valid cache is found, or will be created.
88 // New caches will be created and the unlock returned,
89 // allowing direct access to the newly created
90 // empty data object. A valid owner object must be provided.
91 var cache = this.cache[ this.key( owner ) ];
93 return key === undefined ?
96 access: function( owner, key, value ) {
98 // In cases where either:
100 // 1. No key was specified
101 // 2. A string key was specified, but no value provided
103 // Take the "read" path and allow the get method to determine
104 // which value to return, respectively either:
106 // 1. The entire cache object
107 // 2. The data stored at the key
109 if ( key === undefined ||
110 ((key && typeof key === "string") && value === undefined) ) {
112 stored = this.get( owner, key );
114 return stored !== undefined ?
115 stored : this.get( owner, jQuery.camelCase(key) );
118 // [*]When the key is not a string, or both a key and value
119 // are specified, set or extend (existing objects) with either:
121 // 1. An object of properties
122 // 2. A key and value
124 this.set( owner, key, value );
126 // Since the "set" path can have two possible entry points
127 // return the expected data based on which path was taken[*]
128 return value !== undefined ? value : key;
130 remove: function( owner, key ) {
132 unlock = this.key( owner ),
133 cache = this.cache[ unlock ];
135 if ( key === undefined ) {
136 this.cache[ unlock ] = {};
139 // Support array or space separated string of keys
140 if ( jQuery.isArray( key ) ) {
141 // If "name" is an array of keys...
142 // When data is initially created, via ("key", "val") signature,
143 // keys will be converted to camelCase.
144 // Since there is no way to tell _how_ a key was added, remove
145 // both plain key and camelCase key. #12786
146 // This will only penalize the array argument path.
147 name = key.concat( key.map( jQuery.camelCase ) );
149 camel = jQuery.camelCase( key );
150 // Try the string as a key before any manipulation
151 if ( key in cache ) {
152 name = [ key, camel ];
154 // If a key with the spaces exists, use it.
155 // Otherwise, create an array by matching non-whitespace
157 name = name in cache ?
158 [ name ] : ( name.match( rnotwhite ) || [] );
164 delete cache[ name[ i ] ];
168 hasData: function( owner ) {
169 return !jQuery.isEmptyObject(
170 this.cache[ owner[ this.expando ] ] || {}
173 discard: function( owner ) {
174 if ( owner[ this.expando ] ) {
175 delete this.cache[ owner[ this.expando ] ];