WebKit Bugzilla
Attachment 349621 Details for
Bug 174288
: Capturing event listeners are called during bubbling phase for shadow hosts
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP2
wip174288b.patch (text/plain), 13.62 KB, created by
Ryosuke Niwa
on 2018-09-12 20:49:22 PDT
(
hide
)
Description:
WIP2
Filename:
MIME Type:
Creator:
Ryosuke Niwa
Created:
2018-09-12 20:49:22 PDT
Size:
13.62 KB
patch
obsolete
>Index: Source/WebCore/dom/EventContext.cpp >=================================================================== >--- Source/WebCore/dom/EventContext.cpp (revision 235963) >+++ Source/WebCore/dom/EventContext.cpp (working copy) >@@ -45,15 +45,15 @@ > > EventContext::~EventContext() = default; > >-void EventContext::handleLocalEvents(Event& event) const >+void EventContext::handleLocalEvents(Event& event, EventInvokePhase phase) const > { > event.setTarget(m_target.get()); > event.setCurrentTarget(m_currentTarget.get()); > // FIXME: Consider merging handleLocalEvents and fireEventListeners. > if (m_node) >- m_node->handleLocalEvents(event); >+ m_node->handleLocalEvents(event, phase); > else >- m_currentTarget->fireEventListeners(event); >+ m_currentTarget->fireEventListeners(event, phase); > } > > bool EventContext::isMouseOrFocusEventContext() const >@@ -73,11 +73,11 @@ > > MouseOrFocusEventContext::~MouseOrFocusEventContext() = default; > >-void MouseOrFocusEventContext::handleLocalEvents(Event& event) const >+void MouseOrFocusEventContext::handleLocalEvents(Event& event, EventInvokePhase phase) const > { > if (m_relatedTarget) > event.setRelatedTarget(*m_relatedTarget); >- EventContext::handleLocalEvents(event); >+ EventContext::handleLocalEvents(event, phase); > } > > bool MouseOrFocusEventContext::isMouseOrFocusEventContext() const >@@ -97,7 +97,7 @@ > > TouchEventContext::~TouchEventContext() = default; > >-void TouchEventContext::handleLocalEvents(Event& event) const >+void TouchEventContext::handleLocalEvents(Event& event, EventInvokePhase phase) const > { > checkReachability(m_touches); > checkReachability(m_targetTouches); >@@ -106,7 +106,7 @@ > touchEvent.setTouches(m_touches.ptr()); > touchEvent.setTargetTouches(m_targetTouches.ptr()); > touchEvent.setChangedTouches(m_changedTouches.ptr()); >- EventContext::handleLocalEvents(event); >+ EventContext::handleLocalEvents(event, phase); > } > > bool TouchEventContext::isTouchEventContext() const >Index: Source/WebCore/dom/EventContext.h >=================================================================== >--- Source/WebCore/dom/EventContext.h (revision 235963) >+++ Source/WebCore/dom/EventContext.h (working copy) >@@ -36,6 +36,8 @@ > class EventContext { > WTF_MAKE_FAST_ALLOCATED; > public: >+ using EventInvokePhase = EventTarget::EventInvokePhase; >+ > EventContext(Node*, EventTarget* currentTarget, EventTarget*); > virtual ~EventContext(); > >@@ -43,7 +45,7 @@ > EventTarget* currentTarget() const { return m_currentTarget.get(); } > EventTarget* target() const { return m_target.get(); } > >- virtual void handleLocalEvents(Event&) const; >+ virtual void handleLocalEvents(Event&, EventInvokePhase) const; > > virtual bool isMouseOrFocusEventContext() const; > virtual bool isTouchEventContext() const; >@@ -67,7 +69,7 @@ > void setRelatedTarget(Node*); > > private: >- void handleLocalEvents(Event&) const final; >+ void handleLocalEvents(Event&, EventInvokePhase) const final; > bool isMouseOrFocusEventContext() const final; > > RefPtr<Node> m_relatedTarget; >@@ -84,7 +86,7 @@ > TouchList& touchList(TouchListType); > > private: >- void handleLocalEvents(Event&) const final; >+ void handleLocalEvents(Event&, EventInvokePhase) const final; > bool isTouchEventContext() const final; > > void checkReachability(const Ref<TouchList>&) const; >Index: Source/WebCore/dom/EventDispatcher.cpp >=================================================================== >--- Source/WebCore/dom/EventDispatcher.cpp (revision 235963) >+++ Source/WebCore/dom/EventDispatcher.cpp (working copy) >@@ -75,26 +75,21 @@ > > static void dispatchEventInDOM(Event& event, const EventPath& path) > { >- // Trigger capturing event handlers, starting at the top and working our way down. >- event.setEventPhase(Event::CAPTURING_PHASE); >- >- for (size_t i = path.size() - 1; i > 0; --i) { >- const EventContext& eventContext = path.contextAt(i); >+ // Invoke capturing event listeners in the reverse order. >+ for (size_t i = path.size(); i > 0; --i) { >+ const EventContext& eventContext = path.contextAt(i - 1); > if (eventContext.currentTarget() == eventContext.target()) >- continue; >- eventContext.handleLocalEvents(event); >+ event.setEventPhase(Event::AT_TARGET); >+ else >+ event.setEventPhase(Event::CAPTURING_PHASE); >+ eventContext.handleLocalEvents(event, EventTarget::EventInvokePhase::Capturing); > if (event.propagationStopped()) > return; > } > >- event.setEventPhase(Event::AT_TARGET); >- path.contextAt(0).handleLocalEvents(event); >- if (event.propagationStopped()) >- return; >- >- // Trigger bubbling event handlers, starting at the bottom and working our way up. >+ // Invoke bubbling event listeners. > size_t size = path.size(); >- for (size_t i = 1; i < size; ++i) { >+ for (size_t i = 0; i < size; ++i) { > const EventContext& eventContext = path.contextAt(i); > if (eventContext.currentTarget() == eventContext.target()) > event.setEventPhase(Event::AT_TARGET); >@@ -102,7 +97,7 @@ > event.setEventPhase(Event::BUBBLING_PHASE); > else > continue; >- eventContext.handleLocalEvents(event); >+ eventContext.handleLocalEvents(event, EventTarget::EventInvokePhase::Bubbling); > if (event.propagationStopped()) > return; > } >Index: Source/WebCore/dom/EventPath.cpp >=================================================================== >--- Source/WebCore/dom/EventPath.cpp (revision 235963) >+++ Source/WebCore/dom/EventPath.cpp (working copy) >@@ -37,7 +37,7 @@ > public: > WindowEventContext(Node&, DOMWindow&, EventTarget&); > private: >- void handleLocalEvents(Event&) const final; >+ void handleLocalEvents(Event&, EventInvokePhase) const final; > }; > > inline WindowEventContext::WindowEventContext(Node& node, DOMWindow& currentTarget, EventTarget& target) >@@ -45,11 +45,11 @@ > { > } > >-void WindowEventContext::handleLocalEvents(Event& event) const >+void WindowEventContext::handleLocalEvents(Event& event, EventInvokePhase phase) const > { > event.setTarget(m_target.get()); > event.setCurrentTarget(m_currentTarget.get()); >- m_currentTarget->fireEventListeners(event); >+ m_currentTarget->fireEventListeners(event, phase); > } > > static inline bool shouldEventCrossShadowBoundary(Event& event, ShadowRoot& shadowRoot, EventTarget& target) >Index: Source/WebCore/dom/EventTarget.cpp >=================================================================== >--- Source/WebCore/dom/EventTarget.cpp (revision 235963) >+++ Source/WebCore/dom/EventTarget.cpp (working copy) >@@ -183,6 +183,7 @@ > > void EventTarget::dispatchEvent(Event& event) > { >+ // FIXME: We should always use EventDispatcher. > ASSERT(event.isInitialized()); > ASSERT(!event.isBeingDispatched()); > >@@ -190,7 +191,8 @@ > event.setCurrentTarget(this); > event.setEventPhase(Event::AT_TARGET); > event.resetBeforeDispatch(); >- fireEventListeners(event); >+ fireEventListeners(event, EventInvokePhase::Capturing); >+ fireEventListeners(event, EventInvokePhase::Bubbling); > event.resetAfterDispatch(); > } > >@@ -219,7 +221,8 @@ > return nullAtom(); > } > >-void EventTarget::fireEventListeners(Event& event) >+// https://dom.spec.whatwg.org/#concept-event-listener-invoke >+void EventTarget::fireEventListeners(Event& event, EventInvokePhase phase) > { > ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::isEventAllowedInMainThread()); > ASSERT(event.isInitialized()); >@@ -231,7 +234,7 @@ > SetForScope<bool> firingEventListenersScope(data->isFiringEventListeners, true); > > if (auto* listenersVector = data->eventListenerMap.find(event.type())) { >- fireEventListeners(event, *listenersVector); >+ innerInvokeEventListeners(event, *listenersVector, phase); > return; > } > >@@ -244,7 +247,7 @@ > if (auto* legacyListenersVector = data->eventListenerMap.find(legacyTypeName)) { > AtomicString typeName = event.type(); > event.setType(legacyTypeName); >- fireEventListeners(event, *legacyListenersVector); >+ innerInvokeEventListeners(event, *legacyListenersVector, phase); > event.setType(typeName); > } > } >@@ -252,7 +255,8 @@ > > // Intentionally creates a copy of the listeners vector to avoid event listeners added after this point from being run. > // Note that removal still has an effect due to the removed field in RegisteredEventListener. >-void EventTarget::fireEventListeners(Event& event, EventListenerVector listeners) >+// https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke >+void EventTarget::innerInvokeEventListeners(Event& event, EventListenerVector listeners, EventInvokePhase phase) > { > Ref<EventTarget> protectedThis(*this); > ASSERT(!listeners.isEmpty()); >@@ -268,9 +272,9 @@ > if (UNLIKELY(registeredListener->wasRemoved())) > continue; > >- if (event.eventPhase() == Event::CAPTURING_PHASE && !registeredListener->useCapture()) >+ if (phase == EventInvokePhase::Capturing && !registeredListener->useCapture()) > continue; >- if (event.eventPhase() == Event::BUBBLING_PHASE && registeredListener->useCapture()) >+ if (phase == EventInvokePhase::Bubbling && registeredListener->useCapture()) > continue; > > if (InspectorInstrumentation::isEventListenerDisabled(*this, event.type(), registeredListener->callback(), registeredListener->useCapture())) >Index: Source/WebCore/dom/EventTarget.h >=================================================================== >--- Source/WebCore/dom/EventTarget.h (revision 235963) >+++ Source/WebCore/dom/EventTarget.h (working copy) >@@ -102,7 +102,8 @@ > bool hasActiveEventListeners(const AtomicString& eventType) const; > const EventListenerVector& eventListeners(const AtomicString& eventType); > >- void fireEventListeners(Event&); >+ enum class EventInvokePhase { Capturing, Bubbling }; >+ void fireEventListeners(Event&, EventInvokePhase); > bool isFiringEventListeners() const; > > void visitJSEventListeners(JSC::SlotVisitor&); >@@ -120,7 +121,7 @@ > virtual void refEventTarget() = 0; > virtual void derefEventTarget() = 0; > >- void fireEventListeners(Event&, EventListenerVector); >+ void innerInvokeEventListeners(Event&, EventListenerVector, EventInvokePhase); > > friend class EventListenerIterator; > }; >Index: Source/WebCore/dom/Node.cpp >=================================================================== >--- Source/WebCore/dom/Node.cpp (revision 235963) >+++ Source/WebCore/dom/Node.cpp (working copy) >@@ -2307,7 +2307,7 @@ > } > } > >-void Node::handleLocalEvents(Event& event) >+void Node::handleLocalEvents(Event& event, EventInvokePhase phase) > { > if (!hasEventTargetData()) > return; >@@ -2316,7 +2316,7 @@ > if (is<Element>(*this) && downcast<Element>(*this).isDisabledFormControl() && event.isMouseEvent() && !event.isWheelEvent()) > return; > >- fireEventListeners(event); >+ fireEventListeners(event, phase); > } > > void Node::dispatchScopedEvent(Event& event) >Index: Source/WebCore/dom/Node.h >=================================================================== >--- Source/WebCore/dom/Node.h (revision 235963) >+++ Source/WebCore/dom/Node.h (working copy) >@@ -486,7 +486,7 @@ > > void dispatchScopedEvent(Event&); > >- virtual void handleLocalEvents(Event&); >+ virtual void handleLocalEvents(Event&, EventInvokePhase); > > void dispatchSubtreeModifiedEvent(); > void dispatchDOMActivateEvent(Event& underlyingClickEvent); >Index: Source/WebCore/html/HTMLFormElement.cpp >=================================================================== >--- Source/WebCore/html/HTMLFormElement.cpp (revision 235963) >+++ Source/WebCore/html/HTMLFormElement.cpp (working copy) >@@ -142,13 +142,13 @@ > HTMLElement::removedFromAncestor(removalType, oldParentOfRemovedTree); > } > >-void HTMLFormElement::handleLocalEvents(Event& event) >+void HTMLFormElement::handleLocalEvents(Event& event, EventInvokePhase phase) > { > if (event.eventPhase() != Event::CAPTURING_PHASE && is<Node>(event.target()) && event.target() != this && (event.type() == eventNames().submitEvent || event.type() == eventNames().resetEvent)) { > event.stopPropagation(); > return; > } >- HTMLElement::handleLocalEvents(event); >+ HTMLElement::handleLocalEvents(event, phase); > } > > unsigned HTMLFormElement::length() const >Index: Source/WebCore/html/HTMLFormElement.h >=================================================================== >--- Source/WebCore/html/HTMLFormElement.h (revision 235963) >+++ Source/WebCore/html/HTMLFormElement.h (working copy) >@@ -133,7 +133,7 @@ > void removedFromAncestor(RemovalType, ContainerNode&) final; > void finishParsingChildren() final; > >- void handleLocalEvents(Event&) final; >+ void handleLocalEvents(Event&, EventInvokePhase) final; > > void parseAttribute(const QualifiedName&, const AtomicString&) final; > bool isURLAttribute(const Attribute&) const final; >Index: Source/WebCore/page/DOMWindow.cpp >=================================================================== >--- Source/WebCore/page/DOMWindow.cpp (revision 235963) >+++ Source/WebCore/page/DOMWindow.cpp (working copy) >@@ -2052,7 +2052,9 @@ > event.setEventPhase(Event::AT_TARGET); > event.resetBeforeDispatch(); > auto cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), event, *this); >- fireEventListeners(event); >+ // FIXME: We should use EventDispatcher everywhere. >+ fireEventListeners(event, EventInvokePhase::Capturing); >+ fireEventListeners(event, EventInvokePhase::Bubbling); > InspectorInstrumentation::didDispatchEventOnWindow(cookie); > event.resetAfterDispatch(); > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 174288
:
349618
|
349621
|
349631
|
349640
|
349642
|
349654
|
349713
|
349718
|
349728