mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Event: Don't crash if an element is removed on blur
In Chrome, if an element having a `focusout` handler is blurred by clicking outside of it, it invokes the handler synchronously. If that handler calls `.remove()` on the element, the data is cleared, leaving private data undefined. We're reading a property from that data so we need to guard against this. Fixes gh-4417 Closes gh-4799
This commit is contained in:
parent
a503c691dc
commit
5c2d08704e
@ -558,7 +558,13 @@ function leverageNative( el, type, expectSync ) {
|
||||
// Cancel the outer synthetic event
|
||||
event.stopImmediatePropagation();
|
||||
event.preventDefault();
|
||||
return result.value;
|
||||
|
||||
// Support: Chrome 86+
|
||||
// In Chrome, if an element having a focusout handler is blurred by
|
||||
// clicking outside of it, it invokes the handler synchronously. If
|
||||
// that handler calls `.remove()` on the element, the data is cleared,
|
||||
// leaving `result` undefined. We need to guard against this.
|
||||
return result && result.value;
|
||||
}
|
||||
|
||||
// If this is an inner synthetic event for an event with a bubbling surrogate
|
||||
|
@ -2630,6 +2630,33 @@ QUnit.test( "focusin on document & window", function( assert ) {
|
||||
jQuery( document ).off( "focusout", increment );
|
||||
} );
|
||||
|
||||
QUnit.test( "element removed during focusout (gh-4417)", function( assert ) {
|
||||
assert.expect( 1 );
|
||||
|
||||
var button = jQuery( "<button>Click me</button>" );
|
||||
|
||||
button.appendTo( "#qunit-fixture" );
|
||||
|
||||
button.on( "click", function() {
|
||||
button.trigger( "blur" );
|
||||
assert.ok( true, "Removing the element didn't crash" );
|
||||
} );
|
||||
|
||||
// Support: Chrome 86+
|
||||
// In Chrome, if an element having a focusout handler is blurred by
|
||||
// clicking outside of it, it invokes the handler synchronously. However,
|
||||
// if the click happens programmatically, the invocation is asynchronous.
|
||||
// As we have no way to simulate real user input in unit tests, simulate
|
||||
// this behavior by calling `jQuery.cleanData` & removing the element using
|
||||
// native APIs.
|
||||
button[ 0 ].blur = function() {
|
||||
jQuery.cleanData( [ this ] );
|
||||
this.parentNode.removeChild( this );
|
||||
};
|
||||
|
||||
button[ 0 ].click();
|
||||
} );
|
||||
|
||||
testIframe(
|
||||
"jQuery.ready promise",
|
||||
"event/promiseReady.html",
|
||||
|
Loading…
Reference in New Issue
Block a user