aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Gibson <richard.gibson@gmail.com>2019-04-29 13:18:08 -0400
committerMichał Gołębiowski-Owczarek <m.goleb@gmail.com>2019-04-29 20:49:30 +0200
commitddfa83766478268391bc9da96683fc0d4973fcfe (patch)
tree93e6e74a4ea7db476fc2b8516c19eb0df56d2ced
parentb8d4712825a26a7f24c2bdb5a71aa3abcd345dfd (diff)
downloadjquery-ddfa83766478268391bc9da96683fc0d4973fcfe.tar.gz
jquery-ddfa83766478268391bc9da96683fc0d4973fcfe.zip
Event: Fix handling of multiple async focus events
(cherry-picked from 24d71ac70406f522fc1b09bf7c4025251ec3aee6) Fixes gh-4350 Closes gh-4354
-rw-r--r--src/event.js30
-rw-r--r--test/unit/event.js43
2 files changed, 61 insertions, 12 deletions
diff --git a/src/event.js b/src/event.js
index b63b93b96..48d9095c9 100644
--- a/src/event.js
+++ b/src/event.js
@@ -554,9 +554,13 @@ function leverageNative( el, type, expectSync ) {
if ( ( event.isTrigger & 1 ) && this[ type ] ) {
// Interrupt processing of the outer synthetic .trigger()ed event
- if ( !saved ) {
+ // Saved data should be false in such cases, but might be a leftover capture object
+ // from an async native handler (gh-4350)
+ if ( !saved.length ) {
// Store arguments for use when handling the inner native event
+ // There will always be at least one argument (an event object), so this array
+ // will not be confused with a leftover capture object.
saved = slice.call( arguments );
dataPriv.set( this, type, saved );
@@ -569,14 +573,14 @@ function leverageNative( el, type, expectSync ) {
if ( saved !== result || notAsync ) {
dataPriv.set( this, type, false );
} else {
- result = undefined;
+ result = {};
}
if ( saved !== result ) {
// Cancel the outer synthetic event
event.stopImmediatePropagation();
event.preventDefault();
- return result;
+ return result.value;
}
// If this is an inner synthetic event for an event with a bubbling surrogate
@@ -591,17 +595,19 @@ function leverageNative( el, type, expectSync ) {
// If this is a native event triggered above, everything is now in order
// Fire an inner synthetic event with the original arguments
- } else if ( saved ) {
+ } else if ( saved.length ) {
// ...and capture the result
- dataPriv.set( this, type, jQuery.event.trigger(
-
- // Support: IE <=9 - 11+
- // Extend with the prototype to reset the above stopImmediatePropagation()
- jQuery.extend( saved.shift(), jQuery.Event.prototype ),
- saved,
- this
- ) );
+ dataPriv.set( this, type, {
+ value: jQuery.event.trigger(
+
+ // Support: IE <=9 - 11+
+ // Extend with the prototype to reset the above stopImmediatePropagation()
+ jQuery.extend( saved[ 0 ], jQuery.Event.prototype ),
+ saved.slice( 1 ),
+ this
+ )
+ } );
// Abort handling of the native event
event.stopImmediatePropagation();
diff --git a/test/unit/event.js b/test/unit/event.js
index c7497b9b0..17706a8b1 100644
--- a/test/unit/event.js
+++ b/test/unit/event.js
@@ -3041,6 +3041,49 @@ QUnit.test( "focus-blur order (#12868)", function( assert ) {
}, 50 );
} );
+QUnit.test( "Event handling works with multiple async focus events (gh-4350)", function( assert ) {
+ assert.expect( 3 );
+
+ var remaining = 3,
+ input = jQuery( "#name" ),
+
+ // Support: IE <=9 - 11+
+ // focus and blur events are asynchronous; this is the resulting mess.
+ // The browser window must be topmost for this to work properly!!
+ done = assert.async();
+
+ input
+ .on( "focus", function() {
+ remaining--;
+ assert.ok( true, "received focus event, expecting " + remaining + " more" );
+ if ( remaining > 0 ) {
+ input.trigger( "blur" );
+ } else {
+ done();
+ }
+ } )
+ .on( "blur", function() {
+ setTimeout( function() {
+ input.trigger( "focus" );
+ } );
+ } );
+
+ // gain focus
+ input.trigger( "focus" );
+
+ // DOM focus is unreliable in TestSwarm
+ setTimeout( function() {
+ if ( QUnit.isSwarm && remaining === 3 ) {
+ assert.ok( true, "GAP: Could not observe focus change" );
+ assert.ok( true, "GAP: Could not observe focus change" );
+ assert.ok( true, "GAP: Could not observe focus change" );
+ setTimeout( function() {
+ done();
+ } );
+ }
+ } );
+} );
+
QUnit.test( "native-backed events preserve trigger data (gh-1741, gh-4139)", function( assert ) {
assert.expect( 17 );