Repository: eslint/eslint (js)

Issue:
Rule Change: (valid-typeof) undefined should be banned
### What rule do you want to change?

valid-typeof

### What change to do you want to make?

Generate more warnings

### How do you think the change should be implemented?

A new default behavior

### Example code

```js
typeof foo === null
typeof foo === undefined
```


### What does the rule currently do for this code?

only `null` is reported

### What will the rule do after it's changed?

both `null` and `undefined` should be reported

### Participation

- [X] I am willing to submit a pull request to implement this change.

### Additional comments

_No response_

Pull request:
feat: `valid-typeof`: always ban `undefined`
<!--
    Thank you for contributing!

    ESLint adheres to the [JS Foundation Code of Conduct](https://eslint.org/conduct).
-->

#### Prerequisites checklist

- [x] I have read the [contributing guidelines](https://github.com/eslint/eslint/blob/HEAD/CONTRIBUTING.md).

#### What is the purpose of this pull request? (put an "X" next to an item)

<!--
    The following template is intentionally not a markdown checkbox list for the reasons
    explained in https://github.com/eslint/eslint/pull/12848#issuecomment-580302888
-->

[ ] Documentation update
[ ] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/rule-proposal.md))
[x] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/HEAD/templates/rule-change-proposal.md))
[ ] Add autofix to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

fixes #15591

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

#### What changes did you make? (Give an overview)
check `undefined` and report

#### Is there anything you'd like reviewers to focus on?
should we use `getStaticValue`?

<!-- markdownlint-disable-file MD004 -->


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 15e98f4c1..d11c93dfc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,20 @@
+v8.10.0 - February 25, 2022
+
+* [`cdc5802`](https://github.com/eslint/eslint/commit/cdc58025d9a8b522f516c3665d225b69a76c4ee1) fix: Avoid `__dirname` for built-in configs (#15616) (DoZerg)
+* [`7cec74e`](https://github.com/eslint/eslint/commit/7cec74e842b6e51da1b00a9e9b2c9da97dd17362) chore: upgrade @eslint/eslintrc@1.2.0 (#15648) (Milos Djermanovic)
+* [`6e2c325`](https://github.com/eslint/eslint/commit/6e2c325324479df1b3f868cf00a529b67d2c3d82) feat: Add `ignoreOnInitialization` option to no-shadow rule (#14963) (Soufiane Boutahlil)
+* [`1005bd5`](https://github.com/eslint/eslint/commit/1005bd525a08208fee124149a6ad4cf9da20d7d5) docs: update CLA information (#15630) (Nitin Kumar)
+* [`5d65c3b`](https://github.com/eslint/eslint/commit/5d65c3bc1e514ed07406c502437a1642913b27ed) docs: Fix typo in `no-irregular-whitespace` (#15634) (Ryota Sekiya)
+* [`11c8580`](https://github.com/eslint/eslint/commit/11c8580de0dcedd5577cffe2b23d23a322cc97df) chore: read `ESLINT_MOCHA_TIMEOUT` env var in Makefile.js (#15626) (Piggy)
+* [`b93af98`](https://github.com/eslint/eslint/commit/b93af98b3c417225a027cabc964c38e779adb945) docs: add links between rules about whitespace around block curly braces (#15625) (Milos Djermanovic)
+* [`ebc0460`](https://github.com/eslint/eslint/commit/ebc0460c411ea608ba5bab05829a1fd122fe21e8) docs: update babel links (#15624) (Milos Djermanovic)
+* [`115cae5`](https://github.com/eslint/eslint/commit/115cae54125b9ef509af90620f51d4a692b51ab7) feat: `--debug` prints time it takes to parse a file (#15609) (Bartek Iwańczuk)
+* [`345e70d`](https://github.com/eslint/eslint/commit/345e70d9d6490fb12b18953f56f3cea28fd61d83) feat: Add `onlyOneSimpleParam` option to no-confusing-arrow rule (#15566) (Gautam Arora)
+* [`bfaa548`](https://github.com/eslint/eslint/commit/bfaa5488bbc794c0d160fb55bd277a2c618953b2) test: add integration tests with built-in configs (#15612) (Milos Djermanovic)
+* [`39a2fb3`](https://github.com/eslint/eslint/commit/39a2fb3f448a7096bfb2fc172fef6cc3f6a7ed3b) perf: fix lazy loading of core rules (#15606) (Milos Djermanovic)
+* [`3fc9196`](https://github.com/eslint/eslint/commit/3fc919626ef6a00e35bb6b559b60a1e89cf6ca1a) chore: include `tests/conf` in test runs (#15610) (Milos Djermanovic)
+* [`ee7c5d1`](https://github.com/eslint/eslint/commit/ee7c5d14a2cb5ce352d1851cec858b942572d2cc) fix: false positive in `camelcase` with combined properties (#15581) (Nitin Kumar)
+
 v8.9.0 - February 11, 2022
 
 * [`68f64a9`](https://github.com/eslint/eslint/commit/68f64a9218341e5e9d83270c72587e1b413846de) feat: update eslint-scope to ignore `"use strict"` directives in ES3 (#15595) (Milos Djermanovic)
diff --git a/README.md b/README.md
index de20af780..e513321c6 100644
--- a/README.md
+++ b/README.md
@@ -292,9 +292,9 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <!--sponsorsstart-->
 <h3>Platinum Sponsors</h3>
 <p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
-<p><a href="https://contra.com"><img src="https://images.opencollective.com/contra1/c70f93f/logo.png" alt="Contra" height="96"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="96"></a> <a href="https://google.com/chrome"><img src="https://images.opencollective.com/chrome/dc55bd4/logo.png" alt="Chrome's Web Framework & Tools Performance Fund" height="96"></a> <a href="https://www.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
+<p><a href="https://contra.com"><img src="https://images.opencollective.com/contra1/c70f93f/logo.png" alt="Contra" height="96"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="96"></a> <a href="https://www.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="96"></a> <a href="https://substack.com/"><img src="https://avatars.githubusercontent.com/u/53023767?v=4" alt="Substack" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://launchdarkly.com"><img src="https://images.opencollective.com/launchdarkly/574bb9e/logo.png" alt="launchdarkly" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Practice Ignition" height="32"></a></p>
+<p><a href="https://launchdarkly.com"><img src="https://images.opencollective.com/launchdarkly/574bb9e/logo.png" alt="launchdarkly" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
diff --git a/docs/developer-guide/contributing/README.md b/docs/developer-guide/contributing/README.md
index 25a889466..050953957 100644
--- a/docs/developer-guide/contributing/README.md
+++ b/docs/developer-guide/contributing/README.md
@@ -8,10 +8,6 @@ This guide is intended for anyone who wants to contribute to an ESLint project.
 
 ESLint welcomes contributions from everyone and adheres to the [OpenJS Foundation Code of Conduct](https://eslint.org/conduct). We kindly request that you read over our code of conduct before contributing.
 
-## [Signing the CLA](https://openjsf.org/about/the-openjs-foundation-cla/)
-
-In order to submit code or documentation to an ESLint project, you will need to electronically sign our [Contributor License Agreement](https://github.com/openjs-foundation/easycla). The CLA is the commonly used Apache-style template, and is you giving us permission to use your contribution. You only need to sign the CLA once for any OpenJS Foundation projects that use EasyCLA.
-
 ## [Bug Reporting](reporting-bugs)
 
 Think you found a problem? We'd love to hear about it. This section explains how to submit a bug, the type of information we need to properly verify it, and the overall process.
@@ -39,3 +35,7 @@ Have some extra time and want to contribute? This section talks about the proces
 ## Submitting a [Pull Request](pull-requests.md)
 
 We're always looking for contributions from the community. This section explains the requirements for pull requests and the process of contributing code.
+
+## Signing the CLA
+
+In order to submit code or documentation to an ESLint project, you will need to electronically sign our Contributor License Agreement. The CLA is the commonly used Apache-style template, and is you giving us permission to use your contribution. You only need to sign the CLA once for any OpenJS Foundation projects that use EasyCLA. You will be asked to sign the CLA in the first pull request you open.
diff --git a/docs/developer-guide/contributing/pull-requests.md b/docs/developer-guide/contributing/pull-requests.md
index e67f29669..b58d10500 100644
--- a/docs/developer-guide/contributing/pull-requests.md
+++ b/docs/developer-guide/contributing/pull-requests.md
@@ -6,7 +6,6 @@ If you want to contribute to an ESLint repo, please use a GitHub pull request. T
 
 If you'd like to work on a pull request and you've never submitted code before, follow these steps:
 
-1. Sign our [Contributor License Agreement](https://cla.js.foundation/eslint/eslint).
 1. Set up a [development environment](../development-environment.md).
 1. If you want to implement a breaking change or a change to the core, ensure there's an issue that describes what you're doing and the issue has been accepted. You can create a new issue or just indicate you're [working on an existing issue](working-on-issues.md). Bug fixes, documentation changes, and other pull requests do not require an issue.
 
@@ -137,6 +136,8 @@ git push -f origin issue1234
 
 Now you're ready to send the pull request. Go to your ESLint fork and then follow the [GitHub documentation](https://help.github.com/articles/creating-a-pull-request) on how to send a pull request.
 
+In order to submit code or documentation to an ESLint project, you’ll be asked to sign our CLA when you send your first pull request. (Read more about the Open JS Foundation CLA process at <https://cla.openjsf.org/>.)
+
 ## Following Up
 
 Once your pull request is sent, it's time for the team to review it. As such, please make sure to:
diff --git a/docs/rules/no-shadow.md b/docs/rules/no-shadow.md
index 605a0eb2d..284b7a1b9 100644
--- a/docs/rules/no-shadow.md
+++ b/docs/rules/no-shadow.md
@@ -44,11 +44,11 @@ if (true) {
 
 ## Options
 
-This rule takes one option, an object, with properties `"builtinGlobals"`, `"hoist"` and `"allow"`.
+This rule takes one option, an object, with properties `"builtinGlobals"`, `"hoist"`, `"allow"` and `"ignoreOnInitialization"`.
 
 ```json
 {
-    "no-shadow": ["error", { "builtinGlobals": false, "hoist": "functions", "allow": [] }]
+    "no-shadow": ["error", { "builtinGlobals": false, "hoist": "functions", "allow": [], "ignoreOnInitialization": false }]
 }
 ```
 
@@ -166,6 +166,34 @@ foo(function (err, result) {
 });
 ```
 
+### ignoreOnInitialization
+
+The `ignoreOnInitialization` option is `false` by default. If it is `true`, it prevents reporting shadowing of variables in their initializers when the shadowed variable is presumably still uninitialized.
+
+The shadowed variable must be on the left side. The shadowing variable must be on the right side and declared in a callback function or in an IIFE.
+
+Examples of **incorrect** code for the `{ "ignoreOnInitialization": "true" }` option:
+
+```js
+/*eslint no-shadow: ["error", { "ignoreOnInitialization": true }]*/
+
+var x = x => x;
+```
+
+Because the shadowing variable `x` will shadow the already initialized shadowed variable `x`.
+
+Examples of **correct** code for the `{ "ignoreOnInitialization": true }` option:
+
+```js
+/*eslint no-shadow: ["error", { "ignoreOnInitialization": true }]*/
+
+var x = foo(x => x)
+
+var y = (y => y)()
+```
+
+The rationale for callback functions is the assumption that they will be called during the initialization, so that at the time when the shadowing variable will be used, the shadowed variable has not yet been initialized.
+
 ## Related Rules
 
 * [no-shadow-restricted-names](no-shadow-restricted-names.md)
diff --git a/docs/rules/sort-imports.md b/docs/rules/sort-imports.md
index 087a008bb..5ba4509a2 100644
--- a/docs/rules/sort-imports.md
+++ b/docs/rules/sort-imports.md
@@ -7,6 +7,7 @@ The import statement is used to import members (functions, objects or primitives
 ```js
 // single - Import single member.
 import myMember from "my-module.js";
+import {myOtherMember} from "my-other-module.js";
 
 // multiple - Import multiple members.
 import {foo, bar} from "my-module.js";
@@ -72,7 +73,7 @@ import * as foo from 'foo.js';
 import {alpha, beta} from 'alpha.js';
 import {delta, gamma} from 'delta.js';
 import a from 'baz.js';
-import b from 'qux.js';
+import {b} from 'qux.js';
 
 /*eslint sort-imports: "error"*/
 import a from 'foo.js';
@@ -84,6 +85,7 @@ import 'foo.js'
 import * as bar from 'bar.js';
 import {a, b} from 'baz.js';
 import c from 'qux.js';
+import {d} from 'quux.js';
 
 /*eslint sort-imports: "error"*/
 import {a, b, c} from 'foo.js'
@@ -108,6 +110,10 @@ import {a, b} from 'bar.js';
 import a from 'foo.js';
 import {b, c} from 'bar.js';
 
+/*eslint sort-imports: "error"*/
+import {a} from 'foo.js';
+import {b, c} from 'bar.js';
+
 /*eslint sort-imports: "error"*/
 import a from 'foo.js';
 import * as b from 'bar.js';
diff --git a/lib/cli-engine/cli-engine.js b/lib/cli-engine/cli-engine.js
index 3ae8b685c..92b875578 100644
--- a/lib/cli-engine/cli-engine.js
+++ b/lib/cli-engine/cli-engine.js
@@ -616,8 +616,8 @@ class CLIEngine {
             useEslintrc: options.useEslintrc,
             builtInRules,
             loadRules,
-            eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
-            eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
+            getEslintRecommendedConfig: () => require("../../conf/eslint-recommended.js"),
+            getEslintAllConfig: () => require("../../conf/eslint-all.js")
         });
         const fileEnumerator = new FileEnumerator({
             configArrayFactory,
diff --git a/lib/cli-engine/file-enumerator.js b/lib/cli-engine/file-enumerator.js
index f1442d150..674e83e54 100644
--- a/lib/cli-engine/file-enumerator.js
+++ b/lib/cli-engine/file-enumerator.js
@@ -215,8 +215,8 @@ class FileEnumerator {
         cwd = process.cwd(),
         configArrayFactory = new CascadingConfigArrayFactory({
             cwd,
-            eslintRecommendedPath: path.resolve(__dirname, "../../conf/eslint-recommended.js"),
-            eslintAllPath: path.resolve(__dirname, "../../conf/eslint-all.js")
+            getEslintRecommendedConfig: () => require("../../conf/eslint-recommended.js"),
+            getEslintAllConfig: () => require("../../conf/eslint-all.js")
         }),
         extensions = null,
         globInputPaths = true,
diff --git a/lib/rules/comma-dangle.js b/lib/rules/comma-dangle.js
index 232b27cb3..063e1cb69 100644
--- a/lib/rules/comma-dangle.js
+++ b/lib/rules/comma-dangle.js
@@ -243,8 +243,18 @@ module.exports = {
                     node: lastItem,
                     loc: trailingToken.loc,
                     messageId: "unexpected",
-                    fix(fixer) {
-                        return fixer.remove(trailingToken);
+                    *fix(fixer) {
+                        yield fixer.remove(trailingToken);
+
+                        /*
+                         * Extend the range of the fix to include surrounding tokens to ensure
+                         * that the element after which the comma is removed stays _last_.
+                         * This intentionally makes conflicts in fix ranges with rules that may be
+                         * adding or removing elements in the same autofix pass.
+                         * https://github.com/eslint/eslint/issues/15660
+                         */
+                        yield fixer.insertTextBefore(sourceCode.getTokenBefore(trailingToken), "");
+                        yield fixer.insertTextAfter(sourceCode.getTokenAfter(trailingToken), "");
                     }
                 });
             }
@@ -282,8 +292,18 @@ module.exports = {
                         end: astUtils.getNextLocation(sourceCode, trailingToken.loc.end)
                     },
                     messageId: "missing",
-                    fix(fixer) {
-                        return fixer.insertTextAfter(trailingToken, ",");
+                    *fix(fixer) {
+                        yield fixer.insertTextAfter(trailingToken, ",");
+
+                        /*
+                         * Extend the range of the fix to include surrounding tokens to ensure
+                         * that the element after which the comma is inserted stays _last_.
+                         * This intentionally makes conflicts in fix ranges with rules that may be
+                         * adding or removing elements in the same autofix pass.
+                         * https://github.com/eslint/eslint/issues/15660
+                         */
+                        yield fixer.insertTextBefore(trailingToken, "");
+                        yield fixer.insertTextAfter(sourceCode.getTokenAfter(trailingToken), "");
                     }
                 });
             }
diff --git a/lib/rules/no-shadow.js b/lib/rules/no-shadow.js
index bd619235a..43d7d738e 100644
--- a/lib/rules/no-shadow.js
+++ b/lib/rules/no-shadow.js
@@ -11,6 +11,15 @@
 
 const astUtils = require("./utils/ast-utils");
 
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const FUNC_EXPR_NODE_TYPES = ["ArrowFunctionExpression", "FunctionExpression"];
+const CALL_EXPR_NODE_TYPE = ["CallExpression"];
+const FOR_IN_OF_TYPE = /^For(?:In|Of)Statement$/u;
+const SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/u;
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -37,7 +46,8 @@ module.exports = {
                         items: {
                             type: "string"
                         }
-                    }
+                    },
+                    ignoreOnInitialization: { type: "boolean", default: false }
                 },
                 additionalProperties: false
             }
@@ -54,9 +64,109 @@ module.exports = {
         const options = {
             builtinGlobals: context.options[0] && context.options[0].builtinGlobals,
             hoist: (context.options[0] && context.options[0].hoist) || "functions",
-            allow: (context.options[0] && context.options[0].allow) || []
+            allow: (context.options[0] && context.options[0].allow) || [],
+            ignoreOnInitialization: context.options[0] && context.options[0].ignoreOnInitialization
         };
 
+        /**
+         * Checks whether or not a given location is inside of the range of a given node.
+         * @param {ASTNode} node An node to check.
+         * @param {number} location A location to check.
+         * @returns {boolean} `true` if the location is inside of the range of the node.
+         */
+        function isInRange(node, location) {
+            return node && node.range[0] <= location && location <= node.range[1];
+        }
+
+        /**
+         * Searches from the current node through its ancestry to find a matching node.
+         * @param {ASTNode} node a node to get.
+         * @param {(node: ASTNode) => boolean} match a callback that checks whether or not the node verifies its condition or not.
+         * @returns {ASTNode|null} the matching node.
+         */
+        function findSelfOrAncestor(node, match) {
+            let currentNode = node;
+
+            while (currentNode && !match(currentNode)) {
+                currentNode = currentNode.parent;
+            }
+            return currentNode;
+        }
+
+        /**
+         * Finds function's outer scope.
+         * @param {Scope} scope Function's own scope.
+         * @returns {Scope} Function's outer scope.
+         */
+        function getOuterScope(scope) {
+            const upper = scope.upper;
+
+            if (upper.type === "function-expression-name") {
+                return upper.upper;
+            }
+            return upper;
+        }
+
+        /**
+         * Checks if a variable and a shadowedVariable have the same init pattern ancestor.
+         * @param {Object} variable a variable to check.
+         * @param {Object} shadowedVariable a shadowedVariable to check.
+         * @returns {boolean} Whether or not the variable and the shadowedVariable have the same init pattern ancestor.
+         */
+        function isInitPatternNode(variable, shadowedVariable) {
+            const outerDef = shadowedVariable.defs[0];
+
+            if (!outerDef) {
+                return false;
+            }
+
+            const { variableScope } = variable.scope;
+
+
+            if (!(FUNC_EXPR_NODE_TYPES.includes(variableScope.block.type) && getOuterScope(variableScope) === shadowedVariable.scope)) {
+                return false;
+            }
+
+            const fun = variableScope.block;
+            const { parent } = fun;
+
+            const callExpression = findSelfOrAncestor(
+                parent,
+                node => CALL_EXPR_NODE_TYPE.includes(node.type)
+            );
+
+            if (!callExpression) {
+                return false;
+            }
+
+            let node = outerDef.name;
+            const location = callExpression.range[1];
+
+            while (node) {
+                if (node.type === "VariableDeclarator") {
+                    if (isInRange(node.init, location)) {
+                        return true;
+                    }
+                    if (FOR_IN_OF_TYPE.test(node.parent.parent.type) &&
+                        isInRange(node.parent.parent.right, location)
+                    ) {
+                        return true;
+                    }
+                    break;
+                } else if (node.type === "AssignmentPattern") {
+                    if (isInRange(node.right, location)) {
+                        return true;
+                    }
+                } else if (SENTINEL_TYPE.test(node.type)) {
+                    break;
+                }
+
+                node = node.parent;
+            }
+
+            return false;
+        }
+
         /**
          * Check if variable name is allowed.
          * @param {ASTNode} variable The variable to check.
@@ -99,11 +209,11 @@ module.exports = {
 
             return (
                 outer &&
-                inner &&
-                outer[0] < inner[0] &&
-                inner[1] < outer[1] &&
-                ((innerDef.type === "FunctionName" && innerDef.node.type === "FunctionExpression") || innerDef.node.type === "ClassExpression") &&
-                outerScope === innerScope.upper
+                 inner &&
+                 outer[0] < inner[0] &&
+                 inner[1] < outer[1] &&
+                 ((innerDef.type === "FunctionName" && innerDef.node.type === "FunctionExpression") || innerDef.node.type === "ClassExpression") &&
+                 outerScope === innerScope.upper
             );
         }
 
@@ -154,11 +264,11 @@ module.exports = {
 
             return (
                 inner &&
-                outer &&
-                inner[1] < outer[0] &&
+                 outer &&
+                 inner[1] < outer[0] &&
 
-                // Excepts FunctionDeclaration if is {"hoist":"function"}.
-                (options.hoist !== "functions" || !outerDef || outerDef.node.type !== "FunctionDeclaration")
+                 // Excepts FunctionDeclaration if is {"hoist":"function"}.
+                 (options.hoist !== "functions" || !outerDef || outerDef.node.type !== "FunctionDeclaration")
             );
         }
 
@@ -175,8 +285,8 @@ module.exports = {
 
                 // Skips "arguments" or variables of a class name in the class scope of ClassDeclaration.
                 if (variable.identifiers.length === 0 ||
-                    isDuplicatedClassNameVariable(variable) ||
-                    isAllowed(variable)
+                     isDuplicatedClassNameVariable(variable) ||
+                     isAllowed(variable)
                 ) {
                     continue;
                 }
@@ -185,9 +295,10 @@ module.exports = {
                 const shadowed = astUtils.getVariableByName(scope.upper, variable.name);
 
                 if (shadowed &&
-                    (shadowed.identifiers.length > 0 || (options.builtinGlobals && "writeable" in shadowed)) &&
-                    !isOnInitializer(variable, shadowed) &&
-                    !(options.hoist !== "all" && isInTdz(variable, shadowed))
+                      (shadowed.identifiers.length > 0 || (options.builtinGlobals && "writeable" in shadowed)) &&
+                      !isOnInitializer(variable, shadowed) &&
+                      !(options.ignoreOnInitialization && isInitPatternNode(variable, shadowed)) &&
+                      !(options.hoist !== "all" && isInTdz(variable, shadowed))
                 ) {
                     const location = getDeclaredLocation(shadowed);
                     const messageId = location.global ? "noShadowGlobal" : "noShadow";
diff --git a/lib/rules/valid-typeof.js b/lib/rules/valid-typeof.js
index 604635812..cb85cd9cb 100644
--- a/lib/rules/valid-typeof.js
+++ b/lib/rules/valid-typeof.js
@@ -19,6 +19,8 @@ module.exports = {
             url: "https://eslint.org/docs/rules/valid-typeof"
         },
 
+        hasSuggestions: true,
+
         schema: [
             {
                 type: "object",
@@ -33,7 +35,8 @@ module.exports = {
         ],
         messages: {
             invalidValue: "Invalid typeof comparison value.",
-            notString: "Typeof comparisons should be to string literals."
+            notString: "Typeof comparisons should be to string literals.",
+            suggestString: 'Use `"{{type}}"` instead of `{{type}}`.'
         }
     },
 
@@ -44,6 +47,21 @@ module.exports = {
 
         const requireStringLiterals = context.options[0] && context.options[0].requireStringLiterals;
 
+        let globalScope;
+
+        /**
+         * Checks whether the given node represents a reference to a global variable that is not declared in the source code.
+         * These identifiers will be allowed, as it is assumed that user has no control over the names of external global variables.
+         * @param {ASTNode} node `Identifier` node to check.
+         * @returns {boolean} `true` if the node is a reference to a global variable.
+         */
+        function isReferenceToGlobalVariable(node) {
+            const variable = globalScope.set.get(node.name);
+
+            return variable && variable.defs.length === 0 &&
+                variable.references.some(ref => ref.identifier === node);
+        }
+
         /**
          * Determines whether a node is a typeof expression.
          * @param {ASTNode} node The node
@@ -59,6 +77,10 @@ module.exports = {
 
         return {
 
+            Program() {
+                globalScope = context.getScope();
+            },
+
             UnaryExpression(node) {
                 if (isTypeofExpression(node)) {
                     const parent = context.getAncestors().pop();
@@ -72,6 +94,20 @@ module.exports = {
                             if (VALID_TYPES.indexOf(value) === -1) {
                                 context.report({ node: sibling, messageId: "invalidValue" });
                             }
+                        } else if (sibling.type === "Identifier" && sibling.name === "undefined" && isReferenceToGlobalVariable(sibling)) {
+                            context.report({
+                                node: sibling,
+                                messageId: requireStringLiterals ? "notString" : "invalidValue",
+                                suggest: [
+                                    {
+                                        messageId: "suggestString",
+                                        data: { type: "undefined" },
+                                        fix(fixer) {
+                                            return fixer.replaceText(sibling, '"undefined"');
+                                        }
+                                    }
+                                ]
+                            });
                         } else if (requireStringLiterals && !isTypeofExpression(sibling)) {
                             context.report({ node: sibling, messageId: "notString" });
                         }
diff --git a/package.json b/package.json
index b5dd76432..424b5b777 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "8.9.0",
+  "version": "8.10.0",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
@@ -47,7 +47,7 @@
   "homepage": "https://eslint.org",
   "bugs": "https://github.com/eslint/eslint/issues/",
   "dependencies": {
-    "@eslint/eslintrc": "^1.1.0",
+    "@eslint/eslintrc": "^1.2.0",
     "@humanwhocodes/config-array": "^0.9.2",
     "ajv": "^6.10.0",
     "chalk": "^4.0.0",


Test patch:
diff --git a/tests/lib/rules/comma-dangle.js b/tests/lib/rules/comma-dangle.js
index 2ef7a008e..b02a74a55 100644
--- a/tests/lib/rules/comma-dangle.js
+++ b/tests/lib/rules/comma-dangle.js
@@ -10,6 +10,7 @@
 //------------------------------------------------------------------------------
 
 const path = require("path"),
+    { unIndent } = require("../../_utils"),
     rule = require("../../../lib/rules/comma-dangle"),
     { RuleTester } = require("../../../lib/rule-tester");
 
@@ -35,6 +36,29 @@ function parser(name) {
 
 const ruleTester = new RuleTester();
 
+ruleTester.defineRule("add-named-import", {
+    meta: {
+        fixable: "code"
+    },
+    create(context) {
+        return {
+            ImportDeclaration(node) {
+                const sourceCode = context.getSourceCode();
+                const closingBrace = sourceCode.getLastToken(node, token => token.value === "}");
+                const addComma = sourceCode.getTokenBefore(closingBrace).value !== ",";
+
+                context.report({
+                    message: "Add I18nManager.",
+                    node,
+                    fix(fixer) {
+                        return fixer.insertTextBefore(closingBrace, `${addComma ? "," : ""}I18nManager`);
+                    }
+                });
+            }
+        };
+    }
+});
+
 ruleTester.run("comma-dangle", rule, {
     valid: [
         "var foo = { bar: 'baz' }",
@@ -1766,6 +1790,66 @@ let d = 0;export {d,};
             output: "foo(a)",
             parserOptions: { ecmaVersion: 8 },
             errors: [{ messageId: "unexpected" }]
+        },
+
+        // https://github.com/eslint/eslint/issues/15660
+        {
+            code: unIndent`
+                /*eslint add-named-import:1*/
+                import {
+                    StyleSheet,
+                    View,
+                    TextInput,
+                    ImageBackground,
+                    Image,
+                    TouchableOpacity,
+                    SafeAreaView
+                } from 'react-native';
+            `,
+            output: unIndent`
+                /*eslint add-named-import:1*/
+                import {
+                    StyleSheet,
+                    View,
+                    TextInput,
+                    ImageBackground,
+                    Image,
+                    TouchableOpacity,
+                    SafeAreaView,
+                } from 'react-native';
+            `,
+            options: [{ imports: "always-multiline" }],
+            parserOptions: { ecmaVersion: 6, sourceType: "module" },
+            errors: 2
+        },
+        {
+            code: unIndent`
+                /*eslint add-named-import:1*/
+                import {
+                    StyleSheet,
+                    View,
+                    TextInput,
+                    ImageBackground,
+                    Image,
+                    TouchableOpacity,
+                    SafeAreaView,
+                } from 'react-native';
+            `,
+            output: unIndent`
+                /*eslint add-named-import:1*/
+                import {
+                    StyleSheet,
+                    View,
+                    TextInput,
+                    ImageBackground,
+                    Image,
+                    TouchableOpacity,
+                    SafeAreaView
+                } from 'react-native';
+            `,
+            options: [{ imports: "never" }],
+            parserOptions: { ecmaVersion: 6, sourceType: "module" },
+            errors: 2
         }
     ]
 });
diff --git a/tests/lib/rules/no-shadow.js b/tests/lib/rules/no-shadow.js
index 13c4c1100..0afcc3ff3 100644
--- a/tests/lib/rules/no-shadow.js
+++ b/tests/lib/rules/no-shadow.js
@@ -63,7 +63,35 @@ ruleTester.run("no-shadow", rule, {
         { code: "class C { static { let x; } static { let x; } }", parserOptions: { ecmaVersion: 2022 } },
         { code: "class C { static { var x; { var x; /* redeclaration */ } } }", parserOptions: { ecmaVersion: 2022 } },
         { code: "class C { static { { var x; } { var x; /* redeclaration */ } } }", parserOptions: { ecmaVersion: 2022 } },
-        { code: "class C { static { { let x; } { let x; } } }", parserOptions: { ecmaVersion: 2022 } }
+        { code: "class C { static { { let x; } { let x; } } }", parserOptions: { ecmaVersion: 2022 } },
+        { code: "const a = [].find(a => a)", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const a = [].find(function(a) { return a; })", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const [a = [].find(a => true)] = dummy", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const { a = [].find(a => true) } = dummy", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "function func(a = [].find(a => true)) {}", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "for (const a in [].find(a => true)) {}", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "for (const a of [].find(a => true)) {}", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const a = [].map(a => true).filter(a => a === 'b')", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const a = [].map(a => true).filter(a => a === 'b').find(a => a === 'c')", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const { a } = (({ a }) => ({ a }))();", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const person = people.find(item => {const person = item.name; return person === 'foo'})", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var y = bar || foo(y => y);", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var y = bar && foo(y => y);", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var z = bar(foo(z => z));", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var z = boo(bar(foo(z => z)));", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var match = function (person) { return person.name === 'foo'; };\nconst person = [].find(match);", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const a = foo(x || (a => {}))", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const { a = 1 } = foo(a => {})", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const person = {...people.find((person) => person.firstName.startsWith('s'))}", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 2021 } },
+        { code: "const person = { firstName: people.filter((person) => person.firstName.startsWith('s')).map((person) => person.firstName)[0]}", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 2021 } },
+        { code: "() => { const y = foo(y => y); }", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const x = (x => x)()", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var y = bar || (y => y)();", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var y = bar && (y => y)();", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "var x = (x => x)((y => y)());", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const { a = 1 } = (a => {})()", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "() => { const y = (y => y)(); }", options: [{ ignoreOnInitialization: true }], parserOptions: { ecmaVersion: 6 } },
+        { code: "const [x = y => y] = [].map(y => y)", parserOptions: { ecmaVersion: 6 } }
     ],
     invalid: [
         {
@@ -859,6 +887,232 @@ ruleTester.run("no-shadow", rule, {
                 line: 1,
                 column: 50
             }]
+        },
+        {
+            code: "let x = foo((x,y) => {});\nlet y;",
+            options: [{ hoist: "all" }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "noShadow",
+                    data: {
+                        name: "x",
+                        shadowedLine: 1,
+                        shadowedColumn: 5
+                    },
+                    type: "Identifier"
+                },
+                {
+                    messageId: "noShadow",
+                    data: {
+                        name: "y",
+                        shadowedLine: 2,
+                        shadowedColumn: 5
+                    },
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: "const a = fn(()=>{ class C { fn () { const a = 42; return a } } return new C() })",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "a",
+                    shadowedLine: 1,
+                    shadowedColumn: 7
+                },
+                type: "Identifier",
+                line: 1,
+                column: 44
+            }]
+        },
+        {
+            code: "function a() {}\nfoo(a => {});",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "a",
+                    shadowedLine: 1,
+                    shadowedColumn: 10
+                },
+                type: "Identifier",
+                line: 2,
+                column: 5
+            }]
+        },
+        {
+            code: "const a = fn(()=>{ function C() { this.fn=function() { const a = 42; return a } } return new C() });",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "a",
+                    shadowedLine: 1,
+                    shadowedColumn: 7
+                },
+                type: "Identifier",
+                line: 1,
+                column: 62
+            }]
+        },
+        {
+            code: "const x = foo(() => { const bar = () => { return x => {}; }; return bar; });",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "x",
+                    shadowedLine: 1,
+                    shadowedColumn: 7
+                },
+                type: "Identifier",
+                line: 1,
+                column: 50
+            }]
+        },
+        {
+            code: "const x = foo(() => { return { bar(x) {} }; });",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "x",
+                    shadowedLine: 1,
+                    shadowedColumn: 7
+                },
+                type: "Identifier",
+                line: 1,
+                column: 36
+            }]
+        },
+        {
+            code: "const x = () => { foo(x => x); }",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "x",
+                    shadowedLine: 1,
+                    shadowedColumn: 7
+                },
+                type: "Identifier",
+                line: 1,
+                column: 23
+            }]
+        },
+        {
+            code: "const foo = () => { let x; bar(x => x); }",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "x",
+                    shadowedLine: 1,
+                    shadowedColumn: 25
+                },
+                type: "Identifier",
+                line: 1,
+                column: 32
+            }]
+        },
+        {
+            code: "foo(() => { const x = x => x; });",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "x",
+                    shadowedLine: 1,
+                    shadowedColumn: 19
+                },
+                type: "Identifier",
+                line: 1,
+                column: 23
+            }]
+        },
+        {
+            code: "const foo = (x) => { bar(x => {}) }",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "x",
+                    shadowedLine: 1,
+                    shadowedColumn: 14
+                },
+                type: "Identifier",
+                line: 1,
+                column: 26
+            }]
+        },
+        {
+            code: "let x = ((x,y) => {})();\nlet y;",
+            options: [{ hoist: "all" }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "noShadow",
+                    data: {
+                        name: "x",
+                        shadowedLine: 1,
+                        shadowedColumn: 5
+                    },
+                    type: "Identifier"
+                },
+                {
+                    messageId: "noShadow",
+                    data: {
+                        name: "y",
+                        shadowedLine: 2,
+                        shadowedColumn: 5
+                    },
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: "const a = (()=>{ class C { fn () { const a = 42; return a } } return new C() })()",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "a",
+                    shadowedLine: 1,
+                    shadowedColumn: 7
+                },
+                type: "Identifier",
+                line: 1,
+                column: 42
+            }]
+        },
+        {
+            code: "const x = () => { (x => x)(); }",
+            options: [{ ignoreOnInitialization: true }],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "noShadow",
+                data: {
+                    name: "x",
+                    shadowedLine: 1,
+                    shadowedColumn: 7
+                },
+                type: "Identifier",
+                line: 1,
+                column: 20
+            }]
         }
     ]
 });
diff --git a/tests/lib/rules/valid-typeof.js b/tests/lib/rules/valid-typeof.js
index cd28088a0..35a52f0a6 100644
--- a/tests/lib/rules/valid-typeof.js
+++ b/tests/lib/rules/valid-typeof.js
@@ -45,6 +45,7 @@ ruleTester.run("valid-typeof", rule, {
         "typeof(foo) == 'string'",
         "typeof(foo) != 'string'",
         "var oddUse = typeof foo + 'thing'",
+        "function f(undefined) { typeof x === undefined }",
         {
             code: "typeof foo === 'number'",
             options: [{ requireStringLiterals: true }]
@@ -136,6 +137,21 @@ ruleTester.run("valid-typeof", rule, {
             options: [{ requireStringLiterals: true }],
             errors: [{ messageId: "invalidValue", type: "Literal" }]
         },
+        {
+            code: "if (typeof bar !== undefined) {}",
+            errors: [
+                {
+                    messageId: "invalidValue",
+                    type: "Identifier",
+                    suggestions: [
+                        {
+                            messageId: "suggestString",
+                            data: { type: "undefined" },
+                            output: 'if (typeof bar !== "undefined") {}'
+                        }
+                    ]
+                }]
+        },
         {
             code: "typeof foo == Object",
             options: [{ requireStringLiterals: true }],
@@ -144,17 +160,50 @@ ruleTester.run("valid-typeof", rule, {
         {
             code: "typeof foo === undefined",
             options: [{ requireStringLiterals: true }],
-            errors: [{ messageId: "notString", type: "Identifier" }]
+            errors: [
+                {
+                    messageId: "notString",
+                    type: "Identifier",
+                    suggestions: [
+                        {
+                            messageId: "suggestString",
+                            data: { type: "undefined" },
+                            output: 'typeof foo === "undefined"'
+                        }
+                    ]
+                }]
         },
         {
             code: "undefined === typeof foo",
             options: [{ requireStringLiterals: true }],
-            errors: [{ messageId: "notString", type: "Identifier" }]
+            errors: [
+                {
+                    messageId: "notString",
+                    type: "Identifier",
+                    suggestions: [
+                        {
+                            messageId: "suggestString",
+                            data: { type: "undefined" },
+                            output: '"undefined" === typeof foo'
+                        }
+                    ]
+                }]
         },
         {
             code: "undefined == typeof foo",
             options: [{ requireStringLiterals: true }],
-            errors: [{ messageId: "notString", type: "Identifier" }]
+            errors: [
+                {
+                    messageId: "notString",
+                    type: "Identifier",
+                    suggestions: [
+                        {
+                            messageId: "suggestString",
+                            data: { type: "undefined" },
+                            output: '"undefined" == typeof foo'
+                        }
+                    ]
+                }]
         },
         {
             code: "typeof foo === `undefined${foo}`",