diff options
author | Michał Gołębiowski-Owczarek <m.goleb@gmail.com> | 2020-10-19 21:17:51 +0200 |
---|---|---|
committer | Michał Gołębiowski-Owczarek <m.goleb@gmail.com> | 2020-10-19 21:21:54 +0200 |
commit | aaf9c55ad252ed2241430f5e58e2ee448c3a6bb2 (patch) | |
tree | cba009a070cc896ddf6d25c4845c4972c8f3c256 /test/unit | |
parent | 4c572a7fee5cb45fd6f328933eee7c95e7de51cd (diff) | |
download | jquery-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.js | 27 |
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", |