[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.15.1-1414-gc69ee75
eric at webkit.org
eric at webkit.org
Thu Oct 29 20:32:49 UTC 2009
The following commit has been merged in the webkit-1.1 branch:
commit fa588e6768ec03b9a40c92f557a0d955e94d3bc3
Author: eric at webkit.org <eric at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Thu Sep 24 02:55:39 2009 +0000
2009-09-23 Kent Tamura <tkent at chromium.org>
Reviewed by Darin Adler.
Tests for maxLength of <textarea>
https://bugs.webkit.org/show_bug.cgi?id=29292
* fast/forms/script-tests/textarea-maxlength.js: Added.
* fast/forms/textarea-maxlength-expected.txt: Added.
* fast/forms/textarea-maxlength.html: Added.
2009-09-23 Kent Tamura <tkent at chromium.org>
Reviewed by Darin Adler.
- Support for maxLength of <textarea>
- Move numGraphemeClusters() and numCharactersInGraphemeClusters() from InputElement to String.
https://bugs.webkit.org/show_bug.cgi?id=29292
Test: fast/forms/textarea-maxlength.html
* dom/InputElement.cpp:
(WebCore::InputElement::sanitizeUserInputValue):
(WebCore::InputElement::handleBeforeTextInsertedEvent):
* html/HTMLTextAreaElement.cpp:
(WebCore::HTMLTextAreaElement::defaultEventHandler):
(WebCore::HTMLTextAreaElement::handleBeforeTextInsertedEvent):
(WebCore::HTMLTextAreaElement::sanitizeUserInputValue):
(WebCore::HTMLTextAreaElement::maxLength):
(WebCore::HTMLTextAreaElement::setMaxLength):
* html/HTMLTextAreaElement.h:
* html/HTMLTextAreaElement.idl:
* platform/text/PlatformString.h:
* platform/text/String.cpp:
(WebCore::String::numGraphemeClusters):
(WebCore::String::numCharactersInGraphemeClusters):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@48698 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index cc66725..2469b83 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2009-09-23 Kent Tamura <tkent at chromium.org>
+
+ Reviewed by Darin Adler.
+
+ Tests for maxLength of <textarea>
+ https://bugs.webkit.org/show_bug.cgi?id=29292
+
+ * fast/forms/script-tests/textarea-maxlength.js: Added.
+ * fast/forms/textarea-maxlength-expected.txt: Added.
+ * fast/forms/textarea-maxlength.html: Added.
+
2009-09-23 Martin Robinson <martin.james.robinson at gmail.com>
Reviewed by Xan Lopez.
diff --git a/LayoutTests/fast/forms/script-tests/textarea-maxlength.js b/LayoutTests/fast/forms/script-tests/textarea-maxlength.js
new file mode 100644
index 0000000..7cf0f5d
--- /dev/null
+++ b/LayoutTests/fast/forms/script-tests/textarea-maxlength.js
@@ -0,0 +1,120 @@
+description('Tests for HTMLTextAreaElement.maxLength behaviors.');
+
+var textArea = document.createElement('textarea');
+document.body.appendChild(textArea);
+
+// No maxlength attribute
+shouldBe('textArea.maxLength', '0');
+
+// Invalid maxlength attributes
+textArea.setAttribute('maxlength', '-3');
+shouldBe('textArea.maxLength', '0');
+textArea.setAttribute('maxlength', 'xyz');
+shouldBe('textArea.maxLength', '0');
+
+// Valid maxlength attributes
+textArea.setAttribute('maxlength', '1');
+shouldBe('textArea.maxLength', '1');
+textArea.setAttribute('maxlength', '256');
+shouldBe('textArea.maxLength', '256');
+
+// Set values to .maxLength
+textArea.maxLength = 13;
+shouldBe('textArea.getAttribute("maxlength")', '"13"');
+
+textArea.maxLength = -1;
+shouldBe('textArea.maxLength', '4294967295');
+shouldBe('textArea.getAttribute("maxlength")', '"4294967295"');
+
+// maxLength doesn't truncate the default value.
+textArea = document.createElement('textarea');
+textArea.setAttribute('maxlength', '3');
+textArea.innerHTML = 'abcd';
+document.body.appendChild(textArea);
+shouldBe('textArea.value', '"abcd"');
+
+// maxLength doesn't truncate .value
+textArea.maxLength = 3;
+textArea.value = 'abcde';
+shouldBe('textArea.value', '"abcde"');
+
+// Set up for user-input tests
+function createFocusedTextAreaWithMaxLength3() {
+ if (textArea)
+ document.body.removeChild(textArea);
+ textArea = document.createElement('textarea');
+ textArea.setAttribute('maxlength', '3');
+ document.body.appendChild(textArea);
+ textArea.focus();
+}
+
+// Insert text of which length is maxLength.
+createFocusedTextAreaWithMaxLength3();
+document.execCommand('insertText', false, 'abc');
+shouldBe('textArea.value', '"abc"');
+
+// Try to add characters to maxLength characters.
+createFocusedTextAreaWithMaxLength3();
+textArea.value = 'abc';
+document.execCommand('insertText', false, 'def');
+shouldBe('textArea.value', '"abc"');
+
+// Replace text
+createFocusedTextAreaWithMaxLength3();
+textArea.value = 'abc';
+document.execCommand('selectAll');
+document.execCommand('insertText', false, 'def');
+shouldBe('textArea.value', '"def"');
+
+// Existing value is longer than maxLength. We can't add text.
+createFocusedTextAreaWithMaxLength3();
+textArea.value = 'abcdef';
+document.execCommand('insertText', false, 'ghi');
+shouldBe('textArea.value', '"abcdef"');
+
+// We can delete a character in the longer value.
+createFocusedTextAreaWithMaxLength3();
+textArea.value = 'abcdef';
+document.execCommand('delete');
+shouldBe('textArea.value', '"abcde"');
+
+// A linebreak is 1 character.
+createFocusedTextAreaWithMaxLength3();
+document.execCommand('insertText', false, 'A');
+document.execCommand('insertLineBreak');
+document.execCommand('insertText', false, 'B');
+shouldBe('textArea.value', '"A\\nB"');
+
+// According to the HTML5 specification, maxLength is code-point length.
+// However WebKit handles it as grapheme length.
+
+// fancyX should be treated as 1 grapheme.
+var fancyX = "x\u0305\u0332";// + String.fromCharCode(0x305) + String.fromCharCode(0x332);
+// u10000 is one character consisted of a surrogate pair.
+var u10000 = "\ud800\udc00";
+
+// Inserts 5 code-points in UTF-16
+createFocusedTextAreaWithMaxLength3();
+document.execCommand('insertText', false, 'AB' + fancyX);
+shouldBe('textArea.value', '"AB" + fancyX');
+shouldBe('textArea.value.length', '5');
+
+createFocusedTextAreaWithMaxLength3();
+textArea.value = 'AB' + fancyX;
+textArea.setSelectionRange(2, 5); // Select fancyX
+document.execCommand('insertText', false, 'CDE');
+shouldBe('textArea.value', '"ABC"');
+
+// Inserts 4 code-points in UTF-16
+createFocusedTextAreaWithMaxLength3();
+document.execCommand('insertText', false, 'AB' + u10000);
+shouldBe('textArea.value', '"AB" + u10000');
+shouldBe('textArea.value.length', '4');
+
+createFocusedTextAreaWithMaxLength3();
+textArea.value = 'AB' + u10000;
+textArea.setSelectionRange(2, 4); // Select u10000
+document.execCommand('insertText', false, 'CDE');
+shouldBe('textArea.value', '"ABC"');
+
+var successfullyParsed = true;
diff --git a/LayoutTests/fast/forms/textarea-maxlength-expected.txt b/LayoutTests/fast/forms/textarea-maxlength-expected.txt
new file mode 100644
index 0000000..bd1aa17
--- /dev/null
+++ b/LayoutTests/fast/forms/textarea-maxlength-expected.txt
@@ -0,0 +1,31 @@
+Tests for HTMLTextAreaElement.maxLength behaviors.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS textArea.maxLength is 0
+PASS textArea.maxLength is 0
+PASS textArea.maxLength is 0
+PASS textArea.maxLength is 1
+PASS textArea.maxLength is 256
+PASS textArea.getAttribute("maxlength") is "13"
+PASS textArea.maxLength is 4294967295
+PASS textArea.getAttribute("maxlength") is "4294967295"
+PASS textArea.value is "abcd"
+PASS textArea.value is "abcde"
+PASS textArea.value is "abc"
+PASS textArea.value is "abc"
+PASS textArea.value is "def"
+PASS textArea.value is "abcdef"
+PASS textArea.value is "abcde"
+PASS textArea.value is "A\nB"
+PASS textArea.value is "AB" + fancyX
+PASS textArea.value.length is 5
+PASS textArea.value is "ABC"
+PASS textArea.value is "AB" + u10000
+PASS textArea.value.length is 4
+PASS textArea.value is "ABC"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/textarea-maxlength.html b/LayoutTests/fast/forms/textarea-maxlength.html
new file mode 100644
index 0000000..ac5ecdb
--- /dev/null
+++ b/LayoutTests/fast/forms/textarea-maxlength.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/textarea-maxlength.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 479db41..28b3d4c 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,29 @@
+2009-09-23 Kent Tamura <tkent at chromium.org>
+
+ Reviewed by Darin Adler.
+
+ - Support for maxLength of <textarea>
+ - Move numGraphemeClusters() and numCharactersInGraphemeClusters() from InputElement to String.
+ https://bugs.webkit.org/show_bug.cgi?id=29292
+
+ Test: fast/forms/textarea-maxlength.html
+
+ * dom/InputElement.cpp:
+ (WebCore::InputElement::sanitizeUserInputValue):
+ (WebCore::InputElement::handleBeforeTextInsertedEvent):
+ * html/HTMLTextAreaElement.cpp:
+ (WebCore::HTMLTextAreaElement::defaultEventHandler):
+ (WebCore::HTMLTextAreaElement::handleBeforeTextInsertedEvent):
+ (WebCore::HTMLTextAreaElement::sanitizeUserInputValue):
+ (WebCore::HTMLTextAreaElement::maxLength):
+ (WebCore::HTMLTextAreaElement::setMaxLength):
+ * html/HTMLTextAreaElement.h:
+ * html/HTMLTextAreaElement.idl:
+ * platform/text/PlatformString.h:
+ * platform/text/String.cpp:
+ (WebCore::String::numGraphemeClusters):
+ (WebCore::String::numCharactersInGraphemeClusters):
+
2009-09-23 Martin Robinson <martin.james.robinson at gmail.com>
Reviewed by Xan Lopez.
diff --git a/WebCore/dom/InputElement.cpp b/WebCore/dom/InputElement.cpp
index 97793e2..875d9f2 100644
--- a/WebCore/dom/InputElement.cpp
+++ b/WebCore/dom/InputElement.cpp
@@ -34,7 +34,6 @@
#include "RenderTextControlSingleLine.h"
#include "SelectionController.h"
#include "TextIterator.h"
-#include "TextBreakIterator.h"
#if ENABLE(WML)
#include "WMLInputElement.h"
@@ -159,23 +158,6 @@ void InputElement::setValueFromRenderer(InputElementData& data, InputElement* in
notifyFormStateChanged(element);
}
-static int numCharactersInGraphemeClusters(StringImpl* s, int numGraphemeClusters)
-{
- if (!s)
- return 0;
-
- TextBreakIterator* it = characterBreakIterator(s->characters(), s->length());
- if (!it)
- return 0;
-
- for (int i = 0; i < numGraphemeClusters; ++i) {
- if (textBreakNext(it) == TextBreakDone)
- return s->length();
- }
-
- return textBreakCurrent(it);
-}
-
String InputElement::sanitizeValue(const InputElement* inputElement, const String& proposedValue)
{
return InputElement::sanitizeUserInputValue(inputElement, proposedValue, s_maximumLength);
@@ -191,36 +173,15 @@ String InputElement::sanitizeUserInputValue(const InputElement* inputElement, co
string.replace('\r', ' ');
string.replace('\n', ' ');
- StringImpl* s = string.impl();
- int newLength = numCharactersInGraphemeClusters(s, maxLength);
- for (int i = 0; i < newLength; ++i) {
- const UChar& current = (*s)[i];
+ unsigned newLength = string.numCharactersInGraphemeClusters(maxLength);
+ for (unsigned i = 0; i < newLength; ++i) {
+ const UChar current = string[i];
if (current < ' ' && current != '\t') {
newLength = i;
break;
}
}
-
- if (newLength < static_cast<int>(string.length()))
- return string.left(newLength);
-
- return string;
-}
-
-static int numGraphemeClusters(StringImpl* s)
-{
- if (!s)
- return 0;
-
- TextBreakIterator* it = characterBreakIterator(s->characters(), s->length());
- if (!it)
- return 0;
-
- int num = 0;
- while (textBreakNext(it) != TextBreakDone)
- ++num;
-
- return num;
+ return string.left(newLength);
}
void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputElement* inputElement, Element* element, Event* event)
@@ -231,15 +192,16 @@ void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputEl
// We use RenderTextControlSingleLine::text() instead of InputElement::value()
// because they can be mismatched by sanitizeValue() in
// RenderTextControlSingleLine::subtreeHasChanged() in some cases.
- int oldLength = numGraphemeClusters(toRenderTextControlSingleLine(element->renderer())->text().impl());
+ unsigned oldLength = toRenderTextControlSingleLine(element->renderer())->text().numGraphemeClusters();
// selection() may be a pre-edit text.
- int selectionLength = numGraphemeClusters(plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get()).impl());
+ unsigned selectionLength = plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get()).numGraphemeClusters();
ASSERT(oldLength >= selectionLength);
// Selected characters will be removed by the next text event.
- int baseLength = oldLength - selectionLength;
- int appendableLength = data.maxLength() - baseLength;
+ unsigned baseLength = oldLength - selectionLength;
+ unsigned maxLength = static_cast<unsigned>(data.maxLength()); // maxLength() can never be negative.
+ unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0;
// Truncate the inserted text to avoid violating the maxLength and other constraints.
BeforeTextInsertedEvent* textEvent = static_cast<BeforeTextInsertedEvent*>(event);
diff --git a/WebCore/html/HTMLTextAreaElement.cpp b/WebCore/html/HTMLTextAreaElement.cpp
index d3fc897..3cf4852 100644
--- a/WebCore/html/HTMLTextAreaElement.cpp
+++ b/WebCore/html/HTMLTextAreaElement.cpp
@@ -26,6 +26,7 @@
#include "config.h"
#include "HTMLTextAreaElement.h"
+#include "BeforeTextInsertedEvent.h"
#include "ChromeClient.h"
#include "CSSValueKeywords.h"
#include "Document.h"
@@ -35,12 +36,14 @@
#include "FormDataList.h"
#include "Frame.h"
#include "HTMLNames.h"
+#include "InputElement.h"
#include "MappedAttribute.h"
#include "Page.h"
#include "RenderStyle.h"
#include "RenderTextControlMultiLine.h"
#include "ScriptEventListener.h"
#include "Text.h"
+#include "TextIterator.h"
#include "VisibleSelection.h"
#include <wtf/StdLibExtras.h>
@@ -270,10 +273,34 @@ void HTMLTextAreaElement::defaultEventHandler(Event* event)
{
if (renderer() && (event->isMouseEvent() || event->isDragEvent() || event->isWheelEvent() || event->type() == eventNames().blurEvent))
toRenderTextControlMultiLine(renderer())->forwardEvent(event);
+ else if (renderer() && event->isBeforeTextInsertedEvent())
+ handleBeforeTextInsertedEvent(static_cast<BeforeTextInsertedEvent*>(event));
HTMLFormControlElementWithState::defaultEventHandler(event);
}
+void HTMLTextAreaElement::handleBeforeTextInsertedEvent(BeforeTextInsertedEvent* event) const
+{
+ ASSERT(event);
+ ASSERT(renderer());
+ bool ok;
+ unsigned maxLength = getAttribute(maxlengthAttr).string().toUInt(&ok);
+ if (!ok)
+ return;
+
+ unsigned currentLength = toRenderTextControl(renderer())->text().numGraphemeClusters();
+ unsigned selectionLength = plainText(document()->frame()->selection()->selection().toNormalizedRange().get()).numGraphemeClusters();
+ ASSERT(currentLength >= selectionLength);
+ unsigned baseLength = currentLength - selectionLength;
+ unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0;
+ event->setText(sanitizeUserInputValue(event->text(), appendableLength));
+}
+
+String HTMLTextAreaElement::sanitizeUserInputValue(const String& proposedValue, unsigned maxLength)
+{
+ return proposedValue.left(proposedValue.numCharactersInGraphemeClusters(maxLength));
+}
+
void HTMLTextAreaElement::rendererWillBeDestroyed()
{
updateValue();
@@ -374,6 +401,16 @@ void HTMLTextAreaElement::setDefaultValue(const String& defaultValue)
setValue(value);
}
+unsigned HTMLTextAreaElement::maxLength() const
+{
+ return getAttribute(maxlengthAttr).string().toUInt();
+}
+
+void HTMLTextAreaElement::setMaxLength(unsigned newValue)
+{
+ setAttribute(maxlengthAttr, String::number(newValue));
+}
+
void HTMLTextAreaElement::accessKeyAction(bool)
{
focus();
diff --git a/WebCore/html/HTMLTextAreaElement.h b/WebCore/html/HTMLTextAreaElement.h
index 1f5cb91..fbf519d 100644
--- a/WebCore/html/HTMLTextAreaElement.h
+++ b/WebCore/html/HTMLTextAreaElement.h
@@ -28,6 +28,7 @@
namespace WebCore {
+class BeforeTextInsertedEvent;
class VisibleSelection;
class HTMLTextAreaElement : public HTMLFormControlElementWithState {
@@ -78,6 +79,8 @@ public:
String defaultValue() const;
void setDefaultValue(const String&);
int textLength() const { return value().length(); }
+ unsigned maxLength() const;
+ void setMaxLength(unsigned);
void rendererWillBeDestroyed();
@@ -99,6 +102,8 @@ public:
private:
enum WrapMethod { NoWrap, SoftWrap, HardWrap };
+ void handleBeforeTextInsertedEvent(BeforeTextInsertedEvent*) const;
+ static String sanitizeUserInputValue(const String&, unsigned maxLength);
void updateValue() const;
void updatePlaceholderVisibility(bool placeholderValueChanged);
virtual void dispatchFocusEvent();
diff --git a/WebCore/html/HTMLTextAreaElement.idl b/WebCore/html/HTMLTextAreaElement.idl
index 6d27f54..84583f5 100644
--- a/WebCore/html/HTMLTextAreaElement.idl
+++ b/WebCore/html/HTMLTextAreaElement.idl
@@ -34,6 +34,7 @@ module html {
attribute long cols;
attribute boolean disabled;
attribute boolean autofocus;
+ attribute unsigned long maxLength;
attribute [ConvertNullToNullString] DOMString name;
attribute [ConvertNullToNullString, Reflect] DOMString placeholder;
attribute boolean readOnly;
diff --git a/WebCore/platform/text/PlatformString.h b/WebCore/platform/text/PlatformString.h
index 258b28d..b9b4078 100644
--- a/WebCore/platform/text/PlatformString.h
+++ b/WebCore/platform/text/PlatformString.h
@@ -254,6 +254,14 @@ public:
// Determines the writing direction using the Unicode Bidi Algorithm rules P2 and P3.
WTF::Unicode::Direction defaultWritingDirection() const { return m_impl ? m_impl->defaultWritingDirection() : WTF::Unicode::LeftToRight; }
+ // Counts the number of grapheme clusters. A surrogate pair or a sequence
+ // of a non-combining character and following combining characters is
+ // counted as 1 grapheme cluster.
+ unsigned numGraphemeClusters() const;
+ // Returns the number of characters which will be less than or equal to
+ // the specified grapheme cluster length.
+ unsigned numCharactersInGraphemeClusters(unsigned) const;
+
private:
RefPtr<StringImpl> m_impl;
};
diff --git a/WebCore/platform/text/String.cpp b/WebCore/platform/text/String.cpp
index 2730939..e892ef6 100644
--- a/WebCore/platform/text/String.cpp
+++ b/WebCore/platform/text/String.cpp
@@ -25,6 +25,7 @@
#include "CString.h"
#include "FloatConversion.h"
#include "StringBuffer.h"
+#include "TextBreakIterator.h"
#include "TextEncoding.h"
#include <wtf/dtoa.h>
#include <limits>
@@ -921,6 +922,31 @@ PassRefPtr<SharedBuffer> utf8Buffer(const String& string)
return SharedBuffer::adoptVector(buffer);
}
+unsigned String::numGraphemeClusters() const
+{
+ TextBreakIterator* it = characterBreakIterator(characters(), length());
+ if (!it)
+ return length();
+
+ unsigned num = 0;
+ while (textBreakNext(it) != TextBreakDone)
+ ++num;
+ return num;
+}
+
+unsigned String::numCharactersInGraphemeClusters(unsigned numGraphemeClusters) const
+{
+ TextBreakIterator* it = characterBreakIterator(characters(), length());
+ if (!it)
+ return min(length(), numGraphemeClusters);
+
+ for (unsigned i = 0; i < numGraphemeClusters; ++i) {
+ if (textBreakNext(it) == TextBreakDone)
+ return length();
+ }
+ return textBreakCurrent(it);
+}
+
} // namespace WebCore
#ifndef NDEBUG
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list