From def8a8a0a80042084b2e895ee9b9e281618bd05c Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Mon, 2 Mar 2020 13:17:55 -0500 Subject: [PATCH 1/3] Rich Text: Avoid activeElement focus call --- packages/rich-text/src/to-dom.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/rich-text/src/to-dom.js b/packages/rich-text/src/to-dom.js index 2e5c54e769b1e..3786dad059de9 100644 --- a/packages/rich-text/src/to-dom.js +++ b/packages/rich-text/src/to-dom.js @@ -289,8 +289,6 @@ export function applySelection( { startPath, endPath }, current ) { range.setStart( startContainer, startOffset ); range.setEnd( endContainer, endOffset ); - const { activeElement } = ownerDocument; - if ( selection.rangeCount > 0 ) { // If the to be added range and the live range are the same, there's no // need to remove the live range and add the equivalent range. @@ -302,5 +300,4 @@ export function applySelection( { startPath, endPath }, current ) { } selection.addRange( range ); - activeElement.focus(); } From e56b9b450251696ecbc3dd3082b832202e9d58d4 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Mon, 2 Mar 2020 14:13:04 -0500 Subject: [PATCH 2/3] Rich Text: Restore focus, accounting for null activeElement --- packages/rich-text/src/to-dom.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/rich-text/src/to-dom.js b/packages/rich-text/src/to-dom.js index 3786dad059de9..1bd7e793ac67a 100644 --- a/packages/rich-text/src/to-dom.js +++ b/packages/rich-text/src/to-dom.js @@ -289,6 +289,8 @@ export function applySelection( { startPath, endPath }, current ) { range.setStart( startContainer, startOffset ); range.setEnd( endContainer, endOffset ); + const { activeElement } = ownerDocument; + if ( selection.rangeCount > 0 ) { // If the to be added range and the live range are the same, there's no // need to remove the live range and add the equivalent range. @@ -300,4 +302,17 @@ export function applySelection( { startPath, endPath }, current ) { } selection.addRange( range ); + + // This function is not intended to cause a shift in focus. Since the above + // selection manipulations may shift focus, ensure that focus is restored to + // its previous state. `activeElement` can be `null` or the body element if + // there is no focus, which is accounted for here in the explicit `blur` to + // restore to a state of non-focus. + if ( activeElement !== document.activeElement ) { + if ( activeElement ) { + activeElement.focus(); + } else { + document.activeElement.blur(); + } + } } From 1c5d3ebe815d1b22d7713b7680ecc4c000665521 Mon Sep 17 00:00:00 2001 From: Andrew Duthie Date: Mon, 2 Mar 2020 15:27:46 -0500 Subject: [PATCH 3/3] Rich Text: Verify activeElement instanceof HTMLElement --- packages/rich-text/src/to-dom.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/rich-text/src/to-dom.js b/packages/rich-text/src/to-dom.js index 1bd7e793ac67a..0a63e94a95e3a 100644 --- a/packages/rich-text/src/to-dom.js +++ b/packages/rich-text/src/to-dom.js @@ -309,9 +309,16 @@ export function applySelection( { startPath, endPath }, current ) { // there is no focus, which is accounted for here in the explicit `blur` to // restore to a state of non-focus. if ( activeElement !== document.activeElement ) { + // The `instanceof` checks protect against edge cases where the focused + // element is not of the interface HTMLElement (does not have a `focus` + // or `blur` property). + // + // See: https://github.com/Microsoft/TypeScript/issues/5901#issuecomment-431649653 if ( activeElement ) { - activeElement.focus(); - } else { + if ( activeElement instanceof window.HTMLElement ) { + activeElement.focus(); + } + } else if ( document.activeElement instanceof window.HTMLElement ) { document.activeElement.blur(); } }