Index: WebCore/bindings/v8/custom/V8NodeCustom.cpp |
=================================================================== |
--- WebCore/bindings/v8/custom/V8NodeCustom.cpp (revision 24197) |
+++ WebCore/bindings/v8/custom/V8NodeCustom.cpp (working copy) |
@@ -34,30 +34,86 @@ |
#include "Document.h" |
#include "EventListener.h" |
+#include "V8AbstractEventListener.h" |
#include "V8Binding.h" |
#include "V8CustomBinding.h" |
#include "V8CustomEventListener.h" |
#include "V8Node.h" |
+#include "V8ObjectEventListener.h" |
#include "V8Proxy.h" |
#include <wtf/RefPtr.h> |
namespace WebCore { |
+static inline String toEventType(v8::Local<v8::String> value) |
+{ |
+ String key = toWebCoreString(value); |
+ ASSERT(key.startsWith("on")); |
+ return key.substring(2); |
+} |
+ |
+static PassRefPtr<EventListener> getEventListener(Node* node, v8::Local<v8::Value> value, bool isAttribute, bool findOnly) |
+{ |
+ V8Proxy* proxy = V8Proxy::retrieve(node->scriptExecutionContext()); |
+ // The document might be created using createDocument, which does |
+ // not have a frame, use the active frame. |
+ if (!proxy) |
+ proxy = V8Proxy::retrieve(V8Proxy::retrieveFrameForEnteredContext()); |
+ |
+ if (proxy) { |
+ V8EventListenerList* list = proxy->objectListeners(); |
+ return findOnly ? list->findWrapper(value, isAttribute) : list->findOrCreateWrapper<V8ObjectEventListener>(proxy->frame(), value, isAttribute); |
+ } |
+ |
+ return 0; |
+} |
+ |
+ACCESSOR_SETTER(NodeEventHandler) |
+{ |
+ Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(info.Holder()); |
+ String eventType = toEventType(name); |
+ |
+ // Remove hidden dependency on the old event handler. |
+ if (EventListener* listener = node->getAttributeEventListener(eventType)) { |
+ if (static_cast<V8AbstractEventListener*>(listener)->isObjectListener()) { |
+ v8::Local<v8::Object> v8Listener = static_cast<V8ObjectEventListener*>(listener)->getListenerObject(); |
+ removeHiddenDependency(info.Holder(), v8Listener, V8Custom::kNodeEventListenerCacheIndex); |
+ } |
+ } |
+ |
+ // Set handler if the value is a function. |
+ if (value->IsFunction()) { |
+ RefPtr<EventListener> listener = getEventListener(node, value, true, false); |
+ if (listener) { |
+ node->setAttributeEventListener(eventType, listener); |
+ createHiddenDependency(info.Holder(), value, V8Custom::kNodeEventListenerCacheIndex); |
+ } |
+ } else { |
+ // Otherwise, clear the handler. |
+ node->clearAttributeEventListener(eventType); |
+ } |
+} |
+ |
+ACCESSOR_GETTER(NodeEventHandler) |
+{ |
+ Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(info.Holder()); |
+ |
+ EventListener* listener = node->getAttributeEventListener(toEventType(name)); |
+ return V8DOMWrapper::convertEventListenerToV8Object(listener); |
+} |
+ |
CALLBACK_FUNC_DECL(NodeAddEventListener) |
{ |
INC_STATS("DOM.Node.addEventListener()"); |
Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder()); |
- V8Proxy* proxy = V8Proxy::retrieve(node->document()->frame()); |
- if (!proxy) |
- return v8::Undefined(); |
- |
- RefPtr<EventListener> listener = proxy->eventListeners()->findOrCreateWrapper<V8EventListener>(proxy->frame(), args[1], false); |
+ RefPtr<EventListener> listener = getEventListener(node, args[1], false, false); |
if (listener) { |
String type = toWebCoreString(args[0]); |
bool useCapture = args[2]->BooleanValue(); |
node->addEventListener(type, listener, useCapture); |
+ createHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex); |
} |
return v8::Undefined(); |
} |
@@ -67,18 +123,15 @@ |
INC_STATS("DOM.Node.removeEventListener()"); |
Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder()); |
- V8Proxy* proxy = V8Proxy::retrieve(node->document()->frame()); |
// It is possbile that the owner document of the node is detached |
- // from the frame, return immediately in this case. |
+ // from the frame. |
// See issue http://b/878909 |
- if (!proxy) |
- return v8::Undefined(); |
- |
- RefPtr<EventListener> listener = proxy->eventListeners()->findWrapper(args[1], false); |
+ RefPtr<EventListener> listener = getEventListener(node, args[1], false, true); |
if (listener) { |
String type = toWebCoreString(args[0]); |
bool useCapture = args[2]->BooleanValue(); |
node->removeEventListener(type, listener.get(), useCapture); |
+ removeHiddenDependency(args.Holder(), args[1], V8Custom::kNodeEventListenerCacheIndex); |
} |
return v8::Undefined(); |