blob: ce6d8fa9bab48c7e3bdf5a47cf614f2ff08272fa [file] [log] [blame]
Copybara botbe50d492023-11-30 00:16:42 +01001define( [
2 "../core",
3 "../core/camelCase",
4 "../var/rnothtmlwhite",
5 "./var/acceptData"
6], function( jQuery, camelCase, rnothtmlwhite, acceptData ) {
7
8"use strict";
9
10function Data() {
11 this.expando = jQuery.expando + Data.uid++;
12}
13
14Data.uid = 1;
15
16Data.prototype = {
17
18 cache: function( owner ) {
19
20 // Check if the owner object already has a cache
21 var value = owner[ this.expando ];
22
23 // If not, create one
24 if ( !value ) {
Renovate botf591dcf2023-12-30 14:13:54 +000025 value = Object.create( null );
Copybara botbe50d492023-11-30 00:16:42 +010026
27 // We can accept data for non-element nodes in modern browsers,
28 // but we should not, see #8335.
29 // Always return an empty object.
30 if ( acceptData( owner ) ) {
31
32 // If it is a node unlikely to be stringify-ed or looped over
33 // use plain assignment
34 if ( owner.nodeType ) {
35 owner[ this.expando ] = value;
36
37 // Otherwise secure it in a non-enumerable property
38 // configurable must be true to allow the property to be
39 // deleted when data is removed
40 } else {
41 Object.defineProperty( owner, this.expando, {
42 value: value,
43 configurable: true
44 } );
45 }
46 }
47 }
48
49 return value;
50 },
51 set: function( owner, data, value ) {
52 var prop,
53 cache = this.cache( owner );
54
55 // Handle: [ owner, key, value ] args
56 // Always use camelCase key (gh-2257)
57 if ( typeof data === "string" ) {
58 cache[ camelCase( data ) ] = value;
59
60 // Handle: [ owner, { properties } ] args
61 } else {
62
63 // Copy the properties one-by-one to the cache object
64 for ( prop in data ) {
65 cache[ camelCase( prop ) ] = data[ prop ];
66 }
67 }
68 return cache;
69 },
70 get: function( owner, key ) {
71 return key === undefined ?
72 this.cache( owner ) :
73
74 // Always use camelCase key (gh-2257)
75 owner[ this.expando ] && owner[ this.expando ][ camelCase( key ) ];
76 },
77 access: function( owner, key, value ) {
78
79 // In cases where either:
80 //
81 // 1. No key was specified
82 // 2. A string key was specified, but no value provided
83 //
84 // Take the "read" path and allow the get method to determine
85 // which value to return, respectively either:
86 //
87 // 1. The entire cache object
88 // 2. The data stored at the key
89 //
90 if ( key === undefined ||
91 ( ( key && typeof key === "string" ) && value === undefined ) ) {
92
93 return this.get( owner, key );
94 }
95
96 // When the key is not a string, or both a key and value
97 // are specified, set or extend (existing objects) with either:
98 //
99 // 1. An object of properties
100 // 2. A key and value
101 //
102 this.set( owner, key, value );
103
104 // Since the "set" path can have two possible entry points
105 // return the expected data based on which path was taken[*]
106 return value !== undefined ? value : key;
107 },
108 remove: function( owner, key ) {
109 var i,
110 cache = owner[ this.expando ];
111
112 if ( cache === undefined ) {
113 return;
114 }
115
116 if ( key !== undefined ) {
117
118 // Support array or space separated string of keys
119 if ( Array.isArray( key ) ) {
120
121 // If key is an array of keys...
122 // We always set camelCase keys, so remove that.
123 key = key.map( camelCase );
124 } else {
125 key = camelCase( key );
126
127 // If a key with the spaces exists, use it.
128 // Otherwise, create an array by matching non-whitespace
129 key = key in cache ?
130 [ key ] :
131 ( key.match( rnothtmlwhite ) || [] );
132 }
133
134 i = key.length;
135
136 while ( i-- ) {
137 delete cache[ key[ i ] ];
138 }
139 }
140
141 // Remove the expando if there's no more data
142 if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
143
144 // Support: Chrome <=35 - 45
145 // Webkit & Blink performance suffers when deleting properties
146 // from DOM nodes, so set to undefined instead
147 // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
148 if ( owner.nodeType ) {
149 owner[ this.expando ] = undefined;
150 } else {
151 delete owner[ this.expando ];
152 }
153 }
154 },
155 hasData: function( owner ) {
156 var cache = owner[ this.expando ];
157 return cache !== undefined && !jQuery.isEmptyObject( cache );
158 }
159};
160
161return Data;
162} );