2 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All Rights Reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "JSLazyEventListener.h"
25 #include <runtime/FunctionConstructor.h>
31 JSLazyEventListener::JSLazyEventListener(LazyEventListenerType type, const String& functionName, const String& code, JSDOMGlobalObject* globalObject, Node* node, int lineNumber)
32 : JSProtectedEventListener(0, globalObject, true)
33 , m_functionName(functionName)
36 , m_lineNumber(lineNumber)
37 , m_originalNode(node)
40 // We don't retain the original node because we assume it
41 // will stay alive as long as this handler object is around
42 // and we need to avoid a reference cycle. If JS transfers
43 // this handler to another node, parseCode will be called and
44 // then originalNode is no longer needed.
46 // A JSLazyEventListener can be created with a line number of zero when it is created with
47 // a setAttribute call from JavaScript, so make the line number 1 in that case.
48 if (m_lineNumber == 0)
52 JSObject* JSLazyEventListener::function() const
58 static inline JSValuePtr eventParameterName(JSLazyEventListener::LazyEventListenerType type, ExecState* exec)
61 case JSLazyEventListener::HTMLLazyEventListener:
62 return jsNontrivialString(exec, "event");
64 case JSLazyEventListener::SVGLazyEventListener:
65 return jsNontrivialString(exec, "evt");
72 void JSLazyEventListener::parseCode() const
77 if (m_globalObject->scriptExecutionContext()->isDocument()) {
78 JSDOMWindow* window = static_cast<JSDOMWindow*>(m_globalObject.get());
79 Frame* frame = window->impl()->frame();
82 // FIXME: Is this check needed for non-Document contexts?
83 ScriptController* script = frame->script();
84 if (!script->isEnabled() || script->isPaused())
90 ExecState* exec = m_globalObject->globalExec();
93 UString sourceURL(m_globalObject->scriptExecutionContext()->url().string());
94 args.append(eventParameterName(m_type, exec));
95 args.append(jsString(exec, m_code));
97 // FIXME: Passing the document's URL to construct is not always correct, since this event listener might
98 // have been added with setAttribute from a script, and we should pass String() in that case.
99 m_listener = constructFunction(exec, args, Identifier(exec, m_functionName), sourceURL, m_lineNumber); // FIXME: is globalExec ok?
101 JSFunction* listenerAsFunction = static_cast<JSFunction*>(m_listener.get());
103 if (exec->hadException()) {
104 exec->clearException();
106 // failed to parse, so let's just make this listener a no-op
108 } else if (m_originalNode) {
109 // Add the event's home element to the scope
110 // (and the document, and the form - see JSHTMLElement::eventHandlerScope)
111 ScopeChain scope = listenerAsFunction->scope();
113 JSValuePtr thisObj = toJS(exec, m_originalNode);
114 if (thisObj.isObject()) {
115 static_cast<JSNode*>(asObject(thisObj))->pushEventHandlerScope(exec, scope);
116 listenerAsFunction->setScope(scope);
120 // no more need to keep the unparsed code around
121 m_functionName = String();
126 JSDOMWindow::ProtectedListenersMap& listeners = m_globalObject->jsProtectedInlineEventListeners();
127 listeners.set(m_listener, const_cast<JSLazyEventListener*>(this));
131 } // namespace WebCore