Index: Source/core/events/TreeScopeEventContext.cpp |
diff --git a/Source/core/events/TreeScopeEventContext.cpp b/Source/core/events/TreeScopeEventContext.cpp |
index 22a8cacb23a3b54757233f7eefefd745981e005d..c94a8ff9b299c5b252a357130e0653b3d4c5348b 100644 |
--- a/Source/core/events/TreeScopeEventContext.cpp |
+++ b/Source/core/events/TreeScopeEventContext.cpp |
@@ -34,6 +34,36 @@ |
namespace blink { |
+bool TreeScopeEventContext::shouldIncludeTreeScope(const TreeScopeEventContext& other) |
+{ |
+ const Node& rootNode = other.rootNode(); |
+ |
+ // Exclude nodes in UA shadow. E.g. <details> distributes elements under its tree. |
+ if (rootNode.isShadowRoot() && (toShadowRoot(rootNode).type() == ShadowRootType::UserAgent)) |
+ return false; |
+ |
+ // 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 |other| is an ancestor in tree-of-trees, include it. |
+ if (other.isInclusiveAncestorOf(*this)) |
+ return true; |
+ |
+ // (2) If no closed shadow root in ancestors of |other|, include it. |
+ if (!other.containingClosedShadowTree()) |
+ return true; |
+ |
+ // (3) If |other| is descendent of |this|, exclude if any closed shadow root in between. |
+ if (other.isDescendantOf(*this)) |
+ return !other.containingClosedShadowTree()->isDescendantOf(*this); |
+ |
+ // (4) |this| and |other| must be in exclusive branches. |
+ ASSERT(isExclusivePartOf(other)); |
+ return false; |
+} |
+ |
WillBeHeapVector<RefPtrWillBeMember<EventTarget>>& TreeScopeEventContext::ensureEventPath(EventPath& path) |
{ |
if (m_eventPath) |
@@ -42,11 +72,9 @@ WillBeHeapVector<RefPtrWillBeMember<EventTarget>>& TreeScopeEventContext::ensure |
m_eventPath = adoptPtrWillBeNoop(new WillBeHeapVector<RefPtrWillBeMember<EventTarget>>()); |
LocalDOMWindow* window = path.windowEventContext().window(); |
m_eventPath->reserveCapacity(path.size() + (window ? 1 : 0)); |
+ |
for (size_t i = 0; i < path.size(); ++i) { |
- Node& rootNode = path[i].treeScopeEventContext().rootNode(); |
- if (rootNode.isShadowRoot() && (toShadowRoot(rootNode).type() == ShadowRootType::OpenByDefault || toShadowRoot(rootNode).type() == ShadowRootType::Open)) |
- m_eventPath->append(path[i].node()); |
- else if (path[i].treeScopeEventContext().isInclusiveAncestorOf(*this)) |
+ if (shouldIncludeTreeScope(path[i].treeScopeEventContext())) |
m_eventPath->append(path[i].node()); |
} |
if (window) |
@@ -69,6 +97,7 @@ PassRefPtrWillBeRawPtr<TreeScopeEventContext> TreeScopeEventContext::create(Tree |
TreeScopeEventContext::TreeScopeEventContext(TreeScope& treeScope) |
: m_treeScope(treeScope) |
, m_rootNode(treeScope.rootNode()) |
+ , m_containingClosedShadowTree(nullptr) |
, m_preOrder(-1) |
, m_postOrder(-1) |
{ |
@@ -84,18 +113,21 @@ DEFINE_TRACE(TreeScopeEventContext) |
visitor->trace(m_relatedTarget); |
visitor->trace(m_eventPath); |
visitor->trace(m_touchEventContext); |
+ visitor->trace(m_containingClosedShadowTree); |
#if ENABLE(OILPAN) |
visitor->trace(m_children); |
#endif |
} |
-int TreeScopeEventContext::calculatePrePostOrderNumber(int orderNumber) |
+int TreeScopeEventContext::calculateTreeOrderAndFindClosedTrees(int orderNumber, TreeScopeEventContext* parentClosedTreeScopeEventContext) |
{ |
m_preOrder = orderNumber; |
+ m_containingClosedShadowTree = (rootNode().isShadowRoot() && toShadowRoot(rootNode()).type() == ShadowRootType::Closed) ? this : parentClosedTreeScopeEventContext; |
for (size_t i = 0; i < m_children.size(); ++i) |
- orderNumber = m_children[i]->calculatePrePostOrderNumber(orderNumber + 1); |
+ orderNumber = m_children[i]->calculateTreeOrderAndFindClosedTrees(orderNumber + 1, containingClosedShadowTree()); |
m_postOrder = orderNumber + 1; |
+ |
return orderNumber + 1; |
} |
-} |
+} // namespace blink |