Skip to content

Commit 9d76c0b

Browse files
authored
Data:Event:Manipulation: Prevent collisions with Object.prototype
Make sure events & data keys matching Object.prototype properties work. A separate fix for such events on cloned elements was added as well. Fixes gh-3256 Closes gh-4603
1 parent 358b769 commit 9d76c0b

File tree

6 files changed

+69
-9
lines changed

6 files changed

+69
-9
lines changed

src/data/Data.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Data.prototype = {
1818

1919
// If not, create one
2020
if ( !value ) {
21-
value = {};
21+
value = Object.create( null );
2222

2323
// We can accept data for non-element nodes in modern browsers,
2424
// but we should not, see #8335.

src/event.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ jQuery.event = {
133133

134134
// Init the element's event structure and main handler, if this is the first
135135
if ( !( events = elemData.events ) ) {
136-
events = elemData.events = {};
136+
events = elemData.events = Object.create( null );
137137
}
138138
if ( !( eventHandle = elemData.handle ) ) {
139139
eventHandle = elemData.handle = function( e ) {
@@ -294,7 +294,9 @@ jQuery.event = {
294294
// Make a writable jQuery.Event from the native event object
295295
event = jQuery.event.fix( nativeEvent ),
296296

297-
handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
297+
handlers = (
298+
dataPriv.get( this, "events" ) || Object.create( null )
299+
)[ event.type ] || [],
298300
special = jQuery.event.special[ event.type ] || {};
299301

300302
// Use the fix-ed jQuery.Event rather than the (read-only) native event

src/event/trigger.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ jQuery.extend( jQuery.event, {
9999
special.bindType || type;
100100

101101
// jQuery handler
102-
handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
102+
handle = (
103+
dataPriv.get( cur, "events" ) || Object.create( null )
104+
)[ event.type ] &&
103105
dataPriv.get( cur, "handle" );
104106
if ( handle ) {
105107
handle.apply( cur, data );

src/manipulation.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,19 @@ function restoreScript( elem ) {
6060
}
6161

6262
function cloneCopyEvent( src, dest ) {
63-
var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
63+
var i, l, type, pdataOld, udataOld, udataCur, events;
6464

6565
if ( dest.nodeType !== 1 ) {
6666
return;
6767
}
6868

6969
// 1. Copy private data: events, handlers, etc.
7070
if ( dataPriv.hasData( src ) ) {
71-
pdataOld = dataPriv.access( src );
72-
pdataCur = dataPriv.set( dest, pdataOld );
71+
pdataOld = dataPriv.get( src );
7372
events = pdataOld.events;
7473

7574
if ( events ) {
76-
delete pdataCur.handle;
77-
pdataCur.events = {};
75+
dataPriv.remove( dest, "handle events" );
7876

7977
for ( type in events ) {
8078
for ( i = 0, l = events[ type ].length; i < l; i++ ) {

test/unit/data.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -998,3 +998,18 @@ QUnit.test( ".data(prop) does not create expando", function( assert ) {
998998
}
999999
}
10001000
} );
1001+
1002+
QUnit.test( "keys matching Object.prototype properties (gh-3256)", function( assert ) {
1003+
assert.expect( 2 );
1004+
1005+
var div = jQuery( "<div/>" );
1006+
1007+
assert.strictEqual( div.data( "hasOwnProperty" ), undefined,
1008+
"hasOwnProperty not matched (before forced data creation)" );
1009+
1010+
// Force the creation of a data object for this element.
1011+
div.data( { foo: "bar" } );
1012+
1013+
assert.strictEqual( div.data( "hasOwnProperty" ), undefined,
1014+
"hasOwnProperty not matched (after forced data creation)" );
1015+
} );

test/unit/event.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,6 +1796,49 @@ QUnit.test( "jQuery.off using dispatched jQuery.Event", function( assert ) {
17961796
.remove();
17971797
} );
17981798

1799+
QUnit.test( "events with type matching an Object.prototype property (gh-3256)", function( assert ) {
1800+
assert.expect( 1 );
1801+
1802+
var elem = jQuery( "<div/>" ),
1803+
eventFired = false;
1804+
1805+
elem.appendTo( "#qunit-fixture" );
1806+
1807+
try {
1808+
elem
1809+
.one( "hasOwnProperty", function() {
1810+
eventFired = true;
1811+
} )
1812+
.trigger( "hasOwnProperty" );
1813+
} finally {
1814+
assert.strictEqual( eventFired, true, "trigger fired without crashing" );
1815+
}
1816+
} );
1817+
1818+
QUnit.test( "events with type matching an Object.prototype property, cloned element (gh-3256)",
1819+
function( assert ) {
1820+
assert.expect( 1 );
1821+
1822+
var elem = jQuery( "<div/>" ),
1823+
eventFired = false;
1824+
1825+
elem.appendTo( "#qunit-fixture" );
1826+
1827+
try {
1828+
// Make sure the original element has some event data.
1829+
elem.on( "click", function() {} );
1830+
1831+
elem
1832+
.clone( true )
1833+
.one( "hasOwnProperty", function() {
1834+
eventFired = true;
1835+
} )
1836+
.trigger( "hasOwnProperty" );
1837+
} finally {
1838+
assert.strictEqual( eventFired, true, "trigger fired without crashing" );
1839+
}
1840+
} );
1841+
17991842
// selector-native does not support scope-fixing in delegation
18001843
QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "delegated event with delegateTarget-relative selector", function( assert ) {
18011844
assert.expect( 3 );

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy