aboutsummaryrefslogtreecommitdiffstats
path: root/src/data.js
diff options
context:
space:
mode:
authorRichard Gibson <richard.gibson@gmail.com>2013-02-23 12:41:37 -0500
committerDave Methvin <dave.methvin@gmail.com>2013-02-26 22:38:06 -0500
commit85f1985f2444da01054800d6f41c3a6057da2e16 (patch)
treed1d48d19a10680fd59545f216fa242a4fa09c080 /src/data.js
parentb55bfb140f4ccf871a38ec52f21f7ca698515e52 (diff)
downloadjquery-85f1985f2444da01054800d6f41c3a6057da2e16.tar.gz
jquery-85f1985f2444da01054800d6f41c3a6057da2e16.zip
Fix #13494: Fallback defineProperties to jQuery.extend. Close gh-1182.
Android<4 (ancient WebKit) doesn't have full ES5 support.
Diffstat (limited to 'src/data.js')
-rw-r--r--src/data.js64
1 files changed, 28 insertions, 36 deletions
diff --git a/src/data.js b/src/data.js
index 3685b7006..eea83ab92 100644
--- a/src/data.js
+++ b/src/data.js
@@ -14,44 +14,36 @@ var data_user, data_priv,
rmultiDash = /([A-Z])/g;
function Data() {
- // Data objects. Keys correspond to the
- // unlocker that is accessible via "locker" method
this.cache = {};
+ this.expando = jQuery.expando + Math.random();
}
Data.uid = 1;
Data.prototype = {
- locker: function( owner ) {
- var ovalueOf,
- // Check if the owner object has already been outfitted with a valueOf
- // "locker". They "key" is the "Data" constructor itself, which is scoped
- // to the IIFE that wraps jQuery. This prevents outside tampering with the
- // "valueOf" locker.
- unlock = owner.valueOf( Data );
-
- // If no "unlock" string exists, then create a valueOf "locker"
- // for storing the unlocker key. Since valueOf normally does not accept any
- // arguments, extant calls to valueOf will still behave as expected.
- if ( typeof unlock !== "string" ) {
- unlock = jQuery.expando + Data.uid++;
- ovalueOf = owner.valueOf;
-
- Object.defineProperty( owner, "valueOf", {
- value: function( pick ) {
- if ( pick === Data ) {
- return unlock;
- }
- return ovalueOf.apply( owner );
- }
- // By omitting explicit [ enumerable, writable, configurable ]
- // they will default to "false"
- });
+ key: function( owner ) {
+ var descriptor = {},
+ // Check if the owner object already has a cache key
+ unlock = owner[ this.expando ];
+
+ // If not, create one
+ if ( !unlock ) {
+ unlock = Data.uid++;
+ descriptor[ this.expando ] = { value: unlock };
+
+ // Secure it in a non-enumerable, non-writable property
+ try {
+ Object.defineProperties( owner, descriptor );
+
+ // Support: Android<4
+ // Fallback to a less secure definition
+ } catch ( e ) {
+ descriptor[ this.expando ] = unlock;
+ jQuery.extend( owner, descriptor );
+ }
}
- // If private or user data already create a valueOf locker
- // then we'll reuse the unlock key, but still need to create
- // a cache object for this instance (could be private or user)
+ // Ensure the cache object
if ( !this.cache[ unlock ] ) {
this.cache[ unlock ] = {};
}
@@ -64,7 +56,7 @@ Data.prototype = {
// There may be an unlock assigned to this node,
// if there is no entry for this "owner", create one inline
// and set the unlock as though an owner entry had always existed
- unlock = this.locker( owner );
+ unlock = this.key( owner );
cache = this.cache[ unlock ];
// Handle: [ owner, key, value ] args
@@ -74,7 +66,7 @@ Data.prototype = {
// Handle: [ owner, { properties } ] args
} else {
// [*] In the case where there was actually no "owner" entry and
- // this.locker( owner ) was called to create one, there will be
+ // this.key( owner ) was called to create one, there will be
// a corresponding empty plain object in the cache.
//
// Note, this will kill the reference between
@@ -102,7 +94,7 @@ Data.prototype = {
// New caches will be created and the unlock returned,
// allowing direct access to the newly created
// empty data object.
- var cache = this.cache[ this.locker( owner ) ];
+ var cache = this.cache[ this.key( owner ) ];
return key === undefined ?
cache : cache[ key ];
@@ -138,7 +130,7 @@ Data.prototype = {
},
remove: function( owner, key ) {
var i, l, name,
- unlock = this.locker( owner ),
+ unlock = this.key( owner ),
cache = this.cache[ unlock ];
if ( key === undefined ) {
@@ -178,11 +170,11 @@ Data.prototype = {
},
hasData: function( owner ) {
return !jQuery.isEmptyObject(
- this.cache[ this.locker( owner ) ]
+ this.cache[ this.key( owner ) ]
);
},
discard: function( owner ) {
- delete this.cache[ this.locker( owner ) ];
+ delete this.cache[ this.key( owner ) ];
}
};