void EventPathWalker::moveToParent() { ASSERT(m_node); ASSERT(m_distributedNode); if (ElementShadow* shadow = shadowOfParent(m_node)) { ContentDistributor::ensureDistribution(shadow->youngestShadowRoot()); if (InsertionPoint* insertionPoint = shadow->distributor().findInsertionPointFor(m_distributedNode)) { m_node = insertionPoint; m_isVisitingInsertionPointInReprojection = true; return; } } if (!m_node->isShadowRoot()) { m_node = m_node->parentNode(); if (!(m_node && m_node->isShadowRoot() && ScopeContentDistribution::assignedTo(toShadowRoot(m_node)))) m_distributedNode = m_node; m_isVisitingInsertionPointInReprojection = false; return; } const ShadowRoot* shadowRoot = toShadowRoot(m_node); if (InsertionPoint* insertionPoint = ScopeContentDistribution::assignedTo(shadowRoot)) { m_node = insertionPoint; m_isVisitingInsertionPointInReprojection = true; return; } m_node = shadowRoot->host(); m_distributedNode = m_node; m_isVisitingInsertionPointInReprojection = false; }
void AncestorChainWalker::parent() { ASSERT(m_node); ASSERT(m_distributedNode); if (ElementShadow* shadow = shadowOfParent(m_node)) { if (InsertionPoint* insertionPoint = shadow->insertionPointFor(m_distributedNode)) { m_node = insertionPoint; m_isCrossingInsertionPoint = true; return; } } if (!m_node->isShadowRoot()) { m_node = m_node->parentNode(); m_distributedNode = m_node; m_isCrossingInsertionPoint = false; return; } const ShadowRoot* shadowRoot = toShadowRoot(m_node); if (InsertionPoint* insertionPoint = shadowRoot->assignedTo()) { m_node = insertionPoint; m_isCrossingInsertionPoint = true; return; } m_node = shadowRoot->host(); m_distributedNode = m_node; m_isCrossingInsertionPoint = false; }
Node* ComposedShadowTreeWalker::traverseParent(const Node* node) const { if (!canCrossUpperBoundary() && node->isShadowRoot()) { ASSERT(toShadowRoot(node)->isYoungest()); return 0; } if (ElementShadow* shadow = shadowOfParent(node)) { if (InsertionPoint* insertionPoint = shadow->insertionPointFor(node)) return traverseParent(insertionPoint); } return traverseParentInCurrentTree(node); }
Node* ComposedShadowTreeWalker::traverseSiblingOrBackToInsertionPoint(const Node* node, TraversalDirection direction) { ASSERT(node); ElementShadow* shadow = shadowOfParent(node); if (!shadow) return traverseSiblingInCurrentTree(node, direction); InsertionPoint* insertionPoint = shadow->insertionPointFor(node); if (!insertionPoint) return traverseSiblingInCurrentTree(node, direction); if (Node* next = (direction == TraversalDirectionForward ? insertionPoint->nextTo(node) : insertionPoint->previousTo(node))) return traverseNode(next, direction); return traverseSiblingOrBackToInsertionPoint(insertionPoint, direction); }
static inline InsertionPoint* resolveReprojection(const Node* node) { InsertionPoint* insertionPoint = 0; const Node* current = node; while (ElementShadow* shadow = shadowOfParent(current)) { shadow->ensureDistribution(); if (InsertionPoint* insertedTo = shadow->insertionPointFor(node)) { current = insertedTo; insertionPoint = insertedTo; } else break; } return insertionPoint; }
Node* ComposedShadowTreeWalker::traverseSiblingOrBackToInsertionPoint(const Node* node, TraversalDirection direction) { ASSERT(node); ElementShadow* shadow = shadowOfParent(node); if (!shadow) 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); }
Node* ComposedShadowTreeParentWalker::traverseParentIncludingInsertionPointAndShadowRoot(const Node* node) const { if (ElementShadow* shadow = shadowOfParent(node)) { if (InsertionPoint* insertionPoint = shadow->insertionPointFor(node)) return insertionPoint; } if (!node->isShadowRoot()) return node->parentNode(); const ShadowRoot* shadowRoot = toShadowRoot(node); if (shadowRoot->isYoungest()) return shadowRoot->host(); InsertionPoint* assignedInsertionPoint = shadowRoot->assignedTo(); ASSERT(assignedInsertionPoint); return assignedInsertionPoint; }
// 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 (!canCrossUpperBoundary() && node->isShadowRoot()) { ASSERT(toShadowRoot(node)->isYoungest()); return 0; } if (ElementShadow* shadow = shadowOfParent(node)) { shadow->ensureDistribution(); 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); }