Title: [122689] trunk
Revision
122689
Author
[email protected]
Date
2012-07-15 19:26:03 -0700 (Sun, 15 Jul 2012)

Log Message

REGRESSION(r122660): Cannot iterate over HTMLCollection that contains non-child descendent nodes in some conditions
https://bugs.webkit.org/show_bug.cgi?id=91334

Reviewed by Ojan Vafai.

Source/WebCore: 

The bug was caused by using lastChild() as the starting node for traversePreviousNode. Since it's the inverse of
Node::traverseNextNode(), which visits nodes in pre order, we must start our search from the last descendent node,
which is visited traverseNextNode immediately before reaching the root node.

Test: fast/dom/htmlcollection-backwards-subtree-iteration.html

* html/HTMLCollection.cpp:
(WebCore::lastDescendent):
(WebCore):
(WebCore::itemBeforeOrAfter):

LayoutTests: 

Add a regression test. Without this patch, it results in an console error in release builds and an assertion failure
in debug builds.

* fast/dom/htmlcollection-backwards-subtree-iteration-expected.txt: Added.
* fast/dom/htmlcollection-backwards-subtree-iteration.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (122688 => 122689)


--- trunk/LayoutTests/ChangeLog	2012-07-16 02:25:51 UTC (rev 122688)
+++ trunk/LayoutTests/ChangeLog	2012-07-16 02:26:03 UTC (rev 122689)
@@ -1,3 +1,16 @@
+2012-07-15  Ryosuke Niwa  <[email protected]>
+
+        REGRESSION(r122660): Cannot iterate over HTMLCollection that contains non-child descendent nodes in some conditions
+        https://bugs.webkit.org/show_bug.cgi?id=91334
+
+        Reviewed by Ojan Vafai.
+
+        Add a regression test. Without this patch, it results in an console error in release builds and an assertion failure
+        in debug builds.
+
+        * fast/dom/htmlcollection-backwards-subtree-iteration-expected.txt: Added.
+        * fast/dom/htmlcollection-backwards-subtree-iteration.html: Added.
+
 2012-07-14  Ryosuke Niwa  <[email protected]>
 
         Use testRunner instead of layoutTestController in fast/js, layers, leaks, line-grid, lists, loader, loading, media, mediastream, multicol, and mutation tests

Added: trunk/LayoutTests/fast/dom/htmlcollection-backwards-subtree-iteration-expected.txt (0 => 122689)


--- trunk/LayoutTests/fast/dom/htmlcollection-backwards-subtree-iteration-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/htmlcollection-backwards-subtree-iteration-expected.txt	2012-07-16 02:26:03 UTC (rev 122689)
@@ -0,0 +1,4 @@
+Tests that HTMLCollection of a subtree (as opposed to direct children) can be iterated backwards.
+There should be no console error and WebKit should not hit an assertion.
+
+PASS

Added: trunk/LayoutTests/fast/dom/htmlcollection-backwards-subtree-iteration.html (0 => 122689)


--- trunk/LayoutTests/fast/dom/htmlcollection-backwards-subtree-iteration.html	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/htmlcollection-backwards-subtree-iteration.html	2012-07-16 02:26:03 UTC (rev 122689)
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<body>
+<img id="1"><img id="2"><img id="3"><img id="4">
+<script>
+
+var errors = '';
+var images = document.images;
+for (var i = images.length; i > 0; i--) {
+    images[0].class = 'foo';
+    if (parseInt(images[i - 1].id) != i)
+        errors += 'FAIL - Expected ' + i + ' but got ' + images[i - 1].id + '<br>';
+    images[i - 1].class = 'foo';
+}
+
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+document.body.innerHTML = 'Tests that HTMLCollection of a subtree (as opposed to direct children) can be iterated backwards.<br>'
++ 'There should be no console error and WebKit should not hit an assertion.<br><br>' + (errors ? errors : 'PASS');
+
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (122688 => 122689)


--- trunk/Source/WebCore/ChangeLog	2012-07-16 02:25:51 UTC (rev 122688)
+++ trunk/Source/WebCore/ChangeLog	2012-07-16 02:26:03 UTC (rev 122689)
@@ -1,3 +1,21 @@
+2012-07-15  Ryosuke Niwa  <[email protected]>
+
+        REGRESSION(r122660): Cannot iterate over HTMLCollection that contains non-child descendent nodes in some conditions
+        https://bugs.webkit.org/show_bug.cgi?id=91334
+
+        Reviewed by Ojan Vafai.
+
+        The bug was caused by using lastChild() as the starting node for traversePreviousNode. Since it's the inverse of
+        Node::traverseNextNode(), which visits nodes in pre order, we must start our search from the last descendent node,
+        which is visited traverseNextNode immediately before reaching the root node.
+
+        Test: fast/dom/htmlcollection-backwards-subtree-iteration.html
+
+        * html/HTMLCollection.cpp:
+        (WebCore::lastDescendent):
+        (WebCore):
+        (WebCore::itemBeforeOrAfter):
+
 2012-07-15  Joseph Pecoraro  <[email protected]>
 
         Windowless WebView not firing _javascript_ load event if there is a media element

Modified: trunk/Source/WebCore/html/HTMLCollection.cpp (122688 => 122689)


--- trunk/Source/WebCore/html/HTMLCollection.cpp	2012-07-16 02:25:51 UTC (rev 122688)
+++ trunk/Source/WebCore/html/HTMLCollection.cpp	2012-07-16 02:26:03 UTC (rev 122689)
@@ -246,13 +246,29 @@
         return onlyIncludeDirectChildren ? previous->previousSibling() : previous->traversePreviousNode(base);
 }
 
+static inline Node* lastDescendent(Node* node)
+{
+    node = node->lastChild();
+    for (Node* current = node; current; current = current->lastChild())
+        node = current;
+    return node;
+}
+
 template<bool forward>
 static Element* itemBeforeOrAfter(CollectionType type, Node* base, unsigned& offsetInArray, Node* previous)
 {
     ASSERT_UNUSED(offsetInArray, !offsetInArray);
     bool _onlyIncludeDirectChildren_ = shouldOnlyIncludeDirectChildren(type);
     Node* rootNode = base;
-    Node* current = previous ? nextNode<forward>(rootNode, previous, onlyIncludeDirectChildren) : (forward ? base->firstChild() : base->lastChild());
+    Node* current;
+    if (previous)
+        current = nextNode<forward>(rootNode, previous, onlyIncludeDirectChildren);
+    else {
+        if (forward)
+            current = rootNode->firstChild();
+        else
+            current = onlyIncludeDirectChildren ? rootNode->lastChild() : lastDescendent(rootNode);
+    }
 
     for (; current; current = nextNode<forward>(rootNode, current, onlyIncludeDirectChildren)) {
         if (current->isElementNode() && isAcceptableElement(type, toElement(current)))
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to