diff --git a/src/component/handlers/edit/editOnInput.js b/src/component/handlers/edit/editOnInput.js index 6b0b5a91ff..153ba92d4e 100644 --- a/src/component/handlers/edit/editOnInput.js +++ b/src/component/handlers/edit/editOnInput.js @@ -11,6 +11,7 @@ 'use strict'; +import type {SelectionObject} from 'DraftDOMTypes'; import type DraftEditor from 'DraftEditor.react'; const DraftModifier = require('DraftModifier'); @@ -65,14 +66,14 @@ function editOnInput(editor: DraftEditor, e: SyntheticInputEvent<>): void { } // at this point editor is not null for sure (after input) const castedEditorElement: HTMLElement = (editor.editor: any); - const domSelection = castedEditorElement.ownerDocument.defaultView.getSelection(); + const domSelection: SelectionObject = castedEditorElement.ownerDocument.defaultView.getSelection(); const {anchorNode, isCollapsed} = domSelection; const isNotTextOrElementNode = anchorNode?.nodeType !== Node.TEXT_NODE && anchorNode?.nodeType !== Node.ELEMENT_NODE; - if (isNotTextOrElementNode) { + if (anchorNode == null || isNotTextOrElementNode) { // TODO: (t16149272) figure out context for this change return; } @@ -86,10 +87,14 @@ function editOnInput(editor: DraftEditor, e: SyntheticInputEvent<>): void { // https://chromium.googlesource.com/chromium/src/+/a3b600981286b135632371477f902214c55a1724 // To work around, we'll merge the sibling text nodes back into this one. const span = anchorNode.parentNode; + if (span == null) { + // Handle null-parent case. + return; + } anchorNode.nodeValue = span.textContent; for ( let child = span.firstChild; - child !== null; + child != null; child = child.nextSibling ) { if (child !== anchorNode) { diff --git a/src/component/utils/DraftDOMTypes.js b/src/component/utils/DraftDOMTypes.js new file mode 100644 index 0000000000..f94cd264ea --- /dev/null +++ b/src/component/utils/DraftDOMTypes.js @@ -0,0 +1,28 @@ +/** + * (c) Facebook, Inc. and its affiliates. Confidential and proprietary. + * + * Types for things in the DOM used in Draft.js. These should eventaully be + * added to the flow DOM lib itself. + * + * @emails oncall+draft_js + * @flow strict + * @format + */ + +'use strict'; + +// https://developer.mozilla.org/en-US/docs/Web/API/Selection +export type SelectionObject = {| + /** + * Returns the Node in which the selection begins. Can return null if + * selection never existed in the document (e.g., an iframe that was + * never clicked on). */ + anchorNode: ?Node, + anchorOffset: number, + focusNode: ?Node, + focusOffset: number, + isCollapsed: boolean, + rangeCount: number, + type: string, + // ...etc. This is a non-exhaustive definition. +|};