| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "core/dom/shadow/SlotScopedTraversal.h" |
| 6 |
| 7 #include "core/dom/Element.h" |
| 8 #include "core/dom/ElementTraversal.h" |
| 9 #include "core/html/HTMLSlotElement.h" |
| 10 |
| 11 namespace blink { |
| 12 |
| 13 HTMLSlotElement* SlotScopedTraversal::findScopeOwnerSlot(const Element& current) |
| 14 { |
| 15 if (Element* nearestAncestorAssignedToSlot = SlotScopedTraversal::nearestAnc
estorAssignedToSlot(current)) |
| 16 return nearestAncestorAssignedToSlot->assignedSlot(); |
| 17 return nullptr; |
| 18 } |
| 19 |
| 20 Element* SlotScopedTraversal::nearestAncestorAssignedToSlot(const Element& curre
nt) |
| 21 { |
| 22 // nearestAncestorAssignedToSlot returns an ancestor element of current whic
h is directly assigned to a slot. |
| 23 Element* element = const_cast<Element*>(¤t); |
| 24 for (; element; element = element->parentElement()) { |
| 25 if (element->assignedSlot()) |
| 26 break; |
| 27 } |
| 28 return element; |
| 29 } |
| 30 |
| 31 Element* SlotScopedTraversal::next(const Element& current) |
| 32 { |
| 33 // current.assignedSlot returns a slot only when current is assigned explici
tly |
| 34 // If current is assigned to a slot, return a descendant of current, which i
s in the assigned scope of the same slot as current. |
| 35 HTMLSlotElement* slot = current.assignedSlot(); |
| 36 Element* nearestAncestorAssignedToSlot = SlotScopedTraversal::nearestAncesto
rAssignedToSlot(current); |
| 37 if (slot) { |
| 38 if (Element* next = ElementTraversal::next(current, ¤t)) |
| 39 return next; |
| 40 } else { |
| 41 // If current is in assigned scope, find an assigned ancestor. |
| 42 ASSERT(nearestAncestorAssignedToSlot); |
| 43 if (Element* next = ElementTraversal::next(current, nearestAncestorAssig
nedToSlot)) |
| 44 return next; |
| 45 slot = nearestAncestorAssignedToSlot->assignedSlot(); |
| 46 ASSERT(slot); |
| 47 } |
| 48 WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = slot->getAssigned
Nodes(); |
| 49 size_t currentIndex = assignedNodes.find(*nearestAncestorAssignedToSlot); |
| 50 ASSERT(currentIndex != kNotFound); |
| 51 for (++currentIndex; currentIndex < assignedNodes.size(); ++currentIndex) { |
| 52 if (assignedNodes[currentIndex]->isElementNode()) |
| 53 return toElement(assignedNodes[currentIndex]); |
| 54 } |
| 55 return nullptr; |
| 56 } |
| 57 |
| 58 Element* SlotScopedTraversal::previous(const Element& current) |
| 59 { |
| 60 Element* nearestAncestorAssignedToSlot = SlotScopedTraversal::nearestAncesto
rAssignedToSlot(current); |
| 61 ASSERT(nearestAncestorAssignedToSlot); |
| 62 // NodeTraversal within nearestAncestorAssignedToSlot |
| 63 if (Element* previous = ElementTraversal::previous(current, nearestAncestorA
ssignedToSlot)) |
| 64 return previous; |
| 65 // If null, jump to previous assigned node's descendant |
| 66 const WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = nearestAnce
storAssignedToSlot->assignedSlot()->getAssignedNodes(); |
| 67 size_t currentIndex = assignedNodes.reverseFind(*nearestAncestorAssignedToSl
ot); |
| 68 ASSERT(currentIndex != kNotFound); |
| 69 for (; currentIndex > 0; --currentIndex) { |
| 70 const RefPtrWillBeMember<Node> assignedPrevious = assignedNodes[currentI
ndex - 1]; |
| 71 if (assignedPrevious->isElementNode()) { |
| 72 if (Element* last = ElementTraversal::lastWithin(*toElement(assigned
Previous))) |
| 73 return last; |
| 74 return toElement(assignedPrevious); |
| 75 } |
| 76 } |
| 77 return nullptr; |
| 78 } |
| 79 |
| 80 bool SlotScopedTraversal::isSlotScoped(const Element& current) |
| 81 { |
| 82 return SlotScopedTraversal::nearestAncestorAssignedToSlot(current); |
| 83 } |
| 84 |
| 85 } // namespace blink |
| OLD | NEW |