Don't create renderers for children of shadow host
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 19 Sep 2015 02:31:01 +0000 (02:31 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 19 Sep 2015 02:31:01 +0000 (02:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149363

Reviewed by Ryosuke Niwa.

Source/WebCore:

Test: fast/shadow-dom/css-scoping-shadow-root-hides-children.html

* dom/ShadowRoot.h:
* style/StyleResolveTree.cpp:
(WebCore::Style::attachRenderTree):
(WebCore::Style::resolveShadowTree):
(WebCore::Style::resolveChildren):
(WebCore::Style::resolveTree):

LayoutTests:

* fast/shadow-dom/css-scoping-shadow-root-hides-children-expected.html: Added.
* fast/shadow-dom/css-scoping-shadow-root-hides-children.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/shadow-dom/css-scoping-shadow-root-hides-children-expected.html [new file with mode: 0644]
LayoutTests/fast/shadow-dom/css-scoping-shadow-root-hides-children.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/dom/ShadowRoot.h
Source/WebCore/style/StyleResolveTree.cpp

index d12db95..0f4e8c9 100644 (file)
@@ -1,3 +1,13 @@
+2015-09-18  Antti Koivisto  <antti@apple.com>
+
+        Don't create renderers for children of shadow host
+        https://bugs.webkit.org/show_bug.cgi?id=149363
+
+        Reviewed by Ryosuke Niwa.
+
+        * fast/shadow-dom/css-scoping-shadow-root-hides-children-expected.html: Added.
+        * fast/shadow-dom/css-scoping-shadow-root-hides-children.html: Added.
+
 2015-09-18  Jake Nielsen  <jacob_nielsen@apple.com>
 
         Adds more flaky tests to TestExpecations for iOS and WK2
diff --git a/LayoutTests/fast/shadow-dom/css-scoping-shadow-root-hides-children-expected.html b/LayoutTests/fast/shadow-dom/css-scoping-shadow-root-hides-children-expected.html
new file mode 100644 (file)
index 0000000..e704d24
--- /dev/null
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<html>
+<body>
+    <p>Test passes if you see a single 100px by 100px green box below.</p>
+    <div style="width: 100px; height: 100px; background: green;"></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/shadow-dom/css-scoping-shadow-root-hides-children.html b/LayoutTests/fast/shadow-dom/css-scoping-shadow-root-hides-children.html
new file mode 100644 (file)
index 0000000..d584b65
--- /dev/null
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>CSS Scoping - a shadow tree hides non-distributed children of the host</title>
+    <link rel="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org"/>
+    <link rel="help" href="http://www.w3.org/TR/css-scoping-1/#selectors-data-model">
+    <link rel="match" href="reference/green-box.html"/>
+</head>
+<body>
+    <style>
+    my-host {
+        display: block;
+        width: 100px;
+        height: 100px;
+    }
+    div {
+        width: 100%; height: 100%; background: red;
+    }
+    </style>
+    <p>Test passes if you see a single 100px by 100px green box below.</p> 
+    <my-host>
+        <div>FAIL</div>
+    </my-host>
+    <script>
+
+    try {
+        var shadowHost = document.querySelector('my-host');
+        shadowRoot = shadowHost.attachShadow({mode: 'open'});
+        shadowRoot.innerHTML = '<div style="width: 100px; height: 100px; background: green; color:green">FAIL</div>';
+    } catch (exception) {
+        document.body.appendChild(document.createTextNode(exception));
+    }
+
+    </script>
+</body>
+</html>
index 51d4a35..28321ed 100644 (file)
@@ -1,3 +1,19 @@
+2015-09-18  Antti Koivisto  <antti@apple.com>
+
+        Don't create renderers for children of shadow host
+        https://bugs.webkit.org/show_bug.cgi?id=149363
+
+        Reviewed by Ryosuke Niwa.
+
+        Test: fast/shadow-dom/css-scoping-shadow-root-hides-children.html
+
+        * dom/ShadowRoot.h:
+        * style/StyleResolveTree.cpp:
+        (WebCore::Style::attachRenderTree):
+        (WebCore::Style::resolveShadowTree):
+        (WebCore::Style::resolveChildren):
+        (WebCore::Style::resolveTree):
+
 2015-09-08  Darin Adler  <darin@apple.com>
 
         Refine and simplify some color-related code
index 12b1a36..b5a2da9 100644 (file)
@@ -98,7 +98,7 @@ private:
 
     virtual Ref<Node> cloneNodeInternal(Document&, CloningOperation) override;
 
-    bool m_resetStyleInheritance : 1;
+    bool m_resetStyleInheritance;
     Type m_type;
 
     std::unique_ptr<StyleResolver> m_styleResolver;
index 31d2b9b..09a3856 100644 (file)
@@ -491,13 +491,16 @@ static void attachRenderTree(Element& current, RenderStyle& inheritedStyle, Rend
         RenderTreePosition childRenderTreePosition(*renderer);
         attachBeforeOrAfterPseudoElementIfNeeded(current, BEFORE, childRenderTreePosition);
 
-        if (ShadowRoot* shadowRoot = current.shadowRoot()) {
+        auto* shadowRoot = current.shadowRoot();
+        if (shadowRoot) {
             parentPusher.push();
             attachShadowRoot(*shadowRoot);
         } else if (current.firstChild())
             parentPusher.push();
 
-        attachChildren(current, renderer->style(), childRenderTreePosition);
+        bool skipChildren = shadowRoot && shadowRoot->type() != ShadowRoot::Type::UserAgent;
+        if (!skipChildren)
+            attachChildren(current, renderer->style(), childRenderTreePosition);
 
         if (AXObjectCache* cache = current.document().axObjectCache())
             cache->updateCacheAfterNodeIsAttached(&current);
@@ -676,6 +679,8 @@ void resolveTextNode(Text& text, RenderTreePosition& renderTreePosition)
 
 static void resolveShadowTree(ShadowRoot& shadowRoot, Element& host, Style::Change change)
 {
+    StyleResolverParentPusher parentPusher(&host);
+
     ASSERT(shadowRoot.host() == &host);
     ASSERT(host.renderer());
     RenderTreePosition renderTreePosition(*host.renderer());
@@ -686,8 +691,10 @@ static void resolveShadowTree(ShadowRoot& shadowRoot, Element& host, Style::Chan
             resolveTextNode(downcast<Text>(*child), renderTreePosition);
             continue;
         }
-        if (is<Element>(*child))
+        if (is<Element>(*child)) {
+            parentPusher.push();
             resolveTree(downcast<Element>(*child), host.renderer()->style(), renderTreePosition, change);
+        }
     }
 
     shadowRoot.clearNeedsStyleRecalc();
@@ -762,6 +769,35 @@ private:
 };
 #endif // PLATFORM(IOS)
 
+static void resolveChildren(Element& current, RenderStyle& inheritedStyle, Change change, RenderTreePosition& childRenderTreePosition)
+{
+    StyleResolverParentPusher parentPusher(&current);
+
+    bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false;
+    for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
+        if (RenderObject* childRenderer = child->renderer())
+            childRenderTreePosition.invalidateNextSibling(*childRenderer);
+        if (is<Text>(*child) && child->needsStyleRecalc()) {
+            resolveTextNode(downcast<Text>(*child), childRenderTreePosition);
+            continue;
+        }
+        if (!is<Element>(*child))
+            continue;
+
+        Element& childElement = downcast<Element>(*child);
+        if (elementNeedingStyleRecalcAffectsNextSiblingElementStyle) {
+            if (childElement.styleIsAffectedByPreviousSibling())
+                childElement.setNeedsStyleRecalc();
+            elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement.affectsNextSiblingElementStyle();
+        } else if (childElement.needsStyleRecalc())
+            elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement.affectsNextSiblingElementStyle();
+        if (change >= Inherit || childElement.childNeedsStyleRecalc() || childElement.needsStyleRecalc()) {
+            parentPusher.push();
+            resolveTree(childElement, inheritedStyle, childRenderTreePosition, change);
+        }
+    }
+}
+
 void resolveTree(Element& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, Change change)
 {
     ASSERT(change != Detach);
@@ -790,41 +826,16 @@ void resolveTree(Element& current, RenderStyle& inheritedStyle, RenderTreePositi
     auto* renderer = current.renderer();
 
     if (change != Detach && renderer) {
-        StyleResolverParentPusher parentPusher(&current);
-
-        if (ShadowRoot* shadowRoot = current.shadowRoot()) {
-            if (change >= Inherit || shadowRoot->childNeedsStyleRecalc() || shadowRoot->needsStyleRecalc()) {
-                parentPusher.push();
-                resolveShadowTree(*shadowRoot, current, change);
-            }
-        }
+        auto* shadowRoot = current.shadowRoot();
+        if (shadowRoot && (change >= Inherit || shadowRoot->childNeedsStyleRecalc() || shadowRoot->needsStyleRecalc()))
+            resolveShadowTree(*shadowRoot, current, change);
 
         RenderTreePosition childRenderTreePosition(*renderer);
         updateBeforeOrAfterPseudoElement(current, change, BEFORE, childRenderTreePosition);
 
-        bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false;
-        for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
-            if (RenderObject* childRenderer = child->renderer())
-                childRenderTreePosition.invalidateNextSibling(*childRenderer);
-            if (is<Text>(*child) && child->needsStyleRecalc()) {
-                resolveTextNode(downcast<Text>(*child), childRenderTreePosition);
-                continue;
-            }
-            if (!is<Element>(*child))
-                continue;
-
-            Element& childElement = downcast<Element>(*child);
-            if (elementNeedingStyleRecalcAffectsNextSiblingElementStyle) {
-                if (childElement.styleIsAffectedByPreviousSibling())
-                    childElement.setNeedsStyleRecalc();
-                elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement.affectsNextSiblingElementStyle();
-            } else if (childElement.needsStyleRecalc())
-                elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement.affectsNextSiblingElementStyle();
-            if (change >= Inherit || childElement.childNeedsStyleRecalc() || childElement.needsStyleRecalc()) {
-                parentPusher.push();
-                resolveTree(childElement, renderer->style(), childRenderTreePosition, change);
-            }
-        }
+        bool skipChildren = shadowRoot && shadowRoot->type() != ShadowRoot::Type::UserAgent;
+        if (!skipChildren)
+            resolveChildren(current, renderer->style(), change, childRenderTreePosition);
 
         updateBeforeOrAfterPseudoElement(current, change, AFTER, childRenderTreePosition);
     }