ContainerNode* FlatTreeTraversal::traverseParent(const Node& node, ParentTraversalDetails* details)
{
    // TODO(hayato): Stop this hack for a pseudo element because a pseudo element is not a child of its parentOrShadowHostNode() in a flat tree.
    if (node.isPseudoElement())
        return node.parentOrShadowHostNode();

    if (node.isChildOfV1ShadowHost()) {
        HTMLSlotElement* slot = finalDestinationSlotFor(node);
        if (!slot)
            return nullptr;
        return traverseParent(*slot);
    }

    Element* parent = node.parentElement();
    if (parent && isHTMLSlotElement(parent)) {
        HTMLSlotElement& slot = toHTMLSlotElement(*parent);
        if (!slot.assignedNodes().isEmpty())
            return nullptr;
        return traverseParent(slot, details);
    }

    if (canBeDistributedToInsertionPoint(node))
        return traverseParentForV0(node, details);

    DCHECK(!shadowWhereNodeCanBeDistributed(node));
    return traverseParentOrHost(node);
}
// FIXME: Use an iterative algorithm so that it can be inlined.
// https://bugs.webkit.org/show_bug.cgi?id=90415
Node* ComposedTreeWalker::traverseParent(const Node* node, ParentTraversalDetails* details) const
{
    if (node->isPseudoElement())
        return node->parentOrShadowHostNode();

    if (shadowWhereNodeCanBeDistributed(*node)) {
        if (const InsertionPoint* insertionPoint = resolveReprojection(node)) {
            if (details)
                details->didTraverseInsertionPoint(insertionPoint);
            // The node is distributed. But the distribution was stopped at this insertion point.
            if (shadowWhereNodeCanBeDistributed(*insertionPoint))
                return 0;
            return traverseParentOrHost(insertionPoint, details);
        }
        return 0;
    }
    return traverseParentOrHost(node, details);
}
ContainerNode* FlatTreeTraversal::traverseParentForV0(const Node& node, ParentTraversalDetails* details)
{
    if (shadowWhereNodeCanBeDistributed(node)) {
        if (const InsertionPoint* insertionPoint = resolveReprojection(&node)) {
            if (details)
                details->didTraverseInsertionPoint(insertionPoint);
            // The node is distributed. But the distribution was stopped at this insertion point.
            if (shadowWhereNodeCanBeDistributed(*insertionPoint))
                return nullptr;
            return traverseParent(*insertionPoint);
        }
        return nullptr;
    }
    ContainerNode* parent = traverseParentOrHost(node);
    if (isActiveInsertionPoint(*parent))
        return nullptr;
    return parent;
}