Node* FlatTreeTraversal::commonAncestor(const Node& nodeA, const Node& nodeB) { assertPrecondition(nodeA); assertPrecondition(nodeB); Node* result = nodeA.commonAncestor(nodeB, [](const Node& node) { return FlatTreeTraversal::parent(node); }); assertPostcondition(result); return result; }
bool FlatTreeTraversal::containsIncludingPseudoElement(const ContainerNode& container, const Node& node) { assertPrecondition(container); assertPrecondition(node); // This can be slower than FlatTreeTraversal::contains() because we // can't early exit even when container doesn't have children. for (const Node* current = &node; current; current = traverseParent(*current)) { if (current == &container) return true; } return false; }
bool FlatTreeTraversal::isDescendantOf(const Node& node, const Node& other) { assertPrecondition(node); assertPrecondition(other); if (!hasChildren(other) || node.inShadowIncludingDocument() != other.inShadowIncludingDocument()) return false; for (const ContainerNode* n = traverseParent(node); n; n = traverseParent(*n)) { if (n == other) return true; } return false; }
Node& FlatTreeTraversal::lastWithinOrSelf(const Node& node) { assertPrecondition(node); Node* lastDescendant = lastWithin(node); Node& result = lastDescendant ? *lastDescendant : const_cast<Node&>(node); assertPostcondition(&result); return result; }
unsigned FlatTreeTraversal::countChildren(const Node& node) { assertPrecondition(node); unsigned count = 0; for (Node* runner = traverseFirstChild(node); runner; runner = traverseNextSibling(*runner)) ++count; return count; }
unsigned FlatTreeTraversal::index(const Node& node) { assertPrecondition(node); unsigned count = 0; for (Node* runner = traversePreviousSibling(node); runner; runner = previousSibling(*runner)) ++count; return count; }
// TODO(yosin) We should consider introducing template class to share code // between DOM tree traversal and flat tree tarversal. Node* FlatTreeTraversal::previousPostOrder(const Node& current, const Node* stayWithin) { assertPrecondition(current); if (stayWithin) assertPrecondition(*stayWithin); if (Node* lastChild = traverseLastChild(current)) { assertPostcondition(lastChild); return lastChild; } if (current == stayWithin) return nullptr; if (Node* previousSibling = traversePreviousSibling(current)) { assertPostcondition(previousSibling); return previousSibling; } return previousAncestorSiblingPostOrder(current, stayWithin); }
Node* FlatTreeTraversal::lastWithin(const Node& node) { assertPrecondition(node); Node* descendant = traverseLastChild(node); for (Node* child = descendant; child; child = lastChild(*child)) descendant = child; assertPostcondition(descendant); return descendant; }
Node* FlatTreeTraversal::childAt(const Node& node, unsigned index) { assertPrecondition(node); Node* child = traverseFirstChild(node); while (child && index--) child = nextSibling(*child); assertPostcondition(child); return child; }
ComposedShadowTreeWalker::ComposedShadowTreeWalker(const Node* node, Policy policy) : m_node(node) , m_policy(policy) { #ifndef NDEBUG if (m_node) assertPrecondition(); #endif }
void ComposedShadowTreeWalker::previous() { assertPrecondition(); if (Node* n = traversePreviousSibling(m_node)) { while (Node* child = traverseLastChild(n)) n = child; m_node = n; } else parent(); assertPostcondition(); }
void ComposedShadowTreeWalker::next() { assertPrecondition(); if (Node* next = traverseFirstChild(m_node)) m_node = next; else if (Node* next = traverseNextSibling(m_node)) m_node = next; else { const Node* n = m_node; while (n && !traverseNextSibling(n)) n = traverseParent(n); m_node = n ? traverseNextSibling(n) : 0; } assertPostcondition(); }
void ComposedShadowTreeWalker::lastChild() { assertPrecondition(); m_node = traverseLastChild(m_node); assertPostcondition(); }
void ComposedShadowTreeWalker::firstChild() { assertPrecondition(); m_node = traverseChild(m_node, TraversalDirectionForward); assertPostcondition(); }
void ComposedShadowTreeWalker::parent() { assertPrecondition(); m_node = traverseParent(m_node); assertPostcondition(); }
void ComposedShadowTreeWalker::previousSibling() { assertPrecondition(); m_node = traverseSiblingOrBackToInsertionPoint(m_node, TraversalDirectionBackward); assertPostcondition(); }