Modified: trunk/Source/WebCore/ChangeLog (124290 => 124291)
--- trunk/Source/WebCore/ChangeLog 2012-08-01 03:29:31 UTC (rev 124290)
+++ trunk/Source/WebCore/ChangeLog 2012-08-01 03:41:50 UTC (rev 124291)
@@ -1,3 +1,47 @@
+2012-07-31 Hayato Ito <[email protected]>
+
+ Refactor EventDispatcher::dispatchEvent() so that we can call each phase (Caputure, Target and Bubbling) of event dispatching separately.
+ https://bugs.webkit.org/show_bug.cgi?id=92621
+
+ Reviewed by Dimitri Glazkov.
+
+ This is one of the required refactorings to support event
+ propagation for seamless iframes. I've removed 'goto' statements
+ from EventDispatcher::dispatchEvent() as a result.
+
+ I've verified that all separated functions are successfully
+ inlined. I could not see any performance regression. The
+ benchmark result is:
+
+ Before this patch:
+ % ./Tools/Scripts/run-perf-tests PerformanceTests/DOM/Events.html
+ Running 1 tests
+ Running DOM/Events.html (1 of 1)
+ RESULT DOM: Events= 243.986607143 ms
+ median= 242.297619048 ms, stdev= 5.74748351315 ms, min= 239.80952381 ms, max= 268.0 ms
+
+ After this patch:
+ % ./Tools/Scripts/run-perf-tests PerformanceTests/DOM/Events.html
+ Running 1 tests
+ Running DOM/Events.html (1 of 1)
+ RESULT DOM: Events= 242.291666667 ms
+ median= 240.452380952 ms, stdev= 5.8718643632 ms, min= 238.214285714 ms, max= 266.5 ms
+
+ No new tests, no behavior change.
+
+ * dom/EventDispatcher.cpp:
+ (WebCore::EventDispatcher::dispatchEvent):
+ (WebCore::EventDispatcher::dispatchEventPreProcess):
+ (WebCore):
+ (WebCore::EventDispatcher::dispatchEventAtCapturing):
+ (WebCore::EventDispatcher::dispatchEventAtTarget):
+ (WebCore::EventDispatcher::dispatchEventAtBubbling):
+ (WebCore::EventDispatcher::dispatchEventPostProcess):
+ (WebCore::EventDispatcher::topEventContext):
+ * dom/EventDispatcher.h:
+ (WebCore):
+ (EventDispatcher):
+
2012-07-31 Yoshifumi Inoue <[email protected]>
[Chromium] Enable ENABLE_INPUT_TYPE_TIME_MULTIPLE_FIELDS
Modified: trunk/Source/WebCore/dom/EventDispatcher.cpp (124290 => 124291)
--- trunk/Source/WebCore/dom/EventDispatcher.cpp 2012-08-01 03:29:31 UTC (rev 124290)
+++ trunk/Source/WebCore/dom/EventDispatcher.cpp 2012-08-01 03:41:50 UTC (rev 124291)
@@ -236,31 +236,47 @@
}
}
-bool EventDispatcher::dispatchEvent(PassRefPtr<Event> event)
+bool EventDispatcher::dispatchEvent(PassRefPtr<Event> prpEvent)
{
+ RefPtr<Event> event = prpEvent;
event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
-
ASSERT(!eventDispatchForbidden());
ASSERT(event->target());
ASSERT(!event->type().isNull()); // _javascript_ code can create an event with an empty name, but not null.
-
- RefPtr<EventTarget> originalTarget = event->target();
ensureEventAncestors(event.get());
+ WindowEventContext windowEventContext(event.get(), m_node.get(), topEventContext());
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowEventContext.window(), m_node.get(), m_ancestors);
- WindowEventContext windowContext(event.get(), m_node.get(), topEventContext());
+ void* preDispatchEventHandlerResult;
+ if (dispatchEventPreProcess(event, preDispatchEventHandlerResult) == ContinueDispatching)
+ if (dispatchEventAtCapturing(event, windowEventContext) == ContinueDispatching)
+ if (dispatchEventAtTarget(event) == ContinueDispatching)
+ dispatchEventAtBubbling(event, windowEventContext);
+ dispatchEventPostProcess(event, preDispatchEventHandlerResult);
- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowContext.window(), m_node.get(), m_ancestors);
+ // Ensure that after event dispatch, the event's target object is the
+ // outermost shadow DOM boundary.
+ event->setTarget(windowEventContext.target());
+ event->setCurrentTarget(0);
+ InspectorInstrumentation::didDispatchEvent(cookie);
+ return !event->defaultPrevented();
+}
+
+inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess(PassRefPtr<Event> event, void*& preDispatchEventHandlerResult)
+{
// Give the target node a chance to do some work before DOM event handlers get a crack.
- void* data = ""
- if (m_ancestors.isEmpty() || event->propagationStopped())
- goto doneDispatching;
+ preDispatchEventHandlerResult = m_node->preDispatchEventHandler(event.get());
+ return (m_ancestors.isEmpty() || event->propagationStopped()) ? DoneDispatching : ContinueDispatching;
+}
+inline EventDispatchContinuation EventDispatcher::dispatchEventAtCapturing(PassRefPtr<Event> event, WindowEventContext& windowEventContext)
+{
// Trigger capturing event handlers, starting at the top and working our way down.
event->setEventPhase(Event::CAPTURING_PHASE);
- if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
- goto doneDispatching;
+ if (windowEventContext.handleLocalEvents(event.get()) && event->propagationStopped())
+ return DoneDispatching;
for (size_t i = m_ancestors.size() - 1; i > 0; --i) {
const EventContext& eventContext = m_ancestors[i];
@@ -272,14 +288,21 @@
event->setEventPhase(Event::CAPTURING_PHASE);
eventContext.handleLocalEvents(event.get());
if (event->propagationStopped())
- goto doneDispatching;
+ return DoneDispatching;
}
+ return ContinueDispatching;
+}
+
+inline EventDispatchContinuation EventDispatcher::dispatchEventAtTarget(PassRefPtr<Event> event)
+{
event->setEventPhase(Event::AT_TARGET);
m_ancestors[0].handleLocalEvents(event.get());
- if (event->propagationStopped())
- goto doneDispatching;
+ return event->propagationStopped() ? DoneDispatching : ContinueDispatching;
+}
+inline EventDispatchContinuation EventDispatcher::dispatchEventAtBubbling(PassRefPtr<Event> event, WindowEventContext& windowContext)
+{
if (event->bubbles() && !event->cancelBubble()) {
// Trigger bubbling event handlers, starting at the bottom and working our way up.
event->setEventPhase(Event::BUBBLING_PHASE);
@@ -293,18 +316,21 @@
event->setEventPhase(Event::BUBBLING_PHASE);
eventContext.handleLocalEvents(event.get());
if (event->propagationStopped() || event->cancelBubble())
- goto doneDispatching;
+ return DoneDispatching;
}
windowContext.handleLocalEvents(event.get());
}
+ return ContinueDispatching;
+}
-doneDispatching:
- event->setTarget(originalTarget.get());
+inline void EventDispatcher::dispatchEventPostProcess(PassRefPtr<Event> event, void* preDispatchEventHandlerResult)
+{
+ event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
event->setCurrentTarget(0);
event->setEventPhase(0);
// Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
- m_node->postDispatchEventHandler(event.get(), data);
+ m_node->postDispatchEventHandler(event.get(), preDispatchEventHandlerResult);
// Call default event handlers. While the DOM does have a concept of preventing
// default handling, the detail of which handlers are called is an internal
@@ -314,7 +340,7 @@
m_node->defaultEventHandler(event.get());
ASSERT(!event->defaultPrevented());
if (event->defaultHandled())
- goto doneWithDefault;
+ return;
// For bubbling events, call default event handlers on the same targets in the
// same order as the bubbling phase.
if (event->bubbles()) {
@@ -323,20 +349,10 @@
m_ancestors[i].node()->defaultEventHandler(event.get());
ASSERT(!event->defaultPrevented());
if (event->defaultHandled())
- goto doneWithDefault;
+ return;
}
}
}
-
-doneWithDefault:
-
- // Ensure that after event dispatch, the event's target object is the
- // outermost shadow DOM boundary.
- event->setTarget(windowContext.target());
- event->setCurrentTarget(0);
- InspectorInstrumentation::didDispatchEvent(cookie);
-
- return !event->defaultPrevented();
}
const EventContext* EventDispatcher::topEventContext()
Modified: trunk/Source/WebCore/dom/EventDispatcher.h (124290 => 124291)
--- trunk/Source/WebCore/dom/EventDispatcher.h 2012-08-01 03:29:31 UTC (rev 124290)
+++ trunk/Source/WebCore/dom/EventDispatcher.h 2012-08-01 03:41:50 UTC (rev 124291)
@@ -42,12 +42,18 @@
class PlatformMouseEvent;
class ShadowRoot;
class TreeScope;
+class WindowEventContext;
enum EventDispatchBehavior {
RetargetEvent,
StayInsideShadowDOM
};
+enum EventDispatchContinuation {
+ ContinueDispatching,
+ DoneDispatching
+};
+
class EventRelatedTargetAdjuster {
public:
EventRelatedTargetAdjuster(PassRefPtr<Node>, PassRefPtr<Node> relatedTarget);
@@ -80,6 +86,12 @@
void ensureEventAncestors(Event*);
const EventContext* topEventContext();
+ EventDispatchContinuation dispatchEventPreProcess(PassRefPtr<Event>, void*& preDispatchEventHandlerResult);
+ EventDispatchContinuation dispatchEventAtCapturing(PassRefPtr<Event>, WindowEventContext&);
+ EventDispatchContinuation dispatchEventAtTarget(PassRefPtr<Event>);
+ EventDispatchContinuation dispatchEventAtBubbling(PassRefPtr<Event>, WindowEventContext&);
+ void dispatchEventPostProcess(PassRefPtr<Event>, void* preDispatchEventHandlerResult);
+
Vector<EventContext> m_ancestors;
RefPtr<Node> m_node;
RefPtr<FrameView> m_view;