<!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>[212021] 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/212021">212021</a></dd>
<dt>Author</dt> <dd>bfulgham@apple.com</dd>
<dt>Date</dt> <dd>2017-02-09 18:02:30 -0800 (Thu, 09 Feb 2017)</dd>
</dl>
<h3>Log Message</h3>
<pre>Sloppy mode: We don't properly hoist functions names "arguments" when we have a non-simple parameter list
https://bugs.webkit.org/show_bug.cgi?id=167319
<rdar://problem/30149432>
Patch by Saam Barati <sbarati@apple.com> on 2017-02-09
Reviewed by Mark Lam.
JSTests:
* stress/sloppy-mode-hoist-arguments-function-non-simple-parameter-list.js: Added.
(assert):
(assert.arguments):
(assert.b):
(x.arguments):
(x.b):
(x):
Source/JavaScriptCore:
When hoisting a function inside sloppy mode, we were assuming all "var"s are inside
what we call the "var" SymbolTableEntry. This was almost true, execpt for "arguments",
which has sufficiently weird behavior. "arguments" can be visible to the default
parameter expressions inside a function, therefore can't go inside the "var"
SymbolTableEntry since the parameter SymbolTableEntry comes before the "var"
SymbolTableEntry in the scope chain. Therefore, if we hoist a function named
"arguments", then we must also look for that variable inside the parameter scope
stack entry.
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::hoistSloppyModeFunctionIfNecessary):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstresssloppymodehoistargumentsfunctionnonsimpleparameterlistjs">trunk/JSTests/stress/sloppy-mode-hoist-arguments-function-non-simple-parameter-list.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (212020 => 212021)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-02-10 01:55:30 UTC (rev 212020)
+++ trunk/JSTests/ChangeLog        2017-02-10 02:02:30 UTC (rev 212021)
</span><span class="lines">@@ -1,3 +1,19 @@
</span><ins>+2017-02-09 Saam Barati <sbarati@apple.com>
+
+ Sloppy mode: We don't properly hoist functions names "arguments" when we have a non-simple parameter list
+ https://bugs.webkit.org/show_bug.cgi?id=167319
+ <rdar://problem/30149432>
+
+ Reviewed by Mark Lam.
+
+ * stress/sloppy-mode-hoist-arguments-function-non-simple-parameter-list.js: Added.
+ (assert):
+ (assert.arguments):
+ (assert.b):
+ (x.arguments):
+ (x.b):
+ (x):
+
</ins><span class="cx"> 2017-02-09 Mark Lam <mark.lam@apple.com>
</span><span class="cx">
</span><span class="cx"> Fix max length check in ArrayPrototype.js' concatSlowPath().
</span></span></pre></div>
<a id="trunkJSTestsstresssloppymodehoistargumentsfunctionnonsimpleparameterlistjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/sloppy-mode-hoist-arguments-function-non-simple-parameter-list.js (0 => 212021)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/sloppy-mode-hoist-arguments-function-non-simple-parameter-list.js         (rev 0)
+++ trunk/JSTests/stress/sloppy-mode-hoist-arguments-function-non-simple-parameter-list.js        2017-02-10 02:02:30 UTC (rev 212021)
</span><span class="lines">@@ -0,0 +1,158 @@
</span><ins>+function assert(b) {
+ if (!b)
+ throw new Error("Bad assertion")
+}
+
+(function (x = 20) {
+ var a;
+ assert(arguments.length === 0);
+ assert(typeof arguments !== "function");
+ {
+ function arguments() {
+ }
+
+ function b() {
+ var g = 1;
+ a[5];
+ }
+ }
+ assert(typeof arguments === "function");
+}());
+
+(function (x = () => arguments) {
+ var a;
+ let originalArguments = x();
+ assert(originalArguments === arguments);
+ let z;
+ {
+ function arguments() { return 25; }
+ z = arguments;
+
+ function b() {
+ var g = 1;
+ a[5];
+ }
+ }
+ assert(z !== originalArguments);
+ assert(x() === z);
+ assert(typeof z === "function");
+ assert(z() === 25);
+}());
+
+(function ({arguments}) {
+ assert(arguments === 20);
+
+ var a;
+ {
+ function arguments() { return 25; }
+ assert(arguments() === 25);
+
+ function b() {
+ var g = 1;
+ a[5];
+ }
+ }
+
+ assert(arguments === 20);
+}({arguments: 20}));
+
+(function (y = () => arguments, {arguments}) {
+ assert(y() === arguments);
+ var a;
+ {
+ function arguments() { return 25; }
+ assert(arguments() === 25);
+ assert(y() !== arguments);
+
+ function b() {
+ var g = 1;
+ a[5];
+ }
+ }
+
+ assert(y() === arguments);
+}(undefined, {arguments: {}}));
+
+(function (y = () => arguments, z = y(), {arguments}) {
+ assert(typeof z === "object");
+ assert(z.length === 3);
+ assert(z[0] === undefined);
+ assert(z[1] === undefined);
+ assert(typeof z[2] === "object");
+ assert(z[2].arguments === arguments);
+ assert(y() === arguments);
+
+ var a;
+ {
+ function arguments() { return 25; }
+ assert(arguments() === 25);
+ assert(y() !== arguments);
+
+ function b() {
+ var g = 1;
+ a[5];
+ }
+ }
+
+ assert(y() === arguments);
+}(undefined, undefined, {arguments: {}}));
+
+(function (arguments) {
+ assert(arguments === 25);
+
+ var a;
+ {
+ function arguments() { return 30; }
+ assert(arguments() === 30);
+
+ function b() {
+ var g = 1;
+ a[5];
+ }
+ }
+
+ assert(arguments === 25);
+}(25));
+
+(function (arguments) {
+ assert(arguments === 25);
+ let foo = () => arguments;
+ assert(foo() === arguments);
+
+ var a;
+ {
+ function arguments() { return 30; }
+ assert(arguments() === 30);
+ assert(foo() === 25);
+
+ function b() {
+ var g = 1;
+ a[5];
+ }
+ }
+
+ assert(arguments === 25);
+ assert(foo() === arguments);
+}(25));
+
+(function () {
+ assert(arguments.length === 1);
+ assert(arguments[0] === 25);
+
+ let outer = () => arguments;
+ var a;
+ {
+ assert(outer()[0] === 25);
+ function arguments() { return 30; }
+ assert(outer() === arguments);
+ assert(outer()() === 30);
+ assert(arguments() === 30);
+
+ function b() {
+ var g = 1;
+ a[5];
+ }
+ }
+
+ assert(arguments() === 30);
+}(25));
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (212020 => 212021)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-02-10 01:55:30 UTC (rev 212020)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-02-10 02:02:30 UTC (rev 212021)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2017-02-09 Saam Barati <sbarati@apple.com>
+
+ Sloppy mode: We don't properly hoist functions names "arguments" when we have a non-simple parameter list
+ https://bugs.webkit.org/show_bug.cgi?id=167319
+ <rdar://problem/30149432>
+
+ Reviewed by Mark Lam.
+
+ When hoisting a function inside sloppy mode, we were assuming all "var"s are inside
+ what we call the "var" SymbolTableEntry. This was almost true, execpt for "arguments",
+ which has sufficiently weird behavior. "arguments" can be visible to the default
+ parameter expressions inside a function, therefore can't go inside the "var"
+ SymbolTableEntry since the parameter SymbolTableEntry comes before the "var"
+ SymbolTableEntry in the scope chain. Therefore, if we hoist a function named
+ "arguments", then we must also look for that variable inside the parameter scope
+ stack entry.
+
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::hoistSloppyModeFunctionIfNecessary):
+
</ins><span class="cx"> 2017-02-09 Mark Lam <mark.lam@apple.com>
</span><span class="cx">
</span><span class="cx"> Fix max length check in ArrayPrototype.js' concatSlowPath().
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (212020 => 212021)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2017-02-10 01:55:30 UTC (rev 212020)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2017-02-10 02:02:30 UTC (rev 212021)
</span><span class="lines">@@ -2154,11 +2154,22 @@
</span><span class="cx">
</span><span class="cx"> ASSERT(m_varScopeLexicalScopeStackIndex);
</span><span class="cx"> ASSERT(*m_varScopeLexicalScopeStackIndex < m_lexicalScopeStack.size());
</span><del>- auto& varScope = m_lexicalScopeStack[*m_varScopeLexicalScopeStackIndex];
</del><ins>+ LexicalScopeStackEntry varScope = m_lexicalScopeStack[*m_varScopeLexicalScopeStackIndex];
</ins><span class="cx"> SymbolTable* varSymbolTable = varScope.m_symbolTable;
</span><span class="cx"> ASSERT(varSymbolTable->scopeType() == SymbolTable::ScopeType::VarScope);
</span><span class="cx"> SymbolTableEntry entry = varSymbolTable->get(NoLockingNecessary, functionName.impl());
</span><del>- ASSERT(!entry.isNull());
</del><ins>+ if (functionName == propertyNames().arguments && entry.isNull()) {
+ // "arguments" might be put in the parameter scope when we have a non-simple
+ // parameter list since "arguments" is visible to expressions inside the
+ // parameter evaluation list.
+ // e.g:
+ // function foo(x = arguments) { { function arguments() { } } }
+ RELEASE_ASSERT(*m_varScopeLexicalScopeStackIndex > 0);
+ varScope = m_lexicalScopeStack[*m_varScopeLexicalScopeStackIndex - 1];
+ SymbolTable* parameterSymbolTable = varScope.m_symbolTable;
+ entry = parameterSymbolTable->get(NoLockingNecessary, functionName.impl());
+ }
+ RELEASE_ASSERT(!entry.isNull());
</ins><span class="cx"> bool isLexicallyScoped = false;
</span><span class="cx"> emitPutToScope(varScope.m_scope, variableForLocalEntry(functionName, entry, varScope.m_symbolTableConstantIndex, isLexicallyScoped), currentValue.get(), DoNotThrowIfNotFound, InitializationMode::NotInitialization);
</span><span class="cx"> }
</span></span></pre>
</div>
</div>
</body>
</html>