Repository: jshint/jshint
Pull request #3181 (2017-09-04 14:33:28)

[[FIX]] Report error for duplicate arrow params
Ensure that duplicate parameters in arrow functions are always reported
as a SyntaxError (regardless of strict mode and regardless of whether
the function has a block body.

@rwaldron DI discovered this while updating gh-3177. This one should land first.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/13116774/badge)](https://coveralls.io/builds/13116774)

Coverage increased (+0.0006%) to 98.696% when pulling **a26ec2209d37c0bc5a54921e3082889adac5802d on jugglinmike:validate-params-concise-arrow** into **960680575afbc9e50de4c91140edfc77d8599bd8 on jshint:master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/13116774/badge)](https://coveralls.io/builds/13116774)

Coverage increased (+0.0006%) to 98.696% when pulling **a26ec2209d37c0bc5a54921e3082889adac5802d on jugglinmike:validate-params-concise-arrow** into **960680575afbc9e50de4c91140edfc77d8599bd8 on jshint:master**.


Patch:
diff --git a/src/jshint.js b/src/jshint.js
index 97a20061..d3dbbfbb 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -1795,7 +1795,7 @@ var JSHINT = (function() {
       advance("}", t);
 
       if (isfunc) {
-        state.funct["(scope)"].validateParams();
+        state.funct["(scope)"].validateParams(isfatarrow);
         if (m) {
           state.directive = m;
         }
@@ -1812,6 +1812,10 @@ var JSHINT = (function() {
           error("W118", state.tokens.curr, "function closure expressions");
         }
 
+        if (isfatarrow) {
+          state.funct["(scope)"].validateParams(true);
+        }
+
         expression(10);
 
         if (state.option.strict && state.funct["(context)"]["(global)"]) {
diff --git a/src/scope-manager.js b/src/scope-manager.js
index 3aa92762..04e6319e 100644
--- a/src/scope-manager.js
+++ b/src/scope-manager.js
@@ -487,7 +487,7 @@ var scopeManager = function(state, predefined, exported, declared) {
       }
     },
 
-    validateParams: function() {
+    validateParams: function(isArrow) {
       var isStrict = state.isStrict();
       var currentFunctParamScope = _currentFunctBody["(parent)"];
 
@@ -499,7 +499,7 @@ var scopeManager = function(state, predefined, exported, declared) {
         var label = currentFunctParamScope["(labels)"][labelName];
 
         if (label && label.duplicated) {
-          if (isStrict) {
+          if (isStrict || isArrow) {
             warning("E011", label["(token)"], labelName);
           } else if (state.option.shadow !== true) {
             warning("W004", label["(token)"], labelName);


Test patch:
diff --git a/tests/test262/expectations.txt b/tests/test262/expectations.txt
index 3fac57d8..678b7111 100644
--- a/tests/test262/expectations.txt
+++ b/tests/test262/expectations.txt
@@ -753,17 +753,6 @@ language/expressions/arrow-function/syntax/arrowparameters-cover-formalparameter
 language/expressions/arrow-function/syntax/early-errors/arrowparameters-bindingidentifier-identifier-futurereservedword.js
 language/expressions/arrow-function/syntax/early-errors/arrowparameters-bindingidentifier-identifier-strict-futurereservedword.js
 language/expressions/arrow-function/syntax/early-errors/arrowparameters-bindingidentifier-no-eval.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-binding-array-1.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-binding-array-2.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-binding-array-3.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-binding-object-1.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-binding-object-2.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-binding-object-3.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-binding-object-4.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-binding-object-5.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-binding-object-6.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates-rest.js
-language/expressions/arrow-function/syntax/early-errors/arrowparameters-cover-no-duplicates.js
 language/expressions/arrow-function/syntax/early-errors/asi-restriction-invalid-parenless-parameters-expression-body.js
 language/expressions/arrow-function/syntax/early-errors/asi-restriction-invalid-parenless-parameters.js
 language/expressions/arrow-function/syntax/early-errors/use-strict-with-non-simple-param.js
diff --git a/tests/unit/core.js b/tests/unit/core.js
index 4cb7c82a..db23e44b 100644
--- a/tests/unit/core.js
+++ b/tests/unit/core.js
@@ -1597,6 +1597,28 @@ exports.testDuplicateParamNames = function (test) {
     .addError(18, 3, "Unnecessary directive \"use strict\".")
     .test(src, { shadow: false });
 
+  src = [
+    "void ((x, x) => null);",
+    "void ((x, x) => {});",
+    "void ((x, x) => { 'use strict'; });",
+    "function f() {",
+    "  'use strict';",
+    "  void ((x, x) => null);",
+    "  void ((x, x) => {});",
+    "  void ((x, x) => { 'use strict'; });",
+    "}"
+  ];
+
+  TestRun(test, "Arrow functions - strict mode restriction")
+    .addError(1, 8, "'x' has already been declared.")
+    .addError(2, 8, "'x' has already been declared.")
+    .addError(3, 8, "'x' has already been declared.")
+    .addError(6, 10, "'x' has already been declared.")
+    .addError(7, 10, "'x' has already been declared.")
+    .addError(8, 10, "'x' has already been declared.")
+    .addError(8, 21, "Unnecessary directive \"use strict\".")
+    .test(src, { esversion: 6 });
+
   test.done();
 };