aboutsummaryrefslogtreecommitdiffstats
path: root/test/unit
diff options
context:
space:
mode:
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>2020-10-19 21:17:51 +0200
committerMichał Gołębiowski-Owczarek <m.goleb@gmail.com>2020-10-19 21:21:54 +0200
commitaaf9c55ad252ed2241430f5e58e2ee448c3a6bb2 (patch)
treecba009a070cc896ddf6d25c4845c4972c8f3c256 /test/unit
parent4c572a7fee5cb45fd6f328933eee7c95e7de51cd (diff)
downloadjquery-aaf9c55ad252ed2241430f5e58e2ee448c3a6bb2.tar.gz
jquery-aaf9c55ad252ed2241430f5e58e2ee448c3a6bb2.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 (cherry picked from commit 5c2d08704e289dd2745bcb0557b35a9c0e6af4a4)
Diffstat (limited to 'test/unit')
-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 17f15b2a6..83ce5cc06 100644
--- a/test/unit/event.js
+++ b/test/unit/event.js
@@ -2625,6 +2625,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",