Remove "virtual" from all lines that have both "virtual" and "override".
[WebKit-https.git] / Source / WebCore / bindings / js / JSEventListener.h
1 /*
2  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
3  *  Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #ifndef JSEventListener_h
21 #define JSEventListener_h
22
23 #include "DOMWrapperWorld.h"
24 #include "EventListener.h"
25 #include <heap/StrongInlines.h>
26 #include <heap/Weak.h>
27 #include <heap/WeakInlines.h>
28 #include <wtf/Ref.h>
29
30 namespace WebCore {
31
32 class DOMWindow;
33 class EventTarget;
34 class HTMLElement;
35 class JSDOMGlobalObject;
36
37 class JSEventListener : public EventListener {
38 public:
39     static Ref<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld& world)
40     {
41         return adoptRef(*new JSEventListener(listener, wrapper, isAttribute, world));
42     }
43
44     static const JSEventListener* cast(const EventListener* listener)
45     {
46         return listener->type() == JSEventListenerType
47             ? static_cast<const JSEventListener*>(listener)
48             : 0;
49     }
50
51     virtual ~JSEventListener();
52
53     bool operator==(const EventListener& other) override;
54
55     // Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick".
56     bool isAttribute() const { return m_isAttribute; }
57
58     JSC::JSObject* jsFunction(ScriptExecutionContext*) const;
59     DOMWrapperWorld& isolatedWorld() const { return *m_isolatedWorld; }
60
61     JSC::JSObject* wrapper() const { return m_wrapper.get(); }
62     void setWrapper(JSC::VM&, JSC::JSObject* wrapper) const { m_wrapper = JSC::Weak<JSC::JSObject>(wrapper); }
63
64 private:
65     virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const;
66     void visitJSFunction(JSC::SlotVisitor&) override;
67     bool virtualisAttribute() const override;
68
69 protected:
70     JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&);
71     void handleEvent(ScriptExecutionContext*, Event*) override;
72
73 private:
74     mutable JSC::Weak<JSC::JSObject> m_jsFunction;
75     mutable JSC::Weak<JSC::JSObject> m_wrapper;
76
77     bool m_isAttribute;
78     RefPtr<DOMWrapperWorld> m_isolatedWorld;
79 };
80
81 // For "onxxx" attributes that automatically set up JavaScript event listeners.
82 JSC::JSValue eventHandlerAttribute(EventTarget&, const AtomicString& eventType);
83 void setEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, EventTarget&, const AtomicString& eventType, JSC::JSValue);
84
85 // Like the functions above, but for attributes that forward event handlers to the window object rather than setting them on the target.
86 JSC::JSValue windowEventHandlerAttribute(HTMLElement&, const AtomicString& eventType);
87 void setWindowEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, HTMLElement&, const AtomicString& eventType, JSC::JSValue);
88 JSC::JSValue windowEventHandlerAttribute(DOMWindow&, const AtomicString& eventType);
89 void setWindowEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, DOMWindow&, const AtomicString& eventType, JSC::JSValue);
90
91 // Like the functions above, but for attributes that forward event handlers to the document rather than setting them on the target.
92 JSC::JSValue documentEventHandlerAttribute(HTMLElement&, const AtomicString& eventType);
93 void setDocumentEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, HTMLElement&, const AtomicString& eventType, JSC::JSValue);
94 JSC::JSValue documentEventHandlerAttribute(Document&, const AtomicString& eventType);
95 void setDocumentEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, Document&, const AtomicString& eventType, JSC::JSValue);
96
97 Ref<JSEventListener> createJSEventListenerForAdd(JSC::ExecState&, JSC::JSObject& listener, JSC::JSObject& wrapper);
98 Ref<JSEventListener> createJSEventListenerForRemove(JSC::ExecState&, JSC::JSObject& listener, JSC::JSObject& wrapper);
99
100 inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext* scriptExecutionContext) const
101 {
102     // initializeJSFunction can trigger code that deletes this event listener
103     // before we're done. It should always return 0 in this case.
104     Ref<JSEventListener> protect(const_cast<JSEventListener&>(*this));
105     JSC::Strong<JSC::JSObject> wrapper(m_isolatedWorld->vm(), m_wrapper.get());
106
107     if (!m_jsFunction) {
108         JSC::JSObject* function = initializeJSFunction(scriptExecutionContext);
109         JSC::JSObject* wrapper = m_wrapper.get();
110         if (wrapper)
111             JSC::Heap::heap(wrapper)->writeBarrier(wrapper, function);
112         m_jsFunction = JSC::Weak<JSC::JSObject>(function);
113     }
114
115     // Verify that we have a valid wrapper protecting our function from
116     // garbage collection. That is except for when we're not in the normal
117     // world and can have zombie m_jsFunctions.
118     ASSERT(!m_isolatedWorld->isNormal() || m_wrapper || !m_jsFunction);
119
120     // If m_wrapper is 0, then m_jsFunction is zombied, and should never be accessed.
121     if (!m_wrapper)
122         return 0;
123
124     // Try to verify that m_jsFunction wasn't recycled. (Not exact, since an
125     // event listener can be almost anything, but this makes test-writing easier).
126     ASSERT(!m_jsFunction || static_cast<JSC::JSCell*>(m_jsFunction.get())->isObject());
127
128     return m_jsFunction.get();
129 }
130
131 inline Ref<JSEventListener> createJSEventListenerForRemove(JSC::ExecState& state, JSC::JSObject& listener, JSC::JSObject& wrapper)
132 {
133     return createJSEventListenerForAdd(state, listener, wrapper);
134 }
135
136 } // namespace WebCore
137
138 #endif // JSEventListener_h