JavaScriptCore: Added the ability to swap vectors with inline capacities, so you can
store a vector with inline capacity in a hash table.
Patch by Geoffrey Garen <ggaren@apple.com> on 2009-09-23
Reviewed by Sam Weinig.
* wtf/Vector.h:
(WTF::swap):
(WTF::VectorBuffer::swap):
WebCore: Bring a little sanity to this crazy EventTarget world of ours
https://bugs.webkit.org/show_bug.cgi?id=29701
Patch by Geoffrey Garen <ggaren@apple.com> on 2009-09-23
Reviewed by Sam Weinig.
Lots of EventTarget refactoring to achieve a single shared implementation
that fixes some of the performance and correctness bugs of the many individual
implementations, and makes reasoning about EventTargets and EventListeners
much easier.
The basic design is this:
- EventTarget manages a set of EventListeners.
- onXXX EventListener attributes forward to standard EventTarget APIs.
- Since the onXXX code is repetitive, it is usually done with macros
of the form DEFINE_ATTRIBUTE_EVENT_LISTENER(attributeName).
- EventTarget provides a shared implementation of dispatchEvent,
which subclasses with special event dispatch rules, like Node, override.
- To support Node, which lazily instantiates its EventTarget data,
EventTarget has no data members, and instead makes a virtual call
to get its data from wherever its subclass chose to store it.
Code that used to call dispatchEvent, passing an ExceptionCode paratmeter,
even though no exception could be thrown, has been changed not to do so,
to improve clarity and performance.
Code that used to call a special dispatchXXXEvent function, which just
turned around and called dispatchEvent, has been changed to call
dispatchEvent, to improve clarity and performance.
* WebCore.base.exp:
* WebCore.xcodeproj/project.pbxproj: Another day in the life of a WebKit
engineer.
* bindings/js/JSDOMBinding.cpp:
(WebCore::isObservableThroughDOM): Updated for Node API change. Added
"is not in the document but is firing event listeners" as a condition
that makes a Node observable in the DOM, so that event listeners firing
on removed nodes are not destroyed midstream. (This was a long-standing
bug that was somewhat hidden by the old implementation's habit of
copying the RegisteredEventListener vector before firing events, which
would keep almost all the relevant objects from being destroyed.)
* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::handleEvent): Removed the isWindowEvent flag
because it was one of the most elaborately planned no-ops in the history
of software crime, and one of the reasons clients thought they needed more
than one dispatchEvent function even though they didn't.
* bindings/js/JSEventListener.h:
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::markChildren):
(WebCore::JSMessagePort::markChildren):
* bindings/js/JSNodeCustom.cpp:
(WebCore::JSNode::markChildren):
* bindings/js/JSAbstractWorkerCustom.cpp:
* bindings/js/JSDOMApplicationCacheCustom.cpp:
* bindings/js/JSDedicatedWorkerContextCustom.cpp:
* bindings/js/JSEventSourceCustom.cpp:
* bindings/js/JSMessagePortCustom.cpp:
* bindings/js/JSSharedWorkerContextCustom.cpp: Removed.
* bindings/js/JSWebSocketCustom.cpp:
* bindings/js/JSWorkerContextCustom.cpp:
(WebCore::JSWorkerContext::markChildren):
* bindings/js/JSWorkerCustom.cpp:
* bindings/js/JSXMLHttpRequestCustom.cpp:
(WebCore::JSXMLHttpRequest::markChildren):
* bindings/js/JSXMLHttpRequestUploadCustom.cpp:
(WebCore::JSXMLHttpRequestUpload::markChildren): EventListener marking is
now autogenerated. Classes that still have custom mark functions for other
reasons now call a shared EventTarget API to mark their EventListeners.
* bindings/objc/ObjCEventListener.h:
* bindings/objc/ObjCEventListener.mm:
(WebCore::ObjCEventListener::handleEvent): Bye bye isWindowEvent.
* bindings/scripts/CodeGeneratorJS.pm: Autogeneration support for
marking and invalidating event listeners.
* dom/CharacterData.cpp:
(WebCore::CharacterData::dispatchModifiedEvent):
* dom/ContainerNode.cpp:
(WebCore::ContainerNode::insertBefore):
(WebCore::ContainerNode::replaceChild):
(WebCore::willRemoveChild):
(WebCore::ContainerNode::appendChild):
(WebCore::dispatchChildInsertionEvents):
(WebCore::dispatchChildRemovalEvents):
* dom/Document.cpp:
(WebCore::Document::removeAllEventListeners):
(WebCore::Document::implicitClose):
(WebCore::Document::setFocusedNode):
(WebCore::Document::dispatchWindowEvent):
(WebCore::Document::dispatchWindowLoadEvent):
(WebCore::Document::finishedParsing):
* dom/Document.h: Use dispatchEvent directly.
* dom/Element.h: Moved a few event listener attributes down from Node,
since they don't apply to all Nodes, only Elements.
* dom/EventListener.h: Removed isWindowEvent parameter.
* dom/EventNames.h: Added the "display" event name, so it works correctly
with attribute macros, and for performance.
* dom/EventTarget.cpp:
(WebCore::forbidEventDispatch):
(WebCore::allowEventDispatch):
(WebCore::eventDispatchForbidden): Made this code (embarrasingly) thread
safe, since it's now called on multiple threads. (Currently, we only forbid
event dispatch on the main thread. If we ever want to forbid event dispatch
on secondary threads, we can improve it then.)
(WebCore::EventTarget::addEventListener):
(WebCore::EventTarget::removeEventListener):
(WebCore::EventTarget::setAttributeEventListener):
(WebCore::EventTarget::getAttributeEventListener):
(WebCore::EventTarget::clearAttributeEventListener):
(WebCore::EventTarget::dispatchEvent):
(WebCore::EventTarget::fireEventListeners):
(WebCore::EventTarget::getEventListeners):
(WebCore::EventTarget::removeAllEventListeners):
* dom/EventTarget.h:
(WebCore::FiringEventEndIterator::FiringEventEndIterator):
(WebCore::EventTarget::ref):
(WebCore::EventTarget::deref):
(WebCore::EventTarget::markEventListeners):
(WebCore::EventTarget::invalidateEventListeners):
(WebCore::EventTarget::isFiringEventListeners):
(WebCore::EventTarget::hasEventListeners): The ONE TRUE IMPLEMENTATION of
EventTarget APIs, crafted from an amalgam of all the different versions
we used to have. The most significant change here is that we no longer
make a copy of an EventListener vector before firing the events in the
vector -- instead, we use a reference to the original vector, along with
a notification mechanism for the unlikely case when an EventListener is
removed from the vector. This substantially reduces malloc, copying, and
refcount overhead, and complexity.
* dom/InputElement.cpp:
(WebCore::InputElement::setValueFromRenderer):
* dom/MessageEvent.h:
(WebCore::MessageEvent::create): Use dispatchEvent directly.
* dom/MessagePort.cpp:
(WebCore::MessagePort::dispatchMessages):
(WebCore::MessagePort::eventTargetData):
(WebCore::MessagePort::ensureEventTargetData):
* dom/MessagePort.h:
(WebCore::MessagePort::setOnmessage):
(WebCore::MessagePort::onmessage):
* dom/MessagePort.idl: Removed custom EventTarget implementation.
* dom/MutationEvent.h:
(WebCore::MutationEvent::create): Added some default values so callers
can construct MutationEvents more easily, without calling a custom dispatch
function.
* dom/Node.cpp:
(WebCore::Node::addEventListener):
(WebCore::Node::removeEventListener):
(WebCore::Node::eventTargetData):
(WebCore::Node::ensureEventTargetData):
(WebCore::Node::handleLocalEvents):
(WebCore::Node::dispatchEvent):
(WebCore::Node::dispatchGenericEvent):
(WebCore::Node::dispatchSubtreeModifiedEvent):
(WebCore::Node::dispatchUIEvent):
(WebCore::Node::dispatchKeyEvent):
(WebCore::Node::dispatchMouseEvent):
(WebCore::Node::dispatchWheelEvent):
(WebCore::Node::dispatchFocusEvent):
(WebCore::Node::dispatchBlurEvent):
* dom/Node.h:
(WebCore::Node::preDispatchEventHandler):
(WebCore::Node::postDispatchEventHandler):
* dom/Node.idl:
* dom/NodeRareData.h:
(WebCore::NodeRareData::eventTargetData):
(WebCore::NodeRareData::ensureEventTargetData): Use the shared EventTarget
interface, and call dispatchEvent directly instead of custom dispatchXXXEvent
functions that just forwarded to dispatchEvent.
* dom/RegisteredEventListener.cpp:
* dom/RegisteredEventListener.h:
(WebCore::RegisteredEventListener::RegisteredEventListener):
(WebCore::operator==): This is just a simple struct now, since we no longer
do a complicated copy / refCount / isRemoved dance just to honor the rule
that an EventListener can be removed during event dispatch.
* history/CachedFrame.cpp:
(WebCore::CachedFrameBase::restore): Removed another custom dispatchEvent.
* html/HTMLBodyElement.cpp:
* html/HTMLBodyElement.h: Use the shared EventTarget API.
* html/HTMLFormControlElement.cpp:
(WebCore::HTMLFormControlElement::dispatchFormControlChangeEvent):
(WebCore::HTMLFormControlElement::checkValidity):
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::handleLocalEvents):
(WebCore::HTMLFormElement::prepareSubmit):
(WebCore::HTMLFormElement::reset):
* html/HTMLFormElement.h: Use the standard dispatchEvent API.
* html/HTMLFrameSetElement.cpp:
* html/HTMLFrameSetElement.h: Use the shared EventTarget API.
* html/HTMLImageLoader.cpp:
(WebCore::HTMLImageLoader::dispatchLoadEvent):
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::onSearch):
* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::loadInternal):
* html/HTMLScriptElement.cpp:
(WebCore::HTMLScriptElement::dispatchLoadEvent):
(WebCore::HTMLScriptElement::dispatchErrorEvent):
* html/HTMLSourceElement.cpp:
(WebCore::HTMLSourceElement::errorEventTimerFired):
* html/HTMLTokenizer.cpp:
(WebCore::HTMLTokenizer::notifyFinished): Use the standard dispatchEvent API.
* inspector/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::handleEvent):
* inspector/InspectorDOMAgent.h:
* inspector/InspectorDOMStorageResource.cpp:
(WebCore::InspectorDOMStorageResource::handleEvent):
* inspector/InspectorDOMStorageResource.h:
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::stopLoading):
(WebCore::FrameLoader::canCachePageContainingThisFrame):
(WebCore::FrameLoader::logCanCacheFrameDecision):
(WebCore::HashChangeEventTask::performTask):
(WebCore::FrameLoader::pageHidden): No more isWindowEvent.
* loader/ImageDocument.cpp:
(WebCore::ImageEventListener::handleEvent):
* loader/appcache/ApplicationCacheGroup.cpp:
(WebCore::CallCacheListenerTask::performTask):
* loader/appcache/ApplicationCacheHost.cpp:
(WebCore::ApplicationCacheHost::notifyDOMApplicationCache):
* loader/appcache/ApplicationCacheHost.h:
* loader/appcache/DOMApplicationCache.cpp:
(WebCore::DOMApplicationCache::eventTargetData):
(WebCore::DOMApplicationCache::ensureEventTargetData):
* loader/appcache/DOMApplicationCache.h:
* loader/appcache/DOMApplicationCache.idl: Switched to the standard
EventTarget API. As a part of this, I switched this class from using a
custom internal event name enumeration to using the standard EventNames.
* notifications/Notification.cpp:
(WebCore::Notification::eventTargetData):
(WebCore::Notification::ensureEventTargetData):
* notifications/Notification.h:
(WebCore::Notification::scriptExecutionContext):
* notifications/Notification.idl: Switched to the standard EventTarget API.
* page/DOMWindow.cpp:
(WebCore::PostMessageTimer::event):
(WebCore::windowsWithUnloadEventListeners):
(WebCore::windowsWithBeforeUnloadEventListeners):
(WebCore::allowsBeforeUnloadListeners):
(WebCore::DOMWindow::dispatchAllPendingBeforeUnloadEvents):
(WebCore::DOMWindow::pendingUnloadEventListeners):
(WebCore::DOMWindow::dispatchAllPendingUnloadEvents): Changed the "pending"
unload / beforeunload listener tracker just to track which windows had
such listeners, instead of actually keeping a copy of the listeners. Now,
this code can use the standard EventTarget API.
(WebCore::DOMWindow::~DOMWindow):
(WebCore::DOMWindow::postMessageTimerFired):
(WebCore::DOMWindow::addEventListener):
(WebCore::DOMWindow::removeEventListener):
(WebCore::DOMWindow::dispatchLoadEvent):
(WebCore::DOMWindow::dispatchEvent):
(WebCore::DOMWindow::removeAllEventListeners):
(WebCore::DOMWindow::captureEvents):
(WebCore::DOMWindow::releaseEvents):
(WebCore::DOMWindow::eventTargetData):
(WebCore::DOMWindow::ensureEventTargetData):
* page/DOMWindow.h:
* page/DOMWindow.idl: Use the standard EventTarget APIs.
* page/EventHandler.cpp:
(WebCore::EventHandler::canMouseDownStartSelect):
(WebCore::EventHandler::canMouseDragExtendSelect):
(WebCore::EventHandler::sendResizeEvent):
(WebCore::EventHandler::sendScrollEvent): Use dispatchEvent directly.
* page/EventSource.cpp:
(WebCore::EventSource::endRequest):
(WebCore::EventSource::didReceiveResponse):
(WebCore::EventSource::parseEventStreamLine):
(WebCore::EventSource::stop):
(WebCore::EventSource::createMessageEvent):
(WebCore::EventSource::eventTargetData):
(WebCore::EventSource::ensureEventTargetData):
* page/EventSource.h:
* page/EventSource.idl: Use the standard EventTarget APIs.
* page/FocusController.cpp:
(WebCore::dispatchEventsOnWindowAndFocusedNode):
(WebCore::FocusController::setFocusedFrame):
* page/Frame.cpp:
(WebCore::Frame::shouldClose):
* page/Frame.h:
* page/Page.cpp:
(WebCore::networkStateChanged):
* page/animation/AnimationController.cpp:
(WebCore::AnimationControllerPrivate::updateStyleIfNeededDispatcherFired):
* rendering/RenderListBox.cpp:
(WebCore::RenderListBox::valueChanged):
* rendering/RenderTextControl.cpp:
(WebCore::RenderTextControl::selectionChanged):
* rendering/RenderTextControlMultiLine.cpp:
(WebCore::RenderTextControlMultiLine::subtreeHasChanged): Use dispatchEvent.
* svg/SVGElement.cpp:
(WebCore::hasLoadListener): Rewritten for new EventTarget API.
* svg/SVGElementInstance.cpp:
(WebCore::dummyEventTargetData):
(WebCore::SVGElementInstance::addEventListener):
(WebCore::SVGElementInstance::removeEventListener):
(WebCore::SVGElementInstance::removeAllEventListeners):
(WebCore::SVGElementInstance::dispatchEvent):
(WebCore::SVGElementInstance::eventTargetData):
(WebCore::SVGElementInstance::ensureEventTargetData): Use the EventTarget API.
* svg/SVGElementInstance.h:
* svg/SVGImageLoader.cpp:
(WebCore::SVGImageLoader::dispatchLoadEvent):
* svg/SVGScriptElement.cpp:
(WebCore::SVGScriptElement::dispatchErrorEvent): Use dispatchEvent directly.
* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::transferEventListenersToShadowTree): Updated for
new EventTarget API.
* svg/animation/SVGSMILElement.cpp:
(WebCore::ConditionEventListener::handleEvent): No more isWindowEvent.
* websockets/WebSocket.cpp:
(WebCore::ProcessWebSocketEventTask::create):
(WebCore::ProcessWebSocketEventTask::performTask):
(WebCore::ProcessWebSocketEventTask::ProcessWebSocketEventTask):
(WebCore::WebSocket::didConnect):
(WebCore::WebSocket::didReceiveMessage):
(WebCore::WebSocket::didClose):
(WebCore::WebSocket::eventTargetData):
(WebCore::WebSocket::ensureEventTargetData):
* websockets/WebSocket.h:
* websockets/WebSocket.idl:
* workers/AbstractWorker.cpp:
(WebCore::AbstractWorker::eventTargetData):
(WebCore::AbstractWorker::ensureEventTargetData):
* workers/AbstractWorker.h:
* workers/AbstractWorker.idl:
* workers/DedicatedWorkerContext.cpp:
* workers/DedicatedWorkerContext.h:
* workers/DedicatedWorkerContext.idl:
* workers/DefaultSharedWorkerRepository.cpp:
(WebCore::SharedWorkerConnectTask::performTask):
(WebCore::SharedWorkerScriptLoader::load):
(WebCore::SharedWorkerScriptLoader::notifyFinished):
* workers/SharedWorker.idl:
* workers/SharedWorkerContext.cpp:
(WebCore::createConnectEvent):
* workers/SharedWorkerContext.h:
* workers/SharedWorkerContext.idl:
* workers/Worker.cpp:
(WebCore::Worker::notifyFinished):
* workers/Worker.h:
* workers/Worker.idl:
* workers/WorkerContext.cpp:
(WebCore::WorkerContext::eventTargetData):
(WebCore::WorkerContext::ensureEventTargetData):
* workers/WorkerContext.h:
* workers/WorkerContext.idl:
* workers/WorkerMessagingProxy.cpp:
(WebCore::MessageWorkerContextTask::performTask):
(WebCore::MessageWorkerTask::performTask):
(WebCore::WorkerExceptionTask::performTask):
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::callReadyStateChangeListener):
(WebCore::XMLHttpRequest::createRequest):
(WebCore::XMLHttpRequest::abort):
(WebCore::XMLHttpRequest::networkError):
(WebCore::XMLHttpRequest::abortError):
(WebCore::XMLHttpRequest::didSendData):
(WebCore::XMLHttpRequest::didReceiveData):
(WebCore::XMLHttpRequest::eventTargetData):
(WebCore::XMLHttpRequest::ensureEventTargetData):
* xml/XMLHttpRequest.h:
* xml/XMLHttpRequest.idl:
* xml/XMLHttpRequestProgressEvent.h:
(WebCore::XMLHttpRequestProgressEvent::create):
* xml/XMLHttpRequestUpload.cpp:
(WebCore::XMLHttpRequestUpload::eventTargetData):
(WebCore::XMLHttpRequestUpload::ensureEventTargetData):
* xml/XMLHttpRequestUpload.h:
* xml/XMLHttpRequestUpload.idl: Use new EventTarget API.
WebKit/mac: Updated for a WebCore rename.
Patch by Geoffrey Garen <ggaren@apple.com> on 2009-09-23
Reviewed by Sam Weinig.
* WebView/WebFrame.mm:
(-[WebFrame _cacheabilityDictionary]):
LayoutTests: Layout tests for event target sanitization.
Patch by Geoffrey Garen <ggaren@apple.com> on 2009-09-23
Reviewed by Sam Weinig.
New tests for event dispatch:
* fast/events/event-attributes-after-exception-expected.txt: Added.
* fast/events/event-attributes-after-exception.html: Added.
* fast/events/event-fire-order-expected.txt: Added.
* fast/events/event-fire-order.html: Added.
* fast/events/event-fired-after-removal-expected.txt: Added.
* fast/events/event-fired-after-removal.html: Added.
Fixed these tests:
* fast/xmlhttprequest/xmlhttprequest-get-expected.txt: eventPhase should
be AT_TARGET (2) when firing an event on an XHR, not INVALID (0).
* http/tests/xmlhttprequest/infoOnProgressEvent-expected.txt: ditto
* http/tests/xmlhttprequest/event-target-expected.txt:
* http/tests/xmlhttprequest/event-target.html: Removing an event listener
during event dispatch should prevent it from firing. (This test was backwards.)
* svg/custom/loadevents-capturing.svg: Enhanced this test to tell you
why it fails when it fails. Changed it to register runTest() (now named
reportResults()) using addEventListener() instead of the 'onload' attribute.
The test relies on reportResults() running after handler(), so it needs
to register reportResults() after handler().
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@48701 268f45cc-cd09-0410-ab3c-d52691b4dbfc
138 files changed