summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/bindings/js/JSEventListener.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/bindings/js/JSEventListener.cpp
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/bindings/js/JSEventListener.cpp')
-rw-r--r--Source/WebCore/bindings/js/JSEventListener.cpp158
1 files changed, 158 insertions, 0 deletions
diff --git a/Source/WebCore/bindings/js/JSEventListener.cpp b/Source/WebCore/bindings/js/JSEventListener.cpp
new file mode 100644
index 0000000..5604374
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSEventListener.cpp
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All Rights Reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "JSEventListener.h"
+
+#include "Event.h"
+#include "Frame.h"
+#include "JSEvent.h"
+#include "JSEventTarget.h"
+#include "JSMainThreadExecState.h"
+#include <runtime/JSLock.h>
+#include <wtf/RefCountedLeakCounter.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSEventListener::JSEventListener(JSObject* function, JSObject* wrapper, bool isAttribute, DOMWrapperWorld* isolatedWorld)
+ : EventListener(JSEventListenerType)
+ , m_jsFunction(function)
+ , m_isAttribute(isAttribute)
+ , m_isolatedWorld(isolatedWorld)
+{
+ if (wrapper)
+ m_wrapper = wrapper;
+}
+
+JSEventListener::~JSEventListener()
+{
+}
+
+JSObject* JSEventListener::initializeJSFunction(ScriptExecutionContext*) const
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+void JSEventListener::markJSFunction(MarkStack& markStack)
+{
+ if (m_jsFunction)
+ markStack.append(m_jsFunction);
+}
+
+void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
+{
+ ASSERT(scriptExecutionContext);
+ if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionTerminated())
+ return;
+
+ JSLock lock(SilenceAssertionsOnly);
+
+ JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
+ if (!jsFunction)
+ return;
+
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld.get());
+ if (!globalObject)
+ return;
+
+ if (scriptExecutionContext->isDocument()) {
+ JSDOMWindow* window = static_cast<JSDOMWindow*>(globalObject);
+ Frame* frame = window->impl()->frame();
+ if (!frame)
+ return;
+ // The window must still be active in its frame. See <https://bugs.webkit.org/show_bug.cgi?id=21921>.
+ // FIXME: A better fix for this may be to change DOMWindow::frame() to not return a frame the detached window used to be in.
+ if (frame->domWindow() != window->impl())
+ return;
+ // FIXME: Is this check needed for other contexts?
+ ScriptController* script = frame->script();
+ if (!script->canExecuteScripts(AboutToExecuteScript) || script->isPaused())
+ return;
+ }
+
+ ExecState* exec = globalObject->globalExec();
+ JSValue handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent"));
+
+ CallData callData;
+ CallType callType = getCallData(handleEventFunction, callData);
+ if (callType == CallTypeNone) {
+ handleEventFunction = JSValue();
+ callType = jsFunction->getCallData(callData);
+ }
+
+ if (callType != CallTypeNone) {
+ ref();
+
+ MarkedArgumentBuffer args;
+ args.append(toJS(exec, globalObject, event));
+
+ Event* savedEvent = globalObject->currentEvent();
+ globalObject->setCurrentEvent(event);
+
+ JSGlobalData& globalData = globalObject->globalData();
+ DynamicGlobalObjectScope globalObjectScope(exec, globalData.dynamicGlobalObject ? globalData.dynamicGlobalObject : globalObject);
+
+ globalData.timeoutChecker.start();
+ JSValue retval;
+ if (handleEventFunction) {
+ retval = scriptExecutionContext->isDocument()
+ ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, jsFunction, args)
+ : JSC::call(exec, handleEventFunction, callType, callData, jsFunction, args);
+ } else {
+ JSValue currentTarget = toJS(exec, globalObject, event->currentTarget());
+ retval = scriptExecutionContext->isDocument()
+ ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, currentTarget, args)
+ : JSC::call(exec, jsFunction, callType, callData, currentTarget, args);
+ }
+ globalData.timeoutChecker.stop();
+
+ globalObject->setCurrentEvent(savedEvent);
+
+ if (exec->hadException())
+ reportCurrentException(exec);
+ else {
+ if (!retval.isUndefinedOrNull() && event->storesResultAsString())
+ event->storeResult(ustringToString(retval.toString(exec)));
+ if (m_isAttribute) {
+ bool retvalbool;
+ if (retval.getBoolean(retvalbool) && !retvalbool)
+ event->preventDefault();
+ }
+ }
+
+ deref();
+ }
+}
+
+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