From 59f7b55bf6dad71eee6434116566356d597f1d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Mon, 27 Mar 2023 21:24:42 +0200 Subject: [PATCH] Event: Simulate focus/blur in IE via focusin/focusout (3.x version) In IE (all versions), `focus` & `blur` handlers are fired asynchronously but `focusin` & `focusout` are run synchronously. In other browsers, all those handlers are fired synchronously. Asynchronous behavior of these handlers in IE caused issues for IE (gh-4856, gh-4859). We now simulate `focus` via `focusin` & `blur` via `focusout` in IE to avoid these issues. This also let us simplify some tests. This commit also simplifies `leverageNative` - with IE now using `focusin` to simulate `focus` and `focusout` to simulate `blur`, we don't have to deal with async events in `leverageNative`. This also fixes broken `focus` triggers after first triggering it on a hidden element - previously, `leverageNative` assumed that the native `focus` handler not firing after calling the native `focus` method meant it would be handled later, asynchronously, which was not the case (gh-4950). To preserve relative `focusin`/`focus` & `focusout`/`blur` event order guaranteed on the 3.x branch, attach a single handler for both events in IE. A side effect of this is that to reduce size the `event/focusin` module no longer exists and it's impossible to disable the `focusin` patch in modern browsers via the jQuery custom build system. Fixes gh-4856 Fixes gh-4859 Fixes gh-4950 Ref gh-5223 Closes gh-5224 Co-authored-by: Richard Gibson --- README.md | 1 - src/event.js | 196 +++++++++++++++++++++++++++----------- src/event/focusin.js | 58 ----------- src/event/support.js | 11 --- src/jquery.js | 1 - test/unit/event.js | 222 ++++++++++++++++++++++++++++++------------- test/unit/support.js | 15 --- 7 files changed, 300 insertions(+), 204 deletions(-) delete mode 100644 src/event/focusin.js delete mode 100644 src/event/support.js diff --git a/README.md b/README.md index 84e24b7e9..53c94df55 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,6 @@ Some example modules that can be excluded are: - **dimensions**: The `.width()` and `.height()` methods, including `inner-` and `outer-` variations. - **effects**: The `.animate()` method and its shorthands such as `.slideUp()` or `.hide("slow")`. - **event**: The `.on()` and `.off()` methods and all event functionality. -- **event/focusin**: Cross-browser support for the focusin and focusout events. - **event/trigger**: The `.trigger()` and `.triggerHandler()` methods. - **offset**: The `.offset()`, `.position()`, `.offsetParent()`, `.scrollLeft()`, and `.scrollTop()` methods. - **wrap**: The `.wrap()`, `.wrapAll()`, `.wrapInner()`, and `.unwrap()` methods. diff --git a/src/event.js b/src/event.js index 5925a4070..1d5c495d5 100644 --- a/src/event.js +++ b/src/event.js @@ -27,25 +27,6 @@ function returnFalse() { return false; } -// Support: IE <=9 - 11+ -// focus() and blur() are asynchronous, except when they are no-op. -// So expect focus to be synchronous when the element is already active, -// and blur to be synchronous when the element is not already active. -// (focus and blur are always synchronous in other supported browsers, -// this just defines when we can count on it). -function expectSync( elem, type ) { - return ( elem === safeActiveElement() ) === ( type === "focus" ); -} - -// Support: IE <=9 only -// Accessing document.activeElement can throw unexpectedly -// https://bugs.jquery.com/ticket/13393 -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - function on( elem, types, selector, data, fn, one ) { var origFn, type; @@ -483,7 +464,7 @@ jQuery.event = { el.click && nodeName( el, "input" ) ) { // dataPriv.set( el, "click", ... ) - leverageNative( el, "click", returnTrue ); + leverageNative( el, "click", true ); } // Return false to allow normal processing in the caller @@ -534,10 +515,10 @@ jQuery.event = { // synthetic events by interrupting progress until reinvoked in response to // *native* events that it fires directly, ensuring that state changes have // already occurred before other listeners are invoked. -function leverageNative( el, type, expectSync ) { +function leverageNative( el, type, isSetup ) { - // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add - if ( !expectSync ) { + // Missing `isSetup` indicates a trigger call, which must force setup through jQuery.event.add + if ( !isSetup ) { if ( dataPriv.get( el, type ) === undefined ) { jQuery.event.add( el, type, returnTrue ); } @@ -549,15 +530,13 @@ function leverageNative( el, type, expectSync ) { jQuery.event.add( el, type, { namespace: false, handler: function( event ) { - var notAsync, result, + var result, saved = dataPriv.get( this, type ); if ( ( event.isTrigger & 1 ) && this[ type ] ) { // Interrupt processing of the outer synthetic .trigger()ed event - // Saved data should be false in such cases, but might be a leftover capture object - // from an async native handler (gh-4350) - if ( !saved.length ) { + if ( !saved ) { // Store arguments for use when handling the inner native event // There will always be at least one argument (an event object), so this array @@ -566,28 +545,17 @@ function leverageNative( el, type, expectSync ) { dataPriv.set( this, type, saved ); // Trigger the native event and capture its result - // Support: IE <=9 - 11+ - // focus() and blur() are asynchronous - notAsync = expectSync( this, type ); this[ type ](); result = dataPriv.get( this, type ); - if ( saved !== result || notAsync ) { - dataPriv.set( this, type, false ); - } else { - result = {}; - } + dataPriv.set( this, type, false ); + if ( saved !== result ) { // Cancel the outer synthetic event event.stopImmediatePropagation(); event.preventDefault(); - // Support: Chrome 86+ - // 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 `result` undefined. We need to guard against this. - return result && result.value; + return result; } // If this is an inner synthetic event for an event with a bubbling surrogate @@ -605,16 +573,11 @@ function leverageNative( el, type, expectSync ) { } else if ( saved.length ) { // ...and capture the result - dataPriv.set( this, type, { - value: jQuery.event.trigger( - - // Support: IE <=9 - 11+ - // Extend with the prototype to reset the above stopImmediatePropagation() - jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), - saved.slice( 1 ), - this - ) - } ); + dataPriv.set( this, type, jQuery.event.trigger( + saved[ 0 ], + saved.slice( 1 ), + this + ) ); // Abort handling of the native event event.stopImmediatePropagation(); @@ -756,18 +719,73 @@ jQuery.each( { }, jQuery.event.addProp ); jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + + function focusMappedHandler( nativeEvent ) { + if ( document.documentMode ) { + + // Support: IE 11+ + // Attach a single focusin/focusout handler on the document while someone wants + // focus/blur. This is because the former are synchronous in IE while the latter + // are async. In other browsers, all those handlers are invoked synchronously. + + // `handle` from private data would already wrap the event, but we need + // to change the `type` here. + var handle = dataPriv.get( this, "handle" ), + event = jQuery.event.fix( nativeEvent ); + event.type = nativeEvent.type === "focusin" ? "focus" : "blur"; + event.isSimulated = true; + + // First, handle focusin/focusout + handle( nativeEvent ); + + // ...then, handle focus/blur + // + // focus/blur don't bubble while focusin/focusout do; simulate the former by only + // invoking the handler at the lower level. + if ( event.target === event.currentTarget ) { + + // The setup part calls `leverageNative`, which, in turn, calls + // `jQuery.event.add`, so event handle will already have been set + // by this point. + handle( event ); + } + } else { + + // For non-IE browsers, attach a single capturing handler on the document + // while someone wants focusin/focusout. + jQuery.event.simulate( delegateType, nativeEvent.target, + jQuery.event.fix( nativeEvent ) ); + } + } + jQuery.event.special[ type ] = { // Utilize native event if possible so blur/focus sequence is correct setup: function() { + var attaches; + // Claim the first handler // dataPriv.set( this, "focus", ... ) // dataPriv.set( this, "blur", ... ) - leverageNative( this, type, expectSync ); + leverageNative( this, type, true ); - // Return false to allow normal processing in the caller - return false; + if ( document.documentMode ) { + + // Support: IE 9 - 11+ + // We use the same native handler for focusin & focus (and focusout & blur) + // so we need to coordinate setup & teardown parts between those events. + // Use `delegateType` as the key as `type` is already used by `leverageNative`. + attaches = dataPriv.get( this, delegateType ); + if ( !attaches ) { + this.addEventListener( delegateType, focusMappedHandler ); + } + dataPriv.set( this, delegateType, ( attaches || 0 ) + 1 ); + } else { + + // Return false to allow normal processing in the caller + return false; + } }, trigger: function() { @@ -778,6 +796,24 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp return true; }, + teardown: function() { + var attaches; + + if ( document.documentMode ) { + attaches = dataPriv.get( this, delegateType ) - 1; + if ( !attaches ) { + this.removeEventListener( delegateType, focusMappedHandler ); + dataPriv.remove( this, delegateType ); + } else { + dataPriv.set( this, delegateType, attaches ); + } + } else { + + // Return false to indicate standard teardown should be applied + return false; + } + }, + // Suppress native focus or blur if we're currently inside // a leveraged native-event stack _default: function( event ) { @@ -786,6 +822,58 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp delegateType: delegateType }; + + // Support: Firefox <=44 + // Firefox doesn't have focus(in | out) events + // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 + // + // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 + // focus(in | out) events fire after focus & blur events, + // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order + // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 + // + // Support: IE 9 - 11+ + // To preserve relative focusin/focus & focusout/blur event order guaranteed on the 3.x branch, + // attach a single handler for both events in IE. + jQuery.event.special[ delegateType ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + dataHolder = document.documentMode ? this : doc, + attaches = dataPriv.get( dataHolder, delegateType ); + + // Support: IE 9 - 11+ + // We use the same native handler for focusin & focus (and focusout & blur) + // so we need to coordinate setup & teardown parts between those events. + // Use `delegateType` as the key as `type` is already used by `leverageNative`. + if ( !attaches ) { + if ( document.documentMode ) { + this.addEventListener( delegateType, focusMappedHandler ); + } else { + doc.addEventListener( type, focusMappedHandler, true ); + } + } + dataPriv.set( dataHolder, delegateType, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + dataHolder = document.documentMode ? this : doc, + attaches = dataPriv.get( dataHolder, delegateType ) - 1; + + if ( !attaches ) { + if ( document.documentMode ) { + this.removeEventListener( delegateType, focusMappedHandler ); + } else { + doc.removeEventListener( type, focusMappedHandler, true ); + } + dataPriv.remove( dataHolder, delegateType ); + } else { + dataPriv.set( dataHolder, delegateType, attaches ); + } + } + }; } ); // Create mouseenter/leave events using mouseover/out and event-time checks diff --git a/src/event/focusin.js b/src/event/focusin.js deleted file mode 100644 index 3da86c787..000000000 --- a/src/event/focusin.js +++ /dev/null @@ -1,58 +0,0 @@ -define( [ - "../core", - "../data/var/dataPriv", - "./support", - - "../event", - "./trigger" -], function( jQuery, dataPriv, support ) { - -"use strict"; - -// Support: Firefox <=44 -// Firefox doesn't have focus(in | out) events -// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 -// -// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 -// focus(in | out) events fire after focus & blur events, -// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order -// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 -if ( !support.focusin ) { - jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - - // Handle: regular nodes (via `this.ownerDocument`), window - // (via `this.document`) & document (via `this`). - var doc = this.ownerDocument || this.document || this, - attaches = dataPriv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this.document || this, - attaches = dataPriv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - dataPriv.remove( doc, fix ); - - } else { - dataPriv.access( doc, fix, attaches ); - } - } - }; - } ); -} - -return jQuery; -} ); diff --git a/src/event/support.js b/src/event/support.js deleted file mode 100644 index e3db9ad83..000000000 --- a/src/event/support.js +++ /dev/null @@ -1,11 +0,0 @@ -define( [ - "../var/support" -], function( support ) { - -"use strict"; - -support.focusin = "onfocusin" in window; - -return support; - -} ); diff --git a/src/jquery.js b/src/jquery.js index 0c144c194..46cda5e4b 100644 --- a/src/jquery.js +++ b/src/jquery.js @@ -11,7 +11,6 @@ define( [ "./queue/delay", "./attributes", "./event", - "./event/focusin", "./manipulation", "./manipulation/_evalUrl", "./wrap", diff --git a/test/unit/event.js b/test/unit/event.js index d2753fbd0..c152bf6c0 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -2172,12 +2172,12 @@ QUnit.test( "focusin bubbles", function( assert ) { // Removed since DOM focus is unreliable on test swarm // DOM focus method -// input[0].focus(); +// input[ 0 ].focus(); // To make the next focus test work, we need to take focus off the input. // This will fire another focusin event, so set order to reflect that. // order = 1; -// jQuery("#text1")[0].focus(); +// jQuery( "#text1" )[ 0 ].focus(); // jQuery trigger, which calls DOM focus order = 0; @@ -2187,6 +2187,42 @@ QUnit.test( "focusin bubbles", function( assert ) { jQuery( "body" ).off( "focusin.focusinBubblesTest" ); } ); +QUnit.test( "focus does not bubble", function( assert ) { + assert.expect( 1 ); + + var done = assert.async(), + input = jQuery( "" ).prependTo( "body" ); + + // focus the element so DOM focus won't fire + input[ 0 ].focus(); + + jQuery( "body" ).on( "focus.focusDoesNotBubbleTest", function() { + assert.ok( false, "focus doesn't fire on body" ); + } ); + + input.on( "focus.focusDoesNotBubbleTest", function() { + assert.ok( true, "focus on the element" ); + } ); + +// Removed since DOM focus is unreliable on test swarm + // DOM focus method +// input[ 0 ].focus(); + + // To make the next focus test work, we need to take focus off the input. + // This will fire another focusin event, so set order to reflect that. +// jQuery( "#text1" )[ 0 ].focus(); + + // jQuery trigger, which calls DOM focus + input.trigger( "focus" ); + + input.remove(); + jQuery( "body" ).off( "focus.focusDoesNotBubbleTest" ); + + setTimeout( function() { + done(); + }, 50 ); +} ); + QUnit.test( "custom events with colons (trac-3533, trac-8272)", function( assert ) { assert.expect( 1 ); @@ -2652,6 +2688,10 @@ QUnit.test( "element removed during focusout (gh-4417)", function( assert ) { button[ 0 ].blur = function() { jQuery.cleanData( [ this ] ); this.parentNode.removeChild( this ); + + // Redefine `blur` to avoid a hard crash in Karma tests that stop + // the test runner in case this test fails. + this.blur = jQuery.noop; }; button[ 0 ].click(); @@ -3119,56 +3159,45 @@ QUnit.test( "focus-blur order (trac-12868)", function( assert ) { var order, $text = jQuery( "#text1" ), - $radio = jQuery( "#radio1" ), - - // Support: IE <=9 - 11+ - // focus and blur events are asynchronous; this is the resulting mess. - // The browser window must be topmost for this to work properly!! - done = assert.async(); + $radio = jQuery( "#radio1" ); $radio[ 0 ].focus(); - setTimeout( function() { + $text + .on( "focus", function() { + assert.equal( order++, 1, "text focus" ); + } ) + .on( "blur", function() { + assert.equal( order++, 0, "text blur" ); + } ); + $radio + .on( "focus", function() { + assert.equal( order++, 1, "radio focus" ); + } ) + .on( "blur", function() { + assert.equal( order++, 0, "radio blur" ); + } ); - $text - .on( "focus", function() { - assert.equal( order++, 1, "text focus" ); - } ) - .on( "blur", function() { - assert.equal( order++, 0, "text blur" ); - } ); - $radio - .on( "focus", function() { - assert.equal( order++, 1, "radio focus" ); - } ) - .on( "blur", function() { - assert.equal( order++, 0, "radio blur" ); - } ); + // Enabled input getting focus + order = 0; + assert.equal( document.activeElement, $radio[ 0 ], "radio has focus" ); + $text.trigger( "focus" ); - // Enabled input getting focus - order = 0; - assert.equal( document.activeElement, $radio[ 0 ], "radio has focus" ); - $text.trigger( "focus" ); - setTimeout( function() { + // DOM focus is unreliable in TestSwarm + if ( order === 0 ) { + assert.ok( true, "GAP: Could not observe focus change" ); + assert.ok( true, "GAP: Could not observe focus change" ); + } - // DOM focus is unreliable in TestSwarm - if ( order === 0 ) { - assert.ok( true, "GAP: Could not observe focus change" ); - assert.ok( true, "GAP: Could not observe focus change" ); - } + assert.equal( document.activeElement, $text[ 0 ], "text has focus" ); - assert.equal( document.activeElement, $text[ 0 ], "text has focus" ); + // Run handlers without native method on an input + order = 1; + $radio.triggerHandler( "focus" ); - // Run handlers without native method on an input - order = 1; - $radio.triggerHandler( "focus" ); - - // Clean up - $text.off(); - $radio.off(); - done(); - }, 50 ); - }, 50 ); + // Clean up + $text.off(); + $radio.off(); } ); QUnit.test( "Event handling works with multiple async focus events (gh-4350)", function( assert ) { @@ -3176,10 +3205,6 @@ QUnit.test( "Event handling works with multiple async focus events (gh-4350)", f var remaining = 3, input = jQuery( "#name" ), - - // Support: IE <=9 - 11+ - // focus and blur events are asynchronous; this is the resulting mess. - // The browser window must be topmost for this to work properly!! done = assert.async(); input @@ -3189,6 +3214,17 @@ QUnit.test( "Event handling works with multiple async focus events (gh-4350)", f if ( remaining > 0 ) { input.trigger( "blur" ); } else { + + if ( QUnit.isIE ) { + + // Support: <=IE 11+ + // In IE, one of the blurs sometimes triggers a focus on body + // which in turn restores focus to the input, leading to 4 assertions + // firing instead of three. This only happens if other tests are + // running on the same test page. Avoid this issue in tests by removing + // the handler early. + input.off( "focus" ); + } done(); } } ) @@ -3214,6 +3250,45 @@ QUnit.test( "Event handling works with multiple async focus events (gh-4350)", f } ); } ); +// Support: IE <=9 - 11+ +// focus and blur events are asynchronous. +// The browser window must be topmost for this to work properly!! +QUnit.test( "async focus queues properly (gh-4859)", function( assert ) { + assert.expect( 1 ); + + var $text = jQuery( "#text1" ), + $radio = jQuery( "#radio1" ), + done = assert.async(); + + $text.trigger( "focus" ); + $radio.trigger( "focus" ); + $text.trigger( "focus" ); + + setTimeout( function() { + assert.equal( document.activeElement, $text[ 0 ], "focus follows the last trigger" ); + done(); + }, 500 ); +} ); + +// Support: IE <=9 - 11+ +// focus and blur events are asynchronous. +// The browser window must be topmost for this to work properly!! +QUnit.test( "async focus queues properly with blur (gh-4856)", function( assert ) { + assert.expect( 1 ); + + var $text = jQuery( "#text1" ), + done = assert.async(); + + $text.trigger( "focus" ); + $text.trigger( "blur" ); + $text.trigger( "focus" ); + + setTimeout( function() { + assert.equal( document.activeElement, $text[ 0 ], "focus-after-blur is respected" ); + done(); + }, 500 ); +} ); + QUnit.test( "native-backed events preserve trigger data (gh-1741, gh-4139)", function( assert ) { assert.expect( 17 ); @@ -3223,12 +3298,7 @@ QUnit.test( "native-backed events preserve trigger data (gh-1741, gh-4139)", fun targets = jQuery( parent[ 0 ].childNodes ), checkbox = jQuery( targets[ 0 ] ), data = [ "arg1", "arg2" ], - slice = data.slice, - - // Support: IE <=9 - 11+ - // focus and blur events are asynchronous; this is the resulting mess. - // The browser window must be topmost for this to work properly!! - done = assert.async(); + slice = data.slice; // click (gh-4139) assert.strictEqual( targets[ 0 ].checked, false, "checkbox unchecked before click" ); @@ -3254,18 +3324,26 @@ QUnit.test( "native-backed events preserve trigger data (gh-1741, gh-4139)", fun var type = event.type; assert.deepEqual( slice.call( arguments, 1 ), data, type + " handler received correct data" ); + + if ( QUnit.isIE && type === "focus" ) { + + // Support: <=IE 11+ + // In IE, one of the blurs sometimes triggers a focus on body + // which in turn restores focus to the input, leading to 4 assertions + // firing instead of three. This only happens if other tests are + // running on the same test page. Avoid this issue in tests by removing + // the handler early. + checkbox.off( "focus" ); + } } ); checkbox.trigger( "focus", data ); - setTimeout( function() { - assert.strictEqual( document.activeElement, checkbox[ 0 ], - "element focused after focus event (default action)" ); - checkbox.trigger( "blur", data ); - setTimeout( function() { - assert.notEqual( document.activeElement, checkbox[ 0 ], - "element not focused after blur event (default action)" ); - done(); - }, 50 ); - }, 50 ); + + assert.strictEqual( document.activeElement, checkbox[ 0 ], + "element focused after focus event (default action)" ); + checkbox.trigger( "blur", data ); + + assert.notEqual( document.activeElement, checkbox[ 0 ], + "element not focused after blur event (default action)" ); } ); QUnit.test( "focus change during a focus handler (gh-4382)", function( assert ) { @@ -3318,6 +3396,22 @@ QUnit.test( "trigger(focus) works after .on(focus).off(focus) (gh-4867)", functi assert.equal( document.activeElement, input[ 0 ], "input has focus" ); } ); +QUnit.test( "trigger(focus) works after focusing when hidden (gh-4950)", function( assert ) { + assert.expect( 1 ); + + var input = jQuery( "" ); + + input.appendTo( "#qunit-fixture" ); + + input + .css( "display", "none" ) + .trigger( "focus" ) + .css( "display", "" ) + .trigger( "focus" ); + + assert.equal( document.activeElement, input[ 0 ], "input has focus" ); +} ); + // TODO replace with an adaptation of // https://github.com/jquery/jquery/pull/1367/files#diff-a215316abbaabdf71857809e8673ea28R2464 ( function() { diff --git a/test/unit/support.js b/test/unit/support.js index d4955936d..5be7491e6 100644 --- a/test/unit/support.js +++ b/test/unit/support.js @@ -68,7 +68,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -93,7 +92,6 @@ testIframe( cors: false, createHTMLDocument: true, disconnectedMatch: false, - focusin: true, getById: false, noCloneChecked: false, option: false, @@ -118,7 +116,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: true, getById: true, noCloneChecked: false, option: true, @@ -143,7 +140,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -168,7 +164,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -193,7 +188,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -218,7 +212,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -243,7 +236,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -268,7 +260,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -293,7 +284,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -318,7 +308,6 @@ testIframe( cors: true, createHTMLDocument: false, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -343,7 +332,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -368,7 +356,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -393,7 +380,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true, @@ -418,7 +404,6 @@ testIframe( cors: true, createHTMLDocument: true, disconnectedMatch: true, - focusin: false, getById: true, noCloneChecked: true, option: true,