Commit 93b96c98 authored by abarth@webkit.org's avatar abarth@webkit.org

2009-07-18 Adam Barth <abarth@webkit.org>

        Reviewed by Darin Fisher.

        [V8] Move event listener methods from V8Proxy to V8EventListenerList
        https://bugs.webkit.org/show_bug.cgi?id=27408

        Move some event listener code out of V8Proxy and into the event
        listener list.

        I'd like to remove these methods from V8Proxy entirely and just expose
        getters for the lists themselves, but I'll do that in a follow up
        patch.

        * bindings/v8/V8EventListenerList.cpp:
        (WebCore::V8EventListenerList::findWrapper):
        * bindings/v8/V8EventListenerList.h:
        (WebCore::V8EventListenerList::findOrCreateWrapper):
        * bindings/v8/V8ObjectEventListener.cpp:
        * bindings/v8/V8Proxy.cpp:
        (WebCore::V8Proxy::findV8EventListener):
        (WebCore::V8Proxy::findOrCreateV8EventListener):
        (WebCore::V8Proxy::removeV8EventListener):
        (WebCore::V8Proxy::findObjectEventListener):
        (WebCore::V8Proxy::findOrCreateObjectEventListener):
        (WebCore::V8Proxy::removeObjectEventListener):
        * bindings/v8/V8Proxy.h:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@46091 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 32ca8bb0
2009-07-18 Adam Barth <abarth@webkit.org>
Reviewed by Darin Fisher.
[V8] Move event listener methods from V8Proxy to V8EventListenerList
https://bugs.webkit.org/show_bug.cgi?id=27408
Move some event listener code out of V8Proxy and into the event
listener list.
I'd like to remove these methods from V8Proxy entirely and just expose
getters for the lists themselves, but I'll do that in a follow up
patch.
* bindings/v8/V8EventListenerList.cpp:
(WebCore::V8EventListenerList::findWrapper):
* bindings/v8/V8EventListenerList.h:
(WebCore::V8EventListenerList::findOrCreateWrapper):
* bindings/v8/V8ObjectEventListener.cpp:
* bindings/v8/V8Proxy.cpp:
(WebCore::V8Proxy::findV8EventListener):
(WebCore::V8Proxy::findOrCreateV8EventListener):
(WebCore::V8Proxy::removeV8EventListener):
(WebCore::V8Proxy::findObjectEventListener):
(WebCore::V8Proxy::findOrCreateObjectEventListener):
(WebCore::V8Proxy::removeObjectEventListener):
* bindings/v8/V8Proxy.h:
2009-07-18 Jeremy Orlow <jorlow@chromium.org>
Rubber stamped by Adam Barth.
......
......@@ -182,4 +182,14 @@ V8EventListener* V8EventListenerList::find(v8::Local<v8::Object> object, bool is
return 0;
}
PassRefPtr<V8EventListener> V8EventListenerList::findWrapper(v8::Local<v8::Value> object, bool isAttribute)
{
ASSERT(v8::Context::InContext());
if (!object->IsObject())
return 0;
// FIXME: Should this be v8::Local<v8::Object>::Cast instead?
return find(object->ToObject(), isAttribute);
}
} // namespace WebCore
......@@ -35,7 +35,10 @@
#include <wtf/Vector.h>
#include <wtf/HashMap.h>
#include "PassRefPtr.h"
namespace WebCore {
class Frame;
class V8EventListener;
class V8EventListenerListIterator;
......@@ -67,6 +70,10 @@ namespace WebCore {
void clear();
size_t size() { return m_table.size(); }
PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value>, bool isAttribute);
template<typename WrapperType>
PassRefPtr<V8EventListener> findOrCreateWrapper(Frame*, v8::Local<v8::Value>, bool isAttribute);
private:
ListenerMultiMap m_table;
......@@ -93,6 +100,25 @@ namespace WebCore {
size_t m_vectorIndex;
};
template<typename WrapperType>
PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(Frame* frame, v8::Local<v8::Value> object, bool isAttribute)
{
ASSERT(v8::Context::InContext());
if (!object->IsObject())
return 0;
// FIXME: Should this be v8::Local<v8::Object>::Cast instead?
V8EventListener* wrapper = find(object->ToObject(), isAttribute);
if (wrapper)
return wrapper;
// Create a new one, and add to cache.
RefPtr<WrapperType> newListener = WrapperType::create(frame, v8::Local<v8::Object>::Cast(object), isAttribute);
add(newListener.get());
return newListener;
};
} // namespace WebCore
#endif // V8EventListenerList_h
......@@ -54,6 +54,25 @@ static void weakObjectEventListenerCallback(v8::Persistent<v8::Value>, void* par
listener->disposeListenerObject();
}
// Object event listeners (such as XmlHttpRequest and MessagePort) are
// different from listeners on DOM nodes. An object event listener wrapper
// only holds a weak reference to the JS function. A strong reference can
// create a cycle.
//
// The lifetime of these objects is bounded by the life time of its JS
// wrapper. So we can create a hidden reference from the JS wrapper to
// to its JS function.
//
// (map)
// XHR <---------- JS_wrapper
// | (hidden) : ^
// V V : (may reachable by closure)
// V8_listener --------> JS_function
// (weak) <-- may create a cycle if it is strong
//
// The persistent reference is made weak in the constructor
// of V8ObjectEventListener.
V8ObjectEventListener::V8ObjectEventListener(Frame* frame, v8::Local<v8::Object> listener, bool isInline)
: V8EventListener(frame, listener, isInline)
{
......
......@@ -361,100 +361,34 @@ void V8Proxy::destroyGlobal()
}
}
// Event listeners
static V8EventListener* findEventListenerInList(V8EventListenerList& list, v8::Local<v8::Value> listener, bool isInline)
{
ASSERT(v8::Context::InContext());
if (!listener->IsObject())
return 0;
return list.find(listener->ToObject(), isInline);
}
// Find an existing wrapper for a JS event listener in the map.
PassRefPtr<V8EventListener> V8Proxy::findV8EventListener(v8::Local<v8::Value> listener, bool isInline)
PassRefPtr<V8EventListener> V8Proxy::findV8EventListener(v8::Local<v8::Value> object, bool isAttribute)
{
return findEventListenerInList(m_eventListeners, listener, isInline);
}
PassRefPtr<V8EventListener> V8Proxy::findOrCreateV8EventListener(v8::Local<v8::Value> object, bool isInline)
{
ASSERT(v8::Context::InContext());
if (!object->IsObject())
return 0;
V8EventListener* wrapper = findEventListenerInList(m_eventListeners, object, isInline);
if (wrapper)
return wrapper;
// Create a new one, and add to cache.
RefPtr<V8EventListener> newListener = V8EventListener::create(m_frame, v8::Local<v8::Object>::Cast(object), isInline);
m_eventListeners.add(newListener.get());
return newListener;
return m_eventListeners.findWrapper(object, isAttribute);
}
// Object event listeners (such as XmlHttpRequest and MessagePort) are
// different from listeners on DOM nodes. An object event listener wrapper
// only holds a weak reference to the JS function. A strong reference can
// create a cycle.
//
// The lifetime of these objects is bounded by the life time of its JS
// wrapper. So we can create a hidden reference from the JS wrapper to
// to its JS function.
//
// (map)
// XHR <---------- JS_wrapper
// | (hidden) : ^
// V V : (may reachable by closure)
// V8_listener --------> JS_function
// (weak) <-- may create a cycle if it is strong
//
// The persistent reference is made weak in the constructor
// of V8ObjectEventListener.
PassRefPtr<V8EventListener> V8Proxy::findObjectEventListener( v8::Local<v8::Value> listener, bool isInline)
PassRefPtr<V8EventListener> V8Proxy::findOrCreateV8EventListener(v8::Local<v8::Value> object, bool isAttribute)
{
return findEventListenerInList(m_xhrListeners, listener, isInline);
return m_eventListeners.findOrCreateWrapper<V8EventListener>(m_frame, object, isAttribute);
}
PassRefPtr<V8EventListener> V8Proxy::findOrCreateObjectEventListener(v8::Local<v8::Value> object, bool isInline)
void V8Proxy::removeV8EventListener(V8EventListener* listener)
{
ASSERT(v8::Context::InContext());
if (!object->IsObject())
return 0;
V8EventListener* wrapper = findEventListenerInList(m_xhrListeners, object, isInline);
if (wrapper)
return wrapper;
// Create a new one, and add to cache.
RefPtr<V8EventListener> newListener = V8ObjectEventListener::create(m_frame, v8::Local<v8::Object>::Cast(object), isInline);
m_xhrListeners.add(newListener.get());
return newListener.release();
m_eventListeners.remove(listener);
}
static void removeEventListenerFromList(V8EventListenerList& list, V8EventListener* listener)
PassRefPtr<V8EventListener> V8Proxy::findObjectEventListener( v8::Local<v8::Value> object, bool isAttribute)
{
list.remove(listener);
return m_xhrListeners.findWrapper(object, isAttribute);
}
void V8Proxy::removeV8EventListener(V8EventListener* listener)
PassRefPtr<V8EventListener> V8Proxy::findOrCreateObjectEventListener(v8::Local<v8::Value> object, bool isAttribute)
{
removeEventListenerFromList(m_eventListeners, listener);
return m_xhrListeners.findOrCreateWrapper<V8ObjectEventListener>(m_frame, object, isAttribute);
}
void V8Proxy::removeObjectEventListener(V8ObjectEventListener* listener)
{
removeEventListenerFromList(m_xhrListeners, listener);
m_xhrListeners.remove(listener);
}
static void disconnectEventListenersInList(V8EventListenerList& list)
......@@ -467,14 +401,12 @@ static void disconnectEventListenersInList(V8EventListenerList& list)
list.clear();
}
void V8Proxy::disconnectEventListeners()
{
disconnectEventListenersInList(m_eventListeners);
disconnectEventListenersInList(m_xhrListeners);
}
v8::Handle<v8::Script> V8Proxy::compileScript(v8::Handle<v8::String> code, const String& fileName, int baseLine)
{
const uint16_t* fileNameString = fromWebCoreString(fileName);
......
......@@ -196,14 +196,14 @@ namespace WebCore {
bool isEnabled();
// Find/Create/Remove event listener wrappers.
// FIXME: Replace these APIs with a getter for m_eventListeners
PassRefPtr<V8EventListener> findV8EventListener(v8::Local<v8::Value> listener, bool isHtml);
PassRefPtr<V8EventListener> findOrCreateV8EventListener(v8::Local<v8::Value> listener, bool isHtml);
void removeV8EventListener(V8EventListener*);
// FIXME: Replace these APIs with a getter for m_xhrListeners
PassRefPtr<V8EventListener> findObjectEventListener(v8::Local<v8::Value> listener, bool isHtml);
PassRefPtr<V8EventListener> findOrCreateObjectEventListener(v8::Local<v8::Value> listener, bool isHtml);
void removeV8EventListener(V8EventListener*);
void removeObjectEventListener(V8ObjectEventListener*);
#if ENABLE(SVG)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment