Title: [124291] trunk/Source/WebCore
Revision
124291
Author
[email protected]
Date
2012-07-31 20:41:50 -0700 (Tue, 31 Jul 2012)

Log Message

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):

Modified Paths

Diff

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;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to