Bug 1317374 - Don't do Annex B lexical function behavior when redeclaring a parameter name. (r=Waldo)
authorShu-yu Guo <shu@rfrn.org>
Tue, 17 Jan 2017 14:04:19 -0800
changeset 374728 4f4bae3e495a313037dfbf0acf4e9043654da775
parent 374727 ec08fbdc84b278afa68994acd2c75011d412e227
child 374729 56f0b3f7b1259509f93bc907e25c41cc5b8779c7
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1317374
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1317374 - Don't do Annex B lexical function behavior when redeclaring a parameter name. (r=Waldo)
js/src/frontend/Parser.cpp
js/src/jit-test/tests/basic/testFunctionStatementAliasLocals.js
js/src/tests/ecma_6/LexicalEnvironment/block-scoped-functions-annex-b-parameter.js
js/src/tests/js1_8/regress/regress-467495-05.js
js/src/tests/js1_8/regress/regress-467495-06.js
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1172,16 +1172,22 @@ Parser<ParseHandler>::tryDeclareVar(Hand
                 bool annexB33Allowance = declaredKind == DeclarationKind::LexicalFunction &&
                                          kind == DeclarationKind::VarForAnnexBLexicalFunction &&
                                          scope == pc->innermostScope();
 
                 if (!annexB35Allowance && !annexB33Allowance) {
                     *redeclaredKind = Some(declaredKind);
                     return true;
                 }
+            } else if (kind == DeclarationKind::VarForAnnexBLexicalFunction) {
+                MOZ_ASSERT(DeclarationKindIsParameter(declaredKind));
+
+                // Annex B.3.3.1 disallows redeclaring parameter names.
+                *redeclaredKind = Some(declaredKind);
+                return true;
             }
         } else {
             if (!scope->addDeclaredName(pc, p, name, kind))
                 return false;
         }
     }
 
     if (!pc->sc()->strict() && pc->sc()->isEvalContext())
--- a/js/src/jit-test/tests/basic/testFunctionStatementAliasLocals.js
+++ b/js/src/jit-test/tests/basic/testFunctionStatementAliasLocals.js
@@ -3,14 +3,16 @@ function f1(b) {
     if (b)
         function w() {}
     return w;
 }
 assertEq(typeof f1(true), "function");
 assertEq(f1(false), 3);
 
 function f2(b, w) {
+    // Annex B doesn't apply to functions in blocks with the same name as a
+    // parameter.
     if (b)
         function w() {}
     return w;
 }
-assertEq(typeof f2(true, 3), "function");
+assertEq(typeof f2(true, 3), "number");
 assertEq(f2(false, 3), 3);
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/LexicalEnvironment/block-scoped-functions-annex-b-parameter.js
@@ -0,0 +1,16 @@
+// Annex B.3.3.1 disallows Annex B lexical function behavior when redeclaring a
+// parameter.
+
+(function(f) {
+  if (true) function f() {  }
+  assertEq(f, 123);
+}(123));
+
+(function(f) {
+  { function f() {  } }
+  assertEq(f, 123);
+}(123));
+
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
--- a/js/src/tests/js1_8/regress/regress-467495-05.js
+++ b/js/src/tests/js1_8/regress/regress-467495-05.js
@@ -15,17 +15,17 @@ test();
 //-----------------------------------------------------------------------------
 
 function test()
 {
   enterFunc ('test');
   printBugNumber(BUGNUMBER);
   printStatus (summary);
 
-  expect = 'function x() {}';
+  expect = '1';
 
   function g(x) { if (1) function x() {} return x; }
   print(actual = g(1) + '');
 
   reportCompare(expect, actual, summary);
 
   exitFunc ('test');
 }
--- a/js/src/tests/js1_8/regress/regress-467495-06.js
+++ b/js/src/tests/js1_8/regress/regress-467495-06.js
@@ -27,17 +27,17 @@ function test()
       function x() { }
     if (Math)
       function y() { }
     return [x, y];
   }
 
   var r = f(0);
 
-  if (typeof(r[0]) != "function")
+  if (typeof(r[0]) != "number")
     actual += "Bad r[0]";
 
   if (typeof(r[1]) != "function")
     throw "Bad r[1]";
 
   reportCompare(expect, actual, summary);
 
   exitFunc ('test');