2010-02-11 Kent Tamura <tkent@chromium.org>
authortkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Feb 2010 02:37:19 +0000 (02:37 +0000)
committertkent@chromium.org <tkent@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Feb 2010 02:37:19 +0000 (02:37 +0000)
        Reviewed by Darin Adler.

        Fix two issues on maxLength.
        https://bugs.webkit.org/show_bug.cgi?id=34783

        - Add grapheme test cases
        - Improve test result readability

        * fast/forms/ValidityState-tooLong-input-expected.txt:
        * fast/forms/ValidityState-tooLong-textarea-expected.txt:
        * fast/forms/script-tests/ValidityState-tooLong-input.js:
        * fast/forms/script-tests/ValidityState-tooLong-textarea.js:
2010-02-11  Kent Tamura  <tkent@chromium.org>

        Reviewed by Darin Adler.

        Fix two issues on maxLength.
        https://bugs.webkit.org/show_bug.cgi?id=34783

        - ValidityState.tooLong behavior was inconsistent with UIs of
        <input> and <textarea>. tooLong checked Unicode code point length
        though the UIs checks grapheme cluster length.

        - Setting HTMLTextAreaElement::value didn't update the dirty flag.

        * html/HTMLInputElement.cpp:
        (WebCore::HTMLInputElement::tooLong): Use numGraphemeClusters() instead of length().
        * html/HTMLTextAreaElement.cpp:
          Rename setValue() to setNonDirtyValue(), and introduce setValue()
          which calls setNonDirtyValue() and sets the dirty flag.
        (WebCore::HTMLTextAreaElement::childrenChanged):
        (WebCore::HTMLTextAreaElement::reset):
        (WebCore::HTMLTextAreaElement::setValue):
        (WebCore::HTMLTextAreaElement::setNonDirtyValue):
        (WebCore::HTMLTextAreaElement::setDefaultValue):
        (WebCore::HTMLTextAreaElement::tooLong): Use numGraphemeClusters() instead of length().
        * html/HTMLTextAreaElement.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@54695 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/forms/ValidityState-tooLong-input-expected.txt
LayoutTests/fast/forms/ValidityState-tooLong-textarea-expected.txt
LayoutTests/fast/forms/script-tests/ValidityState-tooLong-input.js
LayoutTests/fast/forms/script-tests/ValidityState-tooLong-textarea.js
WebCore/ChangeLog
WebCore/html/HTMLInputElement.cpp
WebCore/html/HTMLTextAreaElement.cpp
WebCore/html/HTMLTextAreaElement.h

index 0157994..c8d89b6 100644 (file)
@@ -1,3 +1,18 @@
+2010-02-11  Kent Tamura  <tkent@chromium.org>
+
+        Reviewed by Darin Adler.
+
+        Fix two issues on maxLength.
+        https://bugs.webkit.org/show_bug.cgi?id=34783
+
+        - Add grapheme test cases
+        - Improve test result readability
+
+        * fast/forms/ValidityState-tooLong-input-expected.txt:
+        * fast/forms/ValidityState-tooLong-textarea-expected.txt:
+        * fast/forms/script-tests/ValidityState-tooLong-input.js:
+        * fast/forms/script-tests/ValidityState-tooLong-textarea.js:
+
 2010-02-11  Fumitoshi Ukai  <ukai@chromium.org>
 
         Reviewed by Alexey Proskuryakov.
index 945b9b3..e81db3a 100644 (file)
@@ -3,15 +3,27 @@ Tests for tooLong flag with <input> elements.
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
+No maxlength and no value
 PASS input.validity.tooLong is false
+
+Non-dirty value
 PASS input.value.length is 5
 PASS input.validity.tooLong is false
 PASS input.value.length is 6
 PASS input.validity.tooLong is false
+
+Dirty value and longer than maxLength
 PASS input.value.length is 4
 PASS input.validity.tooLong is true
 PASS input.validity.tooLong is false
+
+Sets a value via DOM property
 PASS input.validity.tooLong is true
+
+Grapheme length is not greater than maxLength though character length is greater
+PASS input.validity.tooLong is false
+
+Change the type with a too long value
 PASS input.validity.tooLong is true
 PASS input.validity.tooLong is false
 PASS successfullyParsed is true
index d9e5bb5..947d428 100644 (file)
@@ -3,16 +3,35 @@ Tests for tooLong flag with <textarea> elements.
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
+No maxlength and no value
 PASS textarea.validity.tooLong is false
+
+Non-dirty value
 PASS textarea.value.length is 5
 PASS textarea.validity.tooLong is false
 PASS textarea.value.length is 6
 PASS textarea.validity.tooLong is false
+
+Dirty value and longer than maxLength
 PASS textarea.value.length is 4
 PASS textarea.validity.tooLong is true
 PASS textarea.validity.tooLong is false
+
+Sets a value via DOM property
 PASS textarea.validity.tooLong is true
+
+Grapheme length is not greater than maxLength though character length is greater
+PASS textarea.validity.tooLong is false
+
+A value set by resetting a form or by a child node change doesn't make tooLong true.
+PASS textarea.validity.tooLong is true
+PASS textarea.value is "abc"
+PASS textarea.validity.tooLong is false
+PASS textarea.validity.tooLong is true
+PASS textarea.value is "abcdef"
+PASS textarea.validity.tooLong is false
 PASS successfullyParsed is true
 
 TEST COMPLETE
 
+
index dc6109e..ae00ac9 100644 (file)
@@ -3,10 +3,11 @@ description('Tests for tooLong flag with &lt;input> elements.');
 var input = document.createElement('input');
 document.body.appendChild(input);
 
-// No maxlength and no value
+debug('No maxlength and no value');
 shouldBeFalse('input.validity.tooLong');
 
-// Non-dirty value.
+debug('');
+debug('Non-dirty value');
 input.setAttribute('value', 'abcde');
 input.maxLength = 3;
 shouldBe('input.value.length', '5');
@@ -16,7 +17,8 @@ input.setAttribute('value', 'abcdef');
 shouldBe('input.value.length', '6');
 shouldBeFalse('input.validity.tooLong');
 
-// Dirty value and longer than maxLength.
+debug('');
+debug('Dirty value and longer than maxLength');
 input = document.createElement('input');
 document.body.appendChild(input);
 input.setAttribute('value', 'abcde');
@@ -30,11 +32,28 @@ shouldBeTrue('input.validity.tooLong');
 document.execCommand('delete');
 shouldBeFalse('input.validity.tooLong');
 
-// Sets a value via DOM property.
+debug('');
+debug('Sets a value via DOM property');
+input.maxLength = 3;
 input.value = 'abcde';
 shouldBeTrue('input.validity.tooLong');
 
-// Change the type with a too long value.
+debug('');
+debug('Grapheme length is not greater than maxLength though character length is greater');
+// fancyX should be treated as 1 grapheme.
+// U+0305 COMBINING OVERLINE
+// U+0332 COMBINING LOW LINE
+var fancyX = "x\u0305\u0332";
+input = document.createElement('input');
+document.body.appendChild(input);
+input.value = fancyX; // 3 characters, 1 grapheme clusters.
+input.maxLength = 1;
+shouldBeFalse('input.validity.tooLong');
+
+debug('');
+debug('Change the type with a too long value');
+input.maxLength = 3;
+input.value = 'abcde';
 input.type = 'search';
 shouldBeTrue('input.validity.tooLong');
 
index 4a1fe17..a748d88 100644 (file)
@@ -3,10 +3,11 @@ description('Tests for tooLong flag with &lt;textarea> elements.');
 var textarea = document.createElement('textarea');
 document.body.appendChild(textarea);
 
-// No maxlength and no value
+debug('No maxlength and no value');
 shouldBeFalse('textarea.validity.tooLong');
 
-// Non-dirty value.
+debug('');
+debug('Non-dirty value');
 textarea.defaultValue = 'abcde';
 textarea.maxLength = 3;
 shouldBe('textarea.value.length', '5');
@@ -16,7 +17,8 @@ textarea.defaultValue = 'abcdef';
 shouldBe('textarea.value.length', '6');
 shouldBeFalse('textarea.validity.tooLong');
 
-// Dirty value and longer than maxLength.
+debug('');
+debug('Dirty value and longer than maxLength');
 textarea = document.createElement('textarea');
 document.body.appendChild(textarea);
 textarea.defaultValue = 'abcde';
@@ -30,8 +32,45 @@ shouldBeTrue('textarea.validity.tooLong');
 document.execCommand('delete');
 shouldBeFalse('textarea.validity.tooLong');
 
-// Sets a value via DOM property.
+debug('');
+debug('Sets a value via DOM property');
+textarea = document.createElement('textarea');
+document.body.appendChild(textarea);
+textarea.maxLength = 3;
 textarea.value = 'abcde';
 shouldBeTrue('textarea.validity.tooLong');
 
+debug('');
+debug('Grapheme length is not greater than maxLength though character length is greater');
+// fancyX should be treated as 1 grapheme.
+// U+0305 COMBINING OVERLINE
+// U+0332 COMBINING LOW LINE
+var fancyX = "x\u0305\u0332";
+textarea = document.createElement('textarea');
+document.body.appendChild(textarea);
+textarea.value = fancyX; // 3 characters, 1 grapheme cluster.
+textarea.maxLength = 1;
+shouldBeFalse('textarea.validity.tooLong');
+
+debug('');
+debug('A value set by resetting a form or by a child node change doesn\'t make tooLong true.');
+// Make a dirty textarea.
+var parent = document.createElement('div');
+document.body.appendChild(parent);
+parent.innerHTML = '<form><textarea maxlength=2>abc</textarea></form>';
+textarea = parent.firstChild.firstChild;
+textarea.value = 'def';
+shouldBeTrue('textarea.validity.tooLong');
+parent.firstChild.reset();
+shouldBe('textarea.value', '"abc"');
+shouldBeFalse('textarea.validity.tooLong');
+
+parent.innerHTML = '<textarea maxlength=2>abc</textarea>';
+textarea = parent.firstChild;
+textarea.value = 'def';
+shouldBeTrue('textarea.validity.tooLong');
+parent.firstChild.innerHTML = 'abcdef';
+shouldBe('textarea.value', '"abcdef"');
+shouldBeFalse('textarea.validity.tooLong');
+
 var successfullyParsed = true;
index 10c443e..f87bbc1 100644 (file)
@@ -1,3 +1,29 @@
+2010-02-11  Kent Tamura  <tkent@chromium.org>
+
+        Reviewed by Darin Adler.
+
+        Fix two issues on maxLength.
+        https://bugs.webkit.org/show_bug.cgi?id=34783
+
+        - ValidityState.tooLong behavior was inconsistent with UIs of
+        <input> and <textarea>. tooLong checked Unicode code point length
+        though the UIs checks grapheme cluster length.
+
+        - Setting HTMLTextAreaElement::value didn't update the dirty flag.
+
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::tooLong): Use numGraphemeClusters() instead of length().
+        * html/HTMLTextAreaElement.cpp:
+          Rename setValue() to setNonDirtyValue(), and introduce setValue()
+          which calls setNonDirtyValue() and sets the dirty flag.
+        (WebCore::HTMLTextAreaElement::childrenChanged):
+        (WebCore::HTMLTextAreaElement::reset):
+        (WebCore::HTMLTextAreaElement::setValue):
+        (WebCore::HTMLTextAreaElement::setNonDirtyValue):
+        (WebCore::HTMLTextAreaElement::setDefaultValue):
+        (WebCore::HTMLTextAreaElement::tooLong): Use numGraphemeClusters() instead of length().
+        * html/HTMLTextAreaElement.h:
+
 2010-02-11  Fumitoshi Ukai  <ukai@chromium.org>
 
         Reviewed by Alexey Proskuryakov.
index a1ad0c1..43f71ab 100644 (file)
@@ -267,7 +267,7 @@ bool HTMLInputElement::tooLong() const
         bool userEdited = !m_data.value().isNull();
         if (!userEdited)
             return false;
-        return value().length() > static_cast<unsigned>(max);
+        return value().numGraphemeClusters() > static_cast<unsigned>(max);
     }
     case BUTTON:
     case CHECKBOX:
index afbf43c..79bf45f 100644 (file)
@@ -97,7 +97,7 @@ void HTMLTextAreaElement::restoreFormControlState(const String& state)
 
 void HTMLTextAreaElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
 {
-    setValue(defaultValue());
+    setNonDirtyValue(defaultValue());
     HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
 }
     
@@ -176,8 +176,7 @@ bool HTMLTextAreaElement::appendFormData(FormDataList& encoding, bool)
 
 void HTMLTextAreaElement::reset()
 {
-    setValue(defaultValue());
-    m_isDirty = false;
+    setNonDirtyValue(defaultValue());
 }
 
 bool HTMLTextAreaElement::isKeyboardFocusable(KeyboardEvent*) const
@@ -274,6 +273,12 @@ String HTMLTextAreaElement::value() const
 
 void HTMLTextAreaElement::setValue(const String& value)
 {
+    setNonDirtyValue(value);
+    m_isDirty = true;
+}
+
+void HTMLTextAreaElement::setNonDirtyValue(const String& value)
+{
     // Code elsewhere normalizes line endings added by the user via the keyboard or pasting.
     // We normalize line endings coming from JavaScript here.
     String normalizedValue = value.isNull() ? "" : value;
@@ -286,6 +291,7 @@ void HTMLTextAreaElement::setValue(const String& value)
         return;
 
     m_value = normalizedValue;
+    m_isDirty = false;
     setFormControlValueMatchesRenderer(true);
     updatePlaceholderVisibility(false);
     if (inDocument())
@@ -347,7 +353,7 @@ void HTMLTextAreaElement::setDefaultValue(const String& defaultValue)
 
     insertBefore(document()->createTextNode(value), firstChild(), ec);
 
-    setValue(value);
+    setNonDirtyValue(value);
 }
 
 int HTMLTextAreaElement::maxLength() const
@@ -374,7 +380,7 @@ bool HTMLTextAreaElement::tooLong() const
     int max = maxLength();
     if (max < 0)
         return false;
-    return value().length() > static_cast<unsigned>(max);
+    return value().numGraphemeClusters() > static_cast<unsigned>(max);
 }
 
 void HTMLTextAreaElement::accessKeyAction(bool)
index 23f61d3..8d92a48 100644 (file)
@@ -94,6 +94,7 @@ private:
     void handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*) const;
     static String sanitizeUserInputValue(const String&, unsigned maxLength);
     void updateValue() const;
+    void setNonDirtyValue(const String&);
 
     virtual bool supportsPlaceholder() const { return true; }
     virtual bool isEmptyValue() const { return value().isEmpty(); }