Skip to content

Commit 6e47006

Browse files
committed
Data:Event:Manipulation: Prevent collisions with Object.prototype properties
Make sure events & data keys matching Object.prototype properties work. A separate fix for such events on cloned elements was added as well. The commit also removes a fallback of the `events` private data to an empty object in `jQuery.event.dispatch` because that method is called from the `handle` function in element's private data and both `events` & `handle` are set and removed at the same time. Fixes gh-3256
1 parent 721744a commit 6e47006

File tree

6 files changed

+67
-9
lines changed

6 files changed

+67
-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: 2 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 ) {
@@ -293,7 +293,7 @@ jQuery.event = {
293293

294294
var i, j, ret, matched, handleObj, handlerQueue,
295295
args = new Array( arguments.length ),
296-
handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
296+
handlers = dataPriv.get( this, "events" )[ event.type ] || [],
297297
special = jQuery.event.special[ event.type ] || {};
298298

299299
// 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