Index: third_party/WebKit/Source/core/dom/shadow/ComposedTreeTraversal.cpp |
diff --git a/third_party/WebKit/Source/core/dom/shadow/ComposedTreeTraversal.cpp b/third_party/WebKit/Source/core/dom/shadow/ComposedTreeTraversal.cpp |
index 4050ea183c938d13aa89f4064d03f58a994ba969..a1c84831ebb6d643c091260743940a6577630f56 100644 |
--- a/third_party/WebKit/Source/core/dom/shadow/ComposedTreeTraversal.cpp |
+++ b/third_party/WebKit/Source/core/dom/shadow/ComposedTreeTraversal.cpp |
@@ -38,6 +38,11 @@ static inline ElementShadow* shadowFor(const Node& node) |
return node.isElementNode() ? toElement(node).shadow() : nullptr; |
} |
+static inline bool canBeDistributedToInsertionPoint(const Node& node) |
+{ |
+ return node.isInV0ShadowTree() || node.isChildOfV0ShadowHost(); |
+} |
+ |
Node* ComposedTreeTraversal::traverseChild(const Node& node, TraversalDirection direction) |
{ |
ElementShadow* shadow = shadowFor(node); |
@@ -52,13 +57,23 @@ Node* ComposedTreeTraversal::resolveDistributionStartingAt(const Node* node, Tra |
{ |
if (!node) |
return nullptr; |
- if (node->isInShadowTree() && node->containingShadowRoot()->isV1()) |
- return v1ResolveDistributionStartingAt(*node, direction); |
- return v0ResolveDistributionStartingAt(*node, direction); |
+ for (const Node* sibling = node; sibling; sibling = (direction == TraversalDirectionForward ? sibling->nextSibling() : sibling->previousSibling())) { |
+ if (isHTMLSlotElement(*sibling)) { |
+ const HTMLSlotElement& slot = toHTMLSlotElement(*sibling); |
+ if (Node* found = (direction == TraversalDirectionForward ? slot.firstDistributedNode() : slot.lastDistributedNode())) |
+ return found; |
+ continue; |
+ } |
+ if (node->isInV0ShadowTree()) |
+ return v0ResolveDistributionStartingAt(*sibling, direction); |
+ return const_cast<Node*>(sibling); |
+ } |
+ return nullptr; |
} |
Node* ComposedTreeTraversal::v0ResolveDistributionStartingAt(const Node& node, TraversalDirection direction) |
{ |
+ ASSERT(!isHTMLSlotElement(node)); |
for (const Node* sibling = &node; sibling; sibling = (direction == TraversalDirectionForward ? sibling->nextSibling() : sibling->previousSibling())) { |
if (!isActiveInsertionPoint(*sibling)) |
return const_cast<Node*>(sibling); |
@@ -70,18 +85,6 @@ Node* ComposedTreeTraversal::v0ResolveDistributionStartingAt(const Node& node, T |
return nullptr; |
} |
-Node* ComposedTreeTraversal::v1ResolveDistributionStartingAt(const Node& node, TraversalDirection direction) |
-{ |
- for (const Node* sibling = &node; sibling; sibling = (direction == TraversalDirectionForward ? sibling->nextSibling() : sibling->previousSibling())) { |
- if (!isHTMLSlotElement(*sibling)) |
- return const_cast<Node*>(sibling); |
- const HTMLSlotElement& slot = toHTMLSlotElement(*sibling); |
- if (Node* found = (direction == TraversalDirectionForward ? slot.firstDistributedNode() : slot.lastDistributedNode())) |
- return found; |
- } |
- return nullptr; |
-} |
- |
static HTMLSlotElement* finalDestinationSlotFor(const Node& node) |
{ |
HTMLSlotElement* slot = node.assignedSlot(); |
@@ -93,70 +96,53 @@ static HTMLSlotElement* finalDestinationSlotFor(const Node& node) |
return slot; |
} |
-Node* ComposedTreeTraversal::traverseSiblings(const Node& node, TraversalDirection direction) |
-{ |
- Node* parent = node.parentNode(); |
- if (!parent) |
- return nullptr; |
- if (parent->isElementNode()) { |
- if (ElementShadow* shadow = toElement(parent)->shadow()) { |
- if (shadow->isV1()) { |
- return v1TraverseSiblings(node, direction); |
- } |
- } |
- } |
- return v0TraverseSiblings(node, direction); |
-} |
- |
// TODO(hayato): This may return a wrong result for a node which is not in a |
// document composed tree. See ComposedTreeTraversalTest's redistribution test for details. |
-Node* ComposedTreeTraversal::v0TraverseSiblings(const Node& node, TraversalDirection direction) |
+Node* ComposedTreeTraversal::traverseSiblings(const Node& node, TraversalDirection direction) |
{ |
- if (!shadowWhereNodeCanBeDistributed(node)) |
- return traverseSiblingsOrShadowInsertionPointSiblings(node, direction); |
+ if (node.isChildOfV1ShadowHost()) |
+ return traverseSiblingsForV1HostChild(node, direction); |
- const InsertionPoint* finalDestination = resolveReprojection(&node); |
- if (!finalDestination) |
- return nullptr; |
- if (Node* found = (direction == TraversalDirectionForward ? finalDestination->distributedNodeNextTo(&node) : finalDestination->distributedNodePreviousTo(&node))) |
- return found; |
- return traverseSiblings(*finalDestination, direction); |
-} |
- |
-Node* ComposedTreeTraversal::v1TraverseSiblings(const Node& node, TraversalDirection direction) |
-{ |
- HTMLSlotElement* slot = finalDestinationSlotFor(node); |
- if (!slot) |
- return resolveDistributionStartingAt(direction == TraversalDirectionForward ? node.nextSibling() : node.previousSibling(), direction); |
- if (Node* siblingInDistributedNodes = (direction == TraversalDirectionForward ? slot->distributedNodeNextTo(node) : slot->distributedNodePreviousTo(node))) |
- return siblingInDistributedNodes; |
- return v1TraverseSiblings(*slot, direction); |
-} |
+ if (shadowWhereNodeCanBeDistributed(node)) |
+ return traverseSiblingsForV0Distribution(node, direction); |
-Node* ComposedTreeTraversal::traverseSiblingsOrShadowInsertionPointSiblings(const Node& node, TraversalDirection direction) |
-{ |
if (Node* found = resolveDistributionStartingAt(direction == TraversalDirectionForward ? node.nextSibling() : node.previousSibling(), direction)) |
return found; |
+ if (!node.isInV0ShadowTree()) |
+ return nullptr; |
+ |
+ // For v0 older shadow tree |
if (node.parentNode() && node.parentNode()->isShadowRoot()) { |
ShadowRoot* parentShadowRoot = toShadowRoot(node.parentNode()); |
if (!parentShadowRoot->isYoungest()) { |
HTMLShadowElement* assignedInsertionPoint = parentShadowRoot->shadowInsertionPointOfYoungerShadowRoot(); |
ASSERT(assignedInsertionPoint); |
- return traverseSiblingsOrShadowInsertionPointSiblings(*assignedInsertionPoint, direction); |
+ return traverseSiblings(*assignedInsertionPoint, direction); |
} |
} |
return nullptr; |
} |
-static ElementShadow* parentElementShadow(const Node& node) |
+Node* ComposedTreeTraversal::traverseSiblingsForV1HostChild(const Node& node, TraversalDirection direction) |
{ |
- Node* parent = node.parentNode(); |
- if (!parent) |
+ HTMLSlotElement* slot = finalDestinationSlotFor(node); |
+ if (!slot) |
return nullptr; |
- if (parent->isElementNode()) |
- return toElement(parent)->shadow(); |
- return nullptr; |
+ if (Node* siblingInDistributedNodes = (direction == TraversalDirectionForward ? slot->distributedNodeNextTo(node) : slot->distributedNodePreviousTo(node))) |
+ return siblingInDistributedNodes; |
+ return traverseSiblings(*slot, direction); |
+} |
+ |
+Node* ComposedTreeTraversal::traverseSiblingsForV0Distribution(const Node& node, TraversalDirection direction) |
+{ |
+ const InsertionPoint* finalDestination = resolveReprojection(&node); |
+ if (!finalDestination) |
+ return nullptr; |
+ if (Node* found = (direction == TraversalDirectionForward ? finalDestination->distributedNodeNextTo(&node) : finalDestination->distributedNodePreviousTo(&node))) |
+ return found; |
+ return traverseSiblings(*finalDestination, direction); |
+ |
} |
ContainerNode* ComposedTreeTraversal::traverseParent(const Node& node, ParentTraversalDetails* details) |
@@ -165,43 +151,49 @@ ContainerNode* ComposedTreeTraversal::traverseParent(const Node& node, ParentTra |
if (node.isPseudoElement()) |
return node.parentOrShadowHostNode(); |
- ElementShadow* shadow = parentElementShadow(node); |
- if (shadow && shadow->isV1()) |
- return v1TraverseParent(node); |
- if (shadowWhereNodeCanBeDistributed(node)) |
- return v0TraverseParent(node, details); |
- return traverseParentOrHost(node); |
-} |
+ if (node.isChildOfV1ShadowHost()) { |
+ HTMLSlotElement* slot = finalDestinationSlotFor(node); |
+ if (!slot) |
+ return nullptr; |
+ return traverseParent(*slot); |
+ } |
-ContainerNode* ComposedTreeTraversal::v1TraverseParent(const Node& node) |
-{ |
- HTMLSlotElement* slot = finalDestinationSlotFor(node); |
- if (!slot) |
- return nullptr; |
- if (parentElementShadow(*slot)) { |
- // The node is distributed to the |slot|, however, |slot|, which is a |
- // child of a shadow host, is not assigned to any slots. |
- return nullptr; |
+ Element* parent = node.parentElement(); |
+ if (parent && isHTMLSlotElement(parent)) { |
+ HTMLSlotElement& slot = toHTMLSlotElement(*parent); |
+ if (!slot.getAssignedNodes().isEmpty()) |
+ return nullptr; |
+ return traverseParent(slot, details); |
} |
- return traverseParentOrHost(*slot); |
+ |
+ if (canBeDistributedToInsertionPoint(node)) |
+ return traverseParentForV0(node, details); |
+ |
+ ASSERT(!shadowWhereNodeCanBeDistributed(node)); |
+ return traverseParentOrHost(node); |
} |
-ContainerNode* ComposedTreeTraversal::v0TraverseParent(const Node& node, ParentTraversalDetails* details) |
+ContainerNode* ComposedTreeTraversal::traverseParentForV0(const Node& node, ParentTraversalDetails* details) |
{ |
- if (const InsertionPoint* insertionPoint = resolveReprojection(&node)) { |
- if (details) |
- details->didTraverseInsertionPoint(insertionPoint); |
- // The node is distributed. But the distribution was stopped at this insertion point. |
- if (shadowWhereNodeCanBeDistributed(*insertionPoint)) |
- return nullptr; |
- return traverseParentOrHost(*insertionPoint); |
+ if (shadowWhereNodeCanBeDistributed(node)) { |
+ if (const InsertionPoint* insertionPoint = resolveReprojection(&node)) { |
+ if (details) |
+ details->didTraverseInsertionPoint(insertionPoint); |
+ // The node is distributed. But the distribution was stopped at this insertion point. |
+ if (shadowWhereNodeCanBeDistributed(*insertionPoint)) |
+ return nullptr; |
+ return traverseParent(*insertionPoint); |
+ } |
+ return nullptr; |
} |
- return nullptr; |
+ ContainerNode* parent = traverseParentOrHost(node); |
+ if (isActiveInsertionPoint(*parent)) |
+ return nullptr; |
+ return parent; |
} |
-inline ContainerNode* ComposedTreeTraversal::traverseParentOrHost(const Node& node) |
+ContainerNode* ComposedTreeTraversal::traverseParentOrHost(const Node& node) |
{ |
- // TODO(hayato): Support fallback contents of slots. The parent can be a slot. |
ContainerNode* parent = node.parentNode(); |
if (!parent) |
return nullptr; |
@@ -211,10 +203,7 @@ inline ContainerNode* ComposedTreeTraversal::traverseParentOrHost(const Node& no |
ASSERT(!shadowRoot->shadowInsertionPointOfYoungerShadowRoot()); |
if (!shadowRoot->isYoungest()) |
return nullptr; |
- Element* host = shadowRoot->host(); |
- if (isActiveInsertionPoint(*host)) |
- return nullptr; |
- return host; |
+ return shadowRoot->host(); |
} |
Node* ComposedTreeTraversal::childAt(const Node& node, unsigned index) |