diff --git a/src/data/Data.js b/src/data/Data.js index 556f4e39c09..a5eb090895d 100644 --- a/src/data/Data.js +++ b/src/data/Data.js @@ -18,7 +18,7 @@ Data.prototype = { // If not, create one if ( !value ) { - value = {}; + value = Object.create( null ); // We can accept data for non-element nodes in modern browsers, // but we should not, see #8335. diff --git a/src/event.js b/src/event.js index 796d9621039..dc00faf167f 100644 --- a/src/event.js +++ b/src/event.js @@ -135,7 +135,7 @@ jQuery.event = { // Init the element's event structure and main handler, if this is the first if ( !( events = elemData.events ) ) { - events = elemData.events = {}; + events = elemData.events = Object.create( null ); } if ( !( eventHandle = elemData.handle ) ) { eventHandle = elemData.handle = function( e ) { @@ -298,7 +298,7 @@ jQuery.event = { var i, j, ret, matched, handleObj, handlerQueue, args = new Array( arguments.length ), - handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [], + handlers = dataPriv.get( this, "events" )[ event.type ] || [], special = jQuery.event.special[ event.type ] || {}; // Use the fix-ed jQuery.Event rather than the (read-only) native event diff --git a/src/event/trigger.js b/src/event/trigger.js index aba4c7eddba..86d7ef9675a 100644 --- a/src/event/trigger.js +++ b/src/event/trigger.js @@ -99,8 +99,7 @@ jQuery.extend( jQuery.event, { special.bindType || type; // jQuery handler - handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] && - dataPriv.get( cur, "handle" ); + handle = dataPriv.get( cur, "handle" ); if ( handle ) { handle.apply( cur, data ); } diff --git a/src/manipulation.js b/src/manipulation.js index 7140748edf9..f71bab398c0 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -60,7 +60,7 @@ function restoreScript( elem ) { } function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + var i, l, type, pdataOld, udataOld, udataCur, events; if ( dest.nodeType !== 1 ) { return; @@ -68,13 +68,11 @@ function cloneCopyEvent( src, dest ) { // 1. Copy private data: events, handlers, etc. if ( dataPriv.hasData( src ) ) { - pdataOld = dataPriv.access( src ); - pdataCur = dataPriv.set( dest, pdataOld ); + pdataOld = dataPriv.get( src ); events = pdataOld.events; if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; + dataPriv.remove( dest, "handle events" ); for ( type in events ) { for ( i = 0, l = events[ type ].length; i < l; i++ ) { diff --git a/test/unit/data.js b/test/unit/data.js index 154ea5eebb3..d7ffaa0e601 100644 --- a/test/unit/data.js +++ b/test/unit/data.js @@ -998,3 +998,18 @@ QUnit.test( ".data(prop) does not create expando", function( assert ) { } } } ); + +QUnit.test( "keys matching Object.prototype properties (gh-3256)", function( assert ) { + assert.expect( 2 ); + + var div = jQuery( "
" ); + + assert.strictEqual( div.data( "hasOwnProperty" ), undefined, + "hasOwnProperty not matched (before forced data creation)" ); + + // Query the collection to force the creation of a data object for this element. + div.data(); + + assert.strictEqual( div.data( "hasOwnProperty" ), undefined, + "hasOwnProperty not matched (after forced data creation)" ); +} ); diff --git a/test/unit/event.js b/test/unit/event.js index cecad3f345d..938c66876d2 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -1796,6 +1796,49 @@ QUnit.test( "jQuery.off using dispatched jQuery.Event", function( assert ) { .remove(); } ); +QUnit.test( "events with type matching an Object.prototype property (gh-3256)", function( assert ) { + assert.expect( 1 ); + + var elem = jQuery( "
" ), + eventFired = false; + + elem.appendTo( "#qunit-fixture" ); + + try { + elem + .one( "hasOwnProperty", function() { + eventFired = true; + } ) + .trigger( "hasOwnProperty" ); + } finally { + assert.strictEqual( eventFired, true, "trigger fired without crashing" ); + } +} ); + +QUnit.test( "events with type matching an Object.prototype property, cloned element (gh-3256)", + function( assert ) { + assert.expect( 1 ); + + var elem = jQuery( "
" ), + eventFired = false; + + elem.appendTo( "#qunit-fixture" ); + + try { + // Make sure the original element has some event data. + elem.on( "click", function() {} ); + + elem + .clone( true ) + .one( "hasOwnProperty", function() { + eventFired = true; + } ) + .trigger( "hasOwnProperty" ); + } finally { + assert.strictEqual( eventFired, true, "trigger fired without crashing" ); + } +} ); + // selector-native does not support scope-fixing in delegation QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "delegated event with delegateTarget-relative selector", function( assert ) { assert.expect( 3 );