Title: [206403] trunk
Revision
206403
Author
an...@apple.com
Date
2016-09-26 16:45:21 -0700 (Mon, 26 Sep 2016)

Log Message

Input elements don't work inside shadow tree
https://bugs.webkit.org/show_bug.cgi?id=160427

Reviewed by Darin Adler.

Source/WebCore:

There is a bug in ComposedTreeIterator. If the iterator is initialized with an initial state where the root
is inside a shadow tree it won't iterate into slots.

If an input element is in a shadow tree it generates narrowly scoped style updates. When RenderTreeUpdater
applies such an update the update root will be inside the shadow tree and the bug will prevent the render tree
for slotted content from updating.

Added tests for both the iterator behavior and the specific symptom with input elements.

Tests: fast/shadow-dom/composed-tree-shadow-child-subtree.html
       fast/shadow-dom/input-element-in-shadow.html

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

    Check and cache if the root is inside shadow tree.

(WebCore::ComposedTreeIterator::traverseNextInShadowTree):
* dom/ComposedTreeIterator.h:
(WebCore::ComposedTreeIterator::traverseNext):

    If it is, always use the shadow traversal code path.

LayoutTests:

* fast/shadow-dom/composed-tree-shadow-child-subtree-expected.txt: Added.
* fast/shadow-dom/composed-tree-shadow-child-subtree.html: Added.
* fast/shadow-dom/input-element-in-shadow-expected.html: Added.
* fast/shadow-dom/input-element-in-shadow.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (206402 => 206403)


--- trunk/LayoutTests/ChangeLog	2016-09-26 23:40:06 UTC (rev 206402)
+++ trunk/LayoutTests/ChangeLog	2016-09-26 23:45:21 UTC (rev 206403)
@@ -1,3 +1,15 @@
+2016-09-26  Antti Koivisto  <an...@apple.com>
+
+        Input elements don't work inside shadow tree
+        https://bugs.webkit.org/show_bug.cgi?id=160427
+
+        Reviewed by Darin Adler.
+
+        * fast/shadow-dom/composed-tree-shadow-child-subtree-expected.txt: Added.
+        * fast/shadow-dom/composed-tree-shadow-child-subtree.html: Added.
+        * fast/shadow-dom/input-element-in-shadow-expected.html: Added.
+        * fast/shadow-dom/input-element-in-shadow.html: Added.
+
 2016-09-26  Ryan Haddad  <ryanhad...@apple.com>
 
         Marking media/media-document-audio-repaint.html as flaky on Sierra.

Added: trunk/LayoutTests/fast/shadow-dom/composed-tree-shadow-child-subtree-expected.txt (0 => 206403)


--- trunk/LayoutTests/fast/shadow-dom/composed-tree-shadow-child-subtree-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/composed-tree-shadow-child-subtree-expected.txt	2016-09-26 23:45:21 UTC (rev 206403)
@@ -0,0 +1,93 @@
+
+Test 1.1
+  div (shadow root)
+    div
+      slot
+        #text
+
+Shadow child 0 subtree
+  slot
+    #text
+
+Test 1.2
+  div (shadow root)
+    div
+      slot
+        div
+          #text
+
+Shadow child 0 subtree
+  slot
+    div
+      #text
+
+Test 2.1
+  div (shadow root)
+    div
+      #text
+    div
+      slot
+        #text
+
+Shadow child 0 subtree
+  #text
+
+Shadow child 1 subtree
+  slot
+    #text
+
+Test 2.2
+  div (shadow root)
+    div
+      #text
+    div
+      slot
+        div
+          #text
+
+Shadow child 0 subtree
+  #text
+
+Shadow child 1 subtree
+  slot
+    div
+      #text
+
+Test 3.1
+  div (shadow root)
+    div
+      #text
+      div (shadow root)
+        div
+          slot
+            slot
+              #text
+
+Shadow child 0 subtree
+  #text
+  div (shadow root)
+    div
+      slot
+        slot
+          #text
+
+Test 3.2
+  div (shadow root)
+    div
+      #text
+      div (shadow root)
+        div
+          slot
+            slot
+              div
+                #text
+
+Shadow child 0 subtree
+  #text
+  div (shadow root)
+    div
+      slot
+        slot
+          div
+            #text
+

Added: trunk/LayoutTests/fast/shadow-dom/composed-tree-shadow-child-subtree.html (0 => 206403)


--- trunk/LayoutTests/fast/shadow-dom/composed-tree-shadow-child-subtree.html	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/composed-tree-shadow-child-subtree.html	2016-09-26 23:45:21 UTC (rev 206403)
@@ -0,0 +1,57 @@
+<html>
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+</script>
+
+<template id=shadow1><div><slot></slot></div></template>
+<template id=shadow2><div>text</div><div><slot></slot></div></template>
+<template id=shadow3><div>text<div shadow=shadow1><slot></slot></div></div></template>
+
+
+<template test=1.1><div shadow=shadow1>text</div></template>
+<template test=1.2><div shadow=shadow1><div>text</div></div></template>
+
+<template test=2.1><div shadow=shadow2>text</div></template>
+<template test=2.2><div shadow=shadow2><div>text</div></div></template>
+
+<template test=3.1><div shadow=shadow3>text</div></template>
+<template test=3.2><div shadow=shadow3><div>text</div></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);
+
+    var shadowSubtree = test.querySelector("[shadow]");
+
+    var children = shadowSubtree.shadowRoot.children;
+    for (var j = 0; j < children.length; ++j) {
+        console.innerText += "\nShadow child " + j + " subtree\n"
+        console.innerText += internals.composedTreeAsText(children[j]);
+    }
+}
+
+</script>
+</body>

Added: trunk/LayoutTests/fast/shadow-dom/input-element-in-shadow-expected.html (0 => 206403)


--- trunk/LayoutTests/fast/shadow-dom/input-element-in-shadow-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/input-element-in-shadow-expected.html	2016-09-26 23:45:21 UTC (rev 206403)
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+Test that input elements in shadow trees update when text is entered.
+<div>
+<input value="abc"><br>
+<textarea>def</textarea>
+</div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/shadow-dom/input-element-in-shadow.html (0 => 206403)


--- trunk/LayoutTests/fast/shadow-dom/input-element-in-shadow.html	                        (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/input-element-in-shadow.html	2016-09-26 23:45:21 UTC (rev 206403)
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+</head>
+<body>
+Test that input elements in shadow trees update when text is entered.
+<div id="parentDiv">
+<input placeholder="distributed"><br>
+<textarea></textarea>
+</div>
+</body>
+<script>
+parentDiv.attachShadow({mode: 'open'});
+var innerDiv = document.createElement('div');
+innerDiv.appendChild(document.createElement('slot'))
+parentDiv.shadowRoot.appendChild(innerDiv);
+
+function enterText(selector, characters)
+{
+    if (window.eventSender) {
+        var input = document.querySelector(selector);
+        input.focus();
+        for (c of characters)
+            window.eventSender.keyDown(c);
+        input.blur();
+    }
+}
+
+enterText("input", "abc");
+enterText("textarea", "def");
+
+</script>
+</html>

Modified: trunk/LayoutTests/platform/ios-simulator/TestExpectations (206402 => 206403)


--- trunk/LayoutTests/platform/ios-simulator/TestExpectations	2016-09-26 23:40:06 UTC (rev 206402)
+++ trunk/LayoutTests/platform/ios-simulator/TestExpectations	2016-09-26 23:45:21 UTC (rev 206403)
@@ -332,6 +332,7 @@
 # This test relies on EventSender.keydown(), which is not supported on iOS
 webkit.org/b/155233 fast/events/max-tabindex-focus.html [ Skip ]
 fast/shadow-dom/shadow-host-removal-crash.html [ Skip ]
+fast/shadow-dom/input-element-in-shadow.html [ Skip ]
 
 # The file-wrapper part of <attachment> is not yet working on iOS
 fast/attachment/attachment-type-attribute.html [ Skip ]

Modified: trunk/Source/WebCore/ChangeLog (206402 => 206403)


--- trunk/Source/WebCore/ChangeLog	2016-09-26 23:40:06 UTC (rev 206402)
+++ trunk/Source/WebCore/ChangeLog	2016-09-26 23:45:21 UTC (rev 206403)
@@ -1,3 +1,33 @@
+2016-09-26  Antti Koivisto  <an...@apple.com>
+
+        Input elements don't work inside shadow tree
+        https://bugs.webkit.org/show_bug.cgi?id=160427
+
+        Reviewed by Darin Adler.
+
+        There is a bug in ComposedTreeIterator. If the iterator is initialized with an initial state where the root
+        is inside a shadow tree it won't iterate into slots.
+
+        If an input element is in a shadow tree it generates narrowly scoped style updates. When RenderTreeUpdater
+        applies such an update the update root will be inside the shadow tree and the bug will prevent the render tree
+        for slotted content from updating.
+
+        Added tests for both the iterator behavior and the specific symptom with input elements.
+
+        Tests: fast/shadow-dom/composed-tree-shadow-child-subtree.html
+               fast/shadow-dom/input-element-in-shadow.html
+
+        * dom/ComposedTreeIterator.cpp:
+        (WebCore::ComposedTreeIterator::ComposedTreeIterator):
+
+            Check and cache if the root is inside shadow tree.
+
+        (WebCore::ComposedTreeIterator::traverseNextInShadowTree):
+        * dom/ComposedTreeIterator.h:
+        (WebCore::ComposedTreeIterator::traverseNext):
+
+            If it is, always use the shadow traversal code path.
+
 2016-09-26  Wenson Hsieh  <wenson_hs...@apple.com>
 
         Seeking video doesn't update seek position

Modified: trunk/Source/WebCore/dom/ComposedTreeIterator.cpp (206402 => 206403)


--- trunk/Source/WebCore/dom/ComposedTreeIterator.cpp	2016-09-26 23:40:06 UTC (rev 206402)
+++ trunk/Source/WebCore/dom/ComposedTreeIterator.cpp	2016-09-26 23:45:21 UTC (rev 206403)
@@ -53,6 +53,7 @@
 }
 
 ComposedTreeIterator::ComposedTreeIterator(ContainerNode& root, FirstChildTag)
+    : m_rootIsInShadowTree(root.isInShadowTree())
 {
     ASSERT(!is<ShadowRoot>(root));
 
@@ -73,6 +74,7 @@
 }
 
 ComposedTreeIterator::ComposedTreeIterator(ContainerNode& root, Node& current)
+    : m_rootIsInShadowTree(root.isInShadowTree())
 {
     ASSERT(!is<ShadowRoot>(root));
     ASSERT(!is<ShadowRoot>(current));
@@ -155,7 +157,7 @@
 
 void ComposedTreeIterator::traverseNextInShadowTree()
 {
-    ASSERT(m_contextStack.size() > 1);
+    ASSERT(m_contextStack.size() > 1 || m_rootIsInShadowTree);
 
     if (is<HTMLSlotElement>(current())) {
         auto& slot = downcast<HTMLSlotElement>(current());
@@ -175,8 +177,6 @@
 
 void ComposedTreeIterator::traverseNextLeavingContext()
 {
-    ASSERT(m_contextStack.size() > 1);
-
     while (context().iterator == context().end && m_contextStack.size() > 1) {
         m_contextStack.removeLast();
         if (context().iterator == context().end)

Modified: trunk/Source/WebCore/dom/ComposedTreeIterator.h (206402 => 206403)


--- trunk/Source/WebCore/dom/ComposedTreeIterator.h	2016-09-26 23:40:06 UTC (rev 206402)
+++ trunk/Source/WebCore/dom/ComposedTreeIterator.h	2016-09-26 23:45:21 UTC (rev 206403)
@@ -80,6 +80,7 @@
     const Context& context() const { return m_contextStack.last(); }
     Node& current() { return *context().iterator; }
 
+    bool m_rootIsInShadowTree { false };
     bool m_didDropAssertions { false };
     Vector<Context, 8> m_contextStack;
 };
@@ -96,7 +97,7 @@
         return *this;
     }
 
-    if (m_contextStack.size() > 1) {
+    if (m_contextStack.size() > 1 || m_rootIsInShadowTree) {
         traverseNextInShadowTree();
         return *this;
     }
@@ -109,7 +110,7 @@
 {
     context().iterator.traverseNextSkippingChildren();
 
-    if (context().iterator == context().end && m_contextStack.size() > 1)
+    if (context().iterator == context().end)
         traverseNextLeavingContext();
     
     return *this;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to