diff options
Diffstat (limited to 'Source/WebCore/dom/EventTarget.h')
-rw-r--r-- | Source/WebCore/dom/EventTarget.h | 329 |
1 files changed, 133 insertions, 196 deletions
diff --git a/Source/WebCore/dom/EventTarget.h b/Source/WebCore/dom/EventTarget.h index e6d6b29cc..892d4b812 100644 --- a/Source/WebCore/dom/EventTarget.h +++ b/Source/WebCore/dom/EventTarget.h @@ -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 Apple Inc. All rights reserved. + * Copyright (C) 2004-2017 Apple Inc. All rights reserved. * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) * (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> * @@ -15,227 +15,164 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 COMPUTER, INC. OR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * 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. - * + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef EventTarget_h -#define EventTarget_h +#pragma once #include "EventListenerMap.h" -#include "EventNames.h" #include "EventTargetInterfaces.h" +#include "ExceptionOr.h" +#include "ScriptWrappable.h" +#include <memory> #include <wtf/Forward.h> -#include <wtf/HashMap.h> -#include <wtf/text/AtomicStringHash.h> +#include <wtf/Variant.h> namespace WebCore { - class AudioNode; - class AudioContext; - class AudioTrackList; - class DedicatedWorkerGlobalScope; - class DOMApplicationCache; - class DOMWindow; - class Event; - class EventListener; - class EventSource; - class FileReader; - class FileWriter; - class IDBDatabase; - class IDBRequest; - class IDBTransaction; - class ScriptProcessorNode; - class MediaController; - class MediaStream; - class MessagePort; - class Node; - class Notification; - class SVGElementInstance; - class ScriptExecutionContext; - class SharedWorker; - class SharedWorkerGlobalScope; - class TextTrack; - class TextTrackCue; - class VideoTrackList; - class WebSocket; - class WebKitNamedFlow; - class Worker; - class XMLHttpRequest; - class XMLHttpRequestUpload; - - typedef int ExceptionCode; - - struct FiringEventIterator { - FiringEventIterator(const AtomicString& eventType, size_t& iterator, size_t& size) - : eventType(eventType) - , iterator(iterator) - , size(size) - { - } - - const AtomicString& eventType; - size_t& iterator; - size_t& size; - }; - typedef Vector<FiringEventIterator, 1> FiringEventIteratorVector; +class DOMWindow; +class DOMWrapperWorld; +class Node; - struct EventTargetData { - WTF_MAKE_NONCOPYABLE(EventTargetData); WTF_MAKE_FAST_ALLOCATED; - public: - EventTargetData(); - ~EventTargetData(); +struct EventTargetData { + WTF_MAKE_NONCOPYABLE(EventTargetData); WTF_MAKE_FAST_ALLOCATED; +public: + EventTargetData() = default; + EventListenerMap eventListenerMap; + bool isFiringEventListeners { false }; +}; - EventListenerMap eventListenerMap; - OwnPtr<FiringEventIteratorVector> firingEventIterators; - }; +enum EventTargetInterface { - enum EventTargetInterface { +#define DOM_EVENT_INTERFACE_DECLARE(name) name##EventTargetInterfaceType, +DOM_EVENT_TARGET_INTERFACES_FOR_EACH(DOM_EVENT_INTERFACE_DECLARE) +#undef DOM_EVENT_INTERFACE_DECLARE - #define DOM_EVENT_INTERFACE_DECLARE(name) name##EventTargetInterfaceType, - DOM_EVENT_TARGET_INTERFACES_FOR_EACH(DOM_EVENT_INTERFACE_DECLARE) - #undef DOM_EVENT_INTERFACE_DECLARE +}; - }; +class EventTarget : public ScriptWrappable { +public: + void ref() { refEventTarget(); } + void deref() { derefEventTarget(); } + + virtual EventTargetInterface eventTargetInterface() const = 0; + virtual ScriptExecutionContext* scriptExecutionContext() const = 0; - class EventTarget { - public: - void ref() { refEventTarget(); } - void deref() { derefEventTarget(); } - - virtual EventTargetInterface eventTargetInterface() const = 0; - virtual ScriptExecutionContext* scriptExecutionContext() const = 0; - - virtual Node* toNode(); - virtual DOMWindow* toDOMWindow(); - virtual bool isMessagePort() const; - - virtual bool addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture); - virtual bool removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture); - virtual void removeAllEventListeners(); - virtual bool dispatchEvent(PassRefPtr<Event>); - bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&); // DOM API - virtual void uncaughtExceptionInEventHandler(); - - // Used for legacy "onEvent" attribute APIs. - bool setAttributeEventListener(const AtomicString& eventType, PassRefPtr<EventListener>); - bool clearAttributeEventListener(const AtomicString& eventType); - EventListener* getAttributeEventListener(const AtomicString& eventType); - - bool hasEventListeners() const; - bool hasEventListeners(const AtomicString& eventType); - bool hasCapturingEventListeners(const AtomicString& eventType); - const EventListenerVector& getEventListeners(const AtomicString& eventType); - - bool fireEventListeners(Event*); - bool isFiringEventListeners(); - - void visitJSEventListeners(JSC::SlotVisitor&); - void invalidateJSEventListeners(JSC::JSObject*); - - protected: - virtual ~EventTarget(); - - virtual EventTargetData* eventTargetData() = 0; - virtual EventTargetData& ensureEventTargetData() = 0; - - private: - virtual void refEventTarget() = 0; - virtual void derefEventTarget() = 0; - - void fireEventListeners(Event*, EventTargetData*, EventListenerVector&); - void setupLegacyTypeObserverIfNeeded(const AtomicString& legacyTypeName, bool hasLegacyTypeListeners, bool hasNewTypeListeners); - - friend class EventListenerIterator; + virtual Node* toNode(); + virtual DOMWindow* toDOMWindow(); + virtual bool isMessagePort() const; + + struct ListenerOptions { + ListenerOptions(bool capture = false) + : capture(capture) + { } + + bool capture; }; - class EventTargetWithInlineData : public EventTarget { - protected: - virtual EventTargetData* eventTargetData() override final { return &m_eventTargetData; } - virtual EventTargetData& ensureEventTargetData() override final { return m_eventTargetData; } - private: - EventTargetData m_eventTargetData; + struct AddEventListenerOptions : ListenerOptions { + AddEventListenerOptions(bool capture = false, bool passive = false, bool once = false) + : ListenerOptions(capture) + , passive(passive) + , once(once) + { } + + bool passive; + bool once; }; - // FIXME: These macros should be split into separate DEFINE and DECLARE - // macros to avoid causing so many header includes. - #define DEFINE_ATTRIBUTE_EVENT_LISTENER(attribute) \ - EventListener* on##attribute() { return getAttributeEventListener(eventNames().attribute##Event); } \ - void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().attribute##Event, listener); } \ - - #define DECLARE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(attribute) \ - virtual EventListener* on##attribute(); \ - virtual void setOn##attribute(PassRefPtr<EventListener> listener); \ - - #define DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(type, attribute) \ - EventListener* type::on##attribute() { return getAttributeEventListener(eventNames().attribute##Event); } \ - void type::setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().attribute##Event, listener); } \ - - #define DEFINE_WINDOW_ATTRIBUTE_EVENT_LISTENER(attribute) \ - EventListener* on##attribute() { return document().getWindowAttributeEventListener(eventNames().attribute##Event); } \ - void setOn##attribute(PassRefPtr<EventListener> listener) { document().setWindowAttributeEventListener(eventNames().attribute##Event, listener); } \ - - #define DEFINE_MAPPED_ATTRIBUTE_EVENT_LISTENER(attribute, eventName) \ - EventListener* on##attribute() { return getAttributeEventListener(eventNames().eventName##Event); } \ - void setOn##attribute(PassRefPtr<EventListener> listener) { setAttributeEventListener(eventNames().eventName##Event, listener); } \ - - #define DECLARE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(recipient, attribute) \ - EventListener* on##attribute(); \ - void setOn##attribute(PassRefPtr<EventListener> listener); - - #define DEFINE_FORWARDING_ATTRIBUTE_EVENT_LISTENER(type, recipient, attribute) \ - EventListener* type::on##attribute() { return recipient ? recipient->getAttributeEventListener(eventNames().attribute##Event) : 0; } \ - void type::setOn##attribute(PassRefPtr<EventListener> listener) { if (recipient) recipient->setAttributeEventListener(eventNames().attribute##Event, listener); } - - inline void EventTarget::visitJSEventListeners(JSC::SlotVisitor& visitor) - { - EventListenerIterator iterator(this); - while (EventListener* listener = iterator.nextListener()) - listener->visitJSFunction(visitor); - } - - inline bool EventTarget::isFiringEventListeners() - { - EventTargetData* d = eventTargetData(); - if (!d) - return false; - return d->firingEventIterators && !d->firingEventIterators->isEmpty(); - } - - inline bool EventTarget::hasEventListeners() const - { - EventTargetData* d = const_cast<EventTarget*>(this)->eventTargetData(); - if (!d) - return false; - return !d->eventListenerMap.isEmpty(); - } - - inline bool EventTarget::hasEventListeners(const AtomicString& eventType) - { - EventTargetData* d = eventTargetData(); - if (!d) - return false; - return d->eventListenerMap.contains(eventType); - } - - inline bool EventTarget::hasCapturingEventListeners(const AtomicString& eventType) - { - EventTargetData* d = eventTargetData(); - if (!d) - return false; - return d->eventListenerMap.containsCapturing(eventType); - } + using AddEventListenerOptionsOrBoolean = Variant<AddEventListenerOptions, bool>; + WEBCORE_EXPORT void addEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&&, AddEventListenerOptionsOrBoolean&&); + using ListenerOptionsOrBoolean = Variant<ListenerOptions, bool>; + WEBCORE_EXPORT void removeEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&&, ListenerOptionsOrBoolean&&); + WEBCORE_EXPORT ExceptionOr<bool> dispatchEventForBindings(Event&); + + virtual bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions& = { }); + virtual bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&); + + virtual void removeAllEventListeners(); + virtual bool dispatchEvent(Event&); + virtual void uncaughtExceptionInEventHandler(); + + // Used for legacy "onevent" attributes. + bool setAttributeEventListener(const AtomicString& eventType, RefPtr<EventListener>&&, DOMWrapperWorld&); + EventListener* attributeEventListener(const AtomicString& eventType, DOMWrapperWorld&); + + bool hasEventListeners() const; + bool hasEventListeners(const AtomicString& eventType) const; + bool hasCapturingEventListeners(const AtomicString& eventType); + bool hasActiveEventListeners(const AtomicString& eventType) const; + const EventListenerVector& eventListeners(const AtomicString& eventType); + + bool fireEventListeners(Event&); + bool isFiringEventListeners() const; + + void visitJSEventListeners(JSC::SlotVisitor&); + void invalidateJSEventListeners(JSC::JSObject*); + +protected: + virtual ~EventTarget() = default; + + virtual EventTargetData* eventTargetData() = 0; + virtual EventTargetData* eventTargetDataConcurrently() = 0; + virtual EventTargetData& ensureEventTargetData() = 0; + const EventTargetData* eventTargetData() const; + +private: + virtual void refEventTarget() = 0; + virtual void derefEventTarget() = 0; + + void fireEventListeners(Event&, EventListenerVector); + + friend class EventListenerIterator; +}; + +class EventTargetWithInlineData : public EventTarget { +protected: + EventTargetData* eventTargetData() final { return &m_eventTargetData; } + EventTargetData* eventTargetDataConcurrently() final { return &m_eventTargetData; } + EventTargetData& ensureEventTargetData() final { return m_eventTargetData; } +private: + EventTargetData m_eventTargetData; +}; + +inline const EventTargetData* EventTarget::eventTargetData() const +{ + return const_cast<EventTarget*>(this)->eventTargetData(); +} + +inline bool EventTarget::isFiringEventListeners() const +{ + auto* data = eventTargetData(); + return data && data->isFiringEventListeners; +} + +inline bool EventTarget::hasEventListeners() const +{ + auto* data = eventTargetData(); + return data && !data->eventListenerMap.isEmpty(); +} + +inline bool EventTarget::hasEventListeners(const AtomicString& eventType) const +{ + auto* data = eventTargetData(); + return data && data->eventListenerMap.contains(eventType); +} + +inline bool EventTarget::hasCapturingEventListeners(const AtomicString& eventType) +{ + auto* data = eventTargetData(); + return data && data->eventListenerMap.containsCapturing(eventType); +} } // namespace WebCore - -#endif // EventTarget_h |