Commit f493144c authored by ggaren@apple.com's avatar ggaren@apple.com

Removed the jsEventListeners set from JSDOMGlobalObject, to simplify

creation and destruction of JSDOMGlobalObject and event listeners.
        
Patch by Geoffrey Garen <ggaren@apple.com> on 2009-09-15
Reviewed by Sam Weinig.

Added an abstract operator==() to EventListener, to replace the
jsEventListeners set's role in determining if two event listeners are
equal from the DOM's perspective.
        
Added a type field to EventListener, and casting operations, to support
operator==() and other abstract operations.

* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSAbstractWorkerCustom.cpp:
(WebCore::JSAbstractWorker::addEventListener):
(WebCore::JSAbstractWorker::removeEventListener):
* bindings/js/JSDOMApplicationCacheCustom.cpp:
(WebCore::JSDOMApplicationCache::addEventListener):
(WebCore::JSDOMApplicationCache::removeEventListener):
* bindings/js/JSDOMGlobalObject.cpp:
* bindings/js/JSDOMGlobalObject.h:
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::addEventListener):
(WebCore::JSDOMWindow::removeEventListener):
* bindings/js/JSDesktopNotificationsCustom.cpp:
(WebCore::JSNotification::addEventListener):
(WebCore::):
* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::JSEventListener):
(WebCore::JSEventListener::~JSEventListener):
(WebCore::JSEventListener::markJSFunction):
(WebCore::JSEventListener::handleEvent):
(WebCore::JSEventListener::reportError):
(WebCore::JSEventListener::operator==):
* bindings/js/JSEventListener.h:
(WebCore::JSEventListener::cast):
* bindings/js/JSEventSourceCustom.cpp:
(WebCore::JSEventSource::addEventListener):
(WebCore::JSEventSource::removeEventListener):
* bindings/js/JSMessagePortCustom.cpp:
(WebCore::JSMessagePort::addEventListener):
(WebCore::JSMessagePort::removeEventListener):
* bindings/js/JSNodeCustom.cpp:
(WebCore::JSNode::addEventListener):
(WebCore::JSNode::removeEventListener):
* bindings/js/JSSVGElementInstanceCustom.cpp:
(WebCore::JSSVGElementInstance::addEventListener):
(WebCore::JSSVGElementInstance::removeEventListener):
* bindings/js/JSWorkerContextCustom.cpp:
(WebCore::JSWorkerContext::addEventListener):
(WebCore::JSWorkerContext::removeEventListener):
* bindings/js/JSXMLHttpRequestCustom.cpp:
(WebCore::JSXMLHttpRequest::addEventListener):
(WebCore::JSXMLHttpRequest::removeEventListener):
* bindings/js/JSXMLHttpRequestUploadCustom.cpp:
(WebCore::JSXMLHttpRequestUpload::addEventListener):
(WebCore::JSXMLHttpRequestUpload::removeEventListener):
* bindings/objc/ObjCEventListener.h:
(WebCore::ObjCEventListener::cast):
* bindings/objc/ObjCEventListener.mm:
(WebCore::ObjCEventListener::ObjCEventListener):
(WebCore::ObjCEventListener::operator==):
* dom/EventListener.h:
(WebCore::EventListener::):
(WebCore::EventListener::type):
(WebCore::EventListener::EventListener):
* dom/MessagePort.cpp:
(WebCore::MessagePort::addEventListener):
(WebCore::MessagePort::removeEventListener):
* dom/Node.cpp:
(WebCore::Node::removeEventListener):
* inspector/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::InspectorDOMAgent):
(WebCore::InspectorDOMAgent::mainFrameDocument):
(WebCore::InspectorDOMAgent::operator==):
* inspector/InspectorDOMAgent.h:
(WebCore::InspectorDOMAgent::cast):
* loader/ImageDocument.cpp:
(WebCore::ImageEventListener::cast):
(WebCore::ImageEventListener::ImageEventListener):
(WebCore::ImageEventListener::operator==):
* loader/appcache/DOMApplicationCache.cpp:
(WebCore::DOMApplicationCache::addEventListener):
(WebCore::DOMApplicationCache::removeEventListener):
* notifications/Notification.cpp:
(WebCore::Notification::removeEventListener):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::removeEventListener):
* page/EventSource.cpp:
(WebCore::EventSource::addEventListener):
(WebCore::EventSource::removeEventListener):
* svg/animation/SVGSMILElement.cpp:
(WebCore::ConditionEventListener::cast):
(WebCore::ConditionEventListener::ConditionEventListener):
(WebCore::ConditionEventListener::operator==):
(WebCore::ConditionEventListener::handleEvent):
* workers/AbstractWorker.cpp:
(WebCore::AbstractWorker::addEventListener):
(WebCore::AbstractWorker::removeEventListener):
* workers/WorkerContext.cpp:
(WebCore::WorkerContext::addEventListener):
(WebCore::WorkerContext::removeEventListener):
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::addEventListener):
(WebCore::XMLHttpRequest::removeEventListener):
* xml/XMLHttpRequestUpload.cpp:
(WebCore::XMLHttpRequestUpload::addEventListener):
(WebCore::XMLHttpRequestUpload::removeEventListener):



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@48402 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 4cc20012
2009-09-15 Geoffrey Garen <ggaren@apple.com>
Reviewed by Sam Weinig.
Removed the jsEventListeners set from JSDOMGlobalObject, to simplify
creation and destruction of JSDOMGlobalObject and event listeners.
Added an abstract operator==() to EventListener, to replace the
jsEventListeners set's role in determining if two event listeners are
equal from the DOM's perspective.
Added a type field to EventListener, and casting operations, to support
operator==() and other abstract operations.
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSAbstractWorkerCustom.cpp:
(WebCore::JSAbstractWorker::addEventListener):
(WebCore::JSAbstractWorker::removeEventListener):
* bindings/js/JSDOMApplicationCacheCustom.cpp:
(WebCore::JSDOMApplicationCache::addEventListener):
(WebCore::JSDOMApplicationCache::removeEventListener):
* bindings/js/JSDOMGlobalObject.cpp:
* bindings/js/JSDOMGlobalObject.h:
* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::addEventListener):
(WebCore::JSDOMWindow::removeEventListener):
* bindings/js/JSDesktopNotificationsCustom.cpp:
(WebCore::JSNotification::addEventListener):
(WebCore::):
* bindings/js/JSEventListener.cpp:
(WebCore::JSEventListener::JSEventListener):
(WebCore::JSEventListener::~JSEventListener):
(WebCore::JSEventListener::markJSFunction):
(WebCore::JSEventListener::handleEvent):
(WebCore::JSEventListener::reportError):
(WebCore::JSEventListener::operator==):
* bindings/js/JSEventListener.h:
(WebCore::JSEventListener::cast):
* bindings/js/JSEventSourceCustom.cpp:
(WebCore::JSEventSource::addEventListener):
(WebCore::JSEventSource::removeEventListener):
* bindings/js/JSMessagePortCustom.cpp:
(WebCore::JSMessagePort::addEventListener):
(WebCore::JSMessagePort::removeEventListener):
* bindings/js/JSNodeCustom.cpp:
(WebCore::JSNode::addEventListener):
(WebCore::JSNode::removeEventListener):
* bindings/js/JSSVGElementInstanceCustom.cpp:
(WebCore::JSSVGElementInstance::addEventListener):
(WebCore::JSSVGElementInstance::removeEventListener):
* bindings/js/JSWorkerContextCustom.cpp:
(WebCore::JSWorkerContext::addEventListener):
(WebCore::JSWorkerContext::removeEventListener):
* bindings/js/JSXMLHttpRequestCustom.cpp:
(WebCore::JSXMLHttpRequest::addEventListener):
(WebCore::JSXMLHttpRequest::removeEventListener):
* bindings/js/JSXMLHttpRequestUploadCustom.cpp:
(WebCore::JSXMLHttpRequestUpload::addEventListener):
(WebCore::JSXMLHttpRequestUpload::removeEventListener):
* bindings/objc/ObjCEventListener.h:
(WebCore::ObjCEventListener::cast):
* bindings/objc/ObjCEventListener.mm:
(WebCore::ObjCEventListener::ObjCEventListener):
(WebCore::ObjCEventListener::operator==):
* dom/EventListener.h:
(WebCore::EventListener::):
(WebCore::EventListener::type):
(WebCore::EventListener::EventListener):
* dom/MessagePort.cpp:
(WebCore::MessagePort::addEventListener):
(WebCore::MessagePort::removeEventListener):
* dom/Node.cpp:
(WebCore::Node::removeEventListener):
* inspector/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::InspectorDOMAgent):
(WebCore::InspectorDOMAgent::mainFrameDocument):
(WebCore::InspectorDOMAgent::operator==):
* inspector/InspectorDOMAgent.h:
(WebCore::InspectorDOMAgent::cast):
* loader/ImageDocument.cpp:
(WebCore::ImageEventListener::cast):
(WebCore::ImageEventListener::ImageEventListener):
(WebCore::ImageEventListener::operator==):
* loader/appcache/DOMApplicationCache.cpp:
(WebCore::DOMApplicationCache::addEventListener):
(WebCore::DOMApplicationCache::removeEventListener):
* notifications/Notification.cpp:
(WebCore::Notification::removeEventListener):
* page/DOMWindow.cpp:
(WebCore::DOMWindow::removeEventListener):
* page/EventSource.cpp:
(WebCore::EventSource::addEventListener):
(WebCore::EventSource::removeEventListener):
* svg/animation/SVGSMILElement.cpp:
(WebCore::ConditionEventListener::cast):
(WebCore::ConditionEventListener::ConditionEventListener):
(WebCore::ConditionEventListener::operator==):
(WebCore::ConditionEventListener::handleEvent):
* workers/AbstractWorker.cpp:
(WebCore::AbstractWorker::addEventListener):
(WebCore::AbstractWorker::removeEventListener):
* workers/WorkerContext.cpp:
(WebCore::WorkerContext::addEventListener):
(WebCore::WorkerContext::removeEventListener):
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::addEventListener):
(WebCore::XMLHttpRequest::removeEventListener):
* xml/XMLHttpRequestUpload.cpp:
(WebCore::XMLHttpRequestUpload::addEventListener):
(WebCore::XMLHttpRequestUpload::removeEventListener):
2009-09-15 Alex Milowski <alex@milowski.com>
Reviewed by Tor Arne Vestbø.
......@@ -64,10 +64,12 @@ JSValue JSAbstractWorker::addEventListener(ExecState* exec, const ArgList& args)
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1));
if (!listener)
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -76,10 +78,12 @@ JSValue JSAbstractWorker::removeEventListener(ExecState* exec, const ArgList& ar
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
JSEventListener* listener = globalObject->findJSEventListener(args.at(1));
if (!listener)
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -112,10 +112,12 @@ JSValue JSDOMApplicationCache::addEventListener(ExecState* exec, const ArgList&
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1));
if (!listener)
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -124,10 +126,12 @@ JSValue JSDOMApplicationCache::removeEventListener(ExecState* exec, const ArgLis
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
JSEventListener* listener = globalObject->findJSEventListener(args.at(1));
if (!listener)
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -50,14 +50,6 @@ JSDOMGlobalObject::JSDOMGlobalObject(PassRefPtr<Structure> structure, JSDOMGloba
{
}
JSDOMGlobalObject::~JSDOMGlobalObject()
{
JSListenersMap::iterator it = d()->jsEventListeners.begin();
JSListenersMap::iterator end = d()->jsEventListeners.end();
for (; it != end; ++it)
it->second->clearGlobalObject();
}
void JSDOMGlobalObject::markChildren(MarkStack& markStack)
{
Base::markChildren(markStack);
......@@ -71,26 +63,6 @@ void JSDOMGlobalObject::markChildren(MarkStack& markStack)
markStack.append(it2->second);
}
JSEventListener* JSDOMGlobalObject::findJSEventListener(JSValue val)
{
if (!val.isObject())
return 0;
return d()->jsEventListeners.get(asObject(val));
}
PassRefPtr<JSEventListener> JSDOMGlobalObject::findOrCreateJSEventListener(JSValue val)
{
if (JSEventListener* listener = findJSEventListener(val))
return listener;
if (!val.isObject())
return 0;
// The JSEventListener constructor adds it to our jsEventListeners map.
return JSEventListener::create(asObject(val), this, false).get();
}
PassRefPtr<JSEventListener> JSDOMGlobalObject::createJSAttributeEventListener(JSValue val)
{
if (!val.isObject())
......@@ -99,11 +71,6 @@ PassRefPtr<JSEventListener> JSDOMGlobalObject::createJSAttributeEventListener(JS
return JSEventListener::create(asObject(val), this, true).get();
}
JSDOMGlobalObject::JSListenersMap& JSDOMGlobalObject::jsEventListeners()
{
return d()->jsEventListeners;
}
void JSDOMGlobalObject::setCurrentEvent(Event* evt)
{
d()->evt = evt;
......
......@@ -46,7 +46,6 @@ namespace WebCore {
struct JSDOMGlobalObjectData;
JSDOMGlobalObject(PassRefPtr<JSC::Structure>, JSDOMGlobalObjectData*, JSC::JSObject* thisValue);
virtual ~JSDOMGlobalObject();
public:
JSDOMStructureMap& structures() { return d()->structures; }
......@@ -54,20 +53,10 @@ namespace WebCore {
virtual ScriptExecutionContext* scriptExecutionContext() const = 0;
// Finds a wrapper of a GC-unprotected JS EventListener, returns 0 if no existing one.
JSEventListener* findJSEventListener(JSC::JSValue);
// Finds or creates a wrapper of a JS EventListener. JS EventListener object is *NOT* GC-protected.
PassRefPtr<JSEventListener> findOrCreateJSEventListener(JSC::JSValue);
// Creates a GC-protected JS EventListener for an "onXXX" event attribute.
// These listeners cannot be removed through the removeEventListener API.
// Creates a JS EventListener for an "onXXX" event attribute. These
// listeners cannot be removed through the removeEventListener API.
PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::JSValue);
typedef HashMap<JSC::JSObject*, JSEventListener*> JSListenersMap;
JSListenersMap& jsEventListeners();
// Make binding code generation easier.
JSDOMGlobalObject* globalObject() { return this; }
......@@ -83,8 +72,6 @@ namespace WebCore {
JSDOMStructureMap structures;
JSDOMConstructorMap constructors;
JSDOMGlobalObject::JSListenersMap jsEventListeners;
Event* evt;
};
......
......@@ -1022,9 +1022,11 @@ JSValue JSDOMWindow::addEventListener(ExecState* exec, const ArgList& args)
if (!frame)
return jsUndefined();
if (RefPtr<JSEventListener> listener = findOrCreateJSEventListener(args.at(1)))
impl()->addEventListener(AtomicString(args.at(0).toString(exec)), listener.release(), args.at(2).toBoolean(exec));
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -1034,9 +1036,11 @@ JSValue JSDOMWindow::removeEventListener(ExecState* exec, const ArgList& args)
if (!frame)
return jsUndefined();
if (JSEventListener* listener = findJSEventListener(args.at(1)))
impl()->removeEventListener(AtomicString(args.at(0).toString(exec)), listener, args.at(2).toBoolean(exec));
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -67,9 +67,11 @@ JSValue JSNotification::addEventListener(ExecState* exec, const ArgList& args)
if (!globalObject)
return jsUndefined();
if (RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1)))
impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener)), globalObject, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -79,9 +81,11 @@ JSValue JSNotification::removeEventListener(ExecState* exec, const ArgList& args
if (!globalObject)
return jsUndefined();
if (JSEventListener* listener = globalObject->findJSEventListener(args.at(1)))
impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -32,18 +32,16 @@ using namespace JSC;
namespace WebCore {
JSEventListener::JSEventListener(JSObject* function, JSDOMGlobalObject* globalObject, bool isAttribute)
: m_jsFunction(function)
: EventListener(JSEventListenerType)
, m_jsFunction(function)
, m_globalObject(globalObject)
, m_isAttribute(isAttribute)
{
if (!m_isAttribute && m_jsFunction)
globalObject->jsEventListeners().set(m_jsFunction, this);
ASSERT(m_globalObject);
}
JSEventListener::~JSEventListener()
{
if (!m_isAttribute && m_jsFunction && m_globalObject)
m_globalObject->jsEventListeners().remove(m_jsFunction);
}
JSObject* JSEventListener::jsFunction() const
......@@ -55,8 +53,7 @@ void JSEventListener::markJSFunction(MarkStack& markStack)
{
if (m_jsFunction)
markStack.append(m_jsFunction);
if (m_globalObject)
markStack.append(m_globalObject);
markStack.append(m_globalObject);
}
void JSEventListener::handleEvent(Event* event, bool isWindowEvent)
......@@ -68,13 +65,6 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent)
return;
JSDOMGlobalObject* globalObject = m_globalObject;
// Null check as clearGlobalObject() can clear this and we still get called back by
// xmlhttprequest objects. See http://bugs.webkit.org/show_bug.cgi?id=13275
// FIXME: Is this check still necessary? Requests are supposed to be stopped before clearGlobalObject() is called.
ASSERT(globalObject);
if (!globalObject)
return;
ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext();
if (!scriptExecutionContext)
return;
......@@ -113,15 +103,12 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent)
Event* savedEvent = globalObject->currentEvent();
globalObject->setCurrentEvent(event);
// If this event handler is the first JavaScript to execute, then the
// dynamic global object should be set to the global object of the
// window in which the event occurred.
JSGlobalData* globalData = globalObject->globalData();
DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject);
JSValue retval;
if (handleEventFunction) {
globalObject->globalData()->timeoutChecker.start();
globalData->timeoutChecker.start();
retval = call(exec, handleEventFunction, callType, callData, jsFunction, args);
} else {
JSValue thisValue;
......@@ -129,10 +116,10 @@ void JSEventListener::handleEvent(Event* event, bool isWindowEvent)
thisValue = globalObject->toThisObject(exec);
else
thisValue = toJS(exec, globalObject, event->currentTarget());
globalObject->globalData()->timeoutChecker.start();
globalData->timeoutChecker.start();
retval = call(exec, jsFunction, callType, callData, thisValue, args);
}
globalObject->globalData()->timeoutChecker.stop();
globalData->timeoutChecker.stop();
globalObject->setCurrentEvent(savedEvent);
......@@ -163,9 +150,6 @@ bool JSEventListener::reportError(const String& message, const String& url, int
return false;
JSDOMGlobalObject* globalObject = m_globalObject;
if (!globalObject)
return false;
ExecState* exec = globalObject->globalExec();
CallData callData;
......@@ -179,17 +163,14 @@ bool JSEventListener::reportError(const String& message, const String& url, int
args.append(jsString(exec, url));
args.append(jsNumber(exec, lineNumber));
// If this event handler is the first JavaScript to execute, then the
// dynamic global object should be set to the global object of the
// window in which the event occurred.
JSGlobalData* globalData = globalObject->globalData();
DynamicGlobalObjectScope globalObjectScope(exec, globalData->dynamicGlobalObject ? globalData->dynamicGlobalObject : globalObject);
JSValue thisValue = globalObject->toThisObject(exec);
globalObject->globalData()->timeoutChecker.start();
globalData->timeoutChecker.start();
JSValue returnValue = call(exec, jsFunction, callType, callData, thisValue, args);
globalObject->globalData()->timeoutChecker.stop();
globalData->timeoutChecker.stop();
// If an error occurs while handling the script error, it should be bubbled up.
if (exec->hadException()) {
......@@ -206,4 +187,11 @@ bool JSEventListener::virtualisAttribute() const
return m_isAttribute;
}
bool JSEventListener::operator==(const EventListener& listener)
{
if (const JSEventListener* jsEventListener = JSEventListener::cast(&listener))
return m_jsFunction == jsEventListener->m_jsFunction && m_isAttribute == jsEventListener->m_isAttribute;
return false;
}
} // namespace WebCore
......@@ -34,8 +34,17 @@ namespace WebCore {
{
return adoptRef(new JSEventListener(listener, globalObject, isAttribute));
}
static const JSEventListener* cast(const EventListener* listener)
{
return listener->type() == JSEventListenerType
? static_cast<const JSEventListener*>(listener)
: 0;
}
virtual ~JSEventListener();
void clearGlobalObject() { m_globalObject = 0; }
virtual bool operator==(const EventListener& other);
// Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick".
bool isAttribute() const { return m_isAttribute; }
......
......@@ -65,10 +65,12 @@ JSValue JSEventSource::addEventListener(ExecState* exec, const ArgList& args)
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1));
if (!listener)
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -77,10 +79,12 @@ JSValue JSEventSource::removeEventListener(ExecState* exec, const ArgList& args)
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
JSEventListener* listener = globalObject->findJSEventListener(args.at(1));
if (!listener)
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -68,10 +68,12 @@ JSValue JSMessagePort::addEventListener(ExecState* exec, const ArgList& args)
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1));
if (!listener)
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -80,10 +82,12 @@ JSValue JSMessagePort::removeEventListener(ExecState* exec, const ArgList& args)
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(impl()->scriptExecutionContext());
if (!globalObject)
return jsUndefined();
JSEventListener* listener = globalObject->findJSEventListener(args.at(1));
if (!listener)
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -118,9 +118,11 @@ JSValue JSNode::addEventListener(ExecState* exec, const ArgList& args)
if (!globalObject)
return jsUndefined();
if (RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1)))
impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -134,9 +136,11 @@ JSValue JSNode::removeEventListener(ExecState* exec, const ArgList& args)
if (!globalObject)
return jsUndefined();
if (JSEventListener* listener = globalObject->findJSEventListener(args.at(1)))
impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -54,9 +54,11 @@ JSValue JSSVGElementInstance::addEventListener(ExecState* exec, const ArgList& a
if (!globalObject)
return jsUndefined();
if (RefPtr<JSEventListener> listener = globalObject->findOrCreateJSEventListener(args.at(1)))
impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
......@@ -66,9 +68,11 @@ JSValue JSSVGElementInstance::removeEventListener(ExecState* exec, const ArgList
if (!globalObject)
return jsUndefined();
if (JSEventListener* listener = globalObject->findJSEventListener(args.at(1)))
impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), globalObject, false).get(), args.at(2).toBoolean(exec));
return jsUndefined();
}
......
......@@ -126,19 +126,21 @@ JSValue JSWorkerContext::importScripts(ExecState* exec, const ArgList& args)
JSValue JSWorkerContext::addEventListener(ExecState* exec, const ArgList& args)
{
RefPtr<JSEventListener> listener = findOrCreateJSEventListener(args.at(1));
if (!listener)
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->addEventListener(args.at(0).toString(exec), listener.release(), args.at(2).toBoolean(exec));
impl()->addEventListener(args.at(0).toString(exec), JSEventListener::create(asObject(listener), this, false), args.at(2).toBoolean(exec));
return jsUndefined();
}
JSValue JSWorkerContext::removeEventListener(ExecState* exec, const ArgList& args)
{
JSEventListener* listener = findJSEventListener(args.at(1));
if (!listener)
JSValue listener = args.at(1);
if (!listener.isObject())
return jsUndefined();
impl()->removeEventListener(args.at(0).toString(exec), listener, args.at(2).toBoolean(exec));
impl