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

Side by Side 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 unified diff | 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Neither the name of Google Inc. nor the names of its 10 * * Neither the name of Google Inc. nor the names of its
(...skipping 13 matching lines...) Expand all
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */ 25 */
26 26
27 #include "config.h" 27 #include "config.h"
28 #include "core/events/EventPath.h" 28 #include "core/events/EventPath.h"
29 29
30 #include "core/EventNames.h" 30 #include "core/EventNames.h"
31 #include "core/dom/Document.h" 31 #include "core/dom/Document.h"
32 #include "core/dom/Touch.h" 32 #include "core/dom/Touch.h"
33 #include "core/dom/TouchList.h" 33 #include "core/dom/TouchList.h"
34 #include "core/dom/shadow/ElementShadow.h"
34 #include "core/dom/shadow/InsertionPoint.h" 35 #include "core/dom/shadow/InsertionPoint.h"
35 #include "core/dom/shadow/ShadowRoot.h" 36 #include "core/dom/shadow/ShadowRoot.h"
36 #include "core/events/TouchEvent.h" 37 #include "core/events/TouchEvent.h"
37 #include "core/events/TouchEventContext.h" 38 #include "core/events/TouchEventContext.h"
39 #include "core/html/HTMLShadowElement.h"
38 40
39 namespace blink { 41 namespace blink {
40 42
41 EventTarget* EventPath::eventTargetRespectingTargetRules(Node& referenceNode) 43 EventTarget* EventPath::eventTargetRespectingTargetRules(Node& referenceNode)
42 { 44 {
43 if (referenceNode.isPseudoElement()) 45 if (referenceNode.isPseudoElement())
44 return referenceNode.parentNode(); 46 return referenceNode.parentNode();
45 47
46 return &referenceNode; 48 return &referenceNode;
47 } 49 }
48 50
51 #define W3C23887 3
52 #if !defined(W3C23887) || W3C23887 < 2
49 static inline bool shouldStopAtShadowRoot(Event& event, ShadowRoot& shadowRoot, EventTarget& target) 53 static inline bool shouldStopAtShadowRoot(Event& event, ShadowRoot& shadowRoot, EventTarget& target)
50 { 54 {
51 // WebKit never allowed selectstart event to cross the the shadow DOM bounda ry. 55 // WebKit never allowed selectstart event to cross the the shadow DOM bounda ry.
52 // Changing this breaks existing sites. 56 // Changing this breaks existing sites.
53 // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details. 57 // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
54 const AtomicString eventType = event.type(); 58 const AtomicString eventType = event.type();
55 return target.toNode() && target.toNode()->shadowHost() == shadowRoot.host() 59 return target.toNode() && target.toNode()->shadowHost() == shadowRoot.host()
56 && (eventType == EventTypeNames::abort 60 && (eventType == EventTypeNames::abort
57 || eventType == EventTypeNames::change 61 || eventType == EventTypeNames::change
58 || eventType == EventTypeNames::error 62 || eventType == EventTypeNames::error
59 || eventType == EventTypeNames::load 63 || eventType == EventTypeNames::load
60 || eventType == EventTypeNames::reset 64 || eventType == EventTypeNames::reset
61 || eventType == EventTypeNames::resize 65 || eventType == EventTypeNames::resize
62 || eventType == EventTypeNames::scroll 66 || eventType == EventTypeNames::scroll
63 || eventType == EventTypeNames::select 67 || eventType == EventTypeNames::select
64 || eventType == EventTypeNames::selectstart); 68 || eventType == EventTypeNames::selectstart);
65 } 69 }
70 #else
71 static inline bool shouldStopBeforeShadowHost(Event& event)
72 {
73 // WebKit never allowed selectstart event to cross the the shadow DOM bounda ry.
74 // Changing this breaks existing sites.
75 // See https://bugs.webkit.org/show_bug.cgi?id=52195 for details.
76 const AtomicString eventType = event.type();
77 return (eventType == EventTypeNames::abort
78 || eventType == EventTypeNames::change
79 || eventType == EventTypeNames::error
80 || eventType == EventTypeNames::load
81 || eventType == EventTypeNames::reset
82 || eventType == EventTypeNames::resize
83 || eventType == EventTypeNames::scroll
84 || eventType == EventTypeNames::select
85 || eventType == EventTypeNames::selectstart);
86 }
87 #endif
66 88
67 EventPath::EventPath(Node& node, Event* event) 89 EventPath::EventPath(Node& node, Event* event)
68 : m_node(node) 90 : m_node(node)
69 , m_event(event) 91 , m_event(event)
70 { 92 {
71 initialize(); 93 initialize();
72 } 94 }
73 95
74 void EventPath::initializeWith(Node& node, Event* event) 96 void EventPath::initializeWith(Node& node, Event* event)
75 { 97 {
(...skipping 10 matching lines...) Expand all
86 calculatePath(); 108 calculatePath();
87 calculateAdjustedTargets(); 109 calculateAdjustedTargets();
88 calculateTreeScopePrePostOrderNumbers(); 110 calculateTreeScopePrePostOrderNumbers();
89 } 111 }
90 112
91 void EventPath::addNodeEventContext(Node& node) 113 void EventPath::addNodeEventContext(Node& node)
92 { 114 {
93 m_nodeEventContexts.append(NodeEventContext(&node, eventTargetRespectingTarg etRules(node))); 115 m_nodeEventContexts.append(NodeEventContext(&node, eventTargetRespectingTarg etRules(node)));
94 } 116 }
95 117
118 #if W3C23887 == 1
119 static bool isDistributedToShadowInsertionPoint(const ShadowRoot& shadowRoot)
120 {
121 // 5.2.3. If CURRENT is not the youngest shadow root hosted by SHADOW-POOL-H OST:
122 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23887#c163
123 // and CURRENT is distributed to a shadow insertion point
124 ElementShadow* owner = shadowRoot.owner();
125 if (!owner)
126 return false;
127 if (shadowRoot.firstChild())
128 return owner->finalDestinationInsertionPointFor(shadowRoot.firstChild()) ;
129 // TODO(kojii): how can we determine if a shadow root is distributed?
130 return false;
131 }
132
133 static ShadowRoot* shadowRootDistributedInto(InsertionPoint& insertionPoint)
134 {
135 // 5.4.4.1. Let PROJECTED-SHADOW be the shadow root projected into CURRENT.
136 // TODO(kojii): is this correct way to determine that?
137 #ifndef A1
138 return insertionPoint.containingShadowRoot()->olderShadowRoot();
139 #else
140 // TODO(kojii): should it be first() or last()?
141 Node* distributedNode = insertionPoint.first();
142 if (!distributedNode)
143 return nullptr;
144 return distributedNode->containingShadowRoot();
145 #endif
146 }
147 #endif
148 #if W3C23887 >= 2
149 static inline InsertionPoint* pop(WillBeHeapVector<RawPtrWillBeMember<InsertionP oint>, 8>& stack)
150 {
151 ASSERT(!stack.isEmpty());
152 InsertionPoint* last = stack.last();
153 stack.removeLast();
154 return last;
155 }
156 #endif
157
96 void EventPath::calculatePath() 158 void EventPath::calculatePath()
97 { 159 {
98 ASSERT(m_node); 160 ASSERT(m_node);
99 ASSERT(m_nodeEventContexts.isEmpty()); 161 ASSERT(m_nodeEventContexts.isEmpty());
100 m_node->updateDistribution(); 162 m_node->updateDistribution();
101 163
102 Node* current = m_node; 164 Node* current = m_node;
165 #ifndef W3C23887
103 addNodeEventContext(*current); 166 addNodeEventContext(*current);
104 if (!m_node->inDocument()) 167 if (!m_node->inDocument())
105 return; 168 return;
106 while (current) { 169 while (current) {
107 if (m_event && current->keepEventInNode(m_event)) 170 if (m_event && current->keepEventInNode(m_event))
108 break; 171 break;
109 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints; 172 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
110 collectDestinationInsertionPoints(*current, insertionPoints); 173 collectDestinationInsertionPoints(*current, insertionPoints);
111 if (!insertionPoints.isEmpty()) { 174 if (!insertionPoints.isEmpty()) {
112 for (const auto& insertionPoint : insertionPoints) { 175 for (const auto& insertionPoint : insertionPoints) {
(...skipping 12 matching lines...) Expand all
125 if (m_event && shouldStopAtShadowRoot(*m_event, *toShadowRoot(curren t), *m_node)) 188 if (m_event && shouldStopAtShadowRoot(*m_event, *toShadowRoot(curren t), *m_node))
126 break; 189 break;
127 current = current->shadowHost(); 190 current = current->shadowHost();
128 addNodeEventContext(*current); 191 addNodeEventContext(*current);
129 } else { 192 } else {
130 current = current->parentNode(); 193 current = current->parentNode();
131 if (current) 194 if (current)
132 addNodeEventContext(*current); 195 addNodeEventContext(*current);
133 } 196 }
134 } 197 }
198 #elif W3C23887 == 3
199 if (!m_node->inDocument()) {
200 addNodeEventContext(*current);
201 return;
202 }
203 Element* stopBefore = m_event && shouldStopBeforeShadowHost(*m_event) ? m_no de->shadowHost() : nullptr;
204 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPointStack;
205 for (;;) {
206 ASSERT(current);
207 addNodeEventContext(*current);
208 if (m_event && current->keepEventInNode(m_event))
209 break;
210 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
211 collectDestinationInsertionPoints(*current, insertionPoints);
212 if (!insertionPoints.isEmpty()) {
213 insertionPointStack.appendVector(insertionPoints);
214 current = pop(insertionPointStack);
215 continue;
216 }
217 if (current->isShadowRoot()) {
218 ShadowRoot* shadowRoot = toShadowRoot(current);
219 Node* olderShadowRootOrShadowHost = shadowRoot->olderShadowRoot();
220 if (!olderShadowRootOrShadowHost)
221 olderShadowRootOrShadowHost = shadowRoot->host();
222 ASSERT(olderShadowRootOrShadowHost);
223 if (!insertionPointStack.isEmpty() && insertionPointStack.last()->tr eeScope() == olderShadowRootOrShadowHost->treeScope()) {
224 current = pop(insertionPointStack);
225 continue;
226 }
227 if (olderShadowRootOrShadowHost == stopBefore)
228 break;
229 current = olderShadowRootOrShadowHost;
230 continue;
231 }
232 current = current->parentNode();
233 if (!current)
234 break;
235 }
236 // ASSERT(insertionPointStack.isEmpty());
237 #elif W3C23887 == 2
238 if (!m_node->inDocument()) {
239 addNodeEventContext(*current);
240 return;
241 }
242 Element* stopBefore = m_event && shouldStopBeforeShadowHost(*m_event) ? m_no de->shadowHost() : nullptr;
243 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPointStack;
244 for (;;) {
245 ASSERT(current);
246 addNodeEventContext(*current);
247 if (m_event && current->keepEventInNode(m_event))
248 break;
249 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
250 collectDestinationInsertionPoints(*current, insertionPoints);
251 if (!insertionPoints.isEmpty()) {
252 bool hasInsertionPoints = false;
253 for (const auto& insertionPoint : insertionPoints) {
254 if (insertionPoint->isShadowInsertionPoint() && !insertionPoint- >containingShadowRoot()->isOldest())
255 continue;
256 insertionPointStack.append(insertionPoint);
257 hasInsertionPoints = true;
258 }
259 if (hasInsertionPoints) {
260 current = pop(insertionPointStack);
261 continue;
262 }
263 }
264 if (current->isShadowRoot()) {
265 ShadowRoot* shadowRoot = toShadowRoot(current);
266 Element* shadowHost = shadowRoot->host();
267 ASSERT(shadowHost);
268 if (!insertionPointStack.isEmpty() && insertionPointStack.last()->tr eeScope() == shadowHost->treeScope()) {
269 current = pop(insertionPointStack);
270 continue;
271 }
272 if (HTMLShadowElement* shadowInsertionPointOfYoungerShadowRoot = sha dowRoot->shadowInsertionPointOfYoungerShadowRoot()) {
273 current = shadowInsertionPointOfYoungerShadowRoot;
274 continue;
275 }
276 if (shadowHost == stopBefore)
277 break;
278 current = shadowHost;
279 continue;
280 }
281 current = current->parentNode();
282 if (!current)
283 break;
284 }
285 ASSERT(insertionPointStack.isEmpty());
286 #elif W3C23887 == 1 // https://bugzilla.mozilla.org/show_bug.cgi?id=1059989#c10
287 addNodeEventContext(*current);
288 if (!m_node->inDocument())
289 return;
290 // 3. Let INSERTION-POINTS be an empty stack of nodes.
291 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPointStack;
292 while (current) {
293 if (m_event && current->keepEventInNode(m_event))
294 break;
295 // 5.1. If the destination insertion points of CURRENT is not empty:
296 WillBeHeapVector<RawPtrWillBeMember<InsertionPoint>, 8> insertionPoints;
297 collectDestinationInsertionPoints(*current, insertionPoints);
298 bool removeShadowInsertionPoint = true;
299 if (!insertionPoints.isEmpty()) {
300 // 5.1.1. Push the destination insertion points into INSERTION-POINT S in order of first destination to final destination.
301 insertionPointStack.appendVector(insertionPoints);
302 // 5.1.2. Pop INSERTION-POINTS and set CURRENT to be the popped node .
303 current = insertionPointStack.last();
304 insertionPointStack.removeLast();
305 // 5.2. Otherwise if CURRENT is a shadow root:
306 } else if (current->isShadowRoot()) {
307 // 5.2.2. If SHADOW-POOL-HOST hosts the node tree which NODE partici pates in and EVENT is one of the events which must be stopped:
308 ShadowRoot* currentShadowRoot = toShadowRoot(current);
309 // TODO(kojii): we should be able to check this once and determine w here to stop for better performance
310 if (m_event && shouldStopAtShadowRoot(*m_event, *currentShadowRoot, *m_node)) {
311 // 5.2.2.1. Stop this algorithm
312 break;
313 }
314 // 5.2.1. Let SHADOW-POOL-HOST be the shadow host which hosts CURREN T
315 Element* shadowPoolHost = currentShadowRoot->host();
316 // 5.2.3. If CURRENT is not the youngest shadow root hosted by SHADO W-POOL-HOST:
317 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23887#c163
318 // and CURRENT is distributed to a shadow insertion point
319 if (!currentShadowRoot->isYoungest() && isDistributedToShadowInserti onPoint(*currentShadowRoot)) {
320 // 5.2.3.1. Let SHADOW-POOL-HOST be the shadow insertion point i nto which CURRENT shadow root is projected.
321 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23887#c122
322 // Let SHADOW-POOL-HOST be the shadow insertion point in the you nger shadow tree relative to the shadow tree
323 // whose root is CURRENT shadow root.
324 shadowPoolHost = currentShadowRoot->shadowInsertionPointOfYounge rShadowRoot();
325 }
326 // 5.2.4. If INSERTION-POINTS is not empty and
327 // if the most recent node in the INSERTION-POINTS is in the same no de tree as SHADOW-POOL-HOST:
328 if (!insertionPointStack.isEmpty() && insertionPointStack.last()->tr eeScope() == shadowPoolHost->treeScope()) {
329 // 5.2.4.1. Pop INSERTION-POINTS and set CURRENT to be the poppe d node.
330 current = insertionPointStack.last();
331 insertionPointStack.removeLast();
332 // 5.2.5. Otherwise:
333 } else {
334 // 5.2.5.1. Set CURRENT to SHADOW-POOL-HOST and skip step 4
335 current = shadowPoolHost;
336 removeShadowInsertionPoint = false;
337 }
338 // 5.3. Otherwise:
339 } else {
340 // 5.3.1. 1. Let CURRENT be the parent node of CURRENT.
341 current = current->parentNode();
342 }
343 if (removeShadowInsertionPoint) {
344 // 5.4.4. Repeat while CURRENT is a shadow insertion point.
345 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23887#c170
346 // and there is a shadow root distributed to it (see the "if" within the "while" below)
347 while (current && isActiveShadowInsertionPoint(*current)) {
348 // 5.4.4.1. Let PROJECTED-SHADOW be the shadow root projected in to CURRENT.
349 ShadowRoot* distributedShadowRoot = shadowRootDistributedInto(to InsertionPoint(*current));
350 // https://www.w3.org/Bugs/Public/show_bug.cgi?id=23887#c170
351 // 5.4.4. and there is a shadow root distributed to it
352 if (!distributedShadowRoot)
353 break;
354 // 5.4.4.2. If INSERTION-POINTS is not empty and
355 // if the most recent node in the INSERTION-POINTS is in the sam e node tree as PROJECTED-SHADOW:
356 if (!insertionPointStack.isEmpty() && insertionPointStack.last() ->treeScope() == distributedShadowRoot->treeScope()) {
357 // 5.4.4.2.1. Pop INSERTION-POINTS and set CURRENT to be the popped node.
358 current = insertionPointStack.last();
359 insertionPointStack.removeLast();
360 // 5.4.4.3. Otherwise:
361 } else {
362 // 5.4.4.3.1. Set CURRENT to PROJECTED-SHADOW.
363 current = distributedShadowRoot;
364 }
365 }
366 }
367 // 5.5. If CURRENT exists:
368 // 5.5.1. Add CURRENT to PATH.
369 if (current)
370 addNodeEventContext(*current);
371 }
372 ASSERT(insertionPointStack.isEmpty());
373 #endif
135 } 374 }
136 375
137 void EventPath::calculateTreeScopePrePostOrderNumbers() 376 void EventPath::calculateTreeScopePrePostOrderNumbers()
138 { 377 {
139 // Precondition: 378 // Precondition:
140 // - TreeScopes in m_treeScopeEventContexts must be *connected* in the sam e tree of trees. 379 // - TreeScopes in m_treeScopeEventContexts must be *connected* in the sam e tree of trees.
141 // - The root tree must be included. 380 // - The root tree must be included.
142 WillBeHeapHashMap<RawPtrWillBeMember<const TreeScope>, RawPtrWillBeMember<Tr eeScopeEventContext>> treeScopeEventContextMap; 381 WillBeHeapHashMap<RawPtrWillBeMember<const TreeScope>, RawPtrWillBeMember<Tr eeScopeEventContext>> treeScopeEventContextMap;
143 for (const auto& treeScopeEventContext : m_treeScopeEventContexts) 382 for (const auto& treeScopeEventContext : m_treeScopeEventContexts)
144 treeScopeEventContextMap.add(&treeScopeEventContext->treeScope(), treeSc opeEventContext.get()); 383 treeScopeEventContextMap.add(&treeScopeEventContext->treeScope(), treeSc opeEventContext.get());
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 DEFINE_TRACE(EventPath) 587 DEFINE_TRACE(EventPath)
349 { 588 {
350 visitor->trace(m_nodeEventContexts); 589 visitor->trace(m_nodeEventContexts);
351 visitor->trace(m_node); 590 visitor->trace(m_node);
352 visitor->trace(m_event); 591 visitor->trace(m_event);
353 visitor->trace(m_treeScopeEventContexts); 592 visitor->trace(m_treeScopeEventContexts);
354 visitor->trace(m_windowEventContext); 593 visitor->trace(m_windowEventContext);
355 } 594 }
356 595
357 } // namespace 596 } // namespace
OLDNEW
« 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