REGRESSION r110315: Event handler throws TypeError for an input element with name...
authorharaken@chromium.org <haraken@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 May 2012 07:50:51 +0000 (07:50 +0000)
committerharaken@chromium.org <haraken@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 22 May 2012 07:50:51 +0000 (07:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=86991

Reviewed by Ojan Vafai.

Source/WebCore:

Original Chromium bug: http://code.google.com/p/chromium/issues/detail?id=128723

Consider the following html:

<html><body><form>
<input type="hidden" name="arguments"></input>
<div onclick="onclicked()" id="divInsideForm">Click here</div>
</form></body>
<script>
function onclicked() {
  alert("onclicked");
}
</script>
</html>

If we click "Click here", JavaScript throws "Uncaught TypeError: undefined has no properties".

This is a regression caused by r110315. V8LazyEventListener should not use
'arguments' to retrieve the execution contexts, since 'arguments' can be
shadowed by JavaScript.

This patch changes V8LazyEventListener so that it retrieves contexts
by this[2], this[1] and this[0].

Test: fast/forms/form-input-named-arguments.html

* bindings/v8/V8LazyEventListener.cpp:
(WebCore::V8LazyEventListener::prepareListenerObject):

LayoutTests:

The added test checks whether an event handler is successfully invoked
for an input element with name="arguments".

* fast/forms/form-input-named-arguments-expected.txt: Added.
* fast/forms/form-input-named-arguments.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@117928 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/forms/form-input-named-arguments-expected.txt [new file with mode: 0644]
LayoutTests/fast/forms/form-input-named-arguments.html [new file with mode: 0644]
LayoutTests/platform/chromium-win/inspector/debugger/debugger-scripts-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/bindings/v8/V8LazyEventListener.cpp

index f311d25..79e1dd1 100644 (file)
@@ -1,3 +1,16 @@
+2012-05-22  Kentaro Hara  <haraken@chromium.org>
+
+        REGRESSION r110315: Event handler throws TypeError for an input element with name="arguments"
+        https://bugs.webkit.org/show_bug.cgi?id=86991
+
+        Reviewed by Ojan Vafai.
+
+        The added test checks whether an event handler is successfully invoked
+        for an input element with name="arguments".
+
+        * fast/forms/form-input-named-arguments-expected.txt: Added.
+        * fast/forms/form-input-named-arguments.html: Added.
+
 2012-05-22  Emil A Eklund  <eae@chromium.org>
 
         Chromium linux and mac rebaselines.
diff --git a/LayoutTests/fast/forms/form-input-named-arguments-expected.txt b/LayoutTests/fast/forms/form-input-named-arguments-expected.txt
new file mode 100644 (file)
index 0000000..2916c67
--- /dev/null
@@ -0,0 +1,5 @@
+PASS clicked is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/form-input-named-arguments.html b/LayoutTests/fast/forms/form-input-named-arguments.html
new file mode 100644 (file)
index 0000000..f927d55
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head></head>
+<body>
+<script src="../js/resources/js-test-pre.js"></script>
+<form>
+<input type="hidden" name="arguments"></input>
+<div onclick="onclicked()" id="divInsideForm"></div>
+</form>
+</body>
+<script>
+var clicked = false;
+
+function onclicked() {
+   clicked = true;
+}
+
+var event = document.createEvent("MouseEvents");
+event.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+var div = document.getElementById("divInsideForm");
+div.dispatchEvent(event);
+
+shouldBeTrue('clicked');
+
+var successfullyParsed = true;
+</script>
+<script src="../js/resources/js-test-post.js"></script>
+</html>
index f484b34..47b8617 100644 (file)
@@ -1,5 +1,41 @@
 2012-05-22  Kentaro Hara  <haraken@chromium.org>
 
+        REGRESSION r110315: Event handler throws TypeError for an input element with name="arguments"
+        https://bugs.webkit.org/show_bug.cgi?id=86991
+
+        Reviewed by Ojan Vafai.
+
+        Original Chromium bug: http://code.google.com/p/chromium/issues/detail?id=128723
+
+        Consider the following html:
+
+        <html><body><form>
+        <input type="hidden" name="arguments"></input>
+        <div onclick="onclicked()" id="divInsideForm">Click here</div>
+        </form></body>
+        <script>
+        function onclicked() {
+          alert("onclicked");
+        }
+        </script>
+        </html>
+
+        If we click "Click here", JavaScript throws "Uncaught TypeError: undefined has no properties".
+
+        This is a regression caused by r110315. V8LazyEventListener should not use
+        'arguments' to retrieve the execution contexts, since 'arguments' can be
+        shadowed by JavaScript.
+
+        This patch changes V8LazyEventListener so that it retrieves contexts
+        by this[2], this[1] and this[0].
+
+        Test: fast/forms/form-input-named-arguments.html
+
+        * bindings/v8/V8LazyEventListener.cpp:
+        (WebCore::V8LazyEventListener::prepareListenerObject):
+
+2012-05-22  Kentaro Hara  <haraken@chromium.org>
+
         [V8] setDOMException() should return v8::Handle<v8::Value>()
         https://bugs.webkit.org/show_bug.cgi?id=87083
 
index 840de7f..7332318 100644 (file)
@@ -137,16 +137,21 @@ void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context)
     // 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?
     //
+    // Call with 4 arguments instead of 3, pass additional null as the last parameter.
+    // By calling the function with 4 arguments, we create a setter on arguments object
+    // which would shadow property "3" on the prototype.
     String code = "(function() {" \
-        "with (arguments[2]) {" \
-        "with (arguments[1]) {" \
-        "with (arguments[0]) {";
+        "arguments[3] = function() {" \
+        "with (this[2]) {" \
+        "with (this[1]) {" \
+        "with (this[0]) {";
     code.append("return function(");
     code.append(m_eventParameterName);
     code.append(") {");
     code.append(m_code);
     // Insert '\n' otherwise //-style comments could break the handler.
-    code.append("\n};}}}})");
+    code.append("\n};}}}};");
+    code.append("return arguments[3]();})");
     v8::Handle<v8::String> codeExternalString = v8ExternalString(code);
 
     v8::Handle<v8::Script> script = V8Proxy::compileScript(codeExternalString, m_sourceURL, m_position);
@@ -174,7 +179,7 @@ void V8LazyEventListener::prepareListenerObject(ScriptExecutionContext* context)
     v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formElement);
     v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0);
 
-    v8::Handle<v8::Value> parameters[3] = { nodeWrapper, formWrapper, documentWrapper };
+    v8::Handle<v8::Value> parameters[4] = { nodeWrapper, formWrapper, documentWrapper, v8::Handle<v8::Value>(v8::Null()) };
 
     // FIXME: Remove this code when we stop doing the 'with' hack above.
     v8::Local<v8::Value> innerValue;