Repository: jshint/jshint
Pull request #2061 (2014-12-30 22:37:21)

[[FIX]] Allow array, grouping and string form to follow spread operator in function call args.

rwaldron: Please update the commit message to follow https://github.com/jshint/jshint/blob/master/CONTRIBUTING.md#commit-message-guidelines Thanks!!
coveralls: 
[![Coverage Status](https://coveralls.io/builds/1687749/badge)](https://coveralls.io/builds/1687749)

Coverage remained the same when pulling **ebc39b430116773defedf51959dff521d4419386 on rwaldron:2060** into **08c70e632f889feb8481acdc41e541ca49edfad4 on jshint:master**.

rwaldron: @caitp Updated to new commit message format and changes per your last review
caitp: Looks good to me --- last nit might be adding a "TODO: allow all assignment expressions when parsing enables this" note or something

Patch:
diff --git a/src/jshint.js b/src/jshint.js
index 44279acf..9a079fdd 100644
--- a/src/jshint.js
+++ b/src/jshint.js
@@ -2260,7 +2260,42 @@ var JSHINT = (function () {
     if (!state.option.esnext) {
       warning("W119", this, "spread/rest operator");
     }
-    if (!state.tokens.next.identifier) {
+
+    // TODO: Allow all AssignmentExpression
+    // once parsing permits.
+    //
+    // How to handle eg. number, boolean when the built-in
+    // prototype of may have an @@iterator definition?
+    //
+    // Number.prototype[Symbol.iterator] = function * () {
+    //   yield this.valueOf();
+    // };
+    //
+    // var a = [ ...1 ];
+    // console.log(a); // [1];
+    //
+    // for (let n of [...10]) {
+    //    console.log(n);
+    // }
+    // // 10
+    //
+    //
+    // Boolean.prototype[Symbol.iterator] = function * () {
+    //   yield this.valueOf();
+    // };
+    //
+    // var a = [ ...true ];
+    // console.log(a); // [true];
+    //
+    // for (let n of [...false]) {
+    //    console.log(n);
+    // }
+    // // false
+    //
+    if (!state.tokens.next.identifier &&
+        state.tokens.next.type !== "(string)" &&
+          !checkPunctuators(state.tokens.next, ["[", "("])) {
+
       error("E030", state.tokens.next, state.tokens.next.value);
     }
     expression(150);


Test patch:
diff --git a/tests/unit/parser.js b/tests/unit/parser.js
index c55ad960..d6a0387f 100644
--- a/tests/unit/parser.js
+++ b/tests/unit/parser.js
@@ -3925,48 +3925,81 @@ exports["object ComputedPropertyName"] = function (test) {
 
 exports["spread & rest operator support"] = function (test) {
   var code = [
-    // spread operator
-    "function foo(a, b, c) {",
-    "  console.log(a, b, c); ",
-    "}",
-    "var args = [ 0, 1, 2 ];",
+    // 1
+    // Spread Identifier
     "foo(...args);",
 
-    // spread operator
+    // 2
+    // Spread Array Literal
+    "foo(...[]);",
+
+    // 3, 4
+    // Spread String Literal
+    "foo(...'');",
+    'foo(..."");',
+
+    // 5
+    // Spread Group
+    "foo(...([]));",
+
+    // 6, 7, 8
+    // Spread Operator
     "let initial = [ 1, 2, 3, 4, 5 ];",
     "let extended = [ ...initial, 6, 7, 8, 9 ];",
+    "let nest = [ ...[], 6, 7, 8, 9 ];",
+
+    // 9
+    // Rest Operator
+    "function foo(...args) {}",
+
+    // 10
+    // Rest Operator (Fat Arrow Params)
+    "let bar = (...args) => args;",
 
-    // rest operator
-    "(function foo(i, j, ...args) {",
-    "  return args;",
-    "}());",
+    // 11
+    "foo(...[].entries());",
 
-    // rest operator on a fat arrow function
-    "let bar = (...args) => args;"
+    // 12
+    "foo(...(new Map()).set('a', 1).values());"
   ];
 
-  var run = TestRun(test);
-  run.test(code, {esnext: true});
+  TestRun(test)
+    .test(code, {esnext: true});
 
-  run = TestRun(test)
-    .addError(11, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")
+  TestRun(test)
+    .addError(1, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(2, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(3, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(4, "'spread/rest operator' is only available in ES6 (use esnext option).")
     .addError(5, "'spread/rest operator' is only available in ES6 (use esnext option).")
     .addError(7, "'spread/rest operator' is only available in ES6 (use esnext option).")
     .addError(8, "'spread/rest operator' is only available in ES6 (use esnext option).")
-    .addError(11, "'spread/rest operator' is only available in ES6 (use esnext option).");
-
-  run.test(code, {moz: true});
+    .addError(9, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(10, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(10, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")
+    .addError(11, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(12, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .test(code, {moz: true});
 
-  run = TestRun(test)
+  TestRun(test)
+    .addError(1, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(2, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(3, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(4, "'spread/rest operator' is only available in ES6 (use esnext option).")
     .addError(5, "'spread/rest operator' is only available in ES6 (use esnext option).")
     .addError(6, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
     .addError(7, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
+
     .addError(7, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(8, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
     .addError(8, "'spread/rest operator' is only available in ES6 (use esnext option).")
-    .addError(11, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
+    .addError(9, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(10, "'let' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).")
+    .addError(10, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .addError(10, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).")
     .addError(11, "'spread/rest operator' is only available in ES6 (use esnext option).")
-    .addError(11, "'arrow function syntax (=>)' is only available in ES6 (use esnext option).");
-  run.test(code);
+    .addError(12, "'spread/rest operator' is only available in ES6 (use esnext option).")
+    .test(code);
 
   test.done();
 };