Changeset 201735 in webkit


Ignore:
Timestamp:
Jun 6, 2016 7:35:39 PM (8 years ago)
Author:
Chris Dumez
Message:

Implement EventListenerOptions argument to addEventListener
https://bugs.webkit.org/show_bug.cgi?id=149466
<rdar://problem/22802031>

Reviewed by Dean Jackson.

LayoutTests/imported/w3c:

Import new test from W3C that covers EventListenerOptions.

  • web-platform-tests/dom/events/EventListenerOptions-capture-expected.txt: Added.
  • web-platform-tests/dom/events/EventListenerOptions-capture.html: Added.

Source/WebCore:

Implement AddEventListenerOptions dictionary argument to addEventListener()
and EventListenerOptions dictionary argument to removeEventListener(), as
per the latest DOM specification:

Firefox and Chrome already support this.

Support for AddEventListenerOptions in this patch is as follows:

  • 'capture': fully supported.
  • 'once': fully supported.
  • 'passive': supported in the sense that preventDefault() will be ignored

for passive event listeners. There are however currently no
performance benefits from passing this flag. Those optimizations
will be implemented in follow-up patches (in particular for
Touch and Scroll events).

Tests: fast/events/AddEventListenerOptions-once-recursive.html

fast/events/AddEventListenerOptions-once.html
fast/events/AddEventListenerOptions-passive.html
fast/events/removeEventListener-EventListenerOptions-capture.html
imported/w3c/web-platform-tests/dom/events/EventListenerOptions-capture.html

  • Modules/webaudio/AudioScheduledSourceNode.cpp:

(WebCore::AudioScheduledSourceNode::addEventListener):
(WebCore::AudioScheduledSourceNode::removeEventListener):

  • Modules/webaudio/AudioScheduledSourceNode.h:
  • Modules/webaudio/ScriptProcessorNode.cpp:

(WebCore::ScriptProcessorNode::addEventListener):
(WebCore::ScriptProcessorNode::removeEventListener):

  • Modules/webaudio/ScriptProcessorNode.h:
  • bindings/scripts/CodeGeneratorJS.pm:

(GenerateParametersCheckExpression):

  • dom/Event.h:

(WebCore::Event::preventDefault):
(WebCore::Event::setInPassiveListener):

  • dom/EventListenerMap.cpp:

(WebCore::addListenerToVector):
(WebCore::EventListenerMap::add):

  • dom/EventListenerMap.h:
  • dom/EventTarget.cpp:

(WebCore::EventTarget::addEventListener):
(WebCore::EventTarget::addEventListenerForBindings):
(WebCore::EventTarget::removeEventListenerForBindings):
(WebCore::EventTarget::removeEventListener):
(WebCore::EventTarget::setAttributeEventListener):
(WebCore::EventTarget::fireEventListeners):

  • dom/EventTarget.h:

(WebCore::EventTarget::ListenerOptions::ListenerOptions):
(WebCore::EventTarget::AddEventListenerOptions::AddEventListenerOptions):
(WebCore::EventTarget::addEventListener):
(WebCore::EventTarget::addEventListenerForBindings):
(WebCore::EventTarget::removeEventListenerForBindings):

  • dom/EventTarget.idl:
  • dom/MessagePort.cpp:

(WebCore::MessagePort::addEventListener):

  • dom/MessagePort.h:
  • dom/Node.cpp:

(WebCore::tryAddEventListener):
(WebCore::Node::addEventListener):
(WebCore::tryRemoveEventListener):
(WebCore::Node::removeEventListener):

  • dom/Node.h:
  • dom/RegisteredEventListener.h:

(WebCore::RegisteredEventListener::Options::Options):
(WebCore::RegisteredEventListener::RegisteredEventListener):
(WebCore::operator==):

  • html/HTMLMediaElement.cpp:

(WebCore::HTMLMediaElement::addEventListener):
(WebCore::HTMLMediaElement::removeEventListener):

  • html/HTMLMediaElement.h:
  • page/DOMWindow.cpp:

(WebCore::DOMWindow::addEventListener):
(WebCore::DOMWindow::removeEventListener):

  • page/DOMWindow.h:
  • svg/SVGElement.cpp:

(WebCore::SVGElement::addEventListener):
(WebCore::SVGElement::removeEventListener):

  • svg/SVGElement.h:

LayoutTests:

  • fast/events/AddEventListenerOptions-once-expected.txt: Added.
  • fast/events/AddEventListenerOptions-once-recursive-expected.txt: Added.
  • fast/events/AddEventListenerOptions-once-recursive.html: Added.
  • fast/events/AddEventListenerOptions-once.html: Added.
  • fast/events/AddEventListenerOptions-passive-expected.txt: Added.
  • fast/events/AddEventListenerOptions-passive.html: Added.
  • fast/events/removeEventListener-EventListenerOptions-capture-expected.txt: Added.
  • fast/events/removeEventListener-EventListenerOptions-capture.html: Added.

Add layout testing coverage for various aspects of the functionality.

  • imported/blink/fast/events/eventlisteneroptions/capture_default-expected.txt: Added.
  • imported/blink/fast/events/eventlisteneroptions/capture_default.html: Added.
  • imported/blink/fast/events/eventlisteneroptions/capture_equality-expected.txt: Added.
  • imported/blink/fast/events/eventlisteneroptions/capture_equality.html: Added.
  • imported/blink/fast/events/eventlisteneroptions/capture_query-expected.txt: Added.
  • imported/blink/fast/events/eventlisteneroptions/capture_query.html: Added.
  • imported/blink/fast/events/eventlisteneroptions/passive_dispatch-expected.txt: Added.
  • imported/blink/fast/events/eventlisteneroptions/passive_dispatch.html: Added.
  • imported/blink/fast/events/eventlisteneroptions/passive_inequality-expected.txt: Added.
  • imported/blink/fast/events/eventlisteneroptions/passive_inequality.html: Added.
  • imported/blink/fast/events/eventlisteneroptions/passive_query-expected.txt: Added.
  • imported/blink/fast/events/eventlisteneroptions/passive_query.html: Added.

Import blink tests for this functionality.

Location:
trunk
Files:
23 added
25 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r201734 r201735  
     12016-06-06  Chris Dumez  <cdumez@apple.com>
     2
     3        Implement EventListenerOptions argument to addEventListener
     4        https://bugs.webkit.org/show_bug.cgi?id=149466
     5        <rdar://problem/22802031>
     6
     7        Reviewed by Dean Jackson.
     8
     9        * fast/events/AddEventListenerOptions-once-expected.txt: Added.
     10        * fast/events/AddEventListenerOptions-once-recursive-expected.txt: Added.
     11        * fast/events/AddEventListenerOptions-once-recursive.html: Added.
     12        * fast/events/AddEventListenerOptions-once.html: Added.
     13        * fast/events/AddEventListenerOptions-passive-expected.txt: Added.
     14        * fast/events/AddEventListenerOptions-passive.html: Added.
     15        * fast/events/removeEventListener-EventListenerOptions-capture-expected.txt: Added.
     16        * fast/events/removeEventListener-EventListenerOptions-capture.html: Added.
     17
     18        Add layout testing coverage for various aspects of the functionality.
     19
     20        * imported/blink/fast/events/eventlisteneroptions/capture_default-expected.txt: Added.
     21        * imported/blink/fast/events/eventlisteneroptions/capture_default.html: Added.
     22        * imported/blink/fast/events/eventlisteneroptions/capture_equality-expected.txt: Added.
     23        * imported/blink/fast/events/eventlisteneroptions/capture_equality.html: Added.
     24        * imported/blink/fast/events/eventlisteneroptions/capture_query-expected.txt: Added.
     25        * imported/blink/fast/events/eventlisteneroptions/capture_query.html: Added.
     26        * imported/blink/fast/events/eventlisteneroptions/passive_dispatch-expected.txt: Added.
     27        * imported/blink/fast/events/eventlisteneroptions/passive_dispatch.html: Added.
     28        * imported/blink/fast/events/eventlisteneroptions/passive_inequality-expected.txt: Added.
     29        * imported/blink/fast/events/eventlisteneroptions/passive_inequality.html: Added.
     30        * imported/blink/fast/events/eventlisteneroptions/passive_query-expected.txt: Added.
     31        * imported/blink/fast/events/eventlisteneroptions/passive_query.html: Added.
     32
     33        Import blink tests for this functionality.
     34
    1352016-06-06  Commit Queue  <commit-queue@webkit.org>
    236
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r201734 r201735  
     12016-06-06  Chris Dumez  <cdumez@apple.com>
     2
     3        Implement EventListenerOptions argument to addEventListener
     4        https://bugs.webkit.org/show_bug.cgi?id=149466
     5        <rdar://problem/22802031>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Import new test from W3C that covers EventListenerOptions.
     10
     11        * web-platform-tests/dom/events/EventListenerOptions-capture-expected.txt: Added.
     12        * web-platform-tests/dom/events/EventListenerOptions-capture.html: Added.
     13
    1142016-06-06  Commit Queue  <commit-queue@webkit.org>
    215
  • trunk/Source/WebCore/ChangeLog

    r201734 r201735  
     12016-06-06  Chris Dumez  <cdumez@apple.com>
     2
     3        Implement EventListenerOptions argument to addEventListener
     4        https://bugs.webkit.org/show_bug.cgi?id=149466
     5        <rdar://problem/22802031>
     6
     7        Reviewed by Dean Jackson.
     8
     9        Implement AddEventListenerOptions dictionary argument to addEventListener()
     10        and EventListenerOptions dictionary argument to removeEventListener(), as
     11        per the latest DOM specification:
     12        - https://dom.spec.whatwg.org/#interface-eventtarget
     13
     14        Firefox and Chrome already support this.
     15
     16        Support for AddEventListenerOptions in this patch is as follows:
     17        - 'capture': fully supported.
     18        - 'once': fully supported.
     19        - 'passive': supported in the sense that preventDefault() will be ignored
     20                     for passive event listeners. There are however currently no
     21                     performance benefits from passing this flag. Those optimizations
     22                     will be implemented in follow-up patches (in particular for
     23                     Touch and Scroll events).
     24
     25        Tests: fast/events/AddEventListenerOptions-once-recursive.html
     26               fast/events/AddEventListenerOptions-once.html
     27               fast/events/AddEventListenerOptions-passive.html
     28               fast/events/removeEventListener-EventListenerOptions-capture.html
     29               imported/w3c/web-platform-tests/dom/events/EventListenerOptions-capture.html
     30
     31        * Modules/webaudio/AudioScheduledSourceNode.cpp:
     32        (WebCore::AudioScheduledSourceNode::addEventListener):
     33        (WebCore::AudioScheduledSourceNode::removeEventListener):
     34        * Modules/webaudio/AudioScheduledSourceNode.h:
     35        * Modules/webaudio/ScriptProcessorNode.cpp:
     36        (WebCore::ScriptProcessorNode::addEventListener):
     37        (WebCore::ScriptProcessorNode::removeEventListener):
     38        * Modules/webaudio/ScriptProcessorNode.h:
     39        * bindings/scripts/CodeGeneratorJS.pm:
     40        (GenerateParametersCheckExpression):
     41        * dom/Event.h:
     42        (WebCore::Event::preventDefault):
     43        (WebCore::Event::setInPassiveListener):
     44        * dom/EventListenerMap.cpp:
     45        (WebCore::addListenerToVector):
     46        (WebCore::EventListenerMap::add):
     47        * dom/EventListenerMap.h:
     48        * dom/EventTarget.cpp:
     49        (WebCore::EventTarget::addEventListener):
     50        (WebCore::EventTarget::addEventListenerForBindings):
     51        (WebCore::EventTarget::removeEventListenerForBindings):
     52        (WebCore::EventTarget::removeEventListener):
     53        (WebCore::EventTarget::setAttributeEventListener):
     54        (WebCore::EventTarget::fireEventListeners):
     55        * dom/EventTarget.h:
     56        (WebCore::EventTarget::ListenerOptions::ListenerOptions):
     57        (WebCore::EventTarget::AddEventListenerOptions::AddEventListenerOptions):
     58        (WebCore::EventTarget::addEventListener):
     59        (WebCore::EventTarget::addEventListenerForBindings):
     60        (WebCore::EventTarget::removeEventListenerForBindings):
     61        * dom/EventTarget.idl:
     62        * dom/MessagePort.cpp:
     63        (WebCore::MessagePort::addEventListener):
     64        * dom/MessagePort.h:
     65        * dom/Node.cpp:
     66        (WebCore::tryAddEventListener):
     67        (WebCore::Node::addEventListener):
     68        (WebCore::tryRemoveEventListener):
     69        (WebCore::Node::removeEventListener):
     70        * dom/Node.h:
     71        * dom/RegisteredEventListener.h:
     72        (WebCore::RegisteredEventListener::Options::Options):
     73        (WebCore::RegisteredEventListener::RegisteredEventListener):
     74        (WebCore::operator==):
     75        * html/HTMLMediaElement.cpp:
     76        (WebCore::HTMLMediaElement::addEventListener):
     77        (WebCore::HTMLMediaElement::removeEventListener):
     78        * html/HTMLMediaElement.h:
     79        * page/DOMWindow.cpp:
     80        (WebCore::DOMWindow::addEventListener):
     81        (WebCore::DOMWindow::removeEventListener):
     82        * page/DOMWindow.h:
     83        * svg/SVGElement.cpp:
     84        (WebCore::SVGElement::addEventListener):
     85        (WebCore::SVGElement::removeEventListener):
     86        * svg/SVGElement.h:
     87
    1882016-06-06  Commit Queue  <commit-queue@webkit.org>
    289
  • trunk/Source/WebCore/Modules/webaudio/AudioScheduledSourceNode.cpp

    r201734 r201735  
    202202}
    203203
    204 bool AudioScheduledSourceNode::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, bool useCapture)
    205 {
    206     bool success = AudioNode::addEventListener(eventType, WTFMove(listener), useCapture);
     204bool AudioScheduledSourceNode::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
     205{
     206    bool success = AudioNode::addEventListener(eventType, WTFMove(listener), options);
    207207    if (success && eventType == eventNames().endedEvent)
    208208        m_hasEndedListener = hasEventListeners(eventNames().endedEvent);
     
    210210}
    211211
    212 bool AudioScheduledSourceNode::removeEventListener(const AtomicString& eventType, EventListener& listener, bool useCapture)
    213 {
    214     bool success = AudioNode::removeEventListener(eventType, listener, useCapture);
     212bool AudioScheduledSourceNode::removeEventListener(const AtomicString& eventType, EventListener& listener, const ListenerOptions& options)
     213{
     214    bool success = AudioNode::removeEventListener(eventType, listener, options);
    215215    if (success && eventType == eventNames().endedEvent)
    216216        m_hasEndedListener = hasEventListeners(eventNames().endedEvent);
  • trunk/Source/WebCore/Modules/webaudio/AudioScheduledSourceNode.h

    r201734 r201735  
    102102
    103103private:
    104     bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, bool useCapture) override;
    105     bool removeEventListener(const AtomicString& eventType, EventListener&, bool useCapture) override;
     104    bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
     105    bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) override;
    106106    void removeAllEventListeners() override;
    107107};
  • trunk/Source/WebCore/Modules/webaudio/ScriptProcessorNode.cpp

    r201734 r201735  
    274274}
    275275
    276 bool ScriptProcessorNode::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, bool useCapture)
    277 {
    278     bool success = AudioNode::addEventListener(eventType, WTFMove(listener), useCapture);
     276bool ScriptProcessorNode::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
     277{
     278    bool success = AudioNode::addEventListener(eventType, WTFMove(listener), options);
    279279    if (success && eventType == eventNames().audioprocessEvent)
    280280        m_hasAudioProcessListener = hasEventListeners(eventNames().audioprocessEvent);
     
    282282}
    283283
    284 bool ScriptProcessorNode::removeEventListener(const AtomicString& eventType, EventListener& listener, bool useCapture)
    285 {
    286     bool success = AudioNode::removeEventListener(eventType, listener, useCapture);
     284bool ScriptProcessorNode::removeEventListener(const AtomicString& eventType, EventListener& listener, const ListenerOptions& options)
     285{
     286    bool success = AudioNode::removeEventListener(eventType, listener, options);
    287287    if (success && eventType == eventNames().audioprocessEvent)
    288288        m_hasAudioProcessListener = hasEventListeners(eventNames().audioprocessEvent);
  • trunk/Source/WebCore/Modules/webaudio/ScriptProcessorNode.h

    r201734 r201735  
    7474    void fireProcessEvent();
    7575
    76     bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, bool useCapture) override;
    77     bool removeEventListener(const AtomicString& eventType, EventListener&, bool useCapture) override;
     76    bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
     77    bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) override;
    7878    void removeAllEventListeners() override;
    7979
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r201734 r201735  
    16791679            }
    16801680            $usedArguments{$parameterIndex} = 1;
    1681         } elsif ($codeGenerator->GetArrayOrSequenceType($type) || $codeGenerator->IsTypedArrayType($type) || $codeGenerator->IsWrapperType($type)) {
     1681        } elsif ($codeGenerator->IsDictionaryType($parameter->type)) {
     1682            push(@andExpression, "(${value}.isUndefinedOrNull() || ${value}.isObject())");
     1683            $usedArguments{$parameterIndex} = 1;
     1684        } elsif (($codeGenerator->GetArrayOrSequenceType($type) || $codeGenerator->IsTypedArrayType($type) || $codeGenerator->IsWrapperType($type)) && $type ne "EventListener") {
    16821685            my $condition = "";
    16831686
  • trunk/Source/WebCore/dom/Event.h

    r201734 r201735  
    173173    void preventDefault()
    174174    {
    175         if (m_cancelable)
     175        if (m_cancelable && !m_isExecutingPassiveEventListener)
    176176            m_defaultPrevented = true;
    177177    }
     
    180180    bool defaultHandled() const { return m_defaultHandled; }
    181181    void setDefaultHandled() { m_defaultHandled = true; }
     182
     183    void setInPassiveListener(bool value) { m_isExecutingPassiveEventListener = value; }
    182184
    183185    bool cancelBubble() const { return m_cancelBubble; }
     
    218220    bool m_cancelBubble { false };
    219221    bool m_isTrusted { false };
     222    bool m_isExecutingPassiveEventListener { false };
    220223
    221224    unsigned short m_eventPhase { 0 };
  • trunk/Source/WebCore/dom/EventListenerMap.cpp

    r201734 r201735  
    9696}
    9797
    98 static bool addListenerToVector(EventListenerVector* vector, Ref<EventListener>&& listener, bool useCapture)
    99 {
    100     RegisteredEventListener registeredListener(WTFMove(listener), useCapture);
     98static bool addListenerToVector(EventListenerVector* vector, Ref<EventListener>&& listener, const RegisteredEventListener::Options& options)
     99{
     100    RegisteredEventListener registeredListener(WTFMove(listener), options);
    101101
    102102    if (vector->find(registeredListener) != notFound)
     
    107107}
    108108
    109 bool EventListenerMap::add(const AtomicString& eventType, Ref<EventListener>&& listener, bool useCapture)
     109bool EventListenerMap::add(const AtomicString& eventType, Ref<EventListener>&& listener, const RegisteredEventListener::Options& options)
    110110{
    111111    assertNoActiveIterators();
     
    113113    for (auto& entry : m_entries) {
    114114        if (entry.first == eventType)
    115             return addListenerToVector(entry.second.get(), WTFMove(listener), useCapture);
     115            return addListenerToVector(entry.second.get(), WTFMove(listener), options);
    116116    }
    117117
    118118    m_entries.append(std::make_pair(eventType, std::make_unique<EventListenerVector>()));
    119     return addListenerToVector(m_entries.last().second.get(), WTFMove(listener), useCapture);
     119    return addListenerToVector(m_entries.last().second.get(), WTFMove(listener), options);
    120120}
    121121
  • trunk/Source/WebCore/dom/EventListenerMap.h

    r201734 r201735  
    5555
    5656    void clear();
    57     bool add(const AtomicString& eventType, Ref<EventListener>&&, bool useCapture);
     57
     58    bool add(const AtomicString& eventType, Ref<EventListener>&&, const RegisteredEventListener::Options&);
    5859    bool remove(const AtomicString& eventType, EventListener&, bool useCapture, size_t& indexOfRemovedListener);
    5960    EventListenerVector* find(const AtomicString& eventType);
  • trunk/Source/WebCore/dom/EventTarget.cpp

    r201734 r201735  
    7676}
    7777
    78 bool EventTarget::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, bool useCapture)
    79 {
    80     return ensureEventTargetData().eventListenerMap.add(eventType, WTFMove(listener), useCapture);
    81 }
    82 
    83 void EventTarget::addEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&& listener, bool useCapture)
    84 {
    85     // FIXME: listener is not supposed to be nullable.
     78bool EventTarget::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
     79{
     80    return ensureEventTargetData().eventListenerMap.add(eventType, WTFMove(listener), { options.capture, options.passive, options.once });
     81}
     82
     83void EventTarget::addEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&& listener, const AddEventListenerOptions& options)
     84{
    8685    if (!listener)
    8786        return;
    88     addEventListener(eventType, listener.releaseNonNull(), useCapture);
    89 }
    90 
    91 void EventTarget::removeEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&& listener, bool useCapture)
    92 {
    93     // FIXME: listener is not supposed to be nullable.
     87    addEventListener(eventType, listener.releaseNonNull(), options);
     88}
     89
     90void EventTarget::removeEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&& listener, const ListenerOptions& options)
     91{
    9492    if (!listener)
    9593        return;
    96     removeEventListener(eventType, *listener, useCapture);
    97 }
    98 
    99 bool EventTarget::removeEventListener(const AtomicString& eventType, EventListener& listener, bool useCapture)
     94    removeEventListener(eventType, *listener, options);
     95}
     96
     97bool EventTarget::removeEventListener(const AtomicString& eventType, EventListener& listener, const ListenerOptions& options)
    10098{
    10199    EventTargetData* d = eventTargetData();
     
    105103    size_t indexOfRemovedListener;
    106104
    107     if (!d->eventListenerMap.remove(eventType, listener, useCapture, indexOfRemovedListener))
     105    if (!d->eventListenerMap.remove(eventType, listener, options.capture, indexOfRemovedListener))
    108106        return false;
    109107
     
    132130    if (!listener)
    133131        return false;
    134     return addEventListener(eventType, listener.releaseNonNull(), false);
     132    return addEventListener(eventType, listener.releaseNonNull());
    135133}
    136134
     
    260258
    261259    for (; i < size; ++i) {
    262         RegisteredEventListener& registeredListener = entry[i];
     260        RegisteredEventListener registeredListener = entry[i];
     261
     262        if (registeredListener.isMarkedForRemoval)
     263            continue;
     264
    263265        if (event.eventPhase() == Event::CAPTURING_PHASE && !registeredListener.useCapture)
    264266            continue;
     
    270272        if (event.immediatePropagationStopped())
    271273            break;
     274
     275        if (registeredListener.isPassive)
     276            event.setInPassiveListener(true);
     277
     278        // Mark listener for removal before executing the listener, in case the listener tries to
     279        // dispatch an event that would cause it to get executed again.
     280        if (registeredListener.isOnce)
     281            registeredListener.isMarkedForRemoval = true;
    272282
    273283        InspectorInstrumentationCookie cookie = InspectorInstrumentation::willHandleEvent(context, event);
     
    276286        registeredListener.listener->handleEvent(context, &event);
    277287        InspectorInstrumentation::didHandleEvent(cookie);
    278     }
     288
     289        if (registeredListener.isPassive)
     290            event.setInPassiveListener(false);
     291
     292        if (registeredListener.isOnce)
     293            removeEventListener(event.type(), *registeredListener.listener, ListenerOptions(registeredListener.useCapture));
     294    }
     295
    279296    d->firingEventIterators->removeLast();
    280297
  • trunk/Source/WebCore/dom/EventTarget.h

    r201734 r201735  
    122122    virtual bool isMessagePort() const;
    123123
     124    struct ListenerOptions {
     125        ListenerOptions(bool capture = false)
     126            : capture(capture)
     127        { }
     128
     129        bool capture;
     130    };
     131
     132    struct AddEventListenerOptions : public ListenerOptions {
     133        AddEventListenerOptions(bool capture = false, bool passive = false, bool once = false)
     134            : ListenerOptions(capture)
     135            , passive(passive)
     136            , once(once)
     137        { }
     138
     139        bool passive;
     140        bool once;
     141    };
     142
    124143    void addEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&&, bool useCapture);
    125144    void removeEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&&, bool useCapture);
    126     virtual bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, bool useCapture);
    127     virtual bool removeEventListener(const AtomicString& eventType, EventListener&, bool useCapture);
     145    void addEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&&, const AddEventListenerOptions&);
     146    void removeEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&&, const ListenerOptions&);
     147    virtual bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions& = { });
     148    virtual bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&);
    128149
    129150    virtual void removeAllEventListeners();
     
    210231}
    211232
     233inline void EventTarget::addEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&& listener, bool useCapture)
     234{
     235    addEventListenerForBindings(eventType, WTFMove(listener), AddEventListenerOptions(useCapture));
     236}
     237
     238inline void EventTarget::removeEventListenerForBindings(const AtomicString& eventType, RefPtr<EventListener>&& listener, bool useCapture)
     239{
     240    removeEventListenerForBindings(eventType, WTFMove(listener), ListenerOptions(useCapture));
     241}
     242
    212243} // namespace WebCore
    213244
  • trunk/Source/WebCore/dom/EventTarget.idl

    r201734 r201735  
    2626    ObjCProtocol,
    2727] interface EventTarget {
     28#if defined(LANGUAGE_JAVASCRIPT) && LANGUAGE_JAVASCRIPT
     29    [ImplementedAs=addEventListenerForBindings] void addEventListener([AtomicString] DOMString type, EventListener? listener, optional AddEventListenerOptions options);
     30    [ImplementedAs=removeEventListenerForBindings] void removeEventListener([AtomicString] DOMString type, EventListener? listener, optional EventListenerOptions options);
     31#endif
     32
    2833    // FIXME: The 'type' and 'listener' parameters should not be optional.
    2934    [ObjCLegacyUnnamedParameters, ImplementedAs=addEventListenerForBindings] void addEventListener([AtomicString] optional DOMString type = "undefined", optional EventListener? listener, optional boolean useCapture = false);
     
    3338    [ImplementedAs=dispatchEventForBindings, RaisesException] boolean dispatchEvent(Event? event);
    3439};
     40
     41dictionary EventListenerOptions {
     42    boolean capture = false;
     43};
     44
     45dictionary AddEventListenerOptions {
     46    boolean capture = false;
     47    boolean passive = false;
     48    boolean once = false;
     49};
  • trunk/Source/WebCore/dom/MessagePort.cpp

    r201734 r201735  
    222222}
    223223
    224 bool MessagePort::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, bool useCapture)
     224bool MessagePort::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
    225225{
    226226    if (listener->isAttribute() && eventType == eventNames().messageEvent)
    227227        start();
    228     return EventTargetWithInlineData::addEventListener(eventType, WTFMove(listener), useCapture);
     228    return EventTargetWithInlineData::addEventListener(eventType, WTFMove(listener), options);
    229229}
    230230
  • trunk/Source/WebCore/dom/MessagePort.h

    r201734 r201735  
    9393        bool isNeutered() { return !m_entangledChannel; }
    9494
    95         bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, bool useCapture) override;
     95        bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
    9696
    9797    private:
  • trunk/Source/WebCore/dom/Node.cpp

    r201734 r201735  
    19081908}
    19091909
    1910 static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eventType, Ref<EventListener>&& listener, bool useCapture)
    1911 {
    1912     if (!targetNode->EventTarget::addEventListener(eventType, listener.copyRef(), useCapture))
     1910static inline bool tryAddEventListener(Node* targetNode, const AtomicString& eventType, Ref<EventListener>&& listener, const EventTarget::AddEventListenerOptions& options)
     1911{
     1912    if (!targetNode->EventTarget::addEventListener(eventType, listener.copyRef(), options))
    19131913        return false;
    19141914
     
    19281928    // Forward this call to addEventListener() to the window since these are window-only events.
    19291929    if (eventType == eventNames().orientationchangeEvent || eventType == eventNames().resizeEvent)
    1930         targetNode->document().domWindow()->addEventListener(eventType, WTFMove(listener), useCapture);
     1930        targetNode->document().domWindow()->addEventListener(eventType, WTFMove(listener), options);
    19311931
    19321932#if ENABLE(TOUCH_EVENTS)
     
    19441944}
    19451945
    1946 bool Node::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, bool useCapture)
    1947 {
    1948     return tryAddEventListener(this, eventType, WTFMove(listener), useCapture);
    1949 }
    1950 
    1951 static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& eventType, EventListener& listener, bool useCapture)
    1952 {
    1953     if (!targetNode->EventTarget::removeEventListener(eventType, listener, useCapture))
     1946bool Node::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
     1947{
     1948    return tryAddEventListener(this, eventType, WTFMove(listener), options);
     1949}
     1950
     1951static inline bool tryRemoveEventListener(Node* targetNode, const AtomicString& eventType, EventListener& listener, const EventTarget::ListenerOptions& options)
     1952{
     1953    if (!targetNode->EventTarget::removeEventListener(eventType, listener, options))
    19541954        return false;
    19551955
     
    19691969    // Forward this call to removeEventListener() to the window since these are window-only events.
    19701970    if (eventType == eventNames().orientationchangeEvent || eventType == eventNames().resizeEvent)
    1971         targetNode->document().domWindow()->removeEventListener(eventType, listener, useCapture);
     1971        targetNode->document().domWindow()->removeEventListener(eventType, listener, options);
    19721972
    19731973#if ENABLE(TOUCH_EVENTS)
     
    19851985}
    19861986
    1987 bool Node::removeEventListener(const AtomicString& eventType, EventListener& listener, bool useCapture)
    1988 {
    1989     return tryRemoveEventListener(this, eventType, listener, useCapture);
     1987bool Node::removeEventListener(const AtomicString& eventType, EventListener& listener, const ListenerOptions& options)
     1988{
     1989    return tryRemoveEventListener(this, eventType, listener, options);
    19901990}
    19911991
  • trunk/Source/WebCore/dom/Node.h

    r201734 r201735  
    508508    ScriptExecutionContext* scriptExecutionContext() const final; // Implemented in Document.h
    509509
    510     bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, bool useCapture) override;
    511     bool removeEventListener(const AtomicString& eventType, EventListener&, bool useCapture) override;
     510    bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
     511    bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) override;
    512512
    513513    using EventTarget::dispatchEvent;
  • trunk/Source/WebCore/dom/RegisteredEventListener.h

    r201734 r201735  
    3232    class RegisteredEventListener {
    3333    public:
     34        struct Options {
     35            Options(bool capture = false, bool passive = false, bool once = false)
     36                : capture(capture)
     37                , passive(passive)
     38                , once(once)
     39            { }
     40
     41            bool capture;
     42            bool passive;
     43            bool once;
     44        };
     45
     46        RegisteredEventListener(Ref<EventListener>&& listener, const Options& options)
     47            : listener(WTFMove(listener))
     48            , useCapture(options.capture)
     49            , isPassive(options.passive)
     50            , isOnce(options.once)
     51        {
     52        }
     53
    3454        RegisteredEventListener(Ref<EventListener>&& listener, bool useCapture)
    3555            : listener(WTFMove(listener))
     
    3959
    4060        RefPtr<EventListener> listener;
    41         bool useCapture;
     61        bool useCapture { false };
     62        bool isPassive { false };
     63        bool isOnce { false };
     64        bool isMarkedForRemoval { false };
    4265    };
    4366   
    4467    inline bool operator==(const RegisteredEventListener& a, const RegisteredEventListener& b)
    4568    {
     69        // Other data members are purposefully not checked. The DOM specification says that upon adding / removing
     70        // EventListeners, we should only check the type and the capture flag.
    4671        return *a.listener == *b.listener && a.useCapture == b.useCapture;
    4772    }
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r201734 r201735  
    52295229}
    52305230
    5231 bool HTMLMediaElement::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, bool useCapture)
     5231bool HTMLMediaElement::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
    52325232{
    52335233    if (eventType != eventNames().webkitplaybacktargetavailabilitychangedEvent)
    5234         return Node::addEventListener(eventType, WTFMove(listener), useCapture);
     5234        return Node::addEventListener(eventType, WTFMove(listener), options);
    52355235
    52365236    bool isFirstAvailabilityChangedListener = !hasEventListeners(eventNames().webkitplaybacktargetavailabilitychangedEvent);
    5237     if (!Node::addEventListener(eventType, WTFMove(listener), useCapture))
     5237    if (!Node::addEventListener(eventType, WTFMove(listener), options))
    52385238        return false;
    52395239
     
    52495249}
    52505250
    5251 bool HTMLMediaElement::removeEventListener(const AtomicString& eventType, EventListener& listener, bool useCapture)
     5251bool HTMLMediaElement::removeEventListener(const AtomicString& eventType, EventListener& listener, const ListenerOptions& options)
    52525252{
    52535253    if (eventType != eventNames().webkitplaybacktargetavailabilitychangedEvent)
    5254         return Node::removeEventListener(eventType, listener, useCapture);
    5255 
    5256     if (!Node::removeEventListener(eventType, listener, useCapture))
     5254        return Node::removeEventListener(eventType, listener, options);
     5255
     5256    if (!Node::removeEventListener(eventType, listener, options))
    52575257        return false;
    52585258
  • trunk/Source/WebCore/html/HTMLMediaElement.h

    r201734 r201735  
    343343#if ENABLE(WIRELESS_PLAYBACK_TARGET)
    344344    void webkitShowPlaybackTargetPicker();
    345     bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, bool useCapture) override;
    346     bool removeEventListener(const AtomicString& eventType, EventListener&, bool useCapture) override;
     345    bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
     346    bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) override;
    347347
    348348    void wirelessRoutesAvailableDidChange() override;
  • trunk/Source/WebCore/page/DOMWindow.cpp

    r201734 r201735  
    17231723}
    17241724
    1725 bool DOMWindow::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, bool useCapture)
    1726 {
    1727     if (!EventTarget::addEventListener(eventType, WTFMove(listener), useCapture))
     1725bool DOMWindow::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
     1726{
     1727    if (!EventTarget::addEventListener(eventType, WTFMove(listener), options))
    17281728        return false;
    17291729
     
    18261826}
    18271827
    1828 bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener& listener, bool useCapture)
    1829 {
    1830     if (!EventTarget::removeEventListener(eventType, listener, useCapture))
     1828bool DOMWindow::removeEventListener(const AtomicString& eventType, EventListener& listener, const ListenerOptions& options)
     1829{
     1830    if (!EventTarget::removeEventListener(eventType, listener, options.capture))
    18311831        return false;
    18321832
  • trunk/Source/WebCore/page/DOMWindow.h

    r201734 r201735  
    280280        // Events
    281281        // EventTarget API
    282         bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, bool useCapture) override;
    283         bool removeEventListener(const AtomicString& eventType, EventListener&, bool useCapture) override;
     282        bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
     283        bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) override;
    284284        void removeAllEventListeners() override;
    285285
  • trunk/Source/WebCore/svg/SVGElement.cpp

    r201734 r201735  
    529529}
    530530
    531 bool SVGElement::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, bool useCapture)
     531bool SVGElement::addEventListener(const AtomicString& eventType, Ref<EventListener>&& listener, const AddEventListenerOptions& options)
    532532{   
    533533    // Add event listener to regular DOM element
    534     if (!Node::addEventListener(eventType, listener.copyRef(), useCapture))
     534    if (!Node::addEventListener(eventType, listener.copyRef(), options))
    535535        return false;
    536536
     
    542542    for (auto* instance : instances()) {
    543543        ASSERT(instance->correspondingElement() == this);
    544         bool result = instance->Node::addEventListener(eventType, listener.copyRef(), useCapture);
     544        bool result = instance->Node::addEventListener(eventType, listener.copyRef(), options);
    545545        ASSERT_UNUSED(result, result);
    546546    }
     
    549549}
    550550
    551 bool SVGElement::removeEventListener(const AtomicString& eventType, EventListener& listener, bool useCapture)
     551bool SVGElement::removeEventListener(const AtomicString& eventType, EventListener& listener, const ListenerOptions& options)
    552552{
    553553    if (containingShadowRoot())
    554         return Node::removeEventListener(eventType, listener, useCapture);
     554        return Node::removeEventListener(eventType, listener, options);
    555555
    556556    // EventTarget::removeEventListener creates a PassRefPtr around the given EventListener
     
    562562
    563563    // Remove event listener from regular DOM element
    564     if (!Node::removeEventListener(eventType, listener, useCapture))
     564    if (!Node::removeEventListener(eventType, listener, options))
    565565        return false;
    566566
     
    570570        ASSERT(instance->correspondingElement() == this);
    571571
    572         if (instance->Node::removeEventListener(eventType, listener, useCapture))
     572        if (instance->Node::removeEventListener(eventType, listener, options))
    573573            continue;
    574574
  • trunk/Source/WebCore/svg/SVGElement.h

    r201734 r201735  
    134134    virtual bool haveLoadedRequiredResources();
    135135
    136     bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, bool useCapture) override;
    137     bool removeEventListener(const AtomicString& eventType, EventListener&, bool useCapture) override;
     136    bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
     137    bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) override;
    138138    bool hasFocusEventListeners() const;
    139139
Note: See TracChangeset for help on using the changeset viewer.