- 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;