ComposedTreeIterator fails to traverse slots if root is shadow host
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Mar 2016 22:54:12 +0000 (22:54 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 13 Mar 2016 22:54:12 +0000 (22:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=155407

Reviewed by Darin Adler.

Source/WebCore:

Test: fast/shadow-dom/composed-tree-shadow-subtree.html

* dom/ComposedTreeIterator.cpp:
(WebCore::ComposedTreeIterator::ComposedTreeIterator):

    Traversal functions assume m_contextStack is deeper than 1 before they need to enter slot traversal code paths.
    Call initializeContextStack in case of shadow host which does the right thing.

(WebCore::ComposedTreeIterator::traverseSiblingInSlot):
(WebCore::composedTreeAsText):

    Add option to include pointers as debugging aid.

* dom/ComposedTreeIterator.h:
(WebCore::composedTreeChildren):

LayoutTests:

* fast/shadow-dom/composed-tree-shadow-subtree-expected.txt: Added.
* fast/shadow-dom/composed-tree-shadow-subtree.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/shadow-dom/composed-tree-shadow-subtree-expected.txt [new file with mode: 0644]
LayoutTests/fast/shadow-dom/composed-tree-shadow-subtree.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/ComposedTreeIterator.cpp
Source/WebCore/dom/ComposedTreeIterator.h

index f368d0f..0886e48 100644 (file)
@@ -1,3 +1,13 @@
+2016-03-13  Antti Koivisto  <antti@apple.com>
+
+        ComposedTreeIterator fails to traverse slots if root is shadow host
+        https://bugs.webkit.org/show_bug.cgi?id=155407
+
+        Reviewed by Darin Adler.
+
+        * fast/shadow-dom/composed-tree-shadow-subtree-expected.txt: Added.
+        * fast/shadow-dom/composed-tree-shadow-subtree.html: Added.
+
 2016-03-12  Dean Jackson  <dino@apple.com>
 
         REGRESSION (r188647): Teamtreehouse website sidebar buttons are not rendered
diff --git a/LayoutTests/fast/shadow-dom/composed-tree-shadow-subtree-expected.txt b/LayoutTests/fast/shadow-dom/composed-tree-shadow-subtree-expected.txt
new file mode 100644 (file)
index 0000000..e3994d0
--- /dev/null
@@ -0,0 +1,35 @@
+
+Test 1
+  div (shadow root)
+
+Shadow host subtree
+
+Test 2
+  div (shadow root)
+
+Shadow host subtree
+
+Test 3
+  div (shadow root)
+    slot
+      div
+
+Shadow host subtree
+  slot
+    div
+
+Slot subtree
+  div
+
+Test 4
+  div (shadow root)
+    slot
+      #text
+
+Shadow host subtree
+  slot
+    #text
+
+Slot subtree
+  #text
+
diff --git a/LayoutTests/fast/shadow-dom/composed-tree-shadow-subtree.html b/LayoutTests/fast/shadow-dom/composed-tree-shadow-subtree.html
new file mode 100644 (file)
index 0000000..751a380
--- /dev/null
@@ -0,0 +1,53 @@
+<html>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+</script>
+
+<template id=shadow1></template>
+<template id=shadow2><slot><div></div></slot></template>
+
+<template test=1><div shadow=shadow1></div></template>
+<template test=2><div shadow=shadow1>text</div></template>
+<template test=3><div shadow=shadow2></div></template>
+<template test=4><div shadow=shadow2>text</div></template>
+
+<body>
+<pre id=console></pre>
+<script>
+function installShadows(tree)
+{
+    var shadowHosts = tree.querySelectorAll("[shadow]");
+    for (var i = 0; i < shadowHosts.length; ++i) {
+        var shadowId = shadowHosts[i].getAttribute("shadow");
+        var shadowContents = document.querySelector("#"+shadowId).content.cloneNode(true);
+
+        installShadows(shadowContents);
+
+        var shadowRoot = shadowHosts[i].attachShadow({ mode: "open" });
+        shadowRoot.appendChild(shadowContents);
+    }
+}
+
+var console = document.querySelector("#console");
+
+var tests = document.querySelectorAll("[test]");
+for (var i = 0; i < tests.length; ++i) {
+    var test = tests[i].content.cloneNode(true);
+    installShadows(test);
+    console.innerText += "\nTest " + tests[i].getAttribute("test") + "\n";
+    console.innerText += internals.composedTreeAsText(test);
+
+    console.innerText += "\nShadow host subtree\n"
+    var shadowSubtree = test.querySelector("[shadow]");
+    console.innerText += internals.composedTreeAsText(shadowSubtree);
+
+    var slotSubtree = shadowSubtree.shadowRoot.querySelector("slot");
+    if (slotSubtree) {
+        console.innerText += "\nSlot subtree\n"
+        console.innerText += internals.composedTreeAsText(slotSubtree);
+    }
+}
+
+</script>
+</body>
index 313d753..8ef6488 100644 (file)
@@ -1,3 +1,26 @@
+2016-03-13  Antti Koivisto  <antti@apple.com>
+
+        ComposedTreeIterator fails to traverse slots if root is shadow host
+        https://bugs.webkit.org/show_bug.cgi?id=155407
+
+        Reviewed by Darin Adler.
+
+        Test: fast/shadow-dom/composed-tree-shadow-subtree.html
+
+        * dom/ComposedTreeIterator.cpp:
+        (WebCore::ComposedTreeIterator::ComposedTreeIterator):
+
+            Traversal functions assume m_contextStack is deeper than 1 before they need to enter slot traversal code paths.
+            Call initializeContextStack in case of shadow host which does the right thing.
+
+        (WebCore::ComposedTreeIterator::traverseSiblingInSlot):
+        (WebCore::composedTreeAsText):
+
+            Add option to include pointers as debugging aid.
+
+        * dom/ComposedTreeIterator.h:
+        (WebCore::composedTreeChildren):
+
 2016-03-12  Sam Weinig  <sam@webkit.org>
 
         WebKit can easily crash below NetworkSession::dataTaskForIdentifier() with NSURLSession enabled
index 7f5d75d..f05c91a 100644 (file)
@@ -67,8 +67,13 @@ ComposedTreeIterator::ComposedTreeIterator(ContainerNode& root)
         }
     }
 #endif
-    auto& effectiveRoot = root.shadowRoot() ? *root.shadowRoot() : root;
-    m_contextStack.uncheckedAppend(Context(effectiveRoot));
+    if (auto* shadowRoot = root.shadowRoot()) {
+        auto* firstChild = shadowRoot->firstChild();
+        initializeContextStack(root, firstChild ? *firstChild : root);
+        return;
+    }
+
+    m_contextStack.uncheckedAppend(Context(root));
 }
 
 ComposedTreeIterator::ComposedTreeIterator(ContainerNode& root, Node& current)
@@ -222,7 +227,7 @@ void ComposedTreeIterator::traverseSiblingInSlot(int direction)
 }
 #endif
 
-String composedTreeAsText(ContainerNode& root)
+String composedTreeAsText(ContainerNode& root, ComposedTreeAsTextMode mode)
 {
     TextStream stream;
     auto descendants = composedTreeDescendants(root);
@@ -230,13 +235,18 @@ String composedTreeAsText(ContainerNode& root)
         writeIndent(stream, it.depth());
 
         if (is<Text>(*it)) {
-            stream << "#text\n";
+            stream << "#text";
+            if (mode == ComposedTreeAsTextMode::WithPointers)
+                stream << " " << &*it;
+            stream << "\n";
             continue;
         }
         auto& element = downcast<Element>(*it);
         stream << element.localName();
         if (element.shadowRoot())
             stream << " (shadow root)";
+        if (mode == ComposedTreeAsTextMode::WithPointers)
+            stream << " " << &*it;
         stream << "\n";
     }
     return stream.release();
index 566cf55..36ffb59 100644 (file)
@@ -203,7 +203,8 @@ inline ComposedTreeChildAdapter composedTreeChildren(ContainerNode& parent)
     return ComposedTreeChildAdapter(parent);
 }
 
-WEBCORE_EXPORT String composedTreeAsText(ContainerNode& root);
+enum class ComposedTreeAsTextMode { Normal, WithPointers };
+WEBCORE_EXPORT String composedTreeAsText(ContainerNode& root, ComposedTreeAsTextMode = ComposedTreeAsTextMode::Normal);
 
 }