<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[178517] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/178517">178517</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2015-01-15 11:20:03 -0800 (Thu, 15 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Part 2] Argument object created by &quot;Function dot arguments&quot; should use a clone of argument values.
&lt;https://webkit.org/b/140093&gt;

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

* interpreter/StackVisitor.cpp:
(JSC::StackVisitor::Frame::createArguments):
- We should not fetching the lexicalEnvironment here.  The reason we've
  introduced the ClonedArgumentsCreationMode is because the lexicalEnvironment
  may not be available to us at this point.  Instead, we'll just pass a nullptr.

* runtime/Arguments.cpp:
(JSC::Arguments::tearOffForCloning):
* runtime/Arguments.h:
(JSC::Arguments::finishCreation):
- Use the new tearOffForCloning() to tear off arguments right out of the values
  passed on the stack.  tearOff() is not appropriate for this purpose because
  it takes slowArgumentsData into account.

LayoutTests:

* js/function-dot-arguments-expected.txt:
* js/script-tests/function-dot-arguments.js:
(arrayify):
(indirectCall):
(.inner):
(tearOffTest3):
(tearOffTest3b):
(tearOffTest3c):
(tearOffTest4External):
(tearOffTest4):
(tearOffTest4aExternal):
(tearOffTest4bExternal):
(tearOffTest4b):
(tearOffTest4cExternal):
(tearOffTest4c):
(tearOffTest5):
(tearOffTest5b):
(tearOffTest5c):
(tearOffTest6External):
(tearOffTest6):
(tearOffTest6aExternal):
(tearOffTest6bExternal):
(tearOffTest6b):
(tearOffTest6cExternal):
(tearOffTest6c):
(tearOffTest7):
(tearOffTest7b):
(tearOffTest7c):
(tearOffTest8External):
(tearOffTest8):
(tearOffTest8aExternal):
(tearOffTest8bExternal):
(tearOffTest8b):
(tearOffTest8cExternal):
(tearOffTest8c):
(tearOffTest9b):
(tearOffTest9c):
(tearOffTest10External):
(tearOffTest10):
(tearOffTest10aExternal):
(tearOffTest10bExternal):
(tearOffTest10b):
(tearOffTest10cExternal):
(tearOffTest10c):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsjsfunctiondotargumentsexpectedtxt">trunk/LayoutTests/js/function-dot-arguments-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsfunctiondotargumentsjs">trunk/LayoutTests/js/script-tests/function-dot-arguments.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreinterpreterStackVisitorcpp">trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArgumentscpp">trunk/Source/JavaScriptCore/runtime/Arguments.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeArgumentsh">trunk/Source/JavaScriptCore/runtime/Arguments.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (178516 => 178517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-01-15 19:09:23 UTC (rev 178516)
+++ trunk/LayoutTests/ChangeLog        2015-01-15 19:20:03 UTC (rev 178517)
</span><span class="lines">@@ -1,3 +1,55 @@
</span><ins>+2015-01-15  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        [Part 2] Argument object created by &quot;Function dot arguments&quot; should use a clone of argument values.
+        &lt;https://webkit.org/b/140093&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        * js/function-dot-arguments-expected.txt:
+        * js/script-tests/function-dot-arguments.js:
+        (arrayify):
+        (indirectCall):
+        (.inner):
+        (tearOffTest3):
+        (tearOffTest3b):
+        (tearOffTest3c):
+        (tearOffTest4External):
+        (tearOffTest4):
+        (tearOffTest4aExternal):
+        (tearOffTest4bExternal):
+        (tearOffTest4b):
+        (tearOffTest4cExternal):
+        (tearOffTest4c):
+        (tearOffTest5):
+        (tearOffTest5b):
+        (tearOffTest5c):
+        (tearOffTest6External):
+        (tearOffTest6):
+        (tearOffTest6aExternal):
+        (tearOffTest6bExternal):
+        (tearOffTest6b):
+        (tearOffTest6cExternal):
+        (tearOffTest6c):
+        (tearOffTest7):
+        (tearOffTest7b):
+        (tearOffTest7c):
+        (tearOffTest8External):
+        (tearOffTest8):
+        (tearOffTest8aExternal):
+        (tearOffTest8bExternal):
+        (tearOffTest8b):
+        (tearOffTest8cExternal):
+        (tearOffTest8c):
+        (tearOffTest9b):
+        (tearOffTest9c):
+        (tearOffTest10External):
+        (tearOffTest10):
+        (tearOffTest10aExternal):
+        (tearOffTest10bExternal):
+        (tearOffTest10b):
+        (tearOffTest10cExternal):
+        (tearOffTest10c):
+
</ins><span class="cx"> 2015-01-15  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [Win] Unreviewed gardening.
</span></span></pre></div>
<a id="trunkLayoutTestsjsfunctiondotargumentsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/function-dot-arguments-expected.txt (178516 => 178517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/function-dot-arguments-expected.txt        2015-01-15 19:09:23 UTC (rev 178516)
+++ trunk/LayoutTests/js/function-dot-arguments-expected.txt        2015-01-15 19:20:03 UTC (rev 178517)
</span><span class="lines">@@ -24,6 +24,38 @@
</span><span class="cx"> PASS paramFunctionConstructorInitTest(true).toString() is '[object Arguments]'
</span><span class="cx"> PASS tearOffTest()[0] is true
</span><span class="cx"> PASS tearOffTest2(true)[0] is true
</span><ins>+PASS tearOffTest3(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest3a(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest3b(1, 2, 3, false) is [1, 2, 3, false]
+PASS tearOffTest3c(1, 2, 3, false) is [1, 2, 3, false]
+PASS tearOffTest4(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest4a(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest4b(1, 2, 3, false) is [1, 2, 3, false]
+PASS tearOffTest4c(1, 2, 3, false) is [1, 2, 3, false]
+PASS tearOffTest5(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest5a(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest5b(1, 2, 3, false) is [1, 2, 3, false]
+PASS tearOffTest5c(1, 2, 3, false) is [1, 2, 3, false]
+PASS tearOffTest6(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest6a(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest6b(1, 2, 3, false) is [1, 2, 3, false]
+PASS tearOffTest6c(1, 2, 3, false) is [1, 2, 3, false]
+PASS tearOffTest7(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest7a(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest7b(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest7c(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest8(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest8a(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest8b(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest8c(1, 2, 3, false) is [10, 2, 3, false]
+PASS tearOffTest9(1, 2, 3, false) is [undefined, 2, 3, false]
+PASS tearOffTest9a(1, 2, 3, false) is [undefined, 2, 3, false]
+PASS tearOffTest9b(1, 2, 3, false) is [undefined, 2, 3, false]
+PASS tearOffTest9c(1, 2, 3, false) is [undefined, 2, 3, false]
+PASS tearOffTest10(1, 2, 3, false) is [undefined, 2, 3, false]
+PASS tearOffTest10a(1, 2, 3, false) is [undefined, 2, 3, false]
+PASS tearOffTest10b(1, 2, 3, false) is [undefined, 2, 3, false]
+PASS tearOffTest10c(1, 2, 3, false) is [undefined, 2, 3, false]
</ins><span class="cx"> PASS lexicalArgumentsLiveRead1(0, 2, 3) is 1
</span><span class="cx"> PASS lexicalArgumentsLiveRead2(1, 0, 3) is 2
</span><span class="cx"> PASS lexicalArgumentsLiveRead3(1, 2, 0) is 3
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsfunctiondotargumentsjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/function-dot-arguments.js (178516 => 178517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/function-dot-arguments.js        2015-01-15 19:09:23 UTC (rev 178516)
+++ trunk/LayoutTests/js/script-tests/function-dot-arguments.js        2015-01-15 19:20:03 UTC (rev 178517)
</span><span class="lines">@@ -206,6 +206,533 @@
</span><span class="cx"> }
</span><span class="cx"> shouldBeTrue(&quot;tearOffTest2(true)[0]&quot;);
</span><span class="cx"> 
</span><ins>+
+// Some utility functions/
+function arrayify(args) {
+    if (typeof args != &quot;object&quot;)
+        return args;
+    if (typeof args.length == &quot;undefined&quot; || typeof args.callee == &quot;undefined&quot;)
+        return args;
+    return Array.prototype.slice.call(args);
+}
+
+function indirectCall(callee)
+{
+    return callee();
+}
+
+// Test reading from caller.arguments from an inner function.
+function tearOffTest3(a, b, c, d)
+{
+    a = 10;
+    function inner()
+    {
+        return tearOffTest3.arguments;
+    }
+
+    return arrayify(inner());
+}
+shouldBe(&quot;tearOffTest3(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest3a(a, b, c, d)
+{
+    var x = 42;
+    a = 10;
+    function inner()
+    {
+        return tearOffTest3a.arguments;
+    }
+
+    if (d) {
+        // Force a lexicalEnvironment to be created in the outer function.
+        return function() { return x; }
+    } else {
+        return arrayify(inner());
+    }
+}
+shouldBe(&quot;tearOffTest3a(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest3b(a, b, c, d)
+{
+    a = 10;
+    function inner()
+    {
+        var capture = a; // Capture an arg from the outer function.
+        return tearOffTest3b.arguments;
+    }
+
+    return arrayify(inner());
+}
+shouldBe(&quot;tearOffTest3b(1, 2, 3, false)&quot;, &quot;[1, 2, 3, false]&quot;);
+
+
+function tearOffTest3c(a, b, c, d)
+{
+    a = 10;
+    function inner()
+    {
+        var capture = a; // Capture an arg from the outer function.
+        return tearOffTest3c.arguments;
+    }
+
+    return arrayify(indirectCall(inner));
+}
+shouldBe(&quot;tearOffTest3c(1, 2, 3, false)&quot;, &quot;[1, 2, 3, false]&quot;);
+
+
+// Test reading from caller.arguments from an external function.
+function tearOffTest4External()
+{
+    return tearOffTest4.arguments;
+}
+function tearOffTest4(a, b, c, d)
+{
+    a = 10;
+    return arrayify(tearOffTest4External());
+}
+shouldBe(&quot;tearOffTest4(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest4aExternal()
+{
+    return tearOffTest4a.arguments;
+}
+function tearOffTest4a(a, b, c, d)
+{
+    var x = 42;
+    a = 10;
+
+    if (d) {
+        // Force a lexicalEnvironment to be created in the outer function.
+        return function() { return x; }
+    } else {
+        return arrayify(tearOffTest4aExternal());
+    }
+}
+shouldBe(&quot;tearOffTest4a(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest4bExternal()
+{
+    return tearOffTest4b.arguments;
+}
+function tearOffTest4b(a, b, c, d)
+{
+    a = 10;
+    function inner()
+    {
+        var capture = a; // Capture an arg from the outer function.
+        return capture;
+    }
+
+    return arrayify(tearOffTest4bExternal());
+}
+shouldBe(&quot;tearOffTest4b(1, 2, 3, false)&quot;, &quot;[1, 2, 3, false]&quot;);
+
+
+function tearOffTest4cExternal()
+{
+    return tearOffTest4c.arguments;
+}
+function tearOffTest4c(a, b, c, d)
+{
+    a = 10;
+    function inner()
+    {
+        var capture = a; // Capture an arg from the outer function.
+        return tearOffTest4c.arguments;
+    }
+
+    return arrayify(indirectCall(tearOffTest4cExternal));
+}
+shouldBe(&quot;tearOffTest4c(1, 2, 3, false)&quot;, &quot;[1, 2, 3, false]&quot;);
+
+
+// Test reading from caller.arguments which have Deleted slow data from an inner function.
+function tearOffTest5(a, b, c, d)
+{
+    a = 10;
+    delete arguments[0];
+    function inner()
+    {
+        return tearOffTest5.arguments;
+    }
+
+    return arrayify(inner());
+}
+shouldBe(&quot;tearOffTest5(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest5a(a, b, c, d)
+{
+    var x = 42;
+    a = 10;
+    delete arguments[0];
+    function inner()
+    {
+        return tearOffTest5a.arguments;
+    }
+
+    if (d) {
+        // Force a lexicalEnvironment to be created in the outer function.
+        return function() { return x; }
+    } else {
+        return arrayify(inner());
+    }
+}
+shouldBe(&quot;tearOffTest5a(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest5b(a, b, c, d)
+{
+    a = 10;
+    delete arguments[0];
+    function inner()
+    {
+        var capture = a; // Capture an arg from the outer function.
+        return tearOffTest5b.arguments;
+    }
+
+    return arrayify(inner());
+}
+shouldBe(&quot;tearOffTest5b(1, 2, 3, false)&quot;, &quot;[1, 2, 3, false]&quot;);
+
+
+function tearOffTest5c(a, b, c, d)
+{
+    a = 10;
+    delete arguments[0];
+    function inner()
+    {
+        var capture = a; // Capture an arg from the outer function.
+        return tearOffTest5c.arguments;
+    }
+
+    return arrayify(indirectCall(inner));
+}
+shouldBe(&quot;tearOffTest5c(1, 2, 3, false)&quot;, &quot;[1, 2, 3, false]&quot;);
+
+
+// Test reading from caller.arguments which have Deleted slow data from an external function.
+function tearOffTest6External()
+{
+    return tearOffTest6.arguments;
+}
+function tearOffTest6(a, b, c, d)
+{
+    a = 10;
+    delete arguments[0];
+    return arrayify(tearOffTest6External());
+}
+shouldBe(&quot;tearOffTest6(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest6aExternal()
+{
+    return tearOffTest6a.arguments;
+}
+function tearOffTest6a(a, b, c, d)
+{
+    var x = 42;
+    a = 10;
+    delete arguments[0];
+
+    if (d) {
+        // Force a lexicalEnvironment to be created in the outer function.
+        return function() { return x; }
+    } else {
+        return arrayify(tearOffTest6aExternal());
+    }
+}
+shouldBe(&quot;tearOffTest6a(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest6bExternal()
+{
+    return tearOffTest6b.arguments;
+}
+function tearOffTest6b(a, b, c, d)
+{
+    a = 10;
+    delete arguments[0];
+    function inner()
+    {
+        var capture = a; // Capture an arg from the outer function.
+        return capture;
+    }
+
+    return arrayify(tearOffTest6bExternal());
+}
+shouldBe(&quot;tearOffTest6b(1, 2, 3, false)&quot;, &quot;[1, 2, 3, false]&quot;);
+
+
+function tearOffTest6cExternal()
+{
+    return tearOffTest6c.arguments;
+}
+function tearOffTest6c(a, b, c, d)
+{
+    a = 10;
+    delete arguments[0];
+    function inner()
+    {
+        var capture = a; // Capture an arg from the outer function.
+        return tearOffTest6c.arguments;
+    }
+
+    return arrayify(indirectCall(tearOffTest6cExternal));
+}
+shouldBe(&quot;tearOffTest6c(1, 2, 3, false)&quot;, &quot;[1, 2, 3, false]&quot;);
+
+
+// Test writing to caller.arguments from an inner function.
+function tearOffTest7(a, b, c, d)
+{
+    a = 10;
+    (function inner() {
+        tearOffTest7.arguments[0] = 100;
+    })();
+
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest7(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest7a(a, b, c, d)
+{
+    var x = 42;
+    a = 10;
+
+    if (d) {
+        // Force a lexicalEnvironment to be created in the outer function.
+        return function() { return x; }
+    } else {
+        (function inner() {
+            tearOffTest7a.arguments[0] = 100;
+        }) ();
+
+        return arrayify(arguments);
+    }
+}
+shouldBe(&quot;tearOffTest7a(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest7b(a, b, c, d)
+{
+    a = 10;
+    (function inner() {
+        var capture = a; // Capture an arg from the outer function.
+        tearOffTest7b.arguments[0] = 100;
+    })();
+
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest7b(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest7c(a, b, c, d)
+{
+    a = 10;
+    function inner() {
+        var capture = a; // Capture an arg from the outer function.
+        tearOffTest7c.arguments[0] = 100;
+    }
+    indirectCall(inner);
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest7c(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+// Test writing to caller.arguments from an external function.
+function tearOffTest8External() {
+    tearOffTest8.arguments[0] = 100;
+}
+function tearOffTest8(a, b, c, d)
+{
+    a = 10;
+    tearOffTest8External();
+
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest8(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest8aExternal() {
+    tearOffTest8a.arguments[0] = 100;
+}
+function tearOffTest8a(a, b, c, d)
+{
+    var x = 42;
+    a = 10;
+
+    if (d) {
+        // Force a lexicalEnvironment to be created in the outer function.
+        return function() { return x; }
+    } else {
+        tearOffTest8aExternal();
+        return arrayify(arguments);
+    }
+}
+shouldBe(&quot;tearOffTest8a(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest8bExternal() {
+    tearOffTest8b.arguments[0] = 100;
+}
+function tearOffTest8b(a, b, c, d)
+{
+    a = 10;
+    function inner() {
+        var capture = a; // Capture an arg from the outer function.
+    }
+    tearOffTest8bExternal();
+
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest8b(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+function tearOffTest8cExternal() {
+    tearOffTest8c.arguments[0] = 100;
+}
+function tearOffTest8c(a, b, c, d)
+{
+    a = 10;
+    function inner() {
+        var capture = a; // Capture an arg from the outer function.
+    }
+    indirectCall(tearOffTest8cExternal);
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest8c(1, 2, 3, false)&quot;, &quot;[10, 2, 3, false]&quot;);
+
+
+// Test deleting an arg in caller.arguments from an inner function.
+function tearOffTest9(a, b, c, d)
+{
+    a = 10;
+    delete arguments[0];
+    (function inner() {
+        delete tearOffTest9.arguments[1];
+    })();
+
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest9(1, 2, 3, false)&quot;, &quot;[undefined, 2, 3, false]&quot;);
+
+
+function tearOffTest9a(a, b, c, d)
+{
+    var x = 42;
+    delete arguments[0];
+
+    if (d) {
+        // Force a lexicalEnvironment to be created in the outer function.
+        return function() { return x; }
+    } else {
+        (function inner() {
+            delete tearOffTest9a.arguments[1];
+        }) ();
+
+        return arrayify(arguments);
+    }
+}
+shouldBe(&quot;tearOffTest9a(1, 2, 3, false)&quot;, &quot;[undefined, 2, 3, false]&quot;);
+
+
+function tearOffTest9b(a, b, c, d)
+{
+    delete arguments[0];
+    (function inner() {
+        var capture = a; // Capture an arg from the outer function.
+        delete tearOffTest9b.arguments[1];
+    })();
+
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest9b(1, 2, 3, false)&quot;, &quot;[undefined, 2, 3, false]&quot;);
+
+
+function tearOffTest9c(a, b, c, d)
+{
+    delete arguments[0];
+    function inner() {
+        var capture = a; // Capture an arg from the outer function.
+        delete tearOffTest9c.arguments[1];
+    }
+    indirectCall(inner);
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest9c(1, 2, 3, false)&quot;, &quot;[undefined, 2, 3, false]&quot;);
+
+
+// Test deleting a arg in caller.arguments from an external function.
+
+function tearOffTest10External() {
+    delete tearOffTest10.arguments[1];
+}
+function tearOffTest10(a, b, c, d)
+{
+    delete arguments[0];
+    tearOffTest10External();
+
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest10(1, 2, 3, false)&quot;, &quot;[undefined, 2, 3, false]&quot;);
+
+
+function tearOffTest10aExternal() {
+    delete tearOffTest10a.arguments[1];
+}
+function tearOffTest10a(a, b, c, d)
+{
+    var x = 42;
+    delete arguments[0];
+
+    if (d) {
+        // Force a lexicalEnvironment to be created in the outer function.
+        return function() { return x; }
+    } else {
+        tearOffTest10aExternal();
+        return arrayify(arguments);
+    }
+}
+shouldBe(&quot;tearOffTest10a(1, 2, 3, false)&quot;, &quot;[undefined, 2, 3, false]&quot;);
+
+
+function tearOffTest10bExternal() {
+    delete tearOffTest10b.arguments[1];
+}
+function tearOffTest10b(a, b, c, d)
+{
+    delete arguments[0];
+    function inner() {
+        var capture = a; // Capture an arg from the outer function.
+    }
+    tearOffTest10bExternal();
+
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest10b(1, 2, 3, false)&quot;, &quot;[undefined, 2, 3, false]&quot;);
+
+
+function tearOffTest10cExternal() {
+    delete tearOffTest10c.arguments[1];
+}
+function tearOffTest10c(a, b, c, d)
+{
+    delete arguments[0];
+    function inner() {
+        var capture = a; // Capture an arg from the outer function.
+    }
+    indirectCall(tearOffTest10cExternal);
+    return arrayify(arguments);
+}
+shouldBe(&quot;tearOffTest10c(1, 2, 3, false)&quot;, &quot;[undefined, 2, 3, false]&quot;);
+
+
</ins><span class="cx"> function lexicalArgumentsLiveRead1(a, b, c)
</span><span class="cx"> {
</span><span class="cx">     var o = arguments;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (178516 => 178517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-01-15 19:09:23 UTC (rev 178516)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-01-15 19:20:03 UTC (rev 178517)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2015-01-15  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        [Part 2] Argument object created by &quot;Function dot arguments&quot; should use a clone of argument values.
+        &lt;https://webkit.org/b/140093&gt;
+
+        Reviewed by Geoffrey Garen.
+
+        * interpreter/StackVisitor.cpp:
+        (JSC::StackVisitor::Frame::createArguments):
+        - We should not fetching the lexicalEnvironment here.  The reason we've
+          introduced the ClonedArgumentsCreationMode is because the lexicalEnvironment
+          may not be available to us at this point.  Instead, we'll just pass a nullptr.
+
+        * runtime/Arguments.cpp:
+        (JSC::Arguments::tearOffForCloning):
+        * runtime/Arguments.h:
+        (JSC::Arguments::finishCreation):
+        - Use the new tearOffForCloning() to tear off arguments right out of the values
+          passed on the stack.  tearOff() is not appropriate for this purpose because
+          it takes slowArgumentsData into account.
+
</ins><span class="cx"> 2015-01-14  Matthew Mirman  &lt;mmirman@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Removed accidental commit of &quot;invalid_array.js&quot; 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinterpreterStackVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp (178516 => 178517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp        2015-01-15 19:09:23 UTC (rev 178516)
+++ trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp        2015-01-15 19:20:03 UTC (rev 178517)
</span><span class="lines">@@ -272,7 +272,7 @@
</span><span class="cx">     } else 
</span><span class="cx"> #endif
</span><span class="cx">     {
</span><del>-        JSLexicalEnvironment* lexicalEnvironment = physicalFrame-&gt;lexicalEnvironmentOrNullptr();
</del><ins>+        JSLexicalEnvironment* lexicalEnvironment = nullptr;
</ins><span class="cx">         arguments = Arguments::create(vm, physicalFrame, lexicalEnvironment, mode);
</span><span class="cx">         arguments-&gt;tearOff(physicalFrame);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.cpp (178516 => 178517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.cpp        2015-01-15 19:09:23 UTC (rev 178516)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.cpp        2015-01-15 19:20:03 UTC (rev 178517)
</span><span class="lines">@@ -383,6 +383,40 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx">     
</span><ins>+void Arguments::tearOffForCloning(CallFrame* callFrame)
+{
+    ASSERT(!isTornOff());
+    
+    if (!m_numArguments)
+        return;
+    
+    // Must be called for the same call frame from which it was created.
+    ASSERT(bitwise_cast&lt;WriteBarrier&lt;Unknown&gt;*&gt;(callFrame) == m_registers);
+    
+    m_registers = &amp;registerArray() - CallFrame::offsetFor(1) - 1;
+    
+    ASSERT(!m_slowArgumentData);
+    for (size_t i = 0; i &lt; m_numArguments; ++i)
+        m_registers[CallFrame::argumentOffset(i)].set(callFrame-&gt;vm(), this, callFrame-&gt;argument(i));
+}
+    
+void Arguments::tearOffForCloning(CallFrame* callFrame, InlineCallFrame* inlineCallFrame)
+{
+    RELEASE_ASSERT(!inlineCallFrame-&gt;baselineCodeBlock()-&gt;needsActivation());
+    ASSERT(!isTornOff());
+    
+    if (!m_numArguments)
+        return;
+    
+    m_registers = &amp;registerArray() - CallFrame::offsetFor(1) - 1;
+    
+    ASSERT(!m_slowArgumentData);
+    for (size_t i = 0; i &lt; m_numArguments; ++i) {
+        ValueRecovery&amp; recovery = inlineCallFrame-&gt;arguments[i + 1];
+        m_registers[CallFrame::argumentOffset(i)].set(callFrame-&gt;vm(), this, recovery.recover(callFrame));
+    }
+}
+
</ins><span class="cx"> EncodedJSValue JSC_HOST_CALL argumentsFuncIterator(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     JSObject* thisObj = exec-&gt;thisValue().toThis(exec, StrictMode).toObject(exec);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeArgumentsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Arguments.h (178516 => 178517)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Arguments.h        2015-01-15 19:09:23 UTC (rev 178516)
+++ trunk/Source/JavaScriptCore/runtime/Arguments.h        2015-01-15 19:20:03 UTC (rev 178517)
</span><span class="lines">@@ -87,6 +87,8 @@
</span><span class="cx">     void copyToArguments(ExecState*, CallFrame*, uint32_t copyLength, int32_t firstArgumentOffset);
</span><span class="cx">     void tearOff(CallFrame*);
</span><span class="cx">     void tearOff(CallFrame*, InlineCallFrame*);
</span><ins>+    void tearOffForCloning(CallFrame*);
+    void tearOffForCloning(CallFrame*, InlineCallFrame*);
</ins><span class="cx">     bool isTornOff() const { return m_registers == (&amp;registerArray() - CallFrame::offsetFor(1) - 1); }
</span><span class="cx"> 
</span><span class="cx">     static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype) 
</span><span class="lines">@@ -310,14 +312,14 @@
</span><span class="cx">             tearOff(callFrame);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><del>-        
</del><ins>+
</ins><span class="cx">     case ClonedArgumentsCreationMode: {
</span><span class="cx">         m_numArguments = callFrame-&gt;argumentCount();
</span><span class="cx">         m_registers = reinterpret_cast&lt;WriteBarrierBase&lt;Unknown&gt;*&gt;(callFrame-&gt;registers());
</span><del>-        tearOff(callFrame);
</del><ins>+        tearOffForCloning(callFrame);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><del>-        
</del><ins>+
</ins><span class="cx">     case FakeArgumentValuesCreationMode: {
</span><span class="cx">         m_numArguments = 0;
</span><span class="cx">         m_registers = nullptr;
</span><span class="lines">@@ -368,7 +370,7 @@
</span><span class="cx">         
</span><span class="cx">         ASSERT(!jsCast&lt;FunctionExecutable*&gt;(inlineCallFrame-&gt;executable.get())-&gt;symbolTable(inlineCallFrame-&gt;specializationKind())-&gt;slowArguments());
</span><span class="cx">         
</span><del>-        tearOff(callFrame, inlineCallFrame);
</del><ins>+        tearOffForCloning(callFrame, inlineCallFrame);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span></span></pre>
</div>
</div>

</body>
</html>