diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp
index 9c09940757a9..0402d31aaa50 100644
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -6422,22 +6422,22 @@ HTMLInputElement::SetRangeText(const nsAString& aReplacement, uint32_t aStart,
SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv);
}
-Nullable
+Nullable
HTMLInputElement::GetSelectionStart(ErrorResult& aRv)
{
if (!SupportsTextSelection()) {
- return Nullable();
+ return Nullable();
}
- int32_t selStart = GetSelectionStartIgnoringType(aRv);
+ uint32_t selStart = GetSelectionStartIgnoringType(aRv);
if (aRv.Failed()) {
- return Nullable();
+ return Nullable();
}
- return Nullable(selStart);
+ return Nullable(selStart);
}
-int32_t
+uint32_t
HTMLInputElement::GetSelectionStartIgnoringType(ErrorResult& aRv)
{
int32_t selEnd, selStart;
@@ -6446,7 +6446,7 @@ HTMLInputElement::GetSelectionStartIgnoringType(ErrorResult& aRv)
}
void
-HTMLInputElement::SetSelectionStart(const Nullable& aSelectionStart,
+HTMLInputElement::SetSelectionStart(const Nullable& aSelectionStart,
ErrorResult& aRv)
{
if (!SupportsTextSelection()) {
@@ -6454,35 +6454,9 @@ HTMLInputElement::SetSelectionStart(const Nullable& aSelectionStart,
return;
}
- int32_t selStart = 0;
- if (!aSelectionStart.IsNull()) {
- selStart = aSelectionStart.Value();
- }
-
nsTextEditorState* state = GetEditorState();
- if (state && state->IsSelectionCached()) {
- state->GetSelectionProperties().SetStart(selStart);
- return;
- }
-
- nsAutoString direction;
- GetSelectionDirection(direction, aRv);
- if (aRv.Failed()) {
- return;
- }
-
- int32_t start, end;
- GetSelectionRange(&start, &end, aRv);
- if (aRv.Failed()) {
- return;
- }
-
- start = selStart;
- if (end < start) {
- end = start;
- }
-
- aRv = SetSelectionRange(start, end, direction);
+ MOZ_ASSERT(state, "SupportsTextSelection() returned true!");
+ state->SetSelectionStart(aSelectionStart, aRv);
}
Nullable
diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h
index e9c46e46a404..2691e6065dd7 100644
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -246,7 +246,7 @@ public:
// Methods for nsFormFillController so it can do selection operations on input
// types the HTML spec doesn't support them on, like "email".
- int32_t GetSelectionStartIgnoringType(ErrorResult& aRv);
+ uint32_t GetSelectionStartIgnoringType(ErrorResult& aRv);
int32_t GetSelectionEndIgnoringType(ErrorResult& aRv);
void GetDisplayFileName(nsAString& aFileName) const;
@@ -717,8 +717,8 @@ public:
// XPCOM Select() is OK
- Nullable GetSelectionStart(ErrorResult& aRv);
- void SetSelectionStart(const Nullable& aValue, ErrorResult& aRv);
+ Nullable GetSelectionStart(ErrorResult& aRv);
+ void SetSelectionStart(const Nullable& aValue, ErrorResult& aRv);
Nullable GetSelectionEnd(ErrorResult& aRv);
void SetSelectionEnd(const Nullable& aValue, ErrorResult& aRv);
diff --git a/dom/html/HTMLTextAreaElement.cpp b/dom/html/HTMLTextAreaElement.cpp
index 9ad6bf116a20..09e9af380b7e 100644
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -710,34 +710,7 @@ void
HTMLTextAreaElement::SetSelectionStart(const Nullable& aSelectionStart,
ErrorResult& aError)
{
- int32_t selStart = 0;
- if (!aSelectionStart.IsNull()) {
- selStart = aSelectionStart.Value();
- }
-
- if (mState.IsSelectionCached()) {
- mState.GetSelectionProperties().SetStart(selStart);
- return;
- }
-
- nsAutoString direction;
- GetSelectionDirection(direction, aError);
- if (aError.Failed()) {
- return;
- }
- int32_t start, end;
- GetSelectionRange(&start, &end, aError);
- if (aError.Failed()) {
- return;
- }
- start = selStart;
- if (end < start) {
- end = start;
- }
- nsresult rv = SetSelectionRange(start, end, direction);
- if (NS_FAILED(rv)) {
- aError.Throw(rv);
- }
+ mState.SetSelectionStart(aSelectionStart, aError);
}
Nullable
diff --git a/dom/html/nsTextEditorState.cpp b/dom/html/nsTextEditorState.cpp
index 1bdbe26f330a..8e51853fd4b6 100644
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -1708,6 +1708,35 @@ nsTextEditorState::SetSelectionRange(int32_t aStart, int32_t aEnd,
}
}
+void
+nsTextEditorState::SetSelectionStart(const mozilla::dom::Nullable& aStart,
+ ErrorResult& aRv)
+{
+ int32_t start = 0;
+ if (!aStart.IsNull()) {
+ // XXXbz This will do the wrong thing for input values that are out of the
+ // int32_t range...
+ start = aStart.Value();
+ }
+
+ int32_t ignored, end;
+ GetSelectionRange(&ignored, &end, aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+
+ nsITextControlFrame::SelectionDirection dir = GetSelectionDirection(aRv);
+ if (aRv.Failed()) {
+ return;
+ }
+
+ if (end < start) {
+ end = start;
+ }
+
+ SetSelectionRange(start, end, dir, aRv);
+}
+
HTMLInputElement*
nsTextEditorState::GetParentNumberControl(nsFrame* aFrame) const
{
diff --git a/dom/html/nsTextEditorState.h b/dom/html/nsTextEditorState.h
index 6d41b361fb2a..c26097490485 100644
--- a/dom/html/nsTextEditorState.h
+++ b/dom/html/nsTextEditorState.h
@@ -15,6 +15,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "mozilla/WeakPtr.h"
+#include "mozilla/dom/Nullable.h"
class nsTextInputListener;
class nsTextControlFrame;
@@ -297,6 +298,12 @@ public:
nsITextControlFrame::SelectionDirection aDirection,
mozilla::ErrorResult& aRv);
+ // Set the selection start. This basically implements the
+ // https://html.spec.whatwg.org/multipage/forms.html#dom-textarea/input-selectionstart
+ // setter.
+ void SetSelectionStart(const mozilla::dom::Nullable& aStart,
+ mozilla::ErrorResult& aRv);
+
void UpdateEditableState(bool aNotify) {
if (mRootNode) {
mRootNode->UpdateEditableState(aNotify);
diff --git a/dom/webidl/HTMLInputElement.webidl b/dom/webidl/HTMLInputElement.webidl
index bdfc24ad6264..5f001e68739f 100644
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -117,8 +117,7 @@ interface HTMLInputElement : HTMLElement {
void select();
[Throws]
- // TODO: unsigned vs signed
- attribute long? selectionStart;
+ attribute unsigned long? selectionStart;
[Throws]
attribute long? selectionEnd;
[Throws]
diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json
index b77d3c4c02a4..d4debe9920c9 100644
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -93542,6 +93542,12 @@
{}
]
],
+ "html/semantics/forms/textfieldselection/selection-start-end.html": [
+ [
+ "/html/semantics/forms/textfieldselection/selection-start-end.html",
+ {}
+ ]
+ ],
"html/semantics/forms/textfieldselection/selection.html": [
[
"/html/semantics/forms/textfieldselection/selection.html",
@@ -176663,12 +176669,16 @@
"39ecb031aca3655a06152f94a514981fe59ebbaf",
"testharness"
],
+ "html/semantics/forms/textfieldselection/selection-start-end.html": [
+ "1f3184b72aba5631d6db4379dfa98035ee047283",
+ "testharness"
+ ],
"html/semantics/forms/textfieldselection/selection.html": [
- "d869799718137671a2eacc323aa26ea4364e845f",
+ "f7674721b84ec8fca0e5e40258447ce857b87784",
"testharness"
],
"html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html": [
- "0caf2b08ccc5a35578291af8f5adaf7de9537d66",
+ "3bbd350321f5ec9e0a8f3d47da4e11aaa3ad4d68",
"testharness"
],
"html/semantics/forms/textfieldselection/textfieldselection-setSelectionRange.html": [
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-start-end.html b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-start-end.html
new file mode 100644
index 000000000000..49b598ec8dfc
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/selection-start-end.html
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html b/testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html
index cb0afb17d734..4b586cc10785 100644
--- a/testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html
+++ b/testing/web-platform/tests/html/semantics/forms/textfieldselection/textfieldselection-setRangeText.html
@@ -106,15 +106,23 @@
}, element.id + " setRangeText without argument throws a type error");
async_test(function() {
- var q = false;
- element.onselect = this.step_func_done(function(e) {
- assert_true(q, "event should be queued");
- assert_true(e.isTrusted, "event is trusted");
- assert_true(e.bubbles, "event bubbles");
- assert_false(e.cancelable, "event is not cancelable");
- });
- element.setRangeText("foobar2", 0, 6);
- q = true;
+ // At this point there are already "select" events queued up on
+ // "element". Give them time to fire; otherwise we can get spurious
+ // passes.
+ //
+ // This is unfortunately racy in that we might _still_ get spurious
+ // passes. I'm not sure how best to handle that.
+ setTimeout(this.step_func(function() {
+ var q = false;
+ element.onselect = this.step_func_done(function(e) {
+ assert_true(q, "event should be queued");
+ assert_true(e.isTrusted, "event is trusted");
+ assert_true(e.bubbles, "event bubbles");
+ assert_false(e.cancelable, "event is not cancelable");
+ });
+ element.setRangeText("foobar2", 0, 6);
+ q = true;
+ }), 10);
}, element.id + " setRangeText fires a select event");
})