Simplify event dispatch code and make it a bit more consistent
authordarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 4 Nov 2017 21:19:11 +0000 (21:19 +0000)
committerdarin@apple.com <darin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 4 Nov 2017 21:19:11 +0000 (21:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=178991

Reviewed by Chris Dumez.

Source/WebCore:

Straighten out event dispatch code in three ways:

1) Add an Event::resetAfterDispatch function, and use it instead of the multiple
   separate functions that were used before to reset after dispatching. This fixed
   an extremely minor bug where we would leave some kinds of state on some event
   objects in unusual cases after dispatching the events.

2) Remove IDBEventDispatcher and make its callers use EventDispatcher instead.
   This leaves us with one less event dispatch code path to maintain, more shared code.

3) Remove boolean return values from functions that take event objects and
   dispatch the events. The return values are redundant with various things that
   can be checked by looking at the event itself. The legacy return value indicates
   whether the event has its "canceled flag" set, which means that the default
   behavior should be prevented. If that is what we need to check, it's easier
   to read the code and see that it's correct if it calls the named function
   "defaultPrevented" directly. More importantly, callers can also call whatever
   other function is appropriate to ask the specific relevant question to their needs.
   The general rule is that default behavior that we want to allow even with an
   untrusted event can be inside a default event handler function. Default behavior
   that should only happen for the browser-generated event can and should be done
   after dispatching the event, in the code that dispatches it; but that requires
   explicitly checking "defaultPrevented".

* Modules/indexeddb/IDBDatabase.cpp:
(WebCore::IDBDatabase::dispatchEvent): Removed boolean return value.
* Modules/indexeddb/IDBDatabase.h: Ditto.

* Modules/indexeddb/IDBEventDispatcher.cpp: Removed.
* Modules/indexeddb/IDBEventDispatcher.h: Removed.

* Modules/indexeddb/IDBOpenDBRequest.cpp:
(WebCore::IDBOpenDBRequest::dispatchEvent): Removed boolean return value.
Added protection for "this" since the function accesses it after dispatching the event.
* Modules/indexeddb/IDBOpenDBRequest.h: Ditto.

* Modules/indexeddb/IDBRequest.cpp:
(WebCore::IDBRequest::dispatchEvent): Removed boolean return value. Instead of using
IDBEventDispatcher, use EventDispatcher's new function that takes an initializer_list
with a list of event targets. Added protection for "this" since the function accesses
it after dispatching the event.
* Modules/indexeddb/IDBRequest.h: Ditto.
* Modules/indexeddb/IDBTransaction.cpp:
(WebCore::IDBTransaction::dispatchEvent): Ditto.
* Modules/indexeddb/IDBTransaction.h: Ditto.

* Modules/mediastream/RTCPeerConnection.cpp:
(WebCore::RTCPeerConnection::dispatchEvent): Removed boolean return value.
* Modules/mediastream/RTCPeerConnection.h: Ditto.
* Modules/paymentrequest/PaymentRequest.cpp:
(WebCore::PaymentRequest::shippingAddressChanged): Don't dispatch an event if
m_isUpdating is true; preserves behavior that was implemented in
PaymentRequest::dispatchEvent before. Since this is the source of the trusted
event, cleaner to implement the rule here instead of overriding dispatchEvent.
(WebCore::PaymentRequest::shippingOptionChanged): Ditto.
(WebCore::PaymentRequest::dispatchEvent): Deleted.
* Modules/paymentrequest/PaymentRequest.h: Ditto.

* Sources.txt: Removed IDBEventDispatcher.cpp.
* WebCore.xcodeproj/project.pbxproj: Removed IDBEventDispatcher.h/cpp.

* dom/Element.cpp:
(WebCore::Element::dispatchMouseEvent): Updated to call defaultPrevented
directly instead of using the return value of dispatchEvent.
(WebCore::Element::dispatchWheelEvent): Ditto.
(WebCore::Element::dispatchKeyEvent): Ditto.
(WebCore::Element::dispatchFocusInEvent): Removed assertion, since the
underlying event dispatching takes care of it.
(WebCore::Element::dispatchFocusOutEvent): Ditto.
(WebCore::Element::dispatchFocusEvent): Call dispatchEvent instead of
calling EventDispatcher::dispatchEvent. There is no good reason to use
EventDispatcher directly.
(WebCore::Element::dispatchBlurEvent): Ditto.

* dom/Event.cpp:
(WebCore::Event::eventInterface const): Deleted. Moved into header since this is
short and if called in a non-polymorphic context it's good to have it be inlined.
(WebCore::Event::isUIEvent const): Ditto.
(WebCore::Event::isMouseEvent const): Ditto.
(WebCore::Event::isFocusEvent const): Ditto.
(WebCore::Event::isKeyboardEvent const): Ditto.
(WebCore::Event::isInputEvent const): Ditto.
(WebCore::Event::isCompositionEvent const): Ditto.
(WebCore::Event::isTouchEvent const): Ditto.
(WebCore::Event::isClipboardEvent const): Ditto.
(WebCore::Event::isBeforeTextInsertedEvent const): Ditto.
(WebCore::Event::isBeforeUnloadEvent const): Ditto.
(WebCore::Event::isErrorEvent const): Ditto.
(WebCore::Event::isTextEvent const): Ditto.
(WebCore::Event::isWheelEvent const): Ditto.
(WebCore::Event::receivedTarget): Ditto.
(WebCore::Event::resetAfterDispatch): Added. Replaces functions like
clearEventPath and resetPropagationFlags, covering all the things we need to clear
after dispatching an event.

* dom/Event.h: Removed some unneeded includes and forward declarations. Moved bodies
of multi-line inline member functions out of the class definition. Changed argument
type of setEventPhase and m_eventPhase to an enum rather than just an integer, since
only the getter is for use from the bindings. Removed clearEventPath, srcElement, and
resetPropagationFlags. Sorted the isXXX functions alphabetically and removed previous
attempts to make categories out of them. Marked the constructor explicit since it has
a single argument. Moved trivially short bodies into the class definition.

* dom/Event.idl: Use ImplementedAs to implement srcElement so we don't need it in
the C++ code.

* dom/EventContext.cpp:
(WebCore::EventContext::EventContext): Removed assertion since we now handle event
contexts without nodes so we can use this to dispatch events for IDB, for example.
(WebCore::EventContext::handleLocalEvents const): Add code to handle non-node event
targets by calling fireEventListeners directly.
(WebCore::MouseOrFocusEventContext::MouseOrFocusEventContext): Take a reference
insetad of a pointer for the node.
(WebCore::TouchEventContext::TouchEventContext): Ditto.
(WebCore::TouchEventContext::handleLocalEvents const): Streamline a bit by improving
the checkReachability function to be easier to call. Also removed an unneeded assertion
just before calling downcast<>, the same assertion that downcast<> itself does.
(WebCore::TouchEventContext::checkReachability const): Chagned argument type to take
a Ref& so the caller doesn't have to call get() or ptr().

* dom/EventContext.h: Removed unneeded FIXME and currentTargetSameAsTarget function.
Changed arguemnt types to use Node& instead of Node* as appropriate. Removed unused
functions from TouchEventContext, made more private, and changed data members to Ref
instead of RefPtr. Removed unused NotTouchList value from TouchListType enumeration.
Changed touchList function to return a reference instead of a pointer.

* dom/EventDispatcher.cpp: Removed unneeded includes.
(WebCore::dispatchEventInDOM): Removed use of currentTargetSameAsTarget since it's
clearer if written out.
(WebCore::EventDispatcher::dispatchEvent): Changed no-event dispatch assertion to
use RELEASE_ASSERT_WITH_SECURITY_IMPLICATION since the style checker says so, but
it still doesn't assert anything in release builds because the check in
NoEventDispatchAssertion itself is debug-only. Moved the calls to EventPath's
setRelatedTarget and retargetTouchLists functions inside the EventPath constructor.
Removed the second no-event dispatch assertion because we only need one. Replaced
calls to clearEventPath, setCurrentTarget(nullptr), resetPropagationFlags,
and setEventPhase(NONE) and with a call to resetAfterDispatch. Moved the code that
temporarily sets the target to a different value when calling default event handlers
into the block that calls the default event handlers. Added a new overload that
takes an initializer list of event targets so we can dispatch events that are not
being sent to nodes.

* dom/EventDispatcher.h: Fixed misleading copyright dates and names since this file
just contains a couple of function declarations. Added new overload of dispatchEvent.

* dom/EventPath.cpp:
(WebCore::WindowEventContext::WindowEventContext): Take references instead of pointers.
(WebCore::EventPath::EventPath): Moved the bulk of construction into a new function
named buildPath, so it can still use "return" without skipping the additions here.
Added calls to setRelatedTarget and retargetTouchLists and now both can be private.
Also added a new overload that takes event targets that are not nodes.
(WebCore::EventPath::buildPath): Added. Contains what used to be in the constructor.
But use some references instead of pointers and refactor a bit using lambdas.
(WebCore::EventPath::retargetTouchList): Added. Makes the retargetTouchLists function
shorter and less repetetive.
(WebCore::EventPath::retargetTouchLists): Updated to call retargetTouchList.
(WebCore::EventPath::hasEventListeners const): Deleted. This was unused.
* dom/EventPath.h: Added a constructor that takes an initializer list of event targets.
Made retargetTouchEvents and setRelatedTarget private and used them in the constructor
insead of expecting clients to call them. Removed unused hasEventListeners and
lastContextIfExists functions. Moved body of the eventTargetRespectingTargetRules
function out of the class definition.

* dom/EventTarget.cpp:
(WebCore::EventTarget::dispatchEventForBindings): Updated so it does not expect
dispatchEvent to return a boolean. Instead call a function on the event after dispatching.
Decided to use legacyReturnValue instead of !defaultPrevented, because this is exactly
the return value that the returnValue property is referring to.
(WebCore::EventTarget::dispatchEvent): Removed return value. Replaced calls to
resetPropagationFlags and setEventPhase(NONE) with a call to resetAfterDispatch.
I noticed that there was a local boolean here named "defaultPrevented", which was
backwards; the value in that local was "default not prevented". Doesn't matter since
the boolean return value was removed.
(WebCore::EventTarget::fireEventListeners): Removed the boolean return value.

* dom/EventTarget.h: Added initial values to members of ListenerOptions and
AddEventListenerOptions; maybe we can get rid of the constructors some day.
Removed booelan return values from dispatchEvent and fireEventListeners.

* dom/KeyboardEvent.cpp: Removed unneeded include of EventDispatcher.h.

* dom/Node.cpp:
(WebCore::Node::dispatchEvent): Got rid of boolean return value.
Removed special case code that sometimes called dispatchTouchEvent, since that
just turns around and calls EventDispatcher::dispatchEvent just like this function.
(WebCore::Node::dispatchDOMActivateEvent): Removed boolean return value, removed
integer detail argument and moved the logic to compute the value of the detail
peroprty and to call setDefaultHandled on the underlying click event in here.
This is a private helper function used only in one place.
(WebCore::Node::dispatchTouchEvent): Deleted.
(WebCore::Node::defaultEventHandler): Updated for change to dispatchDOMActivateEvent.
* dom/Node.h: Updated for the above changes.

* dom/RejectedPromiseTracker.cpp:
(WebCore::RejectedPromiseTracker::reportUnhandledRejections): Use defaultPrevented
directly instead of the return value from dispatchEvent.

* dom/ScopedEventQueue.cpp:
(WebCore::ScopedEventQueue::enqueueEvent): Moved assertions here ...
(WebCore::ScopedEventQueue::dispatchEvent const): ... from here. Also changed this
to call Node::dispatchEvent instead of calling EventDispatcher::dispatchEvent directly.

* dom/SimulatedClick.cpp:
(WebCore::simulateMouseEvent): Call Element::dispatchEvent instead of calling
EventDispatcher::dispatchEvent directly.

* editing/Editor.cpp:
(WebCore::dispatchBeforeInputEvent): Use defaultPrevented directly instead of the
return value from dispatchEvent.
* editing/FrameSelection.cpp:
(WebCore::FrameSelection::selectAll): Ditto.
(WebCore::FrameSelection::dispatchSelectStart): Ditto.

* html/CheckboxInputType.cpp:
(WebCore::CheckboxInputType::didDispatchClick): Take a reference instead of a pointer.
* html/CheckboxInputType.h: Updated for above and to use final instead of override.

* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::checkValidity): Use defaultPrevented directly instead
of the return value from dispatchEvent.

* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::prepareForSubmission): Use defaultPrevented directly instead
of the return value from dispatchEvent.
(WebCore::HTMLFormElement::reset): Ditto.

* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::didDispatchClickEvent): Updated to pass references instead
of pointer.

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::dispatchEvent): Got rid of boolean return value.
* html/HTMLMediaElement.h: Ditto.

* html/HTMLPlugInElement.h: Use "delete" instead of just a private function for something
that should never be called.

* html/InputType.cpp:
(WebCore::InputType::didDispatchClick): Take a reference instead of a pointer.
* html/InputType.h: Ditto.
* html/RadioInputType.cpp:
(WebCore::RadioInputType::didDispatchClick): Ditto.
* html/RadioInputType.h: Updated for above and to use final instead of override.

* html/track/TextTrackCue.cpp:
(WebCore::TextTrackCue::dispatchEvent): Got rid of boolean return value.
* html/track/TextTrackCue.h: Ditto.

* inspector/InspectorInstrumentation.cpp: Removed unneeded include of EventDispatcher.h.

* page/DOMWindow.cpp:
(WebCore::DOMWindow::dispatchLoadEvent): Streamlined code a bit so we only have a single
call to dispatchEvent. Improved comments.
(WebCore::DOMWindow::dispatchEvent): Removed return value. Added comments. Replaced
calls to setCurrentTarget(null), setEventPhase(NONE), and resetPropagationFlags with
a call to resetAfterDispatch.
* page/DOMWindow.h: Updated to get rid of the boolean return value.

* page/DragController.cpp:
(WebCore::DragController::dispatchTextInputEventFor): Use defaultPrevented directly instead
of the return value from dispatchEvent.

* page/EventHandler.cpp:
(WebCore::dispatchSelectStart): Use defaultPrevented directly instead
of the return value from dispatchEvent.
(WebCore::EventHandler::accessibilityPreventsEventPropagation): Fixed spelling error in the
name of this function.
(WebCore::EventHandler::dispatchDragSrcEvent): Got rid of boolean return value.
(WebCore::EventHandler::handleTouchEvent): Call dispatchEvent instead of dispatchTouchEvent;
there was no difference between the two except that dispatchTouchEvent required downcasting
and might some day lead to us missing some behavior implemented in an override to dispatchEvent.
* page/EventHandler.h: Updated for above changes.

* platform/graphics/filters/FilterOperation.h:
(WebCore::FilterOperation::clone): Removed dead code that was causing a compiler warning.

* workers/WorkerMessagingProxy.cpp:
(WebCore::WorkerMessagingProxy::postExceptionToWorkerObject): Use defaultPrevented
directly instead of the return value from dispatchEvent.

Source/WebKit:

* WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMEvent.cpp:
(webkit_dom_event_get_src_element): Call target instead of srcElement.

Source/WebKitLegacy/mac:

* DOM/DOMEvent.mm:
(-[DOMEvent srcElement]): Call target instead of srcElement.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@224459 268f45cc-cd09-0410-ab3c-d52691b4dbfc

63 files changed:
Source/WebCore/ChangeLog
Source/WebCore/Modules/indexeddb/IDBDatabase.cpp
Source/WebCore/Modules/indexeddb/IDBDatabase.h
Source/WebCore/Modules/indexeddb/IDBEventDispatcher.cpp [deleted file]
Source/WebCore/Modules/indexeddb/IDBEventDispatcher.h [deleted file]
Source/WebCore/Modules/indexeddb/IDBOpenDBRequest.cpp
Source/WebCore/Modules/indexeddb/IDBOpenDBRequest.h
Source/WebCore/Modules/indexeddb/IDBRequest.cpp
Source/WebCore/Modules/indexeddb/IDBRequest.h
Source/WebCore/Modules/indexeddb/IDBTransaction.cpp
Source/WebCore/Modules/indexeddb/IDBTransaction.h
Source/WebCore/Modules/mediastream/RTCPeerConnection.cpp
Source/WebCore/Modules/mediastream/RTCPeerConnection.h
Source/WebCore/Modules/paymentrequest/PaymentRequest.cpp
Source/WebCore/Modules/paymentrequest/PaymentRequest.h
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Event.cpp
Source/WebCore/dom/Event.h
Source/WebCore/dom/Event.idl
Source/WebCore/dom/EventContext.cpp
Source/WebCore/dom/EventContext.h
Source/WebCore/dom/EventDispatcher.cpp
Source/WebCore/dom/EventDispatcher.h
Source/WebCore/dom/EventPath.cpp
Source/WebCore/dom/EventPath.h
Source/WebCore/dom/EventTarget.cpp
Source/WebCore/dom/EventTarget.h
Source/WebCore/dom/KeyboardEvent.cpp
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/RejectedPromiseTracker.cpp
Source/WebCore/dom/ScopedEventQueue.cpp
Source/WebCore/dom/SimulatedClick.cpp
Source/WebCore/editing/Editor.cpp
Source/WebCore/editing/FrameSelection.cpp
Source/WebCore/html/CheckboxInputType.cpp
Source/WebCore/html/CheckboxInputType.h
Source/WebCore/html/HTMLFormControlElement.cpp
Source/WebCore/html/HTMLFormElement.cpp
Source/WebCore/html/HTMLInputElement.cpp
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/HTMLMediaElement.h
Source/WebCore/html/HTMLPlugInElement.h
Source/WebCore/html/InputType.cpp
Source/WebCore/html/InputType.h
Source/WebCore/html/RadioInputType.cpp
Source/WebCore/html/RadioInputType.h
Source/WebCore/html/track/TextTrackCue.cpp
Source/WebCore/html/track/TextTrackCue.h
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/DOMWindow.h
Source/WebCore/page/DragController.cpp
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/EventHandler.h
Source/WebCore/platform/graphics/filters/FilterOperation.h
Source/WebCore/workers/WorkerMessagingProxy.cpp
Source/WebKit/ChangeLog
Source/WebKit/WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMEvent.cpp
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/DOM/DOMEvent.mm

index 91a2379..f787861 100644 (file)
@@ -1,3 +1,290 @@
+2017-11-01  Darin Adler  <darin@apple.com>
+
+        Simplify event dispatch code and make it a bit more consistent
+        https://bugs.webkit.org/show_bug.cgi?id=178991
+
+        Reviewed by Chris Dumez.
+
+        Straighten out event dispatch code in three ways:
+
+        1) Add an Event::resetAfterDispatch function, and use it instead of the multiple
+           separate functions that were used before to reset after dispatching. This fixed
+           an extremely minor bug where we would leave some kinds of state on some event
+           objects in unusual cases after dispatching the events.
+
+        2) Remove IDBEventDispatcher and make its callers use EventDispatcher instead.
+           This leaves us with one less event dispatch code path to maintain, more shared code.
+
+        3) Remove boolean return values from functions that take event objects and
+           dispatch the events. The return values are redundant with various things that
+           can be checked by looking at the event itself. The legacy return value indicates
+           whether the event has its "canceled flag" set, which means that the default
+           behavior should be prevented. If that is what we need to check, it's easier
+           to read the code and see that it's correct if it calls the named function
+           "defaultPrevented" directly. More importantly, callers can also call whatever
+           other function is appropriate to ask the specific relevant question to their needs.
+           The general rule is that default behavior that we want to allow even with an
+           untrusted event can be inside a default event handler function. Default behavior
+           that should only happen for the browser-generated event can and should be done
+           after dispatching the event, in the code that dispatches it; but that requires
+           explicitly checking "defaultPrevented".
+
+        * Modules/indexeddb/IDBDatabase.cpp:
+        (WebCore::IDBDatabase::dispatchEvent): Removed boolean return value.
+        * Modules/indexeddb/IDBDatabase.h: Ditto.
+
+        * Modules/indexeddb/IDBEventDispatcher.cpp: Removed.
+        * Modules/indexeddb/IDBEventDispatcher.h: Removed.
+
+        * Modules/indexeddb/IDBOpenDBRequest.cpp:
+        (WebCore::IDBOpenDBRequest::dispatchEvent): Removed boolean return value.
+        Added protection for "this" since the function accesses it after dispatching the event.
+        * Modules/indexeddb/IDBOpenDBRequest.h: Ditto.
+
+        * Modules/indexeddb/IDBRequest.cpp:
+        (WebCore::IDBRequest::dispatchEvent): Removed boolean return value. Instead of using
+        IDBEventDispatcher, use EventDispatcher's new function that takes an initializer_list
+        with a list of event targets. Added protection for "this" since the function accesses
+        it after dispatching the event.
+        * Modules/indexeddb/IDBRequest.h: Ditto.
+        * Modules/indexeddb/IDBTransaction.cpp:
+        (WebCore::IDBTransaction::dispatchEvent): Ditto.
+        * Modules/indexeddb/IDBTransaction.h: Ditto.
+
+        * Modules/mediastream/RTCPeerConnection.cpp:
+        (WebCore::RTCPeerConnection::dispatchEvent): Removed boolean return value.
+        * Modules/mediastream/RTCPeerConnection.h: Ditto.
+        * Modules/paymentrequest/PaymentRequest.cpp:
+        (WebCore::PaymentRequest::shippingAddressChanged): Don't dispatch an event if
+        m_isUpdating is true; preserves behavior that was implemented in
+        PaymentRequest::dispatchEvent before. Since this is the source of the trusted
+        event, cleaner to implement the rule here instead of overriding dispatchEvent.
+        (WebCore::PaymentRequest::shippingOptionChanged): Ditto.
+        (WebCore::PaymentRequest::dispatchEvent): Deleted.
+        * Modules/paymentrequest/PaymentRequest.h: Ditto.
+
+        * Sources.txt: Removed IDBEventDispatcher.cpp.
+        * WebCore.xcodeproj/project.pbxproj: Removed IDBEventDispatcher.h/cpp.
+
+        * dom/Element.cpp:
+        (WebCore::Element::dispatchMouseEvent): Updated to call defaultPrevented
+        directly instead of using the return value of dispatchEvent.
+        (WebCore::Element::dispatchWheelEvent): Ditto.
+        (WebCore::Element::dispatchKeyEvent): Ditto.
+        (WebCore::Element::dispatchFocusInEvent): Removed assertion, since the
+        underlying event dispatching takes care of it.
+        (WebCore::Element::dispatchFocusOutEvent): Ditto.
+        (WebCore::Element::dispatchFocusEvent): Call dispatchEvent instead of
+        calling EventDispatcher::dispatchEvent. There is no good reason to use
+        EventDispatcher directly.
+        (WebCore::Element::dispatchBlurEvent): Ditto.
+
+        * dom/Event.cpp:
+        (WebCore::Event::eventInterface const): Deleted. Moved into header since this is
+        short and if called in a non-polymorphic context it's good to have it be inlined.
+        (WebCore::Event::isUIEvent const): Ditto.
+        (WebCore::Event::isMouseEvent const): Ditto.
+        (WebCore::Event::isFocusEvent const): Ditto.
+        (WebCore::Event::isKeyboardEvent const): Ditto.
+        (WebCore::Event::isInputEvent const): Ditto.
+        (WebCore::Event::isCompositionEvent const): Ditto.
+        (WebCore::Event::isTouchEvent const): Ditto.
+        (WebCore::Event::isClipboardEvent const): Ditto.
+        (WebCore::Event::isBeforeTextInsertedEvent const): Ditto.
+        (WebCore::Event::isBeforeUnloadEvent const): Ditto.
+        (WebCore::Event::isErrorEvent const): Ditto.
+        (WebCore::Event::isTextEvent const): Ditto.
+        (WebCore::Event::isWheelEvent const): Ditto.
+        (WebCore::Event::receivedTarget): Ditto.
+        (WebCore::Event::resetAfterDispatch): Added. Replaces functions like
+        clearEventPath and resetPropagationFlags, covering all the things we need to clear
+        after dispatching an event.
+
+        * dom/Event.h: Removed some unneeded includes and forward declarations. Moved bodies
+        of multi-line inline member functions out of the class definition. Changed argument
+        type of setEventPhase and m_eventPhase to an enum rather than just an integer, since
+        only the getter is for use from the bindings. Removed clearEventPath, srcElement, and
+        resetPropagationFlags. Sorted the isXXX functions alphabetically and removed previous
+        attempts to make categories out of them. Marked the constructor explicit since it has
+        a single argument. Moved trivially short bodies into the class definition.
+
+        * dom/Event.idl: Use ImplementedAs to implement srcElement so we don't need it in
+        the C++ code.
+
+        * dom/EventContext.cpp:
+        (WebCore::EventContext::EventContext): Removed assertion since we now handle event
+        contexts without nodes so we can use this to dispatch events for IDB, for example.
+        (WebCore::EventContext::handleLocalEvents const): Add code to handle non-node event
+        targets by calling fireEventListeners directly.
+        (WebCore::MouseOrFocusEventContext::MouseOrFocusEventContext): Take a reference
+        insetad of a pointer for the node.
+        (WebCore::TouchEventContext::TouchEventContext): Ditto.
+        (WebCore::TouchEventContext::handleLocalEvents const): Streamline a bit by improving
+        the checkReachability function to be easier to call. Also removed an unneeded assertion
+        just before calling downcast<>, the same assertion that downcast<> itself does.
+        (WebCore::TouchEventContext::checkReachability const): Chagned argument type to take
+        a Ref& so the caller doesn't have to call get() or ptr().
+
+        * dom/EventContext.h: Removed unneeded FIXME and currentTargetSameAsTarget function.
+        Changed arguemnt types to use Node& instead of Node* as appropriate. Removed unused
+        functions from TouchEventContext, made more private, and changed data members to Ref
+        instead of RefPtr. Removed unused NotTouchList value from TouchListType enumeration.
+        Changed touchList function to return a reference instead of a pointer.
+
+        * dom/EventDispatcher.cpp: Removed unneeded includes.
+        (WebCore::dispatchEventInDOM): Removed use of currentTargetSameAsTarget since it's
+        clearer if written out.
+        (WebCore::EventDispatcher::dispatchEvent): Changed no-event dispatch assertion to
+        use RELEASE_ASSERT_WITH_SECURITY_IMPLICATION since the style checker says so, but
+        it still doesn't assert anything in release builds because the check in
+        NoEventDispatchAssertion itself is debug-only. Moved the calls to EventPath's
+        setRelatedTarget and retargetTouchLists functions inside the EventPath constructor.
+        Removed the second no-event dispatch assertion because we only need one. Replaced
+        calls to clearEventPath, setCurrentTarget(nullptr), resetPropagationFlags,
+        and setEventPhase(NONE) and with a call to resetAfterDispatch. Moved the code that
+        temporarily sets the target to a different value when calling default event handlers
+        into the block that calls the default event handlers. Added a new overload that
+        takes an initializer list of event targets so we can dispatch events that are not
+        being sent to nodes.
+
+        * dom/EventDispatcher.h: Fixed misleading copyright dates and names since this file
+        just contains a couple of function declarations. Added new overload of dispatchEvent.
+
+        * dom/EventPath.cpp:
+        (WebCore::WindowEventContext::WindowEventContext): Take references instead of pointers.
+        (WebCore::EventPath::EventPath): Moved the bulk of construction into a new function
+        named buildPath, so it can still use "return" without skipping the additions here.
+        Added calls to setRelatedTarget and retargetTouchLists and now both can be private.
+        Also added a new overload that takes event targets that are not nodes.
+        (WebCore::EventPath::buildPath): Added. Contains what used to be in the constructor.
+        But use some references instead of pointers and refactor a bit using lambdas.
+        (WebCore::EventPath::retargetTouchList): Added. Makes the retargetTouchLists function
+        shorter and less repetetive.
+        (WebCore::EventPath::retargetTouchLists): Updated to call retargetTouchList.
+        (WebCore::EventPath::hasEventListeners const): Deleted. This was unused.
+        * dom/EventPath.h: Added a constructor that takes an initializer list of event targets.
+        Made retargetTouchEvents and setRelatedTarget private and used them in the constructor
+        insead of expecting clients to call them. Removed unused hasEventListeners and
+        lastContextIfExists functions. Moved body of the eventTargetRespectingTargetRules
+        function out of the class definition.
+
+        * dom/EventTarget.cpp:
+        (WebCore::EventTarget::dispatchEventForBindings): Updated so it does not expect
+        dispatchEvent to return a boolean. Instead call a function on the event after dispatching.
+        Decided to use legacyReturnValue instead of !defaultPrevented, because this is exactly
+        the return value that the returnValue property is referring to.
+        (WebCore::EventTarget::dispatchEvent): Removed return value. Replaced calls to
+        resetPropagationFlags and setEventPhase(NONE) with a call to resetAfterDispatch.
+        I noticed that there was a local boolean here named "defaultPrevented", which was
+        backwards; the value in that local was "default not prevented". Doesn't matter since
+        the boolean return value was removed.
+        (WebCore::EventTarget::fireEventListeners): Removed the boolean return value.
+
+        * dom/EventTarget.h: Added initial values to members of ListenerOptions and
+        AddEventListenerOptions; maybe we can get rid of the constructors some day.
+        Removed booelan return values from dispatchEvent and fireEventListeners.
+
+        * dom/KeyboardEvent.cpp: Removed unneeded include of EventDispatcher.h.
+
+        * dom/Node.cpp:
+        (WebCore::Node::dispatchEvent): Got rid of boolean return value.
+        Removed special case code that sometimes called dispatchTouchEvent, since that
+        just turns around and calls EventDispatcher::dispatchEvent just like this function.
+        (WebCore::Node::dispatchDOMActivateEvent): Removed boolean return value, removed
+        integer detail argument and moved the logic to compute the value of the detail
+        peroprty and to call setDefaultHandled on the underlying click event in here.
+        This is a private helper function used only in one place.
+        (WebCore::Node::dispatchTouchEvent): Deleted.
+        (WebCore::Node::defaultEventHandler): Updated for change to dispatchDOMActivateEvent.
+        * dom/Node.h: Updated for the above changes.
+
+        * dom/RejectedPromiseTracker.cpp:
+        (WebCore::RejectedPromiseTracker::reportUnhandledRejections): Use defaultPrevented
+        directly instead of the return value from dispatchEvent.
+
+        * dom/ScopedEventQueue.cpp:
+        (WebCore::ScopedEventQueue::enqueueEvent): Moved assertions here ...
+        (WebCore::ScopedEventQueue::dispatchEvent const): ... from here. Also changed this
+        to call Node::dispatchEvent instead of calling EventDispatcher::dispatchEvent directly.
+
+        * dom/SimulatedClick.cpp:
+        (WebCore::simulateMouseEvent): Call Element::dispatchEvent instead of calling
+        EventDispatcher::dispatchEvent directly.
+
+        * editing/Editor.cpp:
+        (WebCore::dispatchBeforeInputEvent): Use defaultPrevented directly instead of the
+        return value from dispatchEvent.
+        * editing/FrameSelection.cpp:
+        (WebCore::FrameSelection::selectAll): Ditto.
+        (WebCore::FrameSelection::dispatchSelectStart): Ditto.
+
+        * html/CheckboxInputType.cpp:
+        (WebCore::CheckboxInputType::didDispatchClick): Take a reference instead of a pointer.
+        * html/CheckboxInputType.h: Updated for above and to use final instead of override.
+
+        * html/HTMLFormControlElement.cpp:
+        (WebCore::HTMLFormControlElement::checkValidity): Use defaultPrevented directly instead
+        of the return value from dispatchEvent.
+
+        * html/HTMLFormElement.cpp:
+        (WebCore::HTMLFormElement::prepareForSubmission): Use defaultPrevented directly instead
+        of the return value from dispatchEvent.
+        (WebCore::HTMLFormElement::reset): Ditto.
+
+        * html/HTMLInputElement.cpp:
+        (WebCore::HTMLInputElement::didDispatchClickEvent): Updated to pass references instead
+        of pointer.
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::dispatchEvent): Got rid of boolean return value.
+        * html/HTMLMediaElement.h: Ditto.
+
+        * html/HTMLPlugInElement.h: Use "delete" instead of just a private function for something
+        that should never be called.
+
+        * html/InputType.cpp:
+        (WebCore::InputType::didDispatchClick): Take a reference instead of a pointer.
+        * html/InputType.h: Ditto.
+        * html/RadioInputType.cpp:
+        (WebCore::RadioInputType::didDispatchClick): Ditto.
+        * html/RadioInputType.h: Updated for above and to use final instead of override.
+
+        * html/track/TextTrackCue.cpp:
+        (WebCore::TextTrackCue::dispatchEvent): Got rid of boolean return value.
+        * html/track/TextTrackCue.h: Ditto.
+
+        * inspector/InspectorInstrumentation.cpp: Removed unneeded include of EventDispatcher.h.
+
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::dispatchLoadEvent): Streamlined code a bit so we only have a single
+        call to dispatchEvent. Improved comments.
+        (WebCore::DOMWindow::dispatchEvent): Removed return value. Added comments. Replaced
+        calls to setCurrentTarget(null), setEventPhase(NONE), and resetPropagationFlags with
+        a call to resetAfterDispatch.
+        * page/DOMWindow.h: Updated to get rid of the boolean return value.
+
+        * page/DragController.cpp:
+        (WebCore::DragController::dispatchTextInputEventFor): Use defaultPrevented directly instead
+        of the return value from dispatchEvent.
+
+        * page/EventHandler.cpp:
+        (WebCore::dispatchSelectStart): Use defaultPrevented directly instead
+        of the return value from dispatchEvent.
+        (WebCore::EventHandler::accessibilityPreventsEventPropagation): Fixed spelling error in the
+        name of this function.
+        (WebCore::EventHandler::dispatchDragSrcEvent): Got rid of boolean return value.
+        (WebCore::EventHandler::handleTouchEvent): Call dispatchEvent instead of dispatchTouchEvent;
+        there was no difference between the two except that dispatchTouchEvent required downcasting
+        and might some day lead to us missing some behavior implemented in an override to dispatchEvent.
+        * page/EventHandler.h: Updated for above changes.
+
+        * platform/graphics/filters/FilterOperation.h:
+        (WebCore::FilterOperation::clone): Removed dead code that was causing a compiler warning.
+
+        * workers/WorkerMessagingProxy.cpp:
+        (WebCore::WorkerMessagingProxy::postExceptionToWorkerObject): Use defaultPrevented
+        directly instead of the return value from dispatchEvent.
+
 2017-11-04  Aishwarya Nirmal  <anirmal@apple.com>
 
         [Touch Bar Web API] Add support for menuitem tag
index c0cba87..8f6e775 100644 (file)
@@ -473,17 +473,17 @@ void IDBDatabase::fireVersionChangeEvent(const IDBResourceIdentifier& requestIde
     scriptExecutionContext()->eventQueue().enqueueEvent(WTFMove(event));
 }
 
-bool IDBDatabase::dispatchEvent(Event& event)
+void IDBDatabase::dispatchEvent(Event& event)
 {
     LOG(IndexedDB, "IDBDatabase::dispatchEvent (%" PRIu64 ") (%p)", m_databaseConnectionIdentifier, this);
     ASSERT(currentThread() == originThreadID());
 
-    bool result = EventTargetWithInlineData::dispatchEvent(event);
+    auto protectedThis = makeRef(*this);
 
-    if (event.isVersionChangeEvent() && event.type() == m_eventNames.versionchangeEvent)
-        connectionProxy().didFireVersionChangeEvent(m_databaseConnectionIdentifier, downcast<IDBVersionChangeEvent>(event).requestIdentifier());
+    EventTargetWithInlineData::dispatchEvent(event);
 
-    return result;
+    if (event.isVersionChangeEvent() && event.type() == m_eventNames.versionchangeEvent)
+        m_connectionProxy->didFireVersionChangeEvent(m_databaseConnectionIdentifier, downcast<IDBVersionChangeEvent>(event).requestIdentifier());
 }
 
 void IDBDatabase::didCreateIndexInfo(const IDBIndexInfo& info)
index ba487b3..76a1285 100644 (file)
@@ -106,7 +106,7 @@ public:
 
     bool isClosingOrClosed() const { return m_closePending || m_closedInServer; }
 
-    bool dispatchEvent(Event&) final;
+    void dispatchEvent(Event&) final;
 
     bool hasPendingActivity() const final;
 
diff --git a/Source/WebCore/Modules/indexeddb/IDBEventDispatcher.cpp b/Source/WebCore/Modules/indexeddb/IDBEventDispatcher.cpp
deleted file mode 100644 (file)
index e513143..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "IDBEventDispatcher.h"
-
-#if ENABLE(INDEXED_DATABASE)
-
-#include "Event.h"
-#include "EventTarget.h"
-
-namespace WebCore {
-
-bool IDBEventDispatcher::dispatch(Event& event, Vector<RefPtr<EventTarget>>& eventTargets)
-{
-    size_t size = eventTargets.size();
-    ASSERT(size);
-
-    event.setEventPhase(Event::CAPTURING_PHASE);
-    for (size_t i = size - 1; i; --i) { // Don't do the first element.
-        event.setCurrentTarget(eventTargets[i].get());
-        eventTargets[i]->fireEventListeners(event);
-        if (event.propagationStopped())
-            goto doneDispatching;
-    }
-
-    event.setEventPhase(Event::AT_TARGET);
-    event.setCurrentTarget(eventTargets[0].get());
-    eventTargets[0]->fireEventListeners(event);
-    if (event.propagationStopped() || !event.bubbles())
-        goto doneDispatching;
-
-    event.setEventPhase(Event::BUBBLING_PHASE);
-    for (size_t i = 1; i < size; ++i) { // Don't do the first element.
-        event.setCurrentTarget(eventTargets[i].get());
-        eventTargets[i]->fireEventListeners(event);
-        if (event.propagationStopped())
-            goto doneDispatching;
-    }
-
-    // FIXME: "...However, we also wanted to integrate the window.onerror feature in
-    //        HTML5. So after we've fired an "error" event, if .preventDefault() was
-    //        never called on the event, we fire an error event on the window (can't
-    //        remember if this happens before or after we abort the transaction).
-    //        This is a separate event, which for example means that even if you
-    //        attach a capturing "error" handler on window, you won't see any events
-    //        unless an error really went unhandled. And you also can't call
-    //        .preventDefault on the error event fired on the window in order to
-    //        prevent the transaction from being aborted. It's purely there for
-    //        error reporting and distinctly different from the event propagating to
-    //        the window.
-    //        
-    //        This is similar to how "error" events are handled in workers.
-    //        
-    //        (I think that so far webkit hasn't implemented the window.onerror
-    //        feature yet, so you probably don't want to fire the separate error
-    //        event on the window until that has been implemented)." -- Jonas Sicking
-
-doneDispatching:
-    event.setCurrentTarget(nullptr);
-    event.setEventPhase(0);
-    return !event.defaultPrevented();
-}
-
-} // namespace WebCore
-
-#endif
diff --git a/Source/WebCore/Modules/indexeddb/IDBEventDispatcher.h b/Source/WebCore/Modules/indexeddb/IDBEventDispatcher.h
deleted file mode 100644 (file)
index 97cb7d6..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#if ENABLE(INDEXED_DATABASE)
-
-#include <wtf/Forward.h>
-
-namespace WebCore {
-
-class Event;
-class EventTarget;
-
-class IDBEventDispatcher {
-public:
-    static bool dispatch(Event&, Vector<RefPtr<EventTarget>>&); // The target first and then its ancestors in order of how the event bubbles.
-
-private:
-    IDBEventDispatcher();
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(INDEXED_DATABASE)
index 268cea1..78da970 100644 (file)
@@ -117,16 +117,16 @@ void IDBOpenDBRequest::cancelForStop()
     connectionProxy().openDBRequestCancelled({ connectionProxy(), *this });
 }
 
-bool IDBOpenDBRequest::dispatchEvent(Event& event)
+void IDBOpenDBRequest::dispatchEvent(Event& event)
 {
     ASSERT(currentThread() == originThreadID());
 
-    bool result = IDBRequest::dispatchEvent(event);
+    auto protectedThis = makeRef(*this);
+
+    IDBRequest::dispatchEvent(event);
 
     if (m_transaction && m_transaction->isVersionChange() && (event.type() == eventNames().errorEvent || event.type() == eventNames().successEvent))
         m_transaction->database().connectionProxy().didFinishHandlingVersionChangeTransaction(m_transaction->database().databaseConnectionIdentifier(), *m_transaction);
-
-    return result;
 }
 
 void IDBOpenDBRequest::onSuccess(const IDBResultData& resultData)
index a15a1dc..8f029b5 100644 (file)
@@ -54,7 +54,7 @@ public:
 private:
     IDBOpenDBRequest(ScriptExecutionContext&, IDBClient::IDBConnectionProxy&, const IDBDatabaseIdentifier&, uint64_t version, IndexedDB::RequestType);
 
-    bool dispatchEvent(Event&) final;
+    void dispatchEvent(Event&) final;
 
     void cancelForStop() final;
 
index 8e68f76..cdc9baf 100644 (file)
 
 #include "DOMException.h"
 #include "Event.h"
+#include "EventDispatcher.h"
 #include "EventNames.h"
 #include "EventQueue.h"
 #include "IDBBindingUtilities.h"
 #include "IDBConnectionProxy.h"
 #include "IDBCursor.h"
 #include "IDBDatabase.h"
-#include "IDBEventDispatcher.h"
 #include "IDBIndex.h"
 #include "IDBKeyData.h"
 #include "IDBObjectStore.h"
@@ -296,7 +296,7 @@ void IDBRequest::enqueueEvent(Ref<Event>&& event)
     scriptExecutionContext()->eventQueue().enqueueEvent(WTFMove(event));
 }
 
-bool IDBRequest::dispatchEvent(Event& event)
+void IDBRequest::dispatchEvent(Event& event)
 {
     LOG(IndexedDB, "IDBRequest::dispatchEvent - %s (%p)", event.type().string().utf8().data(), this);
 
@@ -304,30 +304,28 @@ bool IDBRequest::dispatchEvent(Event& event)
     ASSERT(m_hasPendingActivity);
     ASSERT(!m_contextStopped);
 
+    auto protectedThis = makeRef(*this);
+
     if (event.type() != eventNames().blockedEvent)
         m_readyState = ReadyState::Done;
 
-    Vector<RefPtr<EventTarget>> targets;
-    targets.append(this);
+    Vector<EventTarget*> targets { this };
 
     if (&event == m_openDatabaseSuccessEvent)
         m_openDatabaseSuccessEvent = nullptr;
-    else if (m_transaction && !m_transaction->isFinished()) {
-        targets.append(m_transaction);
-        targets.append(m_transaction->db());
-    }
+    else if (m_transaction && !m_transaction->isFinished())
+        targets = { this, m_transaction.get(), &m_transaction->database() };
 
     m_hasPendingActivity = false;
 
     m_cursorRequestNotifier = nullptr;
 
-    bool dontPreventDefault;
     {
         TransactionActivator activator(m_transaction.get());
-        dontPreventDefault = IDBEventDispatcher::dispatch(event, targets);
+        EventDispatcher::dispatchEvent(targets, event);
     }
 
-    // IDBEventDispatcher::dispatch() might have set the pending activity flag back to true, suggesting the request will be reused.
+    // Dispatching the event might have set the pending activity flag back to true, suggesting the request will be reused.
     // We might also re-use the request if this event was the upgradeneeded event for an IDBOpenDBRequest.
     if (!m_hasPendingActivity)
         m_hasPendingActivity = isOpenDBRequest() && (event.type() == eventNames().upgradeneededEvent || event.type() == eventNames().blockedEvent);
@@ -336,15 +334,13 @@ bool IDBRequest::dispatchEvent(Event& event)
     if (m_transaction && !m_pendingCursor && event.type() != eventNames().blockedEvent)
         m_transaction->removeRequest(*this);
 
-    if (dontPreventDefault && event.type() == eventNames().errorEvent && m_transaction && !m_transaction->isFinishedOrFinishing()) {
+    if (!event.defaultPrevented() && event.type() == eventNames().errorEvent && m_transaction && !m_transaction->isFinishedOrFinishing()) {
         ASSERT(m_domError);
         m_transaction->abortDueToFailedRequest(*m_domError);
     }
 
     if (m_transaction)
         m_transaction->finishedDispatchEventForRequest(*this);
-
-    return dontPreventDefault;
 }
 
 void IDBRequest::uncaughtExceptionInEventHandler()
index b1f7b4a..1f92a55 100644 (file)
@@ -118,7 +118,7 @@ protected:
     IDBRequest(ScriptExecutionContext&, IDBClient::IDBConnectionProxy&);
 
     void enqueueEvent(Ref<Event>&&);
-    bool dispatchEvent(Event&) override;
+    void dispatchEvent(Event&) override;
 
     void setResult(Ref<IDBDatabase>&&);
 
index 6460e86..57b63c3 100644 (file)
 #include "DOMStringList.h"
 #include "DOMWindow.h"
 #include "Event.h"
+#include "EventDispatcher.h"
 #include "EventNames.h"
 #include "EventQueue.h"
 #include "IDBCursorWithValue.h"
 #include "IDBDatabase.h"
 #include "IDBError.h"
-#include "IDBEventDispatcher.h"
 #include "IDBGetRecordData.h"
 #include "IDBIndex.h"
 #include "IDBIterateCursorData.h"
@@ -614,7 +614,7 @@ void IDBTransaction::enqueueEvent(Ref<Event>&& event)
     scriptExecutionContext()->eventQueue().enqueueEvent(WTFMove(event));
 }
 
-bool IDBTransaction::dispatchEvent(Event& event)
+void IDBTransaction::dispatchEvent(Event& event)
 {
     LOG(IndexedDB, "IDBTransaction::dispatchEvent");
 
@@ -624,11 +624,9 @@ bool IDBTransaction::dispatchEvent(Event& event)
     ASSERT(event.target() == this);
     ASSERT(event.type() == eventNames().completeEvent || event.type() == eventNames().abortEvent);
 
-    Vector<RefPtr<EventTarget>> targets;
-    targets.append(this);
-    targets.append(db());
+    auto protectedThis = makeRef(*this);
 
-    bool result = IDBEventDispatcher::dispatch(event, targets);
+    EventDispatcher::dispatchEvent({ this, m_database.ptr() }, event);
 
     if (isVersionChange()) {
         ASSERT(m_openDBRequest);
@@ -643,8 +641,6 @@ bool IDBTransaction::dispatchEvent(Event& event)
 
         m_openDBRequest = nullptr;
     }
-
-    return result;
 }
 
 Ref<IDBObjectStore> IDBTransaction::createObjectStore(const IDBObjectStoreInfo& info)
index fdb267d..ecac146 100644 (file)
@@ -85,7 +85,7 @@ public:
     void refEventTarget() final { ThreadSafeRefCounted::ref(); }
     void derefEventTarget() final { ThreadSafeRefCounted::deref(); }
     using EventTarget::dispatchEvent;
-    bool dispatchEvent(Event&) final;
+    void dispatchEvent(Event&) final;
 
     using ThreadSafeRefCounted<IDBTransaction>::ref;
     using ThreadSafeRefCounted<IDBTransaction>::deref;
index 0f9f388..da5021c 100644 (file)
@@ -594,10 +594,10 @@ RTCRtpParameters RTCPeerConnection::getParameters(RTCRtpSender& sender) const
     return m_backend->getParameters(sender);
 }
 
-bool RTCPeerConnection::dispatchEvent(Event& event)
+void RTCPeerConnection::dispatchEvent(Event& event)
 {
     DEBUG_LOG(LOGIDENTIFIER, "dispatching '", event.type(), "'");
-    return EventTarget::dispatchEvent(event);
+    EventTarget::dispatchEvent(event);
 }
 
 #if !RELEASE_LOG_DISABLED
index c749f18..f1c9717 100644 (file)
@@ -181,7 +181,7 @@ private:
     // EventTarget implementation.
     void refEventTarget() final { ref(); }
     void derefEventTarget() final { deref(); }
-    bool dispatchEvent(Event&) final;
+    void dispatchEvent(Event&) final;
 
     // ActiveDOMObject
     WEBCORE_EXPORT void stop() final;
index c1e43cd..9b133a4 100644 (file)
@@ -528,30 +528,18 @@ void PaymentRequest::shippingAddressChanged(Ref<PaymentAddress>&& shippingAddres
 {
     ASSERT(m_state == State::Interactive);
     m_shippingAddress = WTFMove(shippingAddress);
-    auto event = PaymentRequestUpdateEvent::create(eventNames().shippingaddresschangeEvent, *this);
-    dispatchEvent(event.get());
+    if (m_isUpdating)
+        return;
+    dispatchEvent(PaymentRequestUpdateEvent::create(eventNames().shippingaddresschangeEvent, *this));
 }
 
 void PaymentRequest::shippingOptionChanged(const String& shippingOption)
 {
     ASSERT(m_state == State::Interactive);
     m_shippingOption = shippingOption;
-    auto event = PaymentRequestUpdateEvent::create(eventNames().shippingoptionchangeEvent, *this);
-    dispatchEvent(event.get());
-}
-
-bool PaymentRequest::dispatchEvent(Event& event)
-{
-    if (!event.isTrusted())
-        return EventTargetWithInlineData::dispatchEvent(event);
-
     if (m_isUpdating)
-        return false;
-
-    if (m_state != State::Interactive)
-        return false;
-
-    return EventTargetWithInlineData::dispatchEvent(event);
+        return;
+    dispatchEvent(PaymentRequestUpdateEvent::create(eventNames().shippingoptionchangeEvent, *this));
 }
 
 ExceptionOr<void> PaymentRequest::updateWith(Event& event, Ref<DOMPromise>&& promise)
index 295272d..d5c7c3e 100644 (file)
@@ -75,9 +75,6 @@ public:
     void complete(std::optional<PaymentComplete>&&);
     void cancel();
 
-    // EventTarget
-    bool dispatchEvent(Event&) final;
-
     using MethodIdentifier = Variant<String, URL>;
     using RefCounted<PaymentRequest>::ref;
     using RefCounted<PaymentRequest>::deref;
index 1f072b0..0099a33 100644 (file)
@@ -70,7 +70,6 @@ Modules/indexeddb/IDBCursor.cpp
 Modules/indexeddb/IDBCursorWithValue.cpp
 Modules/indexeddb/IDBDatabase.cpp
 Modules/indexeddb/IDBDatabaseIdentifier.cpp
-Modules/indexeddb/IDBEventDispatcher.cpp
 Modules/indexeddb/IDBFactory.cpp
 Modules/indexeddb/IDBGetAllResult.cpp
 Modules/indexeddb/IDBGetResult.cpp
index 301d810..2aab26a 100644 (file)
                5185FC7E1BB4C4E80012898F /* IDBCursorWithValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 51645B431B9F889B00F789CE /* IDBCursorWithValue.h */; };
                5185FC811BB4C4E80012898F /* IDBDatabase.h in Headers */ = {isa = PBXBuildFile; fileRef = 51645B451B9F889B00F789CE /* IDBDatabase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5185FC871BB4C4E80012898F /* IDBDatabaseIdentifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 5103105F1BA8E090003329C0 /* IDBDatabaseIdentifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               5185FC8B1BB4C4E80012898F /* IDBEventDispatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 51D71987181106DF0016DC51 /* IDBEventDispatcher.h */; };
                5185FC8D1BB4C4E80012898F /* IDBFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 51645B471B9F889B00F789CE /* IDBFactory.h */; };
                5185FC8F1BB4C4E80012898F /* IDBGetResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 5123AF1C18918AE40031CDC9 /* IDBGetResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5185FC911BB4C4E80012898F /* IDBIndex.h in Headers */ = {isa = PBXBuildFile; fileRef = 51645B491B9F889B00F789CE /* IDBIndex.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51D71977181106DF0016DC51 /* IDBCursor.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = IDBCursor.idl; sourceTree = "<group>"; };
                51D7197B181106DF0016DC51 /* IDBCursorWithValue.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = IDBCursorWithValue.idl; sourceTree = "<group>"; };
                51D7197E181106DF0016DC51 /* IDBDatabase.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = IDBDatabase.idl; sourceTree = "<group>"; };
-               51D71986181106DF0016DC51 /* IDBEventDispatcher.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBEventDispatcher.cpp; sourceTree = "<group>"; };
-               51D71987181106DF0016DC51 /* IDBEventDispatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBEventDispatcher.h; sourceTree = "<group>"; };
                51D7198A181106DF0016DC51 /* IDBFactory.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = IDBFactory.idl; sourceTree = "<group>"; };
                51D71990181106E00016DC51 /* IDBIndex.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = IDBIndex.idl; sourceTree = "<group>"; };
                51D71991181106E00016DC51 /* IDBKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IDBKey.cpp; sourceTree = "<group>"; };
                                51D7197E181106DF0016DC51 /* IDBDatabase.idl */,
                                5103105E1BA8E090003329C0 /* IDBDatabaseIdentifier.cpp */,
                                5103105F1BA8E090003329C0 /* IDBDatabaseIdentifier.h */,
-                               51D71986181106DF0016DC51 /* IDBEventDispatcher.cpp */,
-                               51D71987181106DF0016DC51 /* IDBEventDispatcher.h */,
                                51645B461B9F889B00F789CE /* IDBFactory.cpp */,
                                51645B471B9F889B00F789CE /* IDBFactory.h */,
                                51D7198A181106DF0016DC51 /* IDBFactory.idl */,
                                5185FC871BB4C4E80012898F /* IDBDatabaseIdentifier.h in Headers */,
                                51BA4AC41BBB5CD800DF3D6D /* IDBDatabaseInfo.h in Headers */,
                                5148453F1BB9D07E006A72ED /* IDBError.h in Headers */,
-                               5185FC8B1BB4C4E80012898F /* IDBEventDispatcher.h in Headers */,
                                5185FC8D1BB4C4E80012898F /* IDBFactory.h in Headers */,
                                519DBC6F1DC011A700329BF5 /* IDBGetAllRecordsData.h in Headers */,
                                519DBC721DC10F5200329BF5 /* IDBGetAllResult.h in Headers */,
index 7fba0c6..904cfb0 100644 (file)
@@ -273,7 +273,8 @@ bool Element::dispatchMouseEvent(const PlatformMouseEvent& platformEvent, const
         return true; // Shouldn't happen.
 
     ASSERT(!mouseEvent->target() || mouseEvent->target() != relatedTarget);
-    bool didNotSwallowEvent = dispatchEvent(mouseEvent) && !mouseEvent->defaultHandled();
+    dispatchEvent(mouseEvent);
+    bool didNotSwallowEvent = !mouseEvent->defaultPrevented() && !mouseEvent->defaultHandled();
 
     if (mouseEvent->type() == eventNames().clickEvent && mouseEvent->detail() == 2) {
         // Special case: If it's a double click event, we also send the dblclick event. This is not part
@@ -295,30 +296,34 @@ bool Element::dispatchMouseEvent(const PlatformMouseEvent& platformEvent, const
     return didNotSwallowEvent;
 }
 
-
-bool Element::dispatchWheelEvent(const PlatformWheelEvent& event)
+bool Element::dispatchWheelEvent(const PlatformWheelEvent& platformEvent)
 {
-    Ref<WheelEvent> wheelEvent = WheelEvent::create(event, document().defaultView());
+    auto event = WheelEvent::create(platformEvent, document().defaultView());
 
     // Events with no deltas are important because they convey platform information about scroll gestures
     // and momentum beginning or ending. However, those events should not be sent to the DOM since some
     // websites will break. They need to be dispatched because dispatching them will call into the default
     // event handler, and our platform code will correctly handle the phase changes. Calling stopPropogation()
     // will prevent the event from being sent to the DOM, but will still call the default event handler.
-    if (!event.deltaX() && !event.deltaY())
-        wheelEvent->stopPropagation();
+    // FIXME: Move this logic into WheelEvent::create.
+    if (!platformEvent.deltaX() && !platformEvent.deltaY())
+        event->stopPropagation();
 
-    return EventDispatcher::dispatchEvent(*this, wheelEvent) && !wheelEvent->defaultHandled();
+    dispatchEvent(event);
+    return !event->defaultPrevented() && !event->defaultHandled();
 }
 
 bool Element::dispatchKeyEvent(const PlatformKeyboardEvent& platformEvent)
 {
-    Ref<KeyboardEvent> event = KeyboardEvent::create(platformEvent, document().defaultView());
+    auto event = KeyboardEvent::create(platformEvent, document().defaultView());
+
     if (Frame* frame = document().frame()) {
-        if (frame->eventHandler().accessibilityPreventsEventPropogation(event))
+        if (frame->eventHandler().accessibilityPreventsEventPropagation(event))
             event->stopPropagation();
     }
-    return EventDispatcher::dispatchEvent(*this, event) && !event->defaultHandled();
+
+    dispatchEvent(event);
+    return !event->defaultPrevented() && !event->defaultHandled();
 }
 
 void Element::dispatchSimulatedClick(Event* underlyingEvent, SimulatedClickMouseEventOptions eventOptions, SimulatedClickVisualOptions visualOptions)
@@ -2489,18 +2494,16 @@ void Element::dispatchFocusOutEvent(const AtomicString& eventType, RefPtr<Elemen
 
 void Element::dispatchFocusEvent(RefPtr<Element>&& oldFocusedElement, FocusDirection)
 {
-    if (document().page())
-        document().page()->chrome().client().elementDidFocus(*this);
-
-    EventDispatcher::dispatchEvent(*this, FocusEvent::create(eventNames().focusEvent, false, false, document().defaultView(), 0, WTFMove(oldFocusedElement)));
+    if (auto* page = document().page())
+        page->chrome().client().elementDidFocus(*this);
+    dispatchEvent(FocusEvent::create(eventNames().focusEvent, false, false, document().defaultView(), 0, WTFMove(oldFocusedElement)));
 }
 
 void Element::dispatchBlurEvent(RefPtr<Element>&& newFocusedElement)
 {
-    if (document().page())
-        document().page()->chrome().client().elementDidBlur(*this);
-
-    EventDispatcher::dispatchEvent(*this, FocusEvent::create(eventNames().blurEvent, false, false, document().defaultView(), 0, WTFMove(newFocusedElement)));
+    if (auto* page = document().page())
+        page->chrome().client().elementDidBlur(*this);
+    dispatchEvent(FocusEvent::create(eventNames().blurEvent, false, false, document().defaultView(), 0, WTFMove(newFocusedElement)));
 }
 
 void Element::dispatchWebKitImageReadyEventForTesting()
index 14b5229..f438206 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
  * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2003, 2005, 2006, 2008, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -114,76 +114,6 @@ bool Event::composed() const
         || isInputEvent();
 }
 
-EventInterface Event::eventInterface() const
-{
-    return EventInterfaceType;
-}
-
-bool Event::isUIEvent() const
-{
-    return false;
-}
-
-bool Event::isMouseEvent() const
-{
-    return false;
-}
-
-bool Event::isFocusEvent() const
-{
-    return false;
-}
-
-bool Event::isKeyboardEvent() const
-{
-    return false;
-}
-
-bool Event::isInputEvent() const
-{
-    return false;
-}
-
-bool Event::isCompositionEvent() const
-{
-    return false;
-}
-
-bool Event::isTouchEvent() const
-{
-    return false;
-}
-
-bool Event::isClipboardEvent() const
-{
-    return false;
-}
-
-bool Event::isBeforeTextInsertedEvent() const
-{
-    return false;
-}
-
-bool Event::isBeforeUnloadEvent() const
-{
-    return false;
-}
-
-bool Event::isErrorEvent() const
-{
-    return false;
-}
-
-bool Event::isTextEvent() const
-{
-    return false;
-}
-
-bool Event::isWheelEvent() const
-{
-    return false;
-}
-
 void Event::setTarget(RefPtr<EventTarget>&& target)
 {
     if (m_target == target)
@@ -206,13 +136,9 @@ Vector<EventTarget*> Event::composedPath() const
     return m_eventPath->computePathUnclosedToTarget(*m_currentTarget);
 }
 
-void Event::receivedTarget()
-{
-}
-
 void Event::setUnderlyingEvent(Event* underlyingEvent)
 {
-    // Prohibit creation of a cycle -- just do nothing in that case.
+    // Prohibit creation of a cycle by doing nothing if a cycle would be created.
     for (Event* event = underlyingEvent; event; event = event->underlyingEvent()) {
         if (event == this)
             return;
@@ -234,4 +160,13 @@ DOMHighResTimeStamp Event::timeStampForBindings(ScriptExecutionContext& context)
     return performance->relativeTimeFromTimeOriginInReducedResolution(m_createTime);
 }
 
+void Event::resetAfterDispatch()
+{
+    m_eventPath = nullptr;
+    m_currentTarget = nullptr;
+    m_eventPhase = NONE;
+    m_propagationStopped = false;
+    m_immediatePropagationStopped = false;
+}
+
 } // namespace WebCore
index 5885c3a..3f095e1 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
  * Copyright (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
  * Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 #include "ExceptionOr.h"
 #include "ScriptWrappable.h"
 #include <wtf/MonotonicTime.h>
-#include <wtf/RefCounted.h>
 #include <wtf/TypeCasts.h>
 #include <wtf/text/AtomicString.h>
 
 namespace WebCore {
 
-class DataTransfer;
 class EventPath;
 class EventTarget;
-class HTMLIFrameElement;
 class ScriptExecutionContext;
 
 enum EventInterface {
@@ -54,26 +51,15 @@ public:
     enum class IsTrusted { No, Yes };
 
     enum PhaseType { 
-        NONE                = 0,
-        CAPTURING_PHASE     = 1, 
-        AT_TARGET           = 2,
-        BUBBLING_PHASE      = 3 
+        NONE = 0,
+        CAPTURING_PHASE = 1,
+        AT_TARGET = 2,
+        BUBBLING_PHASE = 3
     };
 
-    static Ref<Event> create(const AtomicString& type, bool canBubble, bool cancelable)
-    {
-        return adoptRef(*new Event(type, canBubble, cancelable));
-    }
-
-    static Ref<Event> createForBindings()
-    {
-        return adoptRef(*new Event);
-    }
-
-    static Ref<Event> create(const AtomicString& type, const EventInit& initializer, IsTrusted isTrusted = IsTrusted::No)
-    {
-        return adoptRef(*new Event(type, initializer, isTrusted));
-    }
+    static Ref<Event> create(const AtomicString& type, bool canBubble, bool cancelable);
+    static Ref<Event> createForBindings();
+    static Ref<Event> create(const AtomicString& type, const EventInit&, IsTrusted = IsTrusted::No);
 
     virtual ~Event();
 
@@ -91,7 +77,7 @@ public:
     void setCurrentTarget(EventTarget*);
 
     unsigned short eventPhase() const { return m_eventPhase; }
-    void setEventPhase(unsigned short eventPhase) { m_eventPhase = eventPhase; }
+    void setEventPhase(PhaseType phase) { m_eventPhase = phase; }
 
     bool bubbles() const { return m_canBubble; }
     bool cancelable() const { return m_cancelable; }
@@ -101,7 +87,6 @@ public:
     MonotonicTime timeStamp() const { return m_createTime; }
 
     void setEventPath(const EventPath& path) { m_eventPath = &path; }
-    void clearEventPath() { m_eventPath = nullptr; }
     Vector<EventTarget*> composedPath() const;
 
     void stopPropagation() { m_propagationStopped = true; }
@@ -109,49 +94,34 @@ public:
 
     bool isTrusted() const { return m_isTrusted; }
     void setUntrusted() { m_isTrusted = false; }
-    
-    // IE Extensions
-    EventTarget* srcElement() const { return target(); } // MSIE extension - "the object that fired the event"
 
     bool legacyReturnValue() const { return !defaultPrevented(); }
     void setLegacyReturnValue(bool returnValue) { setDefaultPrevented(!returnValue); }
 
-    virtual EventInterface eventInterface() const;
-
-    // These events are general classes of events.
-    virtual bool isUIEvent() const;
-    virtual bool isMouseEvent() const;
-    virtual bool isFocusEvent() const;
-    virtual bool isKeyboardEvent() const;
-    virtual bool isInputEvent() const;
-    virtual bool isCompositionEvent() const;
-    virtual bool isTouchEvent() const;
-
-    // These events lack a DOM interface.
-    virtual bool isClipboardEvent() const;
-    virtual bool isBeforeTextInsertedEvent() const;
-
-    virtual bool isBeforeUnloadEvent() const;
-
-    virtual bool isErrorEvent() const;
-    virtual bool isTextEvent() const;
-    virtual bool isWheelEvent() const;
-
-#if ENABLE(INDEXED_DATABASE)
+    virtual EventInterface eventInterface() const { return EventInterfaceType; }
+
+    virtual bool isBeforeTextInsertedEvent() const { return false; }
+    virtual bool isBeforeUnloadEvent() const { return false; }
+    virtual bool isClipboardEvent() const { return false; }
+    virtual bool isCompositionEvent() const { return false; }
+    virtual bool isErrorEvent() const { return false; }
+    virtual bool isFocusEvent() const { return false; }
+    virtual bool isInputEvent() const { return false; }
+    virtual bool isKeyboardEvent() const { return false; }
+    virtual bool isMouseEvent() const { return false; }
+    virtual bool isTextEvent() const { return false; }
+    virtual bool isTouchEvent() const { return false; }
+    virtual bool isUIEvent() const { return false; }
     virtual bool isVersionChangeEvent() const { return false; }
-#endif
+    virtual bool isWheelEvent() const { return false; }
 
     bool propagationStopped() const { return m_propagationStopped || m_immediatePropagationStopped; }
     bool immediatePropagationStopped() const { return m_immediatePropagationStopped; }
 
-    void resetPropagationFlags();
+    void resetAfterDispatch();
 
     bool defaultPrevented() const { return m_defaultPrevented; }
-    void preventDefault()
-    {
-        if (m_cancelable && !m_isExecutingPassiveEventListener)
-            m_defaultPrevented = true;
-    }
+    void preventDefault();
     void setDefaultPrevented(bool defaultPrevented) { m_defaultPrevented = defaultPrevented; }
 
     bool defaultHandled() const { return m_defaultHandled; }
@@ -173,12 +143,12 @@ public:
     virtual void setRelatedTarget(EventTarget&) { }
 
 protected:
-    Event(IsTrusted = IsTrusted::No);
+    explicit Event(IsTrusted = IsTrusted::No);
     WEBCORE_EXPORT Event(const AtomicString& type, bool canBubble, bool cancelable);
     Event(const AtomicString& type, bool canBubble, bool cancelable, MonotonicTime timestamp);
     Event(const AtomicString& type, const EventInit&, IsTrusted);
 
-    virtual void receivedTarget();
+    virtual void receivedTarget() { }
 
 private:
     AtomicString m_type;
@@ -195,7 +165,7 @@ private:
     bool m_isTrusted { false };
     bool m_isExecutingPassiveEventListener { false };
 
-    unsigned short m_eventPhase { 0 };
+    PhaseType m_eventPhase { NONE };
     RefPtr<EventTarget> m_currentTarget;
     const EventPath* m_eventPath { nullptr };
     RefPtr<EventTarget> m_target;
@@ -204,10 +174,27 @@ private:
     RefPtr<Event> m_underlyingEvent;
 };
 
-inline void Event::resetPropagationFlags()
+inline Ref<Event> Event::create(const AtomicString& type, bool canBubble, bool cancelable)
+{
+    return adoptRef(*new Event(type, canBubble, cancelable));
+}
+
+inline Ref<Event> Event::createForBindings()
+{
+    return adoptRef(*new Event);
+}
+
+inline Ref<Event> Event::create(const AtomicString& type, const EventInit& initializer, IsTrusted isTrusted)
+{
+    return adoptRef(*new Event(type, initializer, isTrusted));
+}
+
+inline void Event::preventDefault()
 {
-    m_propagationStopped = false;
-    m_immediatePropagationStopped = false;
+    if (m_cancelable && !m_isExecutingPassiveEventListener)
+        m_defaultPrevented = true;
+    // FIXME: Specification suggests we log something to the console when preventDefault is called but
+    // doesn't do anything because the event is not cancelable or is executing passive event listeners.
 }
 
 inline void Event::setCancelBubble(bool cancel)
index 87ae1fb..1e6a26a 100644 (file)
@@ -55,6 +55,6 @@ typedef double DOMHighResTimeStamp;
     void initEvent(DOMString type, optional boolean bubbles = false, optional boolean cancelable = false); // Historical.
 
     // IE extensions that may get standardized (https://github.com/whatwg/dom/issues/334).
-    readonly attribute EventTarget srcElement;
+    [ImplementedAs=target] readonly attribute EventTarget srcElement;
     [ImplementedAs=legacyReturnValue] attribute boolean returnValue;
 };
index c7e4130..b680b4c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -39,7 +40,6 @@ EventContext::EventContext(Node* node, EventTarget* currentTarget, EventTarget*
     , m_currentTarget(currentTarget)
     , m_target(target)
 {
-    ASSERT(m_node);
     ASSERT(!isUnreachableNode(m_target.get()));
 }
 
@@ -49,7 +49,11 @@ void EventContext::handleLocalEvents(Event& event) const
 {
     event.setTarget(m_target.get());
     event.setCurrentTarget(m_currentTarget.get());
-    m_node->handleLocalEvents(event);
+    // FIXME: Consider merging handleLocalEvents and fireEventListeners.
+    if (m_node)
+        m_node->handleLocalEvents(event);
+    else
+        m_currentTarget->fireEventListeners(event);
 }
 
 bool EventContext::isMouseOrFocusEventContext() const
@@ -62,8 +66,8 @@ bool EventContext::isTouchEventContext() const
     return false;
 }
 
-MouseOrFocusEventContext::MouseOrFocusEventContext(Node* node, EventTarget* currentTarget, EventTarget* target)
-    : EventContext(node, currentTarget, target)
+MouseOrFocusEventContext::MouseOrFocusEventContext(Node& node, EventTarget* currentTarget, EventTarget* target)
+    : EventContext(&node, currentTarget, target)
 {
 }
 
@@ -83,8 +87,8 @@ bool MouseOrFocusEventContext::isMouseOrFocusEventContext() const
 
 #if ENABLE(TOUCH_EVENTS)
 
-TouchEventContext::TouchEventContext(Node* node, EventTarget* currentTarget, EventTarget* target)
-    : EventContext(node, currentTarget, target)
+TouchEventContext::TouchEventContext(Node& node, EventTarget* currentTarget, EventTarget* target)
+    : EventContext(&node, currentTarget, target)
     , m_touches(TouchList::create())
     , m_targetTouches(TouchList::create())
     , m_changedTouches(TouchList::create())
@@ -95,16 +99,13 @@ TouchEventContext::~TouchEventContext() = default;
 
 void TouchEventContext::handleLocalEvents(Event& event) const
 {
-#if !ASSERT_DISABLED
-    checkReachability(m_touches.get());
-    checkReachability(m_targetTouches.get());
-    checkReachability(m_changedTouches.get());
-#endif
-    ASSERT(is<TouchEvent>(event));
-    TouchEvent& touchEvent = downcast<TouchEvent>(event);
-    touchEvent.setTouches(m_touches.get());
-    touchEvent.setTargetTouches(m_targetTouches.get());
-    touchEvent.setChangedTouches(m_changedTouches.get());
+    checkReachability(m_touches);
+    checkReachability(m_targetTouches);
+    checkReachability(m_changedTouches);
+    auto& touchEvent = downcast<TouchEvent>(event);
+    touchEvent.setTouches(m_touches.ptr());
+    touchEvent.setTargetTouches(m_targetTouches.ptr());
+    touchEvent.setChangedTouches(m_changedTouches.ptr());
     EventContext::handleLocalEvents(event);
 }
 
@@ -115,7 +116,7 @@ bool TouchEventContext::isTouchEventContext() const
 
 #if !ASSERT_DISABLED
 
-void TouchEventContext::checkReachability(TouchList* touchList) const
+void TouchEventContext::checkReachability(const Ref<TouchList>& touchList) const
 {
     size_t length = touchList->length();
     for (size_t i = 0; i < length; ++i)
@@ -124,6 +125,6 @@ void TouchEventContext::checkReachability(TouchList* touchList) const
 
 #endif
 
-#endif // ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
+#endif // ENABLE(TOUCH_EVENTS)
 
 }
index 97da8f8..70789af 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2010 Google Inc. All Rights Reserved.
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,15 +36,15 @@ class TouchList;
 class EventContext {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    // FIXME: Use ContainerNode instead of Node.
     EventContext(Node*, EventTarget* currentTarget, EventTarget*);
     virtual ~EventContext();
 
     Node* node() const { return m_node.get(); }
     EventTarget* currentTarget() const { return m_currentTarget.get(); }
     EventTarget* target() const { return m_target.get(); }
-    bool currentTargetSameAsTarget() const { return m_currentTarget.get() == m_target.get(); }
+
     virtual void handleLocalEvents(Event&) const;
+
     virtual bool isMouseOrFocusEventContext() const;
     virtual bool isTouchEventContext() const;
 
@@ -59,7 +60,7 @@ protected:
 
 class MouseOrFocusEventContext final : public EventContext {
 public:
-    MouseOrFocusEventContext(Node*, EventTarget* currentTarget, EventTarget*);
+    MouseOrFocusEventContext(Node&, EventTarget* currentTarget, EventTarget*);
     virtual ~MouseOrFocusEventContext();
 
     Node* relatedTarget() const { return m_relatedTarget.get(); }
@@ -76,27 +77,21 @@ private:
 
 class TouchEventContext final : public EventContext {
 public:
-    TouchEventContext(Node*, EventTarget* currentTarget, EventTarget*);
+    TouchEventContext(Node&, EventTarget* currentTarget, EventTarget*);
     virtual ~TouchEventContext();
 
-    void handleLocalEvents(Event&) const override;
-    bool isTouchEventContext() const override;
-
-    enum TouchListType { Touches, TargetTouches, ChangedTouches, NotTouchList };
-    TouchList* touchList(TouchListType);
-
-    TouchList* touches() { return m_touches.get(); }
-    TouchList* targetTouches() { return m_targetTouches.get(); }
-    TouchList* changedTouches() { return m_changedTouches.get(); }
+    enum TouchListType { Touches, TargetTouches, ChangedTouches };
+    TouchList& touchList(TouchListType);
 
 private:
-#if !ASSERT_DISABLED
-    void checkReachability(TouchList*) const;
-#endif
+    void handleLocalEvents(Event&) const final;
+    bool isTouchEventContext() const final;
 
-    RefPtr<TouchList> m_touches;
-    RefPtr<TouchList> m_targetTouches;
-    RefPtr<TouchList> m_changedTouches;
+    void checkReachability(const Ref<TouchList>&) const;
+
+    Ref<TouchList> m_touches;
+    Ref<TouchList> m_targetTouches;
+    Ref<TouchList> m_changedTouches;
 };
 
 #endif // ENABLE(TOUCH_EVENTS)
@@ -119,7 +114,7 @@ inline void MouseOrFocusEventContext::setRelatedTarget(Node* relatedTarget)
 
 #if ENABLE(TOUCH_EVENTS)
 
-inline TouchList* TouchEventContext::touchList(TouchListType type)
+inline TouchList& TouchEventContext::touchList(TouchListType type)
 {
     switch (type) {
     case Touches:
@@ -128,11 +123,17 @@ inline TouchList* TouchEventContext::touchList(TouchListType type)
         return m_targetTouches.get();
     case ChangedTouches:
         return m_changedTouches.get();
-    case NotTouchList:
-        break;
     }
     ASSERT_NOT_REACHED();
-    return nullptr;
+    return m_touches.get();
+}
+
+#endif
+
+#if ENABLE(TOUCH_EVENTS) && ASSERT_DISABLED
+
+inline void TouchEventContext::checkReachability(const Ref<TouchList>&) const
+{
 }
 
 #endif
index 6b785e9..fb4a5cb 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  * Copyright (C) 2010, 2011, 2012, 2013 Google Inc. All rights reserved.
@@ -29,7 +29,6 @@
 #include "CompositionEvent.h"
 #include "EventContext.h"
 #include "EventPath.h"
-#include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameView.h"
 #include "HTMLInputElement.h"
@@ -47,12 +46,12 @@ namespace WebCore {
 
 void EventDispatcher::dispatchScopedEvent(Node& node, Event& event)
 {
-    // We need to set the target here because it can go away by the time we actually fire the event.
+    // Need to set the target here so the scoped event queue knows which node to dispatch to.
     event.setTarget(EventPath::eventTargetRespectingTargetRules(node));
     ScopedEventQueue::singleton().enqueueEvent(event);
 }
 
-static void callDefaultEventHandlersInTheBubblingOrder(Event& event, const EventPath& path)
+static void callDefaultEventHandlersInBubblingOrder(Event& event, const EventPath& path)
 {
     if (path.isEmpty())
         return;
@@ -80,7 +79,7 @@ static void dispatchEventInDOM(Event& event, const EventPath& path)
 
     for (size_t i = path.size() - 1; i > 0; --i) {
         const EventContext& eventContext = path.contextAt(i);
-        if (eventContext.currentTargetSameAsTarget())
+        if (eventContext.currentTarget() == eventContext.target())
             continue;
         eventContext.handleLocalEvents(event);
         if (event.propagationStopped())
@@ -96,7 +95,7 @@ static void dispatchEventInDOM(Event& event, const EventPath& path)
     size_t size = path.size();
     for (size_t i = 1; i < size; ++i) {
         const EventContext& eventContext = path.contextAt(i);
-        if (eventContext.currentTargetSameAsTarget())
+        if (eventContext.currentTarget() == eventContext.target())
             event.setEventPhase(Event::AT_TARGET);
         else if (event.bubbles())
             event.setEventPhase(Event::BUBBLING_PHASE);
@@ -128,26 +127,20 @@ static bool shouldSuppressEventDispatchInDOM(Node& node, Event& event)
     return is<CompositionEvent>(event) || is<InputEvent>(event) || is<KeyboardEvent>(event);
 }
 
-bool EventDispatcher::dispatchEvent(Node& node, Event& event)
+void EventDispatcher::dispatchEvent(Node& node, Event& event)
 {
     ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::InMainThread::isEventDispatchAllowedInSubtree(node));
-    Ref<Node> protectedNode(node);
-    RefPtr<FrameView> view = node.document().view();
-    EventPath eventPath(node, event);
 
-    if (EventTarget* relatedTarget = event.relatedTarget())
-        eventPath.setRelatedTarget(node, *relatedTarget);
-#if ENABLE(TOUCH_EVENTS)
-    if (is<TouchEvent>(event))
-        eventPath.retargetTouchLists(downcast<TouchEvent>(event));
-#endif
+    auto protectedNode = makeRef(node);
+    auto protectedView = makeRefPtr(node.document().view());
+
+    EventPath eventPath { node, event };
 
     ChildNodesLazySnapshot::takeChildNodesLazySnapshot();
 
-    EventTarget* target = EventPath::eventTargetRespectingTargetRules(node);
-    event.setTarget(target);
+    event.setTarget(EventPath::eventTargetRespectingTargetRules(node));
     if (!event.target())
-        return true;
+        return;
 
     InputElementClickState clickHandlingState;
     if (is<HTMLInputElement>(node))
@@ -159,14 +152,9 @@ bool EventDispatcher::dispatchEvent(Node& node, Event& event)
     if (!event.propagationStopped() && !eventPath.isEmpty()) {
         event.setEventPath(eventPath);
         dispatchEventInDOM(event, eventPath);
-        event.clearEventPath();
     }
 
-    auto* finalTarget = event.target();
-    event.setTarget(EventPath::eventTargetRespectingTargetRules(node));
-    event.setCurrentTarget(nullptr);
-    event.resetPropagationFlags();
-    event.setEventPhase(Event::NONE);
+    event.resetAfterDispatch();
 
     if (clickHandlingState.stateful)
         downcast<HTMLInputElement>(node).didDispatchClickEvent(event, clickHandlingState);
@@ -174,13 +162,26 @@ bool EventDispatcher::dispatchEvent(Node& node, Event& event)
     // 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
     // implementation detail and not part of the DOM.
-    if (!event.defaultPrevented() && !event.defaultHandled())
-        callDefaultEventHandlersInTheBubblingOrder(event, eventPath);
-
-    event.setTarget(finalTarget);
-    event.setCurrentTarget(nullptr);
+    if (!event.defaultPrevented() && !event.defaultHandled()) {
+        // FIXME: Not clear why we need to reset the target for the default event handlers.
+        // We should research this, and remove this code if possible.
+        auto* finalTarget = event.target();
+        event.setTarget(EventPath::eventTargetRespectingTargetRules(node));
+        callDefaultEventHandlersInBubblingOrder(event, eventPath);
+        event.setTarget(finalTarget);
+    }
+}
 
-    return !event.defaultPrevented();
+void EventDispatcher::dispatchEvent(const Vector<EventTarget*>& targets, Event& event)
+{
+    ASSERT(targets.size() >= 1);
+    ASSERT(*targets.begin());
+
+    EventPath eventPath { targets };
+    event.setTarget(*targets.begin());
+    event.setEventPath(eventPath);
+    dispatchEventInDOM(event, eventPath);
+    event.resetAfterDispatch();
 }
 
 }
index c098c22..05abef5 100644 (file)
@@ -1,11 +1,6 @@
 /*
- * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
- *           (C) 1999 Antti Koivisto (koivisto@kde.org)
- *           (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2013 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
- * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2011-2013 Google Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 namespace WebCore {
 
 class Event;
+class EventTarget;
 class Node;
 
 namespace EventDispatcher {
 
-bool dispatchEvent(Node&, Event&);
+void dispatchEvent(Node&, Event&);
+void dispatchEvent(const Vector<EventTarget*>&, Event&);
+
 void dispatchScopedEvent(Node&, Event&);
 
 }
index 02e8635..b53eba9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2013 Google Inc. All rights reserved.
- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -35,13 +35,15 @@ namespace WebCore {
 
 class WindowEventContext final : public EventContext {
 public:
-    WindowEventContext(Node&, DOMWindow&, EventTarget*);
+    WindowEventContext(Node&, DOMWindow&, EventTarget&);
+private:
     void handleLocalEvents(Event&) const final;
 };
 
-WindowEventContext::WindowEventContext(Node& node, DOMWindow& currentTarget, EventTarget* target)
-    : EventContext(&node, &currentTarget, target)
-{ }
+inline WindowEventContext::WindowEventContext(Node& node, DOMWindow& currentTarget, EventTarget& target)
+    : EventContext(&node, &currentTarget, &target)
+{
+}
 
 void WindowEventContext::handleLocalEvents(Event& event) const
 {
@@ -58,7 +60,7 @@ static inline bool shouldEventCrossShadowBoundary(Event& event, ShadowRoot& shad
     // Video-only full screen is a mode where we use the shadow DOM as an implementation
     // detail that should not be detectable by the web content.
     if (targetNode) {
-        if (Element* element = targetNode->document().webkitCurrentFullScreenElement()) {
+        if (auto* element = targetNode->document().webkitCurrentFullScreenElement()) {
             // FIXME: We assume that if the full screen element is a media element that it's
             // the video-only full screen. Both here and elsewhere. But that is probably wrong.
             if (element->isMediaElement() && shadowRoot.host() == element)
@@ -84,15 +86,10 @@ public:
     void moveToNewTreeScope(TreeScope* previousTreeScope, TreeScope& newTreeScope);
 
 private:
-
     Node* nodeInLowestCommonAncestor();
     void collectTreeScopes();
 
-#if ASSERT_DISABLED
-    void checkConsistency(Node&) { }
-#else
     void checkConsistency(Node& currentTarget);
-#endif
 
     Node& m_relatedNode;
     Node* m_retargetedRelatedNode;
@@ -103,24 +100,41 @@ private:
 
 EventPath::EventPath(Node& originalTarget, Event& event)
 {
-    bool isMouseOrFocusEvent = event.isMouseEvent() || event.isFocusEvent();
+    buildPath(originalTarget, event);
+
+    if (auto* relatedTarget = event.relatedTarget())
+        setRelatedTarget(originalTarget, *relatedTarget);
+
 #if ENABLE(TOUCH_EVENTS)
-    bool isTouchEvent = event.isTouchEvent();
+    if (is<TouchEvent>(event))
+        retargetTouchLists(downcast<TouchEvent>(event));
 #endif
+}
+
+void EventPath::buildPath(Node& originalTarget, Event& event)
+{
+    using MakeEventContext = std::unique_ptr<EventContext> (*)(Node&, EventTarget*, EventTarget*);
+    MakeEventContext makeEventContext = [] (Node& node, EventTarget* currentTarget, EventTarget* target) {
+        return std::make_unique<EventContext>(&node, currentTarget, target);
+    };
+    if (is<MouseEvent>(event) || event.isFocusEvent()) {
+        makeEventContext = [] (Node& node, EventTarget* currentTarget, EventTarget* target) -> std::unique_ptr<EventContext> {
+            return std::make_unique<MouseOrFocusEventContext>(node, currentTarget, target);
+        };
+    }
+#if ENABLE(TOUCH_EVENTS)
+    if (is<TouchEvent>(event)) {
+        makeEventContext = [] (Node& node, EventTarget* currentTarget, EventTarget* target) -> std::unique_ptr<EventContext> {
+            return std::make_unique<TouchEventContext>(node, currentTarget, target);
+        };
+    }
+#endif
+
     Node* node = nodeOrHostIfPseudoElement(&originalTarget);
     Node* target = node ? eventTargetRespectingTargetRules(*node) : nullptr;
     while (node) {
         while (node) {
-            EventTarget* currentTarget = eventTargetRespectingTargetRules(*node);
-
-            if (isMouseOrFocusEvent)
-                m_path.append(std::make_unique<MouseOrFocusEventContext>(node, currentTarget, target));
-#if ENABLE(TOUCH_EVENTS)
-            else if (isTouchEvent)
-                m_path.append(std::make_unique<TouchEventContext>(node, currentTarget, target));
-#endif
-            else
-                m_path.append(std::make_unique<EventContext>(node, currentTarget, target));
+            m_path.append(makeEventContext(*node, eventTargetRespectingTargetRules(*node), target));
 
             if (is<ShadowRoot>(*node))
                 break;
@@ -130,8 +144,10 @@ EventPath::EventPath(Node& originalTarget, Event& event)
                 // https://dom.spec.whatwg.org/#interface-document
                 if (is<Document>(*node) && event.type() != eventNames().loadEvent) {
                     ASSERT(target);
-                    if (auto* window = downcast<Document>(*node).domWindow())
-                        m_path.append(std::make_unique<WindowEventContext>(*node, *window, target));
+                    if (target) {
+                        if (auto* window = downcast<Document>(*node).domWindow())
+                            m_path.append(std::make_unique<WindowEventContext>(*node, *window, *target));
+                    }
                 }
                 return;
             }
@@ -153,7 +169,6 @@ EventPath::EventPath(Node& originalTarget, Event& event)
         node = shadowRoot.host();
         if (exitingShadowTreeOfTarget)
             target = eventTargetRespectingTargetRules(*node);
-
     }
 }
 
@@ -198,7 +213,8 @@ void EventPath::setRelatedTarget(Node& origin, EventTarget& relatedTarget)
 }
 
 #if ENABLE(TOUCH_EVENTS)
-void EventPath::retargetTouch(TouchEventContext::TouchListType touchListType, const Touch& touch)
+
+void EventPath::retargetTouch(TouchEventContext::TouchListType type, const Touch& touch)
 {
     EventTarget* eventTarget = touch.target();
     if (!eventTarget)
@@ -218,42 +234,28 @@ void EventPath::retargetTouch(TouchEventContext::TouchListType touchListType, co
 
         if (is<TouchEventContext>(*context)) {
             Node* currentRelatedNode = retargeter.currentNode(currentTarget);
-            downcast<TouchEventContext>(*context).touchList(touchListType)->append(touch.cloneWithNewTarget(currentRelatedNode));
+            downcast<TouchEventContext>(*context).touchList(type).append(touch.cloneWithNewTarget(currentRelatedNode));
         }
 
         previousTreeScope = &currentTreeScope;
     }
 }
 
-void EventPath::retargetTouchLists(const TouchEvent& touchEvent)
+void EventPath::retargetTouchList(TouchEventContext::TouchListType type, const TouchList* list)
 {
-    if (touchEvent.touches()) {
-        for (size_t i = 0; i < touchEvent.touches()->length(); ++i)
-            retargetTouch(TouchEventContext::Touches, *touchEvent.touches()->item(i));
-    }
-
-    if (touchEvent.targetTouches()) {
-        for (size_t i = 0; i < touchEvent.targetTouches()->length(); ++i)
-            retargetTouch(TouchEventContext::TargetTouches, *touchEvent.targetTouches()->item(i));
-    }
-
-    if (touchEvent.changedTouches()) {
-        for (size_t i = 0; i < touchEvent.changedTouches()->length(); ++i)
-            retargetTouch(TouchEventContext::ChangedTouches, *touchEvent.changedTouches()->item(i));
-    }
+    for (unsigned i = 0, length = list ? list->length() : 0; i < length; ++i)
+        retargetTouch(type, *list->item(i));
 }
-#endif
 
-bool EventPath::hasEventListeners(const AtomicString& eventType) const
+void EventPath::retargetTouchLists(const TouchEvent& event)
 {
-    for (auto& context : m_path) {
-        if (context->node()->hasEventListeners(eventType))
-            return true;
-    }
-
-    return false;
+    retargetTouchList(TouchEventContext::Touches, event.touches());
+    retargetTouchList(TouchEventContext::TargetTouches, event.targetTouches());
+    retargetTouchList(TouchEventContext::ChangedTouches, event.changedTouches());
 }
 
+#endif
+
 // https://dom.spec.whatwg.org/#dom-event-composedpath
 Vector<EventTarget*> EventPath::computePathUnclosedToTarget(const EventTarget& target) const
 {
@@ -276,6 +278,15 @@ Vector<EventTarget*> EventPath::computePathUnclosedToTarget(const EventTarget& t
     return path;
 }
 
+EventPath::EventPath(const Vector<EventTarget*>& targets)
+{
+    for (auto* target : targets) {
+        ASSERT(target);
+        ASSERT(!target->toNode());
+        m_path.append(std::make_unique<EventContext>(nullptr, target, *targets.begin()));
+    }
+}
+
 static Node* moveOutOfAllShadowRoots(Node& startingNode)
 {
     Node* node = &startingNode;
@@ -393,7 +404,14 @@ void RelatedNodeRetargeter::collectTreeScopes()
     ASSERT_WITH_SECURITY_IMPLICATION(!m_ancestorTreeScopes.isEmpty());
 }
 
-#if !ASSERT_DISABLED
+#if ASSERT_DISABLED
+
+inline void RelatedNodeRetargeter::checkConsistency(Node&)
+{
+}
+
+#else
+
 void RelatedNodeRetargeter::checkConsistency(Node& currentTarget)
 {
     if (!m_retargetedRelatedNode)
@@ -401,6 +419,7 @@ void RelatedNodeRetargeter::checkConsistency(Node& currentTarget)
     ASSERT(!currentTarget.isClosedShadowHidden(*m_retargetedRelatedNode));
     ASSERT(m_retargetedRelatedNode == &currentTarget.treeScope().retargetToScope(m_relatedNode));
 }
+
 #endif
 
 }
index a58af5a..5ccba99 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2013 Google Inc. All rights reserved.
- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -32,43 +32,42 @@ namespace WebCore {
 class EventPath {
 public:
     EventPath(Node& origin, Event&);
+    explicit EventPath(const Vector<EventTarget*>&);
 
     bool isEmpty() const { return m_path.isEmpty(); }
     size_t size() const { return m_path.size(); }
     const EventContext& contextAt(size_t i) const { return *m_path[i]; }
     EventContext& contextAt(size_t i) { return *m_path[i]; }
 
-#if ENABLE(TOUCH_EVENTS)
-    void retargetTouchLists(const TouchEvent&);
-#endif
-    void setRelatedTarget(Node& origin, EventTarget&);
-
-    bool hasEventListeners(const AtomicString& eventType) const;
-
-    EventContext* lastContextIfExists() { return m_path.isEmpty() ? nullptr : m_path.last().get(); }
-
     Vector<EventTarget*> computePathUnclosedToTarget(const EventTarget&) const;
 
-    static Node* eventTargetRespectingTargetRules(Node& referenceNode)
-    {
-        if (is<PseudoElement>(referenceNode))
-            return downcast<PseudoElement>(referenceNode).hostElement();
-
-        // Events sent to elements inside an SVG use element's shadow tree go to the use element.
-        if (is<SVGElement>(referenceNode)) {
-            if (auto* useElement = downcast<SVGElement>(referenceNode).correspondingUseElement())
-                return useElement;
-        }
-
-        return &referenceNode;
-    }
+    static Node* eventTargetRespectingTargetRules(Node&);
 
 private:
+    void buildPath(Node& origin, Event&);
+    void setRelatedTarget(Node& origin, EventTarget&);
+
 #if ENABLE(TOUCH_EVENTS)
     void retargetTouch(TouchEventContext::TouchListType, const Touch&);
+    void retargetTouchList(TouchEventContext::TouchListType, const TouchList*);
+    void retargetTouchLists(const TouchEvent&);
 #endif
 
     Vector<std::unique_ptr<EventContext>, 32> m_path;
 };
 
+inline Node* EventPath::eventTargetRespectingTargetRules(Node& referenceNode)
+{
+    if (is<PseudoElement>(referenceNode))
+        return downcast<PseudoElement>(referenceNode).hostElement();
+
+    // Events sent to elements inside an SVG use element's shadow tree go to the use element.
+    if (is<SVGElement>(referenceNode)) {
+        if (auto* useElement = downcast<SVGElement>(referenceNode).correspondingUseElement())
+            return useElement;
+    }
+
+    return &referenceNode;
+}
+
 } // namespace WebCore
index a749e3e..7e14f3a 100644 (file)
@@ -181,10 +181,11 @@ ExceptionOr<bool> EventTarget::dispatchEventForBindings(Event& event)
     if (!scriptExecutionContext())
         return false;
 
-    return dispatchEvent(event);
+    dispatchEvent(event);
+    return event.legacyReturnValue();
 }
 
-bool EventTarget::dispatchEvent(Event& event)
+void EventTarget::dispatchEvent(Event& event)
 {
     ASSERT(event.isInitialized());
     ASSERT(!event.isBeingDispatched());
@@ -192,10 +193,8 @@ bool EventTarget::dispatchEvent(Event& event)
     event.setTarget(this);
     event.setCurrentTarget(this);
     event.setEventPhase(Event::AT_TARGET);
-    bool defaultPrevented = fireEventListeners(event);
-    event.resetPropagationFlags();
-    event.setEventPhase(Event::NONE);
-    return defaultPrevented;
+    fireEventListeners(event);
+    event.resetAfterDispatch();
 }
 
 void EventTarget::uncaughtExceptionInEventHandler()
@@ -223,25 +222,25 @@ static const AtomicString& legacyType(const Event& event)
     return nullAtom();
 }
 
-bool EventTarget::fireEventListeners(Event& event)
+void EventTarget::fireEventListeners(Event& event)
 {
     ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::isEventAllowedInMainThread());
     ASSERT(event.isInitialized());
 
     auto* data = eventTargetData();
     if (!data)
-        return true;
+        return;
 
     SetForScope<bool> firingEventListenersScope(data->isFiringEventListeners, true);
 
     if (auto* listenersVector = data->eventListenerMap.find(event.type())) {
         fireEventListeners(event, *listenersVector);
-        return !event.defaultPrevented();
+        return;
     }
 
     // Only fall back to legacy types for trusted events.
     if (!event.isTrusted())
-        return !event.defaultPrevented();
+        return;
 
     const AtomicString& legacyTypeName = legacyType(event);
     if (!legacyTypeName.isNull()) {
@@ -252,7 +251,6 @@ bool EventTarget::fireEventListeners(Event& event)
             event.setType(typeName);
         }
     }
-    return !event.defaultPrevented();
 }
 
 // Intentionally creates a copy of the listeners vector to avoid event listeners added after this point from being run.
index 5949441..ec5b06d 100644 (file)
@@ -77,7 +77,7 @@ public:
             : capture(capture)
         { }
 
-        bool capture;
+        bool capture { false };
     };
 
     struct AddEventListenerOptions : ListenerOptions {
@@ -88,7 +88,7 @@ public:
         { }
 
         std::optional<bool> passive;
-        bool once;
+        bool once { false };
     };
 
     using AddEventListenerOptionsOrBoolean = Variant<AddEventListenerOptions, bool>;
@@ -101,7 +101,7 @@ public:
     virtual bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&);
 
     virtual void removeAllEventListeners();
-    virtual bool dispatchEvent(Event&);
+    virtual void dispatchEvent(Event&);
     virtual void uncaughtExceptionInEventHandler();
 
     // Used for legacy "onevent" attributes.
@@ -114,7 +114,7 @@ public:
     bool hasActiveEventListeners(const AtomicString& eventType) const;
     const EventListenerVector& eventListeners(const AtomicString& eventType);
 
-    bool fireEventListeners(Event&);
+    void fireEventListeners(Event&);
     bool isFiringEventListeners() const;
 
     void visitJSEventListeners(JSC::SlotVisitor&);
index a7e9253..fde9f2e 100644 (file)
@@ -25,7 +25,6 @@
 
 #include "Document.h"
 #include "Editor.h"
-#include "EventDispatcher.h"
 #include "EventHandler.h"
 #include "EventNames.h"
 #include "Frame.h"
index c7c2bdc..2748079 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  *
@@ -2312,13 +2312,9 @@ void Node::dispatchScopedEvent(Event& event)
     EventDispatcher::dispatchScopedEvent(*this, event);
 }
 
-bool Node::dispatchEvent(Event& event)
+void Node::dispatchEvent(Event& event)
 {
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
-    if (is<TouchEvent>(event))
-        return dispatchTouchEvent(downcast<TouchEvent>(event));
-#endif
-    return EventDispatcher::dispatchEvent(*this, event);
+    EventDispatcher::dispatchEvent(*this, event);
 }
 
 void Node::dispatchSubtreeModifiedEvent()
@@ -2337,31 +2333,26 @@ void Node::dispatchSubtreeModifiedEvent()
     dispatchScopedEvent(MutationEvent::create(subtreeModifiedEventName, true));
 }
 
-bool Node::dispatchDOMActivateEvent(int detail, Event& underlyingEvent)
+void Node::dispatchDOMActivateEvent(Event& underlyingClickEvent)
 {
     ASSERT_WITH_SECURITY_IMPLICATION(NoEventDispatchAssertion::InMainThread::isEventAllowed());
-    Ref<UIEvent> event = UIEvent::create(eventNames().DOMActivateEvent, true, true, document().defaultView(), detail);
-    event->setUnderlyingEvent(&underlyingEvent);
+    int detail = is<UIEvent>(underlyingClickEvent) ? downcast<UIEvent>(underlyingClickEvent).detail() : 0;
+    auto event = UIEvent::create(eventNames().DOMActivateEvent, true, true, document().defaultView(), detail);
+    event->setUnderlyingEvent(&underlyingClickEvent);
     dispatchScopedEvent(event);
-    return event->defaultHandled();
+    if (event->defaultHandled())
+        underlyingClickEvent.setDefaultHandled();
 }
 
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
-bool Node::dispatchTouchEvent(TouchEvent& event)
-{
-    return EventDispatcher::dispatchEvent(*this, event);
-}
-#endif
-
 bool Node::dispatchBeforeLoadEvent(const String& sourceURL)
 {
     if (!document().hasListenerType(Document::BEFORELOAD_LISTENER))
         return true;
 
     Ref<Node> protectedThis(*this);
-    Ref<BeforeLoadEvent> beforeLoadEvent = BeforeLoadEvent::create(sourceURL);
-    dispatchEvent(beforeLoadEvent);
-    return !beforeLoadEvent->defaultPrevented();
+    auto event = BeforeLoadEvent::create(sourceURL);
+    dispatchEvent(event);
+    return !event->defaultPrevented();
 }
 
 void Node::dispatchInputEvent()
@@ -2380,9 +2371,7 @@ void Node::defaultEventHandler(Event& event)
                 frame->eventHandler().defaultKeyboardEventHandler(downcast<KeyboardEvent>(event));
         }
     } else if (eventType == eventNames().clickEvent) {
-        int detail = is<UIEvent>(event) ? downcast<UIEvent>(event).detail() : 0;
-        if (dispatchDOMActivateEvent(detail, event))
-            event.setDefaultHandled();
+        dispatchDOMActivateEvent(event);
 #if ENABLE(CONTEXT_MENUS)
     } else if (eventType == eventNames().contextmenuEvent) {
         if (Frame* frame = document().frame())
index dcf443a..a106948 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  *
  * This library is free software; you can redistribute it and/or
@@ -495,22 +495,19 @@ public:
     bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) override;
 
     using EventTarget::dispatchEvent;
-    bool dispatchEvent(Event&) override;
+    void dispatchEvent(Event&) override;
 
     void dispatchScopedEvent(Event&);
 
     virtual void handleLocalEvents(Event&);
 
     void dispatchSubtreeModifiedEvent();
-    bool dispatchDOMActivateEvent(int detail, Event& underlyingEvent);
+    void dispatchDOMActivateEvent(Event& underlyingClickEvent);
 
 #if ENABLE(TOUCH_EVENTS)
     virtual bool allowsDoubleTapGesture() const { return true; }
 #endif
 
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
-    bool dispatchTouchEvent(TouchEvent&);
-#endif
     bool dispatchBeforeLoadEvent(const String& sourceURL);
 
     void dispatchInputEvent();
index 7c02527..65a37eb 100644 (file)
@@ -169,9 +169,9 @@ void RejectedPromiseTracker::reportUnhandledRejections(Vector<UnhandledPromise>&
 
         auto event = PromiseRejectionEvent::create(state, eventNames().unhandledrejectionEvent, initializer);
         auto target = m_context.errorEventTarget();
-        bool needsDefaultAction = target->dispatchEvent(event);
+        target->dispatchEvent(event);
 
-        if (needsDefaultAction)
+        if (!event->defaultPrevented())
             m_context.reportUnhandledPromiseRejection(state, promise, unhandledPromise.callStack());
 
         if (!promise.isHandled(vm))
index f4b32f3..e8d5e5e 100644 (file)
@@ -32,8 +32,6 @@
 #include "ScopedEventQueue.h"
 
 #include "Event.h"
-#include "EventDispatcher.h"
-#include "EventTarget.h"
 #include "Node.h"
 #include <wtf/NeverDestroyed.h>
 
@@ -47,6 +45,8 @@ ScopedEventQueue& ScopedEventQueue::singleton()
 
 void ScopedEventQueue::enqueueEvent(Ref<Event>&& event)
 {
+    ASSERT(event->target());
+    ASSERT(event->target()->toNode());
     if (m_scopingLevel)
         m_queuedEvents.append(WTFMove(event));
     else
@@ -55,9 +55,7 @@ void ScopedEventQueue::enqueueEvent(Ref<Event>&& event)
 
 void ScopedEventQueue::dispatchEvent(Event& event) const
 {
-    ASSERT(event.target());
-    ASSERT(event.target()->toNode());
-    EventDispatcher::dispatchEvent(*event.target()->toNode(), event);
+    event.target()->toNode()->dispatchEvent(event);
 }
 
 void ScopedEventQueue::dispatchAllEvents()
index f63363a..ec6d947 100644 (file)
@@ -29,7 +29,6 @@
 #include "DOMRect.h"
 #include "DataTransfer.h"
 #include "Element.h"
-#include "EventDispatcher.h"
 #include "EventNames.h"
 #include "MouseEvent.h"
 #include <wtf/CurrentTime.h>
@@ -81,8 +80,7 @@ private:
 
 static void simulateMouseEvent(const AtomicString& eventType, Element& element, Event* underlyingEvent, SimulatedClickSource source)
 {
-    auto event = SimulatedMouseEvent::create(eventType, element.document().defaultView(), underlyingEvent, element, source);
-    EventDispatcher::dispatchEvent(element, event);
+    element.dispatchEvent(SimulatedMouseEvent::create(eventType, element.document().defaultView(), underlyingEvent, element, source));
 }
 
 void simulateClick(Element& element, Event* underlyingEvent, SimulatedClickMouseEventOptions mouseEventOptions, SimulatedClickVisualOptions visualOptions, SimulatedClickSource creationOptions)
index 2644dbd..3a60853 100644 (file)
@@ -116,7 +116,9 @@ static bool dispatchBeforeInputEvent(Element& element, const AtomicString& input
     if (!element.document().settings().inputEventsEnabled())
         return true;
 
-    return element.dispatchEvent(InputEvent::create(eventNames().beforeinputEvent, inputType, true, cancelable, element.document().defaultView(), data, WTFMove(dataTransfer), targetRanges, 0));
+    auto event = InputEvent::create(eventNames().beforeinputEvent, inputType, true, cancelable, element.document().defaultView(), data, WTFMove(dataTransfer), targetRanges, 0);
+    element.dispatchEvent(event);
+    return !event->defaultPrevented();
 }
 
 static void dispatchInputEvent(Element& element, const AtomicString& inputType, const String& data = { }, RefPtr<DataTransfer>&& dataTransfer = nullptr, const Vector<RefPtr<StaticRange>>& targetRanges = { })
index 570bb21..b2073ac 100644 (file)
@@ -1940,8 +1940,12 @@ void FrameSelection::selectAll()
     if (!root)
         return;
 
-    if (selectStartTarget && !selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true)))
-        return;
+    if (selectStartTarget) {
+        auto event = Event::create(eventNames().selectstartEvent, true, true);
+        selectStartTarget->dispatchEvent(event);
+        if (event->defaultPrevented())
+            return;
+    }
 
     VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(root.get()));
 
@@ -2390,7 +2394,9 @@ bool FrameSelection::dispatchSelectStart()
     if (!selectStartTarget)
         return true;
 
-    return selectStartTarget->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
+    auto event = Event::create(eventNames().selectstartEvent, true, true);
+    selectStartTarget->dispatchEvent(event);
+    return !event->defaultPrevented();
 }
 
 void FrameSelection::setShouldShowBlockCursor(bool shouldShowBlockCursor)
index b8b7e08..62c4f7a 100644 (file)
@@ -76,15 +76,15 @@ void CheckboxInputType::willDispatchClick(InputElementClickState& state)
     element().setChecked(!state.checked, DispatchChangeEvent);
 }
 
-void CheckboxInputType::didDispatchClick(Event* event, const InputElementClickState& state)
+void CheckboxInputType::didDispatchClick(Event& event, const InputElementClickState& state)
 {
-    if (event->defaultPrevented() || event->defaultHandled()) {
+    if (event.defaultPrevented() || event.defaultHandled()) {
         element().setIndeterminate(state.indeterminate);
         element().setChecked(state.checked);
     }
 
     // The work we did in willDispatchClick was default handling.
-    event->setDefaultHandled();
+    event.setDefaultHandled();
 }
 
 bool CheckboxInputType::isCheckbox() const
index 155dae4..69a9070 100644 (file)
@@ -39,15 +39,15 @@ public:
     explicit CheckboxInputType(HTMLInputElement& element) : BaseCheckableInputType(element) { }
 
 private:
-    const AtomicString& formControlType() const override;
-    bool valueMissing(const String&) const override;
-    String valueMissingText() const override;
-    void handleKeyupEvent(KeyboardEvent&) override;
-    void willDispatchClick(InputElementClickState&) override;
-    void didDispatchClick(Event*, const InputElementClickState&) override;
-    bool isCheckbox() const override;
-    bool matchesIndeterminatePseudoClass() const override;
-    bool shouldAppearIndeterminate() const override;
+    const AtomicString& formControlType() const final;
+    bool valueMissing(const String&) const final;
+    String valueMissingText() const final;
+    void handleKeyupEvent(KeyboardEvent&) final;
+    void willDispatchClick(InputElementClickState&) final;
+    void didDispatchClick(Event&, const InputElementClickState&) final;
+    bool isCheckbox() const final;
+    bool matchesIndeterminatePseudoClass() const final;
+    bool shouldAppearIndeterminate() const final;
 };
 
 } // namespace WebCore
index f5aa2eb..85899c3 100644 (file)
@@ -482,8 +482,9 @@ bool HTMLFormControlElement::checkValidity(Vector<RefPtr<HTMLFormControlElement>
     // An event handler can deref this object.
     Ref<HTMLFormControlElement> protectedThis(*this);
     Ref<Document> originalDocument(document());
-    bool needsDefaultAction = dispatchEvent(Event::create(eventNames().invalidEvent, false, true));
-    if (needsDefaultAction && unhandledInvalidControls && isConnected() && originalDocument.ptr() == &document())
+    auto event = Event::create(eventNames().invalidEvent, false, true);
+    dispatchEvent(event);
+    if (!event->defaultPrevented() && unhandledInvalidControls && isConnected() && originalDocument.ptr() == &document())
         unhandledInvalidControls->append(this);
     return false;
 }
index 09003d5..498979c 100644 (file)
@@ -150,12 +150,12 @@ void HTMLFormElement::handleLocalEvents(Event& event)
 
 unsigned HTMLFormElement::length() const
 {
-    unsigned len = 0;
+    unsigned length = 0;
     for (auto& associatedElement : m_associatedElements) {
         if (associatedElement->isEnumeratable())
-            ++len;
+            ++length;
     }
-    return len;
+    return length;
 }
 
 HTMLElement* HTMLFormElement::item(unsigned index)
@@ -285,10 +285,13 @@ void HTMLFormElement::prepareForSubmission(Event& event)
     auto formState = FormState::create(*this, textFieldValues(), document(), NotSubmittedByJavaScript);
     targetFrame->loader().client().dispatchWillSendSubmitEvent(WTFMove(formState));
 
-    Ref<HTMLFormElement> protectedThis(*this);
+    auto protectedThis = makeRef(*this);
+
+    auto submitEvent = Event::create(eventNames().submitEvent, true, true);
+    dispatchEvent(submitEvent);
 
-    // Event handling can result in m_shouldSubmit becoming true, regardless of dispatchEvent() return value.
-    if (dispatchEvent(Event::create(eventNames().submitEvent, true, true)))
+    // Event handling could have resulted in m_shouldSubmit becoming true as a side effect, too.
+    if (!submitEvent->defaultPrevented())
         m_shouldSubmit = true;
 
     m_isSubmittingOrPreparingForSubmission = false;
@@ -299,12 +302,12 @@ void HTMLFormElement::prepareForSubmission(Event& event)
 
 void HTMLFormElement::submit()
 {
-    submit(0, false, true, NotSubmittedByJavaScript);
+    submit(nullptr, false, true, NotSubmittedByJavaScript);
 }
 
 void HTMLFormElement::submitFromJavaScript()
 {
-    submit(0, false, ScriptController::processingUserGesture(), SubmittedByJavaScript);
+    submit(nullptr, false, ScriptController::processingUserGesture(), SubmittedByJavaScript);
 }
 
 StringPairVector HTMLFormElement::textFieldValues() const
@@ -370,18 +373,21 @@ void HTMLFormElement::submit(Event* event, bool activateSubmitButton, bool proce
 
 void HTMLFormElement::reset()
 {
-    RefPtr<Frame> frame = document().frame();
-    if (m_isInResetFunction || !frame)
+    if (m_isInResetFunction)
+        return;
+
+    RefPtr<Frame> protectedFrame = document().frame();
+    if (!protectedFrame)
         return;
 
     Ref<HTMLFormElement> protectedThis(*this);
 
     SetForScope<bool> isInResetFunctionRestorer(m_isInResetFunction, true);
 
-    if (!dispatchEvent(Event::create(eventNames().resetEvent, true, true)))
-        return;
-
-    resetAssociatedFormControlElements();
+    auto event = Event::create(eventNames().resetEvent, true, true);
+    dispatchEvent(event);
+    if (!event->defaultPrevented())
+        resetAssociatedFormControlElements();
 }
 
 void HTMLFormElement::resetAssociatedFormControlElements()
index eb74f02..7c833c9 100644 (file)
@@ -1118,7 +1118,7 @@ void HTMLInputElement::willDispatchEvent(Event& event, InputElementClickState& s
 
 void HTMLInputElement::didDispatchClickEvent(Event& event, const InputElementClickState& state)
 {
-    m_inputType->didDispatchClick(&event, state);
+    m_inputType->didDispatchClick(event, state);
 }
 
 void HTMLInputElement::didBlur()
index 08dd013..41d283a 100644 (file)
@@ -5627,7 +5627,7 @@ void HTMLMediaElement::mediaPlayerCurrentPlaybackTargetIsWirelessChanged(MediaPl
     updateSleepDisabling();
 }
 
-bool HTMLMediaElement::dispatchEvent(Event& event)
+void HTMLMediaElement::dispatchEvent(Event& event)
 {
     if (event.type() == eventNames().webkitcurrentplaybacktargetiswirelesschangedEvent) {
         m_failedToPlayToWirelessTarget = false;
@@ -5636,7 +5636,7 @@ bool HTMLMediaElement::dispatchEvent(Event& event)
 
     DEBUG_LOG(LOGIDENTIFIER, "dispatching '", event.type(), "'");
 
-    return HTMLElement::dispatchEvent(event);
+    HTMLElement::dispatchEvent(event);
 }
 
 bool HTMLMediaElement::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
index 9149550..86cfdfa 100644 (file)
@@ -663,7 +663,7 @@ private:
     void enqueuePlaybackTargetAvailabilityChangedEvent();
 
     using EventTarget::dispatchEvent;
-    bool dispatchEvent(Event&) override;
+    void dispatchEvent(Event&) override;
 #endif
 
 #if ENABLE(MEDIA_SESSION)
index 11fe602..578e134 100644 (file)
@@ -109,7 +109,7 @@ private:
     void swapRendererTimerFired();
     bool shouldOverridePlugin(const String& url, const String& mimeType);
 
-    bool dispatchBeforeLoadEvent(const String& sourceURL); // Not implemented, generates a compile error if subclasses call this by mistake.
+    bool dispatchBeforeLoadEvent(const String& sourceURL) = delete; // Generate a compile error if someone calls this by mistake.
 
     // This will load the plugin if necessary.
     virtual RenderWidget* renderWidgetLoadingPlugin() const = 0;
index 99df629..cf590c5 100644 (file)
@@ -697,7 +697,7 @@ void InputType::willDispatchClick(InputElementClickState&)
 {
 }
 
-void InputType::didDispatchClick(Event*, const InputElementClickState&)
+void InputType::didDispatchClick(Event&, const InputElementClickState&)
 {
 }
 
index 0722bb5..c2d857f 100644 (file)
@@ -177,7 +177,7 @@ public:
     virtual void handleClickEvent(MouseEvent&);
     virtual void handleMouseDownEvent(MouseEvent&);
     virtual void willDispatchClick(InputElementClickState&);
-    virtual void didDispatchClick(Event*, const InputElementClickState&);
+    virtual void didDispatchClick(Event&, const InputElementClickState&);
     virtual void handleDOMActivateEvent(Event&);
     virtual void handleKeydownEvent(KeyboardEvent&);
     virtual void handleKeypressEvent(KeyboardEvent&);
index 861b425..9e2663f 100644 (file)
@@ -153,22 +153,18 @@ void RadioInputType::willDispatchClick(InputElementClickState& state)
     element().setChecked(true, DispatchChangeEvent);
 }
 
-void RadioInputType::didDispatchClick(Event* event, const InputElementClickState& state)
+void RadioInputType::didDispatchClick(Event& event, const InputElementClickState& state)
 {
-    if (event->defaultPrevented() || event->defaultHandled()) {
+    if (event.defaultPrevented() || event.defaultHandled()) {
         // Restore the original selected radio button if possible.
         // Make sure it is still a radio button and only do the restoration if it still belongs to our group.
-        RefPtr<HTMLInputElement> checkedRadioButton = state.checkedRadioButton.get();
-        if (checkedRadioButton
-                && checkedRadioButton->isRadioButton()
-                && checkedRadioButton->form() == element().form()
-                && checkedRadioButton->name() == element().name()) {
-            checkedRadioButton->setChecked(true);
-        }
+        auto& button = state.checkedRadioButton;
+        if (button && button->isRadioButton() && button->form() == element().form() && button->name() == element().name())
+            button->setChecked(true);
     }
 
     // The work we did in willDispatchClick was default handling.
-    event->setDefaultHandled();
+    event.setDefaultHandled();
 }
 
 bool RadioInputType::isRadioButton() const
index 2af2afa..6a257a2 100644 (file)
@@ -40,18 +40,18 @@ public:
     explicit RadioInputType(HTMLInputElement& element) : BaseCheckableInputType(element) { }
 
 private:
-    const AtomicString& formControlType() const override;
-    bool valueMissing(const String&) const override;
-    String valueMissingText() const override;
-    void handleClickEvent(MouseEvent&) override;
-    void handleKeydownEvent(KeyboardEvent&) override;
-    void handleKeyupEvent(KeyboardEvent&) override;
-    bool isKeyboardFocusable(KeyboardEvent&) const override;
-    bool shouldSendChangeEventAfterCheckedChanged() override;
-    void willDispatchClick(InputElementClickState&) override;
-    void didDispatchClick(Event*, const InputElementClickState&) override;
-    bool isRadioButton() const override;
-    bool matchesIndeterminatePseudoClass() const override;
+    const AtomicString& formControlType() const final;
+    bool valueMissing(const String&) const final;
+    String valueMissingText() const final;
+    void handleClickEvent(MouseEvent&) final;
+    void handleKeydownEvent(KeyboardEvent&) final;
+    void handleKeyupEvent(KeyboardEvent&) final;
+    bool isKeyboardFocusable(KeyboardEvent&) const final;
+    bool shouldSendChangeEventAfterCheckedChanged() final;
+    void willDispatchClick(InputElementClickState&) final;
+    void didDispatchClick(Event&, const InputElementClickState&) final;
+    bool isRadioButton() const final;
+    bool matchesIndeterminatePseudoClass() const final;
 };
 
 } // namespace WebCore
index 5e96806..2522650 100644 (file)
@@ -144,13 +144,13 @@ void TextTrackCue::setPauseOnExit(bool value)
     m_pauseOnExit = value;
 }
 
-bool TextTrackCue::dispatchEvent(Event& event)
+void TextTrackCue::dispatchEvent(Event& event)
 {
     // When a TextTrack's mode is disabled: no cues are active, no events fired.
     if (!track() || track()->mode() == TextTrack::Mode::Disabled)
-        return false;
+        return;
 
-    return EventTarget::dispatchEvent(event);
+    EventTarget::dispatchEvent(event);
 }
 
 bool TextTrackCue::isActive()
index d902130..1da56c7 100644 (file)
@@ -99,7 +99,7 @@ private:
     void derefEventTarget() final { deref(); }
 
     using EventTarget::dispatchEvent;
-    bool dispatchEvent(Event&) final;
+    void dispatchEvent(Event&) final;
 
     EventTargetInterface eventTargetInterface() const final { return TextTrackCueEventTargetInterfaceType; }
     ScriptExecutionContext* scriptExecutionContext() const final { return &m_scriptExecutionContext; }
index 6974220..a04e3be 100644 (file)
@@ -38,7 +38,6 @@
 #include "Database.h"
 #include "DocumentLoader.h"
 #include "Event.h"
-#include "EventDispatcher.h"
 #include "InspectorApplicationCacheAgent.h"
 #include "InspectorCSSAgent.h"
 #include "InspectorCanvasAgent.h"
index 77d5800..9e1e670 100644 (file)
@@ -1960,63 +1960,66 @@ void DOMWindow::languagesChanged()
 
 void DOMWindow::dispatchLoadEvent()
 {
-    Ref<Event> loadEvent = Event::create(eventNames().loadEvent, false, false);
-    if (m_frame && m_frame->loader().documentLoader() && !m_frame->loader().documentLoader()->timing().loadEventStart()) {
-        // The DocumentLoader (and thus its LoadTiming) might get destroyed while dispatching
-        // the event, so protect it to prevent writing the end time into freed memory.
-        RefPtr<DocumentLoader> documentLoader = m_frame->loader().documentLoader();
-        LoadTiming& timing = documentLoader->timing();
-        timing.markLoadEventStart();
-        dispatchEvent(loadEvent, document());
-        timing.markLoadEventEnd();
-    } else
-        dispatchEvent(loadEvent, document());
-
-    // For load events, send a separate load event to the enclosing frame only.
-    // This is a DOM extension and is independent of bubbling/capturing rules of
-    // the DOM.
-    Element* ownerElement = m_frame ? m_frame->ownerElement() : nullptr;
-    if (ownerElement)
-        ownerElement->dispatchEvent(Event::create(eventNames().loadEvent, false, false));
+    // If we did not protect it, the document loader and its timing subobject might get destroyed
+    // as a side effect of what event handling code does.
+    auto protectedThis = makeRef(*this);
+    auto protectedLoader = makeRefPtr(frame() ? frame()->loader().documentLoader() : nullptr);
+    bool shouldMarkLoadEventTimes = protectedLoader && !protectedLoader->timing().loadEventStart();
+
+    if (shouldMarkLoadEventTimes)
+        protectedLoader->timing().markLoadEventStart();
+
+    dispatchEvent(Event::create(eventNames().loadEvent, false, false), document());
+
+    if (shouldMarkLoadEventTimes)
+        protectedLoader->timing().markLoadEventEnd();
+
+    // Send a separate load event to the element that owns this frame.
+    if (frame()) {
+        if (auto* owner = frame()->ownerElement())
+            owner->dispatchEvent(Event::create(eventNames().loadEvent, false, false));
+    }
 
     InspectorInstrumentation::loadEventFired(frame());
 }
 
-bool DOMWindow::dispatchEvent(Event& event, EventTarget* target)
+void DOMWindow::dispatchEvent(Event& event, EventTarget* target)
 {
-    Ref<EventTarget> protectedThis(*this);
+    // FIXME: It's confusing to have both the inherited EventTarget::dispatchEvent function
+    // and this function, which does something nearly identical but subtly different if
+    // called with a target of null. Most callers pass the document as the target, though.
+    // Fixing this could allow us to remove the special case in DocumentEventQueue::dispatchEvent.
+
+    auto protectedThis = makeRef(*this);
 
     // Pausing a page may trigger pagehide and pageshow events. WebCore also implicitly fires these
     // events when closing a WebView. Here we keep track of the state of the page to prevent duplicate,
     // unbalanced events per the definition of the pageshow event:
     // <http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#event-pageshow>.
+    // FIXME: This code should go at call sites where pageshowEvent and pagehideEvents are
+    // generated, not here inside the event dispatching process.
     if (event.eventInterface() == PageTransitionEventInterfaceType) {
         if (event.type() == eventNames().pageshowEvent) {
             if (m_lastPageStatus == PageStatus::Shown)
-                return true; // Event was previously dispatched; do not fire a duplicate event.
+                return; // Event was previously dispatched; do not fire a duplicate event.
             m_lastPageStatus = PageStatus::Shown;
         } else if (event.type() == eventNames().pagehideEvent) {
             if (m_lastPageStatus == PageStatus::Hidden)
-                return true; // Event was previously dispatched; do not fire a duplicate event.
+                return; // Event was previously dispatched; do not fire a duplicate event.
             m_lastPageStatus = PageStatus::Hidden;
         }
     }
 
+    // FIXME: It doesn't seem right to have the inspector instrumentation here since not all
+    // events dispatched to the window object are guaranteed to flow through this function.
+    // But the instrumentation prevents us from calling EventDispatcher::dispatchEvent here.
     event.setTarget(target ? target : this);
     event.setCurrentTarget(this);
     event.setEventPhase(Event::AT_TARGET);
-
-    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), event, *this);
-
-    bool result = fireEventListeners(event);
-
+    auto cookie = InspectorInstrumentation::willDispatchEventOnWindow(frame(), event, *this);
+    fireEventListeners(event);
     InspectorInstrumentation::didDispatchEventOnWindow(cookie);
-
-    event.setCurrentTarget(nullptr);
-    event.setEventPhase(Event::NONE);
-    event.resetPropagationFlags();
-
-    return result;
+    event.resetAfterDispatch();
 }
 
 void DOMWindow::removeAllEventListeners()
index 1d7b46b..e04acf3 100644 (file)
@@ -266,7 +266,7 @@ public:
     void removeAllEventListeners() final;
 
     using EventTarget::dispatchEvent;
-    bool dispatchEvent(Event&, EventTarget*);
+    void dispatchEvent(Event&, EventTarget*);
 
     void dispatchLoadEvent();
 
index c7995a9..41b0e19 100644 (file)
@@ -507,7 +507,9 @@ bool DragController::dispatchTextInputEventFor(Frame* innerFrame, const DragData
     String text = m_page.dragCaretController().isContentRichlyEditable() ? emptyString() : dragData.asPlainText();
     Element* target = innerFrame->editor().findEventTargetFrom(m_page.dragCaretController().caretPosition());
     // FIXME: What guarantees target is not null?
-    return target->dispatchEvent(TextEvent::createForDrop(innerFrame->document()->domWindow(), text));
+    auto event = TextEvent::createForDrop(innerFrame->document()->domWindow(), text);
+    target->dispatchEvent(event);
+    return !event->defaultPrevented();
 }
 
 bool DragController::concludeEditDrag(const DragData& dragData)
index 64f63ff..989ecbd 100644 (file)
@@ -473,7 +473,9 @@ static inline bool dispatchSelectStart(Node* node)
     if (!node || !node->renderer())
         return true;
 
-    return node->dispatchEvent(Event::create(eventNames().selectstartEvent, true, true));
+    auto event = Event::create(eventNames().selectstartEvent, true, true);
+    node->dispatchEvent(event);
+    return !event->defaultPrevented();
 }
 
 static Node* nodeToSelectOnMouseDownForNode(Node& targetNode)
@@ -2320,10 +2322,8 @@ EventHandler::DragTargetResponse EventHandler::updateDragAndDrop(const PlatformM
                 response = targetFrame->eventHandler().updateDragAndDrop(event, makePasteboard, sourceOperation, draggingFiles);
         } else if (newTarget) {
             // As per section 7.9.4 of the HTML 5 spec., we must always fire a drag event before firing a dragenter, dragleave, or dragover event.
-            if (dragState().source && dragState().shouldDispatchEvents) {
-                // for now we don't care if event handler cancels default behavior, since there is none
+            if (dragState().source && dragState().shouldDispatchEvents)
                 dispatchDragSrcEvent(eventNames().dragEvent, event);
-            }
             response = dispatchDragEnterOrDragOverEvent(eventNames().dragenterEvent, *newTarget, event, makePasteboard(), sourceOperation, draggingFiles);
         }
 
@@ -2349,10 +2349,8 @@ EventHandler::DragTargetResponse EventHandler::updateDragAndDrop(const PlatformM
                 response = targetFrame->eventHandler().updateDragAndDrop(event, makePasteboard, sourceOperation, draggingFiles);
         } else if (newTarget) {
             // Note, when dealing with sub-frames, we may need to fire only a dragover event as a drag event may have been fired earlier.
-            if (!m_shouldOnlyFireDragOverEvent && dragState().source && dragState().shouldDispatchEvents) {
-                // for now we don't care if event handler cancels default behavior, since there is none
+            if (!m_shouldOnlyFireDragOverEvent && dragState().source && dragState().shouldDispatchEvents)
                 dispatchDragSrcEvent(eventNames().dragEvent, event);
-            }
             response = dispatchDragEnterOrDragOverEvent(eventNames().dragoverEvent, *newTarget, event, makePasteboard(), sourceOperation, draggingFiles);
             m_shouldOnlyFireDragOverEvent = false;
         }
@@ -3259,7 +3257,7 @@ bool EventHandler::internalKeyEvent(const PlatformKeyboardEvent& initialKeyEvent
         keydown->setDefaultHandled();
     }
     
-    if (accessibilityPreventsEventPropogation(keydown))
+    if (accessibilityPreventsEventPropagation(keydown))
         keydown->stopPropagation();
 
     element->dispatchEvent(keydown);
@@ -3402,7 +3400,7 @@ void EventHandler::handleKeyboardSelectionMovementForAccessibility(KeyboardEvent
     }
 }
 
-bool EventHandler::accessibilityPreventsEventPropogation(KeyboardEvent& event)
+bool EventHandler::accessibilityPreventsEventPropagation(KeyboardEvent& event)
 {
 #if PLATFORM(COCOA)
     if (!AXObjectCache::accessibilityEnhancedUserInterfaceEnabled())
@@ -3548,7 +3546,6 @@ void EventHandler::dragSourceEndedAt(const PlatformMouseEvent& event, DragOperat
 
     if (dragState().source && dragState().shouldDispatchEvents) {
         dragState().dataTransfer->setDestinationOperation(operation);
-        // For now we don't care if event handler cancels default behavior, since there is no default behavior.
         dispatchDragSrcEvent(eventNames().dragendEvent, event);
     }
     invalidateDataTransfer();
@@ -3571,11 +3568,10 @@ void EventHandler::updateDragStateAfterEditDragIfNeeded(Element& rootEditableEle
         dragState().source = &rootEditableElement;
 }
 
-// Return value indicates if we should continue "default processing", i.e., whether event handler canceled.
-bool EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event)
+void EventHandler::dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent& event)
 {
     ASSERT(dragState().dataTransfer);
-    return !dispatchDragEvent(eventType, *dragState().source, event, *dragState().dataTransfer);
+    dispatchDragEvent(eventType, *dragState().source, event, *dragState().dataTransfer);
 }
 
 bool EventHandler::dispatchDragStartEventOnSourceElement(DataTransfer& dataTransfer)
@@ -4194,7 +4190,7 @@ bool EventHandler::handleTouchEvent(const PlatformTouchEvent& event)
                 TouchEvent::create(effectiveTouches.get(), targetTouches.get(), changedTouches[state].m_touches.get(),
                     stateName, touchEventTarget->toNode()->document().defaultView(),
                     0, 0, 0, 0, event.ctrlKey(), event.altKey(), event.shiftKey(), event.metaKey());
-            touchEventTarget->toNode()->dispatchTouchEvent(touchEvent);
+            touchEventTarget->dispatchEvent(touchEvent);
             swallowedEvent = swallowedEvent || touchEvent->defaultPrevented() || touchEvent->defaultHandled();
         }
     }
index 5c04728..109de3b 100644 (file)
@@ -258,7 +258,7 @@ public:
     WEBCORE_EXPORT bool keyEvent(const PlatformKeyboardEvent&);
     void defaultKeyboardEventHandler(KeyboardEvent&);
 
-    bool accessibilityPreventsEventPropogation(KeyboardEvent&);
+    bool accessibilityPreventsEventPropagation(KeyboardEvent&);
     WEBCORE_EXPORT void handleKeyboardSelectionMovementForAccessibility(KeyboardEvent&);
 
     bool handleTextInputEvent(const String& text, Event* underlyingEvent = nullptr, TextEventInputType = TextEventInputKeyboard);
@@ -417,7 +417,7 @@ private:
 #if ENABLE(DRAG_SUPPORT)
     void clearDragState();
 
-    bool dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent&);
+    void dispatchDragSrcEvent(const AtomicString& eventType, const PlatformMouseEvent&);
     bool dispatchDragStartEventOnSourceElement(DataTransfer&);
 
     bool dragHysteresisExceeded(const FloatPoint&) const;
index d9eb530..3a06104 100644 (file)
@@ -166,11 +166,10 @@ public:
     }
     virtual ~ReferenceFilterOperation();
 
-    Ref<FilterOperation> clone() const override
+    Ref<FilterOperation> clone() const final
     {
         // Reference filters cannot be cloned.
         RELEASE_ASSERT_NOT_REACHED();
-        return *static_cast<FilterOperation*>(nullptr);
     }
 
     bool affectsOpacity() const override { return true; }
index 7e719ea..a5ab1b0 100644 (file)
@@ -162,8 +162,9 @@ void WorkerMessagingProxy::postExceptionToWorkerObject(const String& errorMessag
         // We don't bother checking the askedToTerminate() flag here, because exceptions should *always* be reported even if the thread is terminated.
         // This is intentionally different than the behavior in MessageWorkerTask, because terminated workers no longer deliver messages (section 4.6 of the WebWorker spec), but they do report exceptions.
 
-        bool errorHandled = !workerObject->dispatchEvent(ErrorEvent::create(errorMessage, sourceURL, lineNumber, columnNumber, { }));
-        if (!errorHandled)
+        auto event = ErrorEvent::create(errorMessage, sourceURL, lineNumber, columnNumber, { });
+        workerObject->dispatchEvent(event);
+        if (!event->defaultPrevented())
             context.reportException(errorMessage, lineNumber, columnNumber, sourceURL, nullptr, nullptr);
     });
 }
index 24d3dfa..10b42c6 100644 (file)
@@ -1,3 +1,13 @@
+2017-11-01  Darin Adler  <darin@apple.com>
+
+        Simplify event dispatch code and make it a bit more consistent
+        https://bugs.webkit.org/show_bug.cgi?id=178991
+
+        Reviewed by Chris Dumez.
+
+        * WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMEvent.cpp:
+        (webkit_dom_event_get_src_element): Call target instead of srcElement.
+
 2017-11-04  Aishwarya Nirmal  <anirmal@apple.com>
 
         [Touch Bar Web API] Add support for menuitem tag
index e7ed7d8..ceb01a3 100644 (file)
@@ -370,7 +370,7 @@ WebKitDOMEventTarget* webkit_dom_event_get_src_element(WebKitDOMEvent* self)
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_EVENT(self), 0);
     WebCore::Event* item = WebKit::core(self);
-    RefPtr<WebCore::EventTarget> gobjectResult = WTF::getPtr(item->srcElement());
+    RefPtr<WebCore::EventTarget> gobjectResult = WTF::getPtr(item->target());
     return WebKit::kit(gobjectResult.get());
 }
 
index ad3eb68..cfd52af 100644 (file)
@@ -1,3 +1,13 @@
+2017-11-01  Darin Adler  <darin@apple.com>
+
+        Simplify event dispatch code and make it a bit more consistent
+        https://bugs.webkit.org/show_bug.cgi?id=178991
+
+        Reviewed by Chris Dumez.
+
+        * DOM/DOMEvent.mm:
+        (-[DOMEvent srcElement]): Call target instead of srcElement.
+
 2017-11-04  Aishwarya Nirmal  <anirmal@apple.com>
 
         [Touch Bar Web API] Add support for menuitem tag
index 321a7f0..9aca41b 100644 (file)
 - (id <DOMEventTarget>)srcElement
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->srcElement()));
+    return kit(WTF::getPtr(IMPL->target()));
 }
 
 - (BOOL)returnValue