void EventPath::calculateTreeOrderAndSetNearestAncestorClosedTree() { // Precondition: // - TreeScopes in m_treeScopeEventContexts must be *connected* in the same tree of trees. // - The root tree must be included. WillBeHeapHashMap<RawPtrWillBeMember<const TreeScope>, RawPtrWillBeMember<TreeScopeEventContext>> treeScopeEventContextMap; for (const auto& treeScopeEventContext : m_treeScopeEventContexts) treeScopeEventContextMap.add(&treeScopeEventContext->treeScope(), treeScopeEventContext.get()); TreeScopeEventContext* rootTree = nullptr; for (const auto& treeScopeEventContext : m_treeScopeEventContexts) { // Use olderShadowRootOrParentTreeScope here for parent-child relationships. // See the definition of trees of trees in the Shadow DOM spec: // http://w3c.github.io/webcomponents/spec/shadow/ TreeScope* parent = treeScopeEventContext.get()->treeScope().olderShadowRootOrParentTreeScope(); if (!parent) { ASSERT(!rootTree); rootTree = treeScopeEventContext.get(); continue; } ASSERT(treeScopeEventContextMap.find(parent) != treeScopeEventContextMap.end()); treeScopeEventContextMap.find(parent)->value->addChild(*treeScopeEventContext.get()); } ASSERT(rootTree); rootTree->calculateTreeOrderAndSetNearestAncestorClosedTree(0, nullptr); }
void EventPath::adjustForRelatedTarget(Node* target, EventTarget* relatedTarget) { if (!target) return; if (!relatedTarget) return; Node* relatedNode = relatedTarget->toNode(); if (!relatedNode) return; if (target->document() != relatedNode->document()) return; if (!target->inDocument() || !relatedNode->inDocument()) return; RelatedTargetMap relatedNodeMap; buildRelatedNodeMap(relatedNode, relatedNodeMap); for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) { TreeScopeEventContext* treeScopeEventContext = m_treeScopeEventContexts[i].get(); EventTarget* adjustedRelatedTarget = findRelatedNode(&treeScopeEventContext->treeScope(), relatedNodeMap); ASSERT(adjustedRelatedTarget); treeScopeEventContext->setRelatedTarget(adjustedRelatedTarget); } shrinkIfNeeded(target, relatedTarget); }
void EventPath::calculateAdjustedTargets() { const TreeScope* lastTreeScope = 0; bool useDeprecatedSVGUseTreeEventRules = usesDeprecatedSVGUseTreeEventRules(at(0).node()); TreeScopeEventContextMap treeScopeEventContextMap; TreeScopeEventContext* lastTreeScopeEventContext = 0; for (size_t i = 0; i < size(); ++i) { Node* currentNode = at(i).node(); TreeScope& currentTreeScope = currentNode->treeScope(); if (lastTreeScope != ¤tTreeScope) { if (!useDeprecatedSVGUseTreeEventRules) { lastTreeScopeEventContext = ensureTreeScopeEventContext(currentNode, ¤tTreeScope, treeScopeEventContextMap); } else { TreeScopeEventContextMap::AddResult addResult = treeScopeEventContextMap.add(¤tTreeScope, TreeScopeEventContext::create(currentTreeScope)); lastTreeScopeEventContext = addResult.storedValue->value.get(); if (addResult.isNewEntry) { // Don't adjust an event target for SVG. lastTreeScopeEventContext->setTarget(eventTargetRespectingTargetRules(at(0).node())); } } } ASSERT(lastTreeScopeEventContext); at(i).setTreeScopeEventContext(lastTreeScopeEventContext); lastTreeScope = ¤tTreeScope; } m_treeScopeEventContexts.appendRange(treeScopeEventContextMap.values().begin(), treeScopeEventContextMap.values().end()); }
void EventPath::calculateTreeScopePrePostOrderNumbers() { // Precondition: // - TreeScopes in m_treeScopeEventContexts must be *connected* in the same tree of trees. // - The root tree must be included. HashMap<const TreeScope*, TreeScopeEventContext*> treeScopeEventContextMap; for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) treeScopeEventContextMap.add(&m_treeScopeEventContexts[i]->treeScope(), m_treeScopeEventContexts[i].get()); TreeScopeEventContext* rootTree = 0; for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) { TreeScopeEventContext* treeScopeEventContext = m_treeScopeEventContexts[i].get(); // Use olderShadowRootOrParentTreeScope here for parent-child relationships. // See the definition of trees of trees in the Shado DOM spec: http://w3c.github.io/webcomponents/spec/shadow/ TreeScope* parent = treeScopeEventContext->treeScope().olderShadowRootOrParentTreeScope(); if (!parent) { ASSERT(!rootTree); rootTree = treeScopeEventContext; continue; } ASSERT(treeScopeEventContextMap.find(parent) != treeScopeEventContextMap.end()); treeScopeEventContextMap.find(parent)->value->addChild(*treeScopeEventContext); } ASSERT(rootTree); rootTree->calculatePrePostOrderNumber(0); }
void EventPath::buildRelatedNodeMap(const Node& relatedNode, RelatedTargetMap& relatedTargetMap) { EventPath relatedTargetEventPath(const_cast<Node&>(relatedNode)); for (size_t i = 0; i < relatedTargetEventPath.m_treeScopeEventContexts.size(); ++i) { TreeScopeEventContext* treeScopeEventContext = relatedTargetEventPath.m_treeScopeEventContexts[i].get(); relatedTargetMap.add(&treeScopeEventContext->treeScope(), treeScopeEventContext->target()); } }
void EventPath::buildRelatedNodeMap(const Node& relatedNode, RelatedTargetMap& relatedTargetMap) { OwnPtrWillBeRawPtr<EventPath> relatedTargetEventPath = adoptPtrWillBeNoop(new EventPath(const_cast<Node&>(relatedNode))); for (size_t i = 0; i < relatedTargetEventPath->m_treeScopeEventContexts.size(); ++i) { TreeScopeEventContext* treeScopeEventContext = relatedTargetEventPath->m_treeScopeEventContexts[i].get(); relatedTargetMap.add(&treeScopeEventContext->treeScope(), treeScopeEventContext->target()); } #if ENABLE(OILPAN) // Oilpan: It is important to explicitly clear the vectors to reuse // the memory in subsequent event dispatchings. relatedTargetEventPath->clear(); #endif }
TreeScopeEventContext* EventPath::ensureTreeScopeEventContext(Node* currentTarget, TreeScope* treeScope, TreeScopeEventContextMap& treeScopeEventContextMap) { if (!treeScope) return 0; TreeScopeEventContext* treeScopeEventContext; bool isNewEntry; { TreeScopeEventContextMap::AddResult addResult = treeScopeEventContextMap.add(treeScope, nullptr); isNewEntry = addResult.isNewEntry; if (isNewEntry) addResult.storedValue->value = TreeScopeEventContext::create(*treeScope); treeScopeEventContext = addResult.storedValue->value.get(); } if (isNewEntry) { TreeScopeEventContext* parentTreeScopeEventContext = ensureTreeScopeEventContext(0, treeScope->olderShadowRootOrParentTreeScope(), treeScopeEventContextMap); if (parentTreeScopeEventContext && parentTreeScopeEventContext->target()) { treeScopeEventContext->setTarget(parentTreeScopeEventContext->target()); } else if (currentTarget) { treeScopeEventContext->setTarget(eventTargetRespectingTargetRules(*currentTarget)); } } else if (!treeScopeEventContext->target() && currentTarget) { treeScopeEventContext->setTarget(eventTargetRespectingTargetRules(*currentTarget)); } return treeScopeEventContext; }
void EventPath::calculateAdjustedEventPath() { if (!RuntimeEnabledFeatures::shadowDOMEnabled()) return; for (size_t i = 0; i < m_treeScopeEventContexts.size(); ++i) { TreeScopeEventContext* treeScopeEventContext = m_treeScopeEventContexts[i].get(); Vector<RefPtr<Node> > nodes; nodes.reserveInitialCapacity(size()); for (size_t i = 0; i < size(); ++i) { if (at(i).node()->treeScope().isInclusiveAncestorOf(treeScopeEventContext->treeScope())) nodes.append(at(i).node()); } treeScopeEventContext->adoptEventPath(nodes); } }
bool TreeScopeEventContext::isUnclosedTreeOf(const TreeScopeEventContext& other) { // Exclude closed nodes if necessary. // If a node is in a closed shadow root, or in a tree whose ancestor has a closed shadow root, // it should not be visible to nodes above the closed shadow root. // (1) If |this| is an ancestor of |other| in tree-of-trees, include it. if (isInclusiveAncestorOf(other)) return true; // (2) If no closed shadow root in ancestors of this, include it. if (!containingClosedShadowTree()) return true; // (3) If |this| is descendent of |other|, exclude if any closed shadow root in between. if (isDescendantOf(other)) return !containingClosedShadowTree()->isDescendantOf(other); // (4) |this| and |other| must be in exclusive branches. ASSERT(other.isExclusivePartOf(*this)); return false; }