aboutsummaryrefslogtreecommitdiffstats
path: root/test/unit
diff options
context:
space:
mode:
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>2024-05-20 18:05:19 +0200
committerGitHub <noreply@github.com>2024-05-20 18:05:19 +0200
commit527fb3dcf0dcde69302a741dfc61cbfa58e99eb0 (patch)
tree1e3a6845a1c5cb3f70cc80584579c19f992149be /test/unit
parent5880e02707dcefc4ec527bd1c56f64b8b0eba391 (diff)
downloadjquery-527fb3dcf0dcde69302a741dfc61cbfa58e99eb0.tar.gz
jquery-527fb3dcf0dcde69302a741dfc61cbfa58e99eb0.zip
Event: Increase robustness of an inner native event in leverageNative
In Firefox, alert displayed just before blurring an element dispatches the native blur event twice which tripped the jQuery logic if a jQuery blur handler was not attached before the trigger call. This was because the `leverageNative` logic part for triggering first checked if setup was done before (which, for example, is done if a jQuery handler was registered before for this element+event pair) and - if it was not - added a dummy handler that just returned `true`. The `leverageNative` logic made that `true` then saved into private data, replacing the previous `saved` array. Since `true` passed the truthy check, the second native inner handler treated `true` as an array, crashing on the `slice` call. The same issue could happen if a handler returning `true` is attached before triggering. A bare `length` check would not be enough as the user handler may return an array-like as well. To remove this potential data shape clash, capture the inner result in an object with a `value` property instead of saving it directly. Since it's impossible to call `alert()` in unit tests, simulate the issue by replacing the `addEventListener` method on a test button with a version that calls attached blur handlers twice. Fixes gh-5459 Closes gh-5466 Ref gh-5236
Diffstat (limited to 'test/unit')
-rw-r--r--test/unit/event.js58
1 files changed, 58 insertions, 0 deletions
diff --git a/test/unit/event.js b/test/unit/event.js
index ac309d22d..111b1a18b 100644
--- a/test/unit/event.js
+++ b/test/unit/event.js
@@ -3502,6 +3502,64 @@ QUnit.test( "trigger(focus) fires native & jQuery handlers (gh-5015)", function(
input.trigger( "focus" );
} );
+QUnit.test( "duplicate native blur doesn't crash (gh-5459)", function( assert ) {
+ assert.expect( 4 );
+
+ function patchAddEventListener( elem ) {
+ var nativeAddEvent = elem[ 0 ].addEventListener;
+
+ // Support: Firefox 124+
+ // In Firefox, alert displayed just before blurring an element
+ // dispatches the native blur event twice which tripped the jQuery
+ // logic. We cannot call `alert()` in unit tests; simulate the
+ // behavior by overwriting the native `addEventListener` with
+ // a version that calls blur handlers twice.
+ //
+ // Such a simulation allows us to test whether `leverageNative`
+ // logic correctly differentiates between data saved by outer/inner
+ // handlers, so it's useful even without the Firefox bug.
+ elem[ 0 ].addEventListener = function( eventName, handler ) {
+ var finalHandler;
+ if ( eventName === "blur" ) {
+ finalHandler = function wrappedHandler() {
+ handler.apply( this, arguments );
+ return handler.apply( this, arguments );
+ };
+ } else {
+ finalHandler = handler;
+ }
+ return nativeAddEvent.call( this, eventName, finalHandler );
+ };
+ }
+
+ function runTest( handler, message ) {
+ var button = jQuery( "<button></button>" );
+
+ patchAddEventListener( button );
+ button.appendTo( "#qunit-fixture" );
+
+ if ( handler ) {
+ button.on( "blur", handler );
+ }
+ button.on( "focus", function() {
+ button.trigger( "blur" );
+ assert.ok( true, "Did not crash (" + message + ")" );
+ } );
+ button.trigger( "focus" );
+ }
+
+ runTest( undefined, "no prior handler" );
+ runTest( function() {
+ return true;
+ }, "prior handler returning true" );
+ runTest( function() {
+ return { length: 42 };
+ }, "prior handler returning an array-like" );
+ runTest( function() {
+ return { value: 42 };
+ }, "prior handler returning `{ value }`" );
+} );
+
// TODO replace with an adaptation of
// https://github.com/jquery/jquery/pull/1367/files#diff-a215316abbaabdf71857809e8673ea28R2464
( function() {