aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>2020-10-19 21:17:51 +0200
committerGitHub <noreply@github.com>2020-10-19 21:17:51 +0200
commit5c2d08704e289dd2745bcb0557b35a9c0e6af4a4 (patch)
treeeb5fb38fac065c649ec94bae2b0130bc4a6197b6 /test
parenta503c691dc06c59acdafef6e54eca2613c6e4032 (diff)
downloadjquery-5c2d08704e289dd2745bcb0557b35a9c0e6af4a4.tar.gz
jquery-5c2d08704e289dd2745bcb0557b35a9c0e6af4a4.zip
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
Diffstat (limited to 'test')
-rw-r--r--test/unit/event.js27
1 files changed, 27 insertions, 0 deletions
diff --git a/test/unit/event.js b/test/unit/event.js
index 771283c2f..90318f8fe 100644
--- a/test/unit/event.js
+++ b/test/unit/event.js
@@ -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",