HTMLSlotElement should render its assigned nodes
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 21 Sep 2015 22:27:28 +0000 (22:27 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 21 Sep 2015 22:27:28 +0000 (22:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149242

Reviewed by Ryosuke Niwa.

Source/WebCore:

Support rendering the assigned nodes under HTMLSlotElement.

* dom/SlotAssignment.cpp:
(WebCore::SlotAssignment::assignSlots):

    Move the empty slot finding to the loop as the hash table may mutate.

* html/HTMLSlotElement.cpp:
(WebCore::HTMLSlotElement::attributeChanged):
(WebCore::HTMLSlotElement::assignedNodes):
(WebCore::HTMLSlotElement::getDistributedNodes):
* html/HTMLSlotElement.h:
* style/StyleResolveTree.cpp:
(WebCore::Style::attachBeforeOrAfterPseudoElementIfNeeded):
(WebCore::Style::attachSlot):
(WebCore::Style::attachRenderTree):
(WebCore::Style::detachChildren):
(WebCore::Style::detachShadowRoot):
(WebCore::Style::detachSlot):
(WebCore::Style::detachRenderTree):
(WebCore::Style::resolveChildren):
(WebCore::Style::resolveSlot):
(WebCore::Style::resolveTree):

LayoutTests:

Enable the relevant tests.

* platform/mac/TestExpectations:

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

LayoutTests/ChangeLog
LayoutTests/platform/mac/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/dom/SlotAssignment.cpp
Source/WebCore/html/HTMLSlotElement.cpp
Source/WebCore/html/HTMLSlotElement.h
Source/WebCore/style/StyleResolveTree.cpp

index 33935cf..8a01a3e 100644 (file)
@@ -1,3 +1,14 @@
+2015-09-21  Antti Koivisto  <antti@apple.com>
+
+        HTMLSlotElement should render its assigned nodes
+        https://bugs.webkit.org/show_bug.cgi?id=149242
+
+        Reviewed by Ryosuke Niwa.
+
+        Enable the relevant tests.
+
+        * platform/mac/TestExpectations:
+
 2015-09-21  Alex Christensen  <achristensen@webkit.org>
 
         Remove Windows-specific navigator-detached-no-crash-expected.
index 6a87fe9..a9076d2 100644 (file)
@@ -1303,6 +1303,4 @@ webkit.org/b/143258 [ Mavericks ] http/tests/cache/disk-cache/disk-cache-validat
 webkit.org/b/149128 fast/text/control-characters [ ImageOnlyFailure ]
 
 webkit.org/b/148695 fast/shadow-dom [ Pass ]
-webkit.org/b/149242 fast/shadow-dom/css-scoping-shadow-slot.html [ ImageOnlyFailure ]
-webkit.org/b/149242 fast/shadow-dom/css-scoping-shadow-invisible-slot.html [ ImageOnlyFailure ]
 webkit.org/b/149328 fast/shadow-dom/css-scoping-shadow-with-rules.html [ ImageOnlyFailure ]
index 5c59bd7..0f2455c 100644 (file)
@@ -1,3 +1,34 @@
+2015-09-21  Antti Koivisto  <antti@apple.com>
+
+        HTMLSlotElement should render its assigned nodes
+        https://bugs.webkit.org/show_bug.cgi?id=149242
+
+        Reviewed by Ryosuke Niwa.
+
+        Support rendering the assigned nodes under HTMLSlotElement.
+
+        * dom/SlotAssignment.cpp:
+        (WebCore::SlotAssignment::assignSlots):
+
+            Move the empty slot finding to the loop as the hash table may mutate.
+
+        * html/HTMLSlotElement.cpp:
+        (WebCore::HTMLSlotElement::attributeChanged):
+        (WebCore::HTMLSlotElement::assignedNodes):
+        (WebCore::HTMLSlotElement::getDistributedNodes):
+        * html/HTMLSlotElement.h:
+        * style/StyleResolveTree.cpp:
+        (WebCore::Style::attachBeforeOrAfterPseudoElementIfNeeded):
+        (WebCore::Style::attachSlot):
+        (WebCore::Style::attachRenderTree):
+        (WebCore::Style::detachChildren):
+        (WebCore::Style::detachShadowRoot):
+        (WebCore::Style::detachSlot):
+        (WebCore::Style::detachRenderTree):
+        (WebCore::Style::resolveChildren):
+        (WebCore::Style::resolveSlot):
+        (WebCore::Style::resolveTree):
+
 2015-09-21  Tim Horton  <timothy_horton@apple.com>
 
         svg/custom/hidpi-masking-clipping.svg fails with accelerated drawing on
index 90816d5..7a3fd35 100644 (file)
@@ -175,8 +175,6 @@ void SlotAssignment::assignSlots(ShadowRoot& shadowRoot)
     for (auto& entry : m_slots)
         entry.value->assignedNodes.shrink(0);
 
-    auto defaultSlotEntry = m_slots.find(emptyAtom);
-
     for (Node* child = host->firstChild(); child; child = child->nextSibling()) {
         if (is<Element>(child)) {
             auto& slotName = downcast<Element>(*child).fastGetAttribute(slotAttr);
@@ -186,6 +184,7 @@ void SlotAssignment::assignSlots(ShadowRoot& shadowRoot)
                 continue;
             }
         }
+        auto defaultSlotEntry = m_slots.find(emptyAtom);
         if (defaultSlotEntry != m_slots.end())
             defaultSlotEntry->value->assignedNodes.append(child);
     }
index abad7f4..720a34a 100644 (file)
@@ -85,15 +85,22 @@ void HTMLSlotElement::attributeChanged(const QualifiedName& name, const AtomicSt
     }
 }
 
+const Vector<Node*>* HTMLSlotElement::assignedNodes() const
+{
+    auto* shadowRoot = containingShadowRoot();
+    if (!shadowRoot)
+        return nullptr;
+
+    return shadowRoot->assignedNodesForSlot(*this);
+}
+
 Vector<RefPtr<Node>> HTMLSlotElement::getDistributedNodes() const
 {
     Vector<RefPtr<Node>> distributedNodes;
 
-    if (auto shadowRoot = containingShadowRoot()) {
-        if (auto assignedNodes = shadowRoot->assignedNodesForSlot(*this)) {
-            for (auto* node : *assignedNodes)
-                distributedNodes.append(node);
-        }
+    if (auto* assignedNodes = this->assignedNodes()) {
+        for (auto* node : *assignedNodes)
+            distributedNodes.append(node);
     }
 
     return distributedNodes;
index 3c0327f..098916c 100644 (file)
@@ -36,6 +36,8 @@ class HTMLSlotElement final : public HTMLElement {
 public:
     static Ref<HTMLSlotElement> create(const QualifiedName&, Document&);
 
+    const Vector<Node*>* assignedNodes() const;
+
     Vector<RefPtr<Node>> getDistributedNodes() const;
 
 private:
index 09a3856..33585bf 100644 (file)
@@ -32,6 +32,7 @@
 #include "ElementIterator.h"
 #include "ElementRareData.h"
 #include "FlowThreadController.h"
+#include "HTMLSlotElement.h"
 #include "InsertionPoint.h"
 #include "InspectorInstrumentation.h"
 #include "LoaderStrategy.h"
@@ -468,11 +469,33 @@ static void attachBeforeOrAfterPseudoElementIfNeeded(Element& current, PseudoId
     attachRenderTree(pseudoElement.get(), *current.renderStyle(), renderTreePosition, nullptr);
 }
 
+#if ENABLE(SHADOW_DOM)
+static void attachSlotAssignees(HTMLSlotElement& slot, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition)
+{
+    if (auto* assignedNodes = slot.assignedNodes()) {
+        for (auto* child : *assignedNodes) {
+            if (is<Text>(*child))
+                attachTextRenderer(downcast<Text>(*child), renderTreePosition);
+            else if (is<Element>(*child))
+                attachRenderTree(downcast<Element>(*child), inheritedStyle, renderTreePosition, nullptr);
+        }
+    }
+    slot.clearNeedsStyleRecalc();
+    slot.clearChildNeedsStyleRecalc();
+}
+#endif
+
 static void attachRenderTree(Element& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, PassRefPtr<RenderStyle> resolvedStyle)
 {
     PostResolutionCallbackDisabler callbackDisabler(current.document());
     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
 
+#if ENABLE(SHADOW_DOM)
+    if (is<HTMLSlotElement>(current)) {
+        attachSlotAssignees(downcast<HTMLSlotElement>(current), inheritedStyle, renderTreePosition);
+        return;
+    }
+#endif
     if (is<InsertionPoint>(current)) {
         attachDistributedChildren(downcast<InsertionPoint>(current), inheritedStyle, renderTreePosition);
         current.clearNeedsStyleRecalc();
@@ -532,15 +555,10 @@ static void detachDistributedChildren(InsertionPoint& insertionPoint)
 
 static void detachChildren(ContainerNode& current, DetachType detachType)
 {
-    if (is<InsertionPoint>(current))
-        detachDistributedChildren(downcast<InsertionPoint>(current));
-
     for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
-        if (is<Text>(*child)) {
-            Style::detachTextRenderer(downcast<Text>(*child));
-            continue;
-        }
-        if (is<Element>(*child))
+        if (is<Text>(*child))
+            detachTextRenderer(downcast<Text>(*child));
+        else if (is<Element>(*child))
             detachRenderTree(downcast<Element>(*child), detachType);
     }
     current.clearChildNeedsStyleRecalc();
@@ -551,6 +569,23 @@ static void detachShadowRoot(ShadowRoot& shadowRoot, DetachType detachType)
     detachChildren(shadowRoot, detachType);
 }
 
+#if ENABLE(SHADOW_DOM)
+static void detachSlotAssignees(HTMLSlotElement& slot, DetachType detachType)
+{
+    ASSERT(!slot.renderer());
+    if (auto* assignedNodes = slot.assignedNodes()) {
+        for (auto* child : *assignedNodes) {
+            if (is<Text>(*child))
+                detachTextRenderer(downcast<Text>(*child));
+            else if (is<Element>(*child))
+                detachRenderTree(downcast<Element>(*child), detachType);
+        }
+    }
+    slot.clearNeedsStyleRecalc();
+    slot.clearChildNeedsStyleRecalc();
+}
+#endif
+
 static void detachRenderTree(Element& current, DetachType detachType)
 {
     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
@@ -565,7 +600,13 @@ static void detachRenderTree(Element& current, DetachType detachType)
     if (detachType != ReattachDetach)
         current.clearHoverAndActiveStatusBeforeDetachingRenderer();
 
-    if (ShadowRoot* shadowRoot = current.shadowRoot())
+    if (is<InsertionPoint>(current))
+        detachDistributedChildren(downcast<InsertionPoint>(current));
+#if ENABLE(SHADOW_DOM)
+    else if (is<HTMLSlotElement>(current))
+        detachSlotAssignees(downcast<HTMLSlotElement>(current), detachType);
+#endif
+    else if (ShadowRoot* shadowRoot = current.shadowRoot())
         detachShadowRoot(*shadowRoot, detachType);
 
     detachChildren(current, detachType);
@@ -798,10 +839,32 @@ static void resolveChildren(Element& current, RenderStyle& inheritedStyle, Chang
     }
 }
 
+#if ENABLE(SHADOW_DOM)
+static void resolveSlotAssignees(HTMLSlotElement& slot, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, Change change)
+{
+    if (auto* assignedNodes = slot.assignedNodes()) {
+        for (auto* child : *assignedNodes) {
+            if (is<Text>(*child))
+                resolveTextNode(downcast<Text>(*child), renderTreePosition);
+            else if (is<Element>(*child))
+                resolveTree(downcast<Element>(*child), inheritedStyle, renderTreePosition, change);
+        }
+    }
+    slot.clearNeedsStyleRecalc();
+    slot.clearChildNeedsStyleRecalc();
+}
+#endif
+
 void resolveTree(Element& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, Change change)
 {
     ASSERT(change != Detach);
 
+#if ENABLE(SHADOW_DOM)
+    if (is<HTMLSlotElement>(current)) {
+        resolveSlotAssignees(downcast<HTMLSlotElement>(current), inheritedStyle, renderTreePosition, change);
+        return;
+    }
+#endif
     if (is<InsertionPoint>(current)) {
         current.clearNeedsStyleRecalc();
         current.clearChildNeedsStyleRecalc();