Commit 85f1985f authored by Richard Gibson's avatar Richard Gibson Committed by Dave Methvin

Fix #13494: Fallback defineProperties to jQuery.extend. Close gh-1182.

Android<4 (ancient WebKit) doesn't have full ES5 support.
parent b55bfb14
...@@ -14,44 +14,36 @@ var data_user, data_priv, ...@@ -14,44 +14,36 @@ var data_user, data_priv,
rmultiDash = /([A-Z])/g; rmultiDash = /([A-Z])/g;
function Data() { function Data() {
// Data objects. Keys correspond to the
// unlocker that is accessible via "locker" method
this.cache = {}; this.cache = {};
this.expando = jQuery.expando + Math.random();
} }
Data.uid = 1; Data.uid = 1;
Data.prototype = { Data.prototype = {
locker: function( owner ) { key: function( owner ) {
var ovalueOf, var descriptor = {},
// Check if the owner object has already been outfitted with a valueOf // Check if the owner object already has a cache key
// "locker". They "key" is the "Data" constructor itself, which is scoped unlock = owner[ this.expando ];
// to the IIFE that wraps jQuery. This prevents outside tampering with the
// "valueOf" locker. // If not, create one
unlock = owner.valueOf( Data ); if ( !unlock ) {
unlock = Data.uid++;
// If no "unlock" string exists, then create a valueOf "locker" descriptor[ this.expando ] = { value: unlock };
// for storing the unlocker key. Since valueOf normally does not accept any
// arguments, extant calls to valueOf will still behave as expected. // Secure it in a non-enumerable, non-writable property
if ( typeof unlock !== "string" ) { try {
unlock = jQuery.expando + Data.uid++; Object.defineProperties( owner, descriptor );
ovalueOf = owner.valueOf;
// Support: Android<4
Object.defineProperty( owner, "valueOf", { // Fallback to a less secure definition
value: function( pick ) { } catch ( e ) {
if ( pick === Data ) { descriptor[ this.expando ] = unlock;
return unlock; jQuery.extend( owner, descriptor );
}
return ovalueOf.apply( owner );
} }
// By omitting explicit [ enumerable, writable, configurable ]
// they will default to "false"
});
} }
// If private or user data already create a valueOf locker // Ensure the cache object
// then we'll reuse the unlock key, but still need to create
// a cache object for this instance (could be private or user)
if ( !this.cache[ unlock ] ) { if ( !this.cache[ unlock ] ) {
this.cache[ unlock ] = {}; this.cache[ unlock ] = {};
} }
...@@ -64,7 +56,7 @@ Data.prototype = { ...@@ -64,7 +56,7 @@ Data.prototype = {
// There may be an unlock assigned to this node, // There may be an unlock assigned to this node,
// if there is no entry for this "owner", create one inline // if there is no entry for this "owner", create one inline
// and set the unlock as though an owner entry had always existed // and set the unlock as though an owner entry had always existed
unlock = this.locker( owner ); unlock = this.key( owner );
cache = this.cache[ unlock ]; cache = this.cache[ unlock ];
// Handle: [ owner, key, value ] args // Handle: [ owner, key, value ] args
...@@ -74,7 +66,7 @@ Data.prototype = { ...@@ -74,7 +66,7 @@ Data.prototype = {
// Handle: [ owner, { properties } ] args // Handle: [ owner, { properties } ] args
} else { } else {
// [*] In the case where there was actually no "owner" entry and // [*] 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. // a corresponding empty plain object in the cache.
// //
// Note, this will kill the reference between // Note, this will kill the reference between
...@@ -102,7 +94,7 @@ Data.prototype = { ...@@ -102,7 +94,7 @@ Data.prototype = {
// New caches will be created and the unlock returned, // New caches will be created and the unlock returned,
// allowing direct access to the newly created // allowing direct access to the newly created
// empty data object. // empty data object.
var cache = this.cache[ this.locker( owner ) ]; var cache = this.cache[ this.key( owner ) ];
return key === undefined ? return key === undefined ?
cache : cache[ key ]; cache : cache[ key ];
...@@ -138,7 +130,7 @@ Data.prototype = { ...@@ -138,7 +130,7 @@ Data.prototype = {
}, },
remove: function( owner, key ) { remove: function( owner, key ) {
var i, l, name, var i, l, name,
unlock = this.locker( owner ), unlock = this.key( owner ),
cache = this.cache[ unlock ]; cache = this.cache[ unlock ];
if ( key === undefined ) { if ( key === undefined ) {
...@@ -178,11 +170,11 @@ Data.prototype = { ...@@ -178,11 +170,11 @@ Data.prototype = {
}, },
hasData: function( owner ) { hasData: function( owner ) {
return !jQuery.isEmptyObject( return !jQuery.isEmptyObject(
this.cache[ this.locker( owner ) ] this.cache[ this.key( owner ) ]
); );
}, },
discard: function( owner ) { discard: function( owner ) {
delete this.cache[ this.locker( owner ) ]; delete this.cache[ this.key( owner ) ];
} }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment