Changeset 143303 in webkit
- Timestamp:
- Feb 18, 2013 11:57:37 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r143301 r143303 1 2013-02-18 Hayato Ito <hayato@chromium.org> 2 3 Make EventDispatcher take an Event object in its constructor. 4 https://bugs.webkit.org/show_bug.cgi?id=109898 5 6 Reviewed by Dimitri Glazkov. 7 8 * fast/events/platform-wheelevent-with-delta-zero-crash-expected.txt: Added. 9 * fast/events/platform-wheelevent-with-delta-zero-crash.html: Added. 10 1 11 2013-02-18 Ryosuke Niwa <rniwa@webkit.org> 2 12 -
trunk/Source/WebCore/ChangeLog
r143300 r143303 1 2013-02-18 Hayato Ito <hayato@chromium.org> 2 3 Make EventDispatcher take an Event object in its constructor. 4 https://bugs.webkit.org/show_bug.cgi?id=109898 5 6 Reviewed by Dimitri Glazkov. 7 8 Re-landing r143145, which caused a crash when deltaX and deltaY of a PlatformWheelEvent are both zero. 9 10 Fixed a crash by early exiting in EventDispatcher::dispatchEvent(Node*, PassRefPtr<EventDispatcher*>) 11 if mediator's event() returns null. 12 13 Also Added a layout test to catch this kind of crash in the future. 14 15 Test: fast/events/platform-wheelevent-with-delta-zero-crash.html 16 17 * dom/EventDispatchMediator.cpp: 18 (WebCore::EventDispatchMediator::dispatchEvent): 19 * dom/EventDispatcher.cpp: 20 (WebCore::EventDispatcher::dispatchEvent): 21 (WebCore::EventDispatcher::EventDispatcher): 22 (WebCore::EventDispatcher::ensureEventPath): 23 (WebCore::EventDispatcher::dispatchSimulatedClick): 24 (WebCore::EventDispatcher::dispatch): 25 (WebCore::EventDispatcher::dispatchEventPreProcess): 26 (WebCore::EventDispatcher::dispatchEventAtCapturing): 27 (WebCore::EventDispatcher::dispatchEventAtTarget): 28 (WebCore::EventDispatcher::dispatchEventAtBubbling): 29 (WebCore::EventDispatcher::dispatchEventPostProcess): 30 * dom/EventDispatcher.h: 31 (EventDispatcher): 32 (WebCore::EventDispatcher::node): 33 (WebCore::EventDispatcher::event): 34 * dom/FocusEvent.cpp: 35 (WebCore::FocusEventDispatchMediator::dispatchEvent): 36 (WebCore::BlurEventDispatchMediator::dispatchEvent): 37 (WebCore::FocusInEventDispatchMediator::dispatchEvent): 38 (WebCore::FocusOutEventDispatchMediator::dispatchEvent): 39 * dom/GestureEvent.cpp: 40 (WebCore::GestureEventDispatchMediator::dispatchEvent): 41 * dom/MouseEvent.cpp: 42 (WebCore::MouseEventDispatchMediator::dispatchEvent): 43 * dom/WheelEvent.cpp: 44 (WebCore::WheelEventDispatchMediator::dispatchEvent): 45 Assert event() rather than an early exit since this code path should be hit only when event() is non-null. 46 1 47 2013-02-18 Takashi Sakamoto <tasak@google.com> 2 48 -
trunk/Source/WebCore/dom/EventDispatchMediator.cpp
r143244 r143303 51 51 bool EventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const 52 52 { 53 return dispatcher->dispatchEvent(m_event.get()); 53 ASSERT(m_event.get() == dispatcher->event()); 54 return dispatcher->dispatch(); 54 55 } 55 56 -
trunk/Source/WebCore/dom/EventDispatcher.cpp
r143244 r143303 51 51 { 52 52 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); 53 54 EventDispatcher dispatcher(node); 53 if (!mediator->event()) 54 return true; 55 EventDispatcher dispatcher(node, mediator->event()); 55 56 return mediator->dispatchEvent(&dispatcher); 56 57 } 57 58 58 EventDispatcher::EventDispatcher(Node* node )59 EventDispatcher::EventDispatcher(Node* node, PassRefPtr<Event> event) 59 60 : m_node(node) 61 , m_event(event) 60 62 , m_eventPathInitialized(false) 61 63 #ifndef NDEBUG … … 64 66 { 65 67 ASSERT(node); 68 ASSERT(m_event.get()); 69 ASSERT(!m_event->type().isNull()); // JavaScript code can create an event with an empty name, but not null. 66 70 m_view = node->document()->view(); 67 71 } 68 72 69 EventPath& EventDispatcher::ensureEventPath( Event* event)73 EventPath& EventDispatcher::ensureEventPath() 70 74 { 71 75 if (m_eventPathInitialized) 72 76 return m_eventPath; 73 77 m_eventPathInitialized = true; 74 EventRetargeter::calculateEventPath(m_node.get(), event, m_eventPath);78 EventRetargeter::calculateEventPath(m_node.get(), m_event.get(), m_eventPath); 75 79 return m_eventPath; 76 80 } … … 96 100 97 101 if (mouseEventOptions == SendMouseOverUpDownEvents) 98 EventDispatcher(node ).dispatchEvent(SimulatedMouseEvent::create(eventNames().mouseoverEvent, node->document()->defaultView(), underlyingEvent));102 EventDispatcher(node, SimulatedMouseEvent::create(eventNames().mouseoverEvent, node->document()->defaultView(), underlyingEvent)).dispatch(); 99 103 100 104 if (mouseEventOptions != SendNoEvents) 101 EventDispatcher(node ).dispatchEvent(SimulatedMouseEvent::create(eventNames().mousedownEvent, node->document()->defaultView(), underlyingEvent));105 EventDispatcher(node, SimulatedMouseEvent::create(eventNames().mousedownEvent, node->document()->defaultView(), underlyingEvent)).dispatch(); 102 106 node->setActive(true, visualOptions == ShowPressedLook); 103 107 if (mouseEventOptions != SendNoEvents) 104 EventDispatcher(node ).dispatchEvent(SimulatedMouseEvent::create(eventNames().mouseupEvent, node->document()->defaultView(), underlyingEvent));108 EventDispatcher(node, SimulatedMouseEvent::create(eventNames().mouseupEvent, node->document()->defaultView(), underlyingEvent)).dispatch(); 105 109 node->setActive(false); 106 110 107 111 // always send click 108 EventDispatcher(node ).dispatchEvent(SimulatedMouseEvent::create(eventNames().clickEvent, node->document()->defaultView(), underlyingEvent));112 EventDispatcher(node, SimulatedMouseEvent::create(eventNames().clickEvent, node->document()->defaultView(), underlyingEvent)).dispatch(); 109 113 110 114 gNodesDispatchingSimulatedClicks->remove(node); 111 115 } 112 116 113 bool EventDispatcher::dispatch Event(PassRefPtr<Event> prpEvent)117 bool EventDispatcher::dispatch() 114 118 { 115 119 #ifndef NDEBUG … … 117 121 m_eventDispatched = true; 118 122 #endif 119 RefPtr<Event> event = prpEvent;120 123 ChildNodesLazySnapshot::takeChildNodesLazySnapshot(); 121 124 122 event->setTarget(EventRetargeter::eventTargetRespectingTargetRules(m_node.get()));125 m_event->setTarget(EventRetargeter::eventTargetRespectingTargetRules(m_node.get())); 123 126 ASSERT(!NoEventDispatchAssertion::isEventDispatchForbidden()); 124 ASSERT(event->target()); 125 ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null. 126 ensureEventPath(event.get()); 127 WindowEventContext windowEventContext(event.get(), m_node.get(), topEventContext()); 128 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowEventContext.window(), m_node.get(), m_eventPath); 127 ASSERT(m_event->target()); 128 ensureEventPath(); 129 WindowEventContext windowEventContext(m_event.get(), m_node.get(), topEventContext()); 130 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *m_event, windowEventContext.window(), m_node.get(), m_eventPath); 129 131 130 132 void* preDispatchEventHandlerResult; 131 if (dispatchEventPreProcess( event,preDispatchEventHandlerResult) == ContinueDispatching)132 if (dispatchEventAtCapturing( event,windowEventContext) == ContinueDispatching)133 if (dispatchEventAtTarget( event) == ContinueDispatching)134 dispatchEventAtBubbling( event,windowEventContext);135 dispatchEventPostProcess( event,preDispatchEventHandlerResult);133 if (dispatchEventPreProcess(preDispatchEventHandlerResult) == ContinueDispatching) 134 if (dispatchEventAtCapturing(windowEventContext) == ContinueDispatching) 135 if (dispatchEventAtTarget() == ContinueDispatching) 136 dispatchEventAtBubbling(windowEventContext); 137 dispatchEventPostProcess(preDispatchEventHandlerResult); 136 138 137 139 // Ensure that after event dispatch, the event's target object is the 138 140 // outermost shadow DOM boundary. 139 event->setTarget(windowEventContext.target());140 event->setCurrentTarget(0);141 m_event->setTarget(windowEventContext.target()); 142 m_event->setCurrentTarget(0); 141 143 InspectorInstrumentation::didDispatchEvent(cookie); 142 144 143 return ! event->defaultPrevented();144 } 145 146 inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess( PassRefPtr<Event> event,void*& preDispatchEventHandlerResult)145 return !m_event->defaultPrevented(); 146 } 147 148 inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess(void*& preDispatchEventHandlerResult) 147 149 { 148 150 // Give the target node a chance to do some work before DOM event handlers get a crack. 149 preDispatchEventHandlerResult = m_node->preDispatchEventHandler( event.get());150 return (m_eventPath.isEmpty() || event->propagationStopped()) ? DoneDispatching : ContinueDispatching;151 } 152 153 inline EventDispatchContinuation EventDispatcher::dispatchEventAtCapturing( PassRefPtr<Event> event,WindowEventContext& windowEventContext)151 preDispatchEventHandlerResult = m_node->preDispatchEventHandler(m_event.get()); 152 return (m_eventPath.isEmpty() || m_event->propagationStopped()) ? DoneDispatching : ContinueDispatching; 153 } 154 155 inline EventDispatchContinuation EventDispatcher::dispatchEventAtCapturing(WindowEventContext& windowEventContext) 154 156 { 155 157 // Trigger capturing event handlers, starting at the top and working our way down. 156 event->setEventPhase(Event::CAPTURING_PHASE);157 158 if (windowEventContext.handleLocalEvents( event.get()) &&event->propagationStopped())158 m_event->setEventPhase(Event::CAPTURING_PHASE); 159 160 if (windowEventContext.handleLocalEvents(m_event.get()) && m_event->propagationStopped()) 159 161 return DoneDispatching; 160 162 … … 162 164 const EventContext& eventContext = *m_eventPath[i]; 163 165 if (eventContext.currentTargetSameAsTarget()) { 164 if ( event->bubbles())166 if (m_event->bubbles()) 165 167 continue; 166 event->setEventPhase(Event::AT_TARGET);168 m_event->setEventPhase(Event::AT_TARGET); 167 169 } else 168 event->setEventPhase(Event::CAPTURING_PHASE);169 eventContext.handleLocalEvents( event.get());170 if ( event->propagationStopped())170 m_event->setEventPhase(Event::CAPTURING_PHASE); 171 eventContext.handleLocalEvents(m_event.get()); 172 if (m_event->propagationStopped()) 171 173 return DoneDispatching; 172 174 } … … 175 177 } 176 178 177 inline EventDispatchContinuation EventDispatcher::dispatchEventAtTarget( PassRefPtr<Event> event)178 { 179 event->setEventPhase(Event::AT_TARGET);180 m_eventPath[0]->handleLocalEvents( event.get());181 return event->propagationStopped() ? DoneDispatching : ContinueDispatching;182 } 183 184 inline EventDispatchContinuation EventDispatcher::dispatchEventAtBubbling( PassRefPtr<Event> event,WindowEventContext& windowContext)185 { 186 if ( event->bubbles() && !event->cancelBubble()) {179 inline EventDispatchContinuation EventDispatcher::dispatchEventAtTarget() 180 { 181 m_event->setEventPhase(Event::AT_TARGET); 182 m_eventPath[0]->handleLocalEvents(m_event.get()); 183 return m_event->propagationStopped() ? DoneDispatching : ContinueDispatching; 184 } 185 186 inline EventDispatchContinuation EventDispatcher::dispatchEventAtBubbling(WindowEventContext& windowContext) 187 { 188 if (m_event->bubbles() && !m_event->cancelBubble()) { 187 189 // Trigger bubbling event handlers, starting at the bottom and working our way up. 188 event->setEventPhase(Event::BUBBLING_PHASE);190 m_event->setEventPhase(Event::BUBBLING_PHASE); 189 191 190 192 size_t size = m_eventPath.size(); … … 192 194 const EventContext& eventContext = *m_eventPath[i]; 193 195 if (eventContext.currentTargetSameAsTarget()) 194 event->setEventPhase(Event::AT_TARGET);196 m_event->setEventPhase(Event::AT_TARGET); 195 197 else 196 event->setEventPhase(Event::BUBBLING_PHASE);197 eventContext.handleLocalEvents( event.get());198 if ( event->propagationStopped() ||event->cancelBubble())198 m_event->setEventPhase(Event::BUBBLING_PHASE); 199 eventContext.handleLocalEvents(m_event.get()); 200 if (m_event->propagationStopped() || m_event->cancelBubble()) 199 201 return DoneDispatching; 200 202 } 201 windowContext.handleLocalEvents( event.get());203 windowContext.handleLocalEvents(m_event.get()); 202 204 } 203 205 return ContinueDispatching; 204 206 } 205 207 206 inline void EventDispatcher::dispatchEventPostProcess( PassRefPtr<Event> event,void* preDispatchEventHandlerResult)207 { 208 event->setTarget(EventRetargeter::eventTargetRespectingTargetRules(m_node.get()));209 event->setCurrentTarget(0);210 event->setEventPhase(0);208 inline void EventDispatcher::dispatchEventPostProcess(void* preDispatchEventHandlerResult) 209 { 210 m_event->setTarget(EventRetargeter::eventTargetRespectingTargetRules(m_node.get())); 211 m_event->setCurrentTarget(0); 212 m_event->setEventPhase(0); 211 213 212 214 // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler. 213 m_node->postDispatchEventHandler( event.get(), preDispatchEventHandlerResult);215 m_node->postDispatchEventHandler(m_event.get(), preDispatchEventHandlerResult); 214 216 215 217 // Call default event handlers. While the DOM does have a concept of preventing 216 218 // default handling, the detail of which handlers are called is an internal 217 219 // implementation detail and not part of the DOM. 218 if (! event->defaultPrevented() && !event->defaultHandled()) {220 if (!m_event->defaultPrevented() && !m_event->defaultHandled()) { 219 221 // Non-bubbling events call only one default event handler, the one for the target. 220 m_node->defaultEventHandler( event.get());221 ASSERT(! event->defaultPrevented());222 if ( event->defaultHandled())222 m_node->defaultEventHandler(m_event.get()); 223 ASSERT(!m_event->defaultPrevented()); 224 if (m_event->defaultHandled()) 223 225 return; 224 226 // For bubbling events, call default event handlers on the same targets in the 225 227 // same order as the bubbling phase. 226 if ( event->bubbles()) {228 if (m_event->bubbles()) { 227 229 size_t size = m_eventPath.size(); 228 230 for (size_t i = 1; i < size; ++i) { 229 m_eventPath[i]->node()->defaultEventHandler( event.get());230 ASSERT(! event->defaultPrevented());231 if ( event->defaultHandled())231 m_eventPath[i]->node()->defaultEventHandler(m_event.get()); 232 ASSERT(!m_event->defaultPrevented()); 233 if (m_event->defaultHandled()) 232 234 return; 233 235 } -
trunk/Source/WebCore/dom/EventDispatcher.h
r143244 r143303 31 31 #include <wtf/Forward.h> 32 32 #include <wtf/HashMap.h> 33 #include <wtf/PassRefPtr.h> 33 34 #include <wtf/Vector.h> 34 35 … … 58 59 static void dispatchSimulatedClick(Node*, Event* underlyingEvent, SimulatedClickMouseEventOptions, SimulatedClickVisualOptions); 59 60 60 bool dispatchEvent(PassRefPtr<Event>); 61 Node* node() const; 62 EventPath& ensureEventPath(Event*); 61 bool dispatch(); 62 Node* node() const { return m_node.get(); } 63 Event* event() const { return m_event.get(); } 64 EventPath& ensureEventPath(); 63 65 64 66 private: 65 EventDispatcher(Node* );67 EventDispatcher(Node*, PassRefPtr<Event>); 66 68 const EventContext* topEventContext(); 67 69 68 EventDispatchContinuation dispatchEventPreProcess( PassRefPtr<Event>,void*& preDispatchEventHandlerResult);69 EventDispatchContinuation dispatchEventAtCapturing( PassRefPtr<Event>,WindowEventContext&);70 EventDispatchContinuation dispatchEventAtTarget( PassRefPtr<Event>);71 EventDispatchContinuation dispatchEventAtBubbling( PassRefPtr<Event>,WindowEventContext&);72 void dispatchEventPostProcess( PassRefPtr<Event>,void* preDispatchEventHandlerResult);70 EventDispatchContinuation dispatchEventPreProcess(void*& preDispatchEventHandlerResult); 71 EventDispatchContinuation dispatchEventAtCapturing(WindowEventContext&); 72 EventDispatchContinuation dispatchEventAtTarget(); 73 EventDispatchContinuation dispatchEventAtBubbling(WindowEventContext&); 74 void dispatchEventPostProcess(void* preDispatchEventHandlerResult); 73 75 74 76 EventPath m_eventPath; 75 77 RefPtr<Node> m_node; 78 RefPtr<Event> m_event; 76 79 RefPtr<FrameView> m_view; 77 80 bool m_eventPathInitialized; … … 81 84 }; 82 85 83 inline Node* EventDispatcher::node() const84 {85 return m_node.get();86 }87 88 86 } 89 87 -
trunk/Source/WebCore/dom/FocusEvent.cpp
r143244 r143303 78 78 bool FocusEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const 79 79 { 80 EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath( event()));80 EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath()); 81 81 return EventDispatchMediator::dispatchEvent(dispatcher); 82 82 } … … 94 94 bool BlurEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const 95 95 { 96 EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath( event()));96 EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath()); 97 97 return EventDispatchMediator::dispatchEvent(dispatcher); 98 98 } … … 110 110 bool FocusInEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const 111 111 { 112 EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath( event()));112 EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath()); 113 113 return EventDispatchMediator::dispatchEvent(dispatcher); 114 114 } … … 126 126 bool FocusOutEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const 127 127 { 128 EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath( event()));128 EventRetargeter::adjustForFocusEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath()); 129 129 return EventDispatchMediator::dispatchEvent(dispatcher); 130 130 } -
trunk/Source/WebCore/dom/GestureEvent.cpp
r143244 r143303 123 123 return true; 124 124 125 dispatcher->dispatch Event(event());125 dispatcher->dispatch(); 126 126 ASSERT(!event()->defaultPrevented()); 127 127 return event()->defaultHandled() || event()->defaultPrevented(); -
trunk/Source/WebCore/dom/MouseEvent.cpp
r143244 r143303 263 263 { 264 264 if (isSyntheticMouseEvent()) { 265 EventRetargeter::adjustForMouseEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath( event()));266 return dispatcher->dispatch Event(event());265 EventRetargeter::adjustForMouseEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath()); 266 return dispatcher->dispatch(); 267 267 } 268 268 … … 276 276 277 277 EventTarget* relatedTarget = event()->relatedTarget(); 278 EventRetargeter::adjustForMouseEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath( event()));279 280 dispatcher->dispatch Event(event());278 EventRetargeter::adjustForMouseEvent(dispatcher->node(), *event(), dispatcher->ensureEventPath()); 279 280 dispatcher->dispatch(); 281 281 bool swallowEvent = event()->defaultHandled() || event()->defaultPrevented(); 282 282 -
trunk/Source/WebCore/dom/WheelEvent.cpp
r141826 r143303 139 139 bool WheelEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const 140 140 { 141 if (!event()) 142 return true; 143 141 ASSERT(event()); 144 142 return EventDispatchMediator::dispatchEvent(dispatcher) && !event()->defaultHandled(); 145 143 }
Note: See TracChangeset
for help on using the changeset viewer.