| Index: third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp
|
| diff --git a/third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp b/third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..92a75f5a96ae3c124304784ec2125fe72cd477c9
|
| --- /dev/null
|
| +++ b/third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp
|
| @@ -0,0 +1,85 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "core/dom/shadow/SlotScopedTraversal.h"
|
| +
|
| +#include "core/dom/Element.h"
|
| +#include "core/dom/ElementTraversal.h"
|
| +#include "core/html/HTMLSlotElement.h"
|
| +
|
| +namespace blink {
|
| +
|
| +HTMLSlotElement* SlotScopedTraversal::findScopeOwnerSlot(const Element& current)
|
| +{
|
| + if (Element* nearestAncestorAssignedToSlot = SlotScopedTraversal::nearestAncestorAssignedToSlot(current))
|
| + return nearestAncestorAssignedToSlot->assignedSlot();
|
| + return nullptr;
|
| +}
|
| +
|
| +Element* SlotScopedTraversal::nearestAncestorAssignedToSlot(const Element& current)
|
| +{
|
| + // nearestAncestorAssignedToSlot returns an ancestor element of current which is directly assigned to a slot.
|
| + Element* element = const_cast<Element*>(¤t);
|
| + for (; element; element = element->parentElement()) {
|
| + if (element->assignedSlot())
|
| + break;
|
| + }
|
| + return element;
|
| +}
|
| +
|
| +Element* SlotScopedTraversal::next(const Element& current)
|
| +{
|
| + // current.assignedSlot returns a slot only when current is assigned explicitly
|
| + // If current is assigned to a slot, return a descendant of current, which is in the assigned scope of the same slot as current.
|
| + HTMLSlotElement* slot = current.assignedSlot();
|
| + Element* nearestAncestorAssignedToSlot = SlotScopedTraversal::nearestAncestorAssignedToSlot(current);
|
| + if (slot) {
|
| + if (Element* next = ElementTraversal::next(current, ¤t))
|
| + return next;
|
| + } else {
|
| + // If current is in assigned scope, find an assigned ancestor.
|
| + ASSERT(nearestAncestorAssignedToSlot);
|
| + if (Element* next = ElementTraversal::next(current, nearestAncestorAssignedToSlot))
|
| + return next;
|
| + slot = nearestAncestorAssignedToSlot->assignedSlot();
|
| + ASSERT(slot);
|
| + }
|
| + WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = slot->getAssignedNodes();
|
| + size_t currentIndex = assignedNodes.find(*nearestAncestorAssignedToSlot);
|
| + ASSERT(currentIndex != kNotFound);
|
| + for (++currentIndex; currentIndex < assignedNodes.size(); ++currentIndex) {
|
| + if (assignedNodes[currentIndex]->isElementNode())
|
| + return toElement(assignedNodes[currentIndex]);
|
| + }
|
| + return nullptr;
|
| +}
|
| +
|
| +Element* SlotScopedTraversal::previous(const Element& current)
|
| +{
|
| + Element* nearestAncestorAssignedToSlot = SlotScopedTraversal::nearestAncestorAssignedToSlot(current);
|
| + ASSERT(nearestAncestorAssignedToSlot);
|
| + // NodeTraversal within nearestAncestorAssignedToSlot
|
| + if (Element* previous = ElementTraversal::previous(current, nearestAncestorAssignedToSlot))
|
| + return previous;
|
| + // If null, jump to previous assigned node's descendant
|
| + const WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = nearestAncestorAssignedToSlot->assignedSlot()->getAssignedNodes();
|
| + size_t currentIndex = assignedNodes.reverseFind(*nearestAncestorAssignedToSlot);
|
| + ASSERT(currentIndex != kNotFound);
|
| + for (; currentIndex > 0; --currentIndex) {
|
| + const RefPtrWillBeMember<Node> assignedPrevious = assignedNodes[currentIndex - 1];
|
| + if (assignedPrevious->isElementNode()) {
|
| + if (Element* last = ElementTraversal::lastWithin(*toElement(assignedPrevious)))
|
| + return last;
|
| + return toElement(assignedPrevious);
|
| + }
|
| + }
|
| + return nullptr;
|
| +}
|
| +
|
| +bool SlotScopedTraversal::isSlotScoped(const Element& current)
|
| +{
|
| + return SlotScopedTraversal::nearestAncestorAssignedToSlot(current);
|
| +}
|
| +
|
| +} // namespace blink
|
|
|