18f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian/*
28f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
38f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian *
48f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Redistribution and use in source and binary forms, with or without
58f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * modification, are permitted provided that the following conditions are
68f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * met:
78f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian *
88f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian *     * Redistributions of source code must retain the above copyright
98f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * notice, this list of conditions and the following disclaimer.
108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian *     * Redistributions in binary form must reproduce the above
118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * copyright notice, this list of conditions and the following disclaimer
128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * in the documentation and/or other materials provided with the
138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * distribution.
148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian *     * Neither the name of Google Inc. nor the names of its
158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * contributors may be used to endorse or promote products derived from
168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * this software without specific prior written permission.
178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian *
188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian */
308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "config.h"
328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "V8AbstractEventListener.h"
338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
34231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "DateExtension.h"
358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "Document.h"
368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "Event.h"
378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "Frame.h"
388f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "V8Binding.h"
395e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block#include "V8Event.h"
40231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "V8EventListenerList.h"
41ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block#include "V8HiddenPropertyName.h"
42231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "V8Proxy.h"
43231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "V8Utilities.h"
44cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "WorkerContext.h"
45cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block#include "WorkerContextExecutionProxy.h"
468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qiannamespace WebCore {
488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
49231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic void weakEventListenerCallback(v8::Persistent<v8::Value>, void* parameter)
50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
51231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    V8AbstractEventListener* listener = static_cast<V8AbstractEventListener*>(parameter);
52231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    listener->disposeListenerObject();
53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
54231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
55643ca7872b450ea4efacab6188849e5aac2ba161Steve BlockV8AbstractEventListener::V8AbstractEventListener(bool isAttribute, const WorldContextHandle& worldContext)
56231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    : EventListener(JSEventListenerType)
57231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_isWeak(true)
58231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_isAttribute(isAttribute)
59643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    , m_worldContext(worldContext)
608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve BlockV8AbstractEventListener::~V8AbstractEventListener()
648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
65231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_listener.IsEmpty()) {
66231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        v8::HandleScope scope;
67231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        v8::Local<v8::Object> listener = v8::Local<v8::Object>::New(m_listener);
68231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        V8EventListenerList::clearWrapper(listener, m_isAttribute);
698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    disposeListenerObject();
718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
73cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockvoid V8AbstractEventListener::handleEvent(ScriptExecutionContext* context, Event* event)
748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
75dd888d7ab78958132c660a402edcc490bf690620Ben Murdoch#ifdef ANDROID
76dd888d7ab78958132c660a402edcc490bf690620Ben Murdoch    // Monkey data shows that we can crash here, due to script executing while the
77dd888d7ab78958132c660a402edcc490bf690620Ben Murdoch    // page's frame has been detached (in the middle of a navigation).
78dd888d7ab78958132c660a402edcc490bf690620Ben Murdoch    // See b/5201341
79dd888d7ab78958132c660a402edcc490bf690620Ben Murdoch    if (!context)
80dd888d7ab78958132c660a402edcc490bf690620Ben Murdoch        return;
81dd888d7ab78958132c660a402edcc490bf690620Ben Murdoch#endif
82dd888d7ab78958132c660a402edcc490bf690620Ben Murdoch
832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    // Don't reenter V8 if execution was terminated in this instance of V8.
842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (context->isJSExecutionForbidden())
852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        return;
862daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
8721939df44de1705786c545cd1bf519d47250322dBen Murdoch    ASSERT(event);
8821939df44de1705786c545cd1bf519d47250322dBen Murdoch
898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it.
908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // See issue 889829.
918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    RefPtr<V8AbstractEventListener> protect(this);
928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    v8::HandleScope handleScope;
948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
95643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    v8::Local<v8::Context> v8Context = toV8Context(context, worldContext());
960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (v8Context.IsEmpty())
978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Enter the V8 context in which to perform the event handling.
1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    v8::Context::Scope scope(v8Context);
1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Get the V8 wrapper for the event object.
1035e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    v8::Handle<v8::Value> jsEvent = toV8(event);
10421939df44de1705786c545cd1bf519d47250322dBen Murdoch    ASSERT(!jsEvent.IsEmpty());
1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
106cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    invokeEventHandler(context, event, jsEvent);
1078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid V8AbstractEventListener::disposeListenerObject()
1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!m_listener.IsEmpty()) {
1128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#ifndef NDEBUG
1130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        V8GCController::unregisterGlobalHandle(this, m_listener);
1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#endif
1158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_listener.Dispose();
1168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_listener.Clear();
1178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
1188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
120231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid V8AbstractEventListener::setListenerObject(v8::Handle<v8::Object> listener)
121231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
122231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    disposeListenerObject();
123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_listener = v8::Persistent<v8::Object>::New(listener);
124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#ifndef NDEBUG
125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    V8GCController::registerGlobalHandle(EVENT_LISTENER, this, m_listener);
126231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
127231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_isWeak)
128231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_listener.MakeWeak(this, &weakEventListenerCallback);
129231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
130231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
131cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockvoid V8AbstractEventListener::invokeEventHandler(ScriptExecutionContext* context, Event* event, v8::Handle<v8::Value> jsEvent)
132231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
13321939df44de1705786c545cd1bf519d47250322dBen Murdoch    // If jsEvent is empty, attempt to set it as a hidden value would crash v8.
13421939df44de1705786c545cd1bf519d47250322dBen Murdoch    if (jsEvent.IsEmpty())
13521939df44de1705786c545cd1bf519d47250322dBen Murdoch        return;
136cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
137643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    v8::Local<v8::Context> v8Context = toV8Context(context, worldContext());
138cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (v8Context.IsEmpty())
139cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        return;
140cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
141231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // We push the event being processed into the global object, so that it can be exposed by DOMWindow's bindings.
142ca9cb53ed1119a3fd98fafa0972ffeb56dee1c24Steve Block    v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event();
143231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    v8::Local<v8::Value> returnValue;
144231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
145231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // In beforeunload/unload handlers, we want to avoid sleeps which do tight loops of calling Date.getTime().
146231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (event->type() == "beforeunload" || event->type() == "unload")
147231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        DateExtension::get()->setAllowSleep(false);
148231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
149231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    {
150231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // Catch exceptions thrown in the event handler so they do not propagate to javascript code that caused the event to fire.
151231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        v8::TryCatch tryCatch;
152231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        tryCatch.SetVerbose(true);
153231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
154231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // Save the old 'event' property so we can restore it later.
155231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        v8::Local<v8::Value> savedEvent = v8Context->Global()->GetHiddenValue(eventSymbol);
156231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        tryCatch.Reset();
157231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // Make the event available in the global object, so DOMWindow can expose it.
159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        v8Context->Global()->SetHiddenValue(eventSymbol, jsEvent);
160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        tryCatch.Reset();
161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
162cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        returnValue = callListenerFunction(context, jsEvent, event);
16381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (tryCatch.HasCaught())
16481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            event->target()->uncaughtExceptionInEventHandler();
1652daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
1662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!tryCatch.CanContinue()) { // Result of TerminateExecution().
167574543de6f562b52e4e06c8b493c76dea160473fBen Murdoch#if ENABLE(WORKERS)
1682daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            if (context->isWorkerContext())
1692daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch                static_cast<WorkerContext*>(context)->script()->forbidExecution();
170574543de6f562b52e4e06c8b493c76dea160473fBen Murdoch#endif
171231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return;
1722daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
173dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        tryCatch.Reset();
174231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
175231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // Restore the old event. This must be done for all exit paths through this method.
176231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (savedEvent.IsEmpty())
177231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            v8Context->Global()->SetHiddenValue(eventSymbol, v8::Undefined());
178231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        else
179231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            v8Context->Global()->SetHiddenValue(eventSymbol, savedEvent);
180231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        tryCatch.Reset();
181231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
182231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
183231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (event->type() == "beforeunload" || event->type() == "unload")
184231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        DateExtension::get()->setAllowSleep(true);
185231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
186231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(!V8Proxy::handleOutOfMemory() || returnValue.IsEmpty());
187231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
188231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (returnValue.IsEmpty())
189231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
190231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
191231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!returnValue->IsNull() && !returnValue->IsUndefined() && event->storesResultAsString())
192231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        event->storeResult(toWebCoreString(returnValue));
193231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
194231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Prevent default action if the return value is false;
195231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // FIXME: Add example, and reference to bug entry.
196231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_isAttribute && returnValue->IsBoolean() && !returnValue->BooleanValue())
197231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        event->preventDefault();
198231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
199231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
200231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockv8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event)
2018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
2028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!m_listener.IsEmpty() && !m_listener->IsFunction())
2038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return v8::Local<v8::Object>::New(m_listener);
2048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    EventTarget* target = event->currentTarget();
2060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    v8::Handle<v8::Value> value = V8DOMWrapper::convertEventTargetToV8Object(target);
2078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (value.IsEmpty())
2088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return v8::Local<v8::Object>();
2098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return v8::Local<v8::Object>::New(v8::Handle<v8::Object>::Cast(value));
2108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
2118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian} // namespace WebCore
213