Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Unified Diff: Source/core/events/EventPath.cpp

Issue 906123002: Change the order of insertion points which are involved in a re-distribution in event path (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: test updated Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching-nested-shadow-roots-expected.txt ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/events/EventPath.cpp
diff --git a/Source/core/events/EventPath.cpp b/Source/core/events/EventPath.cpp
index 9e53e718837b7f4b98bb0c5d7645cbec6efd6614..7857bd0f35b306c48eb3b6863b08f4017462c885 100644
--- a/Source/core/events/EventPath.cpp
+++ b/Source/core/events/EventPath.cpp
@@ -31,10 +31,12 @@
#include "core/dom/Document.h"
#include "core/dom/Touch.h"
#include "core/dom/TouchList.h"
+#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/InsertionPoint.h"
#include "core/dom/shadow/ShadowRoot.h"
#include "core/events/TouchEvent.h"
#include "core/events/TouchEventContext.h"
+#include "core/html/HTMLShadowElement.h"
namespace blink {
@@ -46,6 +48,8 @@ EventTarget* EventPath::eventTargetRespectingTargetRules(Node& referenceNode)
return &referenceNode;
}
+#define W3C23887 3
+#if !defined(W3C23887) || W3C23887 < 2
static inline bool shouldStopAtShadowRoot(Event& event, ShadowRoot& shadowRoot, EventTarget& target)
{
// WebKit never allowed selectstart event to cross the the shadow DOM boundary.
@@ -63,6 +67,24 @@ static inline bool shouldStopAtShadowRoot(Event& event, ShadowRoot& shadowRoot,
|| eventType == EventTypeNames::select
|| eventType == EventTypeNames::selectstart);
}
+#else
+static inline bool shouldStopBeforeShadowHost(Event& event)
+{
+ // WebKit never allowed selectstart event to cross the the shadow DOM boundary.
+ // Changing this breaks existing sites.
+ // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
+ const AtomicString eventType = event.type();
+ return (eventType == EventTypeNames::abort
+ || eventType == EventTypeNames::change
+ || eventType == EventTypeNames::error
+ || eventType == EventTypeNames::load
+ || eventType == EventTypeNames::reset
+ || eventType == EventTypeNames::resize
+ || eventType == EventTypeNames::scroll
+ || eventType == EventTypeNames::select
+ || eventType == EventTypeNames::selectstart);
+}
+#endif
EventPath::EventPath(Node& node, Event* event)
: m_node(node)
@@ -93,6 +115,46 @@ void EventPath::addNodeEventContext(Node& node)
m_nodeEventContexts.append(NodeEventContext(&node, eventTargetRespectingTargetRules(node)));
}
+#if W3C23887 == 1
+static bool isDistributedToShadowInsertionPoint(const ShadowRoot& shadowRoot)
+{
+ // 5.2.3. If CURRENT is not the youngest shadow root hosted by SHADOW-POOL-HOST:
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23887#c163
+ // and CURRENT is distributed to a shadow insertion point
+ ElementShadow* owner = shadowRoot.owner();
+ if (!owner)
+ return false;
+ if (shadowRoot.firstChild())
+ return owner->finalDestinationInsertionPointFor(shadowRoot.firstChild());
+ // TODO(kojii): how can we determine if a shadow root is distributed?
+ return false;
+}
+
+static ShadowRoot* shadowRootDistributedInto(InsertionPoint& insertionPoint)
+{
+ // 5.4.4.1. Let PROJECTED-SHADOW be the shadow root projected into CURRENT.
+ // TODO(kojii): is this correct way to determine that?
+#ifndef A1
+ return insertionPoint.containingShadowRoot()->olderShadowRoot();
+#else
+ // TODO(kojii): should it be first() or last()?
+ Node* distributedNode = insertionPoint.first();
+ if (!distributedNode)
+ return nullptr;
+ return distributedNode->containingShadowRoot();
+#endif
+}
+#endif
+#if W3C23887 >= 2
+static inline InsertionPoint* pop(WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8>& stack)
+{
+ ASSERT(!stack.isEmpty());
+ InsertionPoint* last = stack.last();
+ stack.removeLast();
+ return last;
+}
+#endif
+
void EventPath::calculatePath()
{
ASSERT(m_node);
@@ -100,6 +162,7 @@ void EventPath::calculatePath()
m_node->updateDistribution();
Node* current = m_node;
+#ifndef W3C23887
addNodeEventContext(*current);
if (!m_node->inDocument())
return;
@@ -132,6 +195,182 @@ void EventPath::calculatePath()
addNodeEventContext(*current);
}
}
+#elif W3C23887 == 3
+ if (!m_node->inDocument()) {
+ addNodeEventContext(*current);
+ return;
+ }
+ Element* stopBefore = m_event && shouldStopBeforeShadowHost(*m_event) ? m_node->shadowHost() : nullptr;
+ WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPointStack;
+ for (;;) {
+ ASSERT(current);
+ addNodeEventContext(*current);
+ if (m_event && current->keepEventInNode(m_event))
+ break;
+ WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
+ collectDestinationInsertionPoints(*current, insertionPoints);
+ if (!insertionPoints.isEmpty()) {
+ insertionPointStack.appendVector(insertionPoints);
+ current = pop(insertionPointStack);
+ continue;
+ }
+ if (current->isShadowRoot()) {
+ ShadowRoot* shadowRoot = toShadowRoot(current);
+ Node* olderShadowRootOrShadowHost = shadowRoot->olderShadowRoot();
+ if (!olderShadowRootOrShadowHost)
+ olderShadowRootOrShadowHost = shadowRoot->host();
+ ASSERT(olderShadowRootOrShadowHost);
+ if (!insertionPointStack.isEmpty() && insertionPointStack.last()->treeScope() == olderShadowRootOrShadowHost->treeScope()) {
+ current = pop(insertionPointStack);
+ continue;
+ }
+ if (olderShadowRootOrShadowHost == stopBefore)
+ break;
+ current = olderShadowRootOrShadowHost;
+ continue;
+ }
+ current = current->parentNode();
+ if (!current)
+ break;
+ }
+ // ASSERT(insertionPointStack.isEmpty());
+#elif W3C23887 == 2
+ if (!m_node->inDocument()) {
+ addNodeEventContext(*current);
+ return;
+ }
+ Element* stopBefore = m_event && shouldStopBeforeShadowHost(*m_event) ? m_node->shadowHost() : nullptr;
+ WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPointStack;
+ for (;;) {
+ ASSERT(current);
+ addNodeEventContext(*current);
+ if (m_event && current->keepEventInNode(m_event))
+ break;
+ WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
+ collectDestinationInsertionPoints(*current, insertionPoints);
+ if (!insertionPoints.isEmpty()) {
+ bool hasInsertionPoints = false;
+ for (const auto& insertionPoint : insertionPoints) {
+ if (insertionPoint->isShadowInsertionPoint() && !insertionPoint->containingShadowRoot()->isOldest())
+ continue;
+ insertionPointStack.append(insertionPoint);
+ hasInsertionPoints = true;
+ }
+ if (hasInsertionPoints) {
+ current = pop(insertionPointStack);
+ continue;
+ }
+ }
+ if (current->isShadowRoot()) {
+ ShadowRoot* shadowRoot = toShadowRoot(current);
+ Element* shadowHost = shadowRoot->host();
+ ASSERT(shadowHost);
+ if (!insertionPointStack.isEmpty() && insertionPointStack.last()->treeScope() == shadowHost->treeScope()) {
+ current = pop(insertionPointStack);
+ continue;
+ }
+ if (HTMLShadowElement* shadowInsertionPointOfYoungerShadowRoot = shadowRoot->shadowInsertionPointOfYoungerShadowRoot()) {
+ current = shadowInsertionPointOfYoungerShadowRoot;
+ continue;
+ }
+ if (shadowHost == stopBefore)
+ break;
+ current = shadowHost;
+ continue;
+ }
+ current = current->parentNode();
+ if (!current)
+ break;
+ }
+ ASSERT(insertionPointStack.isEmpty());
+#elif W3C23887 == 1 // https://bugzilla.mozilla.org/show_bug.cgi?id=1059989#c10
+ addNodeEventContext(*current);
+ if (!m_node->inDocument())
+ return;
+ // 3. Let INSERTION-POINTS be an empty stack of nodes.
+ WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPointStack;
+ while (current) {
+ if (m_event && current->keepEventInNode(m_event))
+ break;
+ // 5.1. If the destination insertion points of CURRENT is not empty:
+ WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
+ collectDestinationInsertionPoints(*current, insertionPoints);
+ bool removeShadowInsertionPoint = true;
+ if (!insertionPoints.isEmpty()) {
+ // 5.1.1. Push the destination insertion points into INSERTION-POINTS in order of first destination to final destination.
+ insertionPointStack.appendVector(insertionPoints);
+ // 5.1.2. Pop INSERTION-POINTS and set CURRENT to be the popped node.
+ current = insertionPointStack.last();
+ insertionPointStack.removeLast();
+ // 5.2. Otherwise if CURRENT is a shadow root:
+ } else if (current->isShadowRoot()) {
+ // 5.2.2. If SHADOW-POOL-HOST hosts the node tree which NODE participates in and EVENT is one of the events which must be stopped:
+ ShadowRoot* currentShadowRoot = toShadowRoot(current);
+ // TODO(kojii): we should be able to check this once and determine where to stop for better performance
+ if (m_event && shouldStopAtShadowRoot(*m_event, *currentShadowRoot, *m_node)) {
+ // 5.2.2.1. Stop this algorithm
+ break;
+ }
+ // 5.2.1. Let SHADOW-POOL-HOST be the shadow host which hosts CURRENT
+ Element* shadowPoolHost = currentShadowRoot->host();
+ // 5.2.3. If CURRENT is not the youngest shadow root hosted by SHADOW-POOL-HOST:
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23887#c163
+ // and CURRENT is distributed to a shadow insertion point
+ if (!currentShadowRoot->isYoungest() && isDistributedToShadowInsertionPoint(*currentShadowRoot)) {
+ // 5.2.3.1. Let SHADOW-POOL-HOST be the shadow insertion point into which CURRENT shadow root is projected.
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23887#c122
+ // Let SHADOW-POOL-HOST be the shadow insertion point in the younger shadow tree relative to the shadow tree
+ // whose root is CURRENT shadow root.
+ shadowPoolHost = currentShadowRoot->shadowInsertionPointOfYoungerShadowRoot();
+ }
+ // 5.2.4. If INSERTION-POINTS is not empty and
+ // if the most recent node in the INSERTION-POINTS is in the same node tree as SHADOW-POOL-HOST:
+ if (!insertionPointStack.isEmpty() && insertionPointStack.last()->treeScope() == shadowPoolHost->treeScope()) {
+ // 5.2.4.1. Pop INSERTION-POINTS and set CURRENT to be the popped node.
+ current = insertionPointStack.last();
+ insertionPointStack.removeLast();
+ // 5.2.5. Otherwise:
+ } else {
+ // 5.2.5.1. Set CURRENT to SHADOW-POOL-HOST and skip step 4
+ current = shadowPoolHost;
+ removeShadowInsertionPoint = false;
+ }
+ // 5.3. Otherwise:
+ } else {
+ // 5.3.1. 1. Let CURRENT be the parent node of CURRENT.
+ current = current->parentNode();
+ }
+ if (removeShadowInsertionPoint) {
+ // 5.4.4. Repeat while CURRENT is a shadow insertion point.
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23887#c170
+ // and there is a shadow root distributed to it (see the "if" within the "while" below)
+ while (current && isActiveShadowInsertionPoint(*current)) {
+ // 5.4.4.1. Let PROJECTED-SHADOW be the shadow root projected into CURRENT.
+ ShadowRoot* distributedShadowRoot = shadowRootDistributedInto(toInsertionPoint(*current));
+ // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23887#c170
+ // 5.4.4. and there is a shadow root distributed to it
+ if (!distributedShadowRoot)
+ break;
+ // 5.4.4.2. If INSERTION-POINTS is not empty and
+ // if the most recent node in the INSERTION-POINTS is in the same node tree as PROJECTED-SHADOW:
+ if (!insertionPointStack.isEmpty() && insertionPointStack.last()->treeScope() == distributedShadowRoot->treeScope()) {
+ // 5.4.4.2.1. Pop INSERTION-POINTS and set CURRENT to be the popped node.
+ current = insertionPointStack.last();
+ insertionPointStack.removeLast();
+ // 5.4.4.3. Otherwise:
+ } else {
+ // 5.4.4.3.1. Set CURRENT to PROJECTED-SHADOW.
+ current = distributedShadowRoot;
+ }
+ }
+ }
+ // 5.5. If CURRENT exists:
+ // 5.5.1. Add CURRENT to PATH.
+ if (current)
+ addNodeEventContext(*current);
+ }
+ ASSERT(insertionPointStack.isEmpty());
+#endif
}
void EventPath::calculateTreeScopePrePostOrderNumbers()
« no previous file with comments | « LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching-nested-shadow-roots-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698