Skip to content
  • ggaren@apple.com's avatar
    JavaScriptCore: Added the ability to swap vectors with inline capacities, so you can · 521f64b8
    ggaren@apple.com authored
    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
    521f64b8