unsigned FlatTreeTraversal::countChildren(const Node& node)
{
    assertPrecondition(node);
    unsigned count = 0;
    for (Node* runner = traverseFirstChild(node); runner; runner = traverseNextSibling(*runner))
        ++count;
    return count;
}
Node* FlatTreeTraversal::childAt(const Node& node, unsigned index)
{
    assertPrecondition(node);
    Node* child = traverseFirstChild(node);
    while (child && index--)
        child = nextSibling(*child);
    assertPostcondition(child);
    return child;
}
Node* nextInScope(const Node* node)
{
    ASSERT(!isActiveInsertionPoint(node));

    if (Node* next = traverseFirstChild(node, DontCrossShadowRoot))
        return next;
    if (Node* next = traverseNextSibling(node))
        return next;
    const Node* current = node;
    while (current && !traverseNextSibling(current))
        current = traverseParent(current, DontCrossShadowRoot);
    return current ? traverseNextSibling(current) : 0;
}
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();
}
Node* nextSiblingSlow(const Node* node)
{
    ASSERT(!node->isShadowRoot());

    // FIXME: Why do these functions deal with before/after when other code here doesn't?
    Node* nextSibling = 0;
    if (node->isBeforePseudoElement()) {
        nextSibling = traverseParent(node, CrossShadowRoot);
        nextSibling = traverseFirstChild(nextSibling, CrossShadowRoot);
    } else
        nextSibling = traverseNextSibling(node);

    if (nextSibling || node->isAfterPseudoElement())
        return nextSibling;

    Node* parent = traverseParent(node, CrossShadowRoot);
    if (parent && parent->isElementNode())
        return toElement(parent)->afterPseudoElement();

    return 0;
}