⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 124291 in webkit


Ignore:
Timestamp:
Jul 31, 2012, 8:41:50 PM (14 years ago)
Author:
hayato@chromium.org
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):

Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r124290 r124291  
     12012-07-31  Hayato Ito  <hayato@chromium.org>
     2
     3        Refactor EventDispatcher::dispatchEvent() so that we can call each phase (Caputure, Target and Bubbling) of event dispatching separately.
     4        https://bugs.webkit.org/show_bug.cgi?id=92621
     5
     6        Reviewed by Dimitri Glazkov.
     7
     8        This is one of the required refactorings to support event
     9        propagation for seamless iframes.  I've removed 'goto' statements
     10        from EventDispatcher::dispatchEvent() as a result.
     11
     12        I've verified that all separated functions are successfully
     13        inlined. I could not see any performance regression.  The
     14        benchmark result is:
     15
     16        Before this patch:
     17        % ./Tools/Scripts/run-perf-tests PerformanceTests/DOM/Events.html
     18        Running 1 tests
     19        Running DOM/Events.html (1 of 1)
     20        RESULT DOM: Events= 243.986607143 ms
     21        median= 242.297619048 ms, stdev= 5.74748351315 ms, min= 239.80952381 ms, max= 268.0 ms
     22
     23        After this patch:
     24        % ./Tools/Scripts/run-perf-tests PerformanceTests/DOM/Events.html
     25        Running 1 tests
     26        Running DOM/Events.html (1 of 1)
     27        RESULT DOM: Events= 242.291666667 ms
     28        median= 240.452380952 ms, stdev= 5.8718643632 ms, min= 238.214285714 ms, max= 266.5 ms
     29
     30        No new tests, no behavior change.
     31
     32        * dom/EventDispatcher.cpp:
     33        (WebCore::EventDispatcher::dispatchEvent):
     34        (WebCore::EventDispatcher::dispatchEventPreProcess):
     35        (WebCore):
     36        (WebCore::EventDispatcher::dispatchEventAtCapturing):
     37        (WebCore::EventDispatcher::dispatchEventAtTarget):
     38        (WebCore::EventDispatcher::dispatchEventAtBubbling):
     39        (WebCore::EventDispatcher::dispatchEventPostProcess):
     40        (WebCore::EventDispatcher::topEventContext):
     41        * dom/EventDispatcher.h:
     42        (WebCore):
     43        (EventDispatcher):
     44
    1452012-07-31  Yoshifumi Inoue  <yosin@chromium.org>
    246
  • trunk/Source/WebCore/dom/EventDispatcher.cpp

    r124019 r124291  
    237237}
    238238
    239 bool EventDispatcher::dispatchEvent(PassRefPtr<Event> event)
    240 {
     239bool EventDispatcher::dispatchEvent(PassRefPtr<Event> prpEvent)
     240{
     241    RefPtr<Event> event = prpEvent;
    241242    event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
    242 
    243243    ASSERT(!eventDispatchForbidden());
    244244    ASSERT(event->target());
    245245    ASSERT(!event->type().isNull()); // JavaScript code can create an event with an empty name, but not null.
    246 
    247     RefPtr<EventTarget> originalTarget = event->target();
    248246    ensureEventAncestors(event.get());
    249 
    250     WindowEventContext windowContext(event.get(), m_node.get(), topEventContext());
    251 
    252     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowContext.window(), m_node.get(), m_ancestors);
    253 
     247    WindowEventContext windowEventContext(event.get(), m_node.get(), topEventContext());
     248    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEvent(m_node->document(), *event, windowEventContext.window(), m_node.get(), m_ancestors);
     249
     250    void* preDispatchEventHandlerResult;
     251    if (dispatchEventPreProcess(event, preDispatchEventHandlerResult) == ContinueDispatching)
     252        if (dispatchEventAtCapturing(event, windowEventContext) == ContinueDispatching)
     253            if (dispatchEventAtTarget(event) == ContinueDispatching)
     254                dispatchEventAtBubbling(event, windowEventContext);
     255    dispatchEventPostProcess(event, preDispatchEventHandlerResult);
     256
     257    // Ensure that after event dispatch, the event's target object is the
     258    // outermost shadow DOM boundary.
     259    event->setTarget(windowEventContext.target());
     260    event->setCurrentTarget(0);
     261    InspectorInstrumentation::didDispatchEvent(cookie);
     262
     263    return !event->defaultPrevented();
     264}
     265
     266inline EventDispatchContinuation EventDispatcher::dispatchEventPreProcess(PassRefPtr<Event> event, void*& preDispatchEventHandlerResult)
     267{
    254268    // Give the target node a chance to do some work before DOM event handlers get a crack.
    255     void* data = m_node->preDispatchEventHandler(event.get());
    256     if (m_ancestors.isEmpty() || event->propagationStopped())
    257         goto doneDispatching;
    258 
     269    preDispatchEventHandlerResult = m_node->preDispatchEventHandler(event.get());
     270    return (m_ancestors.isEmpty() || event->propagationStopped()) ? DoneDispatching : ContinueDispatching;
     271}
     272
     273inline EventDispatchContinuation EventDispatcher::dispatchEventAtCapturing(PassRefPtr<Event> event, WindowEventContext& windowEventContext)
     274{
    259275    // Trigger capturing event handlers, starting at the top and working our way down.
    260276    event->setEventPhase(Event::CAPTURING_PHASE);
    261277
    262     if (windowContext.handleLocalEvents(event.get()) && event->propagationStopped())
    263         goto doneDispatching;
     278    if (windowEventContext.handleLocalEvents(event.get()) && event->propagationStopped())
     279        return DoneDispatching;
    264280
    265281    for (size_t i = m_ancestors.size() - 1; i > 0; --i) {
     
    273289        eventContext.handleLocalEvents(event.get());
    274290        if (event->propagationStopped())
    275             goto doneDispatching;
    276     }
    277 
     291            return DoneDispatching;
     292    }
     293
     294    return ContinueDispatching;
     295}
     296
     297inline EventDispatchContinuation EventDispatcher::dispatchEventAtTarget(PassRefPtr<Event> event)
     298{
    278299    event->setEventPhase(Event::AT_TARGET);
    279300    m_ancestors[0].handleLocalEvents(event.get());
    280     if (event->propagationStopped())
    281         goto doneDispatching;
    282 
     301    return event->propagationStopped() ? DoneDispatching : ContinueDispatching;
     302}
     303
     304inline EventDispatchContinuation EventDispatcher::dispatchEventAtBubbling(PassRefPtr<Event> event, WindowEventContext& windowContext)
     305{
    283306    if (event->bubbles() && !event->cancelBubble()) {
    284307        // Trigger bubbling event handlers, starting at the bottom and working our way up.
     
    294317            eventContext.handleLocalEvents(event.get());
    295318            if (event->propagationStopped() || event->cancelBubble())
    296                 goto doneDispatching;
     319                return DoneDispatching;
    297320        }
    298321        windowContext.handleLocalEvents(event.get());
    299322    }
    300 
    301 doneDispatching:
    302     event->setTarget(originalTarget.get());
     323    return ContinueDispatching;
     324}
     325
     326inline void EventDispatcher::dispatchEventPostProcess(PassRefPtr<Event> event, void* preDispatchEventHandlerResult)
     327{
     328    event->setTarget(eventTargetRespectingSVGTargetRules(m_node.get()));
    303329    event->setCurrentTarget(0);
    304330    event->setEventPhase(0);
    305331
    306332    // Pass the data from the preDispatchEventHandler to the postDispatchEventHandler.
    307     m_node->postDispatchEventHandler(event.get(), data);
     333    m_node->postDispatchEventHandler(event.get(), preDispatchEventHandlerResult);
    308334
    309335    // Call default event handlers. While the DOM does have a concept of preventing
     
    315341        ASSERT(!event->defaultPrevented());
    316342        if (event->defaultHandled())
    317             goto doneWithDefault;
     343            return;
    318344        // For bubbling events, call default event handlers on the same targets in the
    319345        // same order as the bubbling phase.
     
    324350                ASSERT(!event->defaultPrevented());
    325351                if (event->defaultHandled())
    326                     goto doneWithDefault;
     352                    return;
    327353            }
    328354        }
    329355    }
    330 
    331 doneWithDefault:
    332 
    333     // Ensure that after event dispatch, the event's target object is the
    334     // outermost shadow DOM boundary.
    335     event->setTarget(windowContext.target());
    336     event->setCurrentTarget(0);
    337     InspectorInstrumentation::didDispatchEvent(cookie);
    338 
    339     return !event->defaultPrevented();
    340356}
    341357
  • trunk/Source/WebCore/dom/EventDispatcher.h

    r124019 r124291  
    4343class ShadowRoot;
    4444class TreeScope;
     45class WindowEventContext;
    4546
    4647enum EventDispatchBehavior {
    4748    RetargetEvent,
    4849    StayInsideShadowDOM
     50};
     51
     52enum EventDispatchContinuation {
     53    ContinueDispatching,
     54    DoneDispatching
    4955};
    5056
     
    8187    const EventContext* topEventContext();
    8288
     89    EventDispatchContinuation dispatchEventPreProcess(PassRefPtr<Event>, void*& preDispatchEventHandlerResult);
     90    EventDispatchContinuation dispatchEventAtCapturing(PassRefPtr<Event>, WindowEventContext&);
     91    EventDispatchContinuation dispatchEventAtTarget(PassRefPtr<Event>);
     92    EventDispatchContinuation dispatchEventAtBubbling(PassRefPtr<Event>, WindowEventContext&);
     93    void dispatchEventPostProcess(PassRefPtr<Event>, void* preDispatchEventHandlerResult);
     94
    8395    Vector<EventContext> m_ancestors;
    8496    RefPtr<Node> m_node;
Note: See TracChangeset for help on using the changeset viewer.