Chromium Code Reviews| 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 8c3a70073c9063bf7f50329116c99d37bd0a1925..f974a3cd6f56e3859ea97b7979c29e4162ad4604 100644 |
| --- a/third_party/WebKit/Source/core/dom/shadow/ComposedTreeTraversal.cpp |
| +++ b/third_party/WebKit/Source/core/dom/shadow/ComposedTreeTraversal.cpp |
| @@ -39,6 +39,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); |
| @@ -53,13 +58,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); |
| @@ -71,18 +86,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(); |
| @@ -94,70 +97,50 @@ 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; |
| + // For v0 older shadow tree |
| if (node.parentNode() && node.parentNode()->isShadowRoot()) { |
|
kochi
2016/01/05 07:44:11
Can you add an assertion here (ASSERT(node.isInV0S
hayato
2016/01/06 05:49:09
No. This code is to support v1 shadow tree, but th
kochi
2016/01/06 06:21:34
Acknowledged.
|
| 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) |
| @@ -166,43 +149,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; |
| @@ -212,10 +201,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) |