Diff
Modified: trunk/LayoutTests/ChangeLog (110314 => 110315)
--- trunk/LayoutTests/ChangeLog 2012-03-09 20:07:11 UTC (rev 110314)
+++ trunk/LayoutTests/ChangeLog 2012-03-09 20:12:35 UTC (rev 110315)
@@ -1,3 +1,19 @@
+2012-03-08 Erik Arvidsson <[email protected]>
+
+ [V8] Fix object scope for inline event attribute handlers
+ https://bugs.webkit.org/show_bug.cgi?id=80329
+
+ Reviewed by Ojan Vafai.
+
+ * fast/dom/inline-event-attributes-lookup-expected.txt: Added.
+ * fast/dom/inline-event-attributes-lookup-removed-expected.txt: Added.
+ * fast/dom/inline-event-attributes-lookup-removed-form-expected.txt: Added.
+ * fast/dom/inline-event-attributes-lookup-removed-form.html: Added.
+ * fast/dom/inline-event-attributes-lookup-removed.html: Added.
+ * fast/dom/inline-event-attributes-lookup.html: Added.
+ * fast/forms/lazy-event-listener-scope-chain-expected.txt:
+ * fast/forms/lazy-event-listener-scope-chain.html:
+
2012-03-09 Ojan Vafai <[email protected]>
Add image/png svn:mime-type to all png images that currently lack
Added: trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-expected.txt (0 => 110315)
--- trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-expected.txt 2012-03-09 20:12:35 UTC (rev 110315)
@@ -0,0 +1,17 @@
+Tests the lookup in inline event handlers
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS result is "test-input-a"
+PASS result is "test-form-b"
+PASS result is "document-c"
+PASS result is "div-a"
+PASS result is "document-b"
+PASS result is "document-c"
+PASS result is div
+PASS result is not "FAIL"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed-expected.txt (0 => 110315)
--- trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed-expected.txt 2012-03-09 20:12:35 UTC (rev 110315)
@@ -0,0 +1,10 @@
+Tests that lookup in inline event handlers keeps references alive
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS result is "PASS"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed-form-expected.txt (0 => 110315)
--- trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed-form-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed-form-expected.txt 2012-03-09 20:12:35 UTC (rev 110315)
@@ -0,0 +1,10 @@
+Tests that lookup in inline event handlers keeps references alive
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS result is "PASS"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed-form.html (0 => 110315)
--- trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed-form.html (rev 0)
+++ trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed-form.html 2012-03-09 20:12:35 UTC (rev 110315)
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<script src=""
+<form id="test-form">
+ <input id="test-input">
+</form>
+<script>
+
+description('Tests that lookup in inline event handlers keeps references alive');
+
+function forceGC()
+{
+ if (window.GCController)
+ return GCController.collect();
+
+ // Force garbage collection
+ for (var ndx = 0; ndx < 99000; ndx++)
+ var str = new String("1234");
+}
+
+var result;
+var pa = '(FAIL input)'
+var ss = '(FAIL form)'
+
+var input = document.getElementById('test-input');
+input.pa = 'PA';
+input.form.ss = 'SS';
+input.setAttribute('onclick', 'result = pa + ss');
+
+var f = input.onclick;
+
+input.parentNode.removeChild(input);
+input = null;
+forceGC();
+
+f();
+shouldBeEqualToString('result', 'PASS');
+
+</script>
+<script src=""
\ No newline at end of file
Added: trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed.html (0 => 110315)
--- trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed.html (rev 0)
+++ trunk/LayoutTests/fast/dom/inline-event-attributes-lookup-removed.html 2012-03-09 20:12:35 UTC (rev 110315)
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<script src=""
+<script>
+
+description('Tests that lookup in inline event handlers keeps references alive');
+
+function forceGC()
+{
+ if (window.GCController)
+ return GCController.collect();
+
+ // Force garbage collection
+ for (var ndx = 0; ndx < 99000; ndx++)
+ var str = new String("1234");
+}
+
+function dispatchClick(element)
+{
+ var clickEvent = document.createEvent('MouseEvent');
+ clickEvent.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0,false, false, false, false, 0, null);
+ element.dispatchEvent(clickEvent);
+}
+
+var result;
+var custom = 'FAIL';
+
+var div1 = document.createElement('div');
+div1.custom = 'PASS';
+div1.setAttribute('onclick', 'result = custom');
+
+var div2 = document.createElement('div');
+div2._onclick_ = div1.onclick;
+
+div1 = null;
+forceGC();
+
+dispatchClick(div2);
+shouldBeEqualToString('result', 'PASS');
+
+</script>
+<script src=""
\ No newline at end of file
Added: trunk/LayoutTests/fast/dom/inline-event-attributes-lookup.html (0 => 110315)
--- trunk/LayoutTests/fast/dom/inline-event-attributes-lookup.html (rev 0)
+++ trunk/LayoutTests/fast/dom/inline-event-attributes-lookup.html 2012-03-09 20:12:35 UTC (rev 110315)
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<script src=""
+<form id="test-form">
+ <input id="test-input">
+</form>
+<script>
+
+description('Tests the lookup in inline event handlers');
+
+function dispatchClick(element)
+{
+ var clickEvent = document.createEvent('MouseEvent');
+ clickEvent.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ element.dispatchEvent(clickEvent);
+}
+
+var result;
+var testForm = document.getElementById('test-form');
+var testInput = document.getElementById('test-input');
+
+document.a = 'document-a';
+testForm.a = 'test-form-a';
+testInput.a = 'test-input-a';
+
+document.b = 'document-b';
+testForm.b = 'test-form-b';
+
+document.c = 'document-c';
+
+testInput.setAttribute('onclick', 'result = a');
+dispatchClick(testInput);
+shouldBeEqualToString('result', 'test-input-a');
+
+testInput.setAttribute('onclick', 'result = b');
+dispatchClick(testInput);
+shouldBeEqualToString('result', 'test-form-b');
+
+testInput.setAttribute('onclick', 'result = c');
+dispatchClick(testInput);
+shouldBeEqualToString('result', 'document-c');
+
+
+var div = document.createElement('div');
+
+div.a = 'div-a';
+div.setAttribute('onclick', 'result = a');
+dispatchClick(div);
+shouldBeEqualToString('result', 'div-a');
+
+div.form = {b: 'fake-b'};
+div.setAttribute('onclick', 'result = b');
+dispatchClick(div);
+shouldBeEqualToString('result', 'document-b');
+
+div.ownerDocument = {c: 'fake-c'};
+div.setAttribute('onclick', 'result = c');
+dispatchClick(div);
+shouldBeEqualToString('result', 'document-c');
+
+div.setAttribute('onclick', 'result = this');
+dispatchClick(div);
+shouldBe('result', 'div');
+
+div.event = 'FAIL';
+div.setAttribute('onclick', 'result = event');
+dispatchClick(div);
+shouldNotBe('result', '"FAIL"');
+
+</script>
+<script src=""
\ No newline at end of file
Modified: trunk/LayoutTests/fast/forms/lazy-event-listener-scope-chain-expected.txt (110314 => 110315)
--- trunk/LayoutTests/fast/forms/lazy-event-listener-scope-chain-expected.txt 2012-03-09 20:07:11 UTC (rev 110314)
+++ trunk/LayoutTests/fast/forms/lazy-event-listener-scope-chain-expected.txt 2012-03-09 20:12:35 UTC (rev 110315)
@@ -1,4 +1,9 @@
-This test tests that a lazy event listener attached to a form element keeps its form in the scope chain when the listener is called by _javascript_.
+This test tests that a lazy event listener attached to a form element keeps its form in the scope chain when the listener is called by _javascript_.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS result is "abc"
+PASS result is "abc"
+PASS result is "abc"
-abc
-
Modified: trunk/LayoutTests/fast/forms/lazy-event-listener-scope-chain.html (110314 => 110315)
--- trunk/LayoutTests/fast/forms/lazy-event-listener-scope-chain.html 2012-03-09 20:07:11 UTC (rev 110314)
+++ trunk/LayoutTests/fast/forms/lazy-event-listener-scope-chain.html 2012-03-09 20:12:35 UTC (rev 110315)
@@ -1,32 +1,35 @@
-<html>
-
+<!DOCTYPE html>
+<script src=""
+<form action="" _onsubmit_="runTest(username.value)">
+<input type="text" value="abc" name="username">
+<input type="submit" name="login" value="Login">
+</form>
<script>
-if (window.layoutTestController)
- layoutTestController.dumpAsText();
-function run_test(x) {
- var r = document.getElementById('result');
- r.innerHTML = x + '<br>';
-}
+description('This test tests that a lazy event listener attached to a form element keeps its form in the scope chain when the listener is called by _javascript_.');
-function setup() {
- var f = document.getElementsByTagName('form')[0];
- f.old_f = f.onsubmit;
- f._onsubmit_ = function() {this.old_f();};
- f.login.click();
+var result;
+
+function runTest(x)
+{
+ result = x;
+ shouldBeEqualToString('result', 'abc');
}
-</script>
-This test tests that a lazy event listener attached to a form element
-keeps its form in the scope chain when the listener is called by
-_javascript_. <br>
+var f = document.querySelector('form');
-<body _onload_="setup()">
-<form action="" _onsubmit_="run_test(username.value)">
-<input type="text" value="abc" name="username"/>
-<input type="submit" name="login" value="Login"/>
-</form>
+f.onsubmit();
-<div id="result"></div>
-</body>
-</html>
+// Should keep the ObjectEnvironment even when called without context.
+(0, f.onsubmit)();
+
+f.oldF = f.onsubmit;
+
+f._onsubmit_ = function() {
+ this.oldF();
+};
+
+f.login.click();
+
+</script>
+<script src=""
Modified: trunk/Source/WebCore/ChangeLog (110314 => 110315)
--- trunk/Source/WebCore/ChangeLog 2012-03-09 20:07:11 UTC (rev 110314)
+++ trunk/Source/WebCore/ChangeLog 2012-03-09 20:12:35 UTC (rev 110315)
@@ -1,3 +1,37 @@
+2012-03-08 Erik Arvidsson <[email protected]>
+
+ [V8] Fix object scope for inline event attribute handlers
+ https://bugs.webkit.org/show_bug.cgi?id=80329
+
+ Reviewed by Ojan Vafai.
+
+ We now create the funciton inside the with-statements with the current scope objects.
+ This is important for a few reasons:
+
+ - We need to use the real objects and not just lookup the JS properties because these might have been overridden.
+ - We need to use the node, form and document at the time of the preparation and not at the time of calling.
+ - We need to ensure that event/evt is bound closer than a property with the same name in the object environment
+ created by the with-statements.
+
+ Tests: fast/dom/inline-event-attributes-lookup-removed-form.html
+ fast/dom/inline-event-attributes-lookup-removed.html
+ fast/dom/inline-event-attributes-lookup.html
+
+ * bindings/v8/ScriptEventListener.cpp:
+ (WebCore::eventParameterName):
+ (WebCore):
+ (WebCore::createAttributeEventListener):
+ * bindings/v8/V8LazyEventListener.cpp:
+ (WebCore::V8LazyEventListener::V8LazyEventListener):
+ (WebCore):
+ (WebCore::toObjectWrapper):
+ (WebCore::V8LazyEventListener::callListenerFunction):
+ (WebCore::V8LazyEventListener::prepareListenerObject):
+ * bindings/v8/V8LazyEventListener.h:
+ (WebCore):
+ (WebCore::V8LazyEventListener::create):
+ (V8LazyEventListener):
+
2012-03-09 Stephen Chenney <[email protected]>
Crash in WebCore::SVGUseElement::instanceForShadowTreeElement
Modified: trunk/Source/WebCore/bindings/v8/ScriptEventListener.cpp (110314 => 110315)
--- trunk/Source/WebCore/bindings/v8/ScriptEventListener.cpp 2012-03-09 20:07:11 UTC (rev 110314)
+++ trunk/Source/WebCore/bindings/v8/ScriptEventListener.cpp 2012-03-09 20:12:35 UTC (rev 110315)
@@ -42,6 +42,13 @@
namespace WebCore {
+static const String& eventParameterName(bool isSVGEvent)
+{
+ DEFINE_STATIC_LOCAL(const String, eventString, ("event"));
+ DEFINE_STATIC_LOCAL(const String, evtString, ("evt"));
+ return isSVGEvent ? evtString : eventString;
+}
+
PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, Attribute* attr)
{
ASSERT(node);
@@ -57,12 +64,11 @@
ScriptController* scriptController = frame->script();
if (!scriptController->canExecuteScripts(AboutToExecuteScript))
return 0;
-
position = scriptController->eventHandlerPosition();
sourceURL = node->document()->url().string();
}
- return V8LazyEventListener::create(attr->localName().string(), node->isSVGElement(), attr->value(), sourceURL, position, WorldContextHandle(UseMainWorld));
+ return V8LazyEventListener::create(attr->localName().string(), eventParameterName(node->isSVGElement()), attr->value(), sourceURL, position, node, WorldContextHandle(UseMainWorld));
}
PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, Attribute* attr)
@@ -80,7 +86,8 @@
TextPosition position = scriptController->eventHandlerPosition();
String sourceURL = frame->document()->url().string();
- return V8LazyEventListener::create(attr->localName().string(), frame->document()->isSVGDocument(), attr->value(), sourceURL, position, WorldContextHandle(UseMainWorld));
+
+ return V8LazyEventListener::create(attr->localName().string(), eventParameterName(frame->document()->isSVGDocument()), attr->value(), sourceURL, position, 0, WorldContextHandle(UseMainWorld));
}
String eventListenerHandlerBody(Document* document, EventListener* listener)
Modified: trunk/Source/WebCore/bindings/v8/V8LazyEventListener.cpp (110314 => 110315)
--- trunk/Source/WebCore/bindings/v8/V8LazyEventListener.cpp 2012-03-09 20:07:11 UTC (rev 110314)
+++ trunk/Source/WebCore/bindings/v8/V8LazyEventListener.cpp 2012-03-09 20:12:35 UTC (rev 110315)
@@ -32,9 +32,17 @@
#include "V8LazyEventListener.h"
#include "ContentSecurityPolicy.h"
+#include "Document.h"
#include "Frame.h"
+#include "HTMLElement.h"
+#include "HTMLFormElement.h"
+#include "Node.h"
#include "V8Binding.h"
+#include "V8DOMWrapper.h"
+#include "V8Document.h"
+#include "V8HTMLFormElement.h"
#include "V8HiddenPropertyName.h"
+#include "V8Node.h"
#include "V8Proxy.h"
#include "WorldContextHandle.h"
@@ -42,23 +50,38 @@
namespace WebCore {
-V8LazyEventListener::V8LazyEventListener(const String& functionName, bool isSVGEvent, const String& code, const String sourceURL, const TextPosition& position, const WorldContextHandle& worldContext)
+V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition& position, PassRefPtr<Node> node, const WorldContextHandle& worldContext)
: V8AbstractEventListener(true, worldContext)
, m_functionName(functionName)
- , m_isSVGEvent(isSVGEvent)
+ , m_eventParameterName(eventParameterName)
, m_code(code)
, m_sourceURL(sourceURL)
+ , m_node(node)
+ , m_formElement(0)
, m_position(position)
{
+ if (m_node && m_node->isHTMLElement())
+ m_formElement = static_cast<HTMLElement*>(m_node.get())->form();
}
+template<typename T>
+v8::Handle<v8::Object> toObjectWrapper(T* domObject)
+{
+ if (!domObject)
+ return v8::Object::New();
+ v8::Handle<v8::Value> value = toV8(domObject);
+ if (value.IsEmpty())
+ return v8::Object::New();
+ return value.As<v8::Object>();
+}
+
v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ScriptExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event)
{
v8::Local<v8::Object> listenerObject = getListenerObject(context);
if (listenerObject.IsEmpty())
return v8::Local<v8::Value>();
- v8::Local<v8::Function> handlerFunction = v8::Local<v8::Function>::Cast(listenerObject);
+ v8::Local<v8::Function> handlerFunction = listenerObject.As<v8::Function>();
v8::Local<v8::Object> receiver = getReceiverObject(event);
if (handlerFunction.IsEmpty() || receiver.IsEmpty())
return v8::Local<v8::Value>();
@@ -104,8 +127,6 @@
v8::Context::Scope scope(v8Context);
- // FIXME: cache the wrapper function.
-
// Nodes other than the document object, when executing inline event
// handlers push document, form, and the target node on the scope chain.
// We do this by using 'with' statement.
@@ -115,66 +136,86 @@
//
// Don't use new lines so that lines in the modified handler
// have the same numbers as in the original code.
- // FIXME: This approach is a giant hack! What if m_code escapes to run
- // arbitrary script?
- String eventParameterName = m_isSVGEvent ? "evt" : "event";
- String code = "(function(";
- code.append(eventParameterName);
- code.append(") {" \
- "with (this.ownerDocument ? this.ownerDocument : {}) {" \
- "with (this.form ? this.form : {}) {" \
- "with (this) {" \
- "return (function(");
- code.append(eventParameterName);
- code.append("){");
+ // FIXME: V8 does not allow us to programmatically create object environments so
+ // we have to do this hack! What if m_code escapes to run arbitrary script?
+ //
+ String code = "(function() {" \
+ "with (arguments[2]) {" \
+ "with (arguments[1]) {" \
+ "with (arguments[0]) {";
+ code.append("return function(");
+ code.append(m_eventParameterName);
+ code.append(") {");
+
+ int codePrexixLength = code.length();
+
code.append(m_code);
// Insert '\n' otherwise //-style comments could break the handler.
- code.append("\n}).call(this, ");
- code.append(eventParameterName);
- code.append(");}}}})");
+ code.append("\n};}}}})");
v8::Handle<v8::String> codeExternalString = v8ExternalString(code);
- v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_sourceURL, m_position);
- if (!script.IsEmpty()) {
- // Call v8::Script::Run() directly to avoid an erroneous call to V8RecursionScope::didLeaveScriptContext().
- // FIXME: Remove this code when we stop doing the 'with' hack above.
- v8::Local<v8::Value> value = script->Run();
- if (!value.IsEmpty()) {
- ASSERT(value->IsFunction());
- v8::Local<v8::Function> wrappedFunction = v8::Local<v8::Function>::Cast(value);
+ TextPosition adjustedPosition(m_position.m_line, OrdinalNumber::fromZeroBasedInt(m_position.m_column.zeroBasedInt() - codePrexixLength));
- // 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 use toString on event functions and eval the
- // source returned (sometimes a RegExp is applied as well) for some
- // other use. That fails miserably if the actual wrapper source is
- // returned.
- v8::Persistent<v8::FunctionTemplate>& toStringTemplate =
- V8BindingPerIsolateData::current()->lazyEventListenerToStringTemplate();
- if (toStringTemplate.IsEmpty())
- toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8LazyEventListenerToString));
- v8::Local<v8::Function> toStringFunction;
- if (!toStringTemplate.IsEmpty())
- toStringFunction = toStringTemplate->GetFunction();
- if (!toStringFunction.IsEmpty()) {
- String toStringResult = "function ";
- toStringResult.append(m_functionName);
- toStringResult.append("(");
- toStringResult.append(eventParameterName);
- toStringResult.append(") {\n ");
- toStringResult.append(m_code);
- toStringResult.append("\n}");
- wrappedFunction->SetHiddenValue(V8HiddenPropertyName::toStringString(), v8ExternalString(toStringResult));
- wrappedFunction->Set(v8::String::New("toString"), toStringFunction);
- }
+ v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_sourceURL, adjustedPosition);
+ if (script.IsEmpty())
+ return;
- wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length()));
+ // Call v8::Script::Run() directly to avoid an erroneous call to V8RecursionScope::didLeaveScriptContext().
+ // FIXME: Remove this code when we stop doing the 'with' hack above.
+ v8::Local<v8::Value> value = script->Run();
+ if (value.IsEmpty())
+ return;
- setListenerObject(wrappedFunction);
- }
+ // Call the outer function to get the inner function.
+ ASSERT(value->IsFunction());
+ v8::Local<v8::Function> intermediateFunction = value.As<v8::Function>();
+
+ v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node.get());
+ v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(m_formElement.get());
+ v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0);
+
+ m_node.clear();
+ m_formElement.clear();
+
+ v8::Handle<v8::Value> parameters[3] = { nodeWrapper, formWrapper, documentWrapper };
+
+ // Use Call directly to avoid an erroneous call to V8RecursionScope::didLeaveScriptContext().
+ // FIXME: Remove this code when we stop doing the 'with' hack above.
+ v8::Local<v8::Value> innerValue = intermediateFunction->Call(v8Context->Global(), 3, parameters);
+
+ ASSERT(innerValue->IsFunction());
+ v8::Local<v8::Function> wrappedFunction = innerValue.As<v8::Function>();
+
+ // 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 use toString on event functions and eval the
+ // source returned (sometimes a RegExp is applied as well) for some
+ // other use. That fails miserably if the actual wrapper source is
+ // returned.
+ v8::Persistent<v8::FunctionTemplate>& toStringTemplate =
+ V8BindingPerIsolateData::current()->lazyEventListenerToStringTemplate();
+ if (toStringTemplate.IsEmpty())
+ toStringTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::FunctionTemplate::New(V8LazyEventListenerToString));
+ v8::Local<v8::Function> toStringFunction;
+ if (!toStringTemplate.IsEmpty())
+ toStringFunction = toStringTemplate->GetFunction();
+ if (!toStringFunction.IsEmpty()) {
+ String toStringResult = "function ";
+ toStringResult.append(m_functionName);
+ toStringResult.append("(");
+ toStringResult.append(m_eventParameterName);
+ toStringResult.append(") {\n ");
+ toStringResult.append(m_code);
+ toStringResult.append("\n}");
+ wrappedFunction->SetHiddenValue(V8HiddenPropertyName::toStringString(), v8ExternalString(toStringResult));
+ wrappedFunction->Set(v8::String::New("toString"), toStringFunction);
}
+
+ wrappedFunction->SetName(v8::String::New(fromWebCoreString(m_functionName), m_functionName.length()));
+
+ setListenerObject(wrappedFunction);
}
} // namespace WebCore
Modified: trunk/Source/WebCore/bindings/v8/V8LazyEventListener.h (110314 => 110315)
--- trunk/Source/WebCore/bindings/v8/V8LazyEventListener.h 2012-03-09 20:07:11 UTC (rev 110314)
+++ trunk/Source/WebCore/bindings/v8/V8LazyEventListener.h 2012-03-09 20:12:35 UTC (rev 110315)
@@ -41,14 +41,16 @@
class Event;
class Frame;
+ class HTMLFormElement;
+ class Node;
// V8LazyEventListener is a wrapper for a _javascript_ code string that is compiled and evaluated when an event is fired.
- // A V8LazyEventListener is always a HTML event handler.
+ // A V8LazyEventListener is either a HTML or SVG event handler.
class V8LazyEventListener : public V8AbstractEventListener {
public:
- static PassRefPtr<V8LazyEventListener> create(const String& functionName, bool isSVGEvent, const String& code, const String& sourceURL, const TextPosition& position, const WorldContextHandle& worldContext)
+ static PassRefPtr<V8LazyEventListener> create(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String& sourceURL, const TextPosition& position, PassRefPtr<Node> node, const WorldContextHandle& worldContext)
{
- return adoptRef(new V8LazyEventListener(functionName, isSVGEvent, code, sourceURL, position, worldContext));
+ return adoptRef(new V8LazyEventListener(functionName, eventParameterName, code, sourceURL, position, node, worldContext));
}
virtual bool isLazy() const { return true; }
@@ -57,7 +59,7 @@
virtual void prepareListenerObject(ScriptExecutionContext*);
private:
- V8LazyEventListener(const String& functionName, bool isSVGEvent, const String& code, const String sourceURL, const TextPosition&, const WorldContextHandle&);
+ V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition&, PassRefPtr<Node>, const WorldContextHandle&);
virtual v8::Local<v8::Value> callListenerFunction(ScriptExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*);
@@ -67,10 +69,12 @@
// SVGUseElement::transferEventListenersToShadowTree
virtual bool wasCreatedFromMarkup() const { return true; }
- String m_functionName;
- bool m_isSVGEvent;
+ AtomicString m_functionName;
+ AtomicString m_eventParameterName;
String m_code;
String m_sourceURL;
+ RefPtr<Node> m_node;
+ RefPtr<HTMLFormElement> m_formElement;
TextPosition m_position;
};