Repository: eslint/eslint (JavaScript)

Issue:
5.0.0 - Crash with prefer-const rule where code contains array destructuring assignment with 'ignored values'
This is a minimal reproduction for a bug I've found in `eslint@5.0.0`. As far as I can tell the example code below is valid JavaScript (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Ignoring_some_returned_values).
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).

    This template is for bug reports. If you are here for another reason, please see below:

    1. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
    2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
    3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
    4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint

    Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->

**Tell us about your environment**

* **ESLint Version:** 5.0.0
* **Node Version:** 8.11.0
* **npm Version:** 5.6.0
* **yarn Version:** 1.7.0

**What parser (default, Babel-ESLint, etc.) are you using?** default

**Please show your full configuration:**

<!-- Paste your configuration below: -->
```json
{
    "parserOptions": {
        "ecmaVersion": 2018
    },
    "rules": {
      "prefer-const": 1
    }
}

```


**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**

<!-- Paste the source code below: -->
```js
const b = [1, 2];
let a;

[, a] = b;

```

<!-- Paste the command you used to run ESLint: -->
```bash
cd eslint-5-array-destructuring-assignment-bug
yarn eslint .
```

**What did you expect to happen?**
eslint would lint my project

**What actually happened? Please include the actual, raw output from ESLint.**
eslint did not lint my project and threw a TypeError from one of its built-in rules (`prefer-const`)
```
Cannot read property 'name' of null
TypeError: Cannot read property 'name' of null
    at elements.map.element (/node_modules/eslint/lib/rules/prefer-const.js:173:49)
    at Array.map (<anonymous>)
    at getIdentifierIfShouldBeConst (/node_modules/eslint/lib/rules/prefer-const.js:173:26)
    at groupByDestructuring (/node_modules/eslint/lib/rules/prefer-const.js:227:28)
    at Program:exit (/node_modules/eslint/lib/rules/prefer-const.js:362:17)
    at listeners.(anonymous function).forEach.listener (/node_modules/eslint/lib/util/safe-emitter.js:45:58)
    at Array.forEach (<anonymous>)
    at Object.emit (/node_modules/eslint/lib/util/safe-emitter.js:45:38)
    at NodeEventGenerator.applySelector (/node_modules/eslint/lib/util/node-event-generator.js:251:26)
    at NodeEventGenerator.applySelectors (/node_modules/eslint/lib/util/node-event-generator.js:280:22)
```


Discussion:
Hi @mjmasn, thanks for the issue!

I can reproduce in the [demo](https://eslint.org/demo/#eyJ0ZXh0IjoiLyogZXNsaW50IHByZWZlci1jb25zdDogZXJyb3IgKi9cclxuXHJcbmNvbnN0IGIgPSBbMSwgMl07XHJcbmxldCBhO1xyXG5cclxuIiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjo2LCJzb3VyY2VUeXBlIjoic2NyaXB0IiwiZWNtYUZlYXR1cmVzIjp7fX0sInJ1bGVzIjp7fSwiZW52Ijp7fX19). I'll mark this as a bug.
:+1: BTW changing https://github.com/eslint/eslint/blob/196c1021c070e52259f2ceccc4f141bdb7456c60/lib/rules/prefer-const.js#L173 to
```js
.map(element => element ? element.name : null)
```
fixes the crash but I'm not sure if there are any wider implications...
Thanks @mjmasn, that makes sense. Would you like to create a PR (maybe with a new test that would trigger the crash)?
Just out of curiosity, anyone know if this can be recreated in the 4.x release line?
@platinumazure I don't think so, the code was introduced in https://github.com/eslint/eslint/commit/240c1a4df321de56c12acbcfad21734944d7e116 (first released in [5.0.0-alpha.4](https://github.com/eslint/eslint/releases/tag/v5.0.0-alpha.4))
should we release a patch `5.0.2`, since seems it was introduced in `5.0.0-alpha.4`? cc @eslint/eslint-team 



Patch:
diff --git a/lib/rules/prefer-const.js b/lib/rules/prefer-const.js
index a7c46b34de7e..a784e2e31f28 100644
--- a/lib/rules/prefer-const.js
+++ b/lib/rules/prefer-const.js
@@ -170,7 +170,7 @@ function getIdentifierIfShouldBeConst(variable, ignoreReadBeforeAssign) {
                     const elements = leftNode.elements;
 
                     hasOuterVariables = elements
-                        .map(element => element.name)
+                        .map(element => element && element.name)
                         .some(name => isOuterVariableInDestructing(name, variable.scope));
                 }
                 if (hasOuterVariables) {


Test patch:
diff --git a/tests/lib/rules/prefer-const.js b/tests/lib/rules/prefer-const.js
index 59865ec860ad..c7b8a93c2be6 100644
--- a/tests/lib/rules/prefer-const.js
+++ b/tests/lib/rules/prefer-const.js
@@ -121,7 +121,11 @@ ruleTester.run("prefer-const", rule, {
         {
             code: "let x; function foo() { bar(x); } x = 0;",
             options: [{ ignoreReadBeforeAssign: true }]
-        }
+        },
+
+        // https://github.com/eslint/eslint/issues/10520
+        "const x = [1,2]; let y; [,y] = x; y = 0;",
+        "const x = [1,2,3]; let y, z; [y,,z] = x; y = 0; z = 0;"
     ],
     invalid: [
         {
@@ -361,6 +365,21 @@ ruleTester.run("prefer-const", rule, {
                 { message: "'foo' is never reassigned. Use 'const' instead.", type: "Identifier" },
                 { message: "'bar' is never reassigned. Use 'const' instead.", type: "Identifier" }
             ]
+        },
+
+        // https://github.com/eslint/eslint/issues/10520
+        {
+            code: "const x = [1,2]; let [,y] = x;",
+            output: "const x = [1,2]; const [,y] = x;",
+            errors: [{ message: "'y' is never reassigned. Use 'const' instead.", type: "Identifier" }]
+        },
+        {
+            code: "const x = [1,2,3]; let [y,,z] = x;",
+            output: "const x = [1,2,3]; const [y,,z] = x;",
+            errors: [
+                { message: "'y' is never reassigned. Use 'const' instead.", type: "Identifier" },
+                { message: "'z' is never reassigned. Use 'const' instead.", type: "Identifier" }
+            ]
         }
     ]
 });