static ContainerNode* traverseParent(const Node* node, ShadowRootCrossing shadowRootCrossing) { if (node->isPseudoElement()) return toPseudoElement(node)->hostElement(); if (shadowRootCrossing == DontCrossShadowRoot && node->isShadowRoot()) return 0; if (nodeCanBeDistributed(node)) { if (InsertionPoint* insertionPoint = findInsertionPointOf(node)) return traverseParent(insertionPoint, shadowRootCrossing); return nullptr; } ContainerNode* parent = node->parentNode(); if (!parent) return nullptr; if (parent->isShadowRoot()) return shadowRootCrossing == CrossShadowRoot ? toShadowRoot(parent)->hostElement() : parent; if (parent->isInsertionPoint()) { const InsertionPoint* insertionPoint = toInsertionPoint(parent); if (insertionPoint->hasDistribution()) return nullptr; if (insertionPoint->isActive()) return traverseParent(parent, shadowRootCrossing); } return parent; }
Node* ComposedShadowTreeWalker::traverseSiblingOrBackToInsertionPoint(const Node* node, TraversalDirection direction) { ASSERT(node); if (!nodeCanBeDistributed(node)) return traverseSiblingInCurrentTree(node, direction); InsertionPoint* insertionPoint = resolveReprojection(node); if (!insertionPoint) return traverseSiblingInCurrentTree(node, direction); if (Node* found = traverseDistributedNodes(direction == TraversalDirectionForward ? insertionPoint->nextTo(node) : insertionPoint->previousTo(node), insertionPoint, direction)) return found; return traverseSiblingOrBackToInsertionPoint(insertionPoint, direction); }
static Node* traversePreviousSibling(const Node* node) { ASSERT(node); InsertionPoint* insertionPoint; if (nodeCanBeDistributed(node) && (insertionPoint = findInsertionPointOf(node))) { Node* found = findLastFromDistributedNode(insertionPoint->previousDistributedTo(node), insertionPoint); if (found) return found; return traversePreviousSibling(insertionPoint); } for (const Node* sibling = node->previousSibling(); sibling; sibling = sibling->previousSibling()) { if (Node* found = findLastEnteringInsertionPoints(sibling)) return found; } if (node->parentNode() && isActiveInsertionPoint(node->parentNode())) return traversePreviousSibling(node->parentNode()); return nullptr; }
// FIXME: Use an iterative algorithm so that it can be inlined. // https://bugs.webkit.org/show_bug.cgi?id=90415 Node* ComposedShadowTreeWalker::traverseParent(const Node* node, ParentTraversalDetails* details) const { if (node->isPseudoElement()) return toPseudoElement(node)->hostElement(); if (!canCrossUpperBoundary() && node->isShadowRoot()) return 0; if (nodeCanBeDistributed(node)) { if (InsertionPoint* insertionPoint = resolveReprojection(node)) { if (details) details->didTraverseInsertionPoint(insertionPoint); return traverseParent(insertionPoint, details); } // The node is a non-distributed light child or older shadow's child. if (details) details->childWasOutOfComposition(); } return traverseParentInCurrentTree(node, details); }