Commit 410a8a82 authored by eric@webkit.org's avatar eric@webkit.org

2009-05-06 Soren Gjesse <sgjesse@chromium.org>

        Reviewed by Eric Seidel.

        Changed the toString behaviour for non document dom node event handlers in the V8 bindings.
        https://bugs.webkit.org/show_bug.cgi?id=25544

        In the V8 bindings non document dom node event handlers are wrapped in a number of with blocks and uses an inner
        function. This causes the default toString on such a handler to return all this wrapper code. As some web sites
        use the source of an event handler to create new functions this wrapper code causes compatibility problems.

        Create a specific toString function for these handlers which will return a function source compatible with the
        source returned by the JSC bindings and other browsers.

        Test: fast/events/event-function-toString.html

        * bindings/v8/ScriptEventListener.cpp:
        (WebCore::createAttributeEventListener):
        * bindings/v8/V8LazyEventListener.cpp:
        (WebCore::V8LazyEventListener::V8LazyEventListener):
        (WebCore::V8LazyEventListener::getListenerFunction):
        (WebCore::V8LazyEventListenerToString):
        (WebCore::V8LazyEventListener::getWrappedListenerFunction):
        * bindings/v8/V8LazyEventListener.h:
        (WebCore::V8LazyEventListener::create):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@43289 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent ca60ccd9
2009-05-06 Soren Gjesse <sgjesse@chromium.org>
Reviewed by Eric Seidel.
Changed the toString behaviour for non document dom node event handlers in the V8 bindings.
https://bugs.webkit.org/show_bug.cgi?id=25544
* fast/events/event-function-toString.html: Added.
* fast/events/resources/event-function-toString.js: Added.
(normalizedFunctionString):
2009-05-06 Dan Bernstein <mitz@apple.com>
Reviewed by Justin Garcia.
Test serialization of event handlers for bug 25544.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
FAIL div.onclick should be function onclick(event) { test(); } (of type string). Was function onclick(event) { test();
} (of type function).
FAIL path.onclick should be function onclick(evt) { doIt(); } (of type string). Was function onclick(evt) { doIt();
} (of type function).
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<link rel="stylesheet" href="../js/resources/js-test-style.css">
<script src="../js/resources/js-test-pre.js"></script>
</head>
<body>
<p id="description"></p>
<div id="console"></div>
<script src="resources/event-function-toString.js"></script>
<script src="../js/resources/js-test-post.js"></script>
</body>
</html>
description("Test serialization of event handlers for bug 25544.");
function normalizedFunctionString(string)
{
// Remove the white space before/after { } which differs between browsers
string = string.replace(/\{\s+/g, "{");
string = string.replace(/\s+\}/g, "}");
return string;
}
var div = document.createElement("div");
div.setAttribute("onclick", "test();");
shouldBeEqualToString("normalizedFunctionString(div.onclick.toString())", "function onclick(event) {test();}");
var path = document.createElementNS("http://www.w3.org/2000/svg", "path");
path.setAttribute("onclick", "test();");
shouldBeEqualToString("normalizedFunctionString(path.onclick.toString())", "function onclick(evt) {test();}");
var successfullyParsed = true;
2009-05-06 Soren Gjesse <sgjesse@chromium.org>
Reviewed by Eric Seidel.
Changed the toString behaviour for non document dom node event handlers in the V8 bindings.
https://bugs.webkit.org/show_bug.cgi?id=25544
In the V8 bindings non document dom node event handlers are wrapped in a number of with blocks and uses an inner
function. This causes the default toString on such a handler to return all this wrapper code. As some web sites
use the source of an event handler to create new functions this wrapper code causes compatibility problems.
Create a specific toString function for these handlers which will return a function source compatible with the
source returned by the JSC bindings and other browsers.
Test: fast/events/event-function-toString.html
* bindings/v8/ScriptEventListener.cpp:
(WebCore::createAttributeEventListener):
* bindings/v8/V8LazyEventListener.cpp:
(WebCore::V8LazyEventListener::V8LazyEventListener):
(WebCore::V8LazyEventListener::getListenerFunction):
(WebCore::V8LazyEventListenerToString):
(WebCore::V8LazyEventListener::getWrappedListenerFunction):
* bindings/v8/V8LazyEventListener.h:
(WebCore::V8LazyEventListener::create):
2009-05-06 Tor Arne Vestbø <tor.arne.vestbo@nokia.com>
Reviewed by Simon Hausmann.
......@@ -46,7 +46,7 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, Attribu
if (!frame)
return 0;
return V8LazyEventListener::create(frame, attr->value(), attr->localName().string());
return V8LazyEventListener::create(frame, attr->value(), attr->localName().string(), node->isSVGElement());
}
PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attribute* attr)
......@@ -54,7 +54,7 @@ PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attri
if (!frame)
return 0;
return V8LazyEventListener::create(frame, attr->value(), attr->localName().string());
return V8LazyEventListener::create(frame, attr->value(), attr->localName().string(), frame->document()->isSVGDocument());
}
} // namespace WebCore
......@@ -37,10 +37,11 @@
namespace WebCore {
V8LazyEventListener::V8LazyEventListener(Frame *frame, const String& code, const String& functionName)
V8LazyEventListener::V8LazyEventListener(Frame *frame, const String& code, const String& functionName, bool isSVGEvent)
: V8AbstractEventListener(frame, true)
, m_code(code)
, m_functionName(functionName)
, m_isSVGEvent(isSVGEvent)
, m_compiled(false)
, m_wrappedFunctionCompiled(false)
{
......@@ -93,7 +94,7 @@ v8::Local<v8::Function> V8LazyEventListener::getListenerFunction()
// See issue 944690.
//
// The ECMAScript spec says (very obliquely) that the parameter to an event handler is named "evt".
String code = "(function (evt) {\n";
String code = "(function (evt) {\n ";
code.append(m_code);
code.append("\n})");
......@@ -133,6 +134,13 @@ v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(v8::Handle<v8::Va
return proxy->CallFunction(handlerFunction, receiver, 1, parameters);
}
static v8::Handle<v8::Value> V8LazyEventListenerToString(const v8::Arguments& args)
{
return args.Callee()->GetHiddenValue(v8::String::New("toStringString"));
}
v8::Local<v8::Function> V8LazyEventListener::getWrappedListenerFunction()
{
if (m_wrappedFunctionCompiled) {
......@@ -183,6 +191,26 @@ v8::Local<v8::Function> V8LazyEventListener::getWrappedListenerFunction()
ASSERT(value->IsFunction());
m_wrappedFunction = v8::Persistent<v8::Function>::New(v8::Local<v8::Function>::Cast(value));
// Change the toString function on the wrapper function to avoid it returning the source for the actual wrapper function. Instead
// it returns source for a clean wrapper function with the event argument wrapping the event source code. The reason for this
// is that some web sites uses toString on event functions and the evals the source returned (some times a RegExp is applied as
// well) for some other use. That fails miserably if the actual wrapper source is returned.
v8::Local<v8::FunctionTemplate> toStringTemplate = v8::FunctionTemplate::New(V8LazyEventListenerToString);
v8::Local<v8::Function> toStringFunction = toStringTemplate->GetFunction();
String toStringResult = "function ";
toStringResult.append(m_functionName);
toStringResult.append("(");
if (m_isSVGEvent)
toStringResult.append("evt");
else
toStringResult.append("event");
toStringResult.append(") {\n ");
toStringResult.append(m_code);
toStringResult.append( "\n}");
toStringFunction->SetHiddenValue(v8::String::New("toStringString"), v8ExternalString(toStringResult));
m_wrappedFunction->Set(v8::String::New("toString"), toStringFunction);
#ifndef NDEBUG
V8Proxy::RegisterGlobalHandle(EVENT_LISTENER, this, m_wrappedFunction);
#endif
......
......@@ -45,9 +45,9 @@ namespace WebCore {
// A V8LazyEventListener is always a HTML event handler.
class V8LazyEventListener : public V8AbstractEventListener {
public:
static PassRefPtr<V8LazyEventListener> create(Frame* frame, const String& code, const String& functionName)
static PassRefPtr<V8LazyEventListener> create(Frame* frame, const String& code, const String& functionName, bool isSVGEvent)
{
return adoptRef(new V8LazyEventListener(frame, code, functionName));
return adoptRef(new V8LazyEventListener(frame, code, functionName, isSVGEvent));
}
// For lazy event listener, the listener object is the same as its listener
......@@ -55,13 +55,14 @@ namespace WebCore {
virtual v8::Local<v8::Object> getListenerObject() { return getWrappedListenerFunction(); }
private:
V8LazyEventListener(Frame*, const String& code, const String& functionName);
V8LazyEventListener(Frame*, const String& code, const String& functionName, bool isSVGEvent);
virtual ~V8LazyEventListener();
virtual bool virtualisAttribute() const { return true; }
String m_code;
String m_functionName;
bool m_isSVGEvent;
bool m_compiled;
// If the event listener is on a non-document dom node, we compile the function with some implicit scope chains before it.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment