<https://webkit.org/b/119917> Pasting multiple lines into a textarea can introduce...
authorrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 18 Aug 2013 18:54:12 +0000 (18:54 +0000)
committerrniwa@webkit.org <rniwa@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 18 Aug 2013 18:54:12 +0000 (18:54 +0000)
Reviewed by Darin Adler.

Source/WebCore:

Inspired by https://chromium.googlesource.com/chromium/blink/+/6152a12f7ace27beea4d284ff8416631e8aa5217.

The bug was caused by createFragmentFromText's falsely assuming that the newline were not preserved
if the first node's renderer didn't exist.

Fixed the bug by obtaining the renderer of the container of the first visible position in the context.

Test: editing/pasteboard/paste-into-textarea-with-new-line.html

* editing/markup.cpp:
(WebCore::contextPreservesNewline):
(WebCore::createFragmentFromText):

LayoutTests:

Add a regression test.

* editing/pasteboard/paste-into-textarea-with-new-line-expected.txt: Added.
* editing/pasteboard/paste-into-textarea-with-new-line.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/editing/pasteboard/paste-into-textarea-with-new-line-expected.txt [new file with mode: 0644]
LayoutTests/editing/pasteboard/paste-into-textarea-with-new-line.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/editing/markup.cpp

index 6680aa127da0f91bbaf3347d8a6f5092ad400d6e..9ba9ca08aaa41ae003bc20816bf0a12e6359aa13 100644 (file)
@@ -1,3 +1,14 @@
+2013-08-18  Ryosuke Niwa  <rniwa@webkit.org>
+
+        <https://webkit.org/b/119917> Pasting multiple lines into a textarea can introduce extra new lines
+
+        Reviewed by Darin Adler.
+
+        Add a regression test.
+
+        * editing/pasteboard/paste-into-textarea-with-new-line-expected.txt: Added.
+        * editing/pasteboard/paste-into-textarea-with-new-line.html: Added.
+
 2013-08-18  Antti Koivisto  <antti@apple.com>
 
         <https://webkit.org/b/119963> Use TextNodeTraversal for getting sheet text in StyleElement
diff --git a/LayoutTests/editing/pasteboard/paste-into-textarea-with-new-line-expected.txt b/LayoutTests/editing/pasteboard/paste-into-textarea-with-new-line-expected.txt
new file mode 100644 (file)
index 0000000..20bc1a0
--- /dev/null
@@ -0,0 +1,10 @@
+This tests pasting a multi-line text into a textarea that contains a single new line. WebKit should preserve the number of new lines.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.execCommand('InsertHTML', false, 'first<br><br>third'); textarea.value is 'first\n\nthird\n'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/editing/pasteboard/paste-into-textarea-with-new-line.html b/LayoutTests/editing/pasteboard/paste-into-textarea-with-new-line.html
new file mode 100644 (file)
index 0000000..990cd70
--- /dev/null
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+<script>
+
+description("This tests pasting a multi-line text into a textarea that contains a single new line. WebKit should preserve the number of new lines.");
+
+var textarea = document.createElement("textarea");
+textarea.value = "\n";
+textarea.rows = 10;
+document.body.appendChild(textarea);
+textarea.focus();
+shouldBe("document.execCommand('InsertHTML', false, 'first<br><br>third'); textarea.value", "'first\\n\\nthird\\n'");
+
+var successfullyParsed = true;
+
+</script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
index 6801a29989368f5b8637848a55659dedcc6b22e2..64cc7a658723480089287d0c257f5be9940416c1 100644 (file)
@@ -1,3 +1,22 @@
+2013-08-18  Ryosuke Niwa  <rniwa@webkit.org>
+
+        <https://webkit.org/b/119917> Pasting multiple lines into a textarea can introduce extra new lines
+
+        Reviewed by Darin Adler.
+
+        Inspired by https://chromium.googlesource.com/chromium/blink/+/6152a12f7ace27beea4d284ff8416631e8aa5217.
+
+        The bug was caused by createFragmentFromText's falsely assuming that the newline were not preserved
+        if the first node's renderer didn't exist.
+
+        Fixed the bug by obtaining the renderer of the container of the first visible position in the context.
+
+        Test: editing/pasteboard/paste-into-textarea-with-new-line.html
+
+        * editing/markup.cpp:
+        (WebCore::contextPreservesNewline):
+        (WebCore::createFragmentFromText):
+
 2013-08-18  Andreas Kling  <akling@apple.com>
 
         <https://webkit.org/b/119983> Add two missing RefPtr::release() in HTMLLinkElement.
index 745e1c9f9b28ffab0ec5d35845b6cebaf179a337..9e05453a544fc87be7c2f41e39ea83d1b66cac59 100644 (file)
@@ -823,19 +823,22 @@ bool isPlainTextMarkup(Node *node)
     return (node->childNodeCount() == 2 && isTabSpanTextNode(node->firstChild()->firstChild()) && node->firstChild()->nextSibling()->isTextNode());
 }
 
+static bool contextPreservesNewline(const Range& context)
+{
+    VisiblePosition position(context.startPosition());
+    Node* container = position.deepEquivalent().containerNode();
+    if (!container || !container->renderer())
+        return false;
+
+    return container->renderer()->style()->preserveNewline();
+}
+
 PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String& text)
 {
     if (!context)
         return 0;
 
-    Node* styleNode = context->firstNode();
-    if (!styleNode) {
-        styleNode = context->startPosition().deprecatedNode();
-        if (!styleNode)
-            return 0;
-    }
-
-    Document* document = styleNode->document();
+    Document* document = context->ownerDocument();
     RefPtr<DocumentFragment> fragment = document->createDocumentFragment();
     
     if (text.isEmpty())
@@ -845,8 +848,7 @@ PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String
     string.replace("\r\n", "\n");
     string.replace('\r', '\n');
 
-    RenderObject* renderer = styleNode->renderer();
-    if (renderer && renderer->style()->preserveNewline()) {
+    if (contextPreservesNewline(*context)) {
         fragment->appendChild(document->createTextNode(string), ASSERT_NO_EXCEPTION);
         if (string.endsWith('\n')) {
             RefPtr<Element> element = createBreakElement(document);