Bug 1108425 - Fix dir=auto for textarea with rtl text. r=smaug

I copy-pasted all `SetDirectionFromValue`-related parts from HTMLInputElement to HTMLTextAreaElement

Differential Revision: https://phabricator.services.mozilla.com/D176999
This commit is contained in:
Vincent Hilla 2023-05-22 12:35:01 +00:00
parent 4f180f0ed1
commit 400e875b6d
10 changed files with 91 additions and 124 deletions

View File

@ -1177,12 +1177,15 @@ void SetDirectionalityFromValue(Element* aElement, const nsAString& value,
dir = eDir_LTR;
}
aElement->SetDirectionality(dir, aNotify);
if (aElement->GetDirectionality() != dir) {
aElement->SetDirectionality(dir, aNotify);
}
}
void OnSetDirAttr(Element* aElement, const nsAttrValue* aNewValue,
bool hadValidDir, bool hadDirAuto, bool aNotify) {
if (aElement->IsHTMLElement(nsGkAtoms::input)) {
if (aElement->IsHTMLElement(nsGkAtoms::input) ||
aElement->IsHTMLElement(nsGkAtoms::textarea)) {
return;
}

View File

@ -667,6 +667,16 @@ nsresult HTMLTextAreaElement::SetValueFromSetRangeText(
ValueSetterOption::SetValueChanged});
}
void HTMLTextAreaElement::SetDirectionFromValue(bool aNotify,
const nsAString* aKnownValue) {
nsAutoString value;
if (!aKnownValue) {
GetValue(value);
aKnownValue = &value;
}
SetDirectionalityFromValue(this, *aKnownValue, aNotify);
}
nsresult HTMLTextAreaElement::Reset() {
nsAutoString resetVal;
GetDefaultValue(resetVal, IgnoreErrors());
@ -797,6 +807,11 @@ nsresult HTMLTextAreaElement::BindToTree(BindContext& aContext,
nsGenericHTMLFormControlElementWithState::BindToTree(aContext, aParent);
NS_ENSURE_SUCCESS(rv, rv);
// Set direction based on value if dir=auto
if (HasDirAuto()) {
SetDirectionFromValue(false);
}
// If there is a disabled fieldset in the parent chain, the element is now
// barred from constraint validation and can't suffer from value missing.
UpdateValueMissingValidityState();
@ -923,6 +938,9 @@ void HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
if (nsTextControlFrame* f = do_QueryFrame(GetPrimaryFrame())) {
f->PlaceholderChanged(aOldValue, aValue);
}
} else if (aName == nsGkAtoms::dir && aValue &&
aValue->Equals(nsGkAtoms::_auto, eIgnoreCase)) {
SetDirectionFromValue(aNotify);
}
}
@ -1115,7 +1133,7 @@ void HTMLTextAreaElement::InitializeKeyboardEventListeners() {
void HTMLTextAreaElement::OnValueChanged(ValueChangeKind aKind,
bool aNewValueEmpty,
const nsAString*) {
const nsAString* aKnownNewValue) {
if (aKind != ValueChangeKind::Internal) {
mLastValueChangeWasInteractive = aKind == ValueChangeKind::UserInteraction;
}
@ -1133,6 +1151,10 @@ void HTMLTextAreaElement::OnValueChanged(ValueChangeKind aKind,
UpdateTooShortValidityState();
UpdateValueMissingValidityState();
if (HasDirAuto()) {
SetDirectionFromValue(true, aKnownNewValue);
}
if (validBefore != IsValid() ||
(emptyBefore != IsValueEmpty() && HasAttr(nsGkAtoms::placeholder))) {
UpdateState(true);

View File

@ -347,6 +347,9 @@ class HTMLTextAreaElement final : public TextControlElement,
const nsAttrValue* aValue, const nsAttrValue* aOldValue,
nsIPrincipal* aSubjectPrincipal, bool aNotify) override;
void SetDirectionFromValue(bool aNotify,
const nsAString* aKnownValue = nullptr);
/**
* Return if an element should have a specific validity UI
* (with :-moz-ui-invalid and :-moz-ui-valid pseudo-classes).

View File

@ -1,58 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML Test: textarea with dir=auto, all N+EN</title>
<link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
<link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
<link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#the-dir-attribute">
<link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0">
<meta name="assert" content="
When dir='auto', the direction is set according to the first strong character
of the text.
For textarea and pre elements, the heuristic is applied on a per-paragraph level.
If there is no strong character, as in this test, the direction defaults to LTR.">
<style>
body { text-align:left }
textarea {
font-size:18px;
text-align:left;
resize: none;
}
.ref {
border: medium solid gray;
width: 400px;
margin: 20px;
}
.comments {
display: none;
}
</style>
</head>
<body>
<div class="comments">
We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
specification states whether text-align:start and text-align:end should obey the paragraph
direction or the direction property in a unicode-bidi:plaintext element.
The ...! paragraph, being neutral, is supposed to be displayed LTR (i.e. as ...!, not as !...)
despite both the paragraph before it and the paragraph after it being all-RTL, which makes the
element as a whole RTL.
</div>
<div class="ref">
<div dir="ltr">
<textarea rows="5" dir="ltr">@123!
&#x05d0;
...!
&#x05d0;
</textarea>
</div>
<div dir="rtl">
<textarea rows="5" dir="ltr">@123!
&#x05d0;
...!
&#x05d0;
</textarea>
</div>
</div>
</body>
</html>

View File

@ -1,58 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML Test: textarea with dir=auto, all N+EN</title>
<link rel="author" title="Aharon Lanin" href="mailto:aharon@google.com">
<link rel="author" title="HTML5 bidi test WG" href="mailto:html5bidi@googlegroups.com">
<link rel="help" href="http://dev.w3.org/html5/spec/Overview.html#the-dir-attribute">
<link rel="help" href="http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi0">
<meta name="assert" content="
When dir='auto', the direction is set according to the first strong character
of the text.
For textarea and pre elements, the heuristic is applied on a per-paragraph level.
If there is no strong character, as in this test, the direction defaults to LTR.">
<style>
body { text-align:left; }
textarea {
font-size:18px;
text-align:left;
resize: none;
}
.test {
border: medium solid gray;
width: 400px;
margin: 20px;
}
.comments {
display: none;
}
</style>
</head>
<body>
<div class="comments">
We use text-align:left because neither the dir="auto" nor the unicode-bidi:plaintext
specification states whether text-align:start and text-align:end should obey the paragraph
direction or the direction property in a unicode-bidi:plaintext element.
The ...! paragraph, being neutral, is supposed to be displayed LTR (i.e. as ...!, not as !...)
despite both the paragraph before it and the paragraph after it being all-RTL, which makes the
element as a whole RTL.
</div>
<div class="test">
<div dir="ltr">
<textarea rows="5" dir="auto">@123!
&#x05d0;
...!
&#x05d0;
</textarea>
</div>
<div dir="rtl">
<textarea rows="5" dir="auto">@123!
&#x05d0;
...!
&#x05d0;
</textarea>
</div>
</div>
</body>
</html>

View File

@ -128,7 +128,6 @@ fuzzy(0-1,0-3) == 698291-1.html 698291-1-ref.html
== 718236-1.html 718236-1-ref.html
== 718236-2.html 718236-2-ref.html
== 718236-3.html 718236-3-ref.html
== 726420-1.html 726420-1-ref.html
== 726460-1.html 726460-1-ref.html
== 729047-1.html 729047-1-ref.html
== 730562-1.html 730562-1-ref.html

View File

@ -1,3 +0,0 @@
[dir_auto-textarea-N-between-Rs.html]
expected:
if (os == "android"): FAIL

View File

@ -12,7 +12,7 @@
When dir='auto', the direction is set according to the first strong character
of the text.
For textarea and pre elements, the heuristic is applied on a per-paragraph level.
If there is no strong character, as in this test, the direction defaults to LTR." />
If there is no strong character, the direction defaults to LTR." />
<style>
body, textarea {
font-size:18px;

View File

@ -0,0 +1,47 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="author" title="Vincent Hilla" href="mailto:vhilla@mozilla.com">
<link rel="help" href="https://html.spec.whatwg.org/#the-directionality">
</head>
<body>
<input id="inp"/>
<textarea id="ta"></textarea>
<div id="div"></div>
<pre id="pre"></pre>
<script>
function doTest(e) {
e.dir = "ltr";
assert_true(e.matches(":dir(ltr)"), "dir to ltr on " + e.tagName + " element");
e.dir = "rtl";
assert_true(e.matches(":dir(rtl)"), "dir to rtl on " + e.tagName + " element");
e.dir = "auto";
assert_true(e.matches(":dir(ltr)"), "dir to auto, empty text on " + e.tagName + " element");
e.value = "\u05D0;";
e.textContent = "\u05D0;";
assert_true(e.matches(":dir(rtl)"), "auto dir, text to Hebrew on " + e.tagName + " element");
e.dir = "ltr";
assert_true(e.matches(":dir(ltr)"), "dir to ltr, Hebrew text on " + e.tagName + " element");
e.dir = "auto";
assert_true(e.matches(":dir(rtl)"), "dir to auto, Hebrew text on " + e.tagName + " element");
e.removeAttribute("dir");
assert_true(e.matches(":dir(ltr)"), "dir removed, Hebrew text on " + e.tagName + " element");
}
const elements = [inp, ta, div, pre];
for (const e of elements) {
test(() => doTest(e), "Dynamically changing dir, text on " + e.tagName.toLowerCase() + " element");
}
</script>
</body>
</html>

View File

@ -35,8 +35,15 @@
<bdo dir="auto" id=bdo3>HEBREW</bdo>
<bdo dir="auto" id=bdo4>إيان</bdo>
<bdo dir="ltr" id=bdo5>עברית</bdo>
<textarea dir="auto" id="ta1">إيان</textarea>
<textarea dir="auto" id="ta2">HEBREWإيان</textarea>
<textarea dir="auto" id="ta3">إيان</textarea>
<pre dir="auto" id="pre1">إيان</pre>
<pre dir="auto" id="pre2">HEBREWإيان</pre>
<script id=script4>
ta3.value = "HEBREW";
const rtlElements = [
"bdo1",
"bdi2",
@ -46,6 +53,8 @@
"span7",
"input-tel3",
"bdo4",
"ta1",
"pre1",
];
testSelectorIdsMatch(":dir(rtl)", rtlElements, "':dir(rtl)' matches all elements whose directionality is 'rtl'.");
@ -74,6 +83,9 @@
"input-tel2",
"bdo3",
"bdo5",
"ta2",
"ta3",
"pre2",
"script4",
];