#include "config.h"
#include "NodeTraversal.h"
#include "PseudoElement.h"
namespace WebCore {
namespace NodeTraversal {
Node* previousIncludingPseudo(const Node& current, const Node* stayWithin)
{
Node* previous;
if (¤t == stayWithin)
return nullptr;
if ((previous = current.pseudoAwarePreviousSibling())) {
while (previous->pseudoAwareLastChild())
previous = previous->pseudoAwareLastChild();
return previous;
}
return is<PseudoElement>(current) ? downcast<PseudoElement>(current).hostElement() : current.parentNode();
}
Node* nextIncludingPseudo(const Node& current, const Node* stayWithin)
{
Node* next;
if ((next = current.pseudoAwareFirstChild()))
return next;
if (¤t == stayWithin)
return nullptr;
if ((next = current.pseudoAwareNextSibling()))
return next;
const Node* ancestor = is<PseudoElement>(current) ? downcast<PseudoElement>(current).hostElement() : current.parentNode();
for (; ancestor; ancestor = ancestor->parentNode()) {
if (ancestor == stayWithin)
return nullptr;
if ((next = ancestor->pseudoAwareNextSibling()))
return next;
}
return nullptr;
}
Node* nextIncludingPseudoSkippingChildren(const Node& current, const Node* stayWithin)
{
Node* next;
if (¤t == stayWithin)
return nullptr;
if ((next = current.pseudoAwareNextSibling()))
return next;
const Node* ancestor = is<PseudoElement>(current) ? downcast<PseudoElement>(current).hostElement() : current.parentNode();
for (; ancestor; ancestor = ancestor->parentNode()) {
if (ancestor == stayWithin)
return nullptr;
if ((next = ancestor->pseudoAwareNextSibling()))
return next;
}
return nullptr;
}
Node* nextAncestorSibling(const Node& current)
{
ASSERT(!current.nextSibling());
for (auto* ancestor = current.parentNode(); ancestor; ancestor = ancestor->parentNode()) {
if (ancestor->nextSibling())
return ancestor->nextSibling();
}
return nullptr;
}
Node* nextAncestorSibling(const Node& current, const Node* stayWithin)
{
ASSERT(!current.nextSibling());
ASSERT(¤t != stayWithin);
for (auto* ancestor = current.parentNode(); ancestor; ancestor = ancestor->parentNode()) {
if (ancestor == stayWithin)
return nullptr;
if (ancestor->nextSibling())
return ancestor->nextSibling();
}
return nullptr;
}
Node* last(const ContainerNode& current)
{
Node* node = current.lastChild();
if (!node)
return nullptr;
while (node->lastChild())
node = node->lastChild();
return node;
}
Node* deepLastChild(Node& node)
{
Node* lastChild = &node;
while (lastChild->lastChild())
lastChild = lastChild->lastChild();
return lastChild;
}
Node* previousSkippingChildren(const Node& current, const Node* stayWithin)
{
if (¤t == stayWithin)
return nullptr;
if (current.previousSibling())
return current.previousSibling();
for (auto* ancestor = current.parentNode(); ancestor; ancestor = ancestor->parentNode()) {
if (ancestor == stayWithin)
return nullptr;
if (ancestor->previousSibling())
return ancestor->previousSibling();
}
return nullptr;
}
Node* nextPostOrder(const Node& current, const Node* stayWithin)
{
if (¤t == stayWithin)
return nullptr;
if (!current.nextSibling())
return current.parentNode();
Node* next = current.nextSibling();
while (next->firstChild())
next = next->firstChild();
return next;
}
static Node* previousAncestorSiblingPostOrder(const Node& current, const Node* stayWithin)
{
ASSERT(!current.previousSibling());
for (auto* ancestor = current.parentNode(); ancestor; ancestor = ancestor->parentNode()) {
if (ancestor == stayWithin)
return nullptr;
if (ancestor->previousSibling())
return ancestor->previousSibling();
}
return nullptr;
}
Node* previousPostOrder(const Node& current, const Node* stayWithin)
{
if (current.lastChild())
return current.lastChild();
if (¤t == stayWithin)
return nullptr;
if (current.previousSibling())
return current.previousSibling();
return previousAncestorSiblingPostOrder(current, stayWithin);
}
Node* previousSkippingChildrenPostOrder(const Node& current, const Node* stayWithin)
{
if (¤t == stayWithin)
return nullptr;
if (current.previousSibling())
return current.previousSibling();
return previousAncestorSiblingPostOrder(current, stayWithin);
}
}
}