Skip to content
This repository was archived by the owner on Feb 6, 2023. It is now read-only.

Commit 41beae1

Browse files
mrkevfacebook-github-bot
authored andcommitted
Type selection object in editOnInput.
Summary: Recently I merged D20582792— it was a quick fix to a a huge problem that was causing thousands of exceptions for our users. It could've been prevented with better typing, but wasn't caught by flow because the type of the selection object was assumed to be null. Here I implement the type of the selection object, and in the process catch other elements that could be null and add safeguards to make our code more reliable. This are places where the previous implementation would've thrown an exception. Reviewed By: kedromelon Differential Revision: D20636236 fbshipit-source-id: 6e27040120256e3885bfdd2d9cbedf5e57988062
1 parent 97dd19b commit 41beae1

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/component/handlers/edit/editOnInput.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
'use strict';
1313

14+
import type {SelectionObject} from 'DraftDOMTypes';
1415
import type DraftEditor from 'DraftEditor.react';
1516

1617
const DraftModifier = require('DraftModifier');
@@ -65,14 +66,14 @@ function editOnInput(editor: DraftEditor, e: SyntheticInputEvent<>): void {
6566
}
6667
// at this point editor is not null for sure (after input)
6768
const castedEditorElement: HTMLElement = (editor.editor: any);
68-
const domSelection = castedEditorElement.ownerDocument.defaultView.getSelection();
69+
const domSelection: SelectionObject = castedEditorElement.ownerDocument.defaultView.getSelection();
6970

7071
const {anchorNode, isCollapsed} = domSelection;
7172
const isNotTextOrElementNode =
7273
anchorNode?.nodeType !== Node.TEXT_NODE &&
7374
anchorNode?.nodeType !== Node.ELEMENT_NODE;
7475

75-
if (isNotTextOrElementNode) {
76+
if (anchorNode == null || isNotTextOrElementNode) {
7677
// TODO: (t16149272) figure out context for this change
7778
return;
7879
}
@@ -86,10 +87,14 @@ function editOnInput(editor: DraftEditor, e: SyntheticInputEvent<>): void {
8687
// https://chromium.googlesource.com/chromium/src/+/a3b600981286b135632371477f902214c55a1724
8788
// To work around, we'll merge the sibling text nodes back into this one.
8889
const span = anchorNode.parentNode;
90+
if (span == null) {
91+
// Handle null-parent case.
92+
return;
93+
}
8994
anchorNode.nodeValue = span.textContent;
9095
for (
9196
let child = span.firstChild;
92-
child !== null;
97+
child != null;
9398
child = child.nextSibling
9499
) {
95100
if (child !== anchorNode) {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* (c) Facebook, Inc. and its affiliates. Confidential and proprietary.
3+
*
4+
* Types for things in the DOM used in Draft.js. These should eventaully be
5+
* added to the flow DOM lib itself.
6+
*
7+
* @emails oncall+draft_js
8+
* @flow strict
9+
* @format
10+
*/
11+
12+
'use strict';
13+
14+
// https://developer.mozilla.org/en-US/docs/Web/API/Selection
15+
export type SelectionObject = {|
16+
/**
17+
* Returns the Node in which the selection begins. Can return null if
18+
* selection never existed in the document (e.g., an iframe that was
19+
* never clicked on). */
20+
anchorNode: ?Node,
21+
anchorOffset: number,
22+
focusNode: ?Node,
23+
focusOffset: number,
24+
isCollapsed: boolean,
25+
rangeCount: number,
26+
type: string,
27+
// ...etc. This is a non-exhaustive definition.
28+
|};

0 commit comments

Comments
 (0)