🌐 AI搜索 & 代理 主页
Skip to content

Commit efb6e46

Browse files
committed
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 checks 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 - adds a dummy handler that just returns `true`. The `leverageNative` logic makes that `true` then saved into private data, replacing the previous `saved` array. Since `true` passes the truthy check, the second native inner handler treated `true` as an array, crashing on the `slice` call. 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 jquerygh-5459 Ref jquerygh-5236
1 parent 284b082 commit efb6e46

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

src/event.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -547,16 +547,13 @@ function leverageNative( el, type, isSetup ) {
547547
// If this is an inner synthetic event for an event with a bubbling surrogate
548548
// (focus or blur), assume that the surrogate already propagated from triggering
549549
// the native event and prevent that from happening again here.
550-
// This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the
551-
// bubbling surrogate propagates *after* the non-bubbling base), but that seems
552-
// less bad than duplication.
553550
} else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) {
554551
event.stopPropagation();
555552
}
556553

557554
// If this is a native event triggered above, everything is now in order
558555
// Fire an inner synthetic event with the original arguments
559-
} else if ( saved ) {
556+
} else if ( saved.length ) {
560557

561558
// ...and capture the result
562559
dataPriv.set( this, type, jQuery.event.trigger(

test/unit/event.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3493,6 +3493,40 @@ QUnit.test( "trigger(focus) fires native & jQuery handlers (gh-5015)", function(
34933493
input.trigger( "focus" );
34943494
} );
34953495

3496+
QUnit.test( "duplicate native blur doesn't crash (gh-5459)", function( assert ) {
3497+
assert.expect( 1 );
3498+
3499+
var button = jQuery( "<button></button>" ),
3500+
nativeAddEvent = button[ 0 ].addEventListener;
3501+
button.appendTo( "#qunit-fixture" );
3502+
3503+
button.on( "focus", function() {
3504+
button.trigger( "blur" );
3505+
assert.ok( true, "Did not crash" );
3506+
} );
3507+
3508+
// Support: Firefox 124+
3509+
// In Firefox, alert displayed just before blurring an element
3510+
// dispatches the native blur event twice which tripped the jQuery
3511+
// logic. We cannot call `alert()` in unit tests; simulate the
3512+
// behavior by overwriting the native `addEventListener` with
3513+
// a version that calls blur handlers twice.
3514+
button[ 0 ].addEventListener = function( eventName, handler ) {
3515+
var finalHandler;
3516+
if ( eventName === "blur" ) {
3517+
finalHandler = function wrappedHandler() {
3518+
handler.apply( this, arguments );
3519+
return handler.apply( this, arguments );
3520+
};
3521+
} else {
3522+
finalHandler = handler;
3523+
}
3524+
return nativeAddEvent.call( this, eventName, finalHandler );
3525+
};
3526+
3527+
button.trigger( "focus" );
3528+
} );
3529+
34963530
// TODO replace with an adaptation of
34973531
// https://github.com/jquery/jquery/pull/1367/files#diff-a215316abbaabdf71857809e8673ea28R2464
34983532
( function() {

0 commit comments

Comments
 (0)