<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 6680aa1..9ba9ca0 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 6801a29..64cc7a6 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 745e1c9..9e05453 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);