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

Changeset 273477 in webkit


Ignore:
Timestamp:
Feb 25, 2021, 12:30:59 AM (6 years ago)
Author:
rniwa@webkit.org
Message:

Avoid heap allocation for EventContexts
https://bugs.webkit.org/show_bug.cgi?id=222095
<rdar://problem/74586915>

Reviewed by Simon Fraser.

This patch merges all subclasses of EventContext into itself to avoid heap allocation for each
EventContext in EventPath::m_path. It also merges Node::handleLocalEvents into EventContext's
handleLocalEvents to avoid the extra virtual function call.

No new tests since there should be no observable behavioral differences.

  • dom/EventContext.cpp:

(WebCore::EventContext::EventContext): Moved to the header to be inlined.
(WebCore::EventContext::handleLocalEvents const): Merged handleLocalEvents of HTMLFormElement
and Node. Moved the code to handle related target and touch targets from MouseOrFocusEventContext
and TouchEventContext as they have been merged into this class. Also special case dispatching
an event on window to preserve the behavior of WindowEventContext.
(WebCore::EventContext::initializeTouchLists): Added. Creates TouchList objects.
(WebCore::EventContext::isUnreachableNode const): Moved from the header.
(WebCore::EventContext::isMouseOrFocusEventContext const): Deleted.
(WebCore::EventContext::isTouchEventContext const): Deleted.
(WebCore::MouseOrFocusEventContext::MouseOrFocusEventContext): Deleted.
(WebCore::MouseOrFocusEventContext::handleLocalEvents const): Deleted.
(WebCore::MouseOrFocusEventContext::isMouseOrFocusEventContext const): Deleted.
(WebCore::TouchEventContext::TouchEventContext): Deleted.
(WebCore::TouchEventContext::handleLocalEvents const): Deleted.
(WebCore::TouchEventContext::isTouchEventContext const): Deleted.
(WebCore::TouchEventContext::checkReachability const): Deleted. Merged into handleLocalEvents.

  • dom/EventContext.h:

(WebCore::EventContext::isMouseOrFocusEventContext const): Now simply checks m_type.
(WebCore::EventContext::isTouchEventContext const): Ditto.
(WebCore::EventContext::isWindowContext const): Ditto.
(WebCore::EventContext::relatedTarget const): Moved from MouseOrFocusEventContext.
(WebCore::EventContext::setRelatedTarget): Ditto.
(WebCore::EventContext::touchList): Moved from TouchEventContext.
(WebCore::m_contextNodeIsFormElement): Added. Caching this state here instead of checking it at
every event context during dispatching in EventContext::handleLocalEvents seems to be important
to get a speed up in Intel processors. Apple silicons don't seem to be affected by this.
(WebCore::m_type): Added.
(WebCore::MouseOrFocusEventContext): Deleted.
(WebCore::MouseOrFocusEventContext::relatedTarget const): Deleted.
(WebCore::TouchEventContext): Deleted.
(WebCore::EventContext::EventContext): Moved from cpp file to be inlined here.
(WebCore::EventContext::isUnreachableNode const): Moved into cpp as this is only used for
asserting shadow DOM related conditions.
(WebCore::EventContext::touchList): Renamed from TouchEventContext::touchList.
(isType): Deleted.

  • dom/EventDispatcher.cpp:

(WebCore::EventDispatcher::dispatchEvent): Deleted the variant that takes a vector of elements
since it's not used anywhere.

  • dom/EventDispatcher.h:
  • dom/EventPath.cpp:

(WebCore::WindowEventContext): Deleted.
(WebCore::EventPath::EventPath): Avoid calling setRelatedTarget if related target is not a node
or the path is empty. These were early return conditions in setRelatedTarget before this patch.
(WebCore::EventPath::buildPath): Always create EventContext. Dramatically simplifies the code.
(WebCore::EventPath::setRelatedTarget): Moved the early exit to EventPath::EventPath.
(WebCore::EventPath::retargetTouch):
(WebCore::EventPath::retargetTouchList):
(WebCore::EventPath::retargetTouchLists):
(WebCore::EventPath::EventPath): Deleted the variant which takes a vector of elements as it's
not used anywhere.

  • dom/EventPath.h:

(WebCore::EventPath::contextAt const):
(WebCore::EventPath::contextAt):
(WebCore::EventPath::m_path): Now allocates EventContext in place. The size of the inline buffer
has been reduced to 16 entries for EventContext from 32 entries for std::unique_ptr<EventContext>
since the former is considerably larger than the latter.

  • dom/Node.cpp:

(WebCore::Node::handleLocalEvents): Deleted. Merged into EventContext::handleLocalEvents.

  • dom/Node.h:
  • html/HTMLFormElement.cpp:

(WebCore::HTMLFormElement::handleLocalEvents): Ditto.

  • html/HTMLFormElement.h:
Location:
trunk/Source/WebCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r273474 r273477  
     12021-02-25  Ryosuke Niwa  <rniwa@webkit.org>
     2
     3        Avoid heap allocation for EventContexts
     4        https://bugs.webkit.org/show_bug.cgi?id=222095
     5        <rdar://problem/74586915>
     6
     7        Reviewed by Simon Fraser.
     8
     9        This patch merges all subclasses of EventContext into itself to avoid heap allocation for each
     10        EventContext in EventPath::m_path. It also merges Node::handleLocalEvents into EventContext's
     11        handleLocalEvents to avoid the extra virtual function call.
     12
     13        No new tests since there should be no observable behavioral differences.
     14
     15        * dom/EventContext.cpp:
     16        (WebCore::EventContext::EventContext): Moved to the header to be inlined.
     17        (WebCore::EventContext::handleLocalEvents const): Merged handleLocalEvents of HTMLFormElement
     18        and Node. Moved the code to handle related target and touch targets from MouseOrFocusEventContext
     19        and TouchEventContext as they have been merged into this class. Also special case dispatching
     20        an event on window to preserve the behavior of WindowEventContext.
     21        (WebCore::EventContext::initializeTouchLists): Added. Creates TouchList objects.
     22        (WebCore::EventContext::isUnreachableNode const): Moved from the header.
     23        (WebCore::EventContext::isMouseOrFocusEventContext const): Deleted.
     24        (WebCore::EventContext::isTouchEventContext const): Deleted.
     25        (WebCore::MouseOrFocusEventContext::MouseOrFocusEventContext): Deleted.
     26        (WebCore::MouseOrFocusEventContext::handleLocalEvents const): Deleted.
     27        (WebCore::MouseOrFocusEventContext::isMouseOrFocusEventContext const): Deleted.
     28        (WebCore::TouchEventContext::TouchEventContext): Deleted.
     29        (WebCore::TouchEventContext::handleLocalEvents const): Deleted.
     30        (WebCore::TouchEventContext::isTouchEventContext const): Deleted.
     31        (WebCore::TouchEventContext::checkReachability const): Deleted. Merged into handleLocalEvents.
     32        * dom/EventContext.h:
     33        (WebCore::EventContext::isMouseOrFocusEventContext const): Now simply checks m_type.
     34        (WebCore::EventContext::isTouchEventContext const): Ditto.
     35        (WebCore::EventContext::isWindowContext const): Ditto.
     36        (WebCore::EventContext::relatedTarget const): Moved from MouseOrFocusEventContext.
     37        (WebCore::EventContext::setRelatedTarget): Ditto.
     38        (WebCore::EventContext::touchList): Moved from TouchEventContext.
     39        (WebCore::m_contextNodeIsFormElement): Added. Caching this state here instead of checking it at
     40        every event context during dispatching in EventContext::handleLocalEvents seems to be important
     41        to get a speed up in Intel processors. Apple silicons don't seem to be affected by this.
     42        (WebCore::m_type): Added.
     43        (WebCore::MouseOrFocusEventContext): Deleted.
     44        (WebCore::MouseOrFocusEventContext::relatedTarget const): Deleted.
     45        (WebCore::TouchEventContext): Deleted.
     46        (WebCore::EventContext::EventContext): Moved from cpp file to be inlined here.
     47        (WebCore::EventContext::isUnreachableNode const): Moved into cpp as this is only used for
     48        asserting shadow DOM related conditions.
     49        (WebCore::EventContext::touchList): Renamed from TouchEventContext::touchList.
     50        (isType): Deleted.
     51        * dom/EventDispatcher.cpp:
     52        (WebCore::EventDispatcher::dispatchEvent): Deleted the variant that takes a vector of elements
     53        since it's not used anywhere.
     54        * dom/EventDispatcher.h:
     55        * dom/EventPath.cpp:
     56        (WebCore::WindowEventContext): Deleted.
     57        (WebCore::EventPath::EventPath): Avoid calling setRelatedTarget if related target is not a node
     58        or the path is empty. These were early return conditions in setRelatedTarget before this patch.
     59        (WebCore::EventPath::buildPath): Always create EventContext. Dramatically simplifies the code.
     60        (WebCore::EventPath::setRelatedTarget): Moved the early exit to EventPath::EventPath.
     61        (WebCore::EventPath::retargetTouch):
     62        (WebCore::EventPath::retargetTouchList):
     63        (WebCore::EventPath::retargetTouchLists):
     64        (WebCore::EventPath::EventPath): Deleted the variant which takes a vector of elements as it's
     65        not used anywhere.
     66        * dom/EventPath.h:
     67        (WebCore::EventPath::contextAt const):
     68        (WebCore::EventPath::contextAt):
     69        (WebCore::EventPath::m_path): Now allocates EventContext in place. The size of the inline buffer
     70        has been reduced to 16 entries for EventContext from 32 entries for std::unique_ptr<EventContext>
     71        since the former is considerably larger than the latter.
     72        * dom/Node.cpp:
     73        (WebCore::Node::handleLocalEvents): Deleted. Merged into EventContext::handleLocalEvents.
     74        * dom/Node.h:
     75        * html/HTMLFormElement.cpp:
     76        (WebCore::HTMLFormElement::handleLocalEvents): Ditto.
     77        * html/HTMLFormElement.h:
     78
    1792021-02-24  Ryosuke Niwa  <rniwa@webkit.org>
    280
  • trunk/Source/WebCore/dom/EventContext.cpp

    r269546 r273477  
    2929#include "EventContext.h"
    3030
     31#include "DOMWindow.h"
    3132#include "Document.h"
    3233#include "FocusEvent.h"
     34#include "HTMLFormElement.h"
    3335#include "MouseEvent.h"
    3436#include "TouchEvent.h"
    3537
    3638namespace WebCore {
    37 
    38 EventContext::EventContext(Node* node, EventTarget* currentTarget, EventTarget* target, int closedShadowDepth)
    39     : m_node { node }
    40     , m_currentTarget { currentTarget }
    41     , m_target { target }
    42     , m_closedShadowDepth { closedShadowDepth }
    43     , m_currentTargetIsInShadowTree { is<Node>(currentTarget) && downcast<Node>(*currentTarget).isInShadowTree() }
    44 {
    45     ASSERT(!isUnreachableNode(m_target.get()));
    46 }
    4739
    4840EventContext::~EventContext() = default;
     
    5244    event.setTarget(m_target.get());
    5345    event.setCurrentTarget(m_currentTarget.get(), m_currentTargetIsInShadowTree);
    54     // FIXME: Consider merging handleLocalEvents and fireEventListeners.
    55     if (m_node)
    56         m_node->handleLocalEvents(event, phase);
    57     else
     46
     47    if (m_relatedTarget) {
     48        ASSERT(m_type == Type::MouseOrFocus);
     49        event.setRelatedTarget(m_relatedTarget.get());
     50    }
     51
     52#if ENABLE(TOUCH_EVENTS)
     53    if (m_type == Type::Touch) {
     54
     55#if ASSERT_ENABLED
     56        auto checkReachability = [&](const Ref<TouchList>& touchList) {
     57            size_t length = touchList->length();
     58            for (size_t i = 0; i < length; ++i)
     59                ASSERT(!isUnreachableNode(downcast<Node>(touchList->item(i)->target())));
     60        }
     61        checkReachability(m_touches);
     62        checkReachability(m_targetTouches);
     63        checkReachability(m_changedTouches);
     64#endif
     65
     66        auto& touchEvent = downcast<TouchEvent>(event);
     67        touchEvent.setTouches(m_touches.get());
     68        touchEvent.setTargetTouches(m_targetTouches.get());
     69        touchEvent.setChangedTouches(m_changedTouches.get());
     70    }
     71#endif
     72
     73    if (!m_node || UNLIKELY(m_type == Type::Window)) {
    5874        m_currentTarget->fireEventListeners(event, phase);
    59 }
     75        return;
     76    }
    6077
    61 bool EventContext::isMouseOrFocusEventContext() const
    62 {
    63     return false;
    64 }
     78    if (UNLIKELY(m_contextNodeIsFormElement)) {
     79        ASSERT(is<HTMLFormElement>(*m_node));
     80        if ((event.type() == eventNames().submitEvent || event.type() == eventNames().resetEvent)
     81            && event.eventPhase() != Event::CAPTURING_PHASE && event.target() != m_node && is<Node>(event.target())) {
     82            event.stopPropagation();
     83            return;
     84        }
     85    }
    6586
    66 bool EventContext::isTouchEventContext() const
    67 {
    68     return false;
    69 }
     87    if (!m_node->hasEventTargetData())
     88        return;
    7089
    71 MouseOrFocusEventContext::MouseOrFocusEventContext(Node& node, EventTarget* currentTarget, EventTarget* target, int closedShadowDepth)
    72     : EventContext(&node, currentTarget, target, closedShadowDepth)
    73 {
    74 }
     90    // FIXME: Should we deliver wheel events to disabled form controls or not?
     91    if (event.isTrusted() && is<Element>(m_node) && downcast<Element>(*m_node).isDisabledFormControl() && event.isMouseEvent() && !event.isWheelEvent())
     92        return;
    7593
    76 MouseOrFocusEventContext::~MouseOrFocusEventContext() = default;
    77 
    78 void MouseOrFocusEventContext::handleLocalEvents(Event& event, EventInvokePhase phase) const
    79 {
    80     if (m_relatedTarget)
    81         event.setRelatedTarget(m_relatedTarget.get());
    82     EventContext::handleLocalEvents(event, phase);
    83 }
    84 
    85 bool MouseOrFocusEventContext::isMouseOrFocusEventContext() const
    86 {
    87     return true;
     94    m_node->fireEventListeners(event, phase);
    8895}
    8996
    9097#if ENABLE(TOUCH_EVENTS)
    9198
    92 TouchEventContext::TouchEventContext(Node& node, EventTarget* currentTarget, EventTarget* target, int closedShadowDepth)
    93     : EventContext(&node, currentTarget, target, closedShadowDepth)
    94     , m_touches(TouchList::create())
    95     , m_targetTouches(TouchList::create())
    96     , m_changedTouches(TouchList::create())
     99void EventContext::initializeTouchLists()
    97100{
     101    m_touches = TouchList::create();
     102    m_targetTouches = TouchList::create();
     103    m_changedTouches = TouchList::create();
    98104}
    99105
    100 TouchEventContext::~TouchEventContext() = default;
    101 
    102 void TouchEventContext::handleLocalEvents(Event& event, EventInvokePhase phase) const
    103 {
    104     checkReachability(m_touches);
    105     checkReachability(m_targetTouches);
    106     checkReachability(m_changedTouches);
    107     auto& touchEvent = downcast<TouchEvent>(event);
    108     touchEvent.setTouches(m_touches.ptr());
    109     touchEvent.setTargetTouches(m_targetTouches.ptr());
    110     touchEvent.setChangedTouches(m_changedTouches.ptr());
    111     EventContext::handleLocalEvents(event, phase);
    112 }
    113 
    114 bool TouchEventContext::isTouchEventContext() const
    115 {
    116     return true;
    117 }
     106#endif // ENABLE(TOUCH_EVENTS)
    118107
    119108#if ASSERT_ENABLED
    120109
    121 void TouchEventContext::checkReachability(const Ref<TouchList>& touchList) const
     110bool EventContext::isUnreachableNode(EventTarget* target) const
    122111{
    123     size_t length = touchList->length();
    124     for (size_t i = 0; i < length; ++i)
    125         ASSERT(!isUnreachableNode(downcast<Node>(touchList->item(i)->target())));
     112    // FIXME: Checks also for SVG elements.
     113    return is<Node>(target) && !downcast<Node>(*target).isSVGElement() && m_node->isClosedShadowHidden(downcast<Node>(*target));
    126114}
    127115
    128 #endif // ASSERT_ENABLED
    129 
    130 #endif // ENABLE(TOUCH_EVENTS)
     116#endif
    131117
    132118}
  • trunk/Source/WebCore/dom/EventContext.h

    r269546 r273477  
    2828#pragma once
    2929
    30 #include "Node.h"
     30#include "HTMLFormElement.h"
    3131
    3232namespace WebCore {
     
    3939    using EventInvokePhase = EventTarget::EventInvokePhase;
    4040
    41     EventContext(Node*, EventTarget* currentTarget, EventTarget*, int closedShadowDepth);
    42     virtual ~EventContext();
     41    enum class Type : uint8_t {
     42        Normal = 0,
     43        MouseOrFocus,
     44        Touch,
     45        Window,
     46    };
     47
     48    EventContext(Type, Node*, EventTarget* currentTarget, EventTarget* origin, int closedShadowDepth);
     49    EventContext(Type, Node&, Node* currentTarget, EventTarget* origin, int closedShadowDepth);
     50    ~EventContext();
    4351
    4452    Node* node() const { return m_node.get(); }
     
    4856    int closedShadowDepth() const { return m_closedShadowDepth; }
    4957
    50     virtual void handleLocalEvents(Event&, EventInvokePhase) const;
     58    void handleLocalEvents(Event&, EventInvokePhase) const;
    5159
    52     virtual bool isMouseOrFocusEventContext() const;
    53     virtual bool isTouchEventContext() const;
     60    bool isMouseOrFocusEventContext() const { return m_type == Type::MouseOrFocus; }
     61    bool isTouchEventContext() const { return m_type == Type::Touch; }
     62    bool isWindowContext() const { return m_type == Type::Window; }
    5463
    55     virtual Node* relatedTarget() const { return nullptr; }
     64    Node* relatedTarget() const { return m_relatedTarget.get(); }
     65    void setRelatedTarget(Node*);
    5666
    57 protected:
     67#if ENABLE(TOUCH_EVENTS)
     68    enum TouchListType { Touches, TargetTouches, ChangedTouches };
     69    TouchList& touchList(TouchListType);
     70#endif
     71
     72private:
     73    inline EventContext(Type, Node* currentNode, RefPtr<EventTarget>&& currentTarget, EventTarget* origin, int closedShadowDepth, bool currentTargetIsInShadowTree = false);
     74
     75#if ENABLE(TOUCH_EVENTS)
     76    void initializeTouchLists();
     77#endif
     78
    5879#if ASSERT_ENABLED
    5980    bool isUnreachableNode(EventTarget*) const;
     
    6384    RefPtr<EventTarget> m_currentTarget;
    6485    RefPtr<EventTarget> m_target;
     86    RefPtr<Node> m_relatedTarget;
     87#if ENABLE(TOUCH_EVENTS)
     88    RefPtr<TouchList> m_touches;
     89    RefPtr<TouchList> m_targetTouches;
     90    RefPtr<TouchList> m_changedTouches;
     91#endif
    6592    int m_closedShadowDepth { 0 };
    6693    bool m_currentTargetIsInShadowTree { false };
     94    bool m_contextNodeIsFormElement { false };
     95    Type m_type { Type::Normal };
    6796};
    6897
    69 class MouseOrFocusEventContext final : public EventContext {
    70 public:
    71     MouseOrFocusEventContext(Node&, EventTarget* currentTarget, EventTarget*, int closedShadowDepth);
    72     virtual ~MouseOrFocusEventContext();
    73 
    74     Node* relatedTarget() const final { return m_relatedTarget.get(); }
    75     void setRelatedTarget(Node*);
    76 
    77 private:
    78     void handleLocalEvents(Event&, EventInvokePhase) const final;
    79     bool isMouseOrFocusEventContext() const final;
    80 
    81     RefPtr<Node> m_relatedTarget;
    82 };
    83 
     98inline EventContext::EventContext(Type type, Node* node, RefPtr<EventTarget>&& currentTarget, EventTarget* origin, int closedShadowDepth, bool currentTargetIsInShadowTree)
     99    : m_node { node }
     100    , m_currentTarget { WTFMove(currentTarget) }
     101    , m_target { origin }
     102    , m_closedShadowDepth { closedShadowDepth }
     103    , m_currentTargetIsInShadowTree { currentTargetIsInShadowTree }
     104    , m_type { type }
     105{
     106    ASSERT(!isUnreachableNode(m_target.get()));
    84107#if ENABLE(TOUCH_EVENTS)
    85 
    86 class TouchEventContext final : public EventContext {
    87 public:
    88     TouchEventContext(Node&, EventTarget* currentTarget, EventTarget*, int closedShadowDepth);
    89     virtual ~TouchEventContext();
    90 
    91     enum TouchListType { Touches, TargetTouches, ChangedTouches };
    92     TouchList& touchList(TouchListType);
    93 
    94 private:
    95     void handleLocalEvents(Event&, EventInvokePhase) const final;
    96     bool isTouchEventContext() const final;
    97 
    98     void checkReachability(const Ref<TouchList>&) const;
    99 
    100     Ref<TouchList> m_touches;
    101     Ref<TouchList> m_targetTouches;
    102     Ref<TouchList> m_changedTouches;
    103 };
    104 
    105 #endif // ENABLE(TOUCH_EVENTS)
    106 
    107 #if ASSERT_ENABLED
    108 
    109 inline bool EventContext::isUnreachableNode(EventTarget* target) const
    110 {
    111     // FIXME: Checks also for SVG elements.
    112     return is<Node>(target) && !downcast<Node>(*target).isSVGElement() && m_node->isClosedShadowHidden(downcast<Node>(*target));
     108    if (m_type == Type::Touch)
     109        initializeTouchLists();
     110#else
     111    ASSERT(m_type != Type::Touch);
     112#endif
    113113}
    114114
    115 #endif
     115inline EventContext::EventContext(Type type, Node* node, EventTarget* currentTarget, EventTarget* origin, int closedShadowDepth)
     116    : EventContext(type, node, makeRefPtr(currentTarget), origin, closedShadowDepth)
     117{
     118    ASSERT(!is<Node>(currentTarget));
     119}
    116120
    117 inline void MouseOrFocusEventContext::setRelatedTarget(Node* relatedTarget)
     121// This variant avoids calling EventTarget::ref() which is a virtual function call.
     122inline EventContext::EventContext(Type type, Node& node, Node* currentTarget, EventTarget* origin, int closedShadowDepth)
     123    : EventContext(type, &node, makeRefPtr(currentTarget), origin, closedShadowDepth, currentTarget && currentTarget->isInShadowTree())
     124{
     125    m_contextNodeIsFormElement = is<HTMLFormElement>(node);
     126}
     127
     128inline void EventContext::setRelatedTarget(Node* relatedTarget)
    118129{
    119130    ASSERT(!isUnreachableNode(relatedTarget));
     
    123134#if ENABLE(TOUCH_EVENTS)
    124135
    125 inline TouchList& TouchEventContext::touchList(TouchListType type)
     136inline TouchList& EventContext::touchList(TouchListType type)
    126137{
    127138    switch (type) {
    128139    case Touches:
    129         return m_touches.get();
     140        return *m_touches;
    130141    case TargetTouches:
    131         return m_targetTouches.get();
     142        return *m_targetTouches;
    132143    case ChangedTouches:
    133         return m_changedTouches.get();
     144        return *m_changedTouches;
    134145    }
    135146    ASSERT_NOT_REACHED();
    136     return m_touches.get();
    137 }
    138 
    139 #endif
    140 
    141 #if ENABLE(TOUCH_EVENTS) && !ASSERT_ENABLED
    142 
    143 inline void TouchEventContext::checkReachability(const Ref<TouchList>&) const
    144 {
     147    return *m_touches;
    145148}
    146149
     
    148151
    149152} // namespace WebCore
    150 
    151 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::MouseOrFocusEventContext)
    152 static bool isType(const WebCore::EventContext& context) { return context.isMouseOrFocusEventContext(); }
    153 SPECIALIZE_TYPE_TRAITS_END()
    154 
    155 #if ENABLE(TOUCH_EVENTS)
    156 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::TouchEventContext)
    157 static bool isType(const WebCore::EventContext& context) { return context.isTouchEventContext(); }
    158 SPECIALIZE_TYPE_TRAITS_END()
    159 #endif
  • trunk/Source/WebCore/dom/EventDispatcher.cpp

    r269789 r273477  
    231231}
    232232
    233 void EventDispatcher::dispatchEvent(const Vector<Element*>& targets, Event& event)
    234 {
    235     dispatchEventWithType<Element>(targets, event);
    236 }
    237 
    238 }
     233}
  • trunk/Source/WebCore/dom/EventDispatcher.h

    r228827 r273477  
    3434void dispatchEvent(Node&, Event&);
    3535void dispatchEvent(const Vector<EventTarget*>&, Event&);
    36 void dispatchEvent(const Vector<Element*>&, Event&);
    3736
    3837void dispatchScopedEvent(Node&, Event&);
  • trunk/Source/WebCore/dom/EventPath.cpp

    r269500 r273477  
    3636namespace WebCore {
    3737
    38 class WindowEventContext final : public EventContext {
    39 public:
    40     WindowEventContext(Node&, DOMWindow&, EventTarget&, int closedShadowDepth);
    41 private:
    42     void handleLocalEvents(Event&, EventInvokePhase) const final;
    43 };
    44 
    45 inline WindowEventContext::WindowEventContext(Node& node, DOMWindow& currentTarget, EventTarget& target, int closedShadowDepth)
    46     : EventContext(&node, &currentTarget, &target, closedShadowDepth)
    47 {
    48 }
    49 
    50 void WindowEventContext::handleLocalEvents(Event& event, EventInvokePhase phase) const
    51 {
    52     event.setTarget(m_target.get());
    53     event.setCurrentTarget(m_currentTarget.get(), m_currentTargetIsInShadowTree);
    54     m_currentTarget->fireEventListeners(event, phase);
    55 }
    56 
    5738static inline bool shouldEventCrossShadowBoundary(Event& event, ShadowRoot& shadowRoot, EventTarget& target)
    5839{
     
    10384    buildPath(originalTarget, event);
    10485
    105     if (auto* relatedTarget = event.relatedTarget())
    106         setRelatedTarget(originalTarget, *relatedTarget);
     86    if (auto* relatedTarget = event.relatedTarget(); is<Node>(relatedTarget) && !m_path.isEmpty())
     87        setRelatedTarget(originalTarget, downcast<Node>(*relatedTarget));
    10788
    10889#if ENABLE(TOUCH_EVENTS)
     
    11495void EventPath::buildPath(Node& originalTarget, Event& event)
    11596{
    116     using MakeEventContext = std::unique_ptr<EventContext> (*)(Node&, EventTarget*, EventTarget*, int closedShadowDepth);
    117     MakeEventContext makeEventContext = [] (Node& node, EventTarget* currentTarget, EventTarget* target, int closedShadowDepth) {
    118         return makeUnique<EventContext>(&node, currentTarget, target, closedShadowDepth);
    119     };
    120     if (is<MouseEvent>(event) || event.isFocusEvent()) {
    121         makeEventContext = [] (Node& node, EventTarget* currentTarget, EventTarget* target, int closedShadowDepth) -> std::unique_ptr<EventContext> {
    122             return makeUnique<MouseOrFocusEventContext>(node, currentTarget, target, closedShadowDepth);
    123         };
    124     }
     97    EventContext::Type contextType = [&]() {
     98        if (is<MouseEvent>(event) || event.isFocusEvent())
     99            return EventContext::Type::MouseOrFocus;
    125100#if ENABLE(TOUCH_EVENTS)
    126     if (is<TouchEvent>(event)) {
    127         makeEventContext = [] (Node& node, EventTarget* currentTarget, EventTarget* target, int closedShadowDepth) -> std::unique_ptr<EventContext> {
    128             return makeUnique<TouchEventContext>(node, currentTarget, target, closedShadowDepth);
    129         };
    130     }
     101        if (is<TouchEvent>(event))
     102            return EventContext::Type::Touch;
    131103#endif
     104        return EventContext::Type::Normal;
     105    }();
    132106
    133107    Node* node = nodeOrHostIfPseudoElement(&originalTarget);
     
    138112    while (node) {
    139113        while (node) {
    140             m_path.append(makeEventContext(*node, eventTargetRespectingTargetRules(*node), target, closedShadowDepth));
     114            m_path.append(EventContext { contextType, *node, eventTargetRespectingTargetRules(*node), target, closedShadowDepth });
    141115
    142116            if (is<ShadowRoot>(*node))
     
    150124                    if (target) {
    151125                        if (auto* window = downcast<Document>(*node).domWindow())
    152                             m_path.append(makeUnique<WindowEventContext>(*node, *window, *target, closedShadowDepth));
     126                            m_path.append(EventContext { EventContext::Type::Window, node, window, target, closedShadowDepth });
    153127                    }
    154128                }
     
    156130            }
    157131
    158             auto* shadowRootOfParent = parent->shadowRoot();
    159             if (UNLIKELY(shadowRootOfParent)) {
     132            if (auto* shadowRootOfParent = parent->shadowRoot(); UNLIKELY(shadowRootOfParent)) {
    160133                if (auto* assignedSlot = shadowRootOfParent->findAssignedSlot(*node)) {
    161134                    if (shadowRootOfParent->mode() != ShadowRootMode::Open)
     
    180153}
    181154
    182 void EventPath::setRelatedTarget(Node& origin, EventTarget& relatedTarget)
    183 {
    184     if (!is<Node>(relatedTarget) || m_path.isEmpty())
    185         return;
    186 
    187     auto& relatedNode = downcast<Node>(relatedTarget);
    188     RelatedNodeRetargeter retargeter(relatedNode, *m_path[0]->node());
     155void EventPath::setRelatedTarget(Node& origin, Node& relatedNode)
     156{
     157    RelatedNodeRetargeter retargeter(relatedNode, *m_path[0].node());
    189158
    190159    bool originIsRelatedTarget = &origin == &relatedNode;
     
    193162    size_t originalEventPathSize = m_path.size();
    194163    for (unsigned contextIndex = 0; contextIndex < originalEventPathSize; contextIndex++) {
    195         auto& ambgiousContext = *m_path[contextIndex];
    196         if (!is<MouseOrFocusEventContext>(ambgiousContext))
     164        auto& context = m_path[contextIndex];
     165        if (!context.isMouseOrFocusEventContext()) {
     166            ASSERT(context.isWindowContext());
    197167            continue;
    198         auto& context = downcast<MouseOrFocusEventContext>(ambgiousContext);
     168        }
    199169
    200170        Node& currentTarget = *context.node();
     
    222192#if ENABLE(TOUCH_EVENTS)
    223193
    224 void EventPath::retargetTouch(TouchEventContext::TouchListType type, const Touch& touch)
     194void EventPath::retargetTouch(EventContext::TouchListType type, const Touch& touch)
    225195{
    226196    auto* eventTarget = touch.target();
     
    228198        return;
    229199
    230     RelatedNodeRetargeter retargeter(downcast<Node>(*eventTarget), *m_path[0]->node());
     200    RelatedNodeRetargeter retargeter(downcast<Node>(*eventTarget), *m_path[0].node());
    231201    TreeScope* previousTreeScope = nullptr;
    232202    for (auto& context : m_path) {
    233         Node& currentTarget = *context->node();
     203        Node& currentTarget = *context.node();
    234204        TreeScope& currentTreeScope = currentTarget.treeScope();
    235205        if (UNLIKELY(previousTreeScope && &currentTreeScope != previousTreeScope))
    236206            retargeter.moveToNewTreeScope(previousTreeScope, currentTreeScope);
    237207
    238         if (is<TouchEventContext>(*context)) {
     208        if (context.isTouchEventContext()) {
    239209            Node* currentRelatedNode = retargeter.currentNode(currentTarget);
    240             downcast<TouchEventContext>(*context).touchList(type).append(touch.cloneWithNewTarget(currentRelatedNode));
    241         }
     210            context.touchList(type).append(touch.cloneWithNewTarget(currentRelatedNode));
     211        } else
     212            ASSERT(context.isWindowContext());
    242213
    243214        previousTreeScope = &currentTreeScope;
     
    245216}
    246217
    247 void EventPath::retargetTouchList(TouchEventContext::TouchListType type, const TouchList* list)
     218void EventPath::retargetTouchList(EventContext::TouchListType type, const TouchList* list)
    248219{
    249220    for (unsigned i = 0, length = list ? list->length() : 0; i < length; ++i)
     
    253224void EventPath::retargetTouchLists(const TouchEvent& event)
    254225{
    255     retargetTouchList(TouchEventContext::Touches, event.touches());
    256     retargetTouchList(TouchEventContext::TargetTouches, event.targetTouches());
    257     retargetTouchList(TouchEventContext::ChangedTouches, event.changedTouches());
     226    retargetTouchList(EventContext::TouchListType::Touches, event.touches());
     227    retargetTouchList(EventContext::TouchListType::TargetTouches, event.targetTouches());
     228    retargetTouchList(EventContext::TouchListType::ChangedTouches, event.changedTouches());
    258229}
    259230
     
    272243
    273244    auto currentTargetIndex = m_path.findMatching([&target] (auto& context) {
    274         return context->currentTarget() == &target;
     245        return context.currentTarget() == &target;
    275246    });
    276247    RELEASE_ASSERT(currentTargetIndex != notFound);
    277     auto currentTargetDepth = m_path[currentTargetIndex]->closedShadowDepth();
     248    auto currentTargetDepth = m_path[currentTargetIndex].closedShadowDepth();
    278249
    279250    auto appendTargetWithLesserDepth = [&path] (const EventContext& currentContext, int& currentDepthAllowed) {
     
    291262    auto i = currentTargetIndex;
    292263    do {
    293         appendTargetWithLesserDepth(*m_path[i], currentDepthAllowed);
     264        appendTargetWithLesserDepth(m_path[i], currentDepthAllowed);
    294265    } while (i--);
    295266    path.reverse();
     
    297268    currentDepthAllowed = currentTargetDepth;
    298269    for (auto i = currentTargetIndex + 1; i < pathSize; ++i)
    299         appendTargetWithLesserDepth(*m_path[i], currentDepthAllowed);
    300    
     270        appendTargetWithLesserDepth(m_path[i], currentDepthAllowed);
     271
    301272    return path;
    302 }
    303 
    304 EventPath::EventPath(const Vector<Element*>& targets)
    305 {
    306     // FIXME: This function seems wrong. Why are we not firing events in the closed shadow trees?
    307     for (auto* target : targets) {
    308         ASSERT(target);
    309         Node* origin = *targets.begin();
    310         if (!target->isClosedShadowHidden(*origin))
    311             m_path.append(makeUnique<EventContext>(target, target, origin, 0));
    312     }
    313273}
    314274
     
    318278        ASSERT(target);
    319279        ASSERT(!is<Node>(target));
    320         m_path.append(makeUnique<EventContext>(nullptr, target, *targets.begin(), 0));
     280        m_path.append(EventContext { EventContext::Type::Normal, nullptr, target, *targets.begin(), 0 });
    321281    }
    322282}
  • trunk/Source/WebCore/dom/EventPath.h

    r253923 r273477  
    3636    EventPath(Node& origin, Event&);
    3737    explicit EventPath(const Vector<EventTarget*>&);
    38     explicit EventPath(const Vector<Element*>&);
    3938
    4039    bool isEmpty() const { return m_path.isEmpty(); }
    4140    size_t size() const { return m_path.size(); }
    42     const EventContext& contextAt(size_t i) const { return *m_path[i]; }
    43     EventContext& contextAt(size_t i) { return *m_path[i]; }
     41    const EventContext& contextAt(size_t i) const { return m_path[i]; }
     42    EventContext& contextAt(size_t i) { return m_path[i]; }
    4443
    4544    Vector<EventTarget*> computePathUnclosedToTarget(const EventTarget&) const;
     
    4948private:
    5049    void buildPath(Node& origin, Event&);
    51     void setRelatedTarget(Node& origin, EventTarget&);
     50    void setRelatedTarget(Node& origin, Node&);
    5251
    5352#if ENABLE(TOUCH_EVENTS)
    54     void retargetTouch(TouchEventContext::TouchListType, const Touch&);
    55     void retargetTouchList(TouchEventContext::TouchListType, const TouchList*);
     53    void retargetTouch(EventContext::TouchListType, const Touch&);
     54    void retargetTouchList(EventContext::TouchListType, const TouchList*);
    5655    void retargetTouchLists(const TouchEvent&);
    5756#endif
    5857
    59     Vector<std::unique_ptr<EventContext>, 32> m_path;
     58    Vector<EventContext, 16> m_path;
    6059};
    6160
  • trunk/Source/WebCore/dom/Node.cpp

    r271806 r273477  
    23652365}
    23662366
    2367 void Node::handleLocalEvents(Event& event, EventInvokePhase phase)
    2368 {
    2369     if (!hasEventTargetData())
    2370         return;
    2371 
    2372     // FIXME: Should we deliver wheel events to disabled form controls or not?
    2373     if (is<Element>(*this) && downcast<Element>(*this).isDisabledFormControl() && event.isTrusted() && event.isMouseEvent() && !event.isWheelEvent())
    2374         return;
    2375 
    2376     fireEventListeners(event, phase);
    2377 }
    2378 
    23792367void Node::dispatchScopedEvent(Event& event)
    23802368{
  • trunk/Source/WebCore/dom/Node.h

    r273474 r273477  
    454454    void dispatchScopedEvent(Event&);
    455455
    456     virtual void handleLocalEvents(Event&, EventInvokePhase);
    457 
    458456    void dispatchSubtreeModifiedEvent();
    459457    void dispatchDOMActivateEvent(Event& underlyingClickEvent);
  • trunk/Source/WebCore/html/HTMLFormElement.cpp

    r270931 r273477  
    150150}
    151151
    152 void HTMLFormElement::handleLocalEvents(Event& event, EventInvokePhase phase)
    153 {
    154     if (event.eventPhase() != Event::CAPTURING_PHASE && is<Node>(event.target()) && event.target() != this && (event.type() == eventNames().submitEvent || event.type() == eventNames().resetEvent)) {
    155         event.stopPropagation();
    156         return;
    157     }
    158     HTMLElement::handleLocalEvents(event, phase);
    159 }
    160 
    161152unsigned HTMLFormElement::length() const
    162153{
  • trunk/Source/WebCore/html/HTMLFormElement.h

    r259513 r273477  
    132132    void finishParsingChildren() final;
    133133
    134     void handleLocalEvents(Event&, EventInvokePhase) final;
    135 
    136134    void parseAttribute(const QualifiedName&, const AtomString&) final;
    137135    bool isURLAttribute(const Attribute&) const final;
Note: See TracChangeset for help on using the changeset viewer.