Title: [159620] trunk
Revision
159620
Author
[email protected]
Date
2013-11-21 05:52:09 -0800 (Thu, 21 Nov 2013)

Log Message

Fix Range.insertNode when the inserted node is in the same container as the Range
https://bugs.webkit.org/show_bug.cgi?id=123957

Reviewed by Antti Koivisto.

Source/WebCore:

Inspired by https://chromium.googlesource.com/chromium/blink/+/fb6ca1f488703e8d4f20ce6449cc8ea210be6edb

When a node from the same container is inserted, we can't simply adjust m_end with the offset.
Compute m_start and m_end from the inserted nodes instead.

Also, don't adjust m_start and m_end to nodes outside of the document if the inserted nodes had been
removed by mutation events.

Test: fast/dom/Range/range-insertNode-same-container.html

* dom/Range.cpp:
(WebCore::Range::insertNode):

LayoutTests:

Merge https://chromium.googlesource.com/chromium/blink/+/fb6ca1f488703e8d4f20ce6449cc8ea210be6edb

Used better labels between divs, and added more evalAndLog and shouldBe so that
the expected result is self-explanatory.

* fast/dom/Range/range-insertNode-same-container-expected.txt: Added.
* fast/dom/Range/range-insertNode-same-container.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (159619 => 159620)


--- trunk/LayoutTests/ChangeLog	2013-11-21 13:46:39 UTC (rev 159619)
+++ trunk/LayoutTests/ChangeLog	2013-11-21 13:52:09 UTC (rev 159620)
@@ -1,5 +1,20 @@
 2013-11-21  Ryosuke Niwa  <[email protected]>
 
+        Fix Range.insertNode when the inserted node is in the same container as the Range
+        https://bugs.webkit.org/show_bug.cgi?id=123957
+
+        Reviewed by Antti Koivisto.
+
+        Merge https://chromium.googlesource.com/chromium/blink/+/fb6ca1f488703e8d4f20ce6449cc8ea210be6edb
+
+        Used better labels between divs, and added more evalAndLog and shouldBe so that
+        the expected result is self-explanatory.
+
+        * fast/dom/Range/range-insertNode-same-container-expected.txt: Added.
+        * fast/dom/Range/range-insertNode-same-container.html: Added.
+
+2013-11-21  Ryosuke Niwa  <[email protected]>
+
         nextBoundary and previousBoundary are very slow when there is a password field
         https://bugs.webkit.org/show_bug.cgi?id=123973
 

Added: trunk/LayoutTests/fast/dom/Range/range-insertNode-same-container-expected.txt (0 => 159620)


--- trunk/LayoutTests/fast/dom/Range/range-insertNode-same-container-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/Range/range-insertNode-same-container-expected.txt	2013-11-21 13:52:09 UTC (rev 159620)
@@ -0,0 +1,49 @@
+insertedElement = document.getElementById("div1");
+range.setStart(containerElement, 3); range.setEnd(containerElement, 3); range.insertNode(insertedElement);
+PASS range.startContainer is containerElement
+PASS range.endContainer is containerElement
+PASS range.startOffset is 2
+PASS range.endOffset is 3
+PASS range.toString() is "1"
+range.setStart(containerElement, 3); range.setEnd(containerElement, 3); range.insertNode(insertedElement);
+PASS range.startContainer is containerElement
+PASS range.endContainer is containerElement
+PASS range.startOffset is 2
+PASS range.endOffset is 3
+PASS range.toString() is "1"
+insertedElement = document.getElementById("div3");
+range.setStart(containerElement, 5); range.setEnd(containerElement, 5); range.insertNode(insertedElement);
+PASS range.startContainer is containerElement
+PASS range.endContainer is containerElement
+PASS range.startOffset is 4
+PASS range.endOffset is 5
+PASS range.toString() is "3-begin 45 3-end"
+range.setStart(containerElement, 5); range.setEnd(containerElement, 5); range.insertNode(insertedElement);
+PASS range.startContainer is containerElement
+PASS range.endContainer is containerElement
+PASS range.startOffset is 4
+PASS range.endOffset is 5
+PASS range.toString() is "3-begin 45 3-end"
+insertedElement = document.getElementById("div6");
+range.setStart(containerElement, 1); range.setEnd(containerElement, 1); range.insertNode(insertedElement);
+PASS range.startContainer is containerElement
+PASS range.endContainer is containerElement
+PASS range.startOffset is 1
+PASS range.endOffset is 2
+PASS range.toString() is "6"
+insertedElement = document.getElementById("div3");
+range.setStart(containerElement, 4); range.setEnd(containerElement, 4); range.insertNode(insertedElement);
+PASS range.startContainer is containerElement
+PASS range.endContainer is containerElement
+PASS range.startOffset is 4
+PASS range.endOffset is 5
+PASS range.toString() is "3-begin 45 3-end"
+PASS documentFragment = range.extractContents(); range.startContainer is containerElement
+PASS range.startOffset is 4
+PASS range.endContainer is containerElement
+PASS range.endOffset is 4
+PASS range.insertNode(documentFragment); range.toString() is "3-begin 45 3-end"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/dom/Range/range-insertNode-same-container.html (0 => 159620)


--- trunk/LayoutTests/fast/dom/Range/range-insertNode-same-container.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/Range/range-insertNode-same-container.html	2013-11-21 13:52:09 UTC (rev 159620)
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<div id="rootDiv">
+<div id="div1">1</div><div id="div2">2</div><div id="div3">3-begin <div id="div4">4</div><div id="div5">5</div> 3-end</div><div id="div6">6</div><div id="div7">7</div>
+<div id="description">Test various cases of Range.insertNode with nodes in the same container as the Range.</div>
+</div>
+<script>
+var range = document.createRange();
+
+var containerElement = document.getElementById("rootDiv");
+
+evalAndLog('insertedElement = document.getElementById("div1");');
+evalAndLog('range.setStart(containerElement, 3); range.setEnd(containerElement, 3); range.insertNode(insertedElement);');
+shouldBe('range.startContainer', 'containerElement');
+shouldBe('range.endContainer', 'containerElement');
+shouldBe('range.startOffset', '2');
+shouldBe('range.endOffset', '3');
+shouldBe('range.toString()', '"1"');
+
+evalAndLog('range.setStart(containerElement, 3); range.setEnd(containerElement, 3); range.insertNode(insertedElement);');
+shouldBe('range.startContainer', 'containerElement');
+shouldBe('range.endContainer', 'containerElement');
+shouldBe('range.startOffset', '2');
+shouldBe('range.endOffset', '3');
+shouldBe('range.toString()', '"1"');
+
+evalAndLog('insertedElement = document.getElementById("div3");');
+evalAndLog('range.setStart(containerElement, 5); range.setEnd(containerElement, 5); range.insertNode(insertedElement);');
+shouldBe('range.startContainer', 'containerElement');
+shouldBe('range.endContainer', 'containerElement');
+shouldBe('range.startOffset', '4');
+shouldBe('range.endOffset', '5');
+shouldBe('range.toString()', '"3-begin 45 3-end"');
+
+evalAndLog('range.setStart(containerElement, 5); range.setEnd(containerElement, 5); range.insertNode(insertedElement);');
+shouldBe('range.startContainer', 'containerElement');
+shouldBe('range.endContainer', 'containerElement');
+shouldBe('range.startOffset', '4');
+shouldBe('range.endOffset', '5');
+shouldBe('range.toString()', '"3-begin 45 3-end"');
+
+evalAndLog('insertedElement = document.getElementById("div6");');
+evalAndLog('range.setStart(containerElement, 1); range.setEnd(containerElement, 1); range.insertNode(insertedElement);');
+shouldBe('range.startContainer', 'containerElement');
+shouldBe('range.endContainer', 'containerElement');
+shouldBe('range.startOffset', '1');
+shouldBe('range.endOffset', '2');
+shouldBe('range.toString()', '"6"');
+
+evalAndLog('insertedElement = document.getElementById("div3");');
+evalAndLog('range.setStart(containerElement, 4); range.setEnd(containerElement, 4); range.insertNode(insertedElement);');
+shouldBe('range.startContainer', 'containerElement');
+shouldBe('range.endContainer', 'containerElement');
+shouldBe('range.startOffset', '4');
+shouldBe('range.endOffset', '5');
+shouldBe('range.toString()', '"3-begin 45 3-end"');
+
+shouldBe('documentFragment = range.extractContents(); range.startContainer', 'containerElement');
+shouldBe('range.startOffset', '4');
+shouldBe('range.endContainer', 'containerElement');
+shouldBe('range.endOffset', '4');
+shouldBe('range.insertNode(documentFragment); range.toString()', '"3-begin 45 3-end"');
+
+containerElement.style.display = 'none';
+
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (159619 => 159620)


--- trunk/Source/WebCore/ChangeLog	2013-11-21 13:46:39 UTC (rev 159619)
+++ trunk/Source/WebCore/ChangeLog	2013-11-21 13:52:09 UTC (rev 159620)
@@ -1,5 +1,25 @@
 2013-11-21  Ryosuke Niwa  <[email protected]>
 
+        Fix Range.insertNode when the inserted node is in the same container as the Range
+        https://bugs.webkit.org/show_bug.cgi?id=123957
+
+        Reviewed by Antti Koivisto.
+
+        Inspired by https://chromium.googlesource.com/chromium/blink/+/fb6ca1f488703e8d4f20ce6449cc8ea210be6edb
+
+        When a node from the same container is inserted, we can't simply adjust m_end with the offset.
+        Compute m_start and m_end from the inserted nodes instead.
+
+        Also, don't adjust m_start and m_end to nodes outside of the document if the inserted nodes had been
+        removed by mutation events.
+
+        Test: fast/dom/Range/range-insertNode-same-container.html
+
+        * dom/Range.cpp:
+        (WebCore::Range::insertNode):
+
+2013-11-21  Ryosuke Niwa  <[email protected]>
+
         nextBoundary and previousBoundary are very slow when there is a password field
         https://bugs.webkit.org/show_bug.cgi?id=123973
 

Modified: trunk/Source/WebCore/dom/Range.cpp (159619 => 159620)


--- trunk/Source/WebCore/dom/Range.cpp	2013-11-21 13:46:39 UTC (rev 159619)
+++ trunk/Source/WebCore/dom/Range.cpp	2013-11-21 13:52:09 UTC (rev 159620)
@@ -1034,20 +1034,23 @@
         if (ec)
             return;
 
-        if (collapsed)
+        if (collapsed && newText->parentNode() == container && &container->document() == &ownerDocument())
             m_end.setToBeforeChild(newText.get());
     } else {
-        RefPtr<Node> lastChild;
-        if (collapsed)
-            lastChild = (newNodeType == Node::DOCUMENT_FRAGMENT_NODE) ? newNode->lastChild() : newNode;
-
         container = m_start.container();
-        container->insertBefore(newNode.release(), container->childNode(m_start.offset()), ec);
+        RefPtr<Node> firstInsertedChild = newNodeType == Node::DOCUMENT_FRAGMENT_NODE ? newNode->firstChild() : newNode;
+        RefPtr<Node> lastInsertedChild = newNodeType == Node::DOCUMENT_FRAGMENT_NODE ? newNode->lastChild() : newNode;
+        RefPtr<Node> childAfterInsertedContent = container->childNode(m_start.offset());
+        container->insertBefore(newNode.release(), childAfterInsertedContent.get(), ec);
         if (ec)
             return;
 
-        if (collapsed && numNewChildren)
-            m_end.set(m_start.container(), m_start.offset() + numNewChildren, lastChild.get());
+        if (collapsed && numNewChildren && &container->document() == &ownerDocument()) {
+            if (firstInsertedChild->parentNode() == container)
+                m_start.setToBeforeChild(firstInsertedChild.get());
+            if (lastInsertedChild->parentNode() == container)
+                m_end.set(container, lastInsertedChild->nodeIndex() + 1, lastInsertedChild.get());
+        }
     }
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to