Changeset 208641 in webkit
- Timestamp:
- Nov 11, 2016 9:03:27 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r208639 r208641 1 2016-11-11 Ryosuke Niwa <rniwa@webkit.org> 2 3 event.composedPath() does not include window 4 https://bugs.webkit.org/show_bug.cgi?id=164609 5 <rdar://problem/29210383> 6 7 Reviewed by Antti Koivisto. 8 9 Added a W3C style testharness.js test for dispatching an inside a shadow tree connected to a document. 10 11 * fast/shadow-dom/event-path-with-window-expected.txt: Added. 12 * fast/shadow-dom/event-path-with-window.html: Added. 13 * fast/shadow-dom/resources/event-path-test-helpers.js: 14 (dispatchEventWithLog): Traverse from document to window. Also include the event object in the log. 15 1 16 2016-11-11 Joseph Pecoraro <pecoraro@apple.com> 2 17 -
trunk/LayoutTests/fast/shadow-dom/resources/event-path-test-helpers.js
r200580 r208641 8 8 for (var nodeKey in shadow) { 9 9 var startingNode = shadow[nodeKey]; 10 for (var node = startingNode; node; node = node .parentNode) {10 for (var node = startingNode; node; node = node == document ? window : node.parentNode) { 11 11 if (attachedNodes.indexOf(node) >= 0) 12 12 continue; … … 26 26 target.dispatchEvent(event); 27 27 28 return {event Path: eventPath, relatedTargets: relatedTargets, pathAtTargets: pathAtTargets};28 return {event: event, eventPath: eventPath, relatedTargets: relatedTargets, pathAtTargets: pathAtTargets}; 29 29 } 30 30 -
trunk/Source/WebCore/ChangeLog
r208636 r208641 1 2016-11-11 Ryosuke Niwa <rniwa@webkit.org> 2 3 event.composedPath() does not include window 4 https://bugs.webkit.org/show_bug.cgi?id=164609 5 <rdar://problem/29210383> 6 7 Reviewed by Antti Koivisto. 8 9 Fixed the bug by including WindowContext be a part of the regular EventPath. This also simplifies 10 dispatchEventInDOM which used to had a special logic for dispatching an event on the window. 11 12 Also fixed a bug in EventDispatcher::dispatchEvent that event.target would be nullptr when an event was 13 dispatched inside a disconnected shadow tree or prevented from propagating to the document tree. 14 Preserve the final target by simply saving event.target() prior to invoking the default event handler instead. 15 16 Test: fast/shadow-dom/event-path-with-window.html 17 18 * dom/EventDispatcher.cpp: 19 (WebCore::WindowEventContext): Deleted. Moved to EventPath.cpp. 20 (WebCore::dispatchEventInDOM): Removed the code for WindowContext. The generic event dispatching logic 21 will do the same work now. 22 (WebCore::EventDispatcher::dispatchEvent): Restore the original target instead of using that of WindowContext. 23 * dom/EventPath.cpp: 24 (WebCore::WindowEventContext): Moved from EventDispatcher.cpp. Also made it a subclass of EventContext. 25 (WebCore::WindowEventContext::handleLocalEvents): Added. 26 (WebCore::EventPath::EventPath): When the parent's nullptr, check if the current node is Document. If it is, 27 follow https://dom.spec.whatwg.org/#interface-document where it says: 28 "A document’s get the parent algorithm, given an event, returns null if event’s type attribute value is 'load' 29 or document does not have a browsing context, and the document’s associated Window object otherwise." 30 (WebCore::EventPath::setRelatedTarget): Skip over WindowContext. 31 (WebCore::EventPath::retargetTouch): Ditto. 32 (WebCore::EventPath::computePathUnclosedToTarget): When the target is DOMWindow, use its document as the target. 33 Also, include any event target that is not a node in the event path. 34 1 35 2016-11-11 Dave Hyatt <hyatt@apple.com> 2 36 -
trunk/Source/WebCore/dom/EventDispatcher.cpp
r208112 r208641 40 40 namespace WebCore { 41 41 42 class WindowEventContext {43 public:44 WindowEventContext(Node*, const EventContext*);45 46 DOMWindow* window() const { return m_window.get(); }47 EventTarget* target() const { return m_target.get(); }48 bool handleLocalEvents(Event&);49 50 private:51 RefPtr<DOMWindow> m_window;52 RefPtr<EventTarget> m_target;53 };54 55 WindowEventContext::WindowEventContext(Node* node, const EventContext* topEventContext)56 {57 Node* topLevelContainer = topEventContext ? topEventContext->node() : node;58 if (!is<Document>(*topLevelContainer))59 return;60 61 m_window = downcast<Document>(*topLevelContainer).domWindow();62 m_target = topEventContext ? topEventContext->target() : node;63 }64 65 bool WindowEventContext::handleLocalEvents(Event& event)66 {67 if (!m_window)68 return false;69 70 event.setTarget(m_target.copyRef());71 event.setCurrentTarget(m_window.get());72 m_window->fireEventListeners(event);73 return true;74 }75 76 42 void EventDispatcher::dispatchScopedEvent(Node& node, Event& event) 77 43 { … … 102 68 } 103 69 104 static void dispatchEventInDOM(Event& event, const EventPath& path , WindowEventContext& windowEventContext)70 static void dispatchEventInDOM(Event& event, const EventPath& path) 105 71 { 106 72 // Trigger capturing event handlers, starting at the top and working our way down. 107 73 event.setEventPhase(Event::CAPTURING_PHASE); 108 109 // We don't dispatch load events to the window. This quirk was originally110 // added because Mozilla doesn't propagate load events to the window object.111 bool shouldFireEventAtWindow = event.type() != eventNames().loadEvent;112 if (shouldFireEventAtWindow && windowEventContext.handleLocalEvents(event) && event.propagationStopped())113 return;114 74 115 75 for (size_t i = path.size() - 1; i > 0; --i) { … … 141 101 return; 142 102 } 143 if (event.bubbles() && !event.cancelBubble()) {144 event.setEventPhase(Event::BUBBLING_PHASE);145 if (shouldFireEventAtWindow)146 windowEventContext.handleLocalEvents(event);147 }148 103 } 149 104 … … 172 127 ASSERT_WITH_SECURITY_IMPLICATION(!NoEventDispatchAssertion::isEventDispatchForbidden()); 173 128 174 WindowEventContext windowEventContext(node.get(), eventPath.lastContextIfExists());175 176 129 InputElementClickState clickHandlingState; 177 130 if (is<HTMLInputElement>(*node)) … … 180 133 if (!event.propagationStopped() && !eventPath.isEmpty()) { 181 134 event.setEventPath(eventPath); 182 dispatchEventInDOM(event, eventPath , windowEventContext);135 dispatchEventInDOM(event, eventPath); 183 136 event.clearEventPath(); 184 137 } 185 138 139 auto* finalTarget = event.target(); 186 140 event.setTarget(EventPath::eventTargetRespectingTargetRules(*node)); 187 141 event.setCurrentTarget(nullptr); … … 198 152 callDefaultEventHandlersInTheBubblingOrder(event, eventPath); 199 153 200 // Ensure that after event dispatch, the event's target object is the 201 // outermost shadow DOM boundary. 202 event.setTarget(windowEventContext.target()); 154 event.setTarget(finalTarget); 203 155 event.setCurrentTarget(nullptr); 204 156 -
trunk/Source/WebCore/dom/EventPath.cpp
r206795 r208641 22 22 #include "EventPath.h" 23 23 24 #include "DOMWindow.h" 24 25 #include "Event.h" 25 26 #include "EventContext.h" … … 32 33 33 34 namespace WebCore { 35 36 class WindowEventContext final : public EventContext { 37 public: 38 WindowEventContext(Node&, DOMWindow&, EventTarget*); 39 void handleLocalEvents(Event&) const final; 40 }; 41 42 WindowEventContext::WindowEventContext(Node& node, DOMWindow& currentTarget, EventTarget* target) 43 : EventContext(&node, ¤tTarget, target) 44 { } 45 46 void WindowEventContext::handleLocalEvents(Event& event) const 47 { 48 event.setTarget(m_target.get()); 49 event.setCurrentTarget(m_currentTarget.get()); 50 m_currentTarget->fireEventListeners(event); 51 } 34 52 35 53 static inline bool shouldEventCrossShadowBoundary(Event& event, ShadowRoot& shadowRoot, EventTarget& target) … … 109 127 110 128 ContainerNode* parent = node->parentNode(); 111 if (!parent) 129 if (UNLIKELY(!parent)) { 130 // https://dom.spec.whatwg.org/#interface-document 131 if (is<Document>(*node) && event.type() != eventNames().loadEvent) { 132 ASSERT(target); 133 if (auto* window = downcast<Document>(*node).domWindow()) 134 m_path.append(std::make_unique<WindowEventContext>(*node, *window, target)); 135 } 112 136 return; 113 114 if (ShadowRoot* shadowRootOfParent = parent->shadowRoot()) { 137 } 138 139 auto* shadowRootOfParent = parent->shadowRoot(); 140 if (UNLIKELY(shadowRootOfParent)) { 115 141 if (auto* assignedSlot = shadowRootOfParent->findAssignedSlot(*node)) { 116 142 // node is assigned to a slot. Continue dispatching the event at this slot. … … 145 171 size_t originalEventPathSize = m_path.size(); 146 172 for (unsigned contextIndex = 0; contextIndex < originalEventPathSize; contextIndex++) { 147 auto& context = downcast<MouseOrFocusEventContext>(*m_path[contextIndex]); 173 auto& ambgiousContext = *m_path[contextIndex]; 174 if (!is<MouseOrFocusEventContext>(ambgiousContext)) 175 continue; 176 auto& context = downcast<MouseOrFocusEventContext>(ambgiousContext); 148 177 149 178 Node& currentTarget = *context.node(); … … 188 217 retargeter.moveToNewTreeScope(previousTreeScope, currentTreeScope); 189 218 190 Node* currentRelatedNode = retargeter.currentNode(currentTarget); 191 downcast<TouchEventContext>(*context).touchList(touchListType)->append(touch.cloneWithNewTarget(currentRelatedNode)); 219 if (is<TouchEventContext>(*context)) { 220 Node* currentRelatedNode = retargeter.currentNode(currentTarget); 221 downcast<TouchEventContext>(*context).touchList(touchListType)->append(touch.cloneWithNewTarget(currentRelatedNode)); 222 } 192 223 193 224 previousTreeScope = ¤tTreeScope; … … 224 255 } 225 256 257 // https://dom.spec.whatwg.org/#dom-event-composedpath 226 258 Vector<EventTarget*> EventPath::computePathUnclosedToTarget(const EventTarget& target) const 227 259 { 228 260 Vector<EventTarget*> path; 229 261 const Node* targetNode = const_cast<EventTarget&>(target).toNode(); 230 if (!targetNode) 231 return path; 262 if (!targetNode) { 263 const DOMWindow* domWindow = const_cast<EventTarget&>(target).toDOMWindow(); 264 if (!domWindow) 265 return path; 266 targetNode = domWindow->document(); 267 ASSERT(targetNode); 268 } 232 269 233 270 for (auto& context : m_path) { … … 235 272 if (targetNode->isUnclosedNode(*nodeInPath)) 236 273 path.append(context->currentTarget()); 237 } 274 } else 275 path.append(context->currentTarget()); 238 276 } 239 277
Note: See TracChangeset
for help on using the changeset viewer.