-
Notifications
You must be signed in to change notification settings - Fork 50.2k
Minimally support iframes (nested browsing contexts) in selection event handling #12037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
6940e33
3f3c1d7
b08a270
51be426
3714067
66b8766
75bc65e
5a61b66
f752792
a8fcf05
0003681
fef8519
799ee39
6e3d4b7
d1ad016
3c32963
3f7b5c5
05d8969
a776570
26e9d82
4db5c44
ccf0329
2edf1f8
db02b65
75b9992
0f1de45
95b2aef
d997ba8
e63391c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,7 +12,25 @@ import * as ReactDOMSelection from './ReactDOMSelection'; | |
| import {ELEMENT_NODE} from '../shared/HTMLNodeType'; | ||
|
|
||
| function isInDocument(node) { | ||
| return containsNode(document.documentElement, node); | ||
| return ( | ||
| node && | ||
| node.ownerDocument && | ||
| containsNode(node.ownerDocument.documentElement, node) | ||
| ); | ||
| } | ||
|
|
||
| function getActiveElementDeep() { | ||
| let win = window; | ||
| let element = getActiveElement(); | ||
| while (element instanceof win.HTMLIFrameElement) { | ||
| try { | ||
| win = element.contentDocument.defaultView; | ||
| } catch (e) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What exactly are we catching here? Is it
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you just try to access the contentDocument of an
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a comment to this line describing such a scenario? |
||
| return element; | ||
| } | ||
| element = getActiveElement(win.document); | ||
| } | ||
| return element; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -33,7 +51,7 @@ export function hasSelectionCapabilities(elem) { | |
| } | ||
|
|
||
| export function getSelectionInformation() { | ||
| const focusedElem = getActiveElement(); | ||
| const focusedElem = getActiveElementDeep(); | ||
| return { | ||
| focusedElem: focusedElem, | ||
| selectionRange: hasSelectionCapabilities(focusedElem) | ||
|
|
@@ -48,7 +66,7 @@ export function getSelectionInformation() { | |
| * nodes and place them back in, resulting in focus being lost. | ||
| */ | ||
| export function restoreSelection(priorSelectionInformation) { | ||
| const curFocusedElem = getActiveElement(); | ||
| const curFocusedElem = getActiveElementDeep(); | ||
| const priorFocusedElem = priorSelectionInformation.focusedElem; | ||
| const priorSelectionRange = priorSelectionInformation.selectionRange; | ||
| if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to check if
nodeexists? In what situation willnodenot be a DOM node?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The value that gets passed in comes from
fbjs/lib/getActiveElement, which returns a nullableHTMLElement(https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/dom/getActiveElement.js#L21). The only instance where the return value would be null is if the util was unable to find adocumentobject, which I think would only happen in SSR. But because it is theoretically nullable, all the operations in this file first confirm thatnode(orelem, inhasSelectionCapabilities) is truthy.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't use
fbjs/lib/getActiveElementanymore, and have copied it in the repo. Let's tighten this up? Feel free to changegetActiveElementas you see fit.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gaearon We can update
getActiveElement.jsto look like:But strictly speaking, flow will still complain that
document.bodycan be null (ref: facebook/flow#4783 (comment)), so strictly speaking, theElementreturn value still has to be?Element, unless we did something likeDo you have a preferred approach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to lean towards the first, but I keep reasoning out of it in favor of the second. Body could be null, and it really it should never happen. But I've been surprised too much before :).
With the second example, do you need a try/catch?
Also: do you anticipate any problems with code downstream working with a document body that isn't attached?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nhunzaker No try/catch needed for the second example, and the ReactInputSelection plugin won’t have any issues; the code is already setup to handle detached DOM elements for a case where the active element becomes detached between when it is first read and cached and after React finishes committing an update. The second option has grown on me; I suggested it thinking it was silly, but now feel like it’s pretty reasonable. If we go with that one, should we add a comment explaining that document.body can be null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go with it 👍