]> source.dussan.org Git - jquery.git/commitdiff
Data: avoid using delete on DOM nodes
authorJason Bedard <jason+github@jbedard.ca>
Sat, 18 Jul 2015 18:27:11 +0000 (11:27 -0700)
committerMichał Gołębiowski <m.goleb@gmail.com>
Tue, 8 Sep 2015 18:22:54 +0000 (20:22 +0200)
Closes gh-2479

src/data/Data.js
src/manipulation.js
test/unit/data.js
test/unit/event.js
test/unit/manipulation.js

index e0d1eadcd9f4f64f51544e751472320c97778846..625d203cf9b9b8d1fe2cb75a567d20d63617a16f 100644 (file)
@@ -20,13 +20,12 @@ Data.prototype = {
                if ( owner.nodeType ) {
                        owner[ this.expando ] = value;
 
-               // Otherwise secure it in a non-enumerable, non-writable property
-               // configurability must be true to allow the property to be
-               // deleted with the delete operator
+               // Otherwise secure it in a non-enumerable property
+               // configurable must be true to allow the property to be
+               // deleted when data is removed
                } else {
                        Object.defineProperty( owner, this.expando, {
                                value: value,
-                               writable: true,
                                configurable: true
                        } );
                }
@@ -144,7 +143,16 @@ Data.prototype = {
 
                // Remove the expando if there's no more data
                if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
-                       delete owner[ this.expando ];
+
+                       // Support: Chrome <= 35-45+
+                       // Webkit & Blink performance suffers when deleting properties
+                       // from DOM nodes, so set to undefined instead
+                       // https://code.google.com/p/chromium/issues/detail?id=378607
+                       if ( owner.nodeType ) {
+                               owner[ this.expando ] = undefined;
+                       } else {
+                               delete owner[ this.expando ];
+                       }
                }
        },
        hasData: function( owner ) {
index b85ef1824d2582d5e364012db032891503589404..ceb970cbd5957d38053f9c1b16d4935a000354d9 100644 (file)
@@ -290,10 +290,16 @@ jQuery.extend( {
                                                        }
                                                }
                                        }
-                                       delete elem[ dataPriv.expando ];
+
+                                       // Support: Chrome <= 35-45+
+                                       // Assign undefined instead of using delete, see Data#remove
+                                       elem[ dataPriv.expando ] = undefined;
                                }
                                if ( elem[ dataUser.expando ] ) {
-                                       delete elem[ dataUser.expando ];
+
+                                       // Support: Chrome <= 35-45+
+                                       // Assign undefined instead of using delete, see Data#remove
+                                       elem[ dataUser.expando ] = undefined;
                                }
                        }
                }
index 53cd3a4bbbc6c6a2ea2700ec9b185b0e0048f348..9b0e2314c9c6d3fb0a026118f232942fc0fbd1a2 100644 (file)
@@ -867,7 +867,7 @@ testIframeWithCallback(
 );
 
 QUnit.test( "Check that the expando is removed when there's no more data", function( assert ) {
-       assert.expect( 1 );
+       assert.expect( 2 );
 
        var key,
                div = jQuery( "<div/>" );
@@ -877,6 +877,23 @@ QUnit.test( "Check that the expando is removed when there's no more data", funct
 
        // Make sure the expando is gone
        for ( key in div[ 0 ] ) {
+               if ( /^jQuery/.test( key ) ) {
+                       assert.strictEqual( div[ 0 ][ key ], undefined, "Expando was not removed when there was no more data" );
+               }
+       }
+});
+
+QUnit.test( "Check that the expando is removed when there's no more data on non-nodes", function( assert ) {
+       assert.expect( 1 );
+
+       var key,
+               obj = jQuery( {key: 42} );
+       obj.data( "some", "data" );
+       assert.equal( obj.data( "some" ), "data", "Data is added" );
+       obj.removeData( "some" );
+
+       // Make sure the expando is gone
+       for ( key in obj[ 0 ] ) {
                if ( /^jQuery/.test( key ) ) {
                        assert.ok( false, "Expando was not removed when there was no more data" );
                }
index f932317d2c2be27fe608275e1fc2eda18ea499c8..0f0c9e6dfe5109ab58804bab5ed2ea4423a2af4e 100644 (file)
@@ -2702,7 +2702,7 @@ QUnit.test( "Inline event result is returned (#13993)", function( assert ) {
 } );
 
 QUnit.test( ".off() removes the expando when there's no more data", function( assert ) {
-       assert.expect( 1 );
+       assert.expect( 2 );
 
        var key,
                div = jQuery( "<div/>" ).appendTo( "#qunit-fixture" );
@@ -2717,7 +2717,10 @@ QUnit.test( ".off() removes the expando when there's no more data", function( as
        // Make sure the expando is gone
        for ( key in div[ 0 ] ) {
                if ( /^jQuery/.test( key ) ) {
-                       assert.ok( false, "Expando was not removed when there was no more data" );
+                       assert.strictEqual(
+                               div[ 0 ][ key ], undefined,
+                               "Expando was not removed when there was no more data"
+                       );
                }
        }
 } );
index d9f1b0247e66eeba2435c408bd03dd923f6f62cf..37da1206268be4a9d1bc05d037cf6357d2c2f210 100644 (file)
@@ -2086,7 +2086,7 @@ QUnit.test( "jQuery.cleanData eliminates all private data (gh-2127)", function(
 } );
 
 QUnit.test( "jQuery.cleanData eliminates all public data", function( assert ) {
-       assert.expect( 2 );
+       assert.expect( 3 );
 
        var key,
                div = jQuery( "<div/>" );
@@ -2100,7 +2100,7 @@ QUnit.test( "jQuery.cleanData eliminates all public data", function( assert ) {
        // Make sure the expando is gone
        for ( key in div[ 0 ] ) {
                if ( /^jQuery/.test( key ) ) {
-                       assert.ok( false, "Expando was not removed when there was no more data" );
+                       assert.strictEqual( div[ 0 ][ key ], undefined, "Expando was not removed when there was no more data" );
                }
        }
 } );