diff options
Diffstat (limited to 'WebCore/bindings/v8/custom/V8NodeCustom.cpp')
-rw-r--r-- | WebCore/bindings/v8/custom/V8NodeCustom.cpp | 115 |
1 files changed, 84 insertions, 31 deletions
diff --git a/WebCore/bindings/v8/custom/V8NodeCustom.cpp b/WebCore/bindings/v8/custom/V8NodeCustom.cpp index e81e8b5..6b0d740 100644 --- a/WebCore/bindings/v8/custom/V8NodeCustom.cpp +++ b/WebCore/bindings/v8/custom/V8NodeCustom.cpp @@ -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 { -CALLBACK_FUNC_DECL(NodeAddEventListener) +static inline String toEventType(v8::Local<v8::String> value) { - INC_STATS("DOM.Node.addEventListener()"); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args.Holder()); + String key = toWebCoreString(value); + ASSERT(key.startsWith("on")); + return key.substring(2); +} - V8Proxy* proxy = V8Proxy::retrieve(node->document()->frame()); +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) - return v8::Undefined(); + 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); +} - RefPtr<EventListener> listener = proxy->FindOrCreateV8EventListener(args[1], false); +CALLBACK_FUNC_DECL(NodeAddEventListener) +{ + INC_STATS("DOM.Node.addEventListener()"); + Node* node = V8DOMWrapper::convertDOMWrapperToNode<Node>(args.Holder()); + + 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(); } @@ -65,20 +121,17 @@ CALLBACK_FUNC_DECL(NodeAddEventListener) CALLBACK_FUNC_DECL(NodeRemoveEventListener) { INC_STATS("DOM.Node.removeEventListener()"); - Node* node = V8Proxy::DOMWrapperToNode<Node>(args.Holder()); + 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->FindV8EventListener(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(); @@ -88,14 +141,14 @@ CALLBACK_FUNC_DECL(NodeRemoveEventListener) CALLBACK_FUNC_DECL(NodeInsertBefore) { INC_STATS("DOM.Node.insertBefore"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; - Node* refChild = V8Node::HasInstance(args[1]) ? V8Proxy::DOMWrapperToNode<Node>(args[1]) : 0; + Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; + Node* refChild = V8Node::HasInstance(args[1]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])) : 0; bool success = imp->insertBefore(newChild, refChild, ec, true); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) @@ -107,14 +160,14 @@ CALLBACK_FUNC_DECL(NodeInsertBefore) CALLBACK_FUNC_DECL(NodeReplaceChild) { INC_STATS("DOM.Node.replaceChild"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; - Node* oldChild = V8Node::HasInstance(args[1]) ? V8Proxy::DOMWrapperToNode<Node>(args[1]) : 0; + Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; + Node* oldChild = V8Node::HasInstance(args[1]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[1])) : 0; bool success = imp->replaceChild(newChild, oldChild, ec, true); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) @@ -125,13 +178,13 @@ CALLBACK_FUNC_DECL(NodeReplaceChild) CALLBACK_FUNC_DECL(NodeRemoveChild) { INC_STATS("DOM.Node.removeChild"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* oldChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; + Node* oldChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->removeChild(oldChild, ec); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) @@ -143,13 +196,13 @@ CALLBACK_FUNC_DECL(NodeRemoveChild) CALLBACK_FUNC_DECL(NodeAppendChild) { INC_STATS("DOM.Node.appendChild"); - v8::Handle<v8::Value> holder = args.Holder(); - Node* imp = V8Proxy::DOMWrapperToNode<Node>(holder); + v8::Handle<v8::Object> holder = args.Holder(); + Node* imp = V8DOMWrapper::convertDOMWrapperToNode<Node>(holder); ExceptionCode ec = 0; - Node* newChild = V8Node::HasInstance(args[0]) ? V8Proxy::DOMWrapperToNode<Node>(args[0]) : 0; + Node* newChild = V8Node::HasInstance(args[0]) ? V8DOMWrapper::convertDOMWrapperToNode<Node>(v8::Handle<v8::Object>::Cast(args[0])) : 0; bool success = imp->appendChild(newChild, ec, true ); if (ec) { - V8Proxy::SetDOMException(ec); + V8Proxy::setDOMException(ec); return v8::Handle<v8::Value>(); } if (success) |