void RelatedNodeRetargeter::moveToNewTreeScope(TreeScope* previousTreeScope, TreeScope& newTreeScope) { if (m_hasDifferentTreeRoot) return; auto& currentRelatedNodeScope = m_retargetedRelatedNode->treeScope(); if (previousTreeScope != ¤tRelatedNodeScope) { // currentRelatedNode is still outside our shadow tree. New tree scope may contain currentRelatedNode // but there is no need to re-target it. Moving into a slot (thereby a deeper shadow tree) doesn't matter. return; } bool enteredSlot = newTreeScope.parentTreeScope() == previousTreeScope; if (enteredSlot) { if (m_lowestCommonAncestorIndex) { if (m_ancestorTreeScopes.isEmpty()) collectTreeScopes(); bool relatedNodeIsInSlot = m_ancestorTreeScopes[m_lowestCommonAncestorIndex - 1] == &newTreeScope; if (relatedNodeIsInSlot) { m_lowestCommonAncestorIndex--; m_retargetedRelatedNode = nodeInLowestCommonAncestor(); ASSERT(&newTreeScope == &m_retargetedRelatedNode->treeScope()); } } else ASSERT(m_retargetedRelatedNode == &m_relatedNode); } else { ASSERT(previousTreeScope->parentTreeScope() == &newTreeScope); m_lowestCommonAncestorIndex++; ASSERT_WITH_SECURITY_IMPLICATION(m_ancestorTreeScopes.isEmpty() || m_lowestCommonAncestorIndex < m_ancestorTreeScopes.size()); m_retargetedRelatedNode = downcast<ShadowRoot>(currentRelatedNodeScope.rootNode()).host(); ASSERT(&newTreeScope == &m_retargetedRelatedNode->treeScope()); } }
RelatedNodeRetargeter::RelatedNodeRetargeter(Node& relatedNode, Node& target) : m_relatedNode(relatedNode) , m_retargetedRelatedNode(&relatedNode) { auto& targetTreeScope = target.treeScope(); TreeScope* currentTreeScope = &m_relatedNode.treeScope(); if (LIKELY(currentTreeScope == &targetTreeScope && target.inDocument() && m_relatedNode.inDocument())) return; if (¤tTreeScope->documentScope() != &targetTreeScope.documentScope()) { m_hasDifferentTreeRoot = true; m_retargetedRelatedNode = nullptr; return; } if (relatedNode.inDocument() != target.inDocument()) { m_hasDifferentTreeRoot = true; m_retargetedRelatedNode = moveOutOfAllShadowRoots(relatedNode); return; } collectTreeScopes(); // FIXME: We should collect this while constructing the event path. Vector<TreeScope*, 8> targetTreeScopeAncestors; for (TreeScope* currentTreeScope = &targetTreeScope; currentTreeScope; currentTreeScope = currentTreeScope->parentTreeScope()) targetTreeScopeAncestors.append(currentTreeScope); ASSERT_WITH_SECURITY_IMPLICATION(!targetTreeScopeAncestors.isEmpty()); unsigned i = m_ancestorTreeScopes.size(); unsigned j = targetTreeScopeAncestors.size(); ASSERT_WITH_SECURITY_IMPLICATION(m_ancestorTreeScopes.last() == targetTreeScopeAncestors.last()); while (m_ancestorTreeScopes[i - 1] == targetTreeScopeAncestors[j - 1]) { i--; j--; if (!i || !j) break; } bool lowestCommonAncestorIsDocumentScope = i + 1 == m_ancestorTreeScopes.size(); if (lowestCommonAncestorIsDocumentScope && !relatedNode.inDocument() && !target.inDocument()) { Node& targetAncestorInDocumentScope = i ? *downcast<ShadowRoot>(m_ancestorTreeScopes[i - 1]->rootNode()).shadowHost() : target; Node& relatedNodeAncestorInDocumentScope = j ? *downcast<ShadowRoot>(targetTreeScopeAncestors[j - 1]->rootNode()).shadowHost() : relatedNode; if (targetAncestorInDocumentScope.rootNode() != relatedNodeAncestorInDocumentScope.rootNode()) { m_hasDifferentTreeRoot = true; m_retargetedRelatedNode = moveOutOfAllShadowRoots(relatedNode); return; } } m_lowestCommonAncestorIndex = i; m_retargetedRelatedNode = nodeInLowestCommonAncestor(); }
RelatedNodeRetargeter(Node& relatedNode, TreeScope& targetTreeScope) : m_relatedNode(relatedNode) , m_retargetedRelatedNode(&relatedNode) { TreeScope* currentTreeScope = &m_relatedNode.treeScope(); if (LIKELY(currentTreeScope == &targetTreeScope)) return; if (¤tTreeScope->documentScope() != &targetTreeScope.documentScope()) { m_hasDifferentTreeRoot = true; m_retargetedRelatedNode = nullptr; return; } if (relatedNode.inDocument() != targetTreeScope.rootNode().inDocument()) { m_hasDifferentTreeRoot = true; while (m_retargetedRelatedNode->isInShadowTree()) m_retargetedRelatedNode = downcast<ShadowRoot>(m_retargetedRelatedNode->treeScope().rootNode()).host(); return; } collectTreeScopes(); // FIXME: We should collect this while constructing the event path. Vector<TreeScope*, 8> targetTreeScopeAncestors; for (TreeScope* currentTreeScope = &targetTreeScope; currentTreeScope; currentTreeScope = currentTreeScope->parentTreeScope()) targetTreeScopeAncestors.append(currentTreeScope); ASSERT_WITH_SECURITY_IMPLICATION(!targetTreeScopeAncestors.isEmpty()); unsigned i = m_ancestorTreeScopes.size(); unsigned j = targetTreeScopeAncestors.size(); ASSERT_WITH_SECURITY_IMPLICATION(m_ancestorTreeScopes.last() == targetTreeScopeAncestors.last()); while (m_ancestorTreeScopes[i - 1] == targetTreeScopeAncestors[j - 1]) { i--; j--; if (!i || !j) break; } m_lowestCommonAncestorIndex = i; m_retargetedRelatedNode = nodeInLowestCommonAncestor(); }