diff --git a/fixtures/dom/src/components/fixtures/text-inputs/ReplaceEmailInput.js b/fixtures/dom/src/components/fixtures/text-inputs/ReplaceEmailInput.js
new file mode 100644
index 0000000000000..264be16085a4b
--- /dev/null
+++ b/fixtures/dom/src/components/fixtures/text-inputs/ReplaceEmailInput.js
@@ -0,0 +1,40 @@
+import Fixture from '../../Fixture';
+
+const React = window.React;
+
+class ReplaceEmailInput extends React.Component {
+ state = {
+ formSubmitted: false,
+ };
+
+ onReset = () => {
+ this.setState({formSubmitted: false});
+ };
+
+ onSubmit = event => {
+ event.preventDefault();
+ this.setState({formSubmitted: true});
+ };
+
+ render() {
+ return (
+
+
+
+
+ );
+ }
+}
+
+export default ReplaceEmailInput;
diff --git a/fixtures/dom/src/components/fixtures/text-inputs/index.js b/fixtures/dom/src/components/fixtures/text-inputs/index.js
index 33639686a311d..54026257fd986 100644
--- a/fixtures/dom/src/components/fixtures/text-inputs/index.js
+++ b/fixtures/dom/src/components/fixtures/text-inputs/index.js
@@ -2,6 +2,7 @@ import Fixture from '../../Fixture';
import FixtureSet from '../../FixtureSet';
import TestCase from '../../TestCase';
import InputTestCase from './InputTestCase';
+import ReplaceEmailInput from './ReplaceEmailInput';
const React = window.React;
@@ -125,6 +126,21 @@ class TextInputFixtures extends React.Component {
+
+
+ Type "test@test.com"
+ Press enter
+
+
+
+ There should be no selection-related error in the console.
+
+
+
+
+
diff --git a/packages/react-dom/src/client/ReactInputSelection.js b/packages/react-dom/src/client/ReactInputSelection.js
index 506153a118053..d4b47b992ce86 100644
--- a/packages/react-dom/src/client/ReactInputSelection.js
+++ b/packages/react-dom/src/client/ReactInputSelection.js
@@ -22,11 +22,21 @@ function isInDocument(node) {
* Input selection module for React.
*/
+/**
+ * @hasSelectionCapabilities: we get the element types that support selection
+ * from https://html.spec.whatwg.org/#do-not-apply, looking at `selectionStart`
+ * and `selectionEnd` rows.
+ */
export function hasSelectionCapabilities(elem) {
const nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
return (
nodeName &&
- ((nodeName === 'input' && elem.type === 'text') ||
+ ((nodeName === 'input' &&
+ (elem.type === 'text' ||
+ elem.type === 'search' ||
+ elem.type === 'tel' ||
+ elem.type === 'url' ||
+ elem.type === 'password')) ||
nodeName === 'textarea' ||
elem.contentEditable === 'true')
);
@@ -52,7 +62,10 @@ export function restoreSelection(priorSelectionInformation) {
const priorFocusedElem = priorSelectionInformation.focusedElem;
const priorSelectionRange = priorSelectionInformation.selectionRange;
if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
- if (hasSelectionCapabilities(priorFocusedElem)) {
+ if (
+ priorSelectionRange !== null &&
+ hasSelectionCapabilities(priorFocusedElem)
+ ) {
setSelection(priorFocusedElem, priorSelectionRange);
}