]> git.proxmox.com Git - pve-eslint.git/commitdiff
upgrade to v7.0.0
authorDominik Csapak <d.csapak@proxmox.com>
Fri, 22 May 2020 11:37:30 +0000 (13:37 +0200)
committerDominik Csapak <d.csapak@proxmox.com>
Fri, 22 May 2020 11:50:35 +0000 (13:50 +0200)
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
123 files changed:
Makefile
eslint/.eslintrc.js
eslint/.github/workflows/ci.yml
eslint/CHANGELOG.md
eslint/Makefile.js
eslint/README.md
eslint/bin/eslint.js
eslint/conf/category-list.json
eslint/docs/developer-guide/nodejs-api.md
eslint/docs/rules/array-callback-return.md
eslint/docs/rules/callback-return.md
eslint/docs/rules/curly.md
eslint/docs/rules/global-require.md
eslint/docs/rules/handle-callback-err.md
eslint/docs/rules/no-buffer-constructor.md
eslint/docs/rules/no-inner-declarations.md
eslint/docs/rules/no-mixed-requires.md
eslint/docs/rules/no-new-object.md
eslint/docs/rules/no-new-require.md
eslint/docs/rules/no-path-concat.md
eslint/docs/rules/no-process-env.md
eslint/docs/rules/no-process-exit.md
eslint/docs/rules/no-restricted-modules.md
eslint/docs/rules/no-return-assign.md
eslint/docs/rules/no-sync.md
eslint/docs/rules/object-curly-newline.md
eslint/docs/rules/prefer-rest-params.md
eslint/docs/rules/spaced-comment.md
eslint/docs/user-guide/README.md
eslint/docs/user-guide/migrating-to-7.0.0.md [new file with mode: 0644]
eslint/lib/api.js
eslint/lib/cli-engine/cascading-config-array-factory.js
eslint/lib/cli-engine/cli-engine.js
eslint/lib/cli-engine/config-array-factory.js
eslint/lib/cli-engine/config-array/config-array.js
eslint/lib/cli-engine/config-array/ignore-pattern.js
eslint/lib/cli.js
eslint/lib/eslint/eslint.js [new file with mode: 0644]
eslint/lib/eslint/index.js [new file with mode: 0644]
eslint/lib/init/autoconfig.js
eslint/lib/init/config-initializer.js
eslint/lib/init/source-code-utils.js
eslint/lib/options.js
eslint/lib/rule-tester/rule-tester.js
eslint/lib/rules/array-callback-return.js
eslint/lib/rules/callback-return.js
eslint/lib/rules/comma-style.js
eslint/lib/rules/func-call-spacing.js
eslint/lib/rules/getter-return.js
eslint/lib/rules/global-require.js
eslint/lib/rules/handle-callback-err.js
eslint/lib/rules/key-spacing.js
eslint/lib/rules/new-cap.js
eslint/lib/rules/newline-per-chained-call.js
eslint/lib/rules/no-buffer-constructor.js
eslint/lib/rules/no-empty-function.js
eslint/lib/rules/no-extra-parens.js
eslint/lib/rules/no-inner-declarations.js
eslint/lib/rules/no-lone-blocks.js
eslint/lib/rules/no-mixed-requires.js
eslint/lib/rules/no-new-object.js
eslint/lib/rules/no-new-require.js
eslint/lib/rules/no-path-concat.js
eslint/lib/rules/no-process-env.js
eslint/lib/rules/no-process-exit.js
eslint/lib/rules/no-restricted-modules.js
eslint/lib/rules/no-sync.js
eslint/lib/rules/no-unexpected-multiline.js
eslint/lib/rules/no-useless-concat.js
eslint/lib/rules/space-before-function-paren.js
eslint/lib/rules/yoda.js
eslint/lib/shared/relative-module-resolver.js
eslint/lib/shared/types.js
eslint/package.json
eslint/tests/_utils/in-memory-fs.js [new file with mode: 0644]
eslint/tests/_utils/index.js [new file with mode: 0644]
eslint/tests/bench/large.js
eslint/tests/bench/small.js
eslint/tests/bin/eslint.js
eslint/tests/fixtures/fix-types/ignore-missing-meta.expected.js
eslint/tests/fixtures/fix-types/ignore-missing-meta.js
eslint/tests/lib/_utils.js [deleted file]
eslint/tests/lib/cli-engine/_utils.js [deleted file]
eslint/tests/lib/cli-engine/cascading-config-array-factory.js
eslint/tests/lib/cli-engine/cli-engine.js
eslint/tests/lib/cli-engine/config-array-factory.js
eslint/tests/lib/cli-engine/config-array/ignore-pattern.js
eslint/tests/lib/cli-engine/file-enumerator.js
eslint/tests/lib/cli.js
eslint/tests/lib/eslint/eslint.js [new file with mode: 0644]
eslint/tests/lib/init/autoconfig.js
eslint/tests/lib/init/config-initializer.js
eslint/tests/lib/init/npm-utils.js
eslint/tests/lib/linter/code-path-analysis/code-path.js
eslint/tests/lib/linter/linter.js
eslint/tests/lib/options.js
eslint/tests/lib/rule-tester/rule-tester.js
eslint/tests/lib/rules/array-bracket-newline.js
eslint/tests/lib/rules/array-callback-return.js
eslint/tests/lib/rules/array-element-newline.js
eslint/tests/lib/rules/comma-style.js
eslint/tests/lib/rules/func-call-spacing.js
eslint/tests/lib/rules/getter-return.js
eslint/tests/lib/rules/id-blacklist.js
eslint/tests/lib/rules/implicit-arrow-linebreak.js
eslint/tests/lib/rules/indent.js
eslint/tests/lib/rules/keyword-spacing.js
eslint/tests/lib/rules/new-cap.js
eslint/tests/lib/rules/newline-per-chained-call.js
eslint/tests/lib/rules/no-empty-function.js
eslint/tests/lib/rules/no-extra-parens.js
eslint/tests/lib/rules/no-implied-eval.js
eslint/tests/lib/rules/no-inner-declarations.js
eslint/tests/lib/rules/no-new-object.js
eslint/tests/lib/rules/no-return-assign.js
eslint/tests/lib/rules/no-unexpected-multiline.js
eslint/tests/lib/rules/no-useless-concat.js
eslint/tests/lib/rules/object-shorthand.js
eslint/tests/lib/rules/space-before-function-paren.js
eslint/tests/lib/rules/yoda.js
eslint/tests/lib/shared/runtime-info.js
eslint/tests/performance/jshint.js
src/eslint.js

index 147b4d4be850b37eae1baed93a7e77928c11b6ab..05bc8e07aa4a54eed31af4a4785a78c289619f58 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ DSC=${PACKAGE}_${DEB_VERSION_UPSTREAM_REVISION}.dsc
 
 SRCDIR=src
 UPSTREAM=eslint
-UPSTREAMTAG=v7.0.0-alpha.3
+UPSTREAMTAG=v7.0.0
 BUILDSRC=${UPSTREAM}-${UPSTREAMTAG}
 
 all: ${DEB}
index 6ab4510cb37c785c06a34723312e9851637bc24a..a53fedba15b9df2edf6a2add43aa4d75dc242262 100644 (file)
@@ -1,13 +1,44 @@
 "use strict";
 
-const internalFiles = [
-    "**/cli-engine/**/*",
-    "**/init/**/*",
-    "**/linter/**/*",
-    "**/rule-tester/**/*",
-    "**/rules/**/*",
-    "**/source-code/**/*"
-];
+const path = require("path");
+
+const INTERNAL_FILES = {
+    CLI_ENGINE_PATTERN: "lib/cli-engine/**/*",
+    INIT_PATTERN: "lib/init/**/*",
+    LINTER_PATTERN: "lib/linter/**/*",
+    RULE_TESTER_PATTERN: "lib/rule-tester/**/*",
+    RULES_PATTERN: "lib/rules/**/*",
+    SOURCE_CODE_PATTERN: "lib/source-code/**/*"
+};
+
+/**
+ * Resolve an absolute path or glob pattern.
+ * @param {string} pathOrPattern the path or glob pattern.
+ * @returns {string} The resolved path or glob pattern.
+ */
+function resolveAbsolutePath(pathOrPattern) {
+    return path.resolve(__dirname, pathOrPattern);
+}
+
+/**
+ * Create an array of `no-restricted-require` entries for ESLint's core files.
+ * @param {string} [pattern] The glob pattern to create the entries for.
+ * @returns {Object[]} The array of `no-restricted-require` entries.
+ */
+function createInternalFilesPatterns(pattern = null) {
+    return Object.values(INTERNAL_FILES)
+        .filter(p => p !== pattern)
+        .map(p => ({
+            name: [
+
+                // Disallow all children modules.
+                resolveAbsolutePath(p),
+
+                // Allow the main `index.js` module.
+                `!${resolveAbsolutePath(p.replace(/\*\*\/\*$/u, "index.js"))}`
+            ]
+        }));
+}
 
 module.exports = {
     root: true,
@@ -22,6 +53,16 @@ module.exports = {
     parserOptions: {
         ecmaVersion: 2020
     },
+
+    /*
+     * it fixes eslint-plugin-jsdoc's reports: "Invalid JSDoc tag name "template" jsdoc/check-tag-names"
+     * refs: https://github.com/gajus/eslint-plugin-jsdoc#check-tag-names
+     */
+    settings: {
+        jsdoc: {
+            mode: "typescript"
+        }
+    },
     rules: {
         "eslint-plugin/consistent-output": "error",
         "eslint-plugin/no-deprecated-context-methods": "error",
@@ -84,106 +125,90 @@ module.exports = {
         {
             files: ["lib/*"],
             rules: {
-                "no-restricted-modules": ["error", {
-                    patterns: [
-                        ...internalFiles
-                    ]
-                }]
+                "node/no-restricted-require": ["error", [
+                    ...createInternalFilesPatterns()
+                ]]
             }
         },
         {
-            files: ["lib/cli-engine/**/*"],
+            files: [INTERNAL_FILES.CLI_ENGINE_PATTERN],
             rules: {
-                "no-restricted-modules": ["error", {
-                    patterns: [
-                        ...internalFiles,
-                        "**/init"
-                    ]
-                }]
+                "node/no-restricted-require": ["error", [
+                    ...createInternalFilesPatterns(INTERNAL_FILES.CLI_ENGINE_PATTERN),
+                    resolveAbsolutePath("lib/init/index.js")
+                ]]
             }
         },
         {
-            files: ["lib/init/**/*"],
+            files: [INTERNAL_FILES.INIT_PATTERN],
             rules: {
-                "no-restricted-modules": ["error", {
-                    patterns: [
-                        ...internalFiles,
-                        "**/rule-tester"
-                    ]
-                }]
+                "node/no-restricted-require": ["error", [
+                    ...createInternalFilesPatterns(INTERNAL_FILES.INIT_PATTERN),
+                    resolveAbsolutePath("lib/rule-tester/index.js")
+                ]]
             }
         },
         {
-            files: ["lib/linter/**/*"],
+            files: [INTERNAL_FILES.LINTER_PATTERN],
             rules: {
-                "no-restricted-modules": ["error", {
-                    patterns: [
-                        ...internalFiles,
-                        "fs",
-                        "**/cli-engine",
-                        "**/init",
-                        "**/rule-tester"
-                    ]
-                }]
+                "node/no-restricted-require": ["error", [
+                    ...createInternalFilesPatterns(INTERNAL_FILES.LINTER_PATTERN),
+                    "fs",
+                    resolveAbsolutePath("lib/cli-engine/index.js"),
+                    resolveAbsolutePath("lib/init/index.js"),
+                    resolveAbsolutePath("lib/rule-tester/index.js")
+                ]]
             }
         },
         {
-            files: ["lib/rules/**/*"],
+            files: [INTERNAL_FILES.RULES_PATTERN],
             rules: {
-                "no-restricted-modules": ["error", {
-                    patterns: [
-                        ...internalFiles,
-                        "fs",
-                        "**/cli-engine",
-                        "**/init",
-                        "**/linter",
-                        "**/rule-tester",
-                        "**/source-code"
-                    ]
-                }]
+                "node/no-restricted-require": ["error", [
+                    ...createInternalFilesPatterns(INTERNAL_FILES.RULES_PATTERN),
+                    "fs",
+                    resolveAbsolutePath("lib/cli-engine/index.js"),
+                    resolveAbsolutePath("lib/init/index.js"),
+                    resolveAbsolutePath("lib/linter/index.js"),
+                    resolveAbsolutePath("lib/rule-tester/index.js"),
+                    resolveAbsolutePath("lib/source-code/index.js")
+                ]]
             }
         },
         {
             files: ["lib/shared/**/*"],
             rules: {
-                "no-restricted-modules": ["error", {
-                    patterns: [
-                        ...internalFiles,
-                        "**/cli-engine",
-                        "**/init",
-                        "**/linter",
-                        "**/rule-tester",
-                        "**/source-code"
-                    ]
-                }]
+                "node/no-restricted-require": ["error", [
+                    ...createInternalFilesPatterns(),
+                    resolveAbsolutePath("lib/cli-engine/index.js"),
+                    resolveAbsolutePath("lib/init/index.js"),
+                    resolveAbsolutePath("lib/linter/index.js"),
+                    resolveAbsolutePath("lib/rule-tester/index.js"),
+                    resolveAbsolutePath("lib/source-code/index.js")
+                ]]
             }
         },
         {
-            files: ["lib/source-code/**/*"],
+            files: [INTERNAL_FILES.SOURCE_CODE_PATTERN],
             rules: {
-                "no-restricted-modules": ["error", {
-                    patterns: [
-                        ...internalFiles,
-                        "fs",
-                        "**/cli-engine",
-                        "**/init",
-                        "**/linter",
-                        "**/rule-tester",
-                        "**/rules"
-                    ]
-                }]
+                "node/no-restricted-require": ["error", [
+                    ...createInternalFilesPatterns(INTERNAL_FILES.SOURCE_CODE_PATTERN),
+                    "fs",
+                    resolveAbsolutePath("lib/cli-engine/index.js"),
+                    resolveAbsolutePath("lib/init/index.js"),
+                    resolveAbsolutePath("lib/linter/index.js"),
+                    resolveAbsolutePath("lib/rule-tester/index.js"),
+                    resolveAbsolutePath("lib/rules/index.js")
+                ]]
             }
         },
         {
-            files: ["lib/rule-tester/**/*"],
+            files: [INTERNAL_FILES.RULE_TESTER_PATTERN],
             rules: {
-                "no-restricted-modules": ["error", {
-                    patterns: [
-                        ...internalFiles,
-                        "**/cli-engine",
-                        "**/init"
-                    ]
-                }]
+                "node/no-restricted-require": ["error", [
+                    ...createInternalFilesPatterns(INTERNAL_FILES.RULE_TESTER_PATTERN),
+                    resolveAbsolutePath("lib/cli-engine/index.js"),
+                    resolveAbsolutePath("lib/init/index.js")
+                ]]
             }
         }
     ]
index f1da88295bf4b8ed5ec6eec85b875eeed3a36a7b..2674b575c05f3af1fb76172d76faf84210ba1ada 100644 (file)
@@ -25,21 +25,13 @@ jobs:
     name: Test
     strategy:
       matrix:
-        os: [ubuntu-latest, windows-latest, macOS-latest]
-        node: [13.x, 12.x, 10.x, "10.12.0"]
-        exclude:
+        os: [ubuntu-latest]
+        node: [14.x, 13.x, 12.x, 10.x, "10.12.0"]
+        include:
         - os: windows-latest
-          node: "10.12.0"
-        - os: windows-latest
-          node: 10.x
-        - os: windows-latest
-          node: 13.x
-        - os: macOS-latest
-          node: "10.12.0"
-        - os: macOS-latest
-          node: 10.x
+          node: "12.x"
         - os: macOS-latest
-          node: 13.x
+          node: "12.x"
     runs-on: ${{ matrix.os }}
     steps:
     - uses: actions/checkout@v2
index feaeee47ede5e2aa8324832a27817aa247649626..3ab86f0c0d30254fc7cef426e70c5063d1b73e8c 100644 (file)
@@ -1,3 +1,258 @@
+v7.0.0 - May 8, 2020
+
+* [`b98d8bd`](https://github.com/eslint/eslint/commit/b98d8bda4630fe8278c5aa2b6650630770568fe5) Upgrade: eslint-release@2.0.0 (#13271) (Kai Cataldo)
+* [`4c0b028`](https://github.com/eslint/eslint/commit/4c0b028c55fc1674b374efe0bc6dd22c02b4ac88) Fix: remove Node.js and CommonJS category from build process (#13242) (Kai Cataldo)
+* [`401a687`](https://github.com/eslint/eslint/commit/401a68799d9d15145e1c7d92ee04644abec2f15a) Chore: fix rules list for prereleases (#13230) (Kai Cataldo)
+* [`4ef6158`](https://github.com/eslint/eslint/commit/4ef61580736353f700ab9e4e29f005b5ac552c78) Breaking: espree@7.0.0 (#13270) (Kai Cataldo)
+* [`b5c8d73`](https://github.com/eslint/eslint/commit/b5c8d7389bb2c5d4eae850b866832d099187818b) Docs: update 7.0.0 migration guide for consistency (#13267) (Kai Cataldo)
+* [`356fdb4`](https://github.com/eslint/eslint/commit/356fdb46aa118ba3d81cee93e8c058a7c98acaf9) Docs: add migration guide (#12692) (Toru Nagashima)
+* [`015edf6`](https://github.com/eslint/eslint/commit/015edf6467e33c67b904db037a674d71957a6865) Sponsors: Sync README with website (ESLint Jenkins)
+* [`fdfa364`](https://github.com/eslint/eslint/commit/fdfa364c1b0d88689d02cbe8ae848a3e323209aa) 7.0.0-rc.0 (ESLint Jenkins)
+* [`8d1b4db`](https://github.com/eslint/eslint/commit/8d1b4db9932cf7c3289187afbb3866a83f9b3f8c) Build: changelog update for 7.0.0-rc.0 (ESLint Jenkins)
+* [`0b1d65a`](https://github.com/eslint/eslint/commit/0b1d65a45aa5dfe08cd596c420490e81b546317e) Update: Improve report location for array-callback-return (refs #12334) (#13109) (Milos Djermanovic)
+* [`d85e291`](https://github.com/eslint/eslint/commit/d85e291d1b56960373031f2562547df7285444f7) Fix: yoda left string fix for exceptRange (fixes #12883) (#13052) (Anix)
+* [`2ce6bed`](https://github.com/eslint/eslint/commit/2ce6bed04cad376003f70447ece4b6578c142bfd) Chore: added tests for nested arrays (#13145) (Anix)
+* [`d3aac53`](https://github.com/eslint/eslint/commit/d3aac532f6a24c633f85dedf0e552eabd22d0956) Update: report backtick loc in no-unexpected-multiline (refs #12334) (#13142) (Milos Djermanovic)
+* [`8e7a2d9`](https://github.com/eslint/eslint/commit/8e7a2d93595cfe0c1597af0e7873853369251c0b) Fix: func-call-spacing "never" reports wrong message (fixes #13190) (#13193) (Milos Djermanovic)
+* [`bcafd0f`](https://github.com/eslint/eslint/commit/bcafd0f8508e19ab8087a35fac7b97fc4295df3e) Update: Add ESLint API (refs eslint/rfcs#40) (#12939) (Kai Cataldo)
+* [`3eeae56`](https://github.com/eslint/eslint/commit/3eeae565bfb0834a31e5d3a253a17bbf4027cf88) Upgrade: some (dev) deps (#13155) (薛定谔的猫)
+* [`6b7030b`](https://github.com/eslint/eslint/commit/6b7030b1a1e1e3d1a3953cfa9722074d6a6fc1a9) Chore: Run tests on Node.js v14 (#13210) (fisker Cheung)
+* [`ebc28d7`](https://github.com/eslint/eslint/commit/ebc28d76658f1f3e4e8d56e70a25752b5d4a6686) Fix: Remove default .js from --ext CLI option (#13176) (Brandon Mills)
+* [`5c1bdeb`](https://github.com/eslint/eslint/commit/5c1bdebcf728062fd41583886830c89b65485df9) Update: Improve report location for getter-return (refs #12334) (#13164) (Milos Djermanovic)
+* [`56d2bee`](https://github.com/eslint/eslint/commit/56d2beea0ea0b6395a6d4a3e116ea6a964ff92f3) Docs: fix typos (#13204) (Nitin Kumar)
+* [`e13256e`](https://github.com/eslint/eslint/commit/e13256e395cc413ce45a66c8562621d48440d8f4) Chore: use espree.latestEcmaVersion in config-initializer (#13157) (Kai Cataldo)
+* [`e4f57b7`](https://github.com/eslint/eslint/commit/e4f57b7d7b8b7441a2217a217dcda1e7bfff516a) Chore: add nested array tests for array-element-newline (#13161) (Anix)
+* [`63ac918`](https://github.com/eslint/eslint/commit/63ac91877668205aaa50495a9615806967e6e4cf) Sponsors: Sync README with website (ESLint Jenkins)
+* [`516f253`](https://github.com/eslint/eslint/commit/516f253729daeeb9da5de5e9b38606ff9c1aae71) Docs: Adds import example for object-curly-newline rule (refs #12018) (#13177) (Luke Lewis)
+* [`5a0e84e`](https://github.com/eslint/eslint/commit/5a0e84e9498a946a3e8491a370e012354e087fe0) Sponsors: Sync README with website (ESLint Jenkins)
+* [`b398e0b`](https://github.com/eslint/eslint/commit/b398e0b9ff455e4e7d70f19d5ccea5819c21eb86) Docs: add rule comment in prefer-rest-params doc (#13191) (YeonJuan)
+* [`ffaa4ba`](https://github.com/eslint/eslint/commit/ffaa4ba5e2bb1a51a78a2b2c028cbe2efc9e5165) Sponsors: Sync README with website (ESLint Jenkins)
+* [`932869b`](https://github.com/eslint/eslint/commit/932869b3251b04c4ad5fa72279cb2a56a3e67b55) Sponsors: Sync README with website (ESLint Jenkins)
+* [`54630f0`](https://github.com/eslint/eslint/commit/54630f0063fa66318476473757b5912465d4caf2) Sponsors: Sync README with website (ESLint Jenkins)
+* [`c9a5035`](https://github.com/eslint/eslint/commit/c9a503571a4662f6c2d31cabc7fd7819ec388150) Fix: newBasePath should be an absolute path (fixes #12850) (#13078) (Nick Harris)
+* [`e7c1d4b`](https://github.com/eslint/eslint/commit/e7c1d4b2ac56149a517d4b0000230348a641f1d3) Update: deprecate Node.js & CommonJS rules (#12898) (Kai Cataldo)
+* [`95e1c70`](https://github.com/eslint/eslint/commit/95e1c70cebde210a990ee786ec7ab1c8e522edb8) Upgrade: levn@0.4.1 (fixes #9366) (#13140) (Kai Cataldo)
+* [`c41de38`](https://github.com/eslint/eslint/commit/c41de382a330d4789488fd2dcf6db5a3163bb5d2) Docs: fix curly multi-or-nest examples with comments (refs #12972) (#13151) (Milos Djermanovic)
+* [`57221d5`](https://github.com/eslint/eslint/commit/57221d58c60e757062242f30ed574e0502fc7c31) Docs: fix eslint comment in no-inner-declarations examples (#13152) (Milos Djermanovic)
+* [`301b450`](https://github.com/eslint/eslint/commit/301b450ecd1985ae84d1915124f4638ab2a2e6de) Fix: no-extra-parens export default sequence expression false positive (#13096) (Milos Djermanovic)
+* [`af4472f`](https://github.com/eslint/eslint/commit/af4472fed794b86e63730702e4b27294a4118d09) Update: Improve report location for new-cap (refs #12334) (#13136) (Milos Djermanovic)
+* [`bfa811c`](https://github.com/eslint/eslint/commit/bfa811ceee801fe8ba212a5c879e13743146e909) Fix: init error in extending recommended config (fixes #12707) (#12738) (YeonJuan)
+* [`5dfd4eb`](https://github.com/eslint/eslint/commit/5dfd4eb50d84077a57950f119e5de8976070e49a) Docs: examples with arrow functions in no-return-assign (fixes #13135) (#13138) (Anix)
+* [`adc8fa8`](https://github.com/eslint/eslint/commit/adc8fa88c9f223b984a3519ed159a055bf933b18) Docs: clarify exceptions in spaced-comment (fixes #13032) (#13126) (Anix)
+* [`a784dac`](https://github.com/eslint/eslint/commit/a784dac8bc26f31edbca869b16d6ad91bd4e5cc4) Update: Improve report location newline-per-chained-call (refs #12334) (#13116) (Milos Djermanovic)
+* [`5e07574`](https://github.com/eslint/eslint/commit/5e07574a91861fdcab6888b4c6829868030c3a39) Update: Improve report location for space-before-function-paren (#13128) (Chiawen Chen)
+* [`d0d32a8`](https://github.com/eslint/eslint/commit/d0d32a8c2a6c60c7e6e2d32a054e5987efd4c263) Sponsors: Sync README with website (ESLint Jenkins)
+* [`17e2fe4`](https://github.com/eslint/eslint/commit/17e2fe425168e675fe7607182615e50527eedf53) Update: Improve error message for fatal fixer errors (#13120) (Brad Zacher)
+* [`7551f0c`](https://github.com/eslint/eslint/commit/7551f0c6fd12f0295cc7d6377bf1899c092e79d8) Fix: no check for shadowed Object (fixes #12809) (#13115) (Anix)
+* [`988d842`](https://github.com/eslint/eslint/commit/988d8428811934943ce13b2d8b833d795ac2bb4a) Fix: add end location to report in no-useless-concat (refs #12334) (#13110) (Milos Djermanovic)
+* [`0518ebb`](https://github.com/eslint/eslint/commit/0518ebb840b5bf2d646dbd8a9b3e246e7069eb79) Sponsors: Sync README with website (ESLint Jenkins)
+* [`252fd41`](https://github.com/eslint/eslint/commit/252fd4133805f003151e0220b5d89bbb70cfacb1) Sponsors: Sync README with website (ESLint Jenkins)
+* [`438dcbb`](https://github.com/eslint/eslint/commit/438dcbb981214d67e8848006ce45afc0fbfa1705) Update: Improve report location for comma-style (refs #12334) (#13111) (Chiawen Chen)
+* [`85b7254`](https://github.com/eslint/eslint/commit/85b72548c0c893499c787b82f404348e1b50354d) Update: no-inner-declarations false negative in non-block (fixes #12222) (#13062) (Anix)
+* [`6631ef1`](https://github.com/eslint/eslint/commit/6631ef1678bbdd48680fb3025c3692abd0aeec4a) Update: Improve report location for no-empty-function (refs #12334) (#13121) (Milos Djermanovic)
+* [`b228f95`](https://github.com/eslint/eslint/commit/b228f958afaf507d6f6f99c90b2075b395733839) Docs: Update README team and sponsors (ESLint Jenkins)
+* [`119b7ce`](https://github.com/eslint/eslint/commit/119b7ce97993b84df5af4e4f82e5102e430dfff1) 7.0.0-alpha.3 (ESLint Jenkins)
+* [`2531b80`](https://github.com/eslint/eslint/commit/2531b802a1527ea1084905641a17befcb50350c7) Build: changelog update for 7.0.0-alpha.3 (ESLint Jenkins)
+* [`78c8cda`](https://github.com/eslint/eslint/commit/78c8cda5a5d82f5f8548c4528a6438d29756bb71) Breaking: RuleTester Improvements (refs eslint/rfcs#25) (#12955) (Milos Djermanovic)
+* [`e0f1b6c`](https://github.com/eslint/eslint/commit/e0f1b6c3d62f725b99b8c07654603b559ba43ba9) Update: stricter array index check in no-magic-numbers (fixes #12845) (#12851) (Milos Djermanovic)
+* [`362713c`](https://github.com/eslint/eslint/commit/362713c04aa89092b2b98a77fa94a75b3c933fc6) Update: Improve report location for template-curly-spacing (#12813) (Milos Djermanovic)
+* [`29f32db`](https://github.com/eslint/eslint/commit/29f32db68c921a857e17ae627923d87b9c8708de) Fix: Change error message logic for implicit file ignore (fixes #12873) (#12878) (Scott Hardin)
+* [`eb1a43c`](https://github.com/eslint/eslint/commit/eb1a43ce3113c906800192c3ef766d2ff188776f) Fix: require-await ignore async generators (fixes #12459) (#13048) (Anix)
+* [`920465b`](https://github.com/eslint/eslint/commit/920465b5d8d291df8bce7eef8a066b1dd43d8cae) Fix: getNameLocationInGlobalDirectiveComment end location (refs #12334) (#13086) (Milos Djermanovic)
+* [`ae14a02`](https://github.com/eslint/eslint/commit/ae14a021bbea5117fe366ae4ed235e8f08dc65a8) Fix: add end location to report in no-extra-bind (refs #12334) (#13083) (Milos Djermanovic)
+* [`105384c`](https://github.com/eslint/eslint/commit/105384ccc11dcd7303104fb5a347eda1d4d48357) Update: report operator location in operator-linebreak (refs #12334) (#13102) (Milos Djermanovic)
+* [`081e240`](https://github.com/eslint/eslint/commit/081e24022a40d9a026ddd2a85c68cb8c3f18dc53) Update: support globalThis in no-implied-eval (fixes #12670) (#13105) (YeonJuan)
+* [`185982d`](https://github.com/eslint/eslint/commit/185982d5615d325ae8b45c2360d5847df4098bda) Breaking: improve plugin resolving (refs eslint/rfcs#47) (#12922) (Toru Nagashima)
+* [`0c20bc0`](https://github.com/eslint/eslint/commit/0c20bc068e608869981a10711bba88ffde1539d8) Fix: check assignment property target in camelcase (fixes #13025) (#13027) (YeonJuan)
+* [`8d50a7d`](https://github.com/eslint/eslint/commit/8d50a7d82244d4912f3eab62a66c81c76c44a9da) Fix: add end location to report in no-prototype-builtins (refs #12334) (#13087) (Milos Djermanovic)
+* [`3e4e7f8`](https://github.com/eslint/eslint/commit/3e4e7f8d429dc70b78c0aefaa37f9c22a1e5fc0f) Fix: incorrect logic for required parens in no-extra-boolean-cast fixer (#13061) (Milos Djermanovic)
+* [`6c069f9`](https://github.com/eslint/eslint/commit/6c069f907a04268b671c7f949c04a508df9d42a3) Docs: Add comments to code block in example (#13089) (Kibeom Kwon)
+* [`ee1f053`](https://github.com/eslint/eslint/commit/ee1f0531aa534ef9182cf8586f55ad82aaa55e75) Docs: Fix typo (#13092) (Max Coplan)
+* [`76324ac`](https://github.com/eslint/eslint/commit/76324ace67893c3d7e38a369114d6128df9ffb65) Docs: Add further reading to rule (#13084) (Max Coplan)
+* [`a1370ab`](https://github.com/eslint/eslint/commit/a1370abed72e1fb93e601816d981fa6e46204afb) Update: Report constructor calls in no-obj-calls (#12909) (Milos Djermanovic)
+* [`2111c52`](https://github.com/eslint/eslint/commit/2111c52443e7641caad291e0daaea8e2fe6c4562) Upgrade: esquery@1.2.0 (#13076) (Milos Djermanovic)
+* [`3f7c9bf`](https://github.com/eslint/eslint/commit/3f7c9bf19615122fb776cdd13da532d860bd945a) Docs: clarify variables option in no-use-before-define (fixes #12986) (#13017) (Anix)
+* [`aef9488`](https://github.com/eslint/eslint/commit/aef9488c07d3da4becff6e8d6918824b53086d86) Fix: allow references to external globals in id-blacklist (fixes #12567) (#12987) (Milos Djermanovic)
+* [`4955c50`](https://github.com/eslint/eslint/commit/4955c50dc9e89b4077b28e35f065d45e89bdccd7) Fix: remove type arguments in prefer-object-spread (fixes #13058) (#13063) (Milos Djermanovic)
+* [`48b122f`](https://github.com/eslint/eslint/commit/48b122f450b14dd27afef4c8115c69fca4f02be1) Breaking: change relative paths with --config (refs eslint/rfcs#37) (#12887) (Toru Nagashima)
+* [`085979f`](https://github.com/eslint/eslint/commit/085979fed9a5e24a87e4d92ee79272b59211d03f) Update: consider env in no-implied-eval (fixes #12733) (#12757) (YeonJuan)
+* [`9ac5b9e`](https://github.com/eslint/eslint/commit/9ac5b9edf06d16a9216c2c9b02bb20b6aa8ed0ab) Docs: Clarify node_modules is ignored by default (fixes #13006) (#13054) (Mika Kuijpers)
+* [`0de91f3`](https://github.com/eslint/eslint/commit/0de91f39a97cdf530cb64edbadde57a2bb41ca86) Docs: removed correct code from incorrect eg (#13060) (Anix)
+* [`dbe357d`](https://github.com/eslint/eslint/commit/dbe357de199620675446464f6fd0e35064c4d247) Fix: check template literal in prefer-numeric-literals (fixes #13045) (#13046) (YeonJuan)
+* [`2260611`](https://github.com/eslint/eslint/commit/2260611e616bdc2a0bf16d508b60a50772ce7fbb) Fix: added async in allow method in no-empty-function (fixes #12768) (#13036) (Anix)
+* [`f3788af`](https://github.com/eslint/eslint/commit/f3788aff615edfbfb7afc4c491bb07d20737531b) Sponsors: Sync README with website (ESLint Jenkins)
+* [`e90b29b`](https://github.com/eslint/eslint/commit/e90b29bb1f41d4e5767e33d03db5984f036586ed) Update: Allow testing Suggestions with data in RuleTester (fixes #12606) (#12635) (Milos Djermanovic)
+* [`7224eee`](https://github.com/eslint/eslint/commit/7224eee3ff4b4378d3439deb038bf34b116fa48b) Fix: no-plusplus allow comma operands in for afterthought (fixes #13005) (#13024) (Milos Djermanovic)
+* [`7598cf8`](https://github.com/eslint/eslint/commit/7598cf816bd854de1dd7d96cf00dec6ecc4564ac) Fix: Newline before eof when creating config via --init (#12952) (Andreas Lind)
+* [`183e300`](https://github.com/eslint/eslint/commit/183e3006841c29efdd245c45a72e6cefac86ae35) Update: support globalThis (refs #12670) (#12774) (YeonJuan)
+* [`af7af9d`](https://github.com/eslint/eslint/commit/af7af9d32ea8073d2d0d726cc8551351261a170f) Docs: Update governance (#13055) (Nicholas C. Zakas)
+* [`31d5eb3`](https://github.com/eslint/eslint/commit/31d5eb3e60b6c2ee26976721f07cc89d60867659) Sponsors: Sync README with website (ESLint Jenkins)
+* [`95613d4`](https://github.com/eslint/eslint/commit/95613d46b7900b3d9757a7f6959d5dfb262f29fc) Upgrade: espree@6.2.1 (#13026) (Kai Cataldo)
+* [`f1525dc`](https://github.com/eslint/eslint/commit/f1525dc45dfdbbe31e724671270785b41cffc6bd) Sponsors: Sync README with website (ESLint Jenkins)
+* [`0243549`](https://github.com/eslint/eslint/commit/0243549db4d237cb78e720d55a9cae89b91f6830) Fix: camelcase false positive with computed property (fixes #13022) (#13023) (Milos Djermanovic)
+* [`bc0c02c`](https://github.com/eslint/eslint/commit/bc0c02cd0368559c7a7b1510eb4620022a4cc31c) Chore: added lock files to gitignore (#13015) (Anix)
+* [`79ac6cd`](https://github.com/eslint/eslint/commit/79ac6cd2d8e4c32e03dfea10a957806845058573) Docs: added less confusing explanation for func-style (fixes #12900) (#13004) (Anix)
+* [`26267ed`](https://github.com/eslint/eslint/commit/26267ed70270ef746b785c09e267f815bf7c596a) Chore: update GitHub Actions (#12984) (Pig Fang)
+* [`1299705`](https://github.com/eslint/eslint/commit/12997058626b5167ba4b9d2ae0d0ea965a01c4be) Update: acorn version (#13016) (Idan Avrahami)
+* [`6cef0d5`](https://github.com/eslint/eslint/commit/6cef0d50a0d131bc8897799a54e1af1d38606db4) Fix: Check division operator in astUtils.canTokensBeAdjacent (#12879) (Milos Djermanovic)
+* [`fd8e1f5`](https://github.com/eslint/eslint/commit/fd8e1f52110cada542a120750236fd1ec8779336) Sponsors: Sync README with website (ESLint Jenkins)
+* [`472025f`](https://github.com/eslint/eslint/commit/472025f2814d0360fe8d4cddbcba049982e1cd43) Chore: update space-before-function-paren in eslint-config-eslint (#12966) (Kai Cataldo)
+* [`fd8c42a`](https://github.com/eslint/eslint/commit/fd8c42ada52f0ae2488ad96ee8fee675f63134ce) Sponsors: Sync README with website (ESLint Jenkins)
+* [`c615eae`](https://github.com/eslint/eslint/commit/c615eae0be3c6c167c6f77ec7a73e7adca0ecef0) 7.0.0-alpha.2 (ESLint Jenkins)
+* [`2e8f193`](https://github.com/eslint/eslint/commit/2e8f193ebc970f07ea37d267c8bce02d74c285a8) Build: changelog update for 7.0.0-alpha.2 (ESLint Jenkins)
+* [`a5b41a7`](https://github.com/eslint/eslint/commit/a5b41a75b57572e97476b06ad39b768e15b9d844) Update: no-restricted-modules handle TemplateLiteral (fixes #12926) (#12927) (Michal Piechowiak)
+* [`051567a`](https://github.com/eslint/eslint/commit/051567adca7ca56d691bcda76f54ed72e3eae367) Update: check identifier in array pattern in id-length (fixes #12832) (#12839) (YeonJuan)
+* [`4af06fc`](https://github.com/eslint/eslint/commit/4af06fc49029dac5c9acfd53f01fd9527bfbb4aa) Breaking: Test with an unknown error property should fail in RuleTester (#12096) (Milos Djermanovic)
+* [`9038a29`](https://github.com/eslint/eslint/commit/9038a29569548c0563c29dbe9f7dae280ff3addd) Update: func-names `as-needed` false negative with AssignmentPattern (#12932) (Milos Djermanovic)
+* [`afde78b`](https://github.com/eslint/eslint/commit/afde78b125747ce5ad9e5f871122a0d370dd0152) Fix: curly removes necessary braces between if and else (fixes #12928) (#12943) (Milos Djermanovic)
+* [`4797fb2`](https://github.com/eslint/eslint/commit/4797fb2c29db97bc5cd23b40e5a9235fef1ea06a) Fix: arrow-body-style crash with object literal body (fixes #12884) (#12886) (Milos Djermanovic)
+* [`afa9aac`](https://github.com/eslint/eslint/commit/afa9aac6de9444e935a55b46311e5b5a58f86063) Breaking: class default `true` computed-property-spacing (fixes #12812) (#12915) (Milos Djermanovic)
+* [`b8e20d3`](https://github.com/eslint/eslint/commit/b8e20d33b7d6645266beef09cd231afaf5054328) Docs: Mention TypeScript's compiler check (#12903) (Benny Neugebauer)
+* [`de14d1c`](https://github.com/eslint/eslint/commit/de14d1ce0cf422b4100a686abb906f53fbf905b3) Fix: wrap-iife autofix removes mandatory parentheses (#12905) (Milos Djermanovic)
+* [`5775b06`](https://github.com/eslint/eslint/commit/5775b06a74573cbe068bea56b1d2376421f5e831) Fix: Optionally allow underscores in member names (#11972) (Edgardo Avilés)
+* [`e997f32`](https://github.com/eslint/eslint/commit/e997f32b936463ac38e8b0034f764c47502e56a8) Docs: Updated arrow-parens for minor grammar issue (#12962) (Tom)
+* [`7d52151`](https://github.com/eslint/eslint/commit/7d52151bcd5d5524f240588436a8808162be187f) Breaking: classes default `true` in accessor-pairs (fixes #12811) (#12919) (Milos Djermanovic)
+* [`cf14355`](https://github.com/eslint/eslint/commit/cf14355e34a6757e15806f8e493553bd7110fb36) Docs: Fix links to custom parsers doc (#12965) (Brandon Mills)
+* [`0dfc3ff`](https://github.com/eslint/eslint/commit/0dfc3ff9fb228e1d9b1df99de50033ce9140ac24) Fix: add end location to report in no-eval (#12960) (Milos Djermanovic)
+* [`f479f6f`](https://github.com/eslint/eslint/commit/f479f6fe2eb95156e22bebfccb39a7fc1f19e9c0) Docs: References correct config file name (#12885) (Patrick Kilgore)
+* [`78182e4`](https://github.com/eslint/eslint/commit/78182e45e0178d9eac2591944ef4daee21d2cb44) Breaking: Add new rules to eslint:recommended (fixes #12911) (#12920) (Milos Djermanovic)
+* [`8d5c434`](https://github.com/eslint/eslint/commit/8d5c434f721142be74c7515aaa935668a15b79b1) Docs: fix category descriptions for site generation (fixes #12894) (#12930) (Kai Cataldo)
+* [`05380e6`](https://github.com/eslint/eslint/commit/05380e6e7e19a79d26ea6d6b44a8d5ee7cde51c8) Docs: Remove claim about semicolons from docs (#12944) (Luke Sikina)
+* [`aa9d725`](https://github.com/eslint/eslint/commit/aa9d72525054e641231a2960a2e37b3716228056) Sponsors: Sync README with website (ESLint Jenkins)
+* [`7747177`](https://github.com/eslint/eslint/commit/7747177f8504961059b7c56bdb70a820bd1114c1) Update: report rename id destructuring in id-blacklist (fixes #12807) (#12923) (YeonJuan)
+* [`6423e11`](https://github.com/eslint/eslint/commit/6423e11c0bedd3b4e661ab554316bdeb1fc1ee3c) Breaking: check unnamed default export in func-names (fixes #12194) (#12195) (Chiawen Chen)
+* [`77df505`](https://github.com/eslint/eslint/commit/77df505d9a08496a8eaefeca4f885f54a21d5c5e) Update: check renaming identifier in object destructuring (fixes 12827) (#12881) (YeonJuan)
+* [`41de9df`](https://github.com/eslint/eslint/commit/41de9df41a30a4300243bfe4ca26f716a787b2fc) Update: enforceForLogicalOperands no-extra-boolean-cast (fixes #12137) (#12734) (jmoore914)
+* [`98a9b01`](https://github.com/eslint/eslint/commit/98a9b019e52f344c1a6bc2f704c227f89692afe3) 7.0.0-alpha.1 (ESLint Jenkins)
+* [`e9f1073`](https://github.com/eslint/eslint/commit/e9f1073f748f8c22f754d145b1ba193e7ce82215) Build: changelog update for 7.0.0-alpha.1 (ESLint Jenkins)
+* [`f702b1a`](https://github.com/eslint/eslint/commit/f702b1a54820d2b4e4993dcded99f551a98b490f) Add missing plugin reference (#12796) (Eduard Bardají Puig)
+* [`1f1424c`](https://github.com/eslint/eslint/commit/1f1424cb200e609d58645f6c54739e11469e6265) Fix: fix inconsistently works option in no-extra-parens (fixes #12717) (#12843) (YeonJuan)
+* [`b5adcaa`](https://github.com/eslint/eslint/commit/b5adcaab93f388f1d8e9d35d6f5e8c2994240850) Fix: make YieldExpression throwable (fixes #12880) (#12897) (YeonJuan)
+* [`4293229`](https://github.com/eslint/eslint/commit/4293229709dde105692347241513766e953664dd) Breaking: use-isnan enforceForSwitchCase default `true` (fixes #12810) (#12913) (Milos Djermanovic)
+* [`cf38d0d`](https://github.com/eslint/eslint/commit/cf38d0d939b62f3670cdd59f0143fd896fccd771) Breaking: change default ignore pattern (refs eslint/rfcs#51) (#12888) (Toru Nagashima)
+* [`bfe1dc4`](https://github.com/eslint/eslint/commit/bfe1dc4e614640cb69032afbb5851c1493f537e3) Breaking: no-dupe-class-members checks some computed keys (fixes #12808) (#12837) (Milos Djermanovic)
+* [`1ee6b63`](https://github.com/eslint/eslint/commit/1ee6b6388305a8671c8d4c3cf30c2dbf18a1ff7e) Update: check template literal in yoda (fixes #12863) (#12876) (YeonJuan)
+* [`0ae7041`](https://github.com/eslint/eslint/commit/0ae70417af70ad565450d9e779ae78c05f6a51e2) Sponsors: Sync README with website (ESLint Jenkins)
+* [`1907e57`](https://github.com/eslint/eslint/commit/1907e57362f7d5f7a02a5a78f24ac3347f868e93) Chore: add Twitter and Open Collective badge (#12877) (Kai Cataldo)
+* [`95e0586`](https://github.com/eslint/eslint/commit/95e0586c95e6953d11983d1d11891ed30318109a) Fix: id-blacklist false positives on renamed imports (#12831) (Milos Djermanovic)
+* [`b7f0d20`](https://github.com/eslint/eslint/commit/b7f0d200c125b3d233ccafaabdaa61c66dc60e3c) Chore: Use consistent badge style (#12825) (fisker Cheung)
+* [`3734a66`](https://github.com/eslint/eslint/commit/3734a669983de7d5107ba8f39b291c6e3116489f) Chore: use ids for messages (#12859) (Gareth Jones)
+* [`824d235`](https://github.com/eslint/eslint/commit/824d23585c205f2993716585cb6f55dfbe4a33f0) Docs: add errorOnUnmatchedPattern option to CLIEngine (#12834) (Arthur Denner)
+* [`439c833`](https://github.com/eslint/eslint/commit/439c83342c364ba3ce5168d54e165b1fe3e35630) Update: array-callback-return checks Array.forEach (fixes #12551) (#12646) (Gabriel R Sezefredo)
+* [`33efd71`](https://github.com/eslint/eslint/commit/33efd71d7c3496b4b9cbfe006280527064940826) Docs: Fix spelling mistakes (#12861) (Bryan Mishkin)
+* [`a5b3c5f`](https://github.com/eslint/eslint/commit/a5b3c5fa4edc2312534af0d9f0911f68144f8baf) Docs: Update README team and sponsors (ESLint Jenkins)
+* [`0cae920`](https://github.com/eslint/eslint/commit/0cae9203a8077184ad6beb00028fd376cc806f34) Chore: rename shadowed global (#12862) (Tony Brix)
+* [`055b80d`](https://github.com/eslint/eslint/commit/055b80dc89bba2a5ab22f7a27deb40135b5cacfa) Chore: Fix typo in complexity.js (#12864) (Kyle Shevlin)
+* [`d6c313d`](https://github.com/eslint/eslint/commit/d6c313de794ea0671d35b5027288cd2ea456c0b5) Docs: add missing eslint comments in prefer-regex-literals examples (#12858) (Milos Djermanovic)
+* [`7d551ab`](https://github.com/eslint/eslint/commit/7d551ab8cbf2d3a802b0d0685379aa075fe9d7c0) Sponsors: Sync README with website (ESLint Jenkins)
+* [`540de8e`](https://github.com/eslint/eslint/commit/540de8e34d08f4b17b66b06d13927acb7552357a) Sponsors: Sync README with website (ESLint Jenkins)
+* [`ac5d515`](https://github.com/eslint/eslint/commit/ac5d515252c226f030fa646bf7635a12a3b856fe) Sponsors: Sync README with website (ESLint Jenkins)
+* [`dadc892`](https://github.com/eslint/eslint/commit/dadc8927820576c60b48bcbc7d5a9056a6279d30) Fix: operator-assignment crash on adjacent division assignment (#12844) (Milos Djermanovic)
+* [`9f39ef0`](https://github.com/eslint/eslint/commit/9f39ef0d4b398c7c09ceef89128da448680d587c) Chore: typo in PULL_REQUEST_TEMPLATE.md (#12848) (Balázs Orbán)
+* [`a60d5cd`](https://github.com/eslint/eslint/commit/a60d5cd2325ca72fa1b272b0b90ccd7904b92062) Chore: typo in no-irregular-whitespace.js (#12847) (Balázs Orbán)
+* [`691d19a`](https://github.com/eslint/eslint/commit/691d19a2872bffab50c0024d488b8cb33504cc83) Chore: add missing `ecmaVersion` 2020/11 type value (#12833) (Piotr Błażejewicz (Peter Blazejewicz))
+* [`516ddb3`](https://github.com/eslint/eslint/commit/516ddb37d39502e5a8c88a017ae3bad05046f41d) Sponsors: Sync README with website (ESLint Jenkins)
+* [`a9d92f9`](https://github.com/eslint/eslint/commit/a9d92f991d69902a9150db373590e2ed54dec988) Fix: radix rule crash on disabled globals (#12824) (Milos Djermanovic)
+* [`03a69db`](https://github.com/eslint/eslint/commit/03a69dbe86d5b5768a310105416ae726822e3c1c) Update: check template literal in no-proto, no-iterator (fixes #12801) (#12806) (YeonJuan)
+* [`562e784`](https://github.com/eslint/eslint/commit/562e7845946a490f2e173a0bcd1af631070a4eef) Update: fix no-magic-numbers false negative with ignoreArrayIndexes (#12805) (Milos Djermanovic)
+* [`f5b9656`](https://github.com/eslint/eslint/commit/f5b96564f732962f46755adbb33c49fae9af6a92) Chore: add test for no-constant-condition (#12836) (Milos Djermanovic)
+* [`533c114`](https://github.com/eslint/eslint/commit/533c1140dc98bebdc3ae8334ab2e6c27c7df0c21) Fix: multiline-comment-style rule add extra space after * (fixes #12785) (#12823) (Karthik Priyadarshan)
+* [`0460748`](https://github.com/eslint/eslint/commit/0460748cda67ddc4a4cb0db3cdf187a742d09bf8) Update: check template literal in no-constant-condition (fixes #12815) (#12816) (YeonJuan)
+* [`80309c3`](https://github.com/eslint/eslint/commit/80309c3791188ac5d1c4eebc99ede323a55336e6) Fix: no-constant-condition doesn't introspect arrays (fixes #12225) (#12307) (Sean Gray)
+* [`10a79a6`](https://github.com/eslint/eslint/commit/10a79a672b42d51539bcd6ace482be7afa5f34f8) Chore: Adopt `eslint-plugin/require-meta-docs-description` internally (#12762) (Bryan Mishkin)
+* [`aea1729`](https://github.com/eslint/eslint/commit/aea172998ec4e2af1d9186b6767c3f34428945f4) Docs: Fix anchor links in Node.js API TOC (#12821) (Matija Marohnić)
+* [`1b8a3ce`](https://github.com/eslint/eslint/commit/1b8a3ce15237b9085f2761dcf73655207e6169a6) Sponsors: Sync README with website (ESLint Jenkins)
+* [`c2217c0`](https://github.com/eslint/eslint/commit/c2217c04d6c82b160a21b00fca39c8acec543403) Breaking: make `radix` rule stricter (#12608) (fisker Cheung)
+* [`e03a7b3`](https://github.com/eslint/eslint/commit/e03a7b311cb9ddf55914b1496683609bd564de2f) 7.0.0-alpha.0 (ESLint Jenkins)
+* [`c8c1b2b`](https://github.com/eslint/eslint/commit/c8c1b2b2efadfcd3c04aaf15bd793c5b4dd84cb6) Build: changelog update for 7.0.0-alpha.0 (ESLint Jenkins)
+* [`1aa021d`](https://github.com/eslint/eslint/commit/1aa021d77fdd2c68d7b7d2f4603252110c414b32) Breaking: lint `overrides` files (fixes #10828, refs eslint/rfcs#20) (#12677) (Toru Nagashima)
+* [`e59d775`](https://github.com/eslint/eslint/commit/e59d77536bd8db57e8a75cd5245f6f320aa699f8) Update: Separate pattern/expression options for array-element-newline (#11796) (jacobparish)
+* [`f8f115a`](https://github.com/eslint/eslint/commit/f8f115af6e10539e6cad485588187cb11917f8c9) Update: treat comment tokens in template-curly-spacing (fixes #12744) (#12775) (YeonJuan)
+* [`b50179d`](https://github.com/eslint/eslint/commit/b50179def3fedbd95fdeab25e32c2511867eb760) Breaking: Check assignment targets in no-extra-parens (#12490) (Milos Djermanovic)
+* [`de4fa7c`](https://github.com/eslint/eslint/commit/de4fa7c65c7befefa64d1605550267071ee56a5d) Fix: wrong indent at tagged template in indent (fixes #12122) (#12596) (YeonJuan)
+* [`d86a5bb`](https://github.com/eslint/eslint/commit/d86a5bbb1987d858d4963f647b0af5c1fd924b4f) Breaking: Check flatMap in array-callback-return (fixes #12235) (#12765) (Milos Djermanovic)
+* [`cf46df7`](https://github.com/eslint/eslint/commit/cf46df70158a4ed4c09d5c9d655c07dc6df3ff5e) Breaking: description in directive comments (refs eslint/rfcs#33) (#12699) (Toru Nagashima)
+* [`7350589`](https://github.com/eslint/eslint/commit/7350589a5bdfc9d75d1ff19364f476eec44c3911) Breaking: some rules recognize bigint literals (fixes #11803) (#12701) (Toru Nagashima)
+* [`16a1c1f`](https://github.com/eslint/eslint/commit/16a1c1f79bc0a4cc1c3a87e98d220041de88bb93) Fix: prefer-object-spread false positives with accessors (fixes #12086) (#12784) (Milos Djermanovic)
+* [`f9774ec`](https://github.com/eslint/eslint/commit/f9774ec11b0ebe63fb16a97b97890efb84699548) New: Add default-case-last rule (fixes #12665) (#12668) (Milos Djermanovic)
+* [`9a93d9e`](https://github.com/eslint/eslint/commit/9a93d9ef389c49a133c4df4f9843927f5f806423) Update: fix no-restricted-imports export * false negative (fixes #12737) (#12798) (Milos Djermanovic)
+* [`0d8c0af`](https://github.com/eslint/eslint/commit/0d8c0affe1ae7ecf228cdf91b490921f7e9d1fdb) Fix: improve report location for computed-property-spacing (#12795) (Milos Djermanovic)
+* [`756b95d`](https://github.com/eslint/eslint/commit/756b95d59fb97cd9b3f3adf98cebf529fe4842a2) Fix: id-blacklist should ignore ObjectPatterns (fixes #12787) (#12792) (JP Ramassini)
+* [`561b6d4`](https://github.com/eslint/eslint/commit/561b6d4726f3e77dd40ba0d340ca7f08429cd2eb) Chore: add prerequisites checklist to PR template (#12790) (Kai Cataldo)
+* [`01ff791`](https://github.com/eslint/eslint/commit/01ff7910af86fc45b76e883bc9ab00c9be3b50ac) Fix: Display pipe character correctly in test output (#12771) (Brad Zacher)
+* [`68becbd`](https://github.com/eslint/eslint/commit/68becbd84e8a0693409d36f2be10679c483e233a) Update: fix no-restricted-imports importNames reporting (fixes #12282) (#12711) (Andrey Alexandrov)
+* [`ae959b6`](https://github.com/eslint/eslint/commit/ae959b691fb148ac8b474c924c8cb01ef61c436d) Update: report double extra parens in no-extra-parens (fixes #12127) (#12697) (YeonJuan)
+* [`02fcc05`](https://github.com/eslint/eslint/commit/02fcc055710e8d69d986f1e682cae2014ad881e2) Docs: Improve sort-keys (#12791) (Steven Vachon)
+* [`35cd958`](https://github.com/eslint/eslint/commit/35cd95893be0afd8c954cbcf9268c2aa045b7d5b) Sponsors: Sync README with website (ESLint Jenkins)
+* [`a1d999c`](https://github.com/eslint/eslint/commit/a1d999c6b4e51c317ad409110be7be214ff9f7c6) New: Add no-useless-backreference rule (fixes #12673) (#12690) (Milos Djermanovic)
+* [`b2c6209`](https://github.com/eslint/eslint/commit/b2c62096a8b318765d618cab222240f87d73063b) Update: fix no-extra-parens CallExpression#callee false negatives (#12743) (Milos Djermanovic)
+* [`14b42c3`](https://github.com/eslint/eslint/commit/14b42c386be3387c415267b789f277e1294d4567) Update: fix counting jsx comment len in max-len (fixes #12213) (#12661) (YeonJuan)
+* [`e632c31`](https://github.com/eslint/eslint/commit/e632c31d7e5363f1347b787702ecd4a85f5c11a2) Upgrade: several dependencies (#12753) (Toru Nagashima)
+* [`25eb703`](https://github.com/eslint/eslint/commit/25eb703c8758563988ffb497a53f89a3ed345399) Docs: fix dead link in max-lines rule docs (#12766) (Christian Bundy)
+* [`9dfc850`](https://github.com/eslint/eslint/commit/9dfc8501fb1956c90dc11e6377b4cb38a6bea65d) Chore: Refactor to use messageId in a number of rules (#12715) (Brad Zacher)
+* [`1118fce`](https://github.com/eslint/eslint/commit/1118fceb49af3436b8dcd0c6089f913cedf9a329) Breaking: runtime-deprecation on '~/.eslintrc' (refs eslint/rfcs#32) (#12678) (Toru Nagashima)
+* [`2c28fbb`](https://github.com/eslint/eslint/commit/2c28fbbb563a44282bef0c9fcc9be29d611cc83b) Breaking: drop Node.js 8 support (refs eslint/rfcs#44) (#12700) (Toru Nagashima)
+* [`098b67d`](https://github.com/eslint/eslint/commit/098b67d04a4b4dc8ef4faa6434c6ef5abbde3ed3) Docs: fix minor typo in brace-style.md (#12749) (Marko Kaznovac)
+* [`313f70a`](https://github.com/eslint/eslint/commit/313f70ac9a3cf5d1558d2427b00dd75666e18cf4) Update: add outerIIFEBody: "off" to indent rule (fixes #11377) (#12706) (Kai Cataldo)
+* [`b77b858`](https://github.com/eslint/eslint/commit/b77b8585e33fc4bb438a0e11ca8177c7eb91dbd8) Chore: fix separateRequires tests for one-var rule (#12709) (Milos Djermanovic)
+* [`e4df7df`](https://github.com/eslint/eslint/commit/e4df7dfb0199badb61d2c03ff4f7e4be735279d9) Chore: add JSDoc types for RuleTester test cases (#12325) (Chiawen Chen)
+* [`b23ad0d`](https://github.com/eslint/eslint/commit/b23ad0d789a909baf8d7c41a35bc53df932eaf30) Docs: change a broken link in working-with-rules.md (#12732) (Damien Cassou)
+* [`3fa39a6`](https://github.com/eslint/eslint/commit/3fa39a633b37544fec7cedfc1f2b0e62e9312a72) Update: Handle locally unsupported regex in computed property keys (#12056) (Milos Djermanovic)
+* [`4744397`](https://github.com/eslint/eslint/commit/474439720258b1a64b305c31588f803104fa4aaf) Chore: remove unused code in max-lines-per-function (#12659) (YeonJuan)
+* [`4e16957`](https://github.com/eslint/eslint/commit/4e169576a526023ee297d5bc8b37eedba229f63d) Build: update browser build (#12693) (Toru Nagashima)
+* [`00ddfff`](https://github.com/eslint/eslint/commit/00ddfffe6b4b4244e4680b0f92f2c6697fad136f) Fix: Windows path parsing for JUnit (fixes #12507) (#12509) (Michael Wall)
+* [`985dac3`](https://github.com/eslint/eslint/commit/985dac35e3c367f0f99d1f0e766e06a1d9818dd4) New: Add no-restricted-exports rule (fixes #10428) (#12546) (Milos Djermanovic)
+* [`1aff21b`](https://github.com/eslint/eslint/commit/1aff21bb54da44cef0b6e378a34a74265863b930) Fix: no-mixed-spaces-and-tabs reports multiline strings (#12566) (Milos Djermanovic)
+* [`8f1020f`](https://github.com/eslint/eslint/commit/8f1020ff711b0c57d590bf666e2841f64186d083) Update: no-void add an option to allow void as a statement (#12613) (Brad Zacher)
+* [`bb6cf50`](https://github.com/eslint/eslint/commit/bb6cf5082623ffb67bb1495fee52c0610ee5f421) Update: Add offsetTernaryExpressions option for indent rule (#12556) (Adam Stankiewicz)
+* [`39f5a45`](https://github.com/eslint/eslint/commit/39f5a453579b2ad732212edeb71f84ecb0991f97) Chore: add test cases for for-direction (#12698) (YeonJuan)
+* [`b340304`](https://github.com/eslint/eslint/commit/b3403045e535921df6d34785a4ce053e14ba27fd) Chore: Add extra test, improve docs (#12492) (Kevin Partington)
+* [`827259e`](https://github.com/eslint/eslint/commit/827259ea009f98a0fdf3f7ebf1bfb6cd661ce28d) Build: package.json update for eslint-config-eslint release (ESLint Jenkins)
+v7.0.0-rc.0 - April 24, 2020
+
+* [`0b1d65a`](https://github.com/eslint/eslint/commit/0b1d65a45aa5dfe08cd596c420490e81b546317e) Update: Improve report location for array-callback-return (refs #12334) (#13109) (Milos Djermanovic)
+* [`d85e291`](https://github.com/eslint/eslint/commit/d85e291d1b56960373031f2562547df7285444f7) Fix: yoda left string fix for exceptRange (fixes #12883) (#13052) (Anix)
+* [`2ce6bed`](https://github.com/eslint/eslint/commit/2ce6bed04cad376003f70447ece4b6578c142bfd) Chore: added tests for nested arrays (#13145) (Anix)
+* [`d3aac53`](https://github.com/eslint/eslint/commit/d3aac532f6a24c633f85dedf0e552eabd22d0956) Update: report backtick loc in no-unexpected-multiline (refs #12334) (#13142) (Milos Djermanovic)
+* [`8e7a2d9`](https://github.com/eslint/eslint/commit/8e7a2d93595cfe0c1597af0e7873853369251c0b) Fix: func-call-spacing "never" reports wrong message (fixes #13190) (#13193) (Milos Djermanovic)
+* [`bcafd0f`](https://github.com/eslint/eslint/commit/bcafd0f8508e19ab8087a35fac7b97fc4295df3e) Update: Add ESLint API (refs eslint/rfcs#40) (#12939) (Kai Cataldo)
+* [`3eeae56`](https://github.com/eslint/eslint/commit/3eeae565bfb0834a31e5d3a253a17bbf4027cf88) Upgrade: some (dev) deps (#13155) (薛定谔的猫)
+* [`6b7030b`](https://github.com/eslint/eslint/commit/6b7030b1a1e1e3d1a3953cfa9722074d6a6fc1a9) Chore: Run tests on Node.js v14 (#13210) (fisker Cheung)
+* [`ebc28d7`](https://github.com/eslint/eslint/commit/ebc28d76658f1f3e4e8d56e70a25752b5d4a6686) Fix: Remove default .js from --ext CLI option (#13176) (Brandon Mills)
+* [`5c1bdeb`](https://github.com/eslint/eslint/commit/5c1bdebcf728062fd41583886830c89b65485df9) Update: Improve report location for getter-return (refs #12334) (#13164) (Milos Djermanovic)
+* [`56d2bee`](https://github.com/eslint/eslint/commit/56d2beea0ea0b6395a6d4a3e116ea6a964ff92f3) Docs: fix typos (#13204) (Nitin Kumar)
+* [`e13256e`](https://github.com/eslint/eslint/commit/e13256e395cc413ce45a66c8562621d48440d8f4) Chore: use espree.latestEcmaVersion in config-initializer (#13157) (Kai Cataldo)
+* [`e4f57b7`](https://github.com/eslint/eslint/commit/e4f57b7d7b8b7441a2217a217dcda1e7bfff516a) Chore: add nested array tests for array-element-newline (#13161) (Anix)
+* [`63ac918`](https://github.com/eslint/eslint/commit/63ac91877668205aaa50495a9615806967e6e4cf) Sponsors: Sync README with website (ESLint Jenkins)
+* [`516f253`](https://github.com/eslint/eslint/commit/516f253729daeeb9da5de5e9b38606ff9c1aae71) Docs: Adds import example for object-curly-newline rule (refs #12018) (#13177) (Luke Lewis)
+* [`5a0e84e`](https://github.com/eslint/eslint/commit/5a0e84e9498a946a3e8491a370e012354e087fe0) Sponsors: Sync README with website (ESLint Jenkins)
+* [`b398e0b`](https://github.com/eslint/eslint/commit/b398e0b9ff455e4e7d70f19d5ccea5819c21eb86) Docs: add rule comment in prefer-rest-params doc (#13191) (YeonJuan)
+* [`ffaa4ba`](https://github.com/eslint/eslint/commit/ffaa4ba5e2bb1a51a78a2b2c028cbe2efc9e5165) Sponsors: Sync README with website (ESLint Jenkins)
+* [`932869b`](https://github.com/eslint/eslint/commit/932869b3251b04c4ad5fa72279cb2a56a3e67b55) Sponsors: Sync README with website (ESLint Jenkins)
+* [`54630f0`](https://github.com/eslint/eslint/commit/54630f0063fa66318476473757b5912465d4caf2) Sponsors: Sync README with website (ESLint Jenkins)
+* [`c9a5035`](https://github.com/eslint/eslint/commit/c9a503571a4662f6c2d31cabc7fd7819ec388150) Fix: newBasePath should be an absolute path (fixes #12850) (#13078) (Nick Harris)
+* [`e7c1d4b`](https://github.com/eslint/eslint/commit/e7c1d4b2ac56149a517d4b0000230348a641f1d3) Update: deprecate Node.js & CommonJS rules (#12898) (Kai Cataldo)
+* [`95e1c70`](https://github.com/eslint/eslint/commit/95e1c70cebde210a990ee786ec7ab1c8e522edb8) Upgrade: levn@0.4.1 (fixes #9366) (#13140) (Kai Cataldo)
+* [`c41de38`](https://github.com/eslint/eslint/commit/c41de382a330d4789488fd2dcf6db5a3163bb5d2) Docs: fix curly multi-or-nest examples with comments (refs #12972) (#13151) (Milos Djermanovic)
+* [`57221d5`](https://github.com/eslint/eslint/commit/57221d58c60e757062242f30ed574e0502fc7c31) Docs: fix eslint comment in no-inner-declarations examples (#13152) (Milos Djermanovic)
+* [`301b450`](https://github.com/eslint/eslint/commit/301b450ecd1985ae84d1915124f4638ab2a2e6de) Fix: no-extra-parens export default sequence expression false positive (#13096) (Milos Djermanovic)
+* [`af4472f`](https://github.com/eslint/eslint/commit/af4472fed794b86e63730702e4b27294a4118d09) Update: Improve report location for new-cap (refs #12334) (#13136) (Milos Djermanovic)
+* [`bfa811c`](https://github.com/eslint/eslint/commit/bfa811ceee801fe8ba212a5c879e13743146e909) Fix: init error in extending recommended config (fixes #12707) (#12738) (YeonJuan)
+* [`5dfd4eb`](https://github.com/eslint/eslint/commit/5dfd4eb50d84077a57950f119e5de8976070e49a) Docs: examples with arrow functions in no-return-assign (fixes #13135) (#13138) (Anix)
+* [`adc8fa8`](https://github.com/eslint/eslint/commit/adc8fa88c9f223b984a3519ed159a055bf933b18) Docs: clarify exceptions in spaced-comment (fixes #13032) (#13126) (Anix)
+* [`a784dac`](https://github.com/eslint/eslint/commit/a784dac8bc26f31edbca869b16d6ad91bd4e5cc4) Update: Improve report location newline-per-chained-call (refs #12334) (#13116) (Milos Djermanovic)
+* [`5e07574`](https://github.com/eslint/eslint/commit/5e07574a91861fdcab6888b4c6829868030c3a39) Update: Improve report location for space-before-function-paren (#13128) (Chiawen Chen)
+* [`d0d32a8`](https://github.com/eslint/eslint/commit/d0d32a8c2a6c60c7e6e2d32a054e5987efd4c263) Sponsors: Sync README with website (ESLint Jenkins)
+* [`17e2fe4`](https://github.com/eslint/eslint/commit/17e2fe425168e675fe7607182615e50527eedf53) Update: Improve error message for fatal fixer errors (#13120) (Brad Zacher)
+* [`7551f0c`](https://github.com/eslint/eslint/commit/7551f0c6fd12f0295cc7d6377bf1899c092e79d8) Fix: no check for shadowed Object (fixes #12809) (#13115) (Anix)
+* [`988d842`](https://github.com/eslint/eslint/commit/988d8428811934943ce13b2d8b833d795ac2bb4a) Fix: add end location to report in no-useless-concat (refs #12334) (#13110) (Milos Djermanovic)
+* [`0518ebb`](https://github.com/eslint/eslint/commit/0518ebb840b5bf2d646dbd8a9b3e246e7069eb79) Sponsors: Sync README with website (ESLint Jenkins)
+* [`252fd41`](https://github.com/eslint/eslint/commit/252fd4133805f003151e0220b5d89bbb70cfacb1) Sponsors: Sync README with website (ESLint Jenkins)
+* [`438dcbb`](https://github.com/eslint/eslint/commit/438dcbb981214d67e8848006ce45afc0fbfa1705) Update: Improve report location for comma-style (refs #12334) (#13111) (Chiawen Chen)
+* [`85b7254`](https://github.com/eslint/eslint/commit/85b72548c0c893499c787b82f404348e1b50354d) Update: no-inner-declarations false negative in non-block (fixes #12222) (#13062) (Anix)
+* [`6631ef1`](https://github.com/eslint/eslint/commit/6631ef1678bbdd48680fb3025c3692abd0aeec4a) Update: Improve report location for no-empty-function (refs #12334) (#13121) (Milos Djermanovic)
+* [`b228f95`](https://github.com/eslint/eslint/commit/b228f958afaf507d6f6f99c90b2075b395733839) Docs: Update README team and sponsors (ESLint Jenkins)
+
 v7.0.0-alpha.3 - March 27, 2020
 
 * [`78c8cda`](https://github.com/eslint/eslint/commit/78c8cda5a5d82f5f8548c4528a6438d29756bb71) Breaking: RuleTester Improvements (refs eslint/rfcs#25) (#12955) (Milos Djermanovic)
index a574f25d9a9f5c7d6e5cc55cf78e96c2b2487bed..f5f3fd589ee7d2f9e7a956b643c4b355e4eb759e 100644 (file)
@@ -210,6 +210,9 @@ function generateRuleIndexPage() {
             }
         });
 
+    // `.rules` will be `undefined` if all rules in category are deprecated.
+    categoriesData.categories = categoriesData.categories.filter(category => !!category.rules);
+
     const output = yaml.safeDump(categoriesData, { sortKeys: true });
 
     output.to(outputFile);
@@ -613,7 +616,6 @@ target.gensite = function(prereleaseVersion) {
             htmlFullPath = fullPath.replace(".md", ".html");
 
         if (test("-f", fullPath)) {
-
             rm("-rf", fullPath);
 
             if (filePath.indexOf(".md") >= 0 && test("-f", htmlFullPath)) {
@@ -743,7 +745,7 @@ target.gensite = function(prereleaseVersion) {
     echo(`> Updating files (Steps 4-9)${" ".repeat(50)}`);
 
     // 10. Copy temporary directory to site's docs folder
-    echo("> Copying the temporary directory the site (Step 10)");
+    echo("> Copying the temporary directory into the site's docs folder (Step 10)");
     let outputDir = DOCS_DIR;
 
     if (prereleaseVersion) {
@@ -754,9 +756,13 @@ target.gensite = function(prereleaseVersion) {
     }
     cp("-rf", `${TEMP_DIR}*`, outputDir);
 
-    // 11. Generate rule listing page
-    echo("> Generating the rule listing (Step 11)");
-    generateRuleIndexPage();
+    // 11. Generate rules index page
+    if (prereleaseVersion) {
+        echo("> Skipping generating rules index page because this is a prerelease (Step 11)");
+    } else {
+        echo("> Generating the rules index page (Step 11)");
+        generateRuleIndexPage();
+    }
 
     // 12. Delete temporary directory
     echo("> Removing the temporary directory (Step 12)");
index da75b5c149d799d62357816cfb30e167dedd8c1b..427544bad668c08671ee7497e7b2296e0df2207b 100644 (file)
@@ -214,6 +214,11 @@ The people who review and implement new features.
 <img src="https://github.com/aladdin-add.png?s=75" width="75" height="75"><br />
 薛定谔的猫
 </a>
+</td><td align="center" valign="top" width="11%">
+<a href="https://github.com/mdjermanovic">
+<img src="https://github.com/mdjermanovic.png?s=75" width="75" height="75"><br />
+Milos Djermanovic
+</a>
 </td></tr></tbody></table>
 
 
@@ -233,11 +238,6 @@ Pig Fang
 <img src="https://github.com/yeonjuan.png?s=75" width="75" height="75"><br />
 YeonJuan
 </a>
-</td><td align="center" valign="top" width="11%">
-<a href="https://github.com/mdjermanovic">
-<img src="https://github.com/mdjermanovic.png?s=75" width="75" height="75"><br />
-Milos Djermanovic
-</a>
 </td></tr></tbody></table>
 
 
@@ -250,9 +250,9 @@ The following companies, organizations, and individuals support ESLint's ongoing
 <!-- NOTE: This section is autogenerated. Do not manually edit.-->
 <!--sponsorsstart-->
 <h3>Gold Sponsors</h3>
-<p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/eeb91aa/logo.png" alt="Shopify" height="96"></a> <a href="http://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://magiclab.co/?utm_source=eslint"><img src="https://images.opencollective.com/magiclab/bbf6345/logo.png" alt="MagicLab" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a></p><h3>Silver Sponsors</h3>
+<p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/e780cd4/logo.png" alt="Shopify" 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></p><h3>Silver Sponsors</h3>
 <p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="https://www.kasinot.fi"><img src="https://images.opencollective.com/kasinot-fi/e09aa2e/logo.png" alt="Kasinot.fi" height="32"></a> <a href="https://www.pelisivut.com"><img src="https://images.opencollective.com/pelisivut/04f08f2/logo.png" alt="Pelisivut" height="32"></a> <a href="https://www.nettikasinot.org"><img src="https://images.opencollective.com/nettikasinot-org/bbd887f/logo.png" alt="Nettikasinot.org" height="32"></a> <a href="https://www.bonus.com.de/freispiele"><img src="https://images.opencollective.com/bonusfinder-deutschland/646169e/logo.png" alt="BonusFinder Deutschland" height="32"></a> <a href="https://medium.com/@niksundin/best-web-design-companies-1872e445775f"><img src="https://images.opencollective.com/top-web-design-agencies/d92d747/logo.png" alt="Top Web Design Agencies" height="32"></a> <a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" 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/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/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://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
+<p><a href="https://www.casinotop.com/"><img src="https://images.opencollective.com/casinotop-com/10fd95b/logo.png" alt="CasinoTop.com" height="32"></a> <a href="https://www.casinotopp.net/"><img src="https://images.opencollective.com/casino-topp/1dd399a/logo.png" alt="Casino Topp" height="32"></a> <a href="https://writersperhour.com/urgent-essay-writing-service"><img src="https://images.opencollective.com/writersperhour/5787d4b/logo.png" alt="Writers Per Hour" 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://cooltechzone.com/netflix-vpn"><img src="https://images.opencollective.com/vpn-netflix/4850160/logo.png" alt="vpn netflix" height="32"></a> <a href="https://www.kasinot.fi"><img src="https://images.opencollective.com/kasinot-fi/e09aa2e/logo.png" alt="Kasinot.fi" height="32"></a> <a href="https://www.pelisivut.com"><img src="https://images.opencollective.com/pelisivut/04f08f2/logo.png" alt="Pelisivut" height="32"></a> <a href="https://www.nettikasinot.org"><img src="https://images.opencollective.com/nettikasinot-org/bbd887f/logo.png" alt="Nettikasinot.org" height="32"></a> <a href="https://www.bonus.com.de/freispiele"><img src="https://images.opencollective.com/bonusfinder-deutschland/646169e/logo.png" alt="BonusFinder Deutschland" height="32"></a> <a href="https://medium.com/@niksundin/best-web-design-companies-1872e445775f"><img src="https://images.opencollective.com/top-web-design-agencies/d92d747/logo.png" alt="Top Web Design Agencies" height="32"></a> <a href="https://www.bugsnag.com/platforms?utm_source=Open Collective&utm_medium=Website&utm_content=open-source&utm_campaign=2019-community&utm_term="><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" 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/0b37d14/logo.png" alt="Free Icons by Icons8" height="32"></a> <a href="https://uxplanet.org/top-ui-ux-design-agencies-user-experience-firms-8c54697e290"><img src="https://images.opencollective.com/ui-ux-design-agencies/cae5dfe/logo.png" alt="UI UX Design Agencies" height="32"></a> <a href="https://clay.global"><img src="https://images.opencollective.com/clayglobal/2468f34/logo.png" alt="clay" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/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://tekhattan.com"><img src="https://images.opencollective.com/tekhattan/bc73c28/logo.png" alt="TekHattan" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
 <!--sponsorsend-->
 
 ## <a name="technology-sponsors"></a>Technology Sponsors
index a9f51f1d7d4c572364ae0cc2d470a13f1b65f0ae..75b413148695e564664fc168130158071fb69480 100755 (executable)
 // to use V8's code cache to speed up instantiation time
 require("v8-compile-cache");
 
-//------------------------------------------------------------------------------
-// Helpers
-//------------------------------------------------------------------------------
-
-const useStdIn = process.argv.includes("--stdin"),
-    init = process.argv.includes("--init"),
-    debug = process.argv.includes("--debug");
-
 // must do this initialization *before* other requires in order to work
-if (debug) {
+if (process.argv.includes("--debug")) {
     require("debug").enable("eslint:*,-eslint:code-path");
 }
 
 //------------------------------------------------------------------------------
-// Requirements
+// Helpers
 //------------------------------------------------------------------------------
 
-// now we can safely include the other modules that use debug
-const path = require("path"),
-    fs = require("fs"),
-    cli = require("../lib/cli");
-
-//------------------------------------------------------------------------------
-// Execution
-//------------------------------------------------------------------------------
+/**
+ * Read data from stdin til the end.
+ *
+ * Note: See
+ * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin
+ * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io
+ * - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html
+ * - https://github.com/nodejs/node/issues/7439 (historical)
+ *
+ * On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems
+ * to read 4096 bytes before blocking and never drains to read further data.
+ *
+ * The investigation on the Emacs thread indicates:
+ *
+ * > Emacs on MS-Windows uses pipes to communicate with subprocesses; a
+ * > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than
+ * > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for
+ * > the subprocess to read its end of the pipe, at which time Emacs will
+ * > write the rest of the stuff.
+ * @returns {Promise<string>} The read text.
+ */
+function readStdin() {
+    return new Promise((resolve, reject) => {
+        let content = "";
+        let chunk = "";
+
+        process.stdin
+            .setEncoding("utf8")
+            .on("readable", () => {
+                while ((chunk = process.stdin.read()) !== null) {
+                    content += chunk;
+                }
+            })
+            .on("end", () => resolve(content))
+            .on("error", reject);
+    });
+}
 
-process.once("uncaughtException", err => {
+/**
+ * Get the error message of a given value.
+ * @param {any} error The value to get.
+ * @returns {string} The error message.
+ */
+function getErrorMessage(error) {
 
-    // lazy load
+    // Lazy loading because those are used only if error happened.
+    const fs = require("fs");
+    const path = require("path");
+    const util = require("util");
     const lodash = require("lodash");
 
-    if (typeof err.messageTemplate === "string" && err.messageTemplate.length > 0) {
-        const template = lodash.template(fs.readFileSync(path.resolve(__dirname, `../messages/${err.messageTemplate}.txt`), "utf-8"));
-        const pkg = require("../package.json");
+    // Foolproof -- thirdparty module might throw non-object.
+    if (typeof error !== "object" || error === null) {
+        return String(error);
+    }
+
+    // Use templates if `error.messageTemplate` is present.
+    if (typeof error.messageTemplate === "string") {
+        try {
+            const templateFilePath = path.resolve(
+                __dirname,
+                `../messages/${error.messageTemplate}.txt`
+            );
+
+            // Use sync API because Node.js should exit at this tick.
+            const templateText = fs.readFileSync(templateFilePath, "utf-8");
+            const template = lodash.template(templateText);
+
+            return template(error.messageData || {});
+        } catch {
+
+            // Ignore template error then fallback to use `error.stack`.
+        }
+    }
 
-        console.error("\nOops! Something went wrong! :(");
-        console.error(`\nESLint: ${pkg.version}.\n\n${template(err.messageData || {})}`);
-    } else {
-        console.error(err.stack);
+    // Use the stacktrace if it's an error object.
+    if (typeof error.stack === "string") {
+        return error.stack;
     }
 
+    // Otherwise, dump the object.
+    return util.format("%o", error);
+}
+
+/**
+ * Catch and report unexpected error.
+ * @param {any} error The thrown error object.
+ * @returns {void}
+ */
+function onFatalError(error) {
     process.exitCode = 2;
-});
-
-if (useStdIn) {
-
-    /*
-     * Note: See
-     * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin
-     * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io
-     * - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html
-     * - https://github.com/nodejs/node/issues/7439 (historical)
-     *
-     * On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems
-     * to read 4096 bytes before blocking and never drains to read further data.
-     *
-     * The investigation on the Emacs thread indicates:
-     *
-     * > Emacs on MS-Windows uses pipes to communicate with subprocesses; a
-     * > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than
-     * > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for
-     * > the subprocess to read its end of the pipe, at which time Emacs will
-     * > write the rest of the stuff.
-     *
-     * Using the nodejs code example for reading from stdin.
-     */
-    let contents = "",
-        chunk = "";
-
-    process.stdin.setEncoding("utf8");
-    process.stdin.on("readable", () => {
-
-        // Use a loop to make sure we read all available data.
-        while ((chunk = process.stdin.read()) !== null) {
-            contents += chunk;
-        }
-    });
 
-    process.stdin.on("end", () => {
-        process.exitCode = cli.execute(process.argv, contents, "utf8");
-    });
-} else if (init) {
-    const configInit = require("../lib/init/config-initializer");
-
-    configInit.initializeConfig().then(() => {
-        process.exitCode = 0;
-    }).catch(err => {
-        process.exitCode = 1;
-        console.error(err.message);
-        console.error(err.stack);
-    });
-} else {
-    process.exitCode = cli.execute(process.argv);
+    const { version } = require("../package.json");
+    const message = getErrorMessage(error);
+
+    console.error(`
+Oops! Something went wrong! :(
+
+ESLint: ${version}
+
+${message}`);
 }
+
+//------------------------------------------------------------------------------
+// Execution
+//------------------------------------------------------------------------------
+
+(async function main() {
+    process.on("uncaughtException", onFatalError);
+    process.on("unhandledRejection", onFatalError);
+
+    // Call the config initializer if `--init` is present.
+    if (process.argv.includes("--init")) {
+        await require("../lib/init/config-initializer").initializeConfig();
+        return;
+    }
+
+    // Otherwise, call the CLI.
+    process.exitCode = await require("../lib/cli").execute(
+        process.argv,
+        process.argv.includes("--stdin") ? await readStdin() : null
+    );
+}()).catch(onFatalError);
index 6609734950a443ac9d382a502a4e1a2bf9d881a2..cd3b816b6570a21c93037e92114a6c9c2b433043 100644 (file)
@@ -4,7 +4,6 @@
         { "name": "Best Practices", "description": "These rules relate to better ways of doing things to help you avoid problems:" },
         { "name": "Strict Mode", "description": "These rules relate to strict mode directives:" },
         { "name": "Variables", "description": "These rules relate to variable declarations:" },
-        { "name": "Node.js and CommonJS", "description": "These rules relate to code running in Node.js, or in browsers with CommonJS:" },
         { "name": "Stylistic Issues", "description": "These rules relate to style guidelines, and are therefore quite subjective:" },
         { "name": "ECMAScript 6", "description": "These rules relate to ES6, also known as ES2015:" }
     ],
index ee1a7a449705ca31690ea732b6b24b1205fec182..e980445447c567113aaa2a6a8550405984240f00 100644 (file)
@@ -6,6 +6,20 @@ While ESLint is designed to be run on the command line, it's possible to use ESL
 
 ## Table of Contents
 
+* [ESLint]
+    * [constructor()][eslint-constructor]
+    * [lintFiles()][eslint-lintFiles]
+    * [lintText()][eslint-lintText]
+    * [calculateConfigForFile()][eslint-calculateConfigForFile]
+    * [isPathIgnored()][eslint-isPathIgnored]
+    * [loadFormatter()][eslint-loadFormatter]
+    * [static version][eslint-version]
+    * [static outputFixes()][eslint-outputFixes]
+    * [static getErrorResults()][eslint-getErrorResults]
+    * [LintResult type](lintresult)
+    * [LintMessage type](lintmessage)
+    * [EditInfo type](editinfo)
+    * [Formatter type](formatter)
 * [SourceCode](#sourcecode)
     * [splitLines()](#sourcecode-splitlines)
 * [Linter](#linter)
@@ -17,22 +31,361 @@ While ESLint is designed to be run on the command line, it's possible to use ESL
     * [defineParser()](#linter-defineparser)
     * [version](#linter-version)
 * [linter (deprecated)](#linter-1)
-* [CLIEngine](#cliengine)
-    * [executeOnFiles()](#cliengine-executeonfiles)
-    * [resolveFileGlobPatterns()](#cliengine-resolvefileglobpatterns)
-    * [getConfigForFile()](#cliengine-getconfigforfile)
-    * [executeOnText()](#cliengine-executeontext)
-    * [addPlugin()](#cliengine-addplugin)
-    * [isPathIgnored()](#cliengine-ispathignored)
-    * [getFormatter()](#cliengine-getformatter)
-    * [getErrorResults()](#cliengine-geterrorresults)
-    * [outputFixes()](#cliengine-outputfixes)
-    * [getRules()](#cliengine-getrules)
-    * [version](#cliengine-version)
+* [CLIEngine (deprecated)](#cliengine)
 * [RuleTester](#ruletester)
     * [Customizing RuleTester](#customizing-ruletester)
 * [Deprecated APIs](#deprecated-apis)
 
+---
+
+## ESLint class
+
+The `ESLint` class is the primary class to use in Node.js applications.
+
+This class depends on the Node.js `fs` module and the file system, so you cannot use it in browsers. If you want to lint code on browsers, use the [Linter](#linter) class instead.
+
+Here's a simple example of using the `ESLint` class:
+
+```js
+const { ESLint } = require("eslint");
+
+(async function main() {
+  // 1. Create an instance.
+  const eslint = new ESLint();
+
+  // 2. Lint files.
+  const results = await eslint.lintFiles(["lib/**/*.js"]);
+
+  // 3. Format the results.
+  const formatter = await eslint.loadFormatter("stylish");
+  const resultText = formatter.format(results);
+
+  // 4. Output it.
+  console.log(resultText);
+})().catch((error) => {
+  process.exitCode = 1;
+  console.error(error);
+});
+```
+
+And here is an example that autofixes lint problems:
+
+```js
+const { ESLint } = require("eslint");
+
+(async function main() {
+  // 1. Create an instance with the `fix` option.
+  const eslint = new ESLint({ fix: true });
+
+  // 2. Lint files. This doesn't modify target files.
+  const results = await eslint.lintFiles(["lib/**/*.js"]);
+
+  // 3. Modify the files with the fixed code.
+  await ESLint.outputFixes(results);
+
+  // 4. Format the results.
+  const formatter = await eslint.loadFormatter("stylish");
+  const resultText = formatter.format(results);
+
+  // 5. Output it.
+  console.log(resultText);
+})().catch((error) => {
+  process.exitCode = 1;
+  console.error(error);
+});
+```
+
+### ◆ new ESLint(options)
+
+```js
+const eslint = new ESLint(options);
+```
+
+Create a new `ESLint` instance.
+
+#### Parameters
+
+The `ESLint` constructor takes an `options` object. If you omit the `options` object then it uses default values for all options. The `options` object has the following properties.
+
+##### File Enumeration
+
+* `options.cwd` (`string`)<br>
+  Default is `process.cwd()`. The working directory. This must be an absolute path.
+* `options.errorOnUnmatchedPattern` (`boolean`)<br>
+  Default is `true`. Unless set to `false`, the [`eslint.lintFiles()`][eslint-lintfiles] method will throw an error when no target files are found.
+* `options.extensions` (`string[] | null`)<br>
+  Default is `null`. If you pass directory paths to the [`eslint.lintFiles()`][eslint-lintfiles] method, ESLint checks the files in those directories that have the given extensions. For example, when passing the `src/` directory and `extensions` is `[".js", ".ts"]`, ESLint will lint `*.js` and `*.ts` files in `src/`. If `extensions` is `null`, ESLint checks `*.js` files and files that match `overrides[].files` patterns in your configuration.<br>**Note:** This option only applies when you pass directory paths to the [`eslint.lintFiles()`][eslint-lintfiles] method. If you pass glob patterns like `lib/**/*`, ESLint will lint all files matching the glob pattern regardless of extension.
+* `options.globInputPaths` (`boolean`)<br>
+  Default is `true`. If `false` is present, the [`eslint.lintFiles()`][eslint-lintfiles] method doesn't interpret glob patterns.
+* `options.ignore` (`boolean`)<br>
+  Default is `true`. If `false` is present, the [`eslint.lintFiles()`][eslint-lintfiles] method doesn't respect `.eslintignore` files or `ignorePatterns` in your configuration.
+* `options.ignorePath` (`string | null`)<br>
+  Default is `null`. The path to a file ESLint uses instead of `$CWD/.eslintignore`. If a path is present and the file doesn't exist, this constructor will throw an error.
+
+##### Linting
+
+* `options.allowInlineConfig` (`boolean`)<br>
+  Default is `true`. If `false` is present, ESLint suppresses directive comments in source code. If this option is `false`, it overrides the `noInlineConfig` setting in your configurations.
+* `options.baseConfig` (`ConfigData | null`)<br>
+  Default is `null`. [Configuration object], extended by all configurations used with this instance. You can use this option to define the default settings that will be used if your configuration files don't configure it.
+* `options.overrideConfig` (`ConfigData | null`)<br>
+  Default is `null`. [Configuration object], overrides all configurations used with this instance. You can use this option to define the settings that will be used even if your configuration files configure it.
+* `options.overrideConfigFile` (`string | null`)<br>
+  Default is `null`. The path to a configuration file, overrides all configurations used with this instance. The `options.overrideConfig` option is applied after this option is applied.
+* `options.plugins` (`Record<string, Plugin> | null`)<br>
+  Default is `null`. The plugin implementations that ESLint uses for the `plugins` setting of your configuration. This is a map-like object. Those keys are plugin IDs and each value is implementation.
+* `options.reportUnusedDisableDirectives` (`"error" | "warn" | "off" | null`)<br>
+  Default is `null`. The severity to report unused eslint-disable directives. If this option is a severity, it overrides the `reportUnusedDisableDirectives` setting in your configurations.
+* `options.resolvePluginsRelativeTo` (`string` | `null`)<br>
+  Default is `null`. The path to a directory where plugins should be resolved from. If `null` is present, ESLint loads plugins from the location of the configuration file that contains the plugin setting. If a path is present, ESLint loads all plugins from there.
+* `options.rulePaths` (`string[]`)<br>
+  Default is `[]`. An array of paths to directories to load custom rules from.
+* `options.useEslintrc` (`boolean`)<br>
+  Default is `true`. If `false` is present, ESLint doesn't load configuration files (`.eslintrc.*` files). Only the configuration of the constructor options is valid.
+
+##### Autofix
+
+* `options.fix` (`boolean | (message: LintMessage) => boolean`)<br>
+  Default is `false`. If `true` is present, the [`eslint.lintFiles()`][eslint-lintfiles] and [`eslint.lintText()`][eslint-linttext] methods work in autofix mode. If a predicate function is present, the methods pass each lint message to the function, then use only the lint messages for which the function returned `true`.
+* `options.fixTypes` (`("problem" | "suggestion" | "layout")[] | null`)<br>
+  Default is `null`. The types of the rules that the [`eslint.lintFiles()`][eslint-lintfiles] and [`eslint.lintText()`][eslint-linttext] methods use for autofix.
+
+##### Cache-related
+
+* `options.cache` (`boolean`)<br>
+  Default is `false`. If `true` is present, the [`eslint.lintFiles()`][eslint-lintfiles] method caches lint results and uses it if each target file is not changed. Please mind that ESLint doesn't clear the cache when you upgrade ESLint plugins. In that case, you have to remove the cache file manually. The [`eslint.lintText()`][eslint-linttext] method doesn't use caches even if you pass the `options.filePath` to the method.
+* `options.cacheLocation` (`string`)<br>
+  Default is `.eslintcache`. The [`eslint.lintFiles()`][eslint-lintfiles] method writes caches into this file.
+
+### ◆ eslint.lintFiles(patterns)
+
+```js
+const results = await eslint.lintFiles(patterns);
+```
+
+This method lints the files that match the glob patterns and then returns the results.
+
+#### Parameters
+
+* `patterns` (`string | string[]`)<br>
+  The lint target files. This can contain any of file paths, directory paths, and glob patterns.
+
+#### Return Value
+
+* (`Promise<LintResult[]>`)<br>
+  The promise that will be fulfilled with an array of [LintResult] objects.
+
+### ◆ eslint.lintText(code, options)
+
+```js
+const results = await eslint.lintText(code, options);
+```
+
+This method lints the given source code text and then returns the results.
+
+By default, this method uses the configuration that applies to files in the current working directory (the `cwd` constructor option). If you want to use a different configuration, pass `options.filePath`, and ESLint will load the same configuration that [`eslint.lintFiles()`][eslint-lintfiles] would use for a file at `options.filePath`.
+
+If the `options.filePath` value is configured to be ignored, this method returns an empty array. If the `options.warnIgnored` option is set along with the `options.filePath` option, this method returns a [LintResult] object. In that case, the result may contain a warning that indicates the file was ignored.
+
+#### Parameters
+
+The second parameter `options` is omittable.
+
+* `code` (`string`)<br>
+  The source code text to check.
+* `options.filePath` (`string`)<br>
+  Optional. The path to the file of the source code text. If omitted, the `result.filePath` becomes the string `"<text>"`.
+* `options.warnIgnored` (`boolean`)<br>
+  Optional. If `true` is present and the `options.filePath` is a file ESLint should ignore, this method returns a lint result contains a warning message.
+
+#### Return Value
+
+* (`Promise<LintResult[]>`)<br>
+  The promise that will be fulfilled with an array of [LintResult] objects. This is an array (despite there being only one lint result) in order to keep the interfaces between this and the [`eslint.lintFiles()`][eslint-lintfiles] method similar.
+
+### ◆ eslint.calculateConfigForFile(filePath)
+
+```js
+const config = await eslint.calculateConfigForFile(filePath);
+```
+
+This method calculates the configuration for a given file, which can be useful for debugging purposes.
+
+* It resolves and merges `extends` and `overrides` settings into the top level configuration.
+* It resolves the `parser` setting to absolute paths.
+* It normalizes the `plugins` setting to align short names. (e.g., `eslint-plugin-foo` → `foo`)
+* It adds the `processor` setting if a legacy file extension processor is matched.
+* It doesn't interpret the `env` setting to the `globals` and `parserOptions` settings, so the result object contains the `env` setting as is.
+
+#### Parameters
+
+* `filePath` (`string`)<br>
+  The path to the file whose configuration you would like to calculate. Directory paths are forbidden because ESLint cannot handle the `overrides` setting.
+
+#### Return Value
+
+* (`Promise<Object>`)<br>
+  The promise that will be fulfilled with a configuration object.
+
+### ◆ eslint.isPathIgnored(filePath)
+
+```js
+const isPathIgnored = await eslint.isPathIgnored(filePath);
+```
+
+This method checks if a given file is ignored by your configuration.
+
+#### Parameters
+
+* `filePath` (`string`)<br>
+  The path to the file you want to check.
+
+#### Return Value
+
+* (`Promise<boolean>`)<br>
+  The promise that will be fulfilled with whether the file is ignored or not. If the file is ignored, then it will return `true`.
+
+### ◆ eslint.loadFormatter(nameOrPath)
+
+```js
+const formatter = await eslint.loadFormatter(nameOrPath);
+```
+
+This method loads a formatter. Formatters convert lint results to a human- or machine-readable string.
+
+#### Parameters
+
+* `nameOrPath` (`string | undefined`)<br>
+  The path to the file you want to check. The following values are allowed:
+    * `undefined`. In this case, loads the `"stylish"` built-in formatter.
+    * A name of [built-in formatters][builtin-formatters].
+    * A name of [third-party formatters][thirdparty-formatters]. For examples:
+        * `"foo"` will load `eslint-formatter-foo`.
+        * `"@foo"` will load `@foo/eslint-formatter`.
+        * `"@foo/bar"` will load `@foo/eslint-formatter-bar`.
+    * A path to the file that defines a formatter. The path must contain one or more path separators (`/`) in order to distinguish if it's a path or not. For example, start with `./`.
+
+#### Return Value
+
+* (`Promise<Formatter>`)<br>
+  The promise that will be fulfilled with a [Formatter] object.
+
+### ◆ ESLint.version
+
+```js
+const version = ESLint.version;
+```
+
+The version string of ESLint. E.g. `"7.0.0"`.
+
+This is a static property.
+
+### ◆ ESLint.outputFixes(results)
+
+```js
+await ESLint.outputFixes(results);
+```
+
+This method writes code modified by ESLint's autofix feature into its respective file. If any of the modified files don't exist, this method does nothing.
+
+This is a static method.
+
+#### Parameters
+
+* `results` (`LintResult[]`)<br>
+  The [LintResult] objects to write.
+
+#### Return Value
+
+* (`Promise<void>`)<br>
+  The promise that will be fulfilled after all files are written.
+
+### ◆ ESLint.getErrorResults(results)
+
+```js
+const filteredResults = ESLint.getErrorResults(results);
+```
+
+This method copies the given results and removes warnings. The returned value contains only errors.
+
+This is a static method.
+
+#### Parameters
+
+* `results` (`LintResult[]`)<br>
+  The [LintResult] objects to filter.
+
+#### Return Value
+
+* (`LintResult[]`)<br>
+  The filtered [LintResult] objects.
+
+### ◆ LintResult type
+
+The `LintResult` value is the information of the linting result of each file. The [`eslint.lintFiles()`][eslint-lintfiles] and [`eslint.lintText()`][eslint-linttext] methods return it. It has the following properties:
+
+* `filePath` (`string`)<br>
+  The absolute path to the file of this result. This is the string `"<text>"` if the file path is unknown (when you didn't pass the `options.filePath` option to the [`eslint.lintText()`][eslint-linttext] method).
+* `messages` (`LintMessage[]`)<br>
+  The array of [LintMessage] objects.
+* `fixableErrorCount` (`number`)<br>
+  The number of errors that can be fixed automatically by the `fix` constructor option.
+* `fixableWarningCount` (`number`)<br>
+  The number of warnings that can be fixed automatically by the `fix` constructor option.
+* `errorCount` (`number`)<br>
+  The number of errors. This includes fixable errors.
+* `warningCount` (`number`)<br>
+  The number of warnings. This includes fixable warnings.
+* `output` (`string | undefined`)<br>
+  The modified source code text. This property is undefined if any fixable messages didn't exist.
+* `source` (`string | undefined`)<br>
+  The original source code text. This property is undefined if any messages didn't exist or the `output` property exists.
+* `usedDeprecatedRules` (`{ ruleId: string; replacedBy: string[] }[]`)<br>
+  The information about the deprecated rules that were used to check this file.
+
+### ◆ LintMessage type
+
+The `LintMessage` value is the information of each linting error. The `messages` property of the [LintResult] type contains it. It has the following properties:
+
+* `ruleId` (`string` | `null`)<br>
+  The rule name that generates this lint message. If this message is generated by the ESLint core rather than rules, this is `null`.
+* `severity` (`1 | 2`)<br>
+  The severity of this message. `1` means warning and `2` means error.
+* `message` (`string`)<br>
+  The error message.
+* `line` (`number`)<br>
+  The 1-based line number of the begin point of this message.
+* `column` (`number`)<br>
+  The 1-based column number of the begin point of this message.
+* `endLine` (`number | undefined`)<br>
+  The 1-based line number of the end point of this message. This property is undefined if this message is not a range.
+* `endColumn` (`number | undefined`)<br>
+  The 1-based column number of the end point of this message. This property is undefined if this message is not a range.
+* `fix` (`EditInfo | undefined`)<br>
+  The [EditInfo] object of autofix. This property is undefined if this message is not fixable.
+* `suggestions` (`{ desc: string; fix: EditInfo }[] | undefined`)<br>
+  The list of suggestions. Each suggestion is the pair of a description and an [EditInfo] object to fix code. API users such as editor integrations can choose one of them to fix the problem of this message. This property is undefined if this message doesn't have any suggestions.
+
+### ◆ EditInfo type
+
+The `EditInfo` value is information to edit text. The `fix` and `suggestions` properties of [LintMessage] type contain it. It has following properties:
+
+* `range` (`[number, number]`)<br>
+  The pair of 0-based indices in source code text to remove.
+* `text` (`string`)<br>
+  The text to add.
+
+This edit information means replacing the range of the `range` property by the `text` property value. It's like `sourceCodeText.slice(0, edit.range[0]) + edit.text + sourceCodeText.slice(edit.range[1])`. Therefore, it's an add if the `range[0]` and `range[1]` property values are the same value, and it's removal if the `text` property value is empty string.
+
+### ◆ Formatter type
+
+The `Formatter` value is the object to convert the [LintResult] objects to text. The [eslint.loadFormatter()][eslint-loadformatter] method returns it. It has the following method:
+
+* `format` (`(results: LintResult[]) => string`)<br>
+  The method to convert the [LintResult] objects to text.
+
+---
+
 ## SourceCode
 
 The `SourceCode` type represents the parsed source code that ESLint executes on. It's used internally in ESLint and is also available so that already-parsed code can be used. You can create a new instance of `SourceCode` by passing in the text string representing the code and an abstract syntax tree (AST) in [ESTree](https://github.com/estree/estree) format (including location information, range information, comments, and tokens):
@@ -78,6 +431,8 @@ const codeLines = SourceCode.splitLines(code);
  */
 ```
 
+---
+
 ## Linter
 
 The `Linter` object does the actual evaluation of the JavaScript code. It doesn't do any filesystem operations, it simply parses and reports on the code. In particular, the `Linter` object does not process configuration objects or files.
@@ -336,8 +691,12 @@ const messages = linter.verify("var foo;", {
 
 Note: This API is deprecated as of 4.0.0.
 
+---
+
 ## CLIEngine
 
+⚠️ The `CLIEngine` class has been deprecated in favor of the `ESLint` class as of v7.0.0.
+
 The primary Node.js API is `CLIEngine`, which is the underlying utility that runs the ESLint command line interface. This object will read the filesystem for configuration and file information but will not output any results. Instead, it allows you direct access to the important information so you can deal with the output yourself.
 
 You can get a reference to the `CLIEngine` by doing the following:
@@ -819,6 +1178,8 @@ Map {
 require("eslint").CLIEngine.version; // '4.5.0'
 ```
 
+---
+
 ## RuleTester
 
 `eslint.RuleTester` is a utility to write tests for ESLint rules. It is used internally for the bundled rules that come with ESLint, and it can also be used by plugins.
@@ -1007,7 +1368,31 @@ ruleTester.run("my-rule", myRule, {
 })
 ```
 
+---
+
 ## Deprecated APIs
 
 * `cli` - the `cli` object has been deprecated in favor of `CLIEngine`. As of v1.0.0, `cli` is no longer exported and should not be used by external tools.
 * `linter` - the `linter` object has been deprecated in favor of `Linter` as of v4.0.0.
+* `CLIEngine` - the `CLIEngine` class has been deprecated in favor of the `ESLint` class as of v7.0.0.
+
+---
+
+[configuration object]: ../user-guide/configuring.md
+[builtin-formatters]: https://eslint.org/docs/user-guide/formatters/
+[thirdparty-formatters]: https://www.npmjs.com/search?q=eslintformatter
+[eslint]: #eslint-class
+[eslint-constructor]: #-new-eslintoptions
+[eslint-lintfiles]: #-eslintlintFilespatterns
+[eslint-linttext]: #-eslintlintTextcode-options
+[eslint-calculateconfigforfile]: #-eslintcalculateConfigForFilefilePath
+[eslint-ispathignored]: #-eslintisPathIgnoredfilePath
+[eslint-loadformatter]: #-eslintloadFormatternameOrPath
+[eslint-version]: #-eslintversion
+[eslint-outputfixes]: #-eslintoutputFixesresults
+[eslint-geterrorresults]: #-eslintgetErrorResultsresults
+[lintresult]: #-lintresult-type
+[lintmessage]: #-lintmessage-type
+[editinfo]: #-editinfo-type
+[formatter]: #-formatter-type
+[linter]: #linter
index c0a5ad8ab3510e48ff929428d49f93c0d088747f..84bf0e7710d556f5133ae1bdb079a2a99afff91e 100644 (file)
@@ -13,7 +13,7 @@ var indexMap = myArray.reduce(function(memo, item, index) {
 ## Rule Details
 
 This rule enforces usage of `return` statement in callbacks of array's methods.
-Additionaly, it may also enforce the `forEach` array method callback to __not__ return a value by using the `checkForEach` option.
+Additionally, it may also enforce the `forEach` array method callback to __not__ return a value by using the `checkForEach` option.
 
 This rule finds callback functions of the following methods, then checks usage of `return` statement.
 
index ba27e23340dabc7044c3d388e703c5c4866aed80..f425ccd3f257e5348c4166d16dfff874bb140469 100644 (file)
@@ -1,5 +1,7 @@
 # Enforce Return After Callback (callback-return)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 The callback pattern is at the heart of most I/O and event-driven programming
  in JavaScript.
 
index 9f4df27353cd1200f92c2c68a42e9e1073853ab7..aecbca5576ef9a3048b7bcd934a16230c0bfab50 100644 (file)
@@ -181,10 +181,6 @@ while (true) {
 for (var i = 0; foo; i++) {
     doSomething();
 }
-
-if (foo)
-    // some comment
-    bar();
 ```
 
 Examples of **correct** code for the `"multi-or-nest"` option:
@@ -214,6 +210,18 @@ while (true)
 
 for (var i = 0; foo; i++)
     doSomething();
+```
+
+For single-line statements preceded by a comment, braces are allowed but not required.
+
+Examples of additional **correct** code for the `"multi-or-nest"` option:
+
+```js
+/*eslint curly: ["error", "multi-or-nest"]*/
+
+if (foo)
+    // some comment
+    bar();
 
 if (foo) {
     // some comment
index c31134dcc621d6e82cd9b26c3daa850842ae8548..a81d5a3a50690da0ab6c35b038dfb0d86e59c94a 100644 (file)
@@ -1,5 +1,7 @@
 # Enforce require() on the top-level module scope (global-require)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 In Node.js, module dependencies are included using the `require()` function, such as:
 
 ```js
index 5733e421729ecb0b64b55e0797ab4c29226b6210..dad537e9695cffa9aad5831da137389667fa8242 100644 (file)
@@ -1,5 +1,7 @@
 # Enforce Callback Error Handling (handle-callback-err)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 In Node.js, a common pattern for dealing with asynchronous behavior is called the callback pattern.
 This pattern expects an `Error` object or `null` as the first argument of the callback.
 Forgetting to handle these errors can lead to some really strange behavior in your application.
index f287ce57343c4f84e4c19b0a72fc96ce82070293..9902a71605f5e0efbbdb0347c6c59f4a2f63ce80 100644 (file)
@@ -1,5 +1,7 @@
 # disallow use of the Buffer() constructor (no-buffer-constructor)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 In Node.js, the behavior of the `Buffer` constructor is different depending on the type of its argument. Passing an argument from user input to `Buffer()` without validating its type can lead to security vulnerabilities such as remote memory disclosure and denial of service. As a result, the `Buffer` constructor has been deprecated and should not be used. Use the producer methods `Buffer.from`, `Buffer.alloc`, and `Buffer.allocUnsafe` instead.
 
 ## Rule Details
index 23fd9253b1052ed8ead2484dc28f01cd5cca0d0f..707fc6e781fa698060b8f48944fbea952c046c83 100644 (file)
@@ -81,6 +81,8 @@ function doSomethingElse() {
         function doAnotherThing() { }
     }
 }
+
+if (foo) function f(){}
 ```
 
 Examples of **correct** code for this rule with the default `"functions"` option:
@@ -102,6 +104,8 @@ var fn;
 if (test) {
     fn = function fnExpression() { };
 }
+
+if (foo) var a;
 ```
 
 ### both
@@ -120,12 +124,17 @@ function doAnotherThing() {
         var bar = 81;
     }
 }
+
+
+if (foo) var a;
+
+if (foo) function f(){}
 ```
 
 Examples of **correct** code for this rule with the `"both"` option:
 
 ```js
-/*eslint no-inner-declarations: "error"*/
+/*eslint no-inner-declarations: ["error", "both"]*/
 /*eslint-env es6*/
 
 var bar = 42;
index ee63c99090a21ae3ba871b851b3306e34901e919..c697d04e865deb57376c59184084f6640a9773a7 100644 (file)
@@ -1,5 +1,7 @@
 # disallow `require` calls to be mixed with regular variable declarations (no-mixed-requires)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 In the Node.js community it is often customary to separate initializations with calls to `require` modules from other variable declarations, sometimes also grouping them by the type of module. This rule helps you enforce this convention.
 
 ## Rule Details
index 5186682fc058effa107de7569ba1ea61b62d52f3..aef055c810b552086524018e5e076c428763ce9a 100644 (file)
@@ -27,7 +27,7 @@ Examples of **incorrect** code for this rule:
 
 var myObject = new Object();
 
-var myObject = new Object;
+new Object();
 ```
 
 Examples of **correct** code for this rule:
@@ -38,6 +38,9 @@ Examples of **correct** code for this rule:
 var myObject = new CustomObject();
 
 var myObject = {};
+
+var Object = function Object() {};
+new Object();
 ```
 
 ## When Not To Use It
index 5ffaf2ad46441fcaa9473404bd26a3fea8ee2b6c..6cf1242f72bef45f7e28deb7890898e670b78c6d 100644 (file)
@@ -1,5 +1,7 @@
 # Disallow new require (no-new-require)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 The `require` function is used to include modules that exist in separate files, such as:
 
 ```js
index 998ec10d9785c586b00126c6f98f019fc6953820..fddf27b9e450436acbdc5143aac778a5ffdc5bda 100644 (file)
@@ -1,5 +1,7 @@
 # Disallow string concatenation when using `__dirname` and `__filename` (no-path-concat)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 In Node.js, the `__dirname` and `__filename` global variables contain the directory path and the file path of the currently executing script file, respectively. Sometimes, developers try to use these variables to create paths to other files, such as:
 
 ```js
index 9db800fa153747d1587a4a72b69de558bf8b11b3..83bfa6d02acb5cc28332ea471f35ded1ae005881 100644 (file)
@@ -1,5 +1,7 @@
 # Disallow process.env (no-process-env)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 The `process.env` object in Node.js is used to store deployment/configuration parameters. Littering it through out a project could lead to maintenance issues as it's another kind of global dependency. As such, it could lead to merge conflicts in a multi-user setup and deployment issues in a multi-server setup. Instead, one of the best practices is to define all those parameters in a single configuration/settings file which could be accessed throughout the project.
 
 
index 0070a0965f10ac62b73bc582a36c21bbc55ac49f..54f2661ae2c8ef30cd587c685a469ed5cb897c9d 100644 (file)
@@ -1,5 +1,7 @@
 # Disallow process.exit() (no-process-exit)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 The `process.exit()` method in Node.js is used to immediately stop the Node.js process and exit. This is a dangerous operation because it can occur in any method at any point in time, potentially stopping a Node.js application completely when an error occurs. For example:
 
 ```js
index 7f9c926a1ef98bda9865392ba6cf34592cc41bb4..3fc412fe5d66f83d2d99e7ec0612d0eb07514d50 100644 (file)
@@ -1,5 +1,7 @@
 # Disallow Node.js modules (no-restricted-modules)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 A module in Node.js is a simple or complex functionality organized in a JavaScript file which can be reused throughout the Node.js
 application. The keyword `require` is used in Node.js/CommonJS to import modules into an application. This way you can have dynamic loading where the loaded module name isn't predefined /static, or where you conditionally load a module only if it's "truly required".
 
index 781d5973a78f224a47d788906c4d3f4a89096bb4..ed40c275437d3558e7186792e67273ae771738c9 100644 (file)
@@ -40,6 +40,14 @@ function doSomething() {
 function doSomething() {
     return foo += 2;
 }
+
+const foo = (a, b) => a = b
+
+const bar = (a, b, c) => (a = b, c == b)
+
+function doSomething() {
+    return foo = bar && foo > 0;
+}
 ```
 
 Examples of **correct** code for the default `"except-parens"` option:
@@ -58,6 +66,14 @@ function doSomething() {
 function doSomething() {
     return (foo = bar + 2);
 }
+
+const foo = (a, b) => (a = b)
+
+const bar = (a, b, c) => ((a = b), c == b)
+
+function doSomething() {
+    return (foo = bar) && foo > 0;
+}
 ```
 
 ### always
index 50ab515eef5dbe10087dd857c9829ede50155b77..949df6d36b429e1a038ee635ae5081b1dc9ce5df 100644 (file)
@@ -1,5 +1,7 @@
 # Disallow Synchronous Methods (no-sync)
 
+This rule was **deprecated** in ESLint v7.0.0. Please use the corresponding rule in [`eslint-plugin-node`](https://github.com/mysticatea/eslint-plugin-node).
+
 In Node.js, most I/O is done through asynchronous methods. However, there are often synchronous versions of the asynchronous methods. For example, `fs.exists()` and `fs.existsSync()`. In some contexts, using synchronous operations is okay (if, as with ESLint, you are writing a command line utility). However, in other contexts the use of synchronous operations is considered a bad practice that should be avoided. For example, if you are running a high-travel web server on Node.js, you should consider carefully if you want to allow any synchronous operations that could lock up the server.
 
 ## Rule Details
index 4e1cce7043a9214049109f5c20553f21314e21c7..eabc03eacf4c1a1488953cd091619f388b57f3e3 100644 (file)
@@ -498,6 +498,9 @@ import {
     foo,
     bar
 } from 'foo-bar';
+import {
+    foo, bar
+} from 'foo-bar';
 import {
     foo as f,
     bar
index 6930b4fa75b23d4fd5ec541aef78ced60d1b88bf..c67e744cc595eca47f3c4f272268e0a8a2edbf6c 100644 (file)
@@ -14,6 +14,8 @@ This rule is aimed to flag usage of `arguments` variables.
 Examples of **incorrect** code for this rule:
 
 ```js
+/*eslint prefer-rest-params: "error"*/
+
 function foo() {
     console.log(arguments);
 }
@@ -32,6 +34,8 @@ function foo(action) {
 Examples of **correct** code for this rule:
 
 ```js
+/*eslint prefer-rest-params: "error"*/
+
 function foo(...args) {
     console.log(args);
 }
index 3d0a5d9a90b11cc1db9146e649201e56d6d99926..5a885f9821b9503285182d40ca8fd5f1f730f379 100644 (file)
@@ -21,7 +21,7 @@ The rule takes two options.
 
 * This rule can also take a 2nd option, an object with any of the following keys: `"exceptions"` and `"markers"`.
 
-    * The `"exceptions"` value is an array of string patterns which are considered exceptions to the rule.
+    * The `"exceptions"` value is an array of string patterns which are considered exceptions to the rule. The rule will not warn when the pattern starts from the beginning of the comment and repeats until the end of the line or `*/` if the comment is a single line comment.
     Please note that exceptions are ignored if the first argument is `"never"`.
 
     ```
@@ -175,6 +175,12 @@ Examples of **incorrect** code for this rule with the `"always"` option combined
 /*-+-+-+-+-+-+-+*/
 ```
 
+```js
+/* eslint spaced-comment: ["error", "always", { "block": { "exceptions": ["*"] } }] */
+
+/******** COMMENT *******/
+```
+
 Examples of **correct** code for this rule with the `"always"` option combined with `"exceptions"`:
 
 ```js
@@ -221,6 +227,16 @@ Examples of **correct** code for this rule with the `"always"` option combined w
 /*-+-+-+-+-+-+-+*/
 ```
 
+```js
+/* eslint spaced-comment: ["error", "always", { "block": { "exceptions": ["*"] } }] */
+
+/***************/
+
+/********
+COMMENT
+*******/
+```
+
 ### markers
 
 Examples of **incorrect** code for this rule with the `"always"` option combined with `"markers"`:
index 31160d161896abf9f9bea1ec2eda7766430af803..7339bfe08d1ab63e0680563f8ed9e2b79114edee 100644 (file)
@@ -36,3 +36,4 @@ If you were using a prior version of ESLint, you can get help with the transitio
 - [migrating-to-4.0.0](migrating-to-4.0.0.md)
 - [migrating-to-5.0.0](migrating-to-5.0.0.md)
 - [migrating-to-6.0.0](migrating-to-6.0.0.md)
+- [migrating-to-7.0.0](migrating-to-7.0.0.md)
diff --git a/eslint/docs/user-guide/migrating-to-7.0.0.md b/eslint/docs/user-guide/migrating-to-7.0.0.md
new file mode 100644 (file)
index 0000000..cb39336
--- /dev/null
@@ -0,0 +1,232 @@
+# Migrating to v7.0.0
+
+ESLint v7.0.0 is a major release of ESLint. We have made a few breaking changes in this release. This guide is intended to walk you through the breaking changes.
+
+The lists below are ordered roughly by the number of users each change is expected to affect, where the first items are expected to affect the most users.
+
+## Table of Content
+
+### Breaking changes for users
+
+- [Node.js 8 is no longer supported](#drop-node-8)
+- [Lint files matched by `overrides[].files` by default](#additional-lint-targets)
+- [The base path of `overrides` and `ignorePatterns` is changed if the config file is given by the `--config`/`--ignore-path` options](#base-path-change)
+- [The place where ESLint loads plugins from is changed](#plugin-loading-change)
+- [Runtime deprecation warnings for `~/.eslintrc.*` config files](#runtime-deprecation-on-personal-config-files)
+- [Default ignore patterns have changed](#default-ignore-patterns)
+- [Description in directive comments](#description-in-directive-comments)
+- [Node.js/CommonJS rules are deprecated](#deprecate-node-rules)
+- [Several rules have been updated to cover more cases](#rules-strict)
+- [`eslint:recommended` has been updated](#eslint-recommended)
+
+### Breaking changes for plugin developers
+
+- [Node.js 8 is no longer supported](#drop-node-8)
+- [Lint files matched by `overrides[].files` by default](#additional-lint-targets)
+- [Plugin resolution has been updated](#plugin-loading-change)
+- [Additional validation added to the `RuleTester` class](#rule-tester-strict)
+
+### Breaking changes for integration developers
+
+- [Node.js 8 is no longer supported](#drop-node-8)
+- [Plugin resolution has been updated](#plugin-loading-change)
+- [The `CLIEngine` class has been deprecated](#deprecate-cliengine)
+
+---
+
+## <a name="drop-node-8"></a> Node.js 8 is no longer supported
+
+Node.js 8 reached EOL in December 2019, and we are officially dropping support for it in this release. ESLint now supports the following versions of Node.js:
+
+- Node.js 10 (`10.12.0` and above)
+- Node.js 12 and above
+
+**To address:** Make sure you upgrade to at least Node.js `10.12.0` when using ESLint v7.0.0. One important thing to double check is the Node.js version supported by your editor when using ESLint via editor integrations. If you are unable to upgrade, we recommend continuing to use ESLint 6 until you are able to upgrade Node.js.
+
+**Related issue(s):** [RFC44](https://github.com/eslint/rfcs/blob/master/designs/2019-drop-node8/README.md), [#12700](https://github.com/eslint/eslint/pull/12700)
+
+## <a name="additional-lint-targets"></a> Lint files matched by `overrides[].files` by default
+
+Previously to v7.0.0, ESLint would only lint files with a `.js` extension by default if you give directories like `eslint src`.
+
+ESLint v7.0.0 will now additionally lint files with other extensions (`.ts`, `.vue`, etc.) if the extension is explicitly matched by an `overrides[].files` entry. This will allow for users to lint files that don't end with `*.js` to be linted without having to use the `--ext` command line flag, as well as allow shared configuration authors to enable linting of these files without additional overhead for the end user. Please note that patterns that end with `*` are exempt from this behavior and will behave as they did previously. For example, if the following config file is present,
+
+```yml
+# .eslintrc.yml
+extends: my-config-js
+overrides:
+  - files: "*.ts"
+    extends: my-config-ts
+```
+
+then running `eslint src` would check both `*.js` and `*.ts` files in the `src` directory.
+
+**To address:** Using the `--ext` CLI option will override this new behavior. Run ESLint with `--ext .js`  if you are using `overrides` but only want to lint files that have a `.js` extension.
+
+If you maintain plugins that check files with extensions other than `.js`, this feature will allow you to check these files by default by configuring an `overrides` setting in your `recommended` preset.
+
+**Related issue(s):** [RFC20](https://github.com/eslint/rfcs/blob/master/designs/2019-additional-lint-targets/README.md), [#12677](https://github.com/eslint/eslint/pull/12677)
+
+## <a name="base-path-change"></a> The base path of `overrides` and `ignorePatterns` has changed when using the `--config`/`--ignore-path` options
+
+Up until now, ESLint has resolved the following paths relative to the directory path of the _entry_ configuration file:
+
+- Configuration files (`.eslintrc.*`)
+    - relative paths in the `overrides[].files` setting
+    - relative paths in the `overrides[].excludedFiles` setting
+    - paths which start with `/` in the `ignorePatterns` setting
+- Ignore files (`.eslintignore`)
+    - paths which start with `/`
+
+Starting in ESLint v7.0.0, configuration files and ignore files passed to ESLint using the `--config path/to/a-config` and `--ignore-path path/to/a-ignore` CLI flags, respectively, will resolve from the current working directory rather than the file location. This allows for users to utilize shared plugins without having to install them directly in their project.
+
+**To address:** Update the affected paths if you are using a configuration or ignore file via the `--config` or `--ignore-path` CLI options.
+
+**Related issue(s):** [RFC37](https://github.com/eslint/rfcs/blob/master/designs/2019-changing-base-path-in-config-files-that-cli-options-specify/README.md), [#12887](https://github.com/eslint/eslint/pull/12887)
+
+## <a name="plugin-loading-change"></a> Plugin resolution has been updated
+
+In previous versions, ESLint resolved all plugins from the current working directory by default.
+
+Starting in ESLint v7.0.0, `plugins` are resolved relative to the directory path of the _entry_ configuration file.
+
+This will not change anything in most cases. If a configuration file in a subdirectory has `plugins` defined, the plugins will be loaded from the subdirectory (or ancestor directories that include the current working directory if not found).
+
+This means that if you are using a config file from a shared location via `--config` option, the plugins that the config file declare will be loaded from the shared config file location.
+
+**To address:** Ensure that plugins are installed in a place that can be resolved relative to your configuration file or use `--resolve-plugins-relative-to .` to override this change.
+
+**Related issue(s):** [RFC47](https://github.com/eslint/rfcs/blob/master/designs/2019-plugin-loading-improvement/README.md), [#12922](https://github.com/eslint/eslint/pull/12922)
+
+## <a name="runtime-deprecation-on-personal-config-files"></a> Runtime deprecation warnings for `~/.eslintrc.*` config files
+
+Personal config files have been deprecated since [v6.7.0](https://eslint.org/blog/2019/11/eslint-v6.7.0-released). ESLint v7.0.0 will start printing runtime deprecation warnings. It will print a warning for the following situations:
+
+1. When a project does not have a configuration file present and ESLint loads configuration from `~/.eslintrc.*`.
+1. When a project has a configuration file and ESLint ignored a `~/.eslintrc.*` configuration file. This occurs when the `$HOME` directory is an ancestor directory of the project and the project's configuration files doesn't contain `root:true`.
+
+**To address:** Remove `~/.eslintrc.*` configuration files and add a `.eslintrc.*` configuration file to your project. Alternatively, use the `--config` option to use shared config files.
+
+**Related issue(s):** [RFC32](https://github.com/eslint/rfcs/tree/master/designs/2019-deprecating-personal-config/README.md), [#12678](https://github.com/eslint/eslint/pull/12678)
+
+## <a name="default-ignore-patterns"></a> Default ignore patterns have changed
+
+Up until now, ESLint has ignored the following files by default:
+
+- Dotfiles (`.*`)
+- `node_modules` in the current working directory (`/node_modules/*`)
+- `bower_components` in the current working directory (`/bower_components/*`)
+
+ESLint v7.0.0 ignores `node_modules/*` of subdirectories as well, but no longer ignores `bower_components/*` and `.eslintrc.js`. Therefore, the new default ignore patterns are:
+
+- Dotfiles except `.eslintrc.*` (`.*` but not `.eslintrc.*`)
+- `node_modules` (`/**/node_modules/*`)
+
+**To address:** Modify your `.eslintignore` or the `ignorePatterns` property of your config file if you don't want to lint `bower_components/*` and `.eslintrc.js`.
+
+**Related issue(s):** [RFC51](https://github.com/eslint/rfcs/blob/master/designs/2019-update-default-ignore-patterns/README.md), [#12888](https://github.com/eslint/eslint/pull/12888)
+
+## <a name="description-in-directive-comments"></a> Descriptions in directive comments
+
+In older version of ESLint, there was no convenient way to indicate why a directive comment – such as `/*eslint-disable*/` – was necessary.
+
+To allow for the colocation of comments that provide context with the directive, ESLint v7.0.0 adds the ability to append arbitrary text in directive comments by ignoring text following `--` surrounded by whitespace. For example:
+
+```js
+// eslint-disable-next-line a-rule, another-rule -- those are buggy!!
+```
+
+**To address:** If you have `--` surrounded by whitespace in directive comments, consider moving it into your configuration file.
+
+**Related issue(s):** [RFC33](https://github.com/eslint/rfcs/blob/master/designs/2019-description-in-directive-comments/README.md), [#12699](https://github.com/eslint/eslint/pull/12699)
+
+## <a name="deprecate-node-rules"></a> Node.js/CommonJS rules have been deprecated
+
+The ten Node.js/CommonJS rules in core have been deprecated and moved to the [eslint-plugin-node](https://github.com/mysticatea/eslint-plugin-node) plugin.
+
+**To address:** As per [our deprecation policy](https://eslint.org/docs/user-guide/rule-deprecation), the deprecated rules will remain in core for the foreseeable future and are still available for use. However, we will no longer be updating or fixing any bugs in those rules. To use a supported version of the rules, we recommend using the corresponding rules in the plugin instead.
+
+| Deprecated Rules                                                             | Replacement                                                                                                                     |
+| :--------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| [callback-return](https://eslint.org/docs/rules/callback-return)             | [node/callback-return](https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/callback-return.md)             |
+| [global-require](https://eslint.org/docs/rules/global-require)               | [node/global-require](https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/global-require.md)               |
+| [handle-callback-err](https://eslint.org/docs/rules/handle-callback-err)     | [node/handle-callback-err](https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/handle-callback-err.md)     |
+| [no-mixed-requires](https://eslint.org/docs/rules/no-mixed-requires)         | [node/no-mixed-requires](https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-mixed-requires.md)         |
+| [no-new-require](https://eslint.org/docs/rules/no-new-require)               | [node/no-new-require](https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-new-require.md)               |
+| [no-path-concat](https://eslint.org/docs/rules/no-path-concat)               | [node/no-path-concat](https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-path-concat.md)               |
+| [no-process-env](https://eslint.org/docs/rules/no-process-env)               | [node/no-process-env](https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-process-env.md)               |
+| [no-process-exit](https://eslint.org/docs/rules/no-process-exit)             | [node/no-process-exit](https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-process-exit.md)             |
+| [no-restricted-modules](https://eslint.org/docs/rules/no-restricted-modules) | [node/no-restricted-require](https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-restricted-require.md) |
+| [no-sync](https://eslint.org/docs/rules/no-sync)                             | [node/no-sync](https://github.com/mysticatea/eslint-plugin-node/blob/v11.1.0/docs/rules/no-sync.md)                             |
+
+**Related issue(s):** [#12898](https://github.com/eslint/eslint/pull/12898)
+
+## <a name="rules-strict"></a> Several rules have been updated to cover more cases
+
+Several rules have been enhanced and now report additional errors:
+
+- [accessor-pairs](https://eslint.org/docs/rules/accessor-pairs) rule now recognizes class members by default.
+- [array-callback-return](https://eslint.org/docs/rules/array-callback-return) rule now recognizes `flatMap` method.
+- [computed-property-spacing](https://eslint.org/docs/rules/computed-property-spacing) rule now recognizes class members by default.
+- [func-names](https://eslint.org/docs/rules/func-names) rule now recognizes function declarations in default exports.
+- [no-extra-parens](https://eslint.org/docs/rules/no-extra-parens) rule now recognizes parentheses in assignment targets.
+- [no-dupe-class-members](https://eslint.org/docs/rules/no-dupe-class-members) rule now recognizes computed keys for static class members.
+- [no-magic-number](https://eslint.org/docs/rules/no-magic-number) rule now recognizes bigint literals.
+- [radix](https://eslint.org/docs/rules/radix) rule now recognizes invalid numbers for the second parameter of `parseInt()`.
+- [use-isnan](https://eslint.org/docs/rules/use-isnan) rule now recognizes class members by default.
+- [yoda](https://eslint.org/docs/rules/yoda) rule now recognizes bigint literals.
+
+**To address:** Fix errors or disable these rules.
+
+**Related issue(s):** [#12490](https://github.com/eslint/eslint/pull/12490), [#12608](https://github.com/eslint/eslint/pull/12608), [#12670](https://github.com/eslint/eslint/pull/12670), [#12701](https://github.com/eslint/eslint/pull/12701), [#12765](https://github.com/eslint/eslint/pull/12765), [#12837](https://github.com/eslint/eslint/pull/12837), [#12913](https://github.com/eslint/eslint/pull/12913), [#12915](https://github.com/eslint/eslint/pull/12915), [#12919](https://github.com/eslint/eslint/pull/12919)
+
+## <a name="eslint-recommended"></a> `eslint:recommended` has been updated
+
+Three new rules have been enabled in the `eslint:recommended` preset.
+
+- [no-dupe-else-if](https://eslint.org/docs/rules/no-dupe-else-if)
+- [no-import-assign](https://eslint.org/docs/rules/no-import-assign)
+- [no-setter-return](https://eslint.org/docs/rules/no-setter-return)
+
+**To address:** Fix errors or disable these rules.
+
+**Related issue(s):** [#12920](https://github.com/eslint/eslint/pull/12920)
+
+## <a name="rule-tester-strict"></a> Additional validation added to the `RuleTester` class
+
+The `RuleTester` now validates the following:
+
+- It fails test cases if the rule under test uses the non-standard `node.start` or `node.end` properties. Rules should use `node.range` instead.
+- It fails test cases if the rule under test provides an autofix but a test case doesn't have an `output` property. Add an `output` property to test cases to test the rule's autofix functionality.
+- It fails test cases if any unknown properties are found in the objects in the `errors` property.
+
+**To address:** Modify your rule or test case if existing test cases fail.
+
+**Related issue(s):** [RFC25](https://github.com/eslint/rfcs/blob/master/designs/2019-rule-tester-improvements/README.md), [#12096](https://github.com/eslint/eslint/pull/12096), [#12955](https://github.com/eslint/eslint/pull/12955)
+
+## <a name="deprecate-cliengine"></a> The `CLIEngine` class has been deprecated
+
+The [`CLIEngine` class](https://eslint.org/docs/developer-guide/nodejs-api#cliengine) has been deprecated and replaced by the new [`ESLint` class](https://eslint.org/docs/developer-guide/nodejs-api#eslint-class).
+
+The `CLIEngine` class provides a synchronous API that is blocking the implementation of features such as parallel linting, supporting ES modules in shareable configs/parsers/plugins/formatters, and adding the ability to visually display the progress of linting runs. The new `ESLint` class provides an asynchronous API that ESLint core will now using going forward. `CLIEngine` will remain in core for the foreseeable future but may be removed in a future major version.
+
+**To address:** Update your code to use the new `ESLint` class if you are currently using `CLIEngine`. The following table maps the existing `CLIEngine` methods to their `ESLint` counterparts:
+
+| `CLIEngine`                                  | `ESLint`                           |
+| :------------------------------------------- | :--------------------------------- |
+| `executeOnFiles(patterns)`                   | `lintFiles(patterns)`              |
+| `executeOnText(text, filePath, warnIgnored)` | `lintText(text, options)`          |
+| `getFormatter(name)`                         | `loadFormatter(name)`              |
+| `getConfigForFile(filePath)`                 | `calculateConfigForFile(filePath)` |
+| `isPathIgnored(filePath)`                    | `isPathIgnored(filePath)`          |
+| `static outputFixes(results)`                | `static outputFixes(results)`      |
+| `static getErrorResults(results)`            | `static getErrorResults(results)`  |
+| `static getFormatter(name)`                  | (removed ※1)                       |
+| `addPlugin(pluginId, definition)`            | the `plugins` constructor option   |
+| `getRules()`                                 | (not implemented yet)              |
+| `resolveFileGlobPatterns()`                  | (removed ※2)                       |
+
+- ※1 The `engine.getFormatter()` method currently returns the object of loaded packages as-is, which made it difficult to add new features to formatters for backward compatibility reasons. The new `eslint.loadFormatter()` method returns an adapter object that wraps the object of loaded packages, to ease the process of adding new features. Additionally, the adapter object has access to the `ESLint` instance to calculate default data (using loaded plugin rules to make `rulesMeta`, for example). As a result, the `ESLint` class only implements an instance version of the `loadFormatter()` method.
+- ※2 Since ESLint 6, ESLint uses different logic from the `resolveFileGlobPatterns()` method to iterate files, making this method obsolete.
+
+**Related issue(s):** [RFC40](https://github.com/eslint/rfcs/blob/master/designs/2019-move-to-async-api/README.md), [#12939](https://github.com/eslint/eslint/pull/12939)
index 40a5cc9fa5ccd4a020c0d1389c129510809073d2..e4b6643b44780a176bd6f0c2ef58de78748fe920 100644 (file)
@@ -6,6 +6,7 @@
 "use strict";
 
 const { CLIEngine } = require("./cli-engine");
+const { ESLint } = require("./eslint");
 const { Linter } = require("./linter");
 const { RuleTester } = require("./rule-tester");
 const { SourceCode } = require("./source-code");
@@ -13,6 +14,7 @@ const { SourceCode } = require("./source-code");
 module.exports = {
     Linter,
     CLIEngine,
+    ESLint,
     RuleTester,
     SourceCode
 };
index b53f67bd9dce6c35f5215bbec11b9c0e77bd4c8e..f54605c4db991e75a469d88f7d0bab57118773bc 100644 (file)
@@ -279,6 +279,18 @@ class CascadingConfigArrayFactory {
         );
     }
 
+    /**
+     * Set the config data to override all configs.
+     * Require to call `clearCache()` method after this method is called.
+     * @param {ConfigData} configData The config data to override all configs.
+     * @returns {void}
+     */
+    setOverrideConfig(configData) {
+        const slots = internalSlotsMap.get(this);
+
+        slots.cliConfigData = configData;
+    }
+
     /**
      * Clear config cache.
      * @returns {void}
index 72d1fa4d5dcd5df09899c6fe30adbe5d0bde0fc2..b6aa995beef933b3917f43dea51aae39f24703f9 100644 (file)
@@ -39,6 +39,7 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
 
 // For VSCode IntelliSense
 /** @typedef {import("../shared/types").ConfigData} ConfigData */
+/** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
 /** @typedef {import("../shared/types").LintMessage} LintMessage */
 /** @typedef {import("../shared/types").ParserOptions} ParserOptions */
 /** @typedef {import("../shared/types").Plugin} Plugin */
@@ -50,29 +51,29 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
 /**
  * The options to configure a CLI engine with.
  * @typedef {Object} CLIEngineOptions
- * @property {boolean} allowInlineConfig Enable or disable inline configuration comments.
- * @property {ConfigData} baseConfig Base config object, extended by all configs used with this CLIEngine instance
- * @property {boolean} cache Enable result caching.
- * @property {string} cacheLocation The cache file to use instead of .eslintcache.
- * @property {string} configFile The configuration file to use.
- * @property {string} cwd The value to use for the current working directory.
- * @property {string[]} envs An array of environments to load.
- * @property {string[]|null} extensions An array of file extensions to check.
- * @property {boolean|Function} fix Execute in autofix mode. If a function, should return a boolean.
- * @property {string[]} fixTypes Array of rule types to apply fixes for.
- * @property {string[]} globals An array of global variables to declare.
- * @property {boolean} ignore False disables use of .eslintignore.
- * @property {string} ignorePath The ignore file to use instead of .eslintignore.
- * @property {string|string[]} ignorePattern One or more glob patterns to ignore.
- * @property {boolean} useEslintrc False disables looking for .eslintrc
- * @property {string} parser The name of the parser to use.
- * @property {ParserOptions} parserOptions An object of parserOption settings to use.
- * @property {string[]} plugins An array of plugins to load.
- * @property {Record<string,RuleConf>} rules An object of rules to use.
- * @property {string[]} rulePaths An array of directories to load custom rules from.
- * @property {boolean} reportUnusedDisableDirectives `true` adds reports for unused eslint-disable directives
- * @property {boolean} globInputPaths Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
- * @property {string} resolvePluginsRelativeTo The folder where plugins should be resolved from, defaulting to the CWD
+ * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
+ * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this CLIEngine instance
+ * @property {boolean} [cache] Enable result caching.
+ * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
+ * @property {string} [configFile] The configuration file to use.
+ * @property {string} [cwd] The value to use for the current working directory.
+ * @property {string[]} [envs] An array of environments to load.
+ * @property {string[]|null} [extensions] An array of file extensions to check.
+ * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
+ * @property {string[]} [fixTypes] Array of rule types to apply fixes for.
+ * @property {string[]} [globals] An array of global variables to declare.
+ * @property {boolean} [ignore] False disables use of .eslintignore.
+ * @property {string} [ignorePath] The ignore file to use instead of .eslintignore.
+ * @property {string|string[]} [ignorePattern] One or more glob patterns to ignore.
+ * @property {boolean} [useEslintrc] False disables looking for .eslintrc
+ * @property {string} [parser] The name of the parser to use.
+ * @property {ParserOptions} [parserOptions] An object of parserOption settings to use.
+ * @property {string[]} [plugins] An array of plugins to load.
+ * @property {Record<string,RuleConf>} [rules] An object of rules to use.
+ * @property {string[]} [rulePaths] An array of directories to load custom rules from.
+ * @property {boolean} [reportUnusedDisableDirectives] `true` adds reports for unused eslint-disable directives
+ * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
+ * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD
  */
 
 /**
@@ -88,13 +89,6 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
  * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
  */
 
-/**
- * Information of deprecated rules.
- * @typedef {Object} DeprecatedRuleInfo
- * @property {string} ruleId The rule ID.
- * @property {string[]} replacedBy The rule IDs that replace this deprecated rule.
- */
-
 /**
  * Linting results.
  * @typedef {Object} LintReport
@@ -821,16 +815,22 @@ class CLIEngine {
             lintResultCache.reconcile();
         }
 
-        // Collect used deprecated rules.
-        const usedDeprecatedRules = Array.from(
-            iterateRuleDeprecationWarnings(lastConfigArrays)
-        );
-
         debug(`Linting complete in: ${Date.now() - startTime}ms`);
+        let usedDeprecatedRules;
+
         return {
             results,
             ...calculateStatsPerRun(results),
-            usedDeprecatedRules
+
+            // Initialize it lazily because CLI and `ESLint` API don't use it.
+            get usedDeprecatedRules() {
+                if (!usedDeprecatedRules) {
+                    usedDeprecatedRules = Array.from(
+                        iterateRuleDeprecationWarnings(lastConfigArrays)
+                    );
+                }
+                return usedDeprecatedRules;
+            }
         };
     }
 
@@ -858,9 +858,9 @@ class CLIEngine {
         const startTime = Date.now();
         const resolvedFilename = filename && path.resolve(cwd, filename);
 
+
         // Clear the last used config arrays.
         lastConfigArrays.length = 0;
-
         if (resolvedFilename && this.isPathIgnored(resolvedFilename)) {
             if (warnIgnored) {
                 results.push(createIgnoreResult(resolvedFilename, cwd));
@@ -892,16 +892,22 @@ class CLIEngine {
             }));
         }
 
-        // Collect used deprecated rules.
-        const usedDeprecatedRules = Array.from(
-            iterateRuleDeprecationWarnings(lastConfigArrays)
-        );
-
         debug(`Linting complete in: ${Date.now() - startTime}ms`);
+        let usedDeprecatedRules;
+
         return {
             results,
             ...calculateStatsPerRun(results),
-            usedDeprecatedRules
+
+            // Initialize it lazily because CLI and `ESLint` API don't use it.
+            get usedDeprecatedRules() {
+                if (!usedDeprecatedRules) {
+                    usedDeprecatedRules = Array.from(
+                        iterateRuleDeprecationWarnings(lastConfigArrays)
+                    );
+                }
+                return usedDeprecatedRules;
+            }
         };
     }
 
@@ -955,11 +961,10 @@ class CLIEngine {
     }
 
     /**
-     * Returns the formatter representing the given format or null if no formatter
-     * with the given name can be found.
+     * Returns the formatter representing the given format or null if the `format` is not a string.
      * @param {string} [format] The name of the format to load or the path to a
      *      custom formatter.
-     * @returns {Function} The formatter function or null if not found.
+     * @returns {(Function|null)} The formatter function or null if the `format` is not a string.
      */
     getFormatter(format) {
 
index b1429af6ad95cfb0e80a4990cfed033c6fe5f5cf..fa3fdb3bedd89b861a696068aaadcf59b15995bf 100644 (file)
@@ -817,7 +817,7 @@ class ConfigArrayFactory {
         if (configData) {
             return this._normalizeConfigData(configData, {
                 ...ctx,
-                filePath: plugin.filePath,
+                filePath: plugin.filePath || ctx.filePath,
                 name: `${ctx.name} » plugin:${plugin.id}/${configName}`
             });
         }
@@ -978,7 +978,7 @@ class ConfigArrayFactory {
         if (plugin) {
             return new ConfigDependency({
                 definition: normalizePlugin(plugin),
-                filePath: ctx.filePath,
+                filePath: "", // It's unknown where the plugin came from.
                 id,
                 importerName: ctx.name,
                 importerPath: ctx.filePath
index b3434198b19201e183981dc288c596cb864d5fb9..42a7362737fc7c657105bd079d6488534bcaaff8 100644 (file)
@@ -107,7 +107,7 @@ function getMatchedIndices(elements, filePath) {
     for (let i = elements.length - 1; i >= 0; --i) {
         const element = elements[i];
 
-        if (!element.criteria || element.criteria.test(filePath)) {
+        if (!element.criteria || (filePath && element.criteria.test(filePath))) {
             indices.push(i);
         }
     }
index 92690b9f8ae342a45f2386e9488b5a13d440a519..6eaec4258e1ae4dfece492653aa91937e0cc97af 100644 (file)
@@ -71,7 +71,13 @@ function getCommonAncestorPath(sourcePaths) {
         }
     }
 
-    return result || path.sep;
+    let resolvedResult = result || path.sep;
+
+    // if Windows common ancestor is root of drive must have trailing slash to be absolute.
+    if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
+        resolvedResult += path.sep;
+    }
+    return resolvedResult;
 }
 
 /**
index 815ce68c22fe2e944c3017ee20549c77018b759e..ce11878008f108e239dfdf3dfdf1d752e49cb340 100644 (file)
 
 const fs = require("fs"),
     path = require("path"),
-    { CLIEngine } = require("./cli-engine"),
-    options = require("./options"),
+    { promisify } = require("util"),
+    { ESLint } = require("./eslint"),
+    CLIOptions = require("./options"),
     log = require("./shared/logging"),
     RuntimeInfo = require("./shared/runtime-info");
 
 const debug = require("debug")("eslint:cli");
 
+//------------------------------------------------------------------------------
+// Types
+//------------------------------------------------------------------------------
+
+/** @typedef {import("./eslint/eslint").ESLintOptions} ESLintOptions */
+/** @typedef {import("./eslint/eslint").LintMessage} LintMessage */
+/** @typedef {import("./eslint/eslint").LintResult} LintResult */
+
 //------------------------------------------------------------------------------
 // Helpers
 //------------------------------------------------------------------------------
 
+const mkdir = promisify(fs.mkdir);
+const stat = promisify(fs.stat);
+const writeFile = promisify(fs.writeFile);
+
 /**
  * Predicate function for whether or not to apply fixes in quiet mode.
  * If a message is a warning, do not apply a fix.
- * @param {LintResult} lintResult The lint result.
+ * @param {LintMessage} message The lint result.
  * @returns {boolean} True if the lint message is an error (and thus should be
  * autofixed), false otherwise.
  */
-function quietFixPredicate(lintResult) {
-    return lintResult.severity === 2;
+function quietFixPredicate(message) {
+    return message.severity === 2;
 }
 
 /**
  * Translates the CLI options into the options expected by the CLIEngine.
  * @param {Object} cliOptions The CLI options to translate.
- * @returns {CLIEngineOptions} The options object for the CLIEngine.
+ * @returns {ESLintOptions} The options object for the CLIEngine.
  * @private
  */
-function translateOptions(cliOptions) {
+function translateOptions({
+    cache,
+    cacheFile,
+    cacheLocation,
+    config,
+    env,
+    errorOnUnmatchedPattern,
+    eslintrc,
+    ext,
+    fix,
+    fixDryRun,
+    fixType,
+    global,
+    ignore,
+    ignorePath,
+    ignorePattern,
+    inlineConfig,
+    parser,
+    parserOptions,
+    plugin,
+    quiet,
+    reportUnusedDisableDirectives,
+    resolvePluginsRelativeTo,
+    rule,
+    rulesdir
+}) {
     return {
-        envs: cliOptions.env,
-        extensions: cliOptions.ext,
-        rules: cliOptions.rule,
-        plugins: cliOptions.plugin,
-        globals: cliOptions.global,
-        ignore: cliOptions.ignore,
-        ignorePath: cliOptions.ignorePath,
-        ignorePattern: cliOptions.ignorePattern,
-        configFile: cliOptions.config,
-        rulePaths: cliOptions.rulesdir,
-        useEslintrc: cliOptions.eslintrc,
-        parser: cliOptions.parser,
-        parserOptions: cliOptions.parserOptions,
-        cache: cliOptions.cache,
-        cacheFile: cliOptions.cacheFile,
-        cacheLocation: cliOptions.cacheLocation,
-        fix: (cliOptions.fix || cliOptions.fixDryRun) && (cliOptions.quiet ? quietFixPredicate : true),
-        fixTypes: cliOptions.fixType,
-        allowInlineConfig: cliOptions.inlineConfig,
-        reportUnusedDisableDirectives: cliOptions.reportUnusedDisableDirectives,
-        resolvePluginsRelativeTo: cliOptions.resolvePluginsRelativeTo,
-        errorOnUnmatchedPattern: cliOptions.errorOnUnmatchedPattern
+        allowInlineConfig: inlineConfig,
+        cache,
+        cacheLocation: cacheLocation || cacheFile,
+        errorOnUnmatchedPattern,
+        extensions: ext,
+        fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true),
+        fixTypes: fixType,
+        ignore,
+        ignorePath,
+        overrideConfig: {
+            env: env && env.reduce((obj, name) => {
+                obj[name] = true;
+                return obj;
+            }, {}),
+            globals: global && global.reduce((obj, name) => {
+                if (name.endsWith(":true")) {
+                    obj[name.slice(0, -5)] = "writable";
+                } else {
+                    obj[name] = "readonly";
+                }
+                return obj;
+            }, {}),
+            ignorePatterns: ignorePattern,
+            parser,
+            parserOptions,
+            plugins: plugin,
+            rules: rule
+        },
+        overrideConfigFile: config,
+        reportUnusedDisableDirectives: reportUnusedDisableDirectives ? "error" : void 0,
+        resolvePluginsRelativeTo,
+        rulePaths: rulesdir,
+        useEslintrc: eslintrc
     };
 }
 
+/**
+ * Count error messages.
+ * @param {LintResult[]} results The lint results.
+ * @returns {{errorCount:number;warningCount:number}} The number of error messages.
+ */
+function countErrors(results) {
+    let errorCount = 0;
+    let warningCount = 0;
+
+    for (const result of results) {
+        errorCount += result.errorCount;
+        warningCount += result.warningCount;
+    }
+
+    return { errorCount, warningCount };
+}
+
+/**
+ * Check if a given file path is a directory or not.
+ * @param {string} filePath The path to a file to check.
+ * @returns {Promise<boolean>} `true` if the given path is a directory.
+ */
+async function isDirectory(filePath) {
+    try {
+        return (await stat(filePath)).isDirectory();
+    } catch (error) {
+        if (error.code === "ENOENT" || error.code === "ENOTDIR") {
+            return false;
+        }
+        throw error;
+    }
+}
+
 /**
  * Outputs the results of the linting.
- * @param {CLIEngine} engine The CLIEngine to use.
+ * @param {ESLint} engine The ESLint instance to use.
  * @param {LintResult[]} results The results to print.
  * @param {string} format The name of the formatter to use or the path to the formatter.
  * @param {string} outputFile The path for the output file.
- * @returns {boolean} True if the printing succeeds, false if not.
+ * @returns {Promise<boolean>} True if the printing succeeds, false if not.
  * @private
  */
-function printResults(engine, results, format, outputFile) {
+async function printResults(engine, results, format, outputFile) {
     let formatter;
-    let rulesMeta;
 
     try {
-        formatter = engine.getFormatter(format);
+        formatter = await engine.loadFormatter(format);
     } catch (e) {
         log.error(e.message);
         return false;
     }
 
-    const output = formatter(results, {
-        get rulesMeta() {
-            if (!rulesMeta) {
-                rulesMeta = {};
-                for (const [ruleId, rule] of engine.getRules()) {
-                    rulesMeta[ruleId] = rule.meta;
-                }
-            }
-            return rulesMeta;
-        }
-    });
+    const output = formatter.format(results);
 
     if (output) {
         if (outputFile) {
             const filePath = path.resolve(process.cwd(), outputFile);
 
-            if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {
+            if (await isDirectory(filePath)) {
                 log.error("Cannot write to output file path, it is a directory: %s", outputFile);
                 return false;
             }
 
             try {
-                fs.mkdirSync(path.dirname(filePath), { recursive: true });
-                fs.writeFileSync(filePath, output);
+                await mkdir(path.dirname(filePath), { recursive: true });
+                await writeFile(filePath, output);
             } catch (ex) {
                 log.error("There was a problem writing the output file:\n%s", ex);
                 return false;
@@ -126,7 +197,6 @@ function printResults(engine, results, format, outputFile) {
     }
 
     return true;
-
 }
 
 //------------------------------------------------------------------------------
@@ -143,28 +213,33 @@ const cli = {
      * Executes the CLI based on an array of arguments that is passed in.
      * @param {string|Array|Object} args The arguments to process.
      * @param {string} [text] The text to lint (used for TTY).
-     * @returns {int} The exit code for the operation.
+     * @returns {Promise<number>} The exit code for the operation.
      */
-    execute(args, text) {
+    async execute(args, text) {
         if (Array.isArray(args)) {
             debug("CLI args: %o", args.slice(2));
         }
-
-        let currentOptions;
+        let options;
 
         try {
-            currentOptions = options.parse(args);
+            options = CLIOptions.parse(args);
         } catch (error) {
             log.error(error.message);
             return 2;
         }
 
-        const files = currentOptions._;
+        const files = options._;
         const useStdin = typeof text === "string";
 
-        if (currentOptions.version) {
+        if (options.help) {
+            log.info(CLIOptions.generateHelp());
+            return 0;
+        }
+        if (options.version) {
             log.info(RuntimeInfo.version());
-        } else if (currentOptions.envInfo) {
+            return 0;
+        }
+        if (options.envInfo) {
             try {
                 log.info(RuntimeInfo.environment());
                 return 0;
@@ -172,7 +247,9 @@ const cli = {
                 log.error(err.message);
                 return 2;
             }
-        } else if (currentOptions.printConfig) {
+        }
+
+        if (options.printConfig) {
             if (files.length) {
                 log.error("The --print-config option must be used with exactly one file name.");
                 return 2;
@@ -182,58 +259,67 @@ const cli = {
                 return 2;
             }
 
-            const engine = new CLIEngine(translateOptions(currentOptions));
-            const fileConfig = engine.getConfigForFile(currentOptions.printConfig);
+            const engine = new ESLint(translateOptions(options));
+            const fileConfig =
+                await engine.calculateConfigForFile(options.printConfig);
 
             log.info(JSON.stringify(fileConfig, null, "  "));
             return 0;
-        } else if (currentOptions.help || (!files.length && !useStdin)) {
-            log.info(options.generateHelp());
-        } else {
-            debug(`Running on ${useStdin ? "text" : "files"}`);
-
-            if (currentOptions.fix && currentOptions.fixDryRun) {
-                log.error("The --fix option and the --fix-dry-run option cannot be used together.");
-                return 2;
-            }
+        }
 
-            if (useStdin && currentOptions.fix) {
-                log.error("The --fix option is not available for piped-in code; use --fix-dry-run instead.");
-                return 2;
-            }
+        debug(`Running on ${useStdin ? "text" : "files"}`);
 
-            if (currentOptions.fixType && !currentOptions.fix && !currentOptions.fixDryRun) {
-                log.error("The --fix-type option requires either --fix or --fix-dry-run.");
-                return 2;
-            }
+        if (options.fix && options.fixDryRun) {
+            log.error("The --fix option and the --fix-dry-run option cannot be used together.");
+            return 2;
+        }
+        if (useStdin && options.fix) {
+            log.error("The --fix option is not available for piped-in code; use --fix-dry-run instead.");
+            return 2;
+        }
+        if (options.fixType && !options.fix && !options.fixDryRun) {
+            log.error("The --fix-type option requires either --fix or --fix-dry-run.");
+            return 2;
+        }
 
-            const engine = new CLIEngine(translateOptions(currentOptions));
-            const report = useStdin ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files);
+        const engine = new ESLint(translateOptions(options));
+        let results;
 
-            if (currentOptions.fix) {
-                debug("Fix mode enabled - applying fixes");
-                CLIEngine.outputFixes(report);
-            }
+        if (useStdin) {
+            results = await engine.lintText(text, {
+                filePath: options.stdinFilename,
+                warnIgnored: true
+            });
+        } else {
+            results = await engine.lintFiles(files);
+        }
 
-            if (currentOptions.quiet) {
-                debug("Quiet mode enabled - filtering out warnings");
-                report.results = CLIEngine.getErrorResults(report.results);
-            }
+        if (options.fix) {
+            debug("Fix mode enabled - applying fixes");
+            await ESLint.outputFixes(results);
+        }
 
-            if (printResults(engine, report.results, currentOptions.format, currentOptions.outputFile)) {
-                const tooManyWarnings = currentOptions.maxWarnings >= 0 && report.warningCount > currentOptions.maxWarnings;
+        if (options.quiet) {
+            debug("Quiet mode enabled - filtering out warnings");
+            results = ESLint.getErrorResults(results);
+        }
 
-                if (!report.errorCount && tooManyWarnings) {
-                    log.error("ESLint found too many warnings (maximum: %s).", currentOptions.maxWarnings);
-                }
+        if (await printResults(engine, results, options.format, options.outputFile)) {
+            const { errorCount, warningCount } = countErrors(results);
+            const tooManyWarnings =
+                options.maxWarnings >= 0 && warningCount > options.maxWarnings;
 
-                return (report.errorCount || tooManyWarnings) ? 1 : 0;
+            if (!errorCount && tooManyWarnings) {
+                log.error(
+                    "ESLint found too many warnings (maximum: %s).",
+                    options.maxWarnings
+                );
             }
 
-            return 2;
+            return (errorCount || tooManyWarnings) ? 1 : 0;
         }
 
-        return 0;
+        return 2;
     }
 };
 
diff --git a/eslint/lib/eslint/eslint.js b/eslint/lib/eslint/eslint.js
new file mode 100644 (file)
index 0000000..d195aab
--- /dev/null
@@ -0,0 +1,656 @@
+/**
+ * @fileoverview Main API Class
+ * @author Kai Cataldo
+ * @author Toru Nagashima
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const path = require("path");
+const fs = require("fs");
+const { promisify } = require("util");
+const { CLIEngine, getCLIEngineInternalSlots } = require("../cli-engine/cli-engine");
+const BuiltinRules = require("../rules");
+const { getRuleSeverity } = require("../shared/config-ops");
+const { version } = require("../../package.json");
+
+//------------------------------------------------------------------------------
+// Typedefs
+//------------------------------------------------------------------------------
+
+/** @typedef {import("../cli-engine/cli-engine").LintReport} CLIEngineLintReport */
+/** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
+/** @typedef {import("../shared/types").ConfigData} ConfigData */
+/** @typedef {import("../shared/types").LintMessage} LintMessage */
+/** @typedef {import("../shared/types").Plugin} Plugin */
+/** @typedef {import("../shared/types").Rule} Rule */
+/** @typedef {import("./load-formatter").Formatter} Formatter */
+
+/**
+ * The options with which to configure the ESLint instance.
+ * @typedef {Object} ESLintOptions
+ * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
+ * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this instance
+ * @property {boolean} [cache] Enable result caching.
+ * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
+ * @property {string} [cwd] The value to use for the current working directory.
+ * @property {boolean} [errorOnUnmatchedPattern] If `false` then `ESLint#lintFiles()` doesn't throw even if no target files found. Defaults to `true`.
+ * @property {string[]} [extensions] An array of file extensions to check.
+ * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
+ * @property {string[]} [fixTypes] Array of rule types to apply fixes for.
+ * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
+ * @property {boolean} [ignore] False disables use of .eslintignore.
+ * @property {string} [ignorePath] The ignore file to use instead of .eslintignore.
+ * @property {ConfigData} [overrideConfig] Override config object, overrides all configs used with this instance
+ * @property {string} [overrideConfigFile] The configuration file to use.
+ * @property {Record<string,Plugin>} [plugins] An array of plugin implementations.
+ * @property {"error" | "warn" | "off"} [reportUnusedDisableDirectives] the severity to report unused eslint-disable directives.
+ * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD.
+ * @property {string[]} [rulePaths] An array of directories to load custom rules from.
+ * @property {boolean} [useEslintrc] False disables looking for .eslintrc.* files.
+ */
+
+/**
+ * A rules metadata object.
+ * @typedef {Object} RulesMeta
+ * @property {string} id The plugin ID.
+ * @property {Object} definition The plugin definition.
+ */
+
+/**
+ * A linting result.
+ * @typedef {Object} LintResult
+ * @property {string} filePath The path to the file that was linted.
+ * @property {LintMessage[]} messages All of the messages for the result.
+ * @property {number} errorCount Number of errors for the result.
+ * @property {number} warningCount Number of warnings for the result.
+ * @property {number} fixableErrorCount Number of fixable errors for the result.
+ * @property {number} fixableWarningCount Number of fixable warnings for the result.
+ * @property {string} [source] The source code of the file that was linted.
+ * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
+ * @property {DeprecatedRuleInfo[]} usedDeprecatedRules The list of used deprecated rules.
+ */
+
+/**
+ * Private members for the `ESLint` instance.
+ * @typedef {Object} ESLintPrivateMembers
+ * @property {CLIEngine} cliEngine The wrapped CLIEngine instance.
+ * @property {ESLintOptions} options The options used to instantiate the ESLint instance.
+ */
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const writeFile = promisify(fs.writeFile);
+
+/**
+ * The map with which to store private class members.
+ * @type {WeakMap<ESLint, ESLintPrivateMembers>}
+ */
+const privateMembersMap = new WeakMap();
+
+/**
+ * Check if a given value is a non-empty string or not.
+ * @param {any} x The value to check.
+ * @returns {boolean} `true` if `x` is a non-empty string.
+ */
+function isNonEmptyString(x) {
+    return typeof x === "string" && x.trim() !== "";
+}
+
+/**
+ * Check if a given value is an array of non-empty stringss or not.
+ * @param {any} x The value to check.
+ * @returns {boolean} `true` if `x` is an array of non-empty stringss.
+ */
+function isArrayOfNonEmptyString(x) {
+    return Array.isArray(x) && x.every(isNonEmptyString);
+}
+
+/**
+ * Check if a given value is a valid fix type or not.
+ * @param {any} x The value to check.
+ * @returns {boolean} `true` if `x` is valid fix type.
+ */
+function isFixType(x) {
+    return x === "problem" || x === "suggestion" || x === "layout";
+}
+
+/**
+ * Check if a given value is an array of fix types or not.
+ * @param {any} x The value to check.
+ * @returns {boolean} `true` if `x` is an array of fix types.
+ */
+function isFixTypeArray(x) {
+    return Array.isArray(x) && x.every(isFixType);
+}
+
+/**
+ * The error for invalid options.
+ */
+class ESLintInvalidOptionsError extends Error {
+    constructor(messages) {
+        super(`Invalid Options:\n- ${messages.join("\n- ")}`);
+        this.code = "ESLINT_INVALID_OPTIONS";
+        Error.captureStackTrace(this, ESLintInvalidOptionsError);
+    }
+}
+
+/**
+ * Validates and normalizes options for the wrapped CLIEngine instance.
+ * @param {ESLintOptions} options The options to process.
+ * @returns {ESLintOptions} The normalized options.
+ */
+function processOptions({
+    allowInlineConfig = true, // ← we cannot use `overrideConfig.noInlineConfig` instead because `allowInlineConfig` has side-effect that suppress warnings that show inline configs are ignored.
+    baseConfig = null,
+    cache = false,
+    cacheLocation = ".eslintcache",
+    cwd = process.cwd(),
+    errorOnUnmatchedPattern = true,
+    extensions = null, // ← should be null by default because if it's an array then it suppresses RFC20 feature.
+    fix = false,
+    fixTypes = null, // ← should be null by default because if it's an array then it suppresses rules that don't have the `meta.type` property.
+    globInputPaths = true,
+    ignore = true,
+    ignorePath = null, // ← should be null by default because if it's a string then it may throw ENOENT.
+    overrideConfig = null,
+    overrideConfigFile = null,
+    plugins = {},
+    reportUnusedDisableDirectives = null, // ← should be null by default because if it's a string then it overrides the 'reportUnusedDisableDirectives' setting in config files. And we cannot use `overrideConfig.reportUnusedDisableDirectives` instead because we cannot configure the `error` severity with that.
+    resolvePluginsRelativeTo = null, // ← should be null by default because if it's a string then it suppresses RFC47 feature.
+    rulePaths = [],
+    useEslintrc = true,
+    ...unknownOptions
+}) {
+    const errors = [];
+    const unknownOptionKeys = Object.keys(unknownOptions);
+
+    if (unknownOptionKeys.length >= 1) {
+        errors.push(`Unknown options: ${unknownOptionKeys.join(", ")}`);
+        if (unknownOptionKeys.includes("cacheFile")) {
+            errors.push("'cacheFile' has been removed. Please use the 'cacheLocation' option instead.");
+        }
+        if (unknownOptionKeys.includes("configFile")) {
+            errors.push("'configFile' has been removed. Please use the 'overrideConfigFile' option instead.");
+        }
+        if (unknownOptionKeys.includes("envs")) {
+            errors.push("'envs' has been removed. Please use the 'overrideConfig.env' option instead.");
+        }
+        if (unknownOptionKeys.includes("globals")) {
+            errors.push("'globals' has been removed. Please use the 'overrideConfig.globals' option instead.");
+        }
+        if (unknownOptionKeys.includes("ignorePattern")) {
+            errors.push("'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead.");
+        }
+        if (unknownOptionKeys.includes("parser")) {
+            errors.push("'parser' has been removed. Please use the 'overrideConfig.parser' option instead.");
+        }
+        if (unknownOptionKeys.includes("parserOptions")) {
+            errors.push("'parserOptions' has been removed. Please use the 'overrideConfig.parserOptions' option instead.");
+        }
+        if (unknownOptionKeys.includes("rules")) {
+            errors.push("'rules' has been removed. Please use the 'overrideConfig.rules' option instead.");
+        }
+    }
+    if (typeof allowInlineConfig !== "boolean") {
+        errors.push("'allowInlineConfig' must be a boolean.");
+    }
+    if (typeof baseConfig !== "object") {
+        errors.push("'baseConfig' must be an object or null.");
+    }
+    if (typeof cache !== "boolean") {
+        errors.push("'cache' must be a boolean.");
+    }
+    if (!isNonEmptyString(cacheLocation)) {
+        errors.push("'cacheLocation' must be a non-empty string.");
+    }
+    if (!isNonEmptyString(cwd) || !path.isAbsolute(cwd)) {
+        errors.push("'cwd' must be an absolute path.");
+    }
+    if (typeof errorOnUnmatchedPattern !== "boolean") {
+        errors.push("'errorOnUnmatchedPattern' must be a boolean.");
+    }
+    if (!isArrayOfNonEmptyString(extensions) && extensions !== null) {
+        errors.push("'extensions' must be an array of non-empty strings or null.");
+    }
+    if (typeof fix !== "boolean" && typeof fix !== "function") {
+        errors.push("'fix' must be a boolean or a function.");
+    }
+    if (fixTypes !== null && !isFixTypeArray(fixTypes)) {
+        errors.push("'fixTypes' must be an array of any of \"problem\", \"suggestion\", and \"layout\".");
+    }
+    if (typeof globInputPaths !== "boolean") {
+        errors.push("'globInputPaths' must be a boolean.");
+    }
+    if (typeof ignore !== "boolean") {
+        errors.push("'ignore' must be a boolean.");
+    }
+    if (!isNonEmptyString(ignorePath) && ignorePath !== null) {
+        errors.push("'ignorePath' must be a non-empty string or null.");
+    }
+    if (typeof overrideConfig !== "object") {
+        errors.push("'overrideConfig' must be an object or null.");
+    }
+    if (!isNonEmptyString(overrideConfigFile) && overrideConfigFile !== null) {
+        errors.push("'overrideConfigFile' must be a non-empty string or null.");
+    }
+    if (typeof plugins !== "object") {
+        errors.push("'plugins' must be an object or null.");
+    } else if (plugins !== null && Object.keys(plugins).includes("")) {
+        errors.push("'plugins' must not include an empty string.");
+    }
+    if (Array.isArray(plugins)) {
+        errors.push("'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead.");
+    }
+    if (
+        reportUnusedDisableDirectives !== "error" &&
+        reportUnusedDisableDirectives !== "warn" &&
+        reportUnusedDisableDirectives !== "off" &&
+        reportUnusedDisableDirectives !== null
+    ) {
+        errors.push("'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null.");
+    }
+    if (
+        !isNonEmptyString(resolvePluginsRelativeTo) &&
+        resolvePluginsRelativeTo !== null
+    ) {
+        errors.push("'resolvePluginsRelativeTo' must be a non-empty string or null.");
+    }
+    if (!isArrayOfNonEmptyString(rulePaths)) {
+        errors.push("'rulePaths' must be an array of non-empty strings.");
+    }
+    if (typeof useEslintrc !== "boolean") {
+        errors.push("'useElintrc' must be a boolean.");
+    }
+
+    if (errors.length > 0) {
+        throw new ESLintInvalidOptionsError(errors);
+    }
+
+    return {
+        allowInlineConfig,
+        baseConfig,
+        cache,
+        cacheLocation,
+        configFile: overrideConfigFile,
+        cwd,
+        errorOnUnmatchedPattern,
+        extensions,
+        fix,
+        fixTypes,
+        globInputPaths,
+        ignore,
+        ignorePath,
+        reportUnusedDisableDirectives,
+        resolvePluginsRelativeTo,
+        rulePaths,
+        useEslintrc
+    };
+}
+
+/**
+ * Check if a value has one or more properties and that value is not undefined.
+ * @param {any} obj The value to check.
+ * @returns {boolean} `true` if `obj` has one or more properties that that value is not undefined.
+ */
+function hasDefinedProperty(obj) {
+    if (typeof obj === "object" && obj !== null) {
+        for (const key in obj) {
+            if (typeof obj[key] !== "undefined") {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+/**
+ * Create rulesMeta object.
+ * @param {Map<string,Rule>} rules a map of rules from which to generate the object.
+ * @returns {Object} metadata for all enabled rules.
+ */
+function createRulesMeta(rules) {
+    return Array.from(rules).reduce((retVal, [id, rule]) => {
+        retVal[id] = rule.meta;
+        return retVal;
+    }, {});
+}
+
+/** @type {WeakMap<ExtractedConfig, DeprecatedRuleInfo[]>} */
+const usedDeprecatedRulesCache = new WeakMap();
+
+/**
+ * Create used deprecated rule list.
+ * @param {CLIEngine} cliEngine The CLIEngine instance.
+ * @param {string} maybeFilePath The absolute path to a lint target file or `"<text>"`.
+ * @returns {DeprecatedRuleInfo[]} The used deprecated rule list.
+ */
+function getOrFindUsedDeprecatedRules(cliEngine, maybeFilePath) {
+    const {
+        configArrayFactory,
+        options: { cwd }
+    } = getCLIEngineInternalSlots(cliEngine);
+    const filePath = path.isAbsolute(maybeFilePath)
+        ? maybeFilePath
+        : path.join(cwd, "__placeholder__.js");
+    const configArray = configArrayFactory.getConfigArrayForFile(filePath);
+    const config = configArray.extractConfig(filePath);
+
+    // Most files use the same config, so cache it.
+    if (!usedDeprecatedRulesCache.has(config)) {
+        const pluginRules = configArray.pluginRules;
+        const retv = [];
+
+        for (const [ruleId, ruleConf] of Object.entries(config.rules)) {
+            if (getRuleSeverity(ruleConf) === 0) {
+                continue;
+            }
+            const rule = pluginRules.get(ruleId) || BuiltinRules.get(ruleId);
+            const meta = rule && rule.meta;
+
+            if (meta && meta.deprecated) {
+                retv.push({ ruleId, replacedBy: meta.replacedBy || [] });
+            }
+        }
+
+        usedDeprecatedRulesCache.set(config, Object.freeze(retv));
+    }
+
+    return usedDeprecatedRulesCache.get(config);
+}
+
+/**
+ * Processes the linting results generated by a CLIEngine linting report to
+ * match the ESLint class's API.
+ * @param {CLIEngine} cliEngine The CLIEngine instance.
+ * @param {CLIEngineLintReport} report The CLIEngine linting report to process.
+ * @returns {LintResult[]} The processed linting results.
+ */
+function processCLIEngineLintReport(cliEngine, { results }) {
+    const descriptor = {
+        configurable: true,
+        enumerable: true,
+        get() {
+            return getOrFindUsedDeprecatedRules(cliEngine, this.filePath);
+        }
+    };
+
+    for (const result of results) {
+        Object.defineProperty(result, "usedDeprecatedRules", descriptor);
+    }
+
+    return results;
+}
+
+/**
+ * An Array.prototype.sort() compatible compare function to order results by their file path.
+ * @param {LintResult} a The first lint result.
+ * @param {LintResult} b The second lint result.
+ * @returns {number} An integer representing the order in which the two results should occur.
+ */
+function compareResultsByFilePath(a, b) {
+    if (a.filePath < b.filePath) {
+        return -1;
+    }
+
+    if (a.filePath > b.filePath) {
+        return 1;
+    }
+
+    return 0;
+}
+
+class ESLint {
+
+    /**
+     * Creates a new instance of the main ESLint API.
+     * @param {ESLintOptions} options The options for this instance.
+     */
+    constructor(options = {}) {
+        const processedOptions = processOptions(options);
+        const cliEngine = new CLIEngine(processedOptions);
+        const {
+            additionalPluginPool,
+            configArrayFactory,
+            lastConfigArrays
+        } = getCLIEngineInternalSlots(cliEngine);
+        let updated = false;
+
+        /*
+         * Address `plugins` to add plugin implementations.
+         * Operate the `additionalPluginPool` internal slot directly to avoid
+         * using `addPlugin(id, plugin)` method that resets cache everytime.
+         */
+        if (options.plugins) {
+            for (const [id, plugin] of Object.entries(options.plugins)) {
+                additionalPluginPool.set(id, plugin);
+                updated = true;
+            }
+        }
+
+        /*
+         * Address `overrideConfig` to set override config.
+         * Operate the `configArrayFactory` internal slot directly because this
+         * functionality doesn't exist as the public API of CLIEngine.
+         */
+        if (hasDefinedProperty(options.overrideConfig)) {
+            configArrayFactory.setOverrideConfig(options.overrideConfig);
+            updated = true;
+        }
+
+        // Update caches.
+        if (updated) {
+            configArrayFactory.clearCache();
+            lastConfigArrays[0] = configArrayFactory.getConfigArrayForFile();
+        }
+
+        // Initialize private properties.
+        privateMembersMap.set(this, {
+            cliEngine,
+            options: processedOptions
+        });
+    }
+
+    /**
+     * The version text.
+     * @type {string}
+     */
+    static get version() {
+        return version;
+    }
+
+    /**
+     * Outputs fixes from the given results to files.
+     * @param {LintResult[]} results The lint results.
+     * @returns {Promise<void>} Returns a promise that is used to track side effects.
+     */
+    static async outputFixes(results) {
+        if (!Array.isArray(results)) {
+            throw new Error("'results' must be an array");
+        }
+
+        await Promise.all(
+            results
+                .filter(result => {
+                    if (typeof result !== "object" || result === null) {
+                        throw new Error("'results' must include only objects");
+                    }
+                    return (
+                        typeof result.output === "string" &&
+                        path.isAbsolute(result.filePath)
+                    );
+                })
+                .map(r => writeFile(r.filePath, r.output))
+        );
+    }
+
+    /**
+     * Returns results that only contains errors.
+     * @param {LintResult[]} results The results to filter.
+     * @returns {LintResult[]} The filtered results.
+     */
+    static getErrorResults(results) {
+        return CLIEngine.getErrorResults(results);
+    }
+
+    /**
+     * Executes the current configuration on an array of file and directory names.
+     * @param {string[]} patterns An array of file and directory names.
+     * @returns {Promise<LintResult[]>} The results of linting the file patterns given.
+     */
+    async lintFiles(patterns) {
+        if (!isNonEmptyString(patterns) && !isArrayOfNonEmptyString(patterns)) {
+            throw new Error("'patterns' must be a non-empty string or an array of non-empty strings");
+        }
+        const { cliEngine } = privateMembersMap.get(this);
+
+        return processCLIEngineLintReport(
+            cliEngine,
+            cliEngine.executeOnFiles(patterns)
+        );
+    }
+
+    /**
+     * Executes the current configuration on text.
+     * @param {string} code A string of JavaScript code to lint.
+     * @param {Object} [options] The options.
+     * @param {string} [options.filePath] The path to the file of the source code.
+     * @param {boolean} [options.warnIgnored] When set to true, warn if given filePath is an ignored path.
+     * @returns {Promise<LintResult[]>} The results of linting the string of code given.
+     */
+    async lintText(code, options = {}) {
+        if (typeof code !== "string") {
+            throw new Error("'code' must be a string");
+        }
+        if (typeof options !== "object") {
+            throw new Error("'options' must be an object, null, or undefined");
+        }
+        const {
+            filePath,
+            warnIgnored = false,
+            ...unknownOptions
+        } = options || {};
+
+        for (const key of Object.keys(unknownOptions)) {
+            throw new Error(`'options' must not include the unknown option '${key}'`);
+        }
+        if (filePath !== void 0 && !isNonEmptyString(filePath)) {
+            throw new Error("'options.filePath' must be a non-empty string or undefined");
+        }
+        if (typeof warnIgnored !== "boolean") {
+            throw new Error("'options.warnIgnored' must be a boolean or undefined");
+        }
+
+        const { cliEngine } = privateMembersMap.get(this);
+
+        return processCLIEngineLintReport(
+            cliEngine,
+            cliEngine.executeOnText(code, filePath, warnIgnored)
+        );
+    }
+
+    /**
+     * Returns the formatter representing the given formatter name.
+     * @param {string} [name] The name of the formattter to load.
+     * The following values are allowed:
+     * - `undefined` ... Load `stylish` builtin formatter.
+     * - A builtin formatter name ... Load the builtin formatter.
+     * - A thirdparty formatter name:
+     *   - `foo` → `eslint-formatter-foo`
+     *   - `@foo` → `@foo/eslint-formatter`
+     *   - `@foo/bar` → `@foo/eslint-formatter-bar`
+     * - A file path ... Load the file.
+     * @returns {Promise<Formatter>} A promise resolving to the formatter object.
+     * This promise will be rejected if the given formatter was not found or not
+     * a function.
+     */
+    async loadFormatter(name = "stylish") {
+        if (typeof name !== "string") {
+            throw new Error("'name' must be a string");
+        }
+
+        const { cliEngine } = privateMembersMap.get(this);
+        const formatter = cliEngine.getFormatter(name);
+
+        if (typeof formatter !== "function") {
+            throw new Error(`Formatter must be a function, but got a ${typeof formatter}.`);
+        }
+
+        return {
+
+            /**
+             * The main formatter method.
+             * @param {LintResults[]} results The lint results to format.
+             * @returns {string} The formatted lint results.
+             */
+            format(results) {
+                let rulesMeta = null;
+
+                results.sort(compareResultsByFilePath);
+
+                return formatter(results, {
+                    get rulesMeta() {
+                        if (!rulesMeta) {
+                            rulesMeta = createRulesMeta(cliEngine.getRules());
+                        }
+
+                        return rulesMeta;
+                    }
+                });
+            }
+        };
+    }
+
+    /**
+     * Returns a configuration object for the given file based on the CLI options.
+     * This is the same logic used by the ESLint CLI executable to determine
+     * configuration for each file it processes.
+     * @param {string} filePath The path of the file to retrieve a config object for.
+     * @returns {Promise<ConfigData>} A configuration object for the file.
+     */
+    async calculateConfigForFile(filePath) {
+        if (!isNonEmptyString(filePath)) {
+            throw new Error("'filePath' must be a non-empty string");
+        }
+        const { cliEngine } = privateMembersMap.get(this);
+
+        return cliEngine.getConfigForFile(filePath);
+    }
+
+    /**
+     * Checks if a given path is ignored by ESLint.
+     * @param {string} filePath The path of the file to check.
+     * @returns {Promise<boolean>} Whether or not the given path is ignored.
+     */
+    async isPathIgnored(filePath) {
+        if (!isNonEmptyString(filePath)) {
+            throw new Error("'filePath' must be a non-empty string");
+        }
+        const { cliEngine } = privateMembersMap.get(this);
+
+        return cliEngine.isPathIgnored(filePath);
+    }
+}
+
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+module.exports = {
+    ESLint,
+
+    /**
+     * Get the private class members of a given ESLint instance for tests.
+     * @param {ESLint} instance The ESLint instance to get.
+     * @returns {ESLintPrivateMembers} The instance's private class members.
+     */
+    getESLintPrivateMembers(instance) {
+        return privateMembersMap.get(instance);
+    }
+};
diff --git a/eslint/lib/eslint/index.js b/eslint/lib/eslint/index.js
new file mode 100644 (file)
index 0000000..c9185ee
--- /dev/null
@@ -0,0 +1,7 @@
+"use strict";
+
+const { ESLint } = require("./eslint");
+
+module.exports = {
+    ESLint
+};
index 64be3d2a84f49bc0a646d8a3e85171442b0ec18f..2b0aa12ac13df610b5cf352217162937e9e35f75 100644 (file)
@@ -301,7 +301,7 @@ class Registry {
                 ruleSetIdx += 1;
 
                 if (cb) {
-                    cb(totalFilesLinting); // eslint-disable-line callback-return
+                    cb(totalFilesLinting); // eslint-disable-line node/callback-return
                 }
             });
 
@@ -316,10 +316,10 @@ class Registry {
 /**
  * Extract rule configuration into eslint:recommended where possible.
  *
- * This will return a new config with `"extends": "eslint:recommended"` and
+ * This will return a new config with `["extends": [ ..., "eslint:recommended"]` and
  * only the rules which have configurations different from the recommended config.
  * @param   {Object} config config object
- * @returns {Object}        config object using `"extends": "eslint:recommended"`
+ * @returns {Object}        config object using `"extends": ["eslint:recommended"]`
  */
 function extendFromRecommended(config) {
     const newConfig = Object.assign({}, config);
@@ -333,7 +333,7 @@ function extendFromRecommended(config) {
             delete newConfig.rules[ruleId];
         }
     });
-    newConfig.extends = RECOMMENDED_CONFIG_NAME;
+    newConfig.extends.unshift(RECOMMENDED_CONFIG_NAME);
     return newConfig;
 }
 
index 28dfad194a7e6fac13b89ca1a899e86cd571d37d..70f0a250ad1dd69ab0412271920c9b4e615f1c80 100644 (file)
@@ -15,6 +15,7 @@ const util = require("util"),
     inquirer = require("inquirer"),
     ProgressBar = require("progress"),
     semver = require("semver"),
+    espree = require("espree"),
     recConfig = require("../../conf/eslint-recommended"),
     ConfigOps = require("../shared/config-ops"),
     log = require("../shared/logging"),
@@ -31,8 +32,6 @@ const debug = require("debug")("eslint:config-initializer");
 // Private
 //------------------------------------------------------------------------------
 
-const DEFAULT_ECMA_VERSION = 2018;
-
 /* istanbul ignore next: hard to test fs function */
 /**
  * Create .eslintrc file in the current working directory
@@ -265,8 +264,7 @@ function processAnswers(answers) {
         extends: []
     };
 
-    // set the latest ECMAScript version
-    config.parserOptions.ecmaVersion = DEFAULT_ECMA_VERSION;
+    config.parserOptions.ecmaVersion = espree.latestEcmaVersion;
     config.env.es6 = true;
     config.globals = {
         Atomics: "readonly",
index dfc170a65cf71b9af2632cf83d9ffa0fa42ded34..dca6541d1ed32831791d172d1fdaa7769f6c1f76 100644 (file)
@@ -23,7 +23,7 @@ const { CLIEngine } = require("../cli-engine");
  * TODO1: Expose the API that enumerates target files.
  * TODO2: Extract the creation logic of `SourceCode` from `Linter` class.
  */
-const { getCLIEngineInternalSlots } = require("../cli-engine/cli-engine"); // eslint-disable-line no-restricted-modules
+const { getCLIEngineInternalSlots } = require("../cli-engine/cli-engine"); // eslint-disable-line node/no-restricted-require
 
 const debug = require("debug")("eslint:source-code-utils");
 
@@ -97,7 +97,7 @@ function getSourceCodeOfFiles(patterns, options, callback) {
             sourceCodes[filename] = sourceCode;
         }
         if (callback) {
-            callback(filenames.length); // eslint-disable-line callback-return
+            callback(filenames.length); // eslint-disable-line node/callback-return
         }
     });
 
index 98dc04b6eb3968ce2aea09241d6d838411e0c03b..1681f1dbd1d733fe77255df3839c1dd75dc62e89 100644 (file)
@@ -46,7 +46,6 @@ module.exports = optionator({
         {
             option: "ext",
             type: "[String]",
-            default: ".js",
             description: "Specify JavaScript file extensions"
         },
         {
index 1c1737152c1b197c9d5321c32d4db48dd84265ae..77df1def893ccc57046b5a94c61e62f0570434dc 100644 (file)
@@ -563,7 +563,12 @@ class RuleTester {
                 output = SourceCodeFixer.applyFixes(code, messages).output;
                 const errorMessageInFix = linter.verify(output, config, filename).find(m => m.fatal);
 
-                assert(!errorMessageInFix, `A fatal parsing error occurred in autofix: ${errorMessageInFix && errorMessageInFix.message}`);
+                assert(!errorMessageInFix, [
+                    "A fatal parsing error occurred in autofix.",
+                    `Error: ${errorMessageInFix && errorMessageInFix.message}`,
+                    "Autofix output:",
+                    output
+                ].join("\n"));
             } else {
                 output = code;
             }
index eb38965024f05da3f7062998a30514eb9c53774b..62ba7b72d8725726a4578f725492d7524df35a81 100644 (file)
@@ -29,22 +29,6 @@ function isReachable(segment) {
     return segment.reachable;
 }
 
-/**
- * Gets a readable location.
- *
- * - FunctionExpression -> the function name or `function` keyword.
- * - ArrowFunctionExpression -> `=>` token.
- * @param {ASTNode} node A function node to get.
- * @param {SourceCode} sourceCode A source code to get tokens.
- * @returns {ASTNode|Token} The node or the token of a location.
- */
-function getLocation(node, sourceCode) {
-    if (node.type === "ArrowFunctionExpression") {
-        return sourceCode.getTokenBefore(node.body);
-    }
-    return node.id || node;
-}
-
 /**
  * Checks a given node is a MemberExpression node which has the specified name's
  * property.
@@ -179,6 +163,7 @@ module.exports = {
     create(context) {
 
         const options = context.options[0] || { allowImplicit: false, checkForEach: false };
+        const sourceCode = context.getSourceCode();
 
         let funcInfo = {
             arrayMethodName: null,
@@ -217,12 +202,12 @@ module.exports = {
             }
 
             if (messageId) {
-                let name = astUtils.getFunctionNameWithKind(funcInfo.node);
+                let name = astUtils.getFunctionNameWithKind(node);
 
                 name = messageId === "expectedNoReturnValue" ? lodash.upperFirst(name) : name;
                 context.report({
                     node,
-                    loc: getLocation(node, context.getSourceCode()).loc.start,
+                    loc: astUtils.getFunctionHeadLoc(node, sourceCode),
                     messageId,
                     data: { name }
                 });
index c5263cde46b75255b3ab5995e2d2ed44c4fc3147..5df792d436341e449cb9b2648ea659df6bee64ca 100644 (file)
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/callback-return"],
+
         type: "suggestion",
 
         docs: {
index bc22f05dd3892ce0e3b46ce31267e25a6663af92..f1a23d63b786a0bd9877836c3bf9e1e1b0e0b82d 100644 (file)
@@ -146,10 +146,7 @@ module.exports = {
                 // lone comma
                 context.report({
                     node: reportItem,
-                    loc: {
-                        line: commaToken.loc.end.line,
-                        column: commaToken.loc.start.column
-                    },
+                    loc: commaToken.loc,
                     messageId: "unexpectedLineBeforeAndAfterComma",
                     fix: getFixerFunction(styleType, previousItemToken, commaToken, currentItemToken)
                 });
@@ -158,6 +155,7 @@ module.exports = {
 
                 context.report({
                     node: reportItem,
+                    loc: commaToken.loc,
                     messageId: "expectedCommaFirst",
                     fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken)
                 });
@@ -166,10 +164,7 @@ module.exports = {
 
                 context.report({
                     node: reportItem,
-                    loc: {
-                        line: commaToken.loc.end.line,
-                        column: commaToken.loc.end.column
-                    },
+                    loc: commaToken.loc,
                     messageId: "expectedCommaLast",
                     fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken)
                 });
index e2edd4282da578468571a15bcd4dfc3174c1d61b..dccdd0a40c6d7624773d48ac0261ac6e1ba71a17 100644 (file)
@@ -63,7 +63,8 @@ module.exports = {
         },
 
         messages: {
-            unexpected: "Unexpected newline between function name and paren.",
+            unexpectedWhitespace: "Unexpected whitespace between function name and paren.",
+            unexpectedNewline: "Unexpected newline between function name and paren.",
             missing: "Missing space between function name and paren."
         }
     },
@@ -116,7 +117,7 @@ module.exports = {
                 context.report({
                     node,
                     loc: leftToken.loc.start,
-                    messageId: "unexpected",
+                    messageId: "unexpectedWhitespace",
                     fix(fixer) {
 
                         /*
@@ -143,7 +144,7 @@ module.exports = {
                 context.report({
                     node,
                     loc: leftToken.loc.start,
-                    messageId: "unexpected",
+                    messageId: "unexpectedNewline",
                     fix(fixer) {
                         return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ");
                     }
index e1468a5b19f88d8cc1a1b7b311ace791dfaf8223..c54ebfb4ffb8cd509ebf8e5f489a0cb6e940b4c5 100644 (file)
@@ -25,17 +25,6 @@ function isReachable(segment) {
     return segment.reachable;
 }
 
-/**
- * Gets a readable location.
- *
- * - FunctionExpression -> the function name or `function` keyword.
- * @param {ASTNode} node A function node to get.
- * @returns {ASTNode|Token} The node or the token of a location.
- */
-function getId(node) {
-    return node.id || node;
-}
-
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -75,6 +64,7 @@ module.exports = {
     create(context) {
 
         const options = context.options[0] || { allowImplicit: false };
+        const sourceCode = context.getSourceCode();
 
         let funcInfo = {
             upper: null,
@@ -99,7 +89,7 @@ module.exports = {
             ) {
                 context.report({
                     node,
-                    loc: getId(node).loc.start,
+                    loc: astUtils.getFunctionHeadLoc(node, sourceCode),
                     messageId: funcInfo.hasReturn ? "expectedAlways" : "expected",
                     data: {
                         name: astUtils.getFunctionNameWithKind(funcInfo.node)
index 4af3a6a4669a7983bb55a0407e9950b56f40afa0..9bd073b88546d6307d0630a9b9485883b2975c9e 100644 (file)
@@ -48,6 +48,10 @@ function isShadowed(scope, node) {
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/global-require"],
+
         type: "suggestion",
 
         docs: {
index 640946699e7bea3e0c9123c454e7109b95c4688d..8ad63bbd53a77b29f4c98137ef57d54c22cfe721 100644 (file)
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/handle-callback-err"],
+
         type: "suggestion",
 
         docs: {
index c405043794c7d1eb608d35874b41ab2bb14905b8..57abb00b06e8a4e5df64b2a34f03ef85e0231c7e 100644 (file)
@@ -45,7 +45,7 @@ function isSingleLine(node) {
 /**
  * Checks whether the properties on a single line.
  * @param {ASTNode[]} properties List of Property AST nodes.
- * @returns {boolean} True if all properies is on a single line.
+ * @returns {boolean} True if all properties is on a single line.
  */
 function isSingleLineProperties(properties) {
     const [firstProp] = properties,
index 7cce968c5aed0ec673bf08aca5e5e7c442aded65..0faf45efb92daf6f1137a962bdd426fd37a44768 100644 (file)
@@ -235,7 +235,7 @@ module.exports = {
                 callee = callee.property;
             }
 
-            context.report({ node, loc: callee.loc.start, messageId });
+            context.report({ node, loc: callee.loc, messageId });
         }
 
         //--------------------------------------------------------------------------
index 8ad88386c0f61db3030bb00dec3c9012c766362e..4254fec185ef885113f9192727f43ebe44da3edc 100644 (file)
@@ -90,16 +90,19 @@ module.exports = {
                 }
 
                 if (depth > ignoreChainWithDepth && astUtils.isTokenOnSameLine(callee.object, callee.property)) {
+                    const firstTokenAfterObject = sourceCode.getTokenAfter(callee.object, astUtils.isNotClosingParenToken);
+
                     context.report({
                         node: callee.property,
-                        loc: callee.property.loc.start,
+                        loc: {
+                            start: firstTokenAfterObject.loc.start,
+                            end: callee.loc.end
+                        },
                         messageId: "expected",
                         data: {
                             callee: getPropertyText(callee)
                         },
                         fix(fixer) {
-                            const firstTokenAfterObject = sourceCode.getTokenAfter(callee.object, astUtils.isNotClosingParenToken);
-
                             return fixer.insertTextBefore(firstTokenAfterObject, "\n");
                         }
                     });
index bf4c8891ad1adfff8eabc35aae2ff9b445711526..5dce047b92312efad66a70692c8f71503c7c5958 100644 (file)
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/no-deprecated-api"],
+
         type: "problem",
 
         docs: {
index c74321158b3464c7d3c01e0819a54f2106c78175..c512f8cd5f45004b00c0d927ad279a8c38dcc5f8 100644 (file)
@@ -151,7 +151,7 @@ module.exports = {
             ) {
                 context.report({
                     node,
-                    loc: node.body.loc.start,
+                    loc: node.body.loc,
                     messageId: "unexpected",
                     data: { name }
                 });
index a3dd5bab699da3173c7a7ee99e5235c031f59ed2..7cbb7522ebedfad469f428f74e9892d528c7f933 100644 (file)
@@ -560,7 +560,11 @@ module.exports = {
                 tokensToIgnore.add(secondToken);
             }
 
-            if (hasExcessParens(node)) {
+            const hasExtraParens = node.parent.type === "ExportDefaultDeclaration"
+                ? hasExcessParensWithPrecedence(node, PRECEDENCE_OF_ASSIGNMENT_EXPR)
+                : hasExcessParens(node);
+
+            if (hasExtraParens) {
                 report(node);
             }
         }
index e1c29e0a3b4f3f4e42ea8ef6fbbb378759c7de9e..0768bc61149cecc2040e39ed7b0219cf04912156 100644 (file)
@@ -5,10 +5,19 @@
 
 "use strict";
 
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
 
+const validParent = new Set(["Program", "ExportNamedDeclaration", "ExportDefaultDeclaration"]);
+const validBlockStatementParent = new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]);
+
 module.exports = {
     meta: {
         type: "problem",
@@ -33,54 +42,37 @@ module.exports = {
 
     create(context) {
 
-        /**
-         * Find the nearest Program or Function ancestor node.
-         * @returns {Object} Ancestor's type and distance from node.
-         */
-        function nearestBody() {
-            const ancestors = context.getAncestors();
-            let ancestor = ancestors.pop(),
-                generation = 1;
-
-            while (ancestor && ["Program", "FunctionDeclaration",
-                "FunctionExpression", "ArrowFunctionExpression"
-            ].indexOf(ancestor.type) < 0) {
-                generation += 1;
-                ancestor = ancestors.pop();
-            }
-
-            return {
-
-                // Type of containing ancestor
-                type: ancestor.type,
-
-                // Separation between ancestor and node
-                distance: generation
-            };
-        }
-
         /**
          * Ensure that a given node is at a program or function body's root.
          * @param {ASTNode} node Declaration node to check.
          * @returns {void}
          */
         function check(node) {
-            const body = nearestBody(),
-                valid = ((body.type === "Program" && body.distance === 1) ||
-                    body.distance === 2);
-
-            if (!valid) {
-                context.report({
-                    node,
-                    messageId: "moveDeclToRoot",
-                    data: {
-                        type: (node.type === "FunctionDeclaration" ? "function" : "variable"),
-                        body: (body.type === "Program" ? "program" : "function body")
-                    }
-                });
+            const parent = node.parent;
+
+            if (
+                parent.type === "BlockStatement" && validBlockStatementParent.has(parent.parent.type)
+            ) {
+                return;
+            }
+
+            if (validParent.has(parent.type)) {
+                return;
             }
+
+            const upperFunction = astUtils.getUpperFunction(parent);
+
+            context.report({
+                node,
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: (node.type === "FunctionDeclaration" ? "function" : "variable"),
+                    body: (upperFunction === null ? "program" : "function body")
+                }
+            });
         }
 
+
         return {
 
             FunctionDeclaration: check,
index d7069887b8e4606efc8b5b96216026ebf4f22f4a..290784b82ea2fb7eb416b50dca6ffa8f85ca86fe 100644 (file)
@@ -49,7 +49,7 @@ module.exports = {
         }
 
         /**
-         * Checks for any ocurrence of a BlockStatement in a place where lists of statements can appear
+         * Checks for any occurrence of a BlockStatement in a place where lists of statements can appear
          * @param {ASTNode} node The node to check
          * @returns {boolean} True if the node is a lone block.
          */
index 8e988e32c24f84780fb48bde5841ac525c070b10..bfe9b7aa97858a70704aa79194a6dbf170603973 100644 (file)
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/no-mixed-requires"],
+
         type: "suggestion",
 
         docs: {
index f3e99c9bd13502c793de91e850c70dc82bdca67a..e9f915db5eaa9173dfe8a094da8dbdcd7b519252 100644 (file)
@@ -5,6 +5,12 @@
 
 "use strict";
 
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -28,10 +34,17 @@ module.exports = {
     },
 
     create(context) {
-
         return {
-
             NewExpression(node) {
+                const variable = astUtils.getVariableByName(
+                    context.getScope(),
+                    node.callee.name
+                );
+
+                if (variable && variable.identifiers.length > 0) {
+                    return;
+                }
+
                 if (node.callee.name === "Object") {
                     context.report({
                         node,
@@ -40,6 +53,5 @@ module.exports = {
                 }
             }
         };
-
     }
 };
index df12a424e3527edfe32c7d4ef53ad880924eedb5..7f81e83fd782c33b3f18260cb9c4fc52b105b148 100644 (file)
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/no-new-require"],
+
         type: "suggestion",
 
         docs: {
index 9fa8b852fe8358993291646e72ae0ce740902995..77a03a7f952b047afe9bc0b3b25a1ea280cf4b55 100644 (file)
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/no-path-concat"],
+
         type: "suggestion",
 
         docs: {
index 0f8d7f8a339d0efc2911cf132af3f0300861205d..24bb9f9971d5c923d59cbd492267e31bf870e33e 100644 (file)
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/no-process-env"],
+
         type: "suggestion",
 
         docs: {
index 29871660cc6ee14c5b6d8201dc921e501d2b07cc..9c70ea8808b4c4c6495ed77a53f09ead75db0165 100644 (file)
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/no-process-exit"],
+
         type: "suggestion",
 
         docs: {
index abd8d5cbe29381af123005679275ee49ca3dca51..61834ceeb444d3544df8f1b0434f2842649b6612 100644 (file)
@@ -40,6 +40,10 @@ const arrayOfStringsOrObjects = {
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/no-restricted-require"],
+
         type: "suggestion",
 
         docs: {
index d81110596317340c08e8d6ec6b38f5ade5200bb6..9790d1f94bb20c7c77363d0a2cd61991e4a7f9ce 100644 (file)
 
 module.exports = {
     meta: {
+        deprecated: true,
+
+        replacedBy: ["node/no-sync"],
+
         type: "suggestion",
 
         docs: {
index eb72008a2947e76e8d5bf011de0c6682cfb6717a..b5ec20de4b20a34cd2bbf9bedecab5650f2592a4 100644 (file)
@@ -53,7 +53,11 @@ module.exports = {
             const nodeExpressionEnd = sourceCode.getTokenBefore(openParen);
 
             if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) {
-                context.report({ node, loc: openParen.loc.start, messageId, data: { char: openParen.value } });
+                context.report({
+                    node,
+                    loc: openParen.loc,
+                    messageId
+                });
             }
         }
 
@@ -71,18 +75,24 @@ module.exports = {
             },
 
             TaggedTemplateExpression(node) {
-                if (node.tag.loc.end.line === node.quasi.loc.start.line) {
-                    return;
-                }
-
-                // handle generics type parameters on template tags
-                const tokenBefore = sourceCode.getTokenBefore(node.quasi);
-
-                if (tokenBefore.loc.end.line === node.quasi.loc.start.line) {
-                    return;
+                const { quasi } = node;
+
+                // handles common tags, parenthesized tags, and typescript's generic type arguments
+                const tokenBefore = sourceCode.getTokenBefore(quasi);
+
+                if (tokenBefore.loc.end.line !== quasi.loc.start.line) {
+                    context.report({
+                        node,
+                        loc: {
+                            start: quasi.loc.start,
+                            end: {
+                                line: quasi.loc.start.line,
+                                column: quasi.loc.start.column + 1
+                            }
+                        },
+                        messageId: "taggedTemplate"
+                    });
                 }
-
-                context.report({ node, loc: node.loc.start, messageId: "taggedTemplate" });
             },
 
             CallExpression(node) {
index aa46742abdd5cae6c778db1d1cabc64500b33c6d..cfc60c8fb51a240b3a9a8984ed71256ecced2deb 100644 (file)
@@ -105,7 +105,7 @@ module.exports = {
 
                     context.report({
                         node,
-                        loc: operatorToken.loc.start,
+                        loc: operatorToken.loc,
                         messageId: "unexpectedConcat"
                     });
                 }
index af609c2e7c72fae2d74242b486d6e6e84a21e0a4..1021a110cfd3f0488a46a597a368d6bb2b787f9f 100644 (file)
@@ -127,7 +127,10 @@ module.exports = {
             if (hasSpacing && functionConfig === "never") {
                 context.report({
                     node,
-                    loc: leftToken.loc.end,
+                    loc: {
+                        start: leftToken.loc.end,
+                        end: rightToken.loc.start
+                    },
                     messageId: "unexpectedSpace",
                     fix(fixer) {
                         const comments = sourceCode.getCommentsBefore(rightToken);
@@ -145,7 +148,7 @@ module.exports = {
             } else if (!hasSpacing && functionConfig === "always") {
                 context.report({
                     node,
-                    loc: leftToken.loc.end,
+                    loc: rightToken.loc,
                     messageId: "missingSpace",
                     fix: fixer => fixer.insertTextAfter(leftToken, " ")
                 });
index c4ff3f819385950408383ddbcff79a418913e3c8..f1159e5255df79d00058e3deba4f5fa8048bace6 100644 (file)
@@ -20,7 +20,7 @@ const astUtils = require("./utils/ast-utils");
  * @returns {boolean} Whether or not it is a comparison operator.
  */
 function isComparisonOperator(operator) {
-    return (/^(==|===|!=|!==|<|>|<=|>=)$/u).test(operator);
+    return /^(==|===|!=|!==|<|>|<=|>=)$/u.test(operator);
 }
 
 /**
@@ -29,7 +29,7 @@ function isComparisonOperator(operator) {
  * @returns {boolean} Whether or not it is an equality operator.
  */
 function isEqualityOperator(operator) {
-    return (/^(==|===)$/u).test(operator);
+    return /^(==|===)$/u.test(operator);
 }
 
 /**
@@ -50,10 +50,12 @@ function isRangeTestOperator(operator) {
  *                    real literal and should be treated as such.
  */
 function isNegativeNumericLiteral(node) {
-    return (node.type === "UnaryExpression" &&
+    return (
+        node.type === "UnaryExpression" &&
         node.operator === "-" &&
         node.prefix &&
-        astUtils.isNumericLiteral(node.argument));
+        astUtils.isNumericLiteral(node.argument)
+    );
 }
 
 /**
@@ -71,25 +73,21 @@ function isStaticTemplateLiteral(node) {
  * @returns {boolean} True if the node should be treated as a single Literal node.
  */
 function looksLikeLiteral(node) {
-    return isNegativeNumericLiteral(node) ||
-        isStaticTemplateLiteral(node);
+    return isNegativeNumericLiteral(node) || isStaticTemplateLiteral(node);
 }
 
 /**
  * Attempts to derive a Literal node from nodes that are treated like literals.
  * @param {ASTNode} node Node to normalize.
- * @param {number} [defaultValue] The default value to be returned if the node
- *                                is not a Literal.
  * @returns {ASTNode} One of the following options.
  *  1. The original node if the node is already a Literal
  *  2. A normalized Literal node with the negative number as the value if the
  *     node represents a negative number literal.
  *  3. A normalized Literal node with the string as the value if the node is
  *     a Template Literal without expression.
- *  4. The Literal node which has the `defaultValue` argument if it exists.
- *  5. Otherwise `null`.
+ *  4. Otherwise `null`.
  */
-function getNormalizedLiteral(node, defaultValue) {
+function getNormalizedLiteral(node) {
     if (node.type === "Literal") {
         return node;
     }
@@ -110,14 +108,6 @@ function getNormalizedLiteral(node, defaultValue) {
         };
     }
 
-    if (defaultValue) {
-        return {
-            type: "Literal",
-            value: defaultValue,
-            raw: String(defaultValue)
-        };
-    }
-
     return null;
 }
 
@@ -183,7 +173,7 @@ module.exports = {
         type: "suggestion",
 
         docs: {
-            description: "require or disallow \"Yoda\" conditions",
+            description: 'require or disallow "Yoda" conditions',
             category: "Best Practices",
             recommended: false,
             url: "https://eslint.org/docs/rules/yoda"
@@ -211,16 +201,19 @@ module.exports = {
 
         fixable: "code",
         messages: {
-            expected: "Expected literal to be on the {{expectedSide}} side of {{operator}}."
+            expected:
+                "Expected literal to be on the {{expectedSide}} side of {{operator}}."
         }
     },
 
     create(context) {
 
         // Default to "never" (!always) if no option
-        const always = (context.options[0] === "always");
-        const exceptRange = (context.options[1] && context.options[1].exceptRange);
-        const onlyEquality = (context.options[1] && context.options[1].onlyEquality);
+        const always = context.options[0] === "always";
+        const exceptRange =
+            context.options[1] && context.options[1].exceptRange;
+        const onlyEquality =
+            context.options[1] && context.options[1].onlyEquality;
 
         const sourceCode = context.getSourceCode();
 
@@ -243,13 +236,23 @@ module.exports = {
              * @returns {boolean} Whether node is a "between" range test.
              */
             function isBetweenTest() {
-                let leftLiteral, rightLiteral;
+                if (node.operator === "&&" && same(left.right, right.left)) {
+                    const leftLiteral = getNormalizedLiteral(left.left);
+                    const rightLiteral = getNormalizedLiteral(right.right);
+
+                    if (leftLiteral === null && rightLiteral === null) {
+                        return false;
+                    }
 
-                return (node.operator === "&&" &&
-                    (leftLiteral = getNormalizedLiteral(left.left)) &&
-                    (rightLiteral = getNormalizedLiteral(right.right, Number.POSITIVE_INFINITY)) &&
-                    leftLiteral.value <= rightLiteral.value &&
-                    same(left.right, right.left));
+                    if (rightLiteral === null || leftLiteral === null) {
+                        return true;
+                    }
+
+                    if (leftLiteral.value <= rightLiteral.value) {
+                        return true;
+                    }
+                }
+                return false;
             }
 
             /**
@@ -257,13 +260,24 @@ module.exports = {
              * @returns {boolean} Whether node is an "outside" range test.
              */
             function isOutsideTest() {
-                let leftLiteral, rightLiteral;
+                if (node.operator === "||" && same(left.left, right.right)) {
+                    const leftLiteral = getNormalizedLiteral(left.right);
+                    const rightLiteral = getNormalizedLiteral(right.left);
+
+                    if (leftLiteral === null && rightLiteral === null) {
+                        return false;
+                    }
+
+                    if (rightLiteral === null || leftLiteral === null) {
+                        return true;
+                    }
+
+                    if (leftLiteral.value <= rightLiteral.value) {
+                        return true;
+                    }
+                }
 
-                return (node.operator === "||" &&
-                    (leftLiteral = getNormalizedLiteral(left.right, Number.NEGATIVE_INFINITY)) &&
-                    (rightLiteral = getNormalizedLiteral(right.left)) &&
-                    leftLiteral.value <= rightLiteral.value &&
-                    same(left.left, right.right));
+                return false;
             }
 
             /**
@@ -276,13 +290,15 @@ module.exports = {
                 return astUtils.isParenthesised(sourceCode, node);
             }
 
-            return (node.type === "LogicalExpression" &&
+            return (
+                node.type === "LogicalExpression" &&
                 left.type === "BinaryExpression" &&
                 right.type === "BinaryExpression" &&
                 isRangeTestOperator(left.operator) &&
                 isRangeTestOperator(right.operator) &&
                 (isBetweenTest() || isOutsideTest()) &&
-                isParenWrapped());
+                isParenWrapped()
+            );
         }
 
         const OPERATOR_FLIP_MAP = {
@@ -303,21 +319,52 @@ module.exports = {
          */
         function getFlippedString(node) {
             const tokenBefore = sourceCode.getTokenBefore(node);
-            const operatorToken = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator);
-            const textBeforeOperator = sourceCode.getText().slice(sourceCode.getTokenBefore(operatorToken).range[1], operatorToken.range[0]);
-            const textAfterOperator = sourceCode.getText().slice(operatorToken.range[1], sourceCode.getTokenAfter(operatorToken).range[0]);
-            const leftText = sourceCode.getText().slice(node.range[0], sourceCode.getTokenBefore(operatorToken).range[1]);
+            const operatorToken = sourceCode.getFirstTokenBetween(
+                node.left,
+                node.right,
+                token => token.value === node.operator
+            );
+            const textBeforeOperator = sourceCode
+                .getText()
+                .slice(
+                    sourceCode.getTokenBefore(operatorToken).range[1],
+                    operatorToken.range[0]
+                );
+            const textAfterOperator = sourceCode
+                .getText()
+                .slice(
+                    operatorToken.range[1],
+                    sourceCode.getTokenAfter(operatorToken).range[0]
+                );
+            const leftText = sourceCode
+                .getText()
+                .slice(
+                    node.range[0],
+                    sourceCode.getTokenBefore(operatorToken).range[1]
+                );
             const firstRightToken = sourceCode.getTokenAfter(operatorToken);
-            const rightText = sourceCode.getText().slice(firstRightToken.range[0], node.range[1]);
+            const rightText = sourceCode
+                .getText()
+                .slice(firstRightToken.range[0], node.range[1]);
 
             let prefix = "";
 
-            if (tokenBefore && tokenBefore.range[1] === node.range[0] &&
-                    !astUtils.canTokensBeAdjacent(tokenBefore, firstRightToken)) {
+            if (
+                tokenBefore &&
+                tokenBefore.range[1] === node.range[0] &&
+                !astUtils.canTokensBeAdjacent(tokenBefore, firstRightToken)
+            ) {
                 prefix = " ";
             }
 
-            return prefix + rightText + textBeforeOperator + OPERATOR_FLIP_MAP[operatorToken.value] + textAfterOperator + leftText;
+            return (
+                prefix +
+                rightText +
+                textBeforeOperator +
+                OPERATOR_FLIP_MAP[operatorToken.value] +
+                textAfterOperator +
+                leftText
+            );
         }
 
         //--------------------------------------------------------------------------
@@ -331,8 +378,12 @@ module.exports = {
 
                 // If `expectedLiteral` is not a literal, and `expectedNonLiteral` is a literal, raise an error.
                 if (
-                    (expectedNonLiteral.type === "Literal" || looksLikeLiteral(expectedNonLiteral)) &&
-                    !(expectedLiteral.type === "Literal" || looksLikeLiteral(expectedLiteral)) &&
+                    (expectedNonLiteral.type === "Literal" ||
+                        looksLikeLiteral(expectedNonLiteral)) &&
+                    !(
+                        expectedLiteral.type === "Literal" ||
+                        looksLikeLiteral(expectedLiteral)
+                    ) &&
                     !(!isEqualityOperator(node.operator) && onlyEquality) &&
                     isComparisonOperator(node.operator) &&
                     !(exceptRange && isRangeTest(context.getAncestors().pop()))
@@ -344,12 +395,11 @@ module.exports = {
                             operator: node.operator,
                             expectedSide: always ? "left" : "right"
                         },
-                        fix: fixer => fixer.replaceText(node, getFlippedString(node))
+                        fix: fixer =>
+                            fixer.replaceText(node, getFlippedString(node))
                     });
                 }
-
             }
         };
-
     }
 };
index fa6cca72361df51adc87945e98c351055b16d204..80335c5cfca7c84c1dd83cbe33481ed8247682ec 100644 (file)
@@ -11,6 +11,7 @@ const Module = require("module");
  * `Module.createRequire` is added in v12.2.0. It supports URL as well.
  * We only support the case where the argument is a filepath, not a URL.
  */
+// eslint-disable-next-line node/no-unsupported-features/node-builtins, node/no-deprecated-api
 const createRequire = Module.createRequire || Module.createRequireFromPath;
 
 module.exports = {
index bf37327fa240ca98ebea013112401595efcdce01..bbd95d1b37862fd6af3d38610906b837cac80f0f 100644 (file)
@@ -141,3 +141,10 @@ module.exports = {};
  * @property {Record<string, Processor>} [processors] The definition of plugin processors.
  * @property {Record<string, Function | Rule>} [rules] The definition of plugin rules.
  */
+
+/**
+ * Information of deprecated rules.
+ * @typedef {Object} DeprecatedRuleInfo
+ * @property {string} ruleId The rule ID.
+ * @property {string[]} replacedBy The rule IDs that replace this deprecated rule.
+ */
index ed15f61d02bbe55df5e1c2bd291ffcb64d8d9b08..b775ebda86f844348934ab04c5bc81e51b378110 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "7.0.0-alpha.3",
+  "version": "7.0.0",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
   "dependencies": {
     "@babel/code-frame": "^7.0.0",
     "ajv": "^6.10.0",
-    "chalk": "^3.0.0",
-    "cross-spawn": "^7.0.1",
+    "chalk": "^4.0.0",
+    "cross-spawn": "^7.0.2",
     "debug": "^4.0.1",
     "doctrine": "^3.0.0",
     "eslint-scope": "^5.0.0",
     "eslint-utils": "^2.0.0",
     "eslint-visitor-keys": "^1.1.0",
-    "espree": "^6.2.1",
+    "espree": "^7.0.0",
     "esquery": "^1.2.0",
     "esutils": "^2.0.2",
     "file-entry-cache": "^5.0.1",
     "is-glob": "^4.0.0",
     "js-yaml": "^3.13.1",
     "json-stable-stringify-without-jsonify": "^1.0.1",
-    "levn": "^0.3.0",
+    "levn": "^0.4.1",
     "lodash": "^4.17.14",
     "minimatch": "^3.0.4",
     "natural-compare": "^1.4.0",
-    "optionator": "^0.8.3",
+    "optionator": "^0.9.1",
     "progress": "^2.0.0",
-    "regexpp": "^3.0.0",
-    "semver": "^7.1.1",
+    "regexpp": "^3.1.0",
+    "semver": "^7.2.1",
     "strip-ansi": "^6.0.0",
-    "strip-json-comments": "^3.0.1",
+    "strip-json-comments": "^3.1.0",
     "table": "^5.2.3",
     "text-table": "^0.2.0",
     "v8-compile-cache": "^2.0.3"
     "common-tags": "^1.8.0",
     "core-js": "^3.1.3",
     "dateformat": "^3.0.3",
-    "ejs": "^2.6.1",
+    "ejs": "^3.0.2",
+    "escape-string-regexp": "^3.0.0",
     "eslint": "file:.",
     "eslint-config-eslint": "file:packages/eslint-config-eslint",
     "eslint-plugin-eslint-plugin": "^2.2.1",
     "eslint-plugin-internal-rules": "file:tools/internal-rules",
-    "eslint-plugin-jsdoc": "^15.9.5",
-    "eslint-plugin-node": "^9.0.0",
-    "eslint-release": "^1.2.0",
+    "eslint-plugin-jsdoc": "^22.1.0",
+    "eslint-plugin-node": "^11.1.0",
+    "eslint-release": "^2.0.0",
     "eslump": "^2.0.0",
     "esprima": "^4.0.1",
-    "glob": "^7.1.3",
+    "glob": "^7.1.6",
     "jsdoc": "^3.5.5",
     "karma": "^4.0.1",
-    "karma-chrome-launcher": "^2.2.0",
+    "karma-chrome-launcher": "^3.1.0",
     "karma-mocha": "^1.3.0",
     "karma-mocha-reporter": "^2.2.3",
     "karma-webpack": "^4.0.0-rc.6",
     "leche": "^2.2.3",
-    "lint-staged": "^8.1.5",
+    "lint-staged": "^10.1.2",
     "load-perf": "^0.2.0",
-    "markdownlint": "^0.15.0",
-    "markdownlint-cli": "^0.17.0",
+    "markdownlint": "^0.19.0",
+    "markdownlint-cli": "^0.22.0",
     "memfs": "^3.0.1",
-    "mocha": "^6.1.2",
+    "mocha": "^7.1.1",
     "mocha-junit-reporter": "^1.23.0",
     "npm-license": "^0.3.3",
-    "nyc": "^14.1.1",
+    "nyc": "^15.0.1",
     "proxyquire": "^2.0.1",
-    "puppeteer": "^1.18.0",
-    "recast": "^0.18.1",
+    "puppeteer": "^2.1.1",
+    "recast": "^0.19.0",
     "regenerator-runtime": "^0.13.2",
     "shelljs": "^0.8.2",
-    "sinon": "^7.3.2",
+    "sinon": "^9.0.1",
     "temp": "^0.9.0",
     "webpack": "^4.35.0",
     "webpack-cli": "^3.3.5",
diff --git a/eslint/tests/_utils/in-memory-fs.js b/eslint/tests/_utils/in-memory-fs.js
new file mode 100644 (file)
index 0000000..5ef4f04
--- /dev/null
@@ -0,0 +1,541 @@
+/**
+ * @fileoverview Define classes what use the in-memory file system.
+ *
+ * This provides utilities to test `ConfigArrayFactory`,
+ * `CascadingConfigArrayFactory`, `FileEnumerator`, `CLIEngine`, and `ESLint`.
+ *
+ * - `defineConfigArrayFactoryWithInMemoryFileSystem({ cwd, files })`
+ * - `defineCascadingConfigArrayFactoryWithInMemoryFileSystem({ cwd, files })`
+ * - `defineFileEnumeratorWithInMemoryFileSystem({ cwd, files })`
+ * - `defineCLIEngineWithInMemoryFileSystem({ cwd, files })`
+ * - `defineESLintWithInMemoryFileSystem({ cwd, files })`
+ *
+ * Those functions define correspond classes with the in-memory file system.
+ * Those search config files, parsers, and plugins in the `files` option via the
+ * in-memory file system.
+ *
+ * For each test case, it makes more readable if we define minimal files the
+ * test case requires.
+ *
+ * For example:
+ *
+ * ```js
+ * const { ConfigArrayFactory } = defineConfigArrayFactoryWithInMemoryFileSystem({
+ *     files: {
+ *         "node_modules/eslint-config-foo/index.js": `
+ *             module.exports = {
+ *                 parser: "./parser",
+ *                 rules: {
+ *                     "no-undef": "error"
+ *                 }
+ *             }
+ *         `,
+ *         "node_modules/eslint-config-foo/parser.js": `
+ *             module.exports = {
+ *                 parse() {}
+ *             }
+ *         `,
+ *         ".eslintrc.json": JSON.stringify({ root: true, extends: "foo" })
+ *     }
+ * });
+ * const factory = new ConfigArrayFactory();
+ * const config = factory.loadFile(".eslintrc.json");
+ *
+ * assert(config[0].name === ".eslintrc.json » eslint-config-foo");
+ * assert(config[0].filePath === path.resolve("node_modules/eslint-config-foo/index.js"));
+ * assert(config[0].parser.filePath === path.resolve("node_modules/eslint-config-foo/parser.js"));
+ *
+ * assert(config[1].name === ".eslintrc.json");
+ * assert(config[1].filePath === path.resolve(".eslintrc.json"));
+ * assert(config[1].root === true);
+ * ```
+ *
+ * @author Toru Nagashima <https://github.com/mysticatea>
+ */
+"use strict";
+
+const path = require("path");
+const vm = require("vm");
+const { Volume, createFsFromVolume } = require("memfs");
+const Proxyquire = require("proxyquire/lib/proxyquire");
+
+const CascadingConfigArrayFactoryPath =
+    require.resolve("../../lib/cli-engine/cascading-config-array-factory");
+const CLIEnginePath =
+    require.resolve("../../lib/cli-engine/cli-engine");
+const ConfigArrayFactoryPath =
+    require.resolve("../../lib/cli-engine/config-array-factory");
+const FileEnumeratorPath =
+    require.resolve("../../lib/cli-engine/file-enumerator");
+const LoadRulesPath =
+    require.resolve("../../lib/cli-engine/load-rules");
+const ESLintPath =
+    require.resolve("../../lib/eslint/eslint");
+const ESLintAllPath =
+    require.resolve("../../conf/eslint-all");
+const ESLintRecommendedPath =
+    require.resolve("../../conf/eslint-recommended");
+
+// Ensure the needed files has been loaded and cached.
+require(CascadingConfigArrayFactoryPath);
+require(CLIEnginePath);
+require(ConfigArrayFactoryPath);
+require(FileEnumeratorPath);
+require(LoadRulesPath);
+require(ESLintPath);
+require("js-yaml");
+require("espree");
+
+// Override `_require` in order to throw runtime errors in stubs.
+const ERRORED = Symbol("errored");
+const proxyquire = new class extends Proxyquire {
+    _require(...args) {
+        const retv = super._require(...args); // eslint-disable-line no-underscore-dangle
+
+        if (retv[ERRORED]) {
+            throw retv[ERRORED];
+        }
+        return retv;
+    }
+}(module).noCallThru().noPreserveCache();
+
+// Separated (sandbox) context to compile fixture files.
+const context = vm.createContext();
+
+/**
+ * Check if a given path is an existing file.
+ * @param {import("fs")} fs The file system.
+ * @param {string} filePath Tha path to a file to check.
+ * @returns {boolean} `true` if the file existed.
+ */
+function isExistingFile(fs, filePath) {
+    try {
+        return fs.statSync(filePath).isFile();
+    } catch (error) {
+        return false;
+    }
+}
+
+/**
+ * Get some paths to test.
+ * @param {string} prefix The prefix to try.
+ * @returns {string[]} The paths to test.
+ */
+function getTestPaths(prefix) {
+    return [
+        path.join(prefix),
+        path.join(`${prefix}.js`),
+        path.join(prefix, "index.js")
+    ];
+}
+
+/**
+ * Iterate the candidate paths of a given request to resolve.
+ * @param {string} request Tha package name or file path to resolve.
+ * @param {string} relativeTo Tha path to the file what called this resolving.
+ * @returns {IterableIterator<string>} The candidate paths.
+ */
+function *iterateCandidatePaths(request, relativeTo) {
+    if (path.isAbsolute(request)) {
+        yield* getTestPaths(request);
+        return;
+    }
+    if (/^\.{1,2}[/\\]/u.test(request)) {
+        yield* getTestPaths(path.resolve(path.dirname(relativeTo), request));
+        return;
+    }
+
+    let prevPath = path.resolve(relativeTo);
+    let dirPath = path.dirname(prevPath);
+
+    while (dirPath && dirPath !== prevPath) {
+        yield* getTestPaths(path.join(dirPath, "node_modules", request));
+        prevPath = dirPath;
+        dirPath = path.dirname(dirPath);
+    }
+}
+
+/**
+ * Resolve a given module name or file path relatively in the given file system.
+ * @param {import("fs")} fs The file system.
+ * @param {string} request Tha package name or file path to resolve.
+ * @param {string} relativeTo Tha path to the file what called this resolving.
+ * @returns {void}
+ */
+function fsResolve(fs, request, relativeTo) {
+    for (const filePath of iterateCandidatePaths(request, relativeTo)) {
+        if (isExistingFile(fs, filePath)) {
+            return filePath;
+        }
+    }
+
+    throw Object.assign(
+        new Error(`Cannot find module '${request}'`),
+        { code: "MODULE_NOT_FOUND" }
+    );
+}
+
+/**
+ * Compile a JavaScript file.
+ * This is used to compile only fixture files, so this is minimam.
+ * @param {import("fs")} fs The file system.
+ * @param {Object} stubs The stubs.
+ * @param {string} filePath The path to a JavaScript file to compile.
+ * @param {string} content The source code to compile.
+ * @returns {any} The exported value.
+ */
+function compile(fs, stubs, filePath, content) {
+    const code = `(function(exports, require, module, __filename, __dirname) { ${content} })`;
+    const f = vm.runInContext(code, context);
+    const exports = {};
+    const module = { exports };
+
+    f.call(
+        exports,
+        exports,
+        request => {
+            const modulePath = fsResolve(fs, request, filePath);
+            const stub = stubs[modulePath];
+
+            if (stub[ERRORED]) {
+                throw stub[ERRORED];
+            }
+            return stub;
+        },
+        module,
+        filePath,
+        path.dirname(filePath)
+    );
+
+    return module.exports;
+}
+
+/**
+ * Import a given file path in the given file system.
+ * @param {import("fs")} fs The file system.
+ * @param {Object} stubs The stubs.
+ * @param {string} absolutePath Tha file path to import.
+ * @returns {void}
+ */
+function fsImportFresh(fs, stubs, absolutePath) {
+    if (absolutePath === ESLintAllPath) {
+        return require(ESLintAllPath);
+    }
+    if (absolutePath === ESLintRecommendedPath) {
+        return require(ESLintRecommendedPath);
+    }
+
+    if (fs.existsSync(absolutePath)) {
+        return compile(
+            fs,
+            stubs,
+            absolutePath,
+            fs.readFileSync(absolutePath, "utf8")
+        );
+    }
+
+    throw Object.assign(
+        new Error(`Cannot find module '${absolutePath}'`),
+        { code: "MODULE_NOT_FOUND" }
+    );
+}
+
+/**
+ * Define in-memory file system.
+ * @param {Object} options The options.
+ * @param {() => string} [options.cwd] The current working directory.
+ * @param {Object} [options.files] The initial files definition in the in-memory file system.
+ * @returns {import("fs")} The stubbed `ConfigArrayFactory` class.
+ */
+function defineInMemoryFs({
+    cwd = process.cwd,
+    files = {}
+} = {}) {
+
+    /**
+     * The in-memory file system for this mock.
+     * @type {import("fs")}
+     */
+    const fs = createFsFromVolume(new Volume());
+
+    fs.mkdirSync(cwd(), { recursive: true });
+
+    /*
+     * Write all files to the in-memory file system and compile all JavaScript
+     * files then set to `stubs`.
+     */
+    (function initFiles(directoryPath, definition) {
+        for (const [filename, content] of Object.entries(definition)) {
+            const filePath = path.resolve(directoryPath, filename);
+            const parentPath = path.dirname(filePath);
+
+            if (typeof content === "object") {
+                initFiles(filePath, content);
+            } else if (typeof content === "string") {
+                if (!fs.existsSync(parentPath)) {
+                    fs.mkdirSync(parentPath, { recursive: true });
+                }
+                fs.writeFileSync(filePath, content);
+            } else {
+                throw new Error(`Invalid content: ${typeof content}`);
+            }
+        }
+    }(cwd(), files));
+
+    return fs;
+}
+
+/**
+ * Define stubbed `ConfigArrayFactory` class what uses the in-memory file system.
+ * @param {Object} options The options.
+ * @param {() => string} [options.cwd] The current working directory.
+ * @param {Object} [options.files] The initial files definition in the in-memory file system.
+ * @returns {{ fs: import("fs"), RelativeModuleResolver: import("../../lib/shared/relative-module-resolver"), ConfigArrayFactory: import("../../lib/cli-engine/config-array-factory")["ConfigArrayFactory"] }} The stubbed `ConfigArrayFactory` class.
+ */
+function defineConfigArrayFactoryWithInMemoryFileSystem({
+    cwd = process.cwd,
+    files = {}
+} = {}) {
+    const fs = defineInMemoryFs({ cwd, files });
+    const RelativeModuleResolver = { resolve: fsResolve.bind(null, fs) };
+
+    /*
+     * Stubs for proxyquire.
+     * This contains the JavaScript files in `options.files`.
+     */
+    const stubs = {};
+
+    stubs.fs = fs;
+    stubs["import-fresh"] = fsImportFresh.bind(null, fs, stubs);
+    stubs["../shared/relative-module-resolver"] = RelativeModuleResolver;
+
+    /*
+     * Write all files to the in-memory file system and compile all JavaScript
+     * files then set to `stubs`.
+     */
+    (function initFiles(directoryPath, definition) {
+        for (const [filename, content] of Object.entries(definition)) {
+            const filePath = path.resolve(directoryPath, filename);
+
+            if (typeof content === "object") {
+                initFiles(filePath, content);
+                continue;
+            }
+
+            /*
+             * Compile then stub if this file is a JavaScript file.
+             * For parsers and plugins that `require()` will import.
+             */
+            if (path.extname(filePath) === ".js") {
+                Object.defineProperty(stubs, filePath, {
+                    configurable: true,
+                    enumerable: true,
+                    get() {
+                        let stub;
+
+                        try {
+                            stub = compile(fs, stubs, filePath, content);
+                        } catch (error) {
+                            stub = { [ERRORED]: error };
+                        }
+                        Object.defineProperty(stubs, filePath, {
+                            configurable: true,
+                            enumerable: true,
+                            value: stub
+                        });
+
+                        return stub;
+                    }
+                });
+            }
+        }
+    }(cwd(), files));
+
+    // Load the stubbed one.
+    const { ConfigArrayFactory } = proxyquire(ConfigArrayFactoryPath, stubs);
+
+    // Override the default cwd.
+    return {
+        fs,
+        stubs,
+        RelativeModuleResolver,
+        ConfigArrayFactory: cwd === process.cwd
+            ? ConfigArrayFactory
+            : class extends ConfigArrayFactory {
+                constructor(options) {
+                    super({ cwd: cwd(), ...options });
+                }
+            }
+    };
+}
+
+/**
+ * Define stubbed `CascadingConfigArrayFactory` class what uses the in-memory file system.
+ * @param {Object} options The options.
+ * @param {() => string} [options.cwd] The current working directory.
+ * @param {Object} [options.files] The initial files definition in the in-memory file system.
+ * @returns {{ fs: import("fs"), RelativeModuleResolver: import("../../../lib/shared/relative-module-resolver"), ConfigArrayFactory: import("../../../lib/cli-engine/config-array-factory")["ConfigArrayFactory"], CascadingConfigArrayFactory: import("../../../lib/cli-engine/cascading-config-array-factory")["CascadingConfigArrayFactory"] }} The stubbed `CascadingConfigArrayFactory` class.
+ */
+function defineCascadingConfigArrayFactoryWithInMemoryFileSystem({
+    cwd = process.cwd,
+    files = {}
+} = {}) {
+    const { fs, stubs, RelativeModuleResolver, ConfigArrayFactory } =
+           defineConfigArrayFactoryWithInMemoryFileSystem({ cwd, files });
+    const loadRules = proxyquire(LoadRulesPath, stubs);
+    const { CascadingConfigArrayFactory } =
+        proxyquire(CascadingConfigArrayFactoryPath, {
+            "./config-array-factory": { ConfigArrayFactory },
+            "./load-rules": loadRules
+        });
+
+    // Override the default cwd.
+    return {
+        fs,
+        RelativeModuleResolver,
+        ConfigArrayFactory,
+        CascadingConfigArrayFactory: cwd === process.cwd
+            ? CascadingConfigArrayFactory
+            : class extends CascadingConfigArrayFactory {
+                constructor(options) {
+                    super({ cwd: cwd(), ...options });
+                }
+            }
+    };
+}
+
+/**
+ * Define stubbed `FileEnumerator` class what uses the in-memory file system.
+ * @param {Object} options The options.
+ * @param {() => string} [options.cwd] The current working directory.
+ * @param {Object} [options.files] The initial files definition in the in-memory file system.
+ * @returns {{ fs: import("fs"), RelativeModuleResolver: import("../../../lib/shared/relative-module-resolver"), ConfigArrayFactory: import("../../../lib/cli-engine/config-array-factory")["ConfigArrayFactory"], CascadingConfigArrayFactory: import("../../../lib/cli-engine/cascading-config-array-factory")["CascadingConfigArrayFactory"], FileEnumerator: import("../../../lib/cli-engine/file-enumerator")["FileEnumerator"] }} The stubbed `FileEnumerator` class.
+ */
+function defineFileEnumeratorWithInMemoryFileSystem({
+    cwd = process.cwd,
+    files = {}
+} = {}) {
+    const {
+        fs,
+        RelativeModuleResolver,
+        ConfigArrayFactory,
+        CascadingConfigArrayFactory
+    } =
+        defineCascadingConfigArrayFactoryWithInMemoryFileSystem({ cwd, files });
+    const { FileEnumerator } = proxyquire(FileEnumeratorPath, {
+        fs,
+        "./cascading-config-array-factory": { CascadingConfigArrayFactory }
+    });
+
+    // Override the default cwd.
+    return {
+        fs,
+        RelativeModuleResolver,
+        ConfigArrayFactory,
+        CascadingConfigArrayFactory,
+        FileEnumerator: cwd === process.cwd
+            ? FileEnumerator
+            : class extends FileEnumerator {
+                constructor(options) {
+                    super({ cwd: cwd(), ...options });
+                }
+            }
+    };
+}
+
+/**
+ * Define stubbed `CLIEngine` class what uses the in-memory file system.
+ * @param {Object} options The options.
+ * @param {() => string} [options.cwd] The current working directory.
+ * @param {Object} [options.files] The initial files definition in the in-memory file system.
+ * @returns {{ fs: import("fs"), RelativeModuleResolver: import("../../../lib/shared/relative-module-resolver"), ConfigArrayFactory: import("../../../lib/cli-engine/config-array-factory")["ConfigArrayFactory"], CascadingConfigArrayFactory: import("../../../lib/cli-engine/cascading-config-array-factory")["CascadingConfigArrayFactory"], FileEnumerator: import("../../../lib/cli-engine/file-enumerator")["FileEnumerator"], CLIEngine: import("../../../lib/cli-engine/cli-engine")["CLIEngine"], getCLIEngineInternalSlots: import("../../../lib/cli-engine/cli-engine")["getCLIEngineInternalSlots"] }} The stubbed `CLIEngine` class.
+ */
+function defineCLIEngineWithInMemoryFileSystem({
+    cwd = process.cwd,
+    files = {}
+} = {}) {
+    const {
+        fs,
+        RelativeModuleResolver,
+        ConfigArrayFactory,
+        CascadingConfigArrayFactory,
+        FileEnumerator
+    } =
+        defineFileEnumeratorWithInMemoryFileSystem({ cwd, files });
+    const { CLIEngine, getCLIEngineInternalSlots } = proxyquire(CLIEnginePath, {
+        fs,
+        "./cascading-config-array-factory": { CascadingConfigArrayFactory },
+        "./file-enumerator": { FileEnumerator },
+        "../shared/relative-module-resolver": RelativeModuleResolver
+    });
+
+    // Override the default cwd.
+    return {
+        fs,
+        RelativeModuleResolver,
+        ConfigArrayFactory,
+        CascadingConfigArrayFactory,
+        FileEnumerator,
+        CLIEngine: cwd === process.cwd
+            ? CLIEngine
+            : class extends CLIEngine {
+                constructor(options) {
+                    super({ cwd: cwd(), ...options });
+                }
+            },
+        getCLIEngineInternalSlots
+    };
+}
+
+/**
+ * Define stubbed `ESLint` class that uses the in-memory file system.
+ * @param {Object} options The options.
+ * @param {() => string} [options.cwd] The current working directory.
+ * @param {Object} [options.files] The initial files definition in the in-memory file system.
+ * @returns {{ fs: import("fs"), RelativeModuleResolver: import("../../lib/shared/relative-module-resolver"), ConfigArrayFactory: import("../../lib/cli-engine/config-array-factory")["ConfigArrayFactory"], CascadingConfigArrayFactory: import("../../lib/cli-engine/cascading-config-array-factory")["CascadingConfigArrayFactory"], FileEnumerator: import("../../lib/cli-engine/file-enumerator")["FileEnumerator"], ESLint: import("../../lib/eslint/eslint")["ESLint"], getCLIEngineInternalSlots: import("../../lib//eslint/eslint")["getESLintInternalSlots"] }} The stubbed `ESLint` class.
+ */
+function defineESLintWithInMemoryFileSystem({
+    cwd = process.cwd,
+    files = {}
+} = {}) {
+    const {
+        fs,
+        RelativeModuleResolver,
+        ConfigArrayFactory,
+        CascadingConfigArrayFactory,
+        FileEnumerator,
+        CLIEngine,
+        getCLIEngineInternalSlots
+    } = defineCLIEngineWithInMemoryFileSystem({ cwd, files });
+    const { ESLint, getESLintPrivateMembers } = proxyquire(ESLintPath, {
+        "../cli-engine/cli-engine": { CLIEngine, getCLIEngineInternalSlots }
+    });
+
+    // Override the default cwd.
+    return {
+        fs,
+        RelativeModuleResolver,
+        ConfigArrayFactory,
+        CascadingConfigArrayFactory,
+        FileEnumerator,
+        CLIEngine,
+        getCLIEngineInternalSlots,
+        ESLint: cwd === process.cwd
+            ? ESLint
+            : class extends ESLint {
+                constructor(options) {
+                    super({ cwd: cwd(), ...options });
+                }
+            },
+        getESLintPrivateMembers
+    };
+}
+
+module.exports = {
+    defineInMemoryFs,
+    defineConfigArrayFactoryWithInMemoryFileSystem,
+    defineCascadingConfigArrayFactoryWithInMemoryFileSystem,
+    defineFileEnumeratorWithInMemoryFileSystem,
+    defineCLIEngineWithInMemoryFileSystem,
+    defineESLintWithInMemoryFileSystem
+};
diff --git a/eslint/tests/_utils/index.js b/eslint/tests/_utils/index.js
new file mode 100644 (file)
index 0000000..0431e3a
--- /dev/null
@@ -0,0 +1,39 @@
+"use strict";
+
+const {
+    defineInMemoryFs,
+    defineConfigArrayFactoryWithInMemoryFileSystem,
+    defineCascadingConfigArrayFactoryWithInMemoryFileSystem,
+    defineFileEnumeratorWithInMemoryFileSystem,
+    defineCLIEngineWithInMemoryFileSystem,
+    defineESLintWithInMemoryFileSystem
+} = require("./in-memory-fs");
+
+
+/**
+ * Prevents leading spaces in a multiline template literal from appearing in the resulting string
+ * @param {string[]} strings The strings in the template literal
+ * @param {any[]} values The interpolation values in the template literal.
+ * @returns {string} The template literal, with spaces removed from all lines
+ */
+function unIndent(strings, ...values) {
+    const text = strings
+        .map((s, i) => (i === 0 ? s : values[i - 1] + s))
+        .join("");
+    const lines = text.replace(/^\n/u, "").replace(/\n\s*$/u, "").split("\n");
+    const lineIndents = lines.filter(line => line.trim()).map(line => line.match(/ */u)[0].length);
+    const minLineIndent = Math.min(...lineIndents);
+
+    return lines.map(line => line.slice(minLineIndent)).join("\n");
+}
+
+
+module.exports = {
+    unIndent,
+    defineInMemoryFs,
+    defineConfigArrayFactoryWithInMemoryFileSystem,
+    defineCascadingConfigArrayFactoryWithInMemoryFileSystem,
+    defineFileEnumeratorWithInMemoryFileSystem,
+    defineCLIEngineWithInMemoryFileSystem,
+    defineESLintWithInMemoryFileSystem
+};
index 24ba7271c9f87dd2a6659ecb685d78c48979ca1f..c94e88568d4f35c766ef2b4f503b46eebfad7c7e 100644 (file)
@@ -52779,7 +52779,7 @@ var state    = require("./state.js").state;
 var style    = require("./style.js");
 
 // We need this module here because environments such as IE and Rhino
-// don't necessarilly expose the 'console' API and browserify uses
+// don't necessarily expose the 'console' API and browserify uses
 // it to log things. It's a sad state of affair, really.
 var console = require("console-browserify");
 
@@ -52838,7 +52838,7 @@ var JSHINT = (function () {
       immed       : true, // if immediate invocations must be wrapped in parens
       iterator    : true, // if the `__iterator__` property should be allowed
       jquery      : true, // if jQuery globals should be predefined
-      lastsemic   : true, // if semicolons may be ommitted for the trailing
+      lastsemic   : true, // if semicolons may be omitted for the trailing
                           // statements inside of a one-line blocks.
       laxbreak    : true, // if line breaks should not be checked
       laxcomma    : true, // if line breaks should not be checked around commas
@@ -59115,7 +59115,7 @@ Lexer.prototype = {
   },
 
   /*
-   * Scan for any occurence of mixed tabs and spaces. If smarttabs option
+   * Scan for any occurrence of mixed tabs and spaces. If smarttabs option
    * is on, ignore tabs followed by spaces.
    *
    * Tabs followed by one space followed by a block comment are allowed.
@@ -59135,7 +59135,7 @@ Lexer.prototype = {
   },
 
   /*
-   * Scan for any occurence of non-breaking spaces. Non-breaking spaces
+   * Scan for any occurrence of non-breaking spaces. Non-breaking spaces
    * can be mistakenly typed on OS X with option-space. Non UTF-8 web
    * pages with non-breaking pages produce syntax errors.
    */
@@ -59288,7 +59288,7 @@ Lexer.prototype = {
 
   /*
    * Produce the next token. This function is called by advance() to get
-   * the next token. It retuns a token in a JSLint-compatible format.
+   * the next token. It returns a token in a JSLint-compatible format.
    */
   token: function () {
     /*jshint loopfunc:true */
index b61cf5c4c780ff951d5a72cf00665a983543bb6f..d2cdf354652fe1327c945ae3d37d50fafb76202f 100644 (file)
@@ -1596,7 +1596,7 @@ ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an al
 ko.exportSymbol('isComputed', ko.isComputed);
 
 (function() {
-    var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
+    var maxNestedObservableDepth = 10; // Escape the (unlikely) pathological case where an observable's current value is itself (or similar reference cycle)
 
     ko.toJS = function(rootObject) {
         if (arguments.length == 0)
index 8b771dc5bf541ac46f503412314d4f2d19930453..cfc5128dc5725a728d0e75854449bc3629d7208b 100644 (file)
@@ -8,7 +8,9 @@
 const childProcess = require("child_process");
 const fs = require("fs");
 const assert = require("chai").assert;
-const EXECUTABLE_PATH = require("path").resolve(`${__dirname}/../../bin/eslint.js`);
+const path = require("path");
+
+const EXECUTABLE_PATH = path.resolve(path.join(__dirname, "../../bin/eslint.js"));
 
 /**
  * Returns a Promise for when a child process exits
@@ -90,7 +92,8 @@ describe("bin/eslint.js", () => {
                     warningCount: 0,
                     fixableErrorCount: 0,
                     fixableWarningCount: 0,
-                    output: "var foo = bar;\n"
+                    output: "var foo = bar;\n",
+                    usedDeprecatedRules: []
                 }
             ]);
 
@@ -166,7 +169,7 @@ describe("bin/eslint.js", () => {
 
         it("successfully handles more than 4k data via stdin", () => {
             const child = runESLint(["--stdin", "--no-eslintrc"]);
-            const large = fs.createReadStream(`${__dirname}/../bench/large.js`, "utf8");
+            const large = fs.createReadStream(path.join(__dirname, "../bench/large.js"), "utf8");
 
             large.pipe(child.stdin);
 
@@ -176,13 +179,13 @@ describe("bin/eslint.js", () => {
 
     describe("running on files", () => {
         it("has exit code 0 if no linting errors occur", () => assertExitCode(runESLint(["bin/eslint.js"]), 0));
-        it("has exit code 0 if a linting warning is reported", () => assertExitCode(runESLint(["bin/eslint.js", "--env", "es6", "--no-eslintrc", "--rule", "semi: [1, never]"]), 0));
-        it("has exit code 1 if a linting error is reported", () => assertExitCode(runESLint(["bin/eslint.js", "--env", "es6", "--no-eslintrc", "--rule", "semi: [2, never]"]), 1));
+        it("has exit code 0 if a linting warning is reported", () => assertExitCode(runESLint(["bin/eslint.js", "--env", "es2020", "--no-eslintrc", "--rule", "semi: [1, never]"]), 0));
+        it("has exit code 1 if a linting error is reported", () => assertExitCode(runESLint(["bin/eslint.js", "--env", "es2020", "--no-eslintrc", "--rule", "semi: [2, never]"]), 1));
         it("has exit code 1 if a syntax error is thrown", () => assertExitCode(runESLint(["README.md"]), 1));
     });
 
     describe("automatically fixing files", () => {
-        const fixturesPath = `${__dirname}/../fixtures/autofix-integration`;
+        const fixturesPath = path.join(__dirname, "../fixtures/autofix-integration");
         const tempFilePath = `${fixturesPath}/temp.js`;
         const startingText = fs.readFileSync(`${fixturesPath}/left-pad.js`).toString();
         const expectedFixedText = fs.readFileSync(`${fixturesPath}/left-pad-expected.js`).toString();
@@ -359,7 +362,7 @@ describe("bin/eslint.js", () => {
         });
 
         it("prints the error message pointing to line of code", () => {
-            const invalidConfig = `${__dirname}/../fixtures/bin/.eslintrc.yml`;
+            const invalidConfig = path.join(__dirname, "../fixtures/bin/.eslintrc.yml");
             const child = runESLint(["--no-ignore", invalidConfig]);
             const exitCodeAssertion = assertExitCode(child, 2);
             const outputAssertion = getOutput(child).then(output => {
index b6e3019aa01011f176ceb2f08a327676fb60dd77..dc4cb7223ec6069dc08342fc181b9d1b651b0fb3 100644 (file)
@@ -1,5 +1,5 @@
 /* eslint semi: "error" */
-/* eslint no-program: "error" */
+/* eslint test/no-program: "error" */
 /* eslint prefer-arrow-callback: "error" */
 "use strict";
 
index ee9b9d9d8697fc4dd0294a026db2c171ce17b2a1..4e43de09dc6664c6119eda7ae98e51e8488117c5 100644 (file)
@@ -1,5 +1,5 @@
 /* eslint semi: "error" */
-/* eslint no-program: "error" */
+/* eslint test/no-program: "error" */
 /* eslint prefer-arrow-callback: "error" */
 "use strict";
 
diff --git a/eslint/tests/lib/_utils.js b/eslint/tests/lib/_utils.js
deleted file mode 100644 (file)
index 76e973c..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * @fileoverview utils for rule tests.
- * @author 唯然<weiran.zsd@outlook.com>
- */
-
-"use strict";
-
-const path = require("path");
-const { Volume, createFsFromVolume } = require("memfs");
-
-/**
- * Prevents leading spaces in a multiline template literal from appearing in the resulting string
- * @param {string[]} strings The strings in the template literal
- * @param {any[]} values The interpolation values in the template literal.
- * @returns {string} The template literal, with spaces removed from all lines
- */
-function unIndent(strings, ...values) {
-    const text = strings
-        .map((s, i) => (i === 0 ? s : values[i - 1] + s))
-        .join("");
-    const lines = text.replace(/^\n/u, "").replace(/\n\s*$/u, "").split("\n");
-    const lineIndents = lines.filter(line => line.trim()).map(line => line.match(/ */u)[0].length);
-    const minLineIndent = Math.min(...lineIndents);
-
-    return lines.map(line => line.slice(minLineIndent)).join("\n");
-}
-
-/**
- * Define in-memory file system.
- * @param {Object} options The options.
- * @param {() => string} [options.cwd] The current working directory.
- * @param {Object} [options.files] The initial files definition in the in-memory file system.
- * @returns {import("fs")} The stubbed `ConfigArrayFactory` class.
- */
-function defineInMemoryFs({
-    cwd = process.cwd,
-    files = {}
-} = {}) {
-
-    /**
-     * The in-memory file system for this mock.
-     * @type {import("fs")}
-     */
-    const fs = createFsFromVolume(new Volume());
-
-    fs.mkdirSync(cwd(), { recursive: true });
-
-    /*
-     * Write all files to the in-memory file system and compile all JavaScript
-     * files then set to `stubs`.
-     */
-    (function initFiles(directoryPath, definition) {
-        for (const [filename, content] of Object.entries(definition)) {
-            const filePath = path.resolve(directoryPath, filename);
-            const parentPath = path.dirname(filePath);
-
-            if (typeof content === "object") {
-                initFiles(filePath, content);
-            } else if (typeof content === "string") {
-                if (!fs.existsSync(parentPath)) {
-                    fs.mkdirSync(parentPath, { recursive: true });
-                }
-                fs.writeFileSync(filePath, content);
-            } else {
-                throw new Error(`Invalid content: ${typeof content}`);
-            }
-        }
-    }(cwd(), files));
-
-    return fs;
-}
-
-module.exports = {
-    defineInMemoryFs,
-    unIndent
-};
diff --git a/eslint/tests/lib/cli-engine/_utils.js b/eslint/tests/lib/cli-engine/_utils.js
deleted file mode 100644 (file)
index 1d1bcd2..0000000
+++ /dev/null
@@ -1,446 +0,0 @@
-/**
- * @fileoverview Define classes what use the in-memory file system.
- *
- * This provides utilities to test `ConfigArrayFactory`,
- * `CascadingConfigArrayFactory`, `FileEnumerator`, and `CLIEngine`.
- *
- * - `defineConfigArrayFactoryWithInMemoryFileSystem({ cwd, files })`
- * - `defineCascadingConfigArrayFactoryWithInMemoryFileSystem({ cwd, files })`
- * - `defineFileEnumeratorWithInMemoryFileSystem({ cwd, files })`
- * - `defineCLIEngineWithInMemoryFileSystem({ cwd, files })`
- *
- * Those functions define correspond classes with the in-memory file system.
- * Those search config files, parsers, and plugins in the `files` option via the
- * in-memory file system.
- *
- * For each test case, it makes more readable if we define minimal files the
- * test case requires.
- *
- * For example:
- *
- * ```js
- * const { ConfigArrayFactory } = defineConfigArrayFactoryWithInMemoryFileSystem({
- *     files: {
- *         "node_modules/eslint-config-foo/index.js": `
- *             module.exports = {
- *                 parser: "./parser",
- *                 rules: {
- *                     "no-undef": "error"
- *                 }
- *             }
- *         `,
- *         "node_modules/eslint-config-foo/parser.js": `
- *             module.exports = {
- *                 parse() {}
- *             }
- *         `,
- *         ".eslintrc.json": JSON.stringify({ root: true, extends: "foo" })
- *     }
- * });
- * const factory = new ConfigArrayFactory();
- * const config = factory.loadFile(".eslintrc.json");
- *
- * assert(config[0].name === ".eslintrc.json » eslint-config-foo");
- * assert(config[0].filePath === path.resolve("node_modules/eslint-config-foo/index.js"));
- * assert(config[0].parser.filePath === path.resolve("node_modules/eslint-config-foo/parser.js"));
- *
- * assert(config[1].name === ".eslintrc.json");
- * assert(config[1].filePath === path.resolve(".eslintrc.json"));
- * assert(config[1].root === true);
- * ```
- *
- * @author Toru Nagashima <https://github.com/mysticatea>
- */
-"use strict";
-
-const path = require("path");
-const vm = require("vm");
-const Proxyquire = require("proxyquire/lib/proxyquire");
-const { defineInMemoryFs } = require("../_utils");
-
-const CascadingConfigArrayFactoryPath =
-    require.resolve("../../../lib/cli-engine/cascading-config-array-factory");
-const CLIEnginePath =
-    require.resolve("../../../lib/cli-engine/cli-engine");
-const ConfigArrayFactoryPath =
-    require.resolve("../../../lib/cli-engine/config-array-factory");
-const FileEnumeratorPath =
-    require.resolve("../../../lib/cli-engine/file-enumerator");
-const LoadRulesPath =
-    require.resolve("../../../lib/cli-engine/load-rules");
-const ESLintAllPath =
-    require.resolve("../../../conf/eslint-all");
-const ESLintRecommendedPath =
-    require.resolve("../../../conf/eslint-recommended");
-
-// Ensure the needed files has been loaded and cached.
-require(CascadingConfigArrayFactoryPath);
-require(CLIEnginePath);
-require(ConfigArrayFactoryPath);
-require(FileEnumeratorPath);
-require(LoadRulesPath);
-require("js-yaml");
-require("espree");
-
-// Override `_require` in order to throw runtime errors in stubs.
-const ERRORED = Symbol("errored");
-const proxyquire = new class extends Proxyquire {
-    _require(...args) {
-        const retv = super._require(...args); // eslint-disable-line no-underscore-dangle
-
-        if (retv[ERRORED]) {
-            throw retv[ERRORED];
-        }
-        return retv;
-    }
-}(module).noCallThru().noPreserveCache();
-
-// Separated (sandbox) context to compile fixture files.
-const context = vm.createContext();
-
-/**
- * Check if a given path is an existing file.
- * @param {import("fs")} fs The file system.
- * @param {string} filePath Tha path to a file to check.
- * @returns {boolean} `true` if the file existed.
- */
-function isExistingFile(fs, filePath) {
-    try {
-        return fs.statSync(filePath).isFile();
-    } catch (error) {
-        return false;
-    }
-}
-
-/**
- * Get some paths to test.
- * @param {string} prefix The prefix to try.
- * @returns {string[]} The paths to test.
- */
-function getTestPaths(prefix) {
-    return [
-        path.join(prefix),
-        path.join(`${prefix}.js`),
-        path.join(prefix, "index.js")
-    ];
-}
-
-/**
- * Iterate the candidate paths of a given request to resolve.
- * @param {string} request Tha package name or file path to resolve.
- * @param {string} relativeTo Tha path to the file what called this resolving.
- * @returns {IterableIterator<string>} The candidate paths.
- */
-function *iterateCandidatePaths(request, relativeTo) {
-    if (path.isAbsolute(request)) {
-        yield* getTestPaths(request);
-        return;
-    }
-    if (/^\.{1,2}[/\\]/u.test(request)) {
-        yield* getTestPaths(path.resolve(path.dirname(relativeTo), request));
-        return;
-    }
-
-    let prevPath = path.resolve(relativeTo);
-    let dirPath = path.dirname(prevPath);
-
-    while (dirPath && dirPath !== prevPath) {
-        yield* getTestPaths(path.join(dirPath, "node_modules", request));
-        prevPath = dirPath;
-        dirPath = path.dirname(dirPath);
-    }
-}
-
-/**
- * Resolve a given module name or file path relatively in the given file system.
- * @param {import("fs")} fs The file system.
- * @param {string} request Tha package name or file path to resolve.
- * @param {string} relativeTo Tha path to the file what called this resolving.
- * @returns {void}
- */
-function fsResolve(fs, request, relativeTo) {
-    for (const filePath of iterateCandidatePaths(request, relativeTo)) {
-        if (isExistingFile(fs, filePath)) {
-            return filePath;
-        }
-    }
-
-    throw Object.assign(
-        new Error(`Cannot find module '${request}'`),
-        { code: "MODULE_NOT_FOUND" }
-    );
-}
-
-/**
- * Compile a JavaScript file.
- * This is used to compile only fixture files, so this is minimam.
- * @param {import("fs")} fs The file system.
- * @param {Object} stubs The stubs.
- * @param {string} filePath The path to a JavaScript file to compile.
- * @param {string} content The source code to compile.
- * @returns {any} The exported value.
- */
-function compile(fs, stubs, filePath, content) {
-    const code = `(function(exports, require, module, __filename, __dirname) { ${content} })`;
-    const f = vm.runInContext(code, context);
-    const exports = {};
-    const module = { exports };
-
-    f.call(
-        exports,
-        exports,
-        request => {
-            const modulePath = fsResolve(fs, request, filePath);
-            const stub = stubs[modulePath];
-
-            if (stub[ERRORED]) {
-                throw stub[ERRORED];
-            }
-            return stub;
-        },
-        module,
-        filePath,
-        path.dirname(filePath)
-    );
-
-    return module.exports;
-}
-
-/**
- * Import a given file path in the given file system.
- * @param {import("fs")} fs The file system.
- * @param {Object} stubs The stubs.
- * @param {string} absolutePath Tha file path to import.
- * @returns {void}
- */
-function fsImportFresh(fs, stubs, absolutePath) {
-    if (absolutePath === ESLintAllPath) {
-        return require(ESLintAllPath);
-    }
-    if (absolutePath === ESLintRecommendedPath) {
-        return require(ESLintRecommendedPath);
-    }
-
-    if (fs.existsSync(absolutePath)) {
-        return compile(
-            fs,
-            stubs,
-            absolutePath,
-            fs.readFileSync(absolutePath, "utf8")
-        );
-    }
-
-    throw Object.assign(
-        new Error(`Cannot find module '${absolutePath}'`),
-        { code: "MODULE_NOT_FOUND" }
-    );
-}
-
-/**
- * Define stubbed `ConfigArrayFactory` class what uses the in-memory file system.
- * @param {Object} options The options.
- * @param {() => string} [options.cwd] The current working directory.
- * @param {Object} [options.files] The initial files definition in the in-memory file system.
- * @returns {{ fs: import("fs"), RelativeModuleResolver: import("../../../lib/shared/relative-module-resolver"), ConfigArrayFactory: import("../../../lib/cli-engine/config-array-factory")["ConfigArrayFactory"] }} The stubbed `ConfigArrayFactory` class.
- */
-function defineConfigArrayFactoryWithInMemoryFileSystem({
-    cwd = process.cwd,
-    files = {}
-} = {}) {
-    const fs = defineInMemoryFs({ cwd, files });
-    const RelativeModuleResolver = { resolve: fsResolve.bind(null, fs) };
-
-    /*
-     * Stubs for proxyquire.
-     * This contains the JavaScript files in `options.files`.
-     */
-    const stubs = {};
-
-    stubs.fs = fs;
-    stubs["import-fresh"] = fsImportFresh.bind(null, fs, stubs);
-    stubs["../shared/relative-module-resolver"] = RelativeModuleResolver;
-
-    /*
-     * Write all files to the in-memory file system and compile all JavaScript
-     * files then set to `stubs`.
-     */
-    (function initFiles(directoryPath, definition) {
-        for (const [filename, content] of Object.entries(definition)) {
-            const filePath = path.resolve(directoryPath, filename);
-
-            if (typeof content === "object") {
-                initFiles(filePath, content);
-                continue;
-            }
-
-            /*
-             * Compile then stub if this file is a JavaScript file.
-             * For parsers and plugins that `require()` will import.
-             */
-            if (path.extname(filePath) === ".js") {
-                Object.defineProperty(stubs, filePath, {
-                    configurable: true,
-                    enumerable: true,
-                    get() {
-                        let stub;
-
-                        try {
-                            stub = compile(fs, stubs, filePath, content);
-                        } catch (error) {
-                            stub = { [ERRORED]: error };
-                        }
-                        Object.defineProperty(stubs, filePath, {
-                            configurable: true,
-                            enumerable: true,
-                            value: stub
-                        });
-
-                        return stub;
-                    }
-                });
-            }
-        }
-    }(cwd(), files));
-
-    // Load the stubbed one.
-    const { ConfigArrayFactory } = proxyquire(ConfigArrayFactoryPath, stubs);
-
-    // Override the default cwd.
-    return {
-        fs,
-        stubs,
-        RelativeModuleResolver,
-        ConfigArrayFactory: cwd === process.cwd
-            ? ConfigArrayFactory
-            : class extends ConfigArrayFactory {
-                constructor(options) {
-                    super({ cwd: cwd(), ...options });
-                }
-            }
-    };
-}
-
-/**
- * Define stubbed `CascadingConfigArrayFactory` class what uses the in-memory file system.
- * @param {Object} options The options.
- * @param {() => string} [options.cwd] The current working directory.
- * @param {Object} [options.files] The initial files definition in the in-memory file system.
- * @returns {{ fs: import("fs"), RelativeModuleResolver: import("../../../lib/shared/relative-module-resolver"), ConfigArrayFactory: import("../../../lib/cli-engine/config-array-factory")["ConfigArrayFactory"], CascadingConfigArrayFactory: import("../../../lib/cli-engine/cascading-config-array-factory")["CascadingConfigArrayFactory"] }} The stubbed `CascadingConfigArrayFactory` class.
- */
-function defineCascadingConfigArrayFactoryWithInMemoryFileSystem({
-    cwd = process.cwd,
-    files = {}
-} = {}) {
-    const { fs, stubs, RelativeModuleResolver, ConfigArrayFactory } =
-           defineConfigArrayFactoryWithInMemoryFileSystem({ cwd, files });
-    const loadRules = proxyquire(LoadRulesPath, stubs);
-    const { CascadingConfigArrayFactory } =
-        proxyquire(CascadingConfigArrayFactoryPath, {
-            "./config-array-factory": { ConfigArrayFactory },
-            "./load-rules": loadRules
-        });
-
-    // Override the default cwd.
-    return {
-        fs,
-        RelativeModuleResolver,
-        ConfigArrayFactory,
-        CascadingConfigArrayFactory: cwd === process.cwd
-            ? CascadingConfigArrayFactory
-            : class extends CascadingConfigArrayFactory {
-                constructor(options) {
-                    super({ cwd: cwd(), ...options });
-                }
-            }
-    };
-}
-
-/**
- * Define stubbed `FileEnumerator` class what uses the in-memory file system.
- * @param {Object} options The options.
- * @param {() => string} [options.cwd] The current working directory.
- * @param {Object} [options.files] The initial files definition in the in-memory file system.
- * @returns {{ fs: import("fs"), RelativeModuleResolver: import("../../../lib/shared/relative-module-resolver"), ConfigArrayFactory: import("../../../lib/cli-engine/config-array-factory")["ConfigArrayFactory"], CascadingConfigArrayFactory: import("../../../lib/cli-engine/cascading-config-array-factory")["CascadingConfigArrayFactory"], FileEnumerator: import("../../../lib/cli-engine/file-enumerator")["FileEnumerator"] }} The stubbed `FileEnumerator` class.
- */
-function defineFileEnumeratorWithInMemoryFileSystem({
-    cwd = process.cwd,
-    files = {}
-} = {}) {
-    const {
-        fs,
-        RelativeModuleResolver,
-        ConfigArrayFactory,
-        CascadingConfigArrayFactory
-    } =
-        defineCascadingConfigArrayFactoryWithInMemoryFileSystem({ cwd, files });
-    const { FileEnumerator } = proxyquire(FileEnumeratorPath, {
-        fs,
-        "./cascading-config-array-factory": { CascadingConfigArrayFactory }
-    });
-
-    // Override the default cwd.
-    return {
-        fs,
-        RelativeModuleResolver,
-        ConfigArrayFactory,
-        CascadingConfigArrayFactory,
-        FileEnumerator: cwd === process.cwd
-            ? FileEnumerator
-            : class extends FileEnumerator {
-                constructor(options) {
-                    super({ cwd: cwd(), ...options });
-                }
-            }
-    };
-}
-
-/**
- * Define stubbed `CLIEngine` class what uses the in-memory file system.
- * @param {Object} options The options.
- * @param {() => string} [options.cwd] The current working directory.
- * @param {Object} [options.files] The initial files definition in the in-memory file system.
- * @returns {{ fs: import("fs"), RelativeModuleResolver: import("../../../lib/shared/relative-module-resolver"), ConfigArrayFactory: import("../../../lib/cli-engine/config-array-factory")["ConfigArrayFactory"], CascadingConfigArrayFactory: import("../../../lib/cli-engine/cascading-config-array-factory")["CascadingConfigArrayFactory"], FileEnumerator: import("../../../lib/cli-engine/file-enumerator")["FileEnumerator"], CLIEngine: import("../../../lib/cli-engine/cli-engine")["CLIEngine"], getCLIEngineInternalSlots: import("../../../lib/cli-engine/cli-engine")["getCLIEngineInternalSlots"] }} The stubbed `CLIEngine` class.
- */
-function defineCLIEngineWithInMemoryFileSystem({
-    cwd = process.cwd,
-    files = {}
-} = {}) {
-    const {
-        fs,
-        RelativeModuleResolver,
-        ConfigArrayFactory,
-        CascadingConfigArrayFactory,
-        FileEnumerator
-    } =
-        defineFileEnumeratorWithInMemoryFileSystem({ cwd, files });
-    const { CLIEngine, getCLIEngineInternalSlots } = proxyquire(CLIEnginePath, {
-        fs,
-        "./cascading-config-array-factory": { CascadingConfigArrayFactory },
-        "./file-enumerator": { FileEnumerator },
-        "../shared/relative-module-resolver": RelativeModuleResolver
-    });
-
-    // Override the default cwd.
-    return {
-        fs,
-        RelativeModuleResolver,
-        ConfigArrayFactory,
-        CascadingConfigArrayFactory,
-        FileEnumerator,
-        CLIEngine: cwd === process.cwd
-            ? CLIEngine
-            : class extends CLIEngine {
-                constructor(options) {
-                    super({ cwd: cwd(), ...options });
-                }
-            },
-        getCLIEngineInternalSlots
-    };
-}
-
-module.exports = {
-    defineConfigArrayFactoryWithInMemoryFileSystem,
-    defineCascadingConfigArrayFactoryWithInMemoryFileSystem,
-    defineFileEnumeratorWithInMemoryFileSystem,
-    defineCLIEngineWithInMemoryFileSystem
-};
index f9817717f721727205577084236976797dafd72a..8471ac3b5538e61585fee3aa10d7d78bc0cb08be 100644 (file)
@@ -12,7 +12,7 @@ const sh = require("shelljs");
 const sinon = require("sinon");
 const { ConfigArrayFactory } = require("../../../lib/cli-engine/config-array-factory");
 const { ExtractedConfig } = require("../../../lib/cli-engine/config-array/extracted-config");
-const { defineCascadingConfigArrayFactoryWithInMemoryFileSystem } = require("./_utils");
+const { defineCascadingConfigArrayFactoryWithInMemoryFileSystem } = require("../../_utils");
 
 /** @typedef {InstanceType<ReturnType<defineCascadingConfigArrayFactoryWithInMemoryFileSystem>["CascadingConfigArrayFactory"]>} CascadingConfigArrayFactory */
 /** @typedef {ReturnType<CascadingConfigArrayFactory["getConfigArrayForFile"]>} ConfigArray */
index 6880bf9f98f5429eabf6ba96c6cb5e9bf9b5ade9..a8394b63634c681e33fa54513962bb25ea4cb7d9 100644 (file)
@@ -18,8 +18,7 @@ const assert = require("chai").assert,
     os = require("os"),
     hash = require("../../../lib/cli-engine/hash"),
     { CascadingConfigArrayFactory } = require("../../../lib/cli-engine/cascading-config-array-factory"),
-    { unIndent } = require("../_utils"),
-    { defineCLIEngineWithInMemoryFileSystem } = require("./_utils");
+    { unIndent, defineCLIEngineWithInMemoryFileSystem } = require("../../_utils");
 
 const proxyquire = require("proxyquire").noCallThru().noPreserveCache();
 const fCache = require("file-entry-cache");
@@ -822,7 +821,9 @@ describe("CLIEngine", () => {
 
             engine = new CLIEngine({
                 parser: "espree",
-                envs: ["es6"],
+                parserOptions: {
+                    ecmaVersion: 2020
+                },
                 useEslintrc: false
             });
 
@@ -868,6 +869,29 @@ describe("CLIEngine", () => {
             assert.strictEqual(report.results[0].messages.length, 0);
         });
 
+        it("should fall back to defaults when extensions is set to an empty array", () => {
+
+            engine = new CLIEngine({
+                cwd: getFixturePath("configurations"),
+                configFile: getFixturePath("configurations", "quotes-error.json"),
+                extensions: []
+            });
+            const report = engine.executeOnFiles([getFixturePath("single-quoted.js")]);
+
+            assert.strictEqual(report.results.length, 1);
+            assert.strictEqual(report.results[0].messages.length, 1);
+            assert.strictEqual(report.errorCount, 1);
+            assert.strictEqual(report.warningCount, 0);
+            assert.strictEqual(report.fixableErrorCount, 1);
+            assert.strictEqual(report.fixableWarningCount, 0);
+            assert.strictEqual(report.results[0].messages[0].ruleId, "quotes");
+            assert.strictEqual(report.results[0].messages[0].severity, 2);
+            assert.strictEqual(report.results[0].errorCount, 1);
+            assert.strictEqual(report.results[0].warningCount, 0);
+            assert.strictEqual(report.results[0].fixableErrorCount, 1);
+            assert.strictEqual(report.results[0].fixableWarningCount, 0);
+        });
+
         it("should report zero messages when given a directory with a .js and a .js2 file", () => {
 
             engine = new CLIEngine({
@@ -3208,7 +3232,7 @@ describe("CLIEngine", () => {
                 `);
             });
 
-            it("should use overriden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", () => {
+            it("should use overridden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", () => {
                 CLIEngine = defineCLIEngineWithInMemoryFileSystem({
                     cwd: () => root,
                     files: {
index 20f256bbe61ca4627e495d200a14863cc58ce92a..3b979c1d38f7249e59420537179ed15f155e52b2 100644 (file)
@@ -11,7 +11,7 @@ const { spy } = require("sinon");
 const { ConfigArray } = require("../../../lib/cli-engine/config-array");
 const { OverrideTester } = require("../../../lib/cli-engine/config-array");
 const { createContext } = require("../../../lib/cli-engine/config-array-factory");
-const { defineConfigArrayFactoryWithInMemoryFileSystem } = require("./_utils");
+const { defineConfigArrayFactoryWithInMemoryFileSystem } = require("../../_utils");
 
 const tempDir = path.join(os.tmpdir(), "eslint/config-array-factory");
 
@@ -1026,7 +1026,7 @@ describe("ConfigArrayFactory", () => {
                     });
                 });
 
-                it("should have the given config data at the thrid element.", () => {
+                it("should have the given config data at the third element.", () => {
                     assertConfigArrayElement(configArray[2], {
                         name: ".eslintrc",
                         rules: { eqeqeq: 1 }
index 443d350a2ed0a6ae9a874a8727a5647a5573eb4a..9d652f3b68965b070c17d8ead25b6bc9223a9796 100644 (file)
@@ -6,6 +6,7 @@
 
 const assert = require("assert");
 const path = require("path");
+const sinon = require("sinon");
 const { IgnorePattern } = require("../../../../lib/cli-engine/config-array/ignore-pattern");
 
 describe("IgnorePattern", () => {
@@ -52,74 +53,127 @@ describe("IgnorePattern", () => {
 
     describe("static createIgnore(ignorePatterns)", () => {
         describe("with two patterns should return a function, and the function", () => {
-            const cwd = process.cwd();
-            const basePath1 = path.join(cwd, "foo/bar");
-            const basePath2 = path.join(cwd, "abc/");
-            const ignores = IgnorePattern.createIgnore([
-                new IgnorePattern(["*.js", "/*.ts", "!a.*", "!/b.*"], basePath1),
-                new IgnorePattern(["*.js", "/*.ts", "!a.*", "!/b.*"], basePath2)
-            ]);
-            const patterns = [
-                ["a.js", false],
-                ["a.ts", false],
-                ["b.js", false],
-                ["b.ts", false],
-                ["c.js", false],
-                ["c.ts", false],
-                ["dir/a.js", false],
-                ["dir/a.ts", false],
-                ["dir/b.js", false],
-                ["dir/b.ts", false],
-                ["dir/c.js", false],
-                ["dir/c.ts", false],
-                ["foo/bar/a.js", false],
-                ["foo/bar/a.ts", false],
-                ["foo/bar/b.js", false],
-                ["foo/bar/b.ts", false],
-                ["foo/bar/c.js", true],
-                ["foo/bar/c.ts", true],
-                ["foo/bar/dir/a.js", false],
-                ["foo/bar/dir/a.ts", false],
-                ["foo/bar/dir/b.js", true],
-                ["foo/bar/dir/b.ts", false],
-                ["foo/bar/dir/c.js", true],
-                ["foo/bar/dir/c.ts", false],
-                ["abc/a.js", false],
-                ["abc/a.ts", false],
-                ["abc/b.js", false],
-                ["abc/b.ts", false],
-                ["abc/c.js", true],
-                ["abc/c.ts", true],
-                ["abc/dir/a.js", false],
-                ["abc/dir/a.ts", false],
-                ["abc/dir/b.js", true],
-                ["abc/dir/b.ts", false],
-                ["abc/dir/c.js", true],
-                ["abc/dir/c.ts", false]
-            ];
-
-            for (const [filename, expected] of patterns) {
-                it(`should return ${expected} if '${filename}' was given.`, () => {
-                    assert.strictEqual(ignores(path.join(cwd, filename)), expected);
+
+            /**
+             * performs static createIgnre assertions against the cwd.
+             * @param {string} cwd cwd to be the base path for assertions
+             * @returns {void}
+             */
+            function assertions(cwd) {
+                const basePath1 = path.join(cwd, "foo/bar");
+                const basePath2 = path.join(cwd, "abc/");
+                const ignores = IgnorePattern.createIgnore([
+                    new IgnorePattern(["*.js", "/*.ts", "!a.*", "!/b.*"], basePath1),
+                    new IgnorePattern(["*.js", "/*.ts", "!a.*", "!/b.*"], basePath2)
+                ]);
+                const patterns = [
+                    ["a.js", false],
+                    ["a.ts", false],
+                    ["b.js", false],
+                    ["b.ts", false],
+                    ["c.js", false],
+                    ["c.ts", false],
+                    ["dir/a.js", false],
+                    ["dir/a.ts", false],
+                    ["dir/b.js", false],
+                    ["dir/b.ts", false],
+                    ["dir/c.js", false],
+                    ["dir/c.ts", false],
+                    ["foo/bar/a.js", false],
+                    ["foo/bar/a.ts", false],
+                    ["foo/bar/b.js", false],
+                    ["foo/bar/b.ts", false],
+                    ["foo/bar/c.js", true],
+                    ["foo/bar/c.ts", true],
+                    ["foo/bar/dir/a.js", false],
+                    ["foo/bar/dir/a.ts", false],
+                    ["foo/bar/dir/b.js", true],
+                    ["foo/bar/dir/b.ts", false],
+                    ["foo/bar/dir/c.js", true],
+                    ["foo/bar/dir/c.ts", false],
+                    ["abc/a.js", false],
+                    ["abc/a.ts", false],
+                    ["abc/b.js", false],
+                    ["abc/b.ts", false],
+                    ["abc/c.js", true],
+                    ["abc/c.ts", true],
+                    ["abc/dir/a.js", false],
+                    ["abc/dir/a.ts", false],
+                    ["abc/dir/b.js", true],
+                    ["abc/dir/b.ts", false],
+                    ["abc/dir/c.js", true],
+                    ["abc/dir/c.ts", false]
+                ];
+
+                for (const [filename, expected] of patterns) {
+                    it(`should return ${expected} if '${filename}' was given.`, () => {
+                        assert.strictEqual(ignores(path.join(cwd, filename)), expected);
+                    });
+                }
+
+                it("should return false if '.dot.js' and false was given.", () => {
+                    assert.strictEqual(ignores(path.join(cwd, ".dot.js"), false), true);
                 });
-            }
 
-            it("should return false if '.dot.js' and false was given.", () => {
-                assert.strictEqual(ignores(path.join(cwd, ".dot.js"), false), true);
-            });
+                it("should return true if '.dot.js' and true were given.", () => {
+                    assert.strictEqual(ignores(path.join(cwd, ".dot.js"), true), false);
+                });
 
-            it("should return true if '.dot.js' and true were given.", () => {
-                assert.strictEqual(ignores(path.join(cwd, ".dot.js"), true), false);
-            });
+                it("should return false if '.dot/foo.js' and false was given.", () => {
+                    assert.strictEqual(ignores(path.join(cwd, ".dot/foo.js"), false), true);
+                });
 
+                it("should return true if '.dot/foo.js' and true were given.", () => {
+                    assert.strictEqual(ignores(path.join(cwd, ".dot/foo.js"), true), false);
+                });
+            }
 
-            it("should return false if '.dot/foo.js' and false was given.", () => {
-                assert.strictEqual(ignores(path.join(cwd, ".dot/foo.js"), false), true);
-            });
+            assertions(process.cwd());
+
+            /*
+             * This will catch regressions of Windows specific issue #12850 when run on CI nodes.
+             * This runs the full set of assertions for the function returned from IgnorePattern.createIgnore.
+             * When run on Windows CI nodes the .root drive i.e C:\ will be supplied
+             *  forcing getCommonAncestors to resolve to the root of the drive thus catching any regrssion of 12850.
+             * When run on *nix CI nodes provides additional coverage on this OS too.
+             *  assertions when run on Windows CI nodes and / on *nix OS
+             */
+            assertions(path.parse(process.cwd()).root);
+        });
+    });
 
-            it("should return true if '.dot/foo.js' and true were given.", () => {
-                assert.strictEqual(ignores(path.join(cwd, ".dot/foo.js"), true), false);
-            });
+    describe("static createIgnore(ignorePatterns)", () => {
+
+        /*
+         * This test will catch regressions of Windows specific issue #12850 when run on your local dev box
+         * irrespective of if you are running a Windows or *nix style OS.
+         * When running on *nix sinon is used to emulate Windows behaviors of path and platform APIs
+         * thus ensuring that the Windows specific fix is exercised and any regression is caught.
+         */
+        it("with common ancestor of drive root on windows should not throw", () => {
+            try {
+
+                /*
+                 * When not on Windows return win32 values so local runs on *nix hit the same code path as on Windows
+                 * thus enabling developers with *nix style OS to catch and debug any future regression of #12850 without
+                 * requiring a Windows based OS.
+                 */
+                if (process.platform !== "win32") {
+                    sinon.stub(process, "platform").value("win32");
+                    sinon.stub(path, "sep").value(path.win32.sep);
+                    sinon.replace(path, "isAbsolute", path.win32.isAbsolute);
+                }
+
+                const ignores = IgnorePattern.createIgnore([
+                    new IgnorePattern(["*.js"], "C:\\foo\\bar"),
+                    new IgnorePattern(["*.js"], "C:\\abc\\")
+                ]);
+
+                // calls to this should not throw when getCommonAncestor returns root of drive
+                ignores("C:\\abc\\contract.d.ts");
+            } finally {
+                sinon.restore();
+            }
         });
     });
 });
index c62578c91624f2a3785d3ae49077b202e69de218..43728862d95ce3bedc2c26e303e2b1b81cd83e96 100644 (file)
@@ -11,7 +11,7 @@ const { assert } = require("chai");
 const sh = require("shelljs");
 const { CascadingConfigArrayFactory } =
     require("../../../lib/cli-engine/cascading-config-array-factory");
-const { defineFileEnumeratorWithInMemoryFileSystem } = require("./_utils");
+const { defineFileEnumeratorWithInMemoryFileSystem } = require("../../_utils");
 
 describe("FileEnumerator", () => {
     describe("'iterateFiles(patterns)' method should iterate files and configs.", () => {
index 6af3b5c838e407241ce288fcb7aaf817e20e3238..a1d9a23e49176bb9ef6a98158ed599ca4995f539 100644 (file)
@@ -6,8 +6,8 @@
 "use strict";
 
 /*
- * NOTE: If you are adding new tests for cli.js, use verifyCLIEngineOpts(). The
- * test only needs to verify that CLIEngine receives the correct opts.
+ * NOTE: If you are adding new tests for cli.js, use verifyESLintOpts(). The
+ * test only needs to verify that ESLint receives the correct opts.
  */
 
 //------------------------------------------------------------------------------
@@ -15,7 +15,9 @@
 //------------------------------------------------------------------------------
 
 const assert = require("chai").assert,
-    CLIEngine = require("../../lib/cli-engine/index").CLIEngine,
+    stdAssert = require("assert"),
+    { ESLint } = require("../../lib/eslint"),
+    BuiltinRules = require("../../lib/rules"),
     path = require("path"),
     sinon = require("sinon"),
     fs = require("fs"),
@@ -44,30 +46,30 @@ describe("cli", () => {
     });
 
     /**
-     * Verify that CLIEngine receives correct opts via cli.execute().
+     * Verify that ESLint class receives correct opts via await cli.execute().
      * @param {string} cmd CLI command.
-     * @param {Object} opts Options hash that should match that received by CLIEngine.
+     * @param {Object} opts Options hash that should match that received by ESLint class.
      * @returns {void}
      */
-    function verifyCLIEngineOpts(cmd, opts) {
+    async function verifyESLintOpts(cmd, opts) {
 
-        // create a fake CLIEngine to test with
-        const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match(opts));
+        // create a fake ESLint class to test with
+        const fakeESLint = sinon.mock().withExactArgs(sinon.match(opts));
 
-        Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-        sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({});
-        sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(sinon.spy());
+        Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+        sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+        sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: sinon.spy() });
 
         const localCLI = proxyquire("../../lib/cli", {
-            "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+            "./eslint": { ESLint: fakeESLint },
             "./shared/logging": log
         });
 
-        localCLI.execute(cmd);
+        await localCLI.execute(cmd);
         sinon.verifyAndRestore();
     }
 
-    // verifyCLIEngineOpts
+    // verifyESLintOpts
 
     /**
      * Returns the path inside of the fixture directory.
@@ -96,30 +98,30 @@ describe("cli", () => {
     });
 
     describe("execute()", () => {
-        it("should return error when text with incorrect quotes is passed as argument", () => {
+        it("should return error when text with incorrect quotes is passed as argument", async () => {
             const configFile = getFixturePath("configurations", "quotes-error.json");
-            const result = cli.execute(`-c ${configFile}`, "var foo = 'bar';");
+            const result = await cli.execute(`-c ${configFile}`, "var foo = 'bar';");
 
             assert.strictEqual(result, 1);
         });
 
-        it("should not print debug info when passed the empty string as text", () => {
-            const result = cli.execute(["--stdin", "--no-eslintrc"], "");
+        it("should not print debug info when passed the empty string as text", async () => {
+            const result = await cli.execute(["--stdin", "--no-eslintrc"], "");
 
             assert.strictEqual(result, 0);
             assert.isTrue(log.info.notCalled);
         });
 
-        it("should return no error when --ext .js2 is specified", () => {
+        it("should return no error when --ext .js2 is specified", async () => {
             const filePath = getFixturePath("files");
-            const result = cli.execute(`--ext .js2 ${filePath}`);
+            const result = await cli.execute(`--ext .js2 ${filePath}`);
 
             assert.strictEqual(result, 0);
         });
 
-        it("should exit with console error when passed unsupported arguments", () => {
+        it("should exit with console error when passed unsupported arguments", async () => {
             const filePath = getFixturePath("files");
-            const result = cli.execute(`--blah --another ${filePath}`);
+            const result = await cli.execute(`--blah --another ${filePath}`);
 
             assert.strictEqual(result, 2);
         });
@@ -127,120 +129,119 @@ describe("cli", () => {
     });
 
     describe("when given a config file", () => {
-        it("should load the specified config file", () => {
+        it("should load the specified config file", async () => {
             const configPath = getFixturePath(".eslintrc");
             const filePath = getFixturePath("passing.js");
 
-            cli.execute(`--config ${configPath} ${filePath}`);
+            await cli.execute(`--config ${configPath} ${filePath}`);
         });
     });
 
     describe("when there is a local config file", () => {
         const code = "lib/cli.js";
 
-        it("should load the local config file", () => {
+        it("should load the local config file", async () => {
 
             // Mock CWD
             process.eslintCwd = getFixturePath("configurations", "single-quotes");
 
-            cli.execute(code);
+            await cli.execute(code);
 
             process.eslintCwd = null;
         });
     });
 
     describe("when given a config with rules with options and severity level set to error", () => {
-        it("should exit with an error status (1)", () => {
+        it("should exit with an error status (1)", async () => {
             const configPath = getFixturePath("configurations", "quotes-error.json");
             const filePath = getFixturePath("single-quoted.js");
             const code = `--no-ignore --config ${configPath} ${filePath}`;
 
-            const exitStatus = cli.execute(code);
+            const exitStatus = await cli.execute(code);
 
             assert.strictEqual(exitStatus, 1);
         });
     });
 
     describe("when given a config file and a directory of files", () => {
-        it("should load and execute without error", () => {
+        it("should load and execute without error", async () => {
             const configPath = getFixturePath("configurations", "semi-error.json");
             const filePath = getFixturePath("formatters");
             const code = `--config ${configPath} ${filePath}`;
 
-            const exitStatus = cli.execute(code);
+            const exitStatus = await cli.execute(code);
 
             assert.strictEqual(exitStatus, 0);
         });
     });
 
     describe("when given a config with environment set to browser", () => {
-        it("should execute without any errors", () => {
+        it("should execute without any errors", async () => {
             const configPath = getFixturePath("configurations", "env-browser.json");
             const filePath = getFixturePath("globals-browser.js");
             const code = `--config ${configPath} ${filePath}`;
 
-            const exit = cli.execute(code);
+            const exit = await cli.execute(code);
 
             assert.strictEqual(exit, 0);
         });
     });
 
     describe("when given a config with environment set to Node.js", () => {
-        it("should execute without any errors", () => {
+        it("should execute without any errors", async () => {
             const configPath = getFixturePath("configurations", "env-node.json");
             const filePath = getFixturePath("globals-node.js");
             const code = `--config ${configPath} ${filePath}`;
 
-            const exit = cli.execute(code);
+            const exit = await cli.execute(code);
 
             assert.strictEqual(exit, 0);
         });
     });
 
     describe("when given a config with environment set to Nashorn", () => {
-        it("should execute without any errors", () => {
+        it("should execute without any errors", async () => {
             const configPath = getFixturePath("configurations", "env-nashorn.json");
             const filePath = getFixturePath("globals-nashorn.js");
             const code = `--config ${configPath} ${filePath}`;
 
-            const exit = cli.execute(code);
+            const exit = await cli.execute(code);
 
             assert.strictEqual(exit, 0);
         });
     });
 
     describe("when given a config with environment set to WebExtensions", () => {
-        it("should execute without any errors", () => {
+        it("should execute without any errors", async () => {
             const configPath = getFixturePath("configurations", "env-webextensions.json");
             const filePath = getFixturePath("globals-webextensions.js");
             const code = `--config ${configPath} ${filePath}`;
 
-            const exit = cli.execute(code);
+            const exit = await cli.execute(code);
 
             assert.strictEqual(exit, 0);
         });
     });
 
     describe("when given a valid built-in formatter name", () => {
-        it("should execute without any errors", () => {
+        it("should execute without any errors", async () => {
             const filePath = getFixturePath("passing.js");
-            const exit = cli.execute(`-f checkstyle ${filePath}`);
+            const exit = await cli.execute(`-f checkstyle ${filePath}`);
 
             assert.strictEqual(exit, 0);
         });
     });
 
     describe("when given a valid built-in formatter name that uses rules meta.", () => {
-        it("should execute without any errors", () => {
+        it("should execute without any errors", async () => {
             const filePath = getFixturePath("passing.js");
-            const exit = cli.execute(`-f json-with-metadata ${filePath} --no-eslintrc`);
+            const exit = await cli.execute(`-f json-with-metadata ${filePath} --no-eslintrc`);
 
             assert.strictEqual(exit, 0);
 
             // Check metadata.
             const { metadata } = JSON.parse(log.info.args[0][0]);
-            const rules = new CLIEngine({ useEslintrc: false }).getRules();
-            const expectedMetadata = Array.from(rules).reduce((obj, [ruleId, rule]) => {
+            const expectedMetadata = Array.from(BuiltinRules).reduce((obj, [ruleId, rule]) => {
                 obj.rulesMeta[ruleId] = rule.meta;
                 return obj;
             }, { rulesMeta: {} });
@@ -250,204 +251,204 @@ describe("cli", () => {
     });
 
     describe("when given an invalid built-in formatter name", () => {
-        it("should execute with error", () => {
+        it("should execute with error", async () => {
             const filePath = getFixturePath("passing.js");
-            const exit = cli.execute(`-f fakeformatter ${filePath}`);
+            const exit = await cli.execute(`-f fakeformatter ${filePath}`);
 
             assert.strictEqual(exit, 2);
         });
     });
 
     describe("when given a valid formatter path", () => {
-        it("should execute without any errors", () => {
+        it("should execute without any errors", async () => {
             const formatterPath = getFixturePath("formatters", "simple.js");
             const filePath = getFixturePath("passing.js");
-            const exit = cli.execute(`-f ${formatterPath} ${filePath}`);
+            const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
 
             assert.strictEqual(exit, 0);
         });
     });
 
     describe("when given an invalid formatter path", () => {
-        it("should execute with error", () => {
+        it("should execute with error", async () => {
             const formatterPath = getFixturePath("formatters", "file-does-not-exist.js");
             const filePath = getFixturePath("passing.js");
-            const exit = cli.execute(`-f ${formatterPath} ${filePath}`);
+            const exit = await cli.execute(`-f ${formatterPath} ${filePath}`);
 
             assert.strictEqual(exit, 2);
         });
     });
 
     describe("when executing a file with a lint error", () => {
-        it("should exit with error", () => {
+        it("should exit with error", async () => {
             const filePath = getFixturePath("undef.js");
             const code = `--no-ignore --rule no-undef:2 ${filePath}`;
 
-            const exit = cli.execute(code);
+            const exit = await cli.execute(code);
 
             assert.strictEqual(exit, 1);
         });
     });
 
     describe("when using --fix-type without --fix or --fix-dry-run", () => {
-        it("should exit with error", () => {
+        it("should exit with error", async () => {
             const filePath = getFixturePath("passing.js");
             const code = `--fix-type suggestion ${filePath}`;
 
-            const exit = cli.execute(code);
+            const exit = await cli.execute(code);
 
             assert.strictEqual(exit, 2);
         });
     });
 
     describe("when executing a file with a syntax error", () => {
-        it("should exit with error", () => {
+        it("should exit with error", async () => {
             const filePath = getFixturePath("syntax-error.js");
-            const exit = cli.execute(`--no-ignore ${filePath}`);
+            const exit = await cli.execute(`--no-ignore ${filePath}`);
 
             assert.strictEqual(exit, 1);
         });
     });
 
     describe("when calling execute more than once", () => {
-        it("should not print the results from previous execution", () => {
+        it("should not print the results from previous execution", async () => {
             const filePath = getFixturePath("missing-semicolon.js");
             const passingPath = getFixturePath("passing.js");
 
-            cli.execute(`--no-ignore --rule semi:2 ${filePath}`);
+            await cli.execute(`--no-ignore --rule semi:2 ${filePath}`);
 
             assert.isTrue(log.info.called, "Log should have been called.");
 
             log.info.resetHistory();
 
-            cli.execute(`--no-ignore --rule semi:2 ${passingPath}`);
+            await cli.execute(`--no-ignore --rule semi:2 ${passingPath}`);
             assert.isTrue(log.info.notCalled);
 
         });
     });
 
     describe("when executing with version flag", () => {
-        it("should print out current version", () => {
-            assert.strictEqual(cli.execute("-v"), 0);
+        it("should print out current version", async () => {
+            assert.strictEqual(await cli.execute("-v"), 0);
             assert.strictEqual(log.info.callCount, 1);
         });
     });
 
     describe("when executing with env-info flag", () => {
-        it("should print out environment information", () => {
-            assert.strictEqual(cli.execute("--env-info"), 0);
+        it("should print out environment information", async () => {
+            assert.strictEqual(await cli.execute("--env-info"), 0);
             assert.strictEqual(log.info.callCount, 1);
         });
 
-        it("should print error message and return error code", () => {
+        it("should print error message and return error code", async () => {
             RuntimeInfo.environment.throws("There was an error!");
 
-            assert.strictEqual(cli.execute("--env-info"), 2);
+            assert.strictEqual(await cli.execute("--env-info"), 2);
             assert.strictEqual(log.error.callCount, 1);
         });
     });
 
     describe("when executing without no-error-on-unmatched-pattern flag", () => {
-        it("should throw an error on unmatched glob pattern", () => {
+        it("should throw an error on unmatched glob pattern", async () => {
             const filePath = getFixturePath("unmatched-patterns");
             const globPattern = "*.js3";
 
-            assert.throws(() => {
-                cli.execute(`"${filePath}/${globPattern}"`);
-            }, `No files matching '${filePath}/${globPattern}' were found.`);
+            await stdAssert.rejects(async () => {
+                await cli.execute(`"${filePath}/${globPattern}"`);
+            }, new Error(`No files matching '${filePath}/${globPattern}' were found.`));
         });
 
-        it("should throw an error on unmatched --ext", () => {
+        it("should throw an error on unmatched --ext", async () => {
             const filePath = getFixturePath("unmatched-patterns");
             const extension = ".js3";
 
-            assert.throws(() => {
-                cli.execute(`--ext ${extension} ${filePath}`);
+            await stdAssert.rejects(async () => {
+                await cli.execute(`--ext ${extension} ${filePath}`);
             }, `No files matching '${filePath}' were found`);
         });
     });
 
     describe("when executing with no-error-on-unmatched-pattern flag", () => {
-        it("should not throw an error on unmatched node glob syntax patterns", () => {
+        it("should not throw an error on unmatched node glob syntax patterns", async () => {
             const filePath = getFixturePath("unmatched-patterns");
-            const exit = cli.execute(`--no-error-on-unmatched-pattern "${filePath}/*.js3"`);
+            const exit = await cli.execute(`--no-error-on-unmatched-pattern "${filePath}/*.js3"`);
 
             assert.strictEqual(exit, 0);
         });
 
-        it("should not throw an error on unmatched --ext", () => {
+        it("should not throw an error on unmatched --ext", async () => {
             const filePath = getFixturePath("unmatched-patterns");
-            const exit = cli.execute(`--no-error-on-unmatched-pattern --ext .js3 ${filePath}`);
+            const exit = await cli.execute(`--no-error-on-unmatched-pattern --ext .js3 ${filePath}`);
 
             assert.strictEqual(exit, 0);
         });
     });
 
     describe("when executing with no-error-on-unmatched-pattern flag and multiple patterns", () => {
-        it("should not throw an error on multiple unmatched node glob syntax patterns", () => {
+        it("should not throw an error on multiple unmatched node glob syntax patterns", async () => {
             const filePath = getFixturePath("unmatched-patterns");
-            const exit = cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js4`);
+            const exit = await cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js4`);
 
             assert.strictEqual(exit, 0);
         });
 
-        it("should still throw an error on when a matched pattern has lint errors", () => {
+        it("should still throw an error on when a matched pattern has lint errors", async () => {
             const filePath = getFixturePath("unmatched-patterns");
-            const exit = cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js`);
+            const exit = await cli.execute(`--no-error-on-unmatched-pattern ${filePath}/*.js3 ${filePath}/*.js`);
 
             assert.strictEqual(exit, 1);
         });
     });
 
     describe("when executing with no-error-on-unmatched-pattern flag and multiple --ext arguments", () => {
-        it("should not throw an error on multiple unmatched --ext arguments", () => {
+        it("should not throw an error on multiple unmatched --ext arguments", async () => {
             const filePath = getFixturePath("unmatched-patterns");
-            const exit = cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js4 ${filePath}`);
+            const exit = await cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js4 ${filePath}`);
 
             assert.strictEqual(exit, 0);
         });
 
-        it("should still throw an error on when a matched pattern has lint errors", () => {
+        it("should still throw an error on when a matched pattern has lint errors", async () => {
             const filePath = getFixturePath("unmatched-patterns");
-            const exit = cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js ${filePath}`);
+            const exit = await cli.execute(`--no-error-on-unmatched-pattern --ext .js3 --ext .js ${filePath}`);
 
             assert.strictEqual(exit, 1);
         });
     });
 
     describe("when executing with help flag", () => {
-        it("should print out help", () => {
-            assert.strictEqual(cli.execute("-h"), 0);
+        it("should print out help", async () => {
+            assert.strictEqual(await cli.execute("-h"), 0);
             assert.strictEqual(log.info.callCount, 1);
         });
     });
 
     describe("when given a directory with eslint excluded files in the directory", () => {
-        it("should throw an error and not process any files", () => {
+        it("should throw an error and not process any files", async () => {
             const ignorePath = getFixturePath(".eslintignore");
             const filePath = getFixturePath("cli");
 
-            assert.throws(() => {
-                cli.execute(`--ignore-path ${ignorePath} ${filePath}`);
-            }, `All files matched by '${filePath}' are ignored.`);
+            await stdAssert.rejects(async () => {
+                await cli.execute(`--ignore-path ${ignorePath} ${filePath}`);
+            }, new Error(`All files matched by '${filePath}' are ignored.`));
         });
     });
 
     describe("when given a file in excluded files list", () => {
-        it("should not process the file", () => {
+        it("should not process the file", async () => {
             const ignorePath = getFixturePath(".eslintignore");
             const filePath = getFixturePath("passing.js");
-            const exit = cli.execute(`--ignore-path ${ignorePath} ${filePath}`);
+            const exit = await cli.execute(`--ignore-path ${ignorePath} ${filePath}`);
 
             // a warning about the ignored file
             assert.isTrue(log.info.called);
             assert.strictEqual(exit, 0);
         });
 
-        it("should process the file when forced", () => {
+        it("should process the file when forced", async () => {
             const ignorePath = getFixturePath(".eslintignore");
             const filePath = getFixturePath("passing.js");
-            const exit = cli.execute(`--ignore-path ${ignorePath} --no-ignore ${filePath}`);
+            const exit = await cli.execute(`--ignore-path ${ignorePath} --no-ignore ${filePath}`);
 
             // no warnings
             assert.isFalse(log.info.called);
@@ -456,10 +457,10 @@ describe("cli", () => {
     });
 
     describe("when given a pattern to ignore", () => {
-        it("should not process any files", () => {
+        it("should not process any files", async () => {
             const ignoredFile = getFixturePath("cli/syntax-error.js");
             const filePath = getFixturePath("cli/passing.js");
-            const exit = cli.execute(`--ignore-pattern cli/ ${ignoredFile} ${filePath}`);
+            const exit = await cli.execute(`--ignore-pattern cli/ ${ignoredFile} ${filePath}`);
 
             // warnings about the ignored files
             assert.isTrue(log.info.called);
@@ -468,61 +469,63 @@ describe("cli", () => {
     });
 
     describe("when given patterns to ignore", () => {
-        it("should not process any matching files", () => {
+        it("should not process any matching files", async () => {
             const ignorePaths = ["a", "b"];
 
             const cmd = ignorePaths.map(ignorePath => `--ignore-pattern ${ignorePath}`).concat(".").join(" ");
 
             const opts = {
-                ignorePattern: ignorePaths
+                overrideConfig: {
+                    ignorePatterns: ignorePaths
+                }
             };
 
-            verifyCLIEngineOpts(cmd, opts);
+            await verifyESLintOpts(cmd, opts);
         });
     });
 
     describe("when executing a file with a shebang", () => {
-        it("should execute without error", () => {
+        it("should execute without error", async () => {
             const filePath = getFixturePath("shebang.js");
-            const exit = cli.execute(`--no-ignore ${filePath}`);
+            const exit = await cli.execute(`--no-ignore ${filePath}`);
 
             assert.strictEqual(exit, 0);
         });
     });
 
     describe("when loading a custom rule", () => {
-        it("should return an error when rule isn't found", () => {
+        it("should return an error when rule isn't found", async () => {
             const rulesPath = getFixturePath("rules", "wrong");
             const configPath = getFixturePath("rules", "eslint.json");
             const filePath = getFixturePath("rules", "test", "test-custom-rule.js");
             const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`;
 
-            assert.throws(() => {
-                const exit = cli.execute(code);
+            await stdAssert.rejects(async () => {
+                const exit = await cli.execute(code);
 
                 assert.strictEqual(exit, 2);
             }, /Error while loading rule 'custom-rule': Cannot read property/u);
         });
 
-        it("should return a warning when rule is matched", () => {
+        it("should return a warning when rule is matched", async () => {
             const rulesPath = getFixturePath("rules");
             const configPath = getFixturePath("rules", "eslint.json");
             const filePath = getFixturePath("rules", "test", "test-custom-rule.js");
             const code = `--rulesdir ${rulesPath} --config ${configPath} --no-ignore ${filePath}`;
 
-            cli.execute(code);
+            await cli.execute(code);
 
             assert.isTrue(log.info.calledOnce);
             assert.isTrue(log.info.neverCalledWith(""));
         });
 
-        it("should return warnings from multiple rules in different directories", () => {
+        it("should return warnings from multiple rules in different directories", async () => {
             const rulesPath = getFixturePath("rules", "dir1");
             const rulesPath2 = getFixturePath("rules", "dir2");
             const configPath = getFixturePath("rules", "multi-rulesdirs.json");
             const filePath = getFixturePath("rules", "test-multi-rulesdirs.js");
             const code = `--rulesdir ${rulesPath} --rulesdir ${rulesPath2} --config ${configPath} --no-ignore ${filePath}`;
-            const exit = cli.execute(code);
+            const exit = await cli.execute(code);
 
             const call = log.info.getCall(0);
 
@@ -538,9 +541,9 @@ describe("cli", () => {
     });
 
     describe("when executing with no-eslintrc flag", () => {
-        it("should ignore a local config file", () => {
+        it("should ignore a local config file", async () => {
             const filePath = getFixturePath("eslintrc", "quotes.js");
-            const exit = cli.execute(`--no-eslintrc --no-ignore ${filePath}`);
+            const exit = await cli.execute(`--no-eslintrc --no-ignore ${filePath}`);
 
             assert.isTrue(log.info.notCalled);
             assert.strictEqual(exit, 0);
@@ -548,9 +551,9 @@ describe("cli", () => {
     });
 
     describe("when executing without no-eslintrc flag", () => {
-        it("should load a local config file", () => {
+        it("should load a local config file", async () => {
             const filePath = getFixturePath("eslintrc", "quotes.js");
-            const exit = cli.execute(`--no-ignore ${filePath}`);
+            const exit = await cli.execute(`--no-ignore ${filePath}`);
 
             assert.isTrue(log.info.calledOnce);
             assert.strictEqual(exit, 1);
@@ -558,38 +561,38 @@ describe("cli", () => {
     });
 
     describe("when executing without env flag", () => {
-        it("should not define environment-specific globals", () => {
+        it("should not define environment-specific globals", async () => {
             const files = [
                 getFixturePath("globals-browser.js"),
                 getFixturePath("globals-node.js")
             ];
 
-            cli.execute(`--no-eslintrc --config ./conf/eslint-recommended.js --no-ignore ${files.join(" ")}`);
+            await cli.execute(`--no-eslintrc --config ./conf/eslint-recommended.js --no-ignore ${files.join(" ")}`);
 
             assert.strictEqual(log.info.args[0][0].split("\n").length, 10);
         });
     });
 
     describe("when executing with global flag", () => {
-        it("should default defined variables to read-only", () => {
+        it("should default defined variables to read-only", async () => {
             const filePath = getFixturePath("undef.js");
-            const exit = cli.execute(`--global baz,bat --no-ignore --rule no-global-assign:2 ${filePath}`);
+            const exit = await cli.execute(`--global baz,bat --no-ignore --rule no-global-assign:2 ${filePath}`);
 
             assert.isTrue(log.info.calledOnce);
             assert.strictEqual(exit, 1);
         });
 
-        it("should allow defining writable global variables", () => {
+        it("should allow defining writable global variables", async () => {
             const filePath = getFixturePath("undef.js");
-            const exit = cli.execute(`--global baz:false,bat:true --no-ignore ${filePath}`);
+            const exit = await cli.execute(`--global baz:false,bat:true --no-ignore ${filePath}`);
 
             assert.isTrue(log.info.notCalled);
             assert.strictEqual(exit, 0);
         });
 
-        it("should allow defining variables with multiple flags", () => {
+        it("should allow defining variables with multiple flags", async () => {
             const filePath = getFixturePath("undef.js");
-            const exit = cli.execute(`--global baz --global bat:true --no-ignore ${filePath}`);
+            const exit = await cli.execute(`--global baz --global bat:true --no-ignore ${filePath}`);
 
             assert.isTrue(log.info.notCalled);
             assert.strictEqual(exit, 0);
@@ -597,10 +600,10 @@ describe("cli", () => {
     });
 
     describe("when supplied with rule flag and severity level set to error", () => {
-        it("should exit with an error status (2)", () => {
+        it("should exit with an error status (2)", async () => {
             const filePath = getFixturePath("single-quoted.js");
             const code = `--no-ignore --rule 'quotes: [2, double]' ${filePath}`;
-            const exitStatus = cli.execute(code);
+            const exitStatus = await cli.execute(code);
 
             assert.strictEqual(exitStatus, 1);
         });
@@ -608,11 +611,11 @@ describe("cli", () => {
 
     describe("when the quiet option is enabled", () => {
 
-        it("should only print error", () => {
+        it("should only print error", async () => {
             const filePath = getFixturePath("single-quoted.js");
             const cliArgs = `--no-ignore --quiet  -f compact --rule 'quotes: [2, double]' --rule 'no-unused-vars: 1' ${filePath}`;
 
-            cli.execute(cliArgs);
+            await cli.execute(cliArgs);
 
             sinon.assert.calledOnce(log.info);
 
@@ -622,11 +625,11 @@ describe("cli", () => {
             assert.notInclude(formattedOutput, "Warning");
         });
 
-        it("should print nothing if there are no errors", () => {
+        it("should print nothing if there are no errors", async () => {
             const filePath = getFixturePath("single-quoted.js");
             const cliArgs = `--quiet  -f compact --rule 'quotes: [1, double]' --rule 'no-unused-vars: 1' ${filePath}`;
 
-            cli.execute(cliArgs);
+            await cli.execute(cliArgs);
 
             sinon.assert.notCalled(log.info);
         });
@@ -637,36 +640,36 @@ describe("cli", () => {
             sh.rm("-rf", "tests/output");
         });
 
-        it("should write the file and create dirs if they don't exist", () => {
+        it("should write the file and create dirs if they don't exist", async () => {
             const filePath = getFixturePath("single-quoted.js");
             const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`;
 
-            cli.execute(code);
+            await cli.execute(code);
 
             assert.include(fs.readFileSync("tests/output/eslint-output.txt", "utf8"), filePath);
             assert.isTrue(log.info.notCalled);
         });
 
-        it("should return an error if the path is a directory", () => {
+        it("should return an error if the path is a directory", async () => {
             const filePath = getFixturePath("single-quoted.js");
             const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output ${filePath}`;
 
             fs.mkdirSync("tests/output");
 
-            const exit = cli.execute(code);
+            const exit = await cli.execute(code);
 
             assert.strictEqual(exit, 2);
             assert.isTrue(log.info.notCalled);
             assert.isTrue(log.error.calledOnce);
         });
 
-        it("should return an error if the path could not be written to", () => {
+        it("should return an error if the path could not be written to", async () => {
             const filePath = getFixturePath("single-quoted.js");
             const code = `--no-ignore --rule 'quotes: [1, double]' --o tests/output/eslint-output.txt ${filePath}`;
 
             fs.writeFileSync("tests/output", "foo");
 
-            const exit = cli.execute(code);
+            const exit = await cli.execute(code);
 
             assert.strictEqual(exit, 2);
             assert.isTrue(log.info.notCalled);
@@ -675,106 +678,108 @@ describe("cli", () => {
     });
 
     describe("when supplied with a plugin", () => {
-        it("should pass plugins to CLIEngine", () => {
+        it("should pass plugins to ESLint", async () => {
             const examplePluginName = "eslint-plugin-example";
 
-            verifyCLIEngineOpts(`--no-ignore --plugin ${examplePluginName} foo.js`, {
-                plugins: [examplePluginName]
+            await verifyESLintOpts(`--no-ignore --plugin ${examplePluginName} foo.js`, {
+                overrideConfig: {
+                    plugins: [examplePluginName]
+                }
             });
         });
 
     });
 
     describe("when supplied with a plugin-loading path", () => {
-        it("should pass the option to CLIEngine", () => {
+        it("should pass the option to ESLint", async () => {
             const examplePluginDirPath = "foo/bar";
 
-            verifyCLIEngineOpts(`--resolve-plugins-relative-to ${examplePluginDirPath} foo.js`, {
+            await verifyESLintOpts(`--resolve-plugins-relative-to ${examplePluginDirPath} foo.js`, {
                 resolvePluginsRelativeTo: examplePluginDirPath
             });
         });
     });
 
     describe("when given an parser name", () => {
-        it("should exit with a fatal error if parser is invalid", () => {
+        it("should exit with a fatal error if parser is invalid", async () => {
             const filePath = getFixturePath("passing.js");
 
-            assert.throws(() => cli.execute(`--no-ignore --parser test111 ${filePath}`), "Cannot find module 'test111'");
+            await stdAssert.rejects(async () => await cli.execute(`--no-ignore --parser test111 ${filePath}`), "Cannot find module 'test111'");
         });
 
-        it("should exit with no error if parser is valid", () => {
+        it("should exit with no error if parser is valid", async () => {
             const filePath = getFixturePath("passing.js");
-            const exit = cli.execute(`--no-ignore --parser espree ${filePath}`);
+            const exit = await cli.execute(`--no-ignore --parser espree ${filePath}`);
 
             assert.strictEqual(exit, 0);
         });
     });
 
     describe("when given parser options", () => {
-        it("should exit with error if parser options are invalid", () => {
+        it("should exit with error if parser options are invalid", async () => {
             const filePath = getFixturePath("passing.js");
-            const exit = cli.execute(`--no-ignore --parser-options test111 ${filePath}`);
+            const exit = await cli.execute(`--no-ignore --parser-options test111 ${filePath}`);
 
             assert.strictEqual(exit, 2);
         });
 
-        it("should exit with no error if parser is valid", () => {
+        it("should exit with no error if parser is valid", async () => {
             const filePath = getFixturePath("passing.js");
-            const exit = cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`);
+            const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`);
 
             assert.strictEqual(exit, 0);
         });
 
-        it("should exit with an error on ecmaVersion 7 feature in ecmaVersion 6", () => {
+        it("should exit with an error on ecmaVersion 7 feature in ecmaVersion 6", async () => {
             const filePath = getFixturePath("passing-es7.js");
-            const exit = cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`);
+            const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:6 ${filePath}`);
 
             assert.strictEqual(exit, 1);
         });
 
-        it("should exit with no error on ecmaVersion 7 feature in ecmaVersion 7", () => {
+        it("should exit with no error on ecmaVersion 7 feature in ecmaVersion 7", async () => {
             const filePath = getFixturePath("passing-es7.js");
-            const exit = cli.execute(`--no-ignore --parser-options=ecmaVersion:7 ${filePath}`);
+            const exit = await cli.execute(`--no-ignore --parser-options=ecmaVersion:7 ${filePath}`);
 
             assert.strictEqual(exit, 0);
         });
 
-        it("should exit with no error on ecmaVersion 7 feature with config ecmaVersion 6 and command line ecmaVersion 7", () => {
+        it("should exit with no error on ecmaVersion 7 feature with config ecmaVersion 6 and command line ecmaVersion 7", async () => {
             const configPath = getFixturePath("configurations", "es6.json");
             const filePath = getFixturePath("passing-es7.js");
-            const exit = cli.execute(`--no-ignore --config ${configPath} --parser-options=ecmaVersion:7 ${filePath}`);
+            const exit = await cli.execute(`--no-ignore --config ${configPath} --parser-options=ecmaVersion:7 ${filePath}`);
 
             assert.strictEqual(exit, 0);
         });
     });
 
     describe("when given the max-warnings flag", () => {
-        it("should not change exit code if warning count under threshold", () => {
+        it("should not change exit code if warning count under threshold", async () => {
             const filePath = getFixturePath("max-warnings");
-            const exitCode = cli.execute(`--no-ignore --max-warnings 10 ${filePath}`);
+            const exitCode = await cli.execute(`--no-ignore --max-warnings 10 ${filePath}`);
 
             assert.strictEqual(exitCode, 0);
         });
 
-        it("should exit with exit code 1 if warning count exceeds threshold", () => {
+        it("should exit with exit code 1 if warning count exceeds threshold", async () => {
             const filePath = getFixturePath("max-warnings");
-            const exitCode = cli.execute(`--no-ignore --max-warnings 5 ${filePath}`);
+            const exitCode = await cli.execute(`--no-ignore --max-warnings 5 ${filePath}`);
 
             assert.strictEqual(exitCode, 1);
             assert.ok(log.error.calledOnce);
             assert.include(log.error.getCall(0).args[0], "ESLint found too many warnings");
         });
 
-        it("should not change exit code if warning count equals threshold", () => {
+        it("should not change exit code if warning count equals threshold", async () => {
             const filePath = getFixturePath("max-warnings");
-            const exitCode = cli.execute(`--no-ignore --max-warnings 6 ${filePath}`);
+            const exitCode = await cli.execute(`--no-ignore --max-warnings 6 ${filePath}`);
 
             assert.strictEqual(exitCode, 0);
         });
 
-        it("should not change exit code if flag is not specified and there are warnings", () => {
+        it("should not change exit code if flag is not specified and there are warnings", async () => {
             const filePath = getFixturePath("max-warnings");
-            const exitCode = cli.execute(filePath);
+            const exitCode = await cli.execute(filePath);
 
             assert.strictEqual(exitCode, 0);
         });
@@ -787,58 +792,51 @@ describe("cli", () => {
             sinon.verifyAndRestore();
         });
 
-        it("should pass allowInlineConfig:true to CLIEngine when --no-inline-config is used", () => {
+        it("should pass allowInlineConfig:false to ESLint when --no-inline-config is used", async () => {
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: false }));
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: false }));
 
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({
+            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+            sinon.stub(fakeESLint.prototype, "lintFiles").returns([{
+                filePath: "./foo.js",
+                output: "bar",
+                messages: [
+                    {
+                        severity: 2,
+                        message: "Fake message"
+                    }
+                ],
                 errorCount: 1,
-                warningCount: 0,
-                results: [{
-                    filePath: "./foo.js",
-                    output: "bar",
-                    messages: [
-                        {
-                            severity: 2,
-                            message: "Fake message"
-                        }
-                    ]
-                }]
-            });
-            sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done");
-            fakeCLIEngine.outputFixes = sinon.stub();
+                warningCount: 0
+            }]);
+            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+            fakeESLint.outputFixes = sinon.stub();
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            localCLI.execute("--no-inline-config .");
+            await localCLI.execute("--no-inline-config .");
         });
 
-        it("should not error and allowInlineConfig should be true by default", () => {
+        it("should not error and allowInlineConfig should be true by default", async () => {
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: true }));
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ allowInlineConfig: true }));
 
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({
-                errorCount: 0,
-                warningCount: 0,
-                results: []
-            });
-            sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done");
-            sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map());
-            fakeCLIEngine.outputFixes = sinon.stub();
+            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+            sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+            fakeESLint.outputFixes = sinon.stub();
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute(".");
+            const exitCode = await localCLI.execute(".");
 
             assert.strictEqual(exitCode, 0);
 
@@ -853,119 +851,108 @@ describe("cli", () => {
             sinon.verifyAndRestore();
         });
 
-        it("should pass fix:true to CLIEngine when executing on files", () => {
+        it("should pass fix:true to ESLint when executing on files", async () => {
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
 
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({
-                errorCount: 0,
-                warningCount: 0,
-                results: []
-            });
-            sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done");
-            sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map());
-            fakeCLIEngine.outputFixes = sinon.mock().once();
+            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+            sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+            fakeESLint.outputFixes = sinon.mock().once();
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute("--fix .");
+            const exitCode = await localCLI.execute("--fix .");
 
             assert.strictEqual(exitCode, 0);
 
         });
 
 
-        it("should rewrite files when in fix mode", () => {
+        it("should rewrite files when in fix mode", async () => {
 
-            const report = {
+            const report = [{
+                filePath: "./foo.js",
+                output: "bar",
+                messages: [
+                    {
+                        severity: 2,
+                        message: "Fake message"
+                    }
+                ],
                 errorCount: 1,
-                warningCount: 0,
-                results: [{
-                    filePath: "./foo.js",
-                    output: "bar",
-                    messages: [
-                        {
-                            severity: 2,
-                            message: "Fake message"
-                        }
-                    ]
-                }]
-            };
+                warningCount: 0
+            }];
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
 
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns(report);
-            sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done");
-            sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map());
-            fakeCLIEngine.outputFixes = sinon.mock().withExactArgs(report);
+            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+            sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+            fakeESLint.outputFixes = sinon.mock().withExactArgs(report);
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute("--fix .");
+            const exitCode = await localCLI.execute("--fix .");
 
             assert.strictEqual(exitCode, 1);
 
         });
 
-        it("should provide fix predicate and rewrite files when in fix mode and quiet mode", () => {
+        it("should provide fix predicate and rewrite files when in fix mode and quiet mode", async () => {
 
-            const report = {
+            const report = [{
+                filePath: "./foo.js",
+                output: "bar",
+                messages: [
+                    {
+                        severity: 1,
+                        message: "Fake message"
+                    }
+                ],
                 errorCount: 0,
-                warningCount: 1,
-                results: [{
-                    filePath: "./foo.js",
-                    output: "bar",
-                    messages: [
-                        {
-                            severity: 1,
-                            message: "Fake message"
-                        }
-                    ]
-                }]
-            };
+                warningCount: 1
+            }];
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
 
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns(report);
-            sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done");
-            sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map());
-            fakeCLIEngine.getErrorResults = sinon.stub().returns([]);
-            fakeCLIEngine.outputFixes = sinon.mock().withExactArgs(report);
+            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+            sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+            fakeESLint.getErrorResults = sinon.stub().returns([]);
+            fakeESLint.outputFixes = sinon.mock().withExactArgs(report);
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute("--fix --quiet .");
+            const exitCode = await localCLI.execute("--fix --quiet .");
 
             assert.strictEqual(exitCode, 0);
 
         });
 
-        it("should not call CLIEngine and return 1 when executing on text", () => {
+        it("should not call ESLint and return 2 when executing on text", async () => {
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().never();
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().never();
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute("--fix .", "foo = bar;");
+            const exitCode = await localCLI.execute("--fix .", "foo = bar;");
 
             assert.strictEqual(exitCode, 2);
         });
@@ -979,212 +966,193 @@ describe("cli", () => {
             sinon.verifyAndRestore();
         });
 
-        it("should pass fix:true to CLIEngine when executing on files", () => {
+        it("should pass fix:true to ESLint when executing on files", async () => {
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
 
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({
-                errorCount: 0,
-                warningCount: 0,
-                results: []
-            });
-            sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done");
-            sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map());
-            fakeCLIEngine.outputFixes = sinon.mock().never();
+            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+            sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+            fakeESLint.outputFixes = sinon.mock().never();
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute("--fix-dry-run .");
+            const exitCode = await localCLI.execute("--fix-dry-run .");
 
             assert.strictEqual(exitCode, 0);
 
         });
 
-        it("should pass fixTypes to CLIEngine when --fix-type is passed", () => {
+        it("should pass fixTypes to ESLint when --fix-type is passed", async () => {
 
-            const expectedCLIEngineOptions = {
+            const expectedESLintOptions = {
                 fix: true,
                 fixTypes: ["suggestion"]
             };
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match(expectedCLIEngineOptions));
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().withExactArgs(sinon.match(expectedESLintOptions));
 
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns({
-                errorCount: 0,
-                warningCount: 0,
-                results: []
-            });
-            sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done");
-            sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map());
-            fakeCLIEngine.outputFixes = sinon.stub();
+            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+            sinon.stub(fakeESLint.prototype, "lintFiles").returns([]);
+            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+            fakeESLint.outputFixes = sinon.stub();
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute("--fix-dry-run --fix-type suggestion .");
+            const exitCode = await localCLI.execute("--fix-dry-run --fix-type suggestion .");
 
             assert.strictEqual(exitCode, 0);
         });
 
-        it("should not rewrite files when in fix-dry-run mode", () => {
+        it("should not rewrite files when in fix-dry-run mode", async () => {
 
-            const report = {
+            const report = [{
+                filePath: "./foo.js",
+                output: "bar",
+                messages: [
+                    {
+                        severity: 2,
+                        message: "Fake message"
+                    }
+                ],
                 errorCount: 1,
-                warningCount: 0,
-                results: [{
-                    filePath: "./foo.js",
-                    output: "bar",
-                    messages: [
-                        {
-                            severity: 2,
-                            message: "Fake message"
-                        }
-                    ]
-                }]
-            };
+                warningCount: 0
+            }];
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
 
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns(report);
-            sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done");
-            sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map());
-            fakeCLIEngine.outputFixes = sinon.mock().never();
+            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+            sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+            fakeESLint.outputFixes = sinon.mock().never();
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute("--fix-dry-run .");
+            const exitCode = await localCLI.execute("--fix-dry-run .");
 
             assert.strictEqual(exitCode, 1);
 
         });
 
-        it("should provide fix predicate when in fix-dry-run mode and quiet mode", () => {
+        it("should provide fix predicate when in fix-dry-run mode and quiet mode", async () => {
 
-            const report = {
+            const report = [{
+                filePath: "./foo.js",
+                output: "bar",
+                messages: [
+                    {
+                        severity: 1,
+                        message: "Fake message"
+                    }
+                ],
                 errorCount: 0,
-                warningCount: 1,
-                results: [{
-                    filePath: "./foo.js",
-                    output: "bar",
-                    messages: [
-                        {
-                            severity: 1,
-                            message: "Fake message"
-                        }
-                    ]
-                }]
-            };
+                warningCount: 1
+            }];
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: sinon.match.func }));
 
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnFiles").returns(report);
-            sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done");
-            sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map());
-            fakeCLIEngine.getErrorResults = sinon.stub().returns([]);
-            fakeCLIEngine.outputFixes = sinon.mock().never();
+            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+            sinon.stub(fakeESLint.prototype, "lintFiles").returns(report);
+            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+            fakeESLint.getErrorResults = sinon.stub().returns([]);
+            fakeESLint.outputFixes = sinon.mock().never();
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute("--fix-dry-run --quiet .");
+            const exitCode = await localCLI.execute("--fix-dry-run --quiet .");
 
             assert.strictEqual(exitCode, 0);
 
         });
 
-        it("should allow executing on text", () => {
+        it("should allow executing on text", async () => {
 
-            const report = {
+            const report = [{
+                filePath: "./foo.js",
+                output: "bar",
+                messages: [
+                    {
+                        severity: 2,
+                        message: "Fake message"
+                    }
+                ],
                 errorCount: 1,
-                warningCount: 0,
-                results: [{
-                    filePath: "./foo.js",
-                    output: "bar",
-                    messages: [
-                        {
-                            severity: 2,
-                            message: "Fake message"
-                        }
-                    ]
-                }]
-            };
+                warningCount: 0
+            }];
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().withExactArgs(sinon.match({ fix: true }));
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().withExactArgs(sinon.match({ fix: true }));
 
-            Object.defineProperties(fakeCLIEngine.prototype, Object.getOwnPropertyDescriptors(CLIEngine.prototype));
-            sinon.stub(fakeCLIEngine.prototype, "executeOnText").returns(report);
-            sinon.stub(fakeCLIEngine.prototype, "getFormatter").returns(() => "done");
-            sinon.stub(fakeCLIEngine.prototype, "getRules").returns(new Map());
-            fakeCLIEngine.outputFixes = sinon.mock().never();
+            Object.defineProperties(fakeESLint.prototype, Object.getOwnPropertyDescriptors(ESLint.prototype));
+            sinon.stub(fakeESLint.prototype, "lintText").returns(report);
+            sinon.stub(fakeESLint.prototype, "loadFormatter").returns({ format: () => "done" });
+            fakeESLint.outputFixes = sinon.mock().never();
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute("--fix-dry-run .", "foo = bar;");
+            const exitCode = await localCLI.execute("--fix-dry-run .", "foo = bar;");
 
             assert.strictEqual(exitCode, 1);
         });
 
-        it("should not call CLIEngine and return 1 when used with --fix", () => {
+        it("should not call ESLint and return 2 when used with --fix", async () => {
 
-            // create a fake CLIEngine to test with
-            const fakeCLIEngine = sinon.mock().never();
+            // create a fake ESLint class to test with
+            const fakeESLint = sinon.mock().never();
 
             localCLI = proxyquire("../../lib/cli", {
-                "./cli-engine/index": { CLIEngine: fakeCLIEngine },
+                "./eslint": { ESLint: fakeESLint },
                 "./shared/logging": log
             });
 
-            const exitCode = localCLI.execute("--fix --fix-dry-run .", "foo = bar;");
+            const exitCode = await localCLI.execute("--fix --fix-dry-run .", "foo = bar;");
 
             assert.strictEqual(exitCode, 2);
         });
     });
 
     describe("when passing --print-config", () => {
-        it("should print out the configuration", () => {
+        it("should print out the configuration", async () => {
             const filePath = getFixturePath("xxxx");
 
-            const exitCode = cli.execute(`--print-config ${filePath}`);
+            const exitCode = await cli.execute(`--print-config ${filePath}`);
 
             assert.isTrue(log.info.calledOnce);
             assert.strictEqual(exitCode, 0);
         });
 
-        it("should error if any positional file arguments are passed", () => {
+        it("should error if any positional file arguments are passed", async () => {
             const filePath1 = getFixturePath("files", "bar.js");
             const filePath2 = getFixturePath("files", "foo.js");
 
-            const exitCode = cli.execute(`--print-config ${filePath1} ${filePath2}`);
+            const exitCode = await cli.execute(`--print-config ${filePath1} ${filePath2}`);
 
             assert.isTrue(log.info.notCalled);
             assert.isTrue(log.error.calledOnce);
             assert.strictEqual(exitCode, 2);
         });
 
-        it("should error out when executing on text", () => {
-            const exitCode = cli.execute("--print-config=myFile.js", "foo = bar;");
+        it("should error out when executing on text", async () => {
+            const exitCode = await cli.execute("--print-config=myFile.js", "foo = bar;");
 
             assert.isTrue(log.info.notCalled);
             assert.isTrue(log.error.calledOnce);
diff --git a/eslint/tests/lib/eslint/eslint.js b/eslint/tests/lib/eslint/eslint.js
new file mode 100644 (file)
index 0000000..fc86a78
--- /dev/null
@@ -0,0 +1,6089 @@
+/**
+ * @fileoverview Tests for the ESLint class.
+ * @author Kai Cataldo
+ * @author Toru Nagashima
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const assert = require("assert");
+const fs = require("fs");
+const os = require("os");
+const path = require("path");
+const escapeStringRegExp = require("escape-string-regexp");
+const fCache = require("file-entry-cache");
+const leche = require("leche");
+const sinon = require("sinon");
+const proxyquire = require("proxyquire").noCallThru().noPreserveCache();
+const shell = require("shelljs");
+const { CascadingConfigArrayFactory } = require("../../../lib/cli-engine/cascading-config-array-factory");
+const hash = require("../../../lib/cli-engine/hash");
+const { unIndent, defineESLintWithInMemoryFileSystem } = require("../../_utils");
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+describe("ESLint", () => {
+    const examplePluginName = "eslint-plugin-example";
+    const examplePluginNameWithNamespace = "@eslint/eslint-plugin-example";
+    const examplePlugin = {
+        rules: {
+            "example-rule": require("../../fixtures/rules/custom-rule"),
+            "make-syntax-error": require("../../fixtures/rules/make-syntax-error-rule")
+        }
+    };
+    const examplePreprocessorName = "eslint-plugin-processor";
+    const originalDir = process.cwd();
+    const fixtureDir = path.resolve(fs.realpathSync(os.tmpdir()), "eslint/fixtures");
+
+    /** @type {import("../../../lib/eslint")["ESLint"]} */
+    let ESLint;
+
+    /**
+     * Returns the path inside of the fixture directory.
+     * @param {...string} args file path segments.
+     * @returns {string} The path inside the fixture directory.
+     * @private
+     */
+    function getFixturePath(...args) {
+        const filepath = path.join(fixtureDir, ...args);
+
+        try {
+            return fs.realpathSync(filepath);
+        } catch (e) {
+            return filepath;
+        }
+    }
+
+    /**
+     * Create the ESLint object by mocking some of the plugins
+     * @param {Object} options options for ESLint
+     * @returns {ESLint} engine object
+     * @private
+     */
+    function eslintWithPlugins(options) {
+        return new ESLint({
+            ...options,
+            plugins: {
+                [examplePluginName]: examplePlugin,
+                [examplePluginNameWithNamespace]: examplePlugin,
+                [examplePreprocessorName]: require("../../fixtures/processors/custom-processor")
+            }
+        });
+    }
+
+    /**
+     * Call the last argument.
+     * @param {any[]} args Arguments
+     * @returns {void}
+     */
+    function callLastArgument(...args) {
+        process.nextTick(args[args.length - 1], null);
+    }
+
+    // copy into clean area so as not to get "infected" by this project's .eslintrc files
+    before(() => {
+        shell.mkdir("-p", fixtureDir);
+        shell.cp("-r", "./tests/fixtures/.", fixtureDir);
+    });
+
+    beforeEach(() => {
+        ({ ESLint } = require("../../../lib/eslint/eslint"));
+    });
+
+    after(() => {
+        shell.rm("-r", fixtureDir);
+    });
+
+    describe("ESLint constructor function", () => {
+        it("the default value of 'options.cwd' should be the current working directory.", async () => {
+            process.chdir(__dirname);
+            try {
+                const engine = new ESLint();
+                const results = await engine.lintFiles("eslint.js");
+
+                assert.strictEqual(path.dirname(results[0].filePath), __dirname);
+            } finally {
+                process.chdir(originalDir);
+            }
+        });
+
+        it("should report one fatal message when given a path by --ignore-path that is not a file when ignore is true.", () => {
+            assert.throws(() => {
+                // eslint-disable-next-line no-new
+                new ESLint({ ignorePath: fixtureDir });
+            }, new RegExp(escapeStringRegExp(`Cannot read .eslintignore file: ${fixtureDir}\nError: EISDIR: illegal operation on a directory, read`), "u"));
+        });
+
+        // https://github.com/eslint/eslint/issues/2380
+        it("should not modify baseConfig when format is specified", () => {
+            const customBaseConfig = { root: true };
+
+            new ESLint({ baseConfig: customBaseConfig }); // eslint-disable-line no-new
+
+            assert.deepStrictEqual(customBaseConfig, { root: true });
+        });
+
+        it("should throw readable messages if removed options are present", () => {
+            assert.throws(
+                () => new ESLint({
+                    cacheFile: "",
+                    configFile: "",
+                    envs: [],
+                    globals: [],
+                    ignorePattern: [],
+                    parser: "",
+                    parserOptions: {},
+                    rules: {},
+                    plugins: []
+                }),
+                new RegExp(escapeStringRegExp([
+                    "Invalid Options:",
+                    "- Unknown options: cacheFile, configFile, envs, globals, ignorePattern, parser, parserOptions, rules",
+                    "- 'cacheFile' has been removed. Please use the 'cacheLocation' option instead.",
+                    "- 'configFile' has been removed. Please use the 'overrideConfigFile' option instead.",
+                    "- 'envs' has been removed. Please use the 'overrideConfig.env' option instead.",
+                    "- 'globals' has been removed. Please use the 'overrideConfig.globals' option instead.",
+                    "- 'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead.",
+                    "- 'parser' has been removed. Please use the 'overrideConfig.parser' option instead.",
+                    "- 'parserOptions' has been removed. Please use the 'overrideConfig.parserOptions' option instead.",
+                    "- 'rules' has been removed. Please use the 'overrideConfig.rules' option instead.",
+                    "- 'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead."
+                ].join("\n")), "u")
+            );
+        });
+
+        it("should throw readable messages if wrong type values are given to options", () => {
+            assert.throws(
+                () => new ESLint({
+                    allowInlineConfig: "",
+                    baseConfig: "",
+                    cache: "",
+                    cacheLocation: "",
+                    cwd: "foo",
+                    errorOnUnmatchedPattern: "",
+                    extensions: "",
+                    fix: "",
+                    fixTypes: ["xyz"],
+                    globInputPaths: "",
+                    ignore: "",
+                    ignorePath: "",
+                    overrideConfig: "",
+                    overrideConfigFile: "",
+                    plugins: "",
+                    reportUnusedDisableDirectives: "",
+                    resolvePluginsRelativeTo: "",
+                    rulePaths: "",
+                    useEslintrc: ""
+                }),
+                new RegExp(escapeStringRegExp([
+                    "Invalid Options:",
+                    "- 'allowInlineConfig' must be a boolean.",
+                    "- 'baseConfig' must be an object or null.",
+                    "- 'cache' must be a boolean.",
+                    "- 'cacheLocation' must be a non-empty string.",
+                    "- 'cwd' must be an absolute path.",
+                    "- 'errorOnUnmatchedPattern' must be a boolean.",
+                    "- 'extensions' must be an array of non-empty strings or null.",
+                    "- 'fix' must be a boolean or a function.",
+                    "- 'fixTypes' must be an array of any of \"problem\", \"suggestion\", and \"layout\".",
+                    "- 'globInputPaths' must be a boolean.",
+                    "- 'ignore' must be a boolean.",
+                    "- 'ignorePath' must be a non-empty string or null.",
+                    "- 'overrideConfig' must be an object or null.",
+                    "- 'overrideConfigFile' must be a non-empty string or null.",
+                    "- 'plugins' must be an object or null.",
+                    "- 'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null.",
+                    "- 'resolvePluginsRelativeTo' must be a non-empty string or null.",
+                    "- 'rulePaths' must be an array of non-empty strings.",
+                    "- 'useElintrc' must be a boolean."
+                ].join("\n")), "u")
+            );
+        });
+
+        it("should throw readable messages if 'plugins' option contains empty key", () => {
+            assert.throws(
+                () => new ESLint({
+                    plugins: {
+                        "eslint-plugin-foo": {},
+                        "eslint-plugin-bar": {},
+                        "": {}
+                    }
+                }),
+                new RegExp(escapeStringRegExp([
+                    "Invalid Options:",
+                    "- 'plugins' must not include an empty string."
+                ].join("\n")), "u")
+            );
+        });
+    });
+
+    describe("lintText()", () => {
+        let eslint;
+
+        it("should report the total and per file errors when using local cwd .eslintrc", async () => {
+            eslint = new ESLint();
+            const results = await eslint.lintText("var foo = 'bar';");
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 5);
+            assert.strictEqual(results[0].messages[0].ruleId, "strict");
+            assert.strictEqual(results[0].messages[1].ruleId, "no-var");
+            assert.strictEqual(results[0].messages[2].ruleId, "no-unused-vars");
+            assert.strictEqual(results[0].messages[3].ruleId, "quotes");
+            assert.strictEqual(results[0].messages[4].ruleId, "eol-last");
+            assert.strictEqual(results[0].fixableErrorCount, 3);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+            assert.strictEqual(results[0].usedDeprecatedRules.length, 0);
+        });
+
+        it("should report the total and per file warnings when using local cwd .eslintrc", async () => {
+            eslint = new ESLint({
+                overrideConfig: {
+                    rules: {
+                        quotes: 1,
+                        "no-var": 1,
+                        "eol-last": 1,
+                        strict: 1,
+                        "no-unused-vars": 1
+                    }
+                }
+            });
+            const results = await eslint.lintText("var foo = 'bar';");
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 5);
+            assert.strictEqual(results[0].messages[0].ruleId, "strict");
+            assert.strictEqual(results[0].messages[1].ruleId, "no-var");
+            assert.strictEqual(results[0].messages[2].ruleId, "no-unused-vars");
+            assert.strictEqual(results[0].messages[3].ruleId, "quotes");
+            assert.strictEqual(results[0].messages[4].ruleId, "eol-last");
+            assert.strictEqual(results[0].fixableErrorCount, 0);
+            assert.strictEqual(results[0].fixableWarningCount, 3);
+            assert.strictEqual(results[0].usedDeprecatedRules.length, 0);
+        });
+
+        it("should report one message when using specific config file", async () => {
+            eslint = new ESLint({
+                overrideConfigFile: "fixtures/configurations/quotes-error.json",
+                useEslintrc: false,
+                cwd: getFixturePath("..")
+            });
+            const results = await eslint.lintText("var foo = 'bar';");
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 1);
+            assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+            assert.strictEqual(results[0].messages[0].output, void 0);
+            assert.strictEqual(results[0].errorCount, 1);
+            assert.strictEqual(results[0].fixableErrorCount, 1);
+            assert.strictEqual(results[0].warningCount, 0);
+            assert.strictEqual(results[0].usedDeprecatedRules.length, 0);
+        });
+
+        it("should report the filename when passed in", async () => {
+            eslint = new ESLint({
+                ignore: false,
+                cwd: getFixturePath()
+            });
+            const options = { filePath: "test.js" };
+            const results = await eslint.lintText("var foo = 'bar';", options);
+
+            assert.strictEqual(results[0].filePath, getFixturePath("test.js"));
+        });
+
+        it("should return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is true", async () => {
+            eslint = new ESLint({
+                ignorePath: getFixturePath(".eslintignore"),
+                cwd: getFixturePath("..")
+            });
+            const options = { filePath: "fixtures/passing.js", warnIgnored: true };
+            const results = await eslint.lintText("var bar = foo;", options);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, getFixturePath("passing.js"));
+            assert.strictEqual(results[0].messages[0].severity, 1);
+            assert.strictEqual(results[0].messages[0].message, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
+            assert.strictEqual(results[0].messages[0].output, void 0);
+            assert.strictEqual(results[0].errorCount, 0);
+            assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fixableErrorCount, 0);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+            assert.strictEqual(results[0].usedDeprecatedRules.length, 0);
+        });
+
+        it("should not return a warning when given a filename by --stdin-filename in excluded files list if warnIgnored is false", async () => {
+            eslint = new ESLint({
+                ignorePath: getFixturePath(".eslintignore"),
+                cwd: getFixturePath("..")
+            });
+            const options = {
+                filePath: "fixtures/passing.js",
+                warnIgnored: false
+            };
+
+            // intentional parsing error
+            const results = await eslint.lintText("va r bar = foo;", options);
+
+            // should not report anything because the file is ignored
+            assert.strictEqual(results.length, 0);
+        });
+
+        it("should suppress excluded file warnings by default", async () => {
+            eslint = new ESLint({
+                ignorePath: getFixturePath(".eslintignore"),
+                cwd: getFixturePath("..")
+            });
+            const options = { filePath: "fixtures/passing.js" };
+            const results = await eslint.lintText("var bar = foo;", options);
+
+            // should not report anything because there are no errors
+            assert.strictEqual(results.length, 0);
+        });
+
+        it("should return a message when given a filename by --stdin-filename in excluded files list and ignore is off", async () => {
+            eslint = new ESLint({
+                ignorePath: "fixtures/.eslintignore",
+                cwd: getFixturePath(".."),
+                ignore: false,
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: {
+                        "no-undef": 2
+                    }
+                }
+            });
+            const options = { filePath: "fixtures/passing.js" };
+            const results = await eslint.lintText("var bar = foo;", options);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, getFixturePath("passing.js"));
+            assert.strictEqual(results[0].messages[0].ruleId, "no-undef");
+            assert.strictEqual(results[0].messages[0].severity, 2);
+            assert.strictEqual(results[0].messages[0].output, void 0);
+        });
+
+        it("should return a message and fixed text when in fix mode", async () => {
+            eslint = new ESLint({
+                useEslintrc: false,
+                fix: true,
+                overrideConfig: {
+                    rules: {
+                        semi: 2
+                    }
+                },
+                ignore: false,
+                cwd: getFixturePath()
+            });
+            const options = { filePath: "passing.js" };
+            const results = await eslint.lintText("var bar = foo", options);
+
+            assert.deepStrictEqual(results, [
+                {
+                    filePath: getFixturePath("passing.js"),
+                    messages: [],
+                    errorCount: 0,
+                    warningCount: 0,
+                    fixableErrorCount: 0,
+                    fixableWarningCount: 0,
+                    output: "var bar = foo;",
+                    usedDeprecatedRules: []
+                }
+            ]);
+        });
+
+        it("correctly autofixes semicolon-conflicting-fixes", async () => {
+            eslint = new ESLint({
+                cwd: path.join(fixtureDir, ".."),
+                useEslintrc: false,
+                fix: true
+            });
+            const inputPath = getFixturePath("autofix/semicolon-conflicting-fixes.js");
+            const outputPath = getFixturePath("autofix/semicolon-conflicting-fixes.expected.js");
+            const results = await eslint.lintFiles([inputPath]);
+            const expectedOutput = fs.readFileSync(outputPath, "utf8");
+
+            assert.strictEqual(results[0].output, expectedOutput);
+        });
+
+        it("correctly autofixes return-conflicting-fixes", async () => {
+            eslint = new ESLint({
+                cwd: path.join(fixtureDir, ".."),
+                useEslintrc: false,
+                fix: true
+            });
+            const inputPath = getFixturePath("autofix/return-conflicting-fixes.js");
+            const outputPath = getFixturePath("autofix/return-conflicting-fixes.expected.js");
+            const results = await eslint.lintFiles([inputPath]);
+            const expectedOutput = fs.readFileSync(outputPath, "utf8");
+
+            assert.strictEqual(results[0].output, expectedOutput);
+        });
+
+        describe("Fix Types", () => {
+            it("should throw an error when an invalid fix type is specified", () => {
+                assert.throws(() => {
+                    eslint = new ESLint({
+                        cwd: path.join(fixtureDir, ".."),
+                        useEslintrc: false,
+                        fix: true,
+                        fixTypes: ["layou"]
+                    });
+                }, /'fixTypes' must be an array of any of "problem", "suggestion", and "layout"\./iu);
+            });
+
+            it("should not fix any rules when fixTypes is used without fix", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    fix: false,
+                    fixTypes: ["layout"]
+                });
+                const inputPath = getFixturePath("fix-types/fix-only-semi.js");
+                const results = await eslint.lintFiles([inputPath]);
+
+                assert.strictEqual(results[0].output, void 0);
+            });
+
+            it("should not fix non-style rules when fixTypes has only 'layout'", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    fix: true,
+                    fixTypes: ["layout"]
+                });
+                const inputPath = getFixturePath("fix-types/fix-only-semi.js");
+                const outputPath = getFixturePath("fix-types/fix-only-semi.expected.js");
+                const results = await eslint.lintFiles([inputPath]);
+                const expectedOutput = fs.readFileSync(outputPath, "utf8");
+
+                assert.strictEqual(results[0].output, expectedOutput);
+            });
+
+            it("should not fix style or problem rules when fixTypes has only 'suggestion'", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    fix: true,
+                    fixTypes: ["suggestion"]
+                });
+                const inputPath = getFixturePath("fix-types/fix-only-prefer-arrow-callback.js");
+                const outputPath = getFixturePath("fix-types/fix-only-prefer-arrow-callback.expected.js");
+                const results = await eslint.lintFiles([inputPath]);
+                const expectedOutput = fs.readFileSync(outputPath, "utf8");
+
+                assert.strictEqual(results[0].output, expectedOutput);
+            });
+
+            it("should fix both style and problem rules when fixTypes has 'suggestion' and 'layout'", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    fix: true,
+                    fixTypes: ["suggestion", "layout"]
+                });
+                const inputPath = getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.js");
+                const outputPath = getFixturePath("fix-types/fix-both-semi-and-prefer-arrow-callback.expected.js");
+                const results = await eslint.lintFiles([inputPath]);
+                const expectedOutput = fs.readFileSync(outputPath, "utf8");
+
+                assert.strictEqual(results[0].output, expectedOutput);
+            });
+
+            it("should not throw an error when a rule doesn't have a 'meta' property", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    fix: true,
+                    fixTypes: ["layout"],
+                    rulePaths: [getFixturePath("rules", "fix-types-test")]
+                });
+                const inputPath = getFixturePath("fix-types/ignore-missing-meta.js");
+                const outputPath = getFixturePath("fix-types/ignore-missing-meta.expected.js");
+                const results = await eslint.lintFiles([inputPath]);
+                const expectedOutput = fs.readFileSync(outputPath, "utf8");
+
+                assert.strictEqual(results[0].output, expectedOutput);
+            });
+
+            it("should not throw an error when a rule is loaded after initialization with lintFiles()", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    fix: true,
+                    fixTypes: ["layout"],
+                    plugins: {
+                        test: {
+                            rules: {
+                                "no-program": require(getFixturePath("rules", "fix-types-test", "no-program.js"))
+                            }
+                        }
+                    }
+                });
+                const inputPath = getFixturePath("fix-types/ignore-missing-meta.js");
+                const outputPath = getFixturePath("fix-types/ignore-missing-meta.expected.js");
+                const results = await eslint.lintFiles([inputPath]);
+                const expectedOutput = fs.readFileSync(outputPath, "utf8");
+
+                assert.strictEqual(results[0].output, expectedOutput);
+            });
+
+            it("should not throw an error when a rule is loaded after initialization with lintText()", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    fix: true,
+                    fixTypes: ["layout"],
+                    plugins: {
+                        test: {
+                            rules: {
+                                "no-program": require(getFixturePath("rules", "fix-types-test", "no-program.js"))
+                            }
+                        }
+                    }
+                });
+                const inputPath = getFixturePath("fix-types/ignore-missing-meta.js");
+                const outputPath = getFixturePath("fix-types/ignore-missing-meta.expected.js");
+                const results = await eslint.lintText(fs.readFileSync(inputPath, { encoding: "utf8" }), { filePath: inputPath });
+                const expectedOutput = fs.readFileSync(outputPath, "utf8");
+
+                assert.strictEqual(results[0].output, expectedOutput);
+            });
+        });
+
+        it("should return a message and omit fixed text when in fix mode and fixes aren't done", async () => {
+            eslint = new ESLint({
+                useEslintrc: false,
+                fix: true,
+                overrideConfig: {
+                    rules: {
+                        "no-undef": 2
+                    }
+                },
+                ignore: false,
+                cwd: getFixturePath()
+            });
+            const options = { filePath: "passing.js" };
+            const results = await eslint.lintText("var bar = foo", options);
+
+            assert.deepStrictEqual(results, [
+                {
+                    filePath: getFixturePath("passing.js"),
+                    messages: [
+                        {
+                            ruleId: "no-undef",
+                            severity: 2,
+                            messageId: "undef",
+                            message: "'foo' is not defined.",
+                            line: 1,
+                            column: 11,
+                            endLine: 1,
+                            endColumn: 14,
+                            nodeType: "Identifier"
+                        }
+                    ],
+                    errorCount: 1,
+                    warningCount: 0,
+                    fixableErrorCount: 0,
+                    fixableWarningCount: 0,
+                    source: "var bar = foo",
+                    usedDeprecatedRules: []
+                }
+            ]);
+        });
+
+        it("should not delete code if there is a syntax error after trying to autofix.", async () => {
+            eslint = eslintWithPlugins({
+                useEslintrc: false,
+                fix: true,
+                overrideConfig: {
+                    plugins: ["example"],
+                    rules: {
+                        "example/make-syntax-error": "error"
+                    }
+                },
+                ignore: false,
+                cwd: getFixturePath()
+            });
+            const options = { filePath: "test.js" };
+            const results = await eslint.lintText("var bar = foo", options);
+
+            assert.deepStrictEqual(results, [
+                {
+                    filePath: getFixturePath("test.js"),
+                    messages: [
+                        {
+                            ruleId: null,
+                            fatal: true,
+                            severity: 2,
+                            message: "Parsing error: Unexpected token is",
+                            line: 1,
+                            column: 19
+                        }
+                    ],
+                    errorCount: 1,
+                    warningCount: 0,
+                    fixableErrorCount: 0,
+                    fixableWarningCount: 0,
+                    output: "var bar = foothis is a syntax error.",
+                    usedDeprecatedRules: []
+                }
+            ]);
+        });
+
+        it("should not crash even if there are any syntax error since the first time.", async () => {
+            eslint = new ESLint({
+                useEslintrc: false,
+                fix: true,
+                overrideConfig: {
+                    rules: {
+                        "example/make-syntax-error": "error"
+                    }
+                },
+                ignore: false,
+                cwd: getFixturePath()
+            });
+            const options = { filePath: "test.js" };
+            const results = await eslint.lintText("var bar =", options);
+
+            assert.deepStrictEqual(results, [
+                {
+                    filePath: getFixturePath("test.js"),
+                    messages: [
+                        {
+                            ruleId: null,
+                            fatal: true,
+                            severity: 2,
+                            message: "Parsing error: Unexpected token",
+                            line: 1,
+                            column: 10
+                        }
+                    ],
+                    errorCount: 1,
+                    warningCount: 0,
+                    fixableErrorCount: 0,
+                    fixableWarningCount: 0,
+                    source: "var bar =",
+                    usedDeprecatedRules: []
+                }
+            ]);
+        });
+
+        it("should return source code of file in `source` property when errors are present", async () => {
+            eslint = new ESLint({
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: { semi: 2 }
+                }
+            });
+            const results = await eslint.lintText("var foo = 'bar'");
+
+            assert.strictEqual(results[0].source, "var foo = 'bar'");
+        });
+
+        it("should return source code of file in `source` property when warnings are present", async () => {
+            eslint = new ESLint({
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: { semi: 1 }
+                }
+            });
+            const results = await eslint.lintText("var foo = 'bar'");
+
+            assert.strictEqual(results[0].source, "var foo = 'bar'");
+        });
+
+
+        it("should not return a `source` property when no errors or warnings are present", async () => {
+            eslint = new ESLint({
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: { semi: 2 }
+                }
+            });
+            const results = await eslint.lintText("var foo = 'bar';");
+
+            assert.strictEqual(results[0].messages.length, 0);
+            assert.strictEqual(results[0].source, void 0);
+        });
+
+        it("should not return a `source` property when fixes are applied", async () => {
+            eslint = new ESLint({
+                useEslintrc: false,
+                fix: true,
+                overrideConfig: {
+                    rules: {
+                        semi: 2,
+                        "no-unused-vars": 2
+                    }
+                }
+            });
+            const results = await eslint.lintText("var msg = 'hi' + foo\n");
+
+            assert.strictEqual(results[0].source, void 0);
+            assert.strictEqual(results[0].output, "var msg = 'hi' + foo;\n");
+        });
+
+        it("should return a `source` property when a parsing error has occurred", async () => {
+            eslint = new ESLint({
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: { semi: 2 }
+                }
+            });
+            const results = await eslint.lintText("var bar = foothis is a syntax error.\n return bar;");
+
+            assert.deepStrictEqual(results, [
+                {
+                    filePath: "<text>",
+                    messages: [
+                        {
+                            ruleId: null,
+                            fatal: true,
+                            severity: 2,
+                            message: "Parsing error: Unexpected token is",
+                            line: 1,
+                            column: 19
+                        }
+                    ],
+                    errorCount: 1,
+                    warningCount: 0,
+                    fixableErrorCount: 0,
+                    fixableWarningCount: 0,
+                    source: "var bar = foothis is a syntax error.\n return bar;",
+                    usedDeprecatedRules: []
+                }
+            ]);
+        });
+
+        // https://github.com/eslint/eslint/issues/5547
+        it("should respect default ignore rules, even with --no-ignore", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath(),
+                ignore: false
+            });
+            const results = await eslint.lintText("var bar = foo;", { filePath: "node_modules/passing.js", warnIgnored: true });
+            const expectedMsg = "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, getFixturePath("node_modules/passing.js"));
+            assert.strictEqual(results[0].messages[0].message, expectedMsg);
+        });
+
+        describe('plugin shorthand notation ("@scope" for "@scope/eslint-plugin")', () => {
+            const Module = require("module");
+            let originalFindPath = null;
+
+            /* eslint-disable no-underscore-dangle */
+            before(() => {
+                originalFindPath = Module._findPath;
+                Module._findPath = function(id, ...otherArgs) {
+                    if (id === "@scope/eslint-plugin") {
+                        return path.resolve(__dirname, "../../fixtures/plugin-shorthand/basic/node_modules/@scope/eslint-plugin/index.js");
+                    }
+                    return originalFindPath.call(this, id, ...otherArgs);
+                };
+            });
+            after(() => {
+                Module._findPath = originalFindPath;
+            });
+            /* eslint-enable no-underscore-dangle */
+
+            it("should resolve 'plugins:[\"@scope\"]' to 'node_modules/@scope/eslint-plugin'.", async () => {
+                eslint = new ESLint({ cwd: getFixturePath("plugin-shorthand/basic") });
+                const [result] = await eslint.lintText("var x = 0", { filePath: "index.js" });
+
+                assert.strictEqual(result.filePath, getFixturePath("plugin-shorthand/basic/index.js"));
+                assert.strictEqual(result.messages[0].ruleId, "@scope/rule");
+                assert.strictEqual(result.messages[0].message, "OK");
+            });
+
+            it("should resolve 'extends:[\"plugin:@scope/recommended\"]' to 'node_modules/@scope/eslint-plugin'.", async () => {
+                eslint = new ESLint({ cwd: getFixturePath("plugin-shorthand/extends") });
+                const [result] = await eslint.lintText("var x = 0", { filePath: "index.js" });
+
+                assert.strictEqual(result.filePath, getFixturePath("plugin-shorthand/extends/index.js"));
+                assert.strictEqual(result.messages[0].ruleId, "@scope/rule");
+                assert.strictEqual(result.messages[0].message, "OK");
+            });
+        });
+
+        it("should warn when deprecated rules are found in a config", async () => {
+            eslint = new ESLint({
+                cwd: originalDir,
+                useEslintrc: false,
+                overrideConfigFile: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml"
+            });
+            const [result] = await eslint.lintText("foo");
+
+            assert.deepStrictEqual(
+                result.usedDeprecatedRules,
+                [{ ruleId: "indent-legacy", replacedBy: ["indent"] }]
+            );
+        });
+
+        it("should throw if non-string value is given to 'code' parameter", async () => {
+            eslint = new ESLint();
+            await assert.rejects(() => eslint.lintText(100), /'code' must be a string/u);
+        });
+
+        it("should throw if non-object value is given to 'options' parameter", async () => {
+            eslint = new ESLint();
+            await assert.rejects(() => eslint.lintText("var a = 0", "foo.js"), /'options' must be an object, null, or undefined/u);
+        });
+
+        it("should throw if 'options' argument contains unknown key", async () => {
+            eslint = new ESLint();
+            await assert.rejects(() => eslint.lintText("var a = 0", { filename: "foo.js" }), /'options' must not include the unknown option 'filename'/u);
+        });
+
+        it("should throw if non-string value is given to 'options.filePath' option", async () => {
+            eslint = new ESLint();
+            await assert.rejects(() => eslint.lintText("var a = 0", { filePath: "" }), /'options.filePath' must be a non-empty string or undefined/u);
+        });
+
+        it("should throw if non-boolean value is given to 'options.warnIgnored' option", async () => {
+            eslint = new ESLint();
+            await assert.rejects(() => eslint.lintText("var a = 0", { warnIgnored: "" }), /'options.warnIgnored' must be a boolean or undefined/u);
+        });
+    });
+
+    describe("lintFiles()", () => {
+
+        /** @type {InstanceType<import("../../../lib/eslint")["ESLint"]>} */
+        let eslint;
+
+        it("should use correct parser when custom parser is specified", async () => {
+            eslint = new ESLint({
+                cwd: originalDir,
+                ignore: false
+            });
+            const filePath = path.resolve(__dirname, "../../fixtures/configurations/parser/custom.js");
+            const results = await eslint.lintFiles([filePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 1);
+            assert.strictEqual(results[0].messages[0].message, "Parsing error: Boom!");
+        });
+
+        it("should report zero messages when given a config file and a valid file", async () => {
+            eslint = new ESLint({
+                cwd: originalDir,
+                overrideConfigFile: ".eslintrc.js"
+            });
+            const results = await eslint.lintFiles(["lib/**/cli*.js"]);
+
+            assert.strictEqual(results.length, 2);
+            assert.strictEqual(results[0].messages.length, 0);
+            assert.strictEqual(results[1].messages.length, 0);
+        });
+
+        it("should handle multiple patterns with overlapping files", async () => {
+            eslint = new ESLint({
+                cwd: originalDir,
+                overrideConfigFile: ".eslintrc.js"
+            });
+            const results = await eslint.lintFiles(["lib/**/cli*.js", "lib/cli.?s", "lib/{cli,cli-engine/cli-engine}.js"]);
+
+            assert.strictEqual(results.length, 2);
+            assert.strictEqual(results[0].messages.length, 0);
+            assert.strictEqual(results[1].messages.length, 0);
+        });
+
+        it("should report zero messages when given a config file and a valid file and espree as parser", async () => {
+            eslint = new ESLint({
+                overrideConfig: {
+                    parser: "espree",
+                    parserOptions: {
+                        ecmaVersion: 2020
+                    }
+                },
+                useEslintrc: false
+            });
+            const results = await eslint.lintFiles(["lib/cli.js"]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should report zero messages when given a config file and a valid file and esprima as parser", async () => {
+            eslint = new ESLint({
+                overrideConfig: {
+                    parser: "esprima"
+                },
+                useEslintrc: false,
+                ignore: false
+            });
+            const results = await eslint.lintFiles(["tests/fixtures/passing.js"]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should throw an error when given a config file and a valid file and invalid parser", async () => {
+            eslint = new ESLint({
+                overrideConfig: {
+                    parser: "test11"
+                },
+                useEslintrc: false
+            });
+
+            await assert.rejects(async () => await eslint.lintFiles(["lib/cli.js"]), /Cannot find module 'test11'/u);
+        });
+
+        it("should report zero messages when given a directory with a .js2 file", async () => {
+            eslint = new ESLint({
+                cwd: path.join(fixtureDir, ".."),
+                extensions: [".js2"]
+            });
+            const results = await eslint.lintFiles([getFixturePath("files/foo.js2")]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should fall back to defaults when extensions is set to an empty array", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath("configurations"),
+                overrideConfigFile: getFixturePath("configurations", "quotes-error.json"),
+                extensions: []
+            });
+            const results = await eslint.lintFiles([getFixturePath("single-quoted.js")]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 1);
+            assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+            assert.strictEqual(results[0].messages[0].severity, 2);
+            assert.strictEqual(results[0].errorCount, 1);
+            assert.strictEqual(results[0].warningCount, 0);
+            assert.strictEqual(results[0].fixableErrorCount, 1);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+        });
+
+        it("should report zero messages when given a directory with a .js and a .js2 file", async () => {
+            eslint = new ESLint({
+                extensions: [".js", ".js2"],
+                ignore: false,
+                cwd: getFixturePath("..")
+            });
+            const results = await eslint.lintFiles(["fixtures/files/"]);
+
+            assert.strictEqual(results.length, 2);
+            assert.strictEqual(results[0].messages.length, 0);
+            assert.strictEqual(results[1].messages.length, 0);
+        });
+
+        it("should report zero messages when given a '**' pattern with a .js and a .js2 file", async () => {
+            eslint = new ESLint({
+                extensions: [".js", ".js2"],
+                ignore: false,
+                cwd: path.join(fixtureDir, "..")
+            });
+            const results = await eslint.lintFiles(["fixtures/files/*"]);
+
+            assert.strictEqual(results.length, 2);
+            assert.strictEqual(results[0].messages.length, 0);
+            assert.strictEqual(results[1].messages.length, 0);
+        });
+
+        it("should resolve globs when 'globInputPaths' option is true", async () => {
+            eslint = new ESLint({
+                extensions: [".js", ".js2"],
+                ignore: false,
+                cwd: getFixturePath("..")
+            });
+            const results = await eslint.lintFiles(["fixtures/files/*"]);
+
+            assert.strictEqual(results.length, 2);
+            assert.strictEqual(results[0].messages.length, 0);
+            assert.strictEqual(results[1].messages.length, 0);
+        });
+
+        it("should not resolve globs when 'globInputPaths' option is false", async () => {
+            eslint = new ESLint({
+                extensions: [".js", ".js2"],
+                ignore: false,
+                cwd: getFixturePath(".."),
+                globInputPaths: false
+            });
+
+            await assert.rejects(async () => {
+                await eslint.lintFiles(["fixtures/files/*"]);
+            }, /No files matching 'fixtures\/files\/\*' were found \(glob was disabled\)\./u);
+        });
+
+        it("should report on all files passed explicitly, even if ignored by default", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath("cli-engine")
+            });
+            const results = await eslint.lintFiles(["node_modules/foo.js"]);
+            const expectedMsg = "File ignored by default. Use \"--ignore-pattern '!node_modules/*'\" to override.";
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].errorCount, 0);
+            assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fixableErrorCount, 0);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+            assert.strictEqual(results[0].messages[0].message, expectedMsg);
+        });
+
+        it("should report on globs with explicit inclusion of dotfiles, even though ignored by default", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath("cli-engine"),
+                overrideConfig: {
+                    rules: {
+                        quotes: [2, "single"]
+                    }
+                }
+            });
+            const results = await eslint.lintFiles(["hidden/.hiddenfolder/*.js"]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].errorCount, 1);
+            assert.strictEqual(results[0].warningCount, 0);
+            assert.strictEqual(results[0].fixableErrorCount, 1);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+        });
+
+        it("should not check default ignored files without --no-ignore flag", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath("cli-engine")
+            });
+
+            await assert.rejects(async () => {
+                await eslint.lintFiles(["node_modules"]);
+            }, /All files matched by 'node_modules' are ignored\./u);
+        });
+
+        // https://github.com/eslint/eslint/issues/5547
+        it("should not check node_modules files even with --no-ignore flag", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath("cli-engine"),
+                ignore: false
+            });
+
+            await assert.rejects(async () => {
+                await eslint.lintFiles(["node_modules"]);
+            }, /All files matched by 'node_modules' are ignored\./u);
+        });
+
+        it("should not check .hidden files if they are passed explicitly without --no-ignore flag", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath(".."),
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: {
+                        quotes: [2, "single"]
+                    }
+                }
+            });
+            const results = await eslint.lintFiles(["fixtures/files/.bar.js"]);
+            const expectedMsg = "File ignored by default.  Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].errorCount, 0);
+            assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fixableErrorCount, 0);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+            assert.strictEqual(results[0].messages[0].message, expectedMsg);
+        });
+
+        // https://github.com/eslint/eslint/issues/12873
+        it("should not check files within a .hidden folder if they are passed explicitly without the --no-ignore flag", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath("cli-engine"),
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: {
+                        quotes: [2, "single"]
+                    }
+                }
+            });
+            const results = await eslint.lintFiles(["hidden/.hiddenfolder/double-quotes.js"]);
+            const expectedMsg = "File ignored by default.  Use a negated ignore pattern (like \"--ignore-pattern '!<relative/path/to/filename>'\") to override.";
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].errorCount, 0);
+            assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fixableErrorCount, 0);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+            assert.strictEqual(results[0].messages[0].message, expectedMsg);
+        });
+
+        it("should check .hidden files if they are passed explicitly with --no-ignore flag", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath(".."),
+                ignore: false,
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: {
+                        quotes: [2, "single"]
+                    }
+                }
+            });
+            const results = await eslint.lintFiles(["fixtures/files/.bar.js"]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].warningCount, 0);
+            assert.strictEqual(results[0].errorCount, 1);
+            assert.strictEqual(results[0].fixableErrorCount, 1);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+            assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+        });
+
+        it("should check .hidden files if they are unignored with an --ignore-pattern", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath("cli-engine"),
+                ignore: true,
+                useEslintrc: false,
+                overrideConfig: {
+                    ignorePatterns: "!.hidden*",
+                    rules: {
+                        quotes: [2, "single"]
+                    }
+                }
+            });
+            const results = await eslint.lintFiles(["hidden/"]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].warningCount, 0);
+            assert.strictEqual(results[0].errorCount, 1);
+            assert.strictEqual(results[0].fixableErrorCount, 1);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+            assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+        });
+
+        it("should report zero messages when given a pattern with a .js and a .js2 file", async () => {
+            eslint = new ESLint({
+                extensions: [".js", ".js2"],
+                ignore: false,
+                cwd: path.join(fixtureDir, "..")
+            });
+            const results = await eslint.lintFiles(["fixtures/files/*.?s*"]);
+
+            assert.strictEqual(results.length, 2);
+            assert.strictEqual(results[0].messages.length, 0);
+            assert.strictEqual(results[1].messages.length, 0);
+        });
+
+        it("should return one error message when given a config with rules with options and severity level set to error", async () => {
+            eslint = new ESLint({
+                cwd: getFixturePath("configurations"),
+                overrideConfigFile: getFixturePath("configurations", "quotes-error.json")
+            });
+            const results = await eslint.lintFiles([getFixturePath("single-quoted.js")]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 1);
+            assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+            assert.strictEqual(results[0].messages[0].severity, 2);
+            assert.strictEqual(results[0].errorCount, 1);
+            assert.strictEqual(results[0].warningCount, 0);
+            assert.strictEqual(results[0].fixableErrorCount, 1);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+        });
+
+        it("should return 3 messages when given a config file and a directory of 3 valid files", async () => {
+            eslint = new ESLint({
+                cwd: path.join(fixtureDir, ".."),
+                overrideConfigFile: getFixturePath("configurations", "semi-error.json")
+            });
+            const results = await eslint.lintFiles([getFixturePath("formatters")]);
+
+            assert.strictEqual(results.length, 3);
+            assert.strictEqual(results[0].messages.length, 0);
+            assert.strictEqual(results[1].messages.length, 0);
+            assert.strictEqual(results[2].messages.length, 0);
+            assert.strictEqual(results[0].errorCount, 0);
+            assert.strictEqual(results[0].warningCount, 0);
+            assert.strictEqual(results[0].fixableErrorCount, 0);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+            assert.strictEqual(results[1].errorCount, 0);
+            assert.strictEqual(results[1].warningCount, 0);
+            assert.strictEqual(results[1].fixableErrorCount, 0);
+            assert.strictEqual(results[1].fixableWarningCount, 0);
+            assert.strictEqual(results[2].errorCount, 0);
+            assert.strictEqual(results[2].warningCount, 0);
+            assert.strictEqual(results[2].fixableErrorCount, 0);
+            assert.strictEqual(results[2].fixableWarningCount, 0);
+        });
+
+        it("should process when file is given by not specifying extensions", async () => {
+            eslint = new ESLint({
+                ignore: false,
+                cwd: path.join(fixtureDir, "..")
+            });
+            const results = await eslint.lintFiles(["fixtures/files/foo.js2"]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should return zero messages when given a config with environment set to browser", async () => {
+            eslint = new ESLint({
+                cwd: path.join(fixtureDir, ".."),
+                overrideConfigFile: getFixturePath("configurations", "env-browser.json")
+            });
+            const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("globals-browser.js"))]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should return zero messages when given an option to set environment to browser", async () => {
+            eslint = new ESLint({
+                cwd: path.join(fixtureDir, ".."),
+                overrideConfig: {
+                    env: { browser: true },
+                    rules: {
+                        "no-alert": 0,
+                        "no-undef": 2
+                    }
+                }
+            });
+            const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("globals-browser.js"))]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should return zero messages when given a config with environment set to Node.js", async () => {
+            eslint = new ESLint({
+                cwd: path.join(fixtureDir, ".."),
+                overrideConfigFile: getFixturePath("configurations", "env-node.json")
+            });
+            const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("globals-node.js"))]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should not return results from previous call when calling more than once", async () => {
+            eslint = new ESLint({
+                cwd: path.join(fixtureDir, ".."),
+                ignore: false,
+                overrideConfig: {
+                    rules: {
+                        semi: 2
+                    }
+                }
+            });
+            const failFilePath = fs.realpathSync(getFixturePath("missing-semicolon.js"));
+            const passFilePath = fs.realpathSync(getFixturePath("passing.js"));
+
+            let results = await eslint.lintFiles([failFilePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, failFilePath);
+            assert.strictEqual(results[0].messages.length, 1);
+            assert.strictEqual(results[0].messages[0].ruleId, "semi");
+            assert.strictEqual(results[0].messages[0].severity, 2);
+
+            results = await eslint.lintFiles([passFilePath]);
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, passFilePath);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should throw an error when given a directory with all eslint excluded files in the directory", async () => {
+            eslint = new ESLint({
+                ignorePath: getFixturePath(".eslintignore")
+            });
+
+            await assert.rejects(async () => {
+                await eslint.lintFiles([getFixturePath("./cli-engine/")]);
+            }, new RegExp(escapeStringRegExp(`All files matched by '${getFixturePath("./cli-engine/")}' are ignored.`), "u"));
+        });
+
+        it("should throw an error when all given files are ignored", async () => {
+            await assert.rejects(async () => {
+                await eslint.lintFiles(["tests/fixtures/cli-engine/"]);
+            }, /All files matched by 'tests\/fixtures\/cli-engine\/' are ignored\./u);
+        });
+
+        it("should throw an error when all given files are ignored even with a `./` prefix", async () => {
+            eslint = new ESLint({
+                ignorePath: getFixturePath(".eslintignore")
+            });
+
+            await assert.rejects(async () => {
+                await eslint.lintFiles(["./tests/fixtures/cli-engine/"]);
+            }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u);
+        });
+
+        // https://github.com/eslint/eslint/issues/3788
+        it("should ignore one-level down node_modules when ignore file has 'node_modules/' in it", async () => {
+            eslint = new ESLint({
+                ignorePath: getFixturePath("cli-engine", "nested_node_modules", ".eslintignore"),
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: {
+                        quotes: [2, "double"]
+                    }
+                },
+                cwd: getFixturePath("cli-engine", "nested_node_modules")
+            });
+            const results = await eslint.lintFiles(["."]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].errorCount, 0);
+            assert.strictEqual(results[0].warningCount, 0);
+            assert.strictEqual(results[0].fixableErrorCount, 0);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+        });
+
+        // https://github.com/eslint/eslint/issues/3812
+        it("should ignore all files and throw an error when tests/fixtures/ is in ignore file", async () => {
+            eslint = new ESLint({
+                ignorePath: getFixturePath("cli-engine/.eslintignore2"),
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: {
+                        quotes: [2, "double"]
+                    }
+                }
+            });
+
+            await assert.rejects(async () => {
+                await eslint.lintFiles(["./tests/fixtures/cli-engine/"]);
+            }, /All files matched by '\.\/tests\/fixtures\/cli-engine\/' are ignored\./u);
+        });
+
+        it("should throw an error when all given files are ignored via ignore-pattern", async () => {
+            eslint = new ESLint({
+                overrideConfig: {
+                    ignorePatterns: "tests/fixtures/single-quoted.js"
+                }
+            });
+
+            await assert.rejects(async () => {
+                await eslint.lintFiles(["tests/fixtures/*-quoted.js"]);
+            }, /All files matched by 'tests\/fixtures\/\*-quoted\.js' are ignored\./u);
+        });
+
+        it("should return a warning when an explicitly given file is ignored", async () => {
+            eslint = new ESLint({
+                ignorePath: getFixturePath(".eslintignore"),
+                cwd: getFixturePath()
+            });
+            const filePath = getFixturePath("passing.js");
+            const results = await eslint.lintFiles([filePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, filePath);
+            assert.strictEqual(results[0].messages[0].severity, 1);
+            assert.strictEqual(results[0].messages[0].message, "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to override.");
+            assert.strictEqual(results[0].errorCount, 0);
+            assert.strictEqual(results[0].warningCount, 1);
+            assert.strictEqual(results[0].fixableErrorCount, 0);
+            assert.strictEqual(results[0].fixableWarningCount, 0);
+        });
+
+        it("should return two messages when given a file in excluded files list while ignore is off", async () => {
+            eslint = new ESLint({
+                ignorePath: getFixturePath(".eslintignore"),
+                ignore: false,
+                overrideConfig: {
+                    rules: {
+                        "no-undef": 2
+                    }
+                }
+            });
+            const filePath = fs.realpathSync(getFixturePath("undef.js"));
+            const results = await eslint.lintFiles([filePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, filePath);
+            assert.strictEqual(results[0].messages[0].ruleId, "no-undef");
+            assert.strictEqual(results[0].messages[0].severity, 2);
+            assert.strictEqual(results[0].messages[1].ruleId, "no-undef");
+            assert.strictEqual(results[0].messages[1].severity, 2);
+        });
+
+        it("should return zero messages when executing a file with a shebang", async () => {
+            eslint = new ESLint({
+                ignore: false
+            });
+            const results = await eslint.lintFiles([getFixturePath("shebang.js")]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should give a warning when loading a custom rule that doesn't exist", async () => {
+            eslint = new ESLint({
+                ignore: false,
+                rulePaths: [getFixturePath("rules", "dir1")],
+                overrideConfigFile: getFixturePath("rules", "missing-rule.json")
+            });
+            const results = await eslint.lintFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].messages.length, 1);
+            assert.strictEqual(results[0].messages[0].ruleId, "missing-rule");
+            assert.strictEqual(results[0].messages[0].severity, 2);
+            assert.strictEqual(results[0].messages[0].message, "Definition for rule 'missing-rule' was not found.");
+        });
+
+        it("should throw an error when loading a bad custom rule", async () => {
+            eslint = new ESLint({
+                ignore: false,
+                rulePaths: [getFixturePath("rules", "wrong")],
+                overrideConfigFile: getFixturePath("rules", "eslint.json")
+            });
+
+
+            await assert.rejects(async () => {
+                await eslint.lintFiles([getFixturePath("rules", "test", "test-custom-rule.js")]);
+            }, /Error while loading rule 'custom-rule'/u);
+        });
+
+        it("should return one message when a custom rule matches a file", async () => {
+            eslint = new ESLint({
+                ignore: false,
+                useEslintrc: false,
+                rulePaths: [getFixturePath("rules/")],
+                overrideConfigFile: getFixturePath("rules", "eslint.json")
+            });
+            const filePath = fs.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
+            const results = await eslint.lintFiles([filePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, filePath);
+            assert.strictEqual(results[0].messages.length, 2);
+            assert.strictEqual(results[0].messages[0].ruleId, "custom-rule");
+            assert.strictEqual(results[0].messages[0].severity, 1);
+        });
+
+        it("should load custom rule from the provided cwd", async () => {
+            const cwd = path.resolve(getFixturePath("rules"));
+
+            eslint = new ESLint({
+                ignore: false,
+                cwd,
+                rulePaths: ["./"],
+                overrideConfigFile: "eslint.json"
+            });
+            const filePath = fs.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"));
+            const results = await eslint.lintFiles([filePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, filePath);
+            assert.strictEqual(results[0].messages.length, 2);
+            assert.strictEqual(results[0].messages[0].ruleId, "custom-rule");
+            assert.strictEqual(results[0].messages[0].severity, 1);
+        });
+
+        it("should return messages when multiple custom rules match a file", async () => {
+            eslint = new ESLint({
+                ignore: false,
+                rulePaths: [
+                    getFixturePath("rules", "dir1"),
+                    getFixturePath("rules", "dir2")
+                ],
+                overrideConfigFile: getFixturePath("rules", "multi-rulesdirs.json")
+            });
+            const filePath = fs.realpathSync(getFixturePath("rules", "test-multi-rulesdirs.js"));
+            const results = await eslint.lintFiles([filePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, filePath);
+            assert.strictEqual(results[0].messages.length, 2);
+            assert.strictEqual(results[0].messages[0].ruleId, "no-literals");
+            assert.strictEqual(results[0].messages[0].severity, 2);
+            assert.strictEqual(results[0].messages[1].ruleId, "no-strings");
+            assert.strictEqual(results[0].messages[1].severity, 2);
+        });
+
+        it("should return zero messages when executing without useEslintrc flag", async () => {
+            eslint = new ESLint({
+                ignore: false,
+                useEslintrc: false
+            });
+            const filePath = fs.realpathSync(getFixturePath("missing-semicolon.js"));
+            const results = await eslint.lintFiles([filePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, filePath);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should return zero messages when executing without useEslintrc flag in Node.js environment", async () => {
+            eslint = new ESLint({
+                ignore: false,
+                useEslintrc: false,
+                overrideConfig: {
+                    env: { node: true }
+                }
+            });
+            const filePath = fs.realpathSync(getFixturePath("process-exit.js"));
+            const results = await eslint.lintFiles([filePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, filePath);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should return zero messages and ignore .eslintrc files when executing with no-eslintrc flag", async () => {
+            eslint = new ESLint({
+                ignore: false,
+                useEslintrc: false,
+                overrideConfig: {
+                    env: { node: true }
+                }
+            });
+            const filePath = fs.realpathSync(getFixturePath("eslintrc", "quotes.js"));
+            const results = await eslint.lintFiles([filePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, filePath);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should return zero messages and ignore package.json files when executing with no-eslintrc flag", async () => {
+            eslint = new ESLint({
+                ignore: false,
+                useEslintrc: false,
+                overrideConfig: {
+                    env: { node: true }
+                }
+            });
+            const filePath = fs.realpathSync(getFixturePath("packagejson", "quotes.js"));
+            const results = await eslint.lintFiles([filePath]);
+
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].filePath, filePath);
+            assert.strictEqual(results[0].messages.length, 0);
+        });
+
+        it("should warn when deprecated rules are configured", async () => {
+            eslint = new ESLint({
+                cwd: originalDir,
+                overrideConfigFile: ".eslintrc.js",
+                overrideConfig: {
+                    rules: {
+                        "indent-legacy": 1,
+                        "require-jsdoc": 1,
+                        "valid-jsdoc": 1
+                    }
+                }
+            });
+            const results = await eslint.lintFiles(["lib/cli*.js"]);
+
+            assert.deepStrictEqual(
+                results[0].usedDeprecatedRules,
+                [
+                    { ruleId: "indent-legacy", replacedBy: ["indent"] },
+                    { ruleId: "require-jsdoc", replacedBy: [] },
+                    { ruleId: "valid-jsdoc", replacedBy: [] }
+                ]
+            );
+        });
+
+        it("should not warn when deprecated rules are not configured", async () => {
+            eslint = new ESLint({
+                cwd: originalDir,
+                overrideConfigFile: ".eslintrc.js",
+                overrideConfig: {
+                    rules: { indent: 1, "valid-jsdoc": 0, "require-jsdoc": 0 }
+                }
+            });
+            const results = await eslint.lintFiles(["lib/cli*.js"]);
+
+            assert.deepStrictEqual(results[0].usedDeprecatedRules, []);
+        });
+
+        it("should warn when deprecated rules are found in a config", async () => {
+            eslint = new ESLint({
+                cwd: originalDir,
+                overrideConfigFile: "tests/fixtures/cli-engine/deprecated-rule-config/.eslintrc.yml",
+                useEslintrc: false
+            });
+            const results = await eslint.lintFiles(["lib/cli*.js"]);
+
+            assert.deepStrictEqual(
+                results[0].usedDeprecatedRules,
+                [{ ruleId: "indent-legacy", replacedBy: ["indent"] }]
+            );
+        });
+
+        describe("Fix Mode", () => {
+            it("should return fixed text on multiple files when in fix mode", async () => {
+
+                /**
+                 * Converts CRLF to LF in output.
+                 * This is a workaround for git's autocrlf option on Windows.
+                 * @param {Object} result A result object to convert.
+                 * @returns {void}
+                 */
+                function convertCRLF(result) {
+                    if (result && result.output) {
+                        result.output = result.output.replace(/\r\n/gu, "\n");
+                    }
+                }
+
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    fix: true,
+                    overrideConfig: {
+                        rules: {
+                            semi: 2,
+                            quotes: [2, "double"],
+                            eqeqeq: 2,
+                            "no-undef": 2,
+                            "space-infix-ops": 2
+                        }
+                    }
+                });
+                const results = await eslint.lintFiles([path.resolve(fixtureDir, `${fixtureDir}/fixmode`)]);
+
+                results.forEach(convertCRLF);
+                assert.deepStrictEqual(results, [
+                    {
+                        filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/multipass.js")),
+                        messages: [],
+                        errorCount: 0,
+                        warningCount: 0,
+                        fixableErrorCount: 0,
+                        fixableWarningCount: 0,
+                        output: "true ? \"yes\" : \"no\";\n",
+                        usedDeprecatedRules: []
+                    },
+                    {
+                        filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/ok.js")),
+                        messages: [],
+                        errorCount: 0,
+                        warningCount: 0,
+                        fixableErrorCount: 0,
+                        fixableWarningCount: 0,
+                        usedDeprecatedRules: []
+                    },
+                    {
+                        filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/quotes-semi-eqeqeq.js")),
+                        messages: [
+                            {
+                                column: 9,
+                                line: 2,
+                                endColumn: 11,
+                                endLine: 2,
+                                message: "Expected '===' and instead saw '=='.",
+                                messageId: "unexpected",
+                                nodeType: "BinaryExpression",
+                                ruleId: "eqeqeq",
+                                severity: 2
+                            }
+                        ],
+                        errorCount: 1,
+                        warningCount: 0,
+                        fixableErrorCount: 0,
+                        fixableWarningCount: 0,
+                        output: "var msg = \"hi\";\nif (msg == \"hi\") {\n\n}\n",
+                        usedDeprecatedRules: []
+                    },
+                    {
+                        filePath: fs.realpathSync(path.resolve(fixtureDir, "fixmode/quotes.js")),
+                        messages: [
+                            {
+                                column: 18,
+                                line: 1,
+                                endColumn: 21,
+                                endLine: 1,
+                                messageId: "undef",
+                                message: "'foo' is not defined.",
+                                nodeType: "Identifier",
+                                ruleId: "no-undef",
+                                severity: 2
+                            }
+                        ],
+                        errorCount: 1,
+                        warningCount: 0,
+                        fixableErrorCount: 0,
+                        fixableWarningCount: 0,
+                        output: "var msg = \"hi\" + foo;\n",
+                        usedDeprecatedRules: []
+                    }
+                ]);
+            });
+
+            it("should run autofix even if files are cached without autofix results", async () => {
+                const baseOptions = {
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    overrideConfig: {
+                        rules: {
+                            semi: 2,
+                            quotes: [2, "double"],
+                            eqeqeq: 2,
+                            "no-undef": 2,
+                            "space-infix-ops": 2
+                        }
+                    }
+                };
+
+                eslint = new ESLint(Object.assign({}, baseOptions, { cache: true, fix: false }));
+
+                // Do initial lint run and populate the cache file
+                await eslint.lintFiles([path.resolve(fixtureDir, `${fixtureDir}/fixmode`)]);
+
+                eslint = new ESLint(Object.assign({}, baseOptions, { cache: true, fix: true }));
+                const results = await eslint.lintFiles([path.resolve(fixtureDir, `${fixtureDir}/fixmode`)]);
+
+                assert(results.some(result => result.output));
+            });
+        });
+
+        // These tests have to do with https://github.com/eslint/eslint/issues/963
+
+        describe("configuration hierarchy", () => {
+
+            // Default configuration - blank
+            it("should return zero messages when executing with no .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 0);
+            });
+
+            // No default configuration rules - conf/environments.js (/*eslint-env node*/)
+            it("should return zero messages when executing with no .eslintrc in the Node.js environment", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes-node.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 0);
+            });
+
+            // Project configuration - first level .eslintrc
+            it("should return zero messages when executing with .eslintrc in the Node.js environment", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 0);
+            });
+
+            // Project configuration - first level .eslintrc
+            it("should return zero messages when executing with .eslintrc in the Node.js environment", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/process-exit.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 0);
+            });
+
+            // Project configuration - first level .eslintrc
+            it("should return one message when executing with .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+                assert.strictEqual(results[0].messages[0].severity, 2);
+            });
+
+            // Project configuration - second level .eslintrc
+            it("should return one message when executing with local .eslintrc that overrides parent .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "no-console");
+                assert.strictEqual(results[0].messages[0].severity, 1);
+            });
+
+            // Project configuration - third level .eslintrc
+            it("should return one message when executing with local .eslintrc that overrides parent and grandparent .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/subsubbroken/console-wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+                assert.strictEqual(results[0].messages[0].severity, 1);
+            });
+
+            // Project configuration - first level package.json
+            it("should return one message when executing with package.json", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+                assert.strictEqual(results[0].messages[0].severity, 1);
+            });
+
+            // Project configuration - second level package.json
+            it("should return zero messages when executing with local package.json that overrides parent package.json", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 0);
+            });
+
+            // Project configuration - third level package.json
+            it("should return one message when executing with local package.json that overrides parent and grandparent package.json", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/subdir/subsubdir/subsubsubdir/wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+                assert.strictEqual(results[0].messages[0].severity, 2);
+            });
+
+            // Project configuration - .eslintrc overrides package.json in same directory
+            it("should return one message when executing with .eslintrc that overrides a package.json in the same directory", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/packagejson/wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+                assert.strictEqual(results[0].messages[0].severity, 2);
+            });
+
+            // Command line configuration - --config with first level .eslintrc
+            it("should return two messages when executing with config file that adds to local .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+                assert.strictEqual(results[0].messages[0].severity, 2);
+                assert.strictEqual(results[0].messages[1].ruleId, "semi");
+                assert.strictEqual(results[0].messages[1].severity, 1);
+            });
+
+            // Command line configuration - --config with first level .eslintrc
+            it("should return no messages when executing with config file that overrides local .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 0);
+            });
+
+            // Command line configuration - --config with second level .eslintrc
+            it("should return two messages when executing with config file that adds to local and parent .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: `${fixtureDir}/config-hierarchy/broken/add-conf.yaml`
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "no-console");
+                assert.strictEqual(results[0].messages[0].severity, 1);
+                assert.strictEqual(results[0].messages[1].ruleId, "semi");
+                assert.strictEqual(results[0].messages[1].severity, 1);
+            });
+
+            // Command line configuration - --config with second level .eslintrc
+            it("should return one message when executing with config file that overrides local and parent .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: getFixturePath("config-hierarchy/broken/override-conf.yaml")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/subbroken/console-wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "no-console");
+                assert.strictEqual(results[0].messages[0].severity, 1);
+            });
+
+            // Command line configuration - --config with first level .eslintrc
+            it("should return no messages when executing with config file that overrides local .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: `${fixtureDir}/config-hierarchy/broken/override-conf.yaml`
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 0);
+            });
+
+            // Command line configuration - --rule with --config and first level .eslintrc
+            it("should return one message when executing with command line rule and config file that overrides local .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: getFixturePath("config-hierarchy/broken/override-conf.yaml"),
+                    overrideConfig: {
+                        rules: {
+                            quotes: [1, "double"]
+                        }
+                    }
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(`${fixtureDir}/config-hierarchy/broken/console-wrong-quotes.js`)]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+                assert.strictEqual(results[0].messages[0].severity, 1);
+            });
+
+            // Command line configuration - --rule with --config and first level .eslintrc
+            it("should return one message when executing with command line rule and config file that overrides local .eslintrc", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: getFixturePath("/config-hierarchy/broken/override-conf.yaml"),
+                    overrideConfig: {
+                        rules: {
+                            quotes: [1, "double"]
+                        }
+                    }
+                });
+                const results = await eslint.lintFiles([getFixturePath("config-hierarchy/broken/console-wrong-quotes.js")]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "quotes");
+                assert.strictEqual(results[0].messages[0].severity, 1);
+            });
+        });
+
+        describe("plugins", () => {
+            it("should return two messages when executing with config file that specifies a plugin", async () => {
+                eslint = eslintWithPlugins({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: getFixturePath("configurations", "plugins-with-prefix.json"),
+                    useEslintrc: false
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("rules", "test/test-custom-rule.js"))]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "example/example-rule");
+            });
+
+            it("should return two messages when executing with config file that specifies a plugin with namespace", async () => {
+                eslint = eslintWithPlugins({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: getFixturePath("configurations", "plugins-with-prefix-and-namespace.json"),
+                    useEslintrc: false
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "@eslint/example/example-rule");
+            });
+
+            it("should return two messages when executing with config file that specifies a plugin without prefix", async () => {
+                eslint = eslintWithPlugins({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: getFixturePath("configurations", "plugins-without-prefix.json"),
+                    useEslintrc: false
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "example/example-rule");
+            });
+
+            it("should return two messages when executing with config file that specifies a plugin without prefix and with namespace", async () => {
+                eslint = eslintWithPlugins({
+                    cwd: path.join(fixtureDir, ".."),
+                    overrideConfigFile: getFixturePath("configurations", "plugins-without-prefix-with-namespace.json"),
+                    useEslintrc: false
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "@eslint/example/example-rule");
+            });
+
+            it("should return two messages when executing with cli option that specifies a plugin", async () => {
+                eslint = eslintWithPlugins({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    overrideConfig: {
+                        plugins: ["example"],
+                        rules: { "example/example-rule": 1 }
+                    }
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "example/example-rule");
+            });
+
+            it("should return two messages when executing with cli option that specifies preloaded plugin", async () => {
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    overrideConfig: {
+                        plugins: ["test"],
+                        rules: { "test/example-rule": 1 }
+                    },
+                    plugins: {
+                        "eslint-plugin-test": { rules: { "example-rule": require("../../fixtures/rules/custom-rule") } }
+                    }
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("rules", "test", "test-custom-rule.js"))]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "test/example-rule");
+            });
+
+            it("should load plugins from the `loadPluginsRelativeTo` directory, if specified", async () => {
+                eslint = new ESLint({
+                    resolvePluginsRelativeTo: getFixturePath("plugins"),
+                    baseConfig: {
+                        plugins: ["with-rules"],
+                        rules: { "with-rules/rule1": "error" }
+                    },
+                    useEslintrc: false
+                });
+                const results = await eslint.lintText("foo");
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "with-rules/rule1");
+                assert.strictEqual(results[0].messages[0].message, "Rule report from plugin");
+            });
+        });
+
+        describe("cache", () => {
+
+            /**
+             * helper method to delete a file without caring about exceptions
+             * @param {string} filePath The file path
+             * @returns {void}
+             */
+            function doDelete(filePath) {
+                try {
+                    fs.unlinkSync(filePath);
+                } catch (ex) {
+
+                    /*
+                     * we don't care if the file didn't exist, since our
+                     * intention was to remove the file
+                     */
+                }
+            }
+
+            /**
+             * helper method to delete the cache files created during testing
+             * @returns {void}
+             */
+            function deleteCache() {
+                doDelete(path.resolve(".eslintcache"));
+                doDelete(path.resolve(".cache/custom-cache"));
+            }
+
+            beforeEach(() => {
+                deleteCache();
+            });
+
+            afterEach(() => {
+                sinon.restore();
+                deleteCache();
+            });
+
+            describe("when the cacheFile is a directory or looks like a directory", () => {
+
+                /**
+                 * helper method to delete the cache files created during testing
+                 * @returns {void}
+                 */
+                function deleteCacheDir() {
+                    try {
+                        fs.unlinkSync("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory");
+                    } catch (ex) {
+
+                        /*
+                         * we don't care if the file didn't exist, since our
+                         * intention was to remove the file
+                         */
+                    }
+                }
+                beforeEach(() => {
+                    deleteCacheDir();
+                });
+
+                afterEach(() => {
+                    deleteCacheDir();
+                });
+
+                it("should create the cache file inside the provided directory", async () => {
+                    assert(!shell.test("-d", path.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
+
+                    eslint = new ESLint({
+                        useEslintrc: false,
+
+                        // specifying cache true the cache will be created
+                        cache: true,
+                        cacheLocation: "./tmp/.cacheFileDir/",
+                        overrideConfig: {
+                            rules: {
+                                "no-console": 0,
+                                "no-unused-vars": 2
+                            }
+                        },
+                        extensions: ["js"],
+                        ignore: false
+                    });
+                    const file = getFixturePath("cache/src", "test-file.js");
+
+                    await eslint.lintFiles([file]);
+
+                    assert(shell.test("-f", path.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
+
+                    sinon.restore();
+                });
+            });
+
+            it("should create the cache file inside the provided directory using the cacheLocation option", async () => {
+                assert(!shell.test("-d", path.resolve("./tmp/.cacheFileDir/.cache_hashOfCurrentWorkingDirectory")), "the cache for eslint does not exist");
+
+                eslint = new ESLint({
+                    useEslintrc: false,
+
+                    // specifying cache true the cache will be created
+                    cache: true,
+                    cacheLocation: "./tmp/.cacheFileDir/",
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"],
+                    ignore: false
+                });
+                const file = getFixturePath("cache/src", "test-file.js");
+
+                await eslint.lintFiles([file]);
+
+                assert(shell.test("-f", path.resolve(`./tmp/.cacheFileDir/.cache_${hash(process.cwd())}`)), "the cache for eslint was created");
+
+                sinon.restore();
+            });
+
+            it("should create the cache file inside cwd when no cacheLocation provided", async () => {
+                const cwd = path.resolve(getFixturePath("cli-engine"));
+
+                eslint = new ESLint({
+                    useEslintrc: false,
+                    cache: true,
+                    cwd,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0
+                        }
+                    },
+                    extensions: ["js"],
+                    ignore: false
+                });
+                const file = getFixturePath("cli-engine", "console.js");
+
+                await eslint.lintFiles([file]);
+
+                assert(shell.test("-f", path.resolve(cwd, ".eslintcache")), "the cache for eslint was created at provided cwd");
+            });
+
+            it("should invalidate the cache if the configuration changed between executions", async () => {
+                assert(!shell.test("-f", path.resolve(".eslintcache")), "the cache for eslint does not exist");
+
+                eslint = new ESLint({
+                    useEslintrc: false,
+
+                    // specifying cache true the cache will be created
+                    cache: true,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"],
+                    ignore: false
+                });
+
+                let spy = sinon.spy(fs, "readFileSync");
+
+                let file = getFixturePath("cache/src", "test-file.js");
+
+                file = fs.realpathSync(file);
+                const results = await eslint.lintFiles([file]);
+
+                for (const { errorCount, warningCount } of results) {
+                    assert.strictEqual(errorCount + warningCount, 0, "the file passed without errors or warnings");
+                }
+                assert.strictEqual(spy.getCall(0).args[0], file, "the module read the file because is considered changed");
+                assert(shell.test("-f", path.resolve(".eslintcache")), "the cache for eslint was created");
+
+                // destroy the spy
+                sinon.restore();
+
+                eslint = new ESLint({
+                    useEslintrc: false,
+
+                    // specifying cache true the cache will be created
+                    cache: true,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 2,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"],
+                    ignore: false
+                });
+
+                // create a new spy
+                spy = sinon.spy(fs, "readFileSync");
+
+                const [cachedResult] = await eslint.lintFiles([file]);
+
+                assert.strictEqual(spy.getCall(0).args[0], file, "the module read the file because is considered changed because the config changed");
+                assert.strictEqual(cachedResult.errorCount, 1, "since configuration changed the cache was not used an one error was reported");
+                assert(shell.test("-f", path.resolve(".eslintcache")), "the cache for eslint was created");
+            });
+
+            it("should remember the files from a previous run and do not operate on them if not changed", async () => {
+                assert(!shell.test("-f", path.resolve(".eslintcache")), "the cache for eslint does not exist");
+
+                eslint = new ESLint({
+                    useEslintrc: false,
+
+                    // specifying cache true the cache will be created
+                    cache: true,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"],
+                    ignore: false
+                });
+
+                let spy = sinon.spy(fs, "readFileSync");
+
+                let file = getFixturePath("cache/src", "test-file.js");
+
+                file = fs.realpathSync(file);
+
+                const result = await eslint.lintFiles([file]);
+
+                assert.strictEqual(spy.getCall(0).args[0], file, "the module read the file because is considered changed");
+                assert(shell.test("-f", path.resolve(".eslintcache")), "the cache for eslint was created");
+
+                // destroy the spy
+                sinon.restore();
+
+                eslint = new ESLint({
+                    useEslintrc: false,
+
+                    // specifying cache true the cache will be created
+                    cache: true,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"],
+                    ignore: false
+                });
+
+                // create a new spy
+                spy = sinon.spy(fs, "readFileSync");
+
+                const cachedResult = await eslint.lintFiles([file]);
+
+                assert.deepStrictEqual(result, cachedResult, "the result is the same regardless of using cache or not");
+
+                // assert the file was not processed because the cache was used
+                assert(!spy.calledWith(file), "the file was not loaded because it used the cache");
+            });
+
+            it("should remember the files from a previous run and do not operate on then if not changed", async () => {
+                const cacheLocation = getFixturePath(".eslintcache");
+                const eslintOptions = {
+                    useEslintrc: false,
+
+                    // specifying cache true the cache will be created
+                    cache: true,
+                    cacheLocation,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"],
+                    cwd: path.join(fixtureDir, "..")
+                };
+
+                assert(!shell.test("-f", cacheLocation), "the cache for eslint does not exist");
+
+                eslint = new ESLint(eslintOptions);
+
+                let file = getFixturePath("cache/src", "test-file.js");
+
+                file = fs.realpathSync(file);
+
+                await eslint.lintFiles([file]);
+
+                assert(shell.test("-f", cacheLocation), "the cache for eslint was created");
+
+                eslintOptions.cache = false;
+                eslint = new ESLint(eslintOptions);
+
+                await eslint.lintFiles([file]);
+
+                assert(!shell.test("-f", cacheLocation), "the cache for eslint was deleted since last run did not used the cache");
+            });
+
+            it("should store in the cache a file that failed the test", async () => {
+                const cacheLocation = getFixturePath(".eslintcache");
+
+                assert(!shell.test("-f", cacheLocation), "the cache for eslint does not exist");
+
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+
+                    // specifying cache true the cache will be created
+                    cache: true,
+                    cacheLocation,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"]
+                });
+                const badFile = fs.realpathSync(getFixturePath("cache/src", "fail-file.js"));
+                const goodFile = fs.realpathSync(getFixturePath("cache/src", "test-file.js"));
+                const result = await eslint.lintFiles([badFile, goodFile]);
+
+                assert(shell.test("-f", cacheLocation), "the cache for eslint was created");
+                const fileCache = fCache.createFromFile(cacheLocation);
+                const { cache } = fileCache;
+
+                assert.strictEqual(typeof cache.getKey(goodFile), "object", "the entry for the good file is in the cache");
+                assert.strictEqual(typeof cache.getKey(badFile), "object", "the entry for the bad file is in the cache");
+                const cachedResult = await eslint.lintFiles([badFile, goodFile]);
+
+                assert.deepStrictEqual(result, cachedResult, "result is the same with or without cache");
+            });
+
+            it("should not contain in the cache a file that was deleted", async () => {
+                const cacheLocation = getFixturePath(".eslintcache");
+
+                doDelete(cacheLocation);
+
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+
+                    // specifying cache true the cache will be created
+                    cache: true,
+                    cacheLocation,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"]
+                });
+                const badFile = fs.realpathSync(getFixturePath("cache/src", "fail-file.js"));
+                const goodFile = fs.realpathSync(getFixturePath("cache/src", "test-file.js"));
+                const toBeDeletedFile = fs.realpathSync(getFixturePath("cache/src", "file-to-delete.js"));
+
+                await eslint.lintFiles([badFile, goodFile, toBeDeletedFile]);
+                const fileCache = fCache.createFromFile(cacheLocation);
+                let { cache } = fileCache;
+
+                assert.strictEqual(typeof cache.getKey(toBeDeletedFile), "object", "the entry for the file to be deleted is in the cache");
+
+                // delete the file from the file system
+                fs.unlinkSync(toBeDeletedFile);
+
+                /*
+                 * file-entry-cache@2.0.0 will remove from the cache deleted files
+                 * even when they were not part of the array of files to be analyzed
+                 */
+                await eslint.lintFiles([badFile, goodFile]);
+
+                cache = JSON.parse(fs.readFileSync(cacheLocation));
+
+                assert.strictEqual(typeof cache[toBeDeletedFile], "undefined", "the entry for the file to be deleted is not in the cache");
+            });
+
+            it("should contain files that were not visited in the cache provided they still exist", async () => {
+                const cacheLocation = getFixturePath(".eslintcache");
+
+                doDelete(cacheLocation);
+
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+
+                    // specifying cache true the cache will be created
+                    cache: true,
+                    cacheLocation,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"]
+                });
+                const badFile = fs.realpathSync(getFixturePath("cache/src", "fail-file.js"));
+                const goodFile = fs.realpathSync(getFixturePath("cache/src", "test-file.js"));
+                const testFile2 = fs.realpathSync(getFixturePath("cache/src", "test-file2.js"));
+
+                await eslint.lintFiles([badFile, goodFile, testFile2]);
+
+                let fileCache = fCache.createFromFile(cacheLocation);
+                let { cache } = fileCache;
+
+                assert.strictEqual(typeof cache.getKey(testFile2), "object", "the entry for the test-file2 is in the cache");
+
+                /*
+                 * we pass a different set of files minus test-file2
+                 * previous version of file-entry-cache would remove the non visited
+                 * entries. 2.0.0 version will keep them unless they don't exist
+                 */
+                await eslint.lintFiles([badFile, goodFile]);
+
+                fileCache = fCache.createFromFile(cacheLocation);
+                cache = fileCache.cache;
+
+                assert.strictEqual(typeof cache.getKey(testFile2), "object", "the entry for the test-file2 is in the cache");
+            });
+
+            it("should not delete cache when executing on text", async () => {
+                const cacheLocation = getFixturePath(".eslintcache");
+
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    cacheLocation,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"]
+                });
+
+                assert(shell.test("-f", cacheLocation), "the cache for eslint exists");
+
+                await eslint.lintText("var foo = 'bar';");
+
+                assert(shell.test("-f", cacheLocation), "the cache for eslint still exists");
+            });
+
+            it("should not delete cache when executing on text with a provided filename", async () => {
+                const cacheLocation = getFixturePath(".eslintcache");
+
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    cacheLocation,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"]
+                });
+
+                assert(shell.test("-f", cacheLocation), "the cache for eslint exists");
+
+                await eslint.lintText("var bar = foo;", { filePath: "fixtures/passing.js" });
+
+                assert(shell.test("-f", cacheLocation), "the cache for eslint still exists");
+            });
+
+            it("should not delete cache when executing on files with --cache flag", async () => {
+                const cacheLocation = getFixturePath(".eslintcache");
+
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    cache: true,
+                    cacheLocation,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"]
+                });
+                const file = getFixturePath("cli-engine", "console.js");
+
+                assert(shell.test("-f", cacheLocation), "the cache for eslint exists");
+
+                await eslint.lintFiles([file]);
+
+                assert(shell.test("-f", cacheLocation), "the cache for eslint still exists");
+            });
+
+            it("should delete cache when executing on files without --cache flag", async () => {
+                const cacheLocation = getFixturePath(".eslintcache");
+
+                eslint = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    cacheLocation,
+                    overrideConfig: {
+                        rules: {
+                            "no-console": 0,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js"]
+                });
+                const file = getFixturePath("cli-engine", "console.js");
+
+                assert(shell.test("-f", cacheLocation), "the cache for eslint exists");
+
+                await eslint.lintFiles([file]);
+
+                assert(!shell.test("-f", cacheLocation), "the cache for eslint has been deleted");
+            });
+
+            describe("cacheFile", () => {
+                it("should use the specified cache file", async () => {
+                    const customCacheFile = path.resolve(".cache/custom-cache");
+
+                    assert(!shell.test("-f", customCacheFile), "the cache for eslint does not exist");
+
+                    eslint = new ESLint({
+                        useEslintrc: false,
+
+                        // specify a custom cache file
+                        cacheLocation: customCacheFile,
+
+                        // specifying cache true the cache will be created
+                        cache: true,
+                        overrideConfig: {
+                            rules: {
+                                "no-console": 0,
+                                "no-unused-vars": 2
+                            }
+                        },
+                        extensions: ["js"],
+                        cwd: path.join(fixtureDir, "..")
+                    });
+                    const badFile = fs.realpathSync(getFixturePath("cache/src", "fail-file.js"));
+                    const goodFile = fs.realpathSync(getFixturePath("cache/src", "test-file.js"));
+                    const result = await eslint.lintFiles([badFile, goodFile]);
+
+                    assert(shell.test("-f", customCacheFile), "the cache for eslint was created");
+                    const fileCache = fCache.createFromFile(customCacheFile);
+                    const { cache } = fileCache;
+
+                    assert(typeof cache.getKey(goodFile) === "object", "the entry for the good file is in the cache");
+
+                    assert(typeof cache.getKey(badFile) === "object", "the entry for the bad file is in the cache");
+                    const cachedResult = await eslint.lintFiles([badFile, goodFile]);
+
+                    assert.deepStrictEqual(result, cachedResult, "result is the same with or without cache");
+                });
+            });
+        });
+
+        describe("processors", () => {
+            it("should return two messages when executing with config file that specifies a processor", async () => {
+                eslint = eslintWithPlugins({
+                    overrideConfigFile: getFixturePath("configurations", "processors.json"),
+                    useEslintrc: false,
+                    extensions: ["js", "txt"],
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+            });
+
+            it("should return two messages when executing with config file that specifies preloaded processor", async () => {
+                eslint = new ESLint({
+                    useEslintrc: false,
+                    overrideConfig: {
+                        plugins: ["test-processor"],
+                        rules: {
+                            "no-console": 2,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js", "txt"],
+                    cwd: path.join(fixtureDir, ".."),
+                    plugins: {
+                        "test-processor": {
+                            processors: {
+                                ".txt": {
+                                    preprocess(text) {
+                                        return [text];
+                                    },
+                                    postprocess(messages) {
+                                        return messages[0];
+                                    }
+                                }
+                            }
+                        }
+                    }
+                });
+                const results = await eslint.lintFiles([fs.realpathSync(getFixturePath("processors", "test", "test-processor.txt"))]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+            });
+
+            it("should run processors when calling lintFiles with config file that specifies a processor", async () => {
+                eslint = eslintWithPlugins({
+                    overrideConfigFile: getFixturePath("configurations", "processors.json"),
+                    useEslintrc: false,
+                    extensions: ["js", "txt"],
+                    cwd: path.join(fixtureDir, "..")
+                });
+                const results = await eslint.lintFiles([getFixturePath("processors", "test", "test-processor.txt")]);
+
+                assert.strictEqual(results[0].messages[0].message, "'b' is defined but never used.");
+                assert.strictEqual(results[0].messages[0].ruleId, "post-processed");
+            });
+
+            it("should run processors when calling lintFiles with config file that specifies preloaded processor", async () => {
+                eslint = new ESLint({
+                    useEslintrc: false,
+                    overrideConfig: {
+                        plugins: ["test-processor"],
+                        rules: {
+                            "no-console": 2,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js", "txt"],
+                    cwd: path.join(fixtureDir, ".."),
+                    plugins: {
+                        "test-processor": {
+                            processors: {
+                                ".txt": {
+                                    preprocess(text) {
+                                        return [text.replace("a()", "b()")];
+                                    },
+                                    postprocess(messages) {
+                                        messages[0][0].ruleId = "post-processed";
+                                        return messages[0];
+                                    }
+                                }
+                            }
+                        }
+                    }
+                });
+                const results = await eslint.lintFiles([getFixturePath("processors", "test", "test-processor.txt")]);
+
+                assert.strictEqual(results[0].messages[0].message, "'b' is defined but never used.");
+                assert.strictEqual(results[0].messages[0].ruleId, "post-processed");
+            });
+
+            it("should run processors when calling lintText with config file that specifies a processor", async () => {
+                eslint = eslintWithPlugins({
+                    overrideConfigFile: getFixturePath("configurations", "processors.json"),
+                    useEslintrc: false,
+                    extensions: ["js", "txt"],
+                    ignore: false
+                });
+                const results = await eslint.lintText("function a() {console.log(\"Test\");}", { filePath: "tests/fixtures/processors/test/test-processor.txt" });
+
+                assert.strictEqual(results[0].messages[0].message, "'b' is defined but never used.");
+                assert.strictEqual(results[0].messages[0].ruleId, "post-processed");
+            });
+
+            it("should run processors when calling lintText with config file that specifies preloaded processor", async () => {
+                eslint = new ESLint({
+                    useEslintrc: false,
+                    overrideConfig: {
+                        plugins: ["test-processor"],
+                        rules: {
+                            "no-console": 2,
+                            "no-unused-vars": 2
+                        }
+                    },
+                    extensions: ["js", "txt"],
+                    ignore: false,
+                    plugins: {
+                        "test-processor": {
+                            processors: {
+                                ".txt": {
+                                    preprocess(text) {
+                                        return [text.replace("a()", "b()")];
+                                    },
+                                    postprocess(messages) {
+                                        messages[0][0].ruleId = "post-processed";
+                                        return messages[0];
+                                    }
+                                }
+                            }
+                        }
+                    }
+                });
+                const results = await eslint.lintText("function a() {console.log(\"Test\");}", { filePath: "tests/fixtures/processors/test/test-processor.txt" });
+
+                assert.strictEqual(results[0].messages[0].message, "'b' is defined but never used.");
+                assert.strictEqual(results[0].messages[0].ruleId, "post-processed");
+            });
+
+            describe("autofixing with processors", () => {
+                const HTML_PROCESSOR = Object.freeze({
+                    preprocess(text) {
+                        return [text.replace(/^<script>/u, "").replace(/<\/script>$/u, "")];
+                    },
+                    postprocess(problemLists) {
+                        return problemLists[0].map(problem => {
+                            if (problem.fix) {
+                                const updatedFix = Object.assign({}, problem.fix, {
+                                    range: problem.fix.range.map(index => index + "<script>".length)
+                                });
+
+                                return Object.assign({}, problem, { fix: updatedFix });
+                            }
+                            return problem;
+                        });
+                    }
+                });
+
+
+                it("should run in autofix mode when using a processor that supports autofixing", async () => {
+                    eslint = new ESLint({
+                        useEslintrc: false,
+                        overrideConfig: {
+                            plugins: ["test-processor"],
+                            rules: {
+                                semi: 2
+                            }
+                        },
+                        extensions: ["js", "txt"],
+                        ignore: false,
+                        fix: true,
+                        plugins: {
+                            "test-processor": {
+                                processors: {
+                                    ".html": Object.assign({ supportsAutofix: true }, HTML_PROCESSOR)
+                                }
+                            }
+                        }
+                    });
+                    const results = await eslint.lintText("<script>foo</script>", { filePath: "foo.html" });
+
+                    assert.strictEqual(results[0].messages.length, 0);
+                    assert.strictEqual(results[0].output, "<script>foo;</script>");
+                });
+
+                it("should not run in autofix mode when using a processor that does not support autofixing", async () => {
+                    eslint = new ESLint({
+                        useEslintrc: false,
+                        overrideConfig: {
+                            plugins: ["test-processor"],
+                            rules: {
+                                semi: 2
+                            }
+                        },
+                        extensions: ["js", "txt"],
+                        ignore: false,
+                        fix: true,
+                        plugins: {
+                            "test-processor": { processors: { ".html": HTML_PROCESSOR } }
+                        }
+                    });
+                    const results = await eslint.lintText("<script>foo</script>", { filePath: "foo.html" });
+
+                    assert.strictEqual(results[0].messages.length, 1);
+                    assert(!Object.prototype.hasOwnProperty.call(results[0], "output"));
+                });
+
+                it("should not run in autofix mode when `fix: true` is not provided, even if the processor supports autofixing", async () => {
+                    eslint = new ESLint({
+                        useEslintrc: false,
+                        overrideConfig: {
+                            plugins: ["test-processor"],
+                            rules: {
+                                semi: 2
+                            }
+                        },
+                        extensions: ["js", "txt"],
+                        ignore: false,
+                        plugins: {
+                            "test-processor": {
+                                processors: {
+                                    ".html": Object.assign({ supportsAutofix: true }, HTML_PROCESSOR)
+                                }
+                            }
+                        }
+                    });
+                    const results = await eslint.lintText("<script>foo</script>", { filePath: "foo.html" });
+
+                    assert.strictEqual(results[0].messages.length, 1);
+                    assert(!Object.prototype.hasOwnProperty.call(results[0], "output"));
+                });
+            });
+        });
+
+        describe("Patterns which match no file should throw errors.", () => {
+            beforeEach(() => {
+                eslint = new ESLint({
+                    cwd: getFixturePath("cli-engine"),
+                    useEslintrc: false
+                });
+            });
+
+            it("one file", async () => {
+                await assert.rejects(async () => {
+                    await eslint.lintFiles(["non-exist.js"]);
+                }, /No files matching 'non-exist\.js' were found\./u);
+            });
+
+            it("should throw if the directory exists and is empty", async () => {
+                await assert.rejects(async () => {
+                    await eslint.lintFiles(["empty"]);
+                }, /No files matching 'empty' were found\./u);
+            });
+
+            it("one glob pattern", async () => {
+                await assert.rejects(async () => {
+                    await eslint.lintFiles(["non-exist/**/*.js"]);
+                }, /No files matching 'non-exist\/\*\*\/\*\.js' were found\./u);
+            });
+
+            it("two files", async () => {
+                await assert.rejects(async () => {
+                    await eslint.lintFiles(["aaa.js", "bbb.js"]);
+                }, /No files matching 'aaa\.js' were found\./u);
+            });
+
+            it("a mix of an existing file and a non-existing file", async () => {
+                await assert.rejects(async () => {
+                    await eslint.lintFiles(["console.js", "non-exist.js"]);
+                }, /No files matching 'non-exist\.js' were found\./u);
+            });
+        });
+
+        describe("overrides", () => {
+            beforeEach(() => {
+                eslint = new ESLint({
+                    cwd: getFixturePath("cli-engine/overrides-with-dot"),
+                    ignore: false
+                });
+            });
+
+            it("should recognize dotfiles", async () => {
+                const ret = await eslint.lintFiles([".test-target.js"]);
+
+                assert.strictEqual(ret.length, 1);
+                assert.strictEqual(ret[0].messages.length, 1);
+                assert.strictEqual(ret[0].messages[0].ruleId, "no-unused-vars");
+            });
+        });
+
+        describe("a config file setting should have higher priority than a shareable config file's settings always; https://github.com/eslint/eslint/issues/11510", () => {
+            beforeEach(() => {
+                ({ ESLint } = defineESLintWithInMemoryFileSystem({
+                    cwd: () => path.join(os.tmpdir(), "eslint/11510"),
+                    files: {
+                        "no-console-error-in-overrides.json": JSON.stringify({
+                            overrides: [{
+                                files: ["*.js"],
+                                rules: { "no-console": "error" }
+                            }]
+                        }),
+                        ".eslintrc.json": JSON.stringify({
+                            extends: "./no-console-error-in-overrides.json",
+                            rules: { "no-console": "off" }
+                        }),
+                        "a.js": "console.log();"
+                    }
+                }));
+                eslint = new ESLint();
+            });
+
+            it("should not report 'no-console' error.", async () => {
+                const results = await eslint.lintFiles("a.js");
+
+                assert.strictEqual(results.length, 1);
+                assert.deepStrictEqual(results[0].messages, []);
+            });
+        });
+
+        describe("configs of plugin rules should be validated even if 'plugins' key doesn't exist; https://github.com/eslint/eslint/issues/11559", () => {
+            beforeEach(() => {
+                ({ ESLint } = defineESLintWithInMemoryFileSystem({
+                    cwd: () => path.join(os.tmpdir(), "eslint/11559"),
+                    files: {
+                        "node_modules/eslint-plugin-test/index.js": `
+                            exports.configs = {
+                                recommended: { plugins: ["test"] }
+                            };
+                            exports.rules = {
+                                foo: {
+                                    meta: { schema: [{ type: "number" }] },
+                                    create() { return {}; }
+                                }
+                            };
+                        `,
+                        ".eslintrc.json": JSON.stringify({
+
+                            // Import via the recommended config.
+                            extends: "plugin:test/recommended",
+
+                            // Has invalid option.
+                            rules: { "test/foo": ["error", "invalid-option"] }
+                        }),
+                        "a.js": "console.log();"
+                    }
+                }));
+                eslint = new ESLint();
+            });
+
+            it("should throw fatal error.", async () => {
+                await assert.rejects(async () => {
+                    await eslint.lintFiles("a.js");
+                }, /invalid-option/u);
+            });
+        });
+
+        describe("'--fix-type' should not crash even if plugin rules exist; https://github.com/eslint/eslint/issues/11586", () => {
+            beforeEach(() => {
+                ({ ESLint } = defineESLintWithInMemoryFileSystem({
+                    cwd: () => path.join(os.tmpdir(), "eslint/11586"),
+                    files: {
+                        "node_modules/eslint-plugin-test/index.js": `
+                            exports.rules = {
+                                "no-example": {
+                                    meta: { type: "problem", fixable: "code" },
+                                    create(context) {
+                                        return {
+                                            Identifier(node) {
+                                                if (node.name === "example") {
+                                                    context.report({
+                                                        node,
+                                                        message: "fix",
+                                                        fix: fixer => fixer.replaceText(node, "fixed")
+                                                    })
+                                                }
+                                            }
+                                        };
+                                    }
+                                }
+                            };
+                        `,
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["test"],
+                            rules: { "test/no-example": "error" }
+                        }),
+                        "a.js": "example;"
+                    }
+                }));
+                eslint = new ESLint({ fix: true, fixTypes: ["problem"] });
+            });
+
+            it("should not crash.", async () => {
+                const results = await eslint.lintFiles("a.js");
+
+                assert.strictEqual(results.length, 1);
+                assert.deepStrictEqual(results[0].messages, []);
+                assert.deepStrictEqual(results[0].output, "fixed;");
+            });
+        });
+
+        describe("multiple processors", () => {
+            const root = path.join(os.tmpdir(), "eslint/eslint/multiple-processors");
+            const commonFiles = {
+                "node_modules/pattern-processor/index.js": fs.readFileSync(
+                    require.resolve("../../fixtures/processors/pattern-processor"),
+                    "utf8"
+                ),
+                "node_modules/eslint-plugin-markdown/index.js": `
+                    const { defineProcessor } = require("pattern-processor");
+                    const processor = defineProcessor(${/```(\w+)\n([\s\S]+?)\n```/gu});
+                    exports.processors = {
+                        ".md": { ...processor, supportsAutofix: true },
+                        "non-fixable": processor
+                    };
+                `,
+                "node_modules/eslint-plugin-html/index.js": `
+                    const { defineProcessor } = require("pattern-processor");
+                    const processor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu});
+                    const legacyProcessor = defineProcessor(${/<script lang="(\w*)">\n([\s\S]+?)\n<\/script>/gu}, true);
+                    exports.processors = {
+                        ".html": { ...processor, supportsAutofix: true },
+                        "non-fixable": processor,
+                        "legacy": legacyProcessor
+                    };
+                `,
+                "test.md": unIndent`
+                    \`\`\`js
+                    console.log("hello")
+                    \`\`\`
+                    \`\`\`html
+                    <div>Hello</div>
+                    <script lang="js">
+                        console.log("hello")
+                    </script>
+                    <script lang="ts">
+                        console.log("hello")
+                    </script>
+                    \`\`\`
+                `
+            };
+
+            it("should lint only JavaScript blocks if '--ext' was not given.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ...commonFiles,
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["markdown", "html"],
+                            rules: { semi: "error" }
+                        })
+                    }
+                }).ESLint;
+                eslint = new ESLint({ cwd: root });
+                const results = await eslint.lintFiles(["test.md"]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "semi");
+                assert.strictEqual(results[0].messages[0].line, 2);
+            });
+
+            it("should fix only JavaScript blocks if '--ext' was not given.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ...commonFiles,
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["markdown", "html"],
+                            rules: { semi: "error" }
+                        })
+                    }
+                }).ESLint;
+                eslint = new ESLint({ cwd: root, fix: true });
+                const results = await eslint.lintFiles(["test.md"]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 0);
+                assert.strictEqual(results[0].output, unIndent`
+                    \`\`\`js
+                    console.log("hello");${/* ← fixed */""}
+                    \`\`\`
+                    \`\`\`html
+                    <div>Hello</div>
+                    <script lang="js">
+                        console.log("hello")${/* ← ignored */""}
+                    </script>
+                    <script lang="ts">
+                        console.log("hello")${/* ← ignored */""}
+                    </script>
+                    \`\`\`
+                `);
+            });
+
+            it("should lint HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ...commonFiles,
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["markdown", "html"],
+                            rules: { semi: "error" }
+                        })
+                    }
+                }).ESLint;
+                eslint = new ESLint({ cwd: root, extensions: ["js", "html"] });
+                const results = await eslint.lintFiles(["test.md"]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "semi"); // JS block
+                assert.strictEqual(results[0].messages[0].line, 2);
+                assert.strictEqual(results[0].messages[1].ruleId, "semi"); // JS block in HTML block
+                assert.strictEqual(results[0].messages[1].line, 7);
+            });
+
+            it("should fix HTML blocks as well with multiple processors if '--ext' option was given.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ...commonFiles,
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["markdown", "html"],
+                            rules: { semi: "error" }
+                        })
+                    }
+                }).ESLint;
+                eslint = new ESLint({ cwd: root, extensions: ["js", "html"], fix: true });
+                const results = await eslint.lintFiles(["test.md"]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 0);
+                assert.strictEqual(results[0].output, unIndent`
+                    \`\`\`js
+                    console.log("hello");${/* ← fixed */""}
+                    \`\`\`
+                    \`\`\`html
+                    <div>Hello</div>
+                    <script lang="js">
+                        console.log("hello");${/* ← fixed */""}
+                    </script>
+                    <script lang="ts">
+                        console.log("hello")${/* ← ignored */""}
+                    </script>
+                    \`\`\`
+                `);
+            });
+
+            it("should use overriden processor; should report HTML blocks but not fix HTML blocks if the processor for '*.html' didn't support autofix.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ...commonFiles,
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["markdown", "html"],
+                            rules: { semi: "error" },
+                            overrides: [
+                                {
+                                    files: "*.html",
+                                    processor: "html/non-fixable" // supportsAutofix: false
+                                }
+                            ]
+                        })
+                    }
+                }).ESLint;
+                eslint = new ESLint({ cwd: root, extensions: ["js", "html"], fix: true });
+                const results = await eslint.lintFiles(["test.md"]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].ruleId, "semi"); // JS Block in HTML Block
+                assert.strictEqual(results[0].messages[0].line, 7);
+                assert.strictEqual(results[0].messages[0].fix, void 0);
+                assert.strictEqual(results[0].output, unIndent`
+                    \`\`\`js
+                    console.log("hello");${/* ← fixed */""}
+                    \`\`\`
+                    \`\`\`html
+                    <div>Hello</div>
+                    <script lang="js">
+                        console.log("hello")${/* ← reported but not fixed */""}
+                    </script>
+                    <script lang="ts">
+                        console.log("hello")
+                    </script>
+                    \`\`\`
+                `);
+            });
+
+            it("should use the config '**/*.html/*.js' to lint JavaScript blocks in HTML.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ...commonFiles,
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["markdown", "html"],
+                            rules: { semi: "error" },
+                            overrides: [
+                                {
+                                    files: "*.html",
+
+                                    // this rules are not used because ESLint re-resolve configs if a code block had a different file extension.
+                                    rules: {
+                                        semi: "error",
+                                        "no-console": "off"
+                                    }
+                                },
+                                {
+                                    files: "**/*.html/*.js",
+                                    rules: {
+                                        semi: "off",
+                                        "no-console": "error"
+                                    }
+                                }
+                            ]
+                        })
+                    }
+                }).ESLint;
+                eslint = new ESLint({ cwd: root, extensions: ["js", "html"] });
+                const results = await eslint.lintFiles(["test.md"]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "semi");
+                assert.strictEqual(results[0].messages[0].line, 2);
+                assert.strictEqual(results[0].messages[1].ruleId, "no-console");
+                assert.strictEqual(results[0].messages[1].line, 7);
+            });
+
+            it("should use the same config as one which has 'processor' property in order to lint blocks in HTML if the processor was legacy style.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ...commonFiles,
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["markdown", "html"],
+                            rules: { semi: "error" },
+                            overrides: [
+                                {
+                                    files: "*.html",
+                                    processor: "html/legacy", // this processor returns strings rather than `{text, filename}`
+                                    rules: {
+                                        semi: "off",
+                                        "no-console": "error"
+                                    }
+                                },
+                                {
+                                    files: "**/*.html/*.js",
+                                    rules: {
+                                        semi: "error",
+                                        "no-console": "off"
+                                    }
+                                }
+                            ]
+                        })
+                    }
+                }).ESLint;
+                eslint = new ESLint({ cwd: root, extensions: ["js", "html"] });
+                const results = await eslint.lintFiles(["test.md"]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 3);
+                assert.strictEqual(results[0].messages[0].ruleId, "semi");
+                assert.strictEqual(results[0].messages[0].line, 2);
+                assert.strictEqual(results[0].messages[1].ruleId, "no-console");
+                assert.strictEqual(results[0].messages[1].line, 7);
+                assert.strictEqual(results[0].messages[2].ruleId, "no-console");
+                assert.strictEqual(results[0].messages[2].line, 10);
+            });
+
+            it("should throw an error if invalid processor was specified.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ...commonFiles,
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["markdown", "html"],
+                            processor: "markdown/unknown"
+                        })
+                    }
+                }).ESLint;
+                eslint = new ESLint({ cwd: root });
+
+                await assert.rejects(async () => {
+                    await eslint.lintFiles(["test.md"]);
+                }, /ESLint configuration of processor in '\.eslintrc\.json' is invalid: 'markdown\/unknown' was not found\./u);
+            });
+
+            it("should lint HTML blocks as well with multiple processors if 'overrides[].files' is present.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ...commonFiles,
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["markdown", "html"],
+                            rules: { semi: "error" },
+                            overrides: [
+                                {
+                                    files: "*.html",
+                                    processor: "html/.html"
+                                },
+                                {
+                                    files: "*.md",
+                                    processor: "markdown/.md"
+                                }
+                            ]
+                        })
+                    }
+                }).ESLint;
+                eslint = new ESLint({ cwd: root });
+                const results = await eslint.lintFiles(["test.md"]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 2);
+                assert.strictEqual(results[0].messages[0].ruleId, "semi"); // JS block
+                assert.strictEqual(results[0].messages[0].line, 2);
+                assert.strictEqual(results[0].messages[1].ruleId, "semi"); // JS block in HTML block
+                assert.strictEqual(results[0].messages[1].line, 7);
+            });
+        });
+
+        describe("MODULE_NOT_FOUND error handling", () => {
+            const cwd = getFixturePath("module-not-found");
+
+            beforeEach(() => {
+                eslint = new ESLint({ cwd });
+            });
+
+            it("should throw an error with a message template when 'extends' property has a non-existence JavaScript config.", async () => {
+                try {
+                    await eslint.lintText("test", { filePath: "extends-js/test.js" });
+                } catch (err) {
+                    assert.strictEqual(err.messageTemplate, "extend-config-missing");
+                    assert.deepStrictEqual(err.messageData, {
+                        configName: "nonexistent-config",
+                        importerName: getFixturePath("module-not-found", "extends-js", ".eslintrc.yml")
+                    });
+                    return;
+                }
+                assert.fail("Expected to throw an error");
+            });
+
+            it("should throw an error with a message template when 'extends' property has a non-existence plugin config.", async () => {
+                try {
+                    await eslint.lintText("test", { filePath: "extends-plugin/test.js" });
+                } catch (err) {
+                    assert.strictEqual(err.code, "MODULE_NOT_FOUND");
+                    assert.strictEqual(err.messageTemplate, "plugin-missing");
+                    assert.deepStrictEqual(err.messageData, {
+                        importerName: `extends-plugin${path.sep}.eslintrc.yml`,
+                        pluginName: "eslint-plugin-nonexistent-plugin",
+                        resolvePluginsRelativeTo: path.join(cwd, "extends-plugin") // the directory of the config file.
+                    });
+                    return;
+                }
+                assert.fail("Expected to throw an error");
+            });
+
+            it("should throw an error with a message template when 'plugins' property has a non-existence plugin.", async () => {
+                try {
+                    await eslint.lintText("test", { filePath: "plugins/test.js" });
+                } catch (err) {
+                    assert.strictEqual(err.code, "MODULE_NOT_FOUND");
+                    assert.strictEqual(err.messageTemplate, "plugin-missing");
+                    assert.deepStrictEqual(err.messageData, {
+                        importerName: `plugins${path.sep}.eslintrc.yml`,
+                        pluginName: "eslint-plugin-nonexistent-plugin",
+                        resolvePluginsRelativeTo: path.join(cwd, "plugins") // the directory of the config file.
+                    });
+                    return;
+                }
+                assert.fail("Expected to throw an error");
+            });
+
+            it("should throw an error with no message template when a JavaScript config threw a 'MODULE_NOT_FOUND' error.", async () => {
+                try {
+                    await eslint.lintText("test", { filePath: "throw-in-config-itself/test.js" });
+                } catch (err) {
+                    assert.strictEqual(err.code, "MODULE_NOT_FOUND");
+                    assert.strictEqual(err.messageTemplate, void 0);
+                    return;
+                }
+                assert.fail("Expected to throw an error");
+            });
+
+            it("should throw an error with no message template when 'extends' property has a JavaScript config that throws a 'MODULE_NOT_FOUND' error.", async () => {
+                try {
+                    await eslint.lintText("test", { filePath: "throw-in-extends-js/test.js" });
+                } catch (err) {
+                    assert.strictEqual(err.code, "MODULE_NOT_FOUND");
+                    assert.strictEqual(err.messageTemplate, void 0);
+                    return;
+                }
+                assert.fail("Expected to throw an error");
+            });
+
+            it("should throw an error with no message template when 'extends' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", async () => {
+                try {
+                    await eslint.lintText("test", { filePath: "throw-in-extends-plugin/test.js" });
+                } catch (err) {
+                    assert.strictEqual(err.code, "MODULE_NOT_FOUND");
+                    assert.strictEqual(err.messageTemplate, void 0);
+                    return;
+                }
+                assert.fail("Expected to throw an error");
+            });
+
+            it("should throw an error with no message template when 'plugins' property has a plugin config that throws a 'MODULE_NOT_FOUND' error.", async () => {
+                try {
+                    await eslint.lintText("test", { filePath: "throw-in-plugins/test.js" });
+                } catch (err) {
+                    assert.strictEqual(err.code, "MODULE_NOT_FOUND");
+                    assert.strictEqual(err.messageTemplate, void 0);
+                    return;
+                }
+                assert.fail("Expected to throw an error");
+            });
+        });
+
+        describe("with '--rulesdir' option", () => {
+            it("should use the configured rules which are defined by '--rulesdir' option.", async () => {
+                const rootPath = getFixturePath("cli-engine/with-rulesdir");
+                const StubbedESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => rootPath,
+                    files: {
+                        "internal-rules/test.js": `
+                            module.exports = context => ({
+                                ExpressionStatement(node) {
+                                    context.report({ node, message: "ok" })
+                                }
+                            })
+                        `,
+                        ".eslintrc.json": JSON.stringify({
+                            root: true,
+                            rules: { test: "error" }
+                        }),
+                        "test.js": "console.log('hello')"
+                    }
+                }).ESLint;
+
+                eslint = new StubbedESLint({
+                    rulePaths: ["internal-rules"]
+                });
+                const results = await eslint.lintFiles(["test.js"]);
+
+                assert.strictEqual(results.length, 1);
+                assert.strictEqual(results[0].messages.length, 1);
+                assert.strictEqual(results[0].messages[0].message, "ok");
+            });
+        });
+
+        describe("glob pattern '[ab].js'", () => {
+            const root = getFixturePath("cli-engine/unmatched-glob");
+
+            it("should match '[ab].js' if existed.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "a.js": "",
+                        "b.js": "",
+                        "ab.js": "",
+                        "[ab].js": "",
+                        ".eslintrc.yml": "root: true"
+                    }
+                }).ESLint;
+                eslint = new ESLint();
+                const results = await eslint.lintFiles(["[ab].js"]);
+                const filenames = results.map(r => path.basename(r.filePath));
+
+                assert.deepStrictEqual(filenames, ["[ab].js"]);
+            });
+
+            it("should match 'a.js' and 'b.js' if '[ab].js' didn't existed.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "a.js": "",
+                        "b.js": "",
+                        "ab.js": "",
+                        ".eslintrc.yml": "root: true"
+                    }
+                }).ESLint;
+                eslint = new ESLint();
+                const results = await eslint.lintFiles(["[ab].js"]);
+                const filenames = results.map(r => path.basename(r.filePath));
+
+                assert.deepStrictEqual(filenames, ["a.js", "b.js"]);
+            });
+        });
+
+        describe("with 'noInlineConfig' setting", () => {
+            const root = getFixturePath("cli-engine/noInlineConfig");
+
+            it("should warn directive comments if 'noInlineConfig' was given.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "test.js": "/* globals foo */",
+                        ".eslintrc.yml": "noInlineConfig: true"
+                    }
+                }).ESLint;
+                eslint = new ESLint();
+                const results = await eslint.lintFiles(["test.js"]);
+                const messages = results[0].messages;
+
+                assert.strictEqual(messages.length, 1);
+                assert.strictEqual(messages[0].message, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml).");
+            });
+
+            it("should show the config file what the 'noInlineConfig' came from.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-config-foo/index.js": "module.exports = {noInlineConfig: true}",
+                        "test.js": "/* globals foo */",
+                        ".eslintrc.yml": "extends: foo"
+                    }
+                }).ESLint;
+                eslint = new ESLint();
+                const results = await eslint.lintFiles(["test.js"]);
+                const messages = results[0].messages;
+
+                assert.strictEqual(messages.length, 1);
+                assert.strictEqual(messages[0].message, "'/*globals*/' has no effect because you have 'noInlineConfig' setting in your config (.eslintrc.yml » eslint-config-foo).");
+            });
+        });
+
+        describe("with 'reportUnusedDisableDirectives' setting", () => {
+            const root = getFixturePath("cli-engine/reportUnusedDisableDirectives");
+
+            it("should warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives' was given.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "test.js": "/* eslint-disable eqeqeq */",
+                        ".eslintrc.yml": "reportUnusedDisableDirectives: true"
+                    }
+                }).ESLint;
+                eslint = new ESLint();
+                const results = await eslint.lintFiles(["test.js"]);
+                const messages = results[0].messages;
+
+                assert.strictEqual(messages.length, 1);
+                assert.strictEqual(messages[0].severity, 1);
+                assert.strictEqual(messages[0].message, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
+            });
+
+            describe("the runtime option overrides config files.", () => {
+                it("should not warn unused 'eslint-disable' comments if 'reportUnusedDisableDirectives=off' was given in runtime.", async () => {
+                    ESLint = defineESLintWithInMemoryFileSystem({
+                        cwd: () => root,
+                        files: {
+                            "test.js": "/* eslint-disable eqeqeq */",
+                            ".eslintrc.yml": "reportUnusedDisableDirectives: true"
+                        }
+                    }).ESLint;
+                    eslint = new ESLint({ reportUnusedDisableDirectives: "off" });
+                    const results = await eslint.lintFiles(["test.js"]);
+                    const messages = results[0].messages;
+
+                    assert.strictEqual(messages.length, 0);
+                });
+
+                it("should warn unused 'eslint-disable' comments as error if 'reportUnusedDisableDirectives=error' was given in runtime.", async () => {
+                    ESLint = defineESLintWithInMemoryFileSystem({
+                        cwd: () => root,
+                        files: {
+                            "test.js": "/* eslint-disable eqeqeq */",
+                            ".eslintrc.yml": "reportUnusedDisableDirectives: true"
+                        }
+                    }).ESLint;
+                    eslint = new ESLint({ reportUnusedDisableDirectives: "error" });
+                    const results = await eslint.lintFiles(["test.js"]);
+                    const messages = results[0].messages;
+
+                    assert.strictEqual(messages.length, 1);
+                    assert.strictEqual(messages[0].severity, 2);
+                    assert.strictEqual(messages[0].message, "Unused eslint-disable directive (no problems were reported from 'eqeqeq').");
+                });
+            });
+        });
+
+        describe("with 'overrides[*].extends' setting on deep locations", () => {
+            const root = getFixturePath("cli-engine/deeply-overrides-i-extends");
+
+            it("should not throw.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
+                            overrides: [{ files: ["*test*"], extends: "two" }]
+                        })}`,
+                        "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
+                            overrides: [{ files: ["*.js"], extends: "three" }]
+                        })}`,
+                        "node_modules/eslint-config-three/index.js": `module.exports = ${JSON.stringify({
+                            rules: { "no-console": "error" }
+                        })}`,
+                        "test.js": "console.log('hello')",
+                        ".eslintrc.yml": "extends: one"
+                    }
+                }).ESLint;
+                eslint = new ESLint();
+                const results = await eslint.lintFiles(["test.js"]);
+                const messages = results[0].messages;
+
+                assert.strictEqual(messages.length, 1);
+                assert.strictEqual(messages[0].ruleId, "no-console");
+            });
+        });
+
+        describe("don't ignore the entry directory.", () => {
+            const root = getFixturePath("cli-engine/dont-ignore-entry-dir");
+
+            it("'lintFiles(\".\")' should not load config files from outside of \".\".", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "../.eslintrc.json": "BROKEN FILE",
+                        ".eslintrc.json": JSON.stringify({ root: true }),
+                        "index.js": "console.log(\"hello\")"
+                    }
+                }).ESLint;
+                eslint = new ESLint();
+
+                // Don't throw "failed to load config file" error.
+                await eslint.lintFiles(".");
+            });
+
+            it("'lintFiles(\".\")' should not ignore '.' even if 'ignorePatterns' contains it.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "../.eslintrc.json": JSON.stringify({ ignorePatterns: ["/dont-ignore-entry-dir"] }),
+                        ".eslintrc.json": JSON.stringify({ root: true }),
+                        "index.js": "console.log(\"hello\")"
+                    }
+                }).ESLint;
+                eslint = new ESLint();
+
+                // Don't throw "file not found" error.
+                await eslint.lintFiles(".");
+            });
+
+            it("'lintFiles(\"subdir\")' should not ignore './subdir' even if 'ignorePatterns' contains it.", async () => {
+                ESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({ ignorePatterns: ["/subdir"] }),
+                        "subdir/.eslintrc.json": JSON.stringify({ root: true }),
+                        "subdir/index.js": "console.log(\"hello\")"
+                    }
+                }).ESLint;
+                eslint = new ESLint();
+
+                // Don't throw "file not found" error.
+                await eslint.lintFiles("subdir");
+            });
+        });
+
+        it("should throw if non-boolean value is given to 'options.warnIgnored' option", async () => {
+            eslint = new ESLint();
+            await assert.rejects(() => eslint.lintFiles(777), /'patterns' must be a non-empty string or an array of non-empty strings/u);
+            await assert.rejects(() => eslint.lintFiles([null]), /'patterns' must be a non-empty string or an array of non-empty strings/u);
+        });
+    });
+
+    describe("calculateConfigForFile", () => {
+        it("should return the info from Config#getConfig when called", async () => {
+            const options = {
+                overrideConfigFile: getFixturePath("configurations", "quotes-error.json")
+            };
+            const engine = new ESLint(options);
+            const filePath = getFixturePath("single-quoted.js");
+            const actualConfig = await engine.calculateConfigForFile(filePath);
+            const expectedConfig = new CascadingConfigArrayFactory({ specificConfigPath: options.overrideConfigFile })
+                .getConfigArrayForFile(filePath)
+                .extractConfig(filePath)
+                .toCompatibleObjectAsConfigFileContent();
+
+            assert.deepStrictEqual(actualConfig, expectedConfig);
+        });
+
+
+        it("should return the config when run from within a subdir", async () => {
+            const options = {
+                cwd: getFixturePath("config-hierarchy", "root-true", "parent", "root", "subdir")
+            };
+            const engine = new ESLint(options);
+            const filePath = getFixturePath("config-hierarchy", "root-true", "parent", "root", ".eslintrc");
+            const actualConfig = await engine.calculateConfigForFile("./.eslintrc");
+            const expectedConfig = new CascadingConfigArrayFactory(options)
+                .getConfigArrayForFile(filePath)
+                .extractConfig(filePath)
+                .toCompatibleObjectAsConfigFileContent();
+
+            assert.deepStrictEqual(actualConfig, expectedConfig);
+        });
+
+        it("should throw an error if a directory path was given.", async () => {
+            const engine = new ESLint();
+
+            try {
+                await engine.calculateConfigForFile(".");
+            } catch (error) {
+                assert.strictEqual(error.messageTemplate, "print-config-with-directory-path");
+                return;
+            }
+            assert.fail("should throw an error");
+        });
+
+        it("should throw if non-string value is given to 'filePath' parameter", async () => {
+            const eslint = new ESLint();
+
+            await assert.rejects(() => eslint.calculateConfigForFile(null), /'filePath' must be a non-empty string/u);
+        });
+    });
+
+    describe("isPathIgnored", () => {
+        it("should check if the given path is ignored", async () => {
+            const engine = new ESLint({
+                ignorePath: getFixturePath(".eslintignore2"),
+                cwd: getFixturePath()
+            });
+
+            assert(await engine.isPathIgnored("undef.js"));
+            assert(!await engine.isPathIgnored("passing.js"));
+        });
+
+        it("should return false if ignoring is disabled", async () => {
+            const engine = new ESLint({
+                ignore: false,
+                ignorePath: getFixturePath(".eslintignore2"),
+                cwd: getFixturePath()
+            });
+
+            assert(!await engine.isPathIgnored("undef.js"));
+        });
+
+        // https://github.com/eslint/eslint/issues/5547
+        it("should return true for default ignores even if ignoring is disabled", async () => {
+            const engine = new ESLint({
+                ignore: false,
+                cwd: getFixturePath("cli-engine")
+            });
+
+            assert(await engine.isPathIgnored("node_modules/foo.js"));
+        });
+
+        describe("about the default ignore patterns", () => {
+            it("should always apply defaultPatterns if ignore option is true", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
+            });
+
+            it("should still apply defaultPatterns if ignore option is is false", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ ignore: false, cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "node_modules/package/file.js")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "subdir/node_modules/package/file.js")));
+            });
+
+            it("should allow subfolders of defaultPatterns to be unignored by ignorePattern", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({
+                    cwd,
+                    overrideConfig: {
+                        ignorePatterns: "!/node_modules/package"
+                    }
+                });
+
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
+            });
+
+            it("should allow subfolders of defaultPatterns to be unignored by ignorePath", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ cwd, ignorePath: getFixturePath("ignored-paths", ".eslintignoreWithUnignoredDefaults") });
+
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "package", "file.js")));
+            });
+
+            it("should ignore dotfiles", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
+            });
+
+            it("should ignore directories beginning with a dot", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
+            });
+
+            it("should still ignore dotfiles when ignore option disabled", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ ignore: false, cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", ".foo")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar")));
+            });
+
+            it("should still ignore directories beginning with a dot when ignore option disabled", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ ignore: false, cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", ".foo/bar")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "foo/.bar/baz")));
+            });
+
+            it("should not ignore absolute paths containing '..'", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ cwd });
+
+                assert(!await engine.isPathIgnored(`${getFixturePath("ignored-paths", "foo")}/../unignored.js`));
+            });
+
+            it("should ignore /node_modules/ relative to .eslintignore when loaded", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ ignorePath: getFixturePath("ignored-paths", ".eslintignore"), cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "node_modules", "existing.js")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "foo", "node_modules", "existing.js")));
+            });
+
+            it("should ignore /node_modules/ relative to cwd without an .eslintignore", async () => {
+                const cwd = getFixturePath("ignored-paths", "no-ignore-file");
+                const engine = new ESLint({ cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "node_modules", "existing.js")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "no-ignore-file", "foo", "node_modules", "existing.js")));
+            });
+        });
+
+        describe("with no .eslintignore file", () => {
+            it("should not travel to parent directories to find .eslintignore when it's missing and cwd is provided", async () => {
+                const cwd = getFixturePath("ignored-paths", "configurations");
+                const engine = new ESLint({ cwd });
+
+                // a .eslintignore in parent directories includes `*.js`, but don't load it.
+                assert(!await engine.isPathIgnored("foo.js"));
+                assert(await engine.isPathIgnored("node_modules/foo.js"));
+            });
+
+            it("should return false for files outside of the cwd (with no ignore file provided)", async () => {
+
+                // Default ignore patterns should not inadvertently ignore files in parent directories
+                const engine = new ESLint({ cwd: getFixturePath("ignored-paths", "no-ignore-file") });
+
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
+            });
+        });
+
+        describe("with .eslintignore file or package.json file", () => {
+            it("should load .eslintignore from cwd when explicitly passed", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ cwd });
+
+                // `${cwd}/.eslintignore` includes `sampleignorepattern`.
+                assert(await engine.isPathIgnored("sampleignorepattern"));
+            });
+
+            it("should use package.json's eslintIgnore files if no specified .eslintignore file", async () => {
+                const cwd = getFixturePath("ignored-paths", "package-json-ignore");
+                const engine = new ESLint({ cwd });
+
+                assert(await engine.isPathIgnored("hello.js"));
+                assert(await engine.isPathIgnored("world.js"));
+            });
+
+            it("should use correct message template if failed to parse package.json", () => {
+                const cwd = getFixturePath("ignored-paths", "broken-package-json");
+
+                assert.throws(() => {
+                    try {
+                        // eslint-disable-next-line no-new
+                        new ESLint({ cwd });
+                    } catch (error) {
+                        assert.strictEqual(error.messageTemplate, "failed-to-read-json");
+                        throw error;
+                    }
+                });
+            });
+
+            it("should not use package.json's eslintIgnore files if specified .eslintignore file", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ cwd });
+
+                /*
+                 * package.json includes `hello.js` and `world.js`.
+                 * .eslintignore includes `sampleignorepattern`.
+                 */
+                assert(!await engine.isPathIgnored("hello.js"));
+                assert(!await engine.isPathIgnored("world.js"));
+                assert(await engine.isPathIgnored("sampleignorepattern"));
+            });
+
+            it("should error if package.json's eslintIgnore is not an array of file paths", () => {
+                const cwd = getFixturePath("ignored-paths", "bad-package-json-ignore");
+
+                assert.throws(() => {
+                    // eslint-disable-next-line no-new
+                    new ESLint({ cwd });
+                }, /Package\.json eslintIgnore property requires an array of paths/u);
+            });
+        });
+
+        describe("with --ignore-pattern option", () => {
+            it("should accept a string for options.ignorePattern", async () => {
+                const cwd = getFixturePath("ignored-paths", "ignore-pattern");
+                const engine = new ESLint({
+                    overrideConfig: {
+                        ignorePatterns: "ignore-me.txt"
+                    },
+                    cwd
+                });
+
+                assert(await engine.isPathIgnored("ignore-me.txt"));
+            });
+
+            it("should accept an array for options.ignorePattern", async () => {
+                const engine = new ESLint({
+                    overrideConfig: {
+                        ignorePatterns: ["a", "b"]
+                    },
+                    useEslintrc: false
+                });
+
+                assert(await engine.isPathIgnored("a"));
+                assert(await engine.isPathIgnored("b"));
+                assert(!await engine.isPathIgnored("c"));
+            });
+
+            it("should return true for files which match an ignorePattern even if they do not exist on the filesystem", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({
+                    overrideConfig: {
+                        ignorePatterns: "not-a-file"
+                    },
+                    cwd
+                });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "not-a-file")));
+            });
+
+            it("should return true for file matching an ignore pattern exactly", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ overrideConfig: { ignorePatterns: "undef.js" }, cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
+            });
+
+            it("should return false for file matching an invalid ignore pattern with leading './'", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ overrideConfig: { ignorePatterns: "./undef.js" }, cwd });
+
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
+            });
+
+            it("should return false for file in subfolder of cwd matching an ignore pattern with leading '/'", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ overrideConfig: { ignorePatterns: "/undef.js" }, cwd });
+
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "subdir", "undef.js")));
+            });
+
+            it("should return true for file matching a child of an ignore pattern", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ overrideConfig: { ignorePatterns: "ignore-pattern" }, cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "ignore-me.txt")));
+            });
+
+            it("should return true for file matching a grandchild of an ignore pattern", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ overrideConfig: { ignorePatterns: "ignore-pattern" }, cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "ignore-pattern", "subdir", "ignore-me.txt")));
+            });
+
+            it("should return false for file not matching any ignore pattern", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ overrideConfig: { ignorePatterns: "failing.js" }, cwd });
+
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "unignored.js")));
+            });
+
+            it("two globstar '**' ignore pattern should ignore files in nested directories", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({ overrideConfig: { ignorePatterns: "**/*.js" }, cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.js")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.js")));
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "foo.j2")));
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "foo/bar.j2")));
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "foo/bar/baz.j2")));
+            });
+        });
+
+        describe("with --ignore-path option", () => {
+            it("initialization with ignorePath should work when cwd is a parent directory", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const ignorePath = getFixturePath("ignored-paths", "custom-name", "ignore-file");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(await engine.isPathIgnored("custom-name/foo.js"));
+            });
+
+            it("initialization with ignorePath should work when the file is in the cwd", async () => {
+                const cwd = getFixturePath("ignored-paths", "custom-name");
+                const ignorePath = getFixturePath("ignored-paths", "custom-name", "ignore-file");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(await engine.isPathIgnored("foo.js"));
+            });
+
+            it("initialization with ignorePath should work when cwd is a subdirectory", async () => {
+                const cwd = getFixturePath("ignored-paths", "custom-name", "subdirectory");
+                const ignorePath = getFixturePath("ignored-paths", "custom-name", "ignore-file");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(await engine.isPathIgnored("../custom-name/foo.js"));
+            });
+
+            it("initialization with invalid file should throw error", () => {
+                const cwd = getFixturePath("ignored-paths");
+                const ignorePath = getFixturePath("ignored-paths", "not-a-directory", ".foobaz");
+
+                assert.throws(() => {
+                    // eslint-disable-next-line no-new
+                    new ESLint({ ignorePath, cwd });
+                }, /Cannot read \.eslintignore file/u);
+            });
+
+            it("should return false for files outside of ignorePath's directory", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const ignorePath = getFixturePath("ignored-paths", "custom-name", "ignore-file");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
+            });
+
+            it("should resolve relative paths from CWD", async () => {
+                const cwd = getFixturePath("ignored-paths", "subdir");
+                const ignorePath = getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
+            });
+
+            it("should resolve relative paths from CWD when it's in a child directory", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const ignorePath = getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "subdir/undef.js")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "undef.js")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "foo.js")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "subdir/foo.js")));
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "node_modules/bar.js")));
+            });
+
+            it("should resolve relative paths from CWD when it contains negated globs", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const ignorePath = getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(await engine.isPathIgnored("subdir/blah.txt"));
+                assert(await engine.isPathIgnored("blah.txt"));
+                assert(await engine.isPathIgnored("subdir/bar.txt"));
+                assert(!await engine.isPathIgnored("bar.txt"));
+                assert(!await engine.isPathIgnored("subdir/baz.txt"));
+                assert(!await engine.isPathIgnored("baz.txt"));
+            });
+
+            it("should resolve default ignore patterns from the CWD even when the ignorePath is in a subdirectory", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const ignorePath = getFixturePath("ignored-paths", "subdir/.eslintignoreInChildDir");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(await engine.isPathIgnored("node_modules/blah.js"));
+            });
+
+            it("should resolve default ignore patterns from the CWD even when the ignorePath is in a parent directory", async () => {
+                const cwd = getFixturePath("ignored-paths", "subdir");
+                const ignorePath = getFixturePath("ignored-paths", ".eslintignoreForDifferentCwd");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(await engine.isPathIgnored("node_modules/blah.js"));
+            });
+
+            it("should handle .eslintignore which contains CRLF correctly.", async () => {
+                const ignoreFileContent = fs.readFileSync(getFixturePath("ignored-paths", "crlf/.eslintignore"), "utf8");
+
+                assert(ignoreFileContent.includes("\r"), "crlf/.eslintignore should contains CR.");
+                const cwd = getFixturePath("ignored-paths");
+                const ignorePath = getFixturePath("ignored-paths", "crlf/.eslintignore");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide1/a.js")));
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide2/a.js")));
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "crlf/hide3/a.js")));
+            });
+
+            it("should not include comments in ignore rules", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const ignorePath = getFixturePath("ignored-paths", ".eslintignoreWithComments");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(!await engine.isPathIgnored("# should be ignored"));
+                assert(await engine.isPathIgnored("this_one_not"));
+            });
+
+            it("should ignore a non-negated pattern", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const ignorePath = getFixturePath("ignored-paths", ".eslintignoreWithNegation");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(await engine.isPathIgnored(getFixturePath("ignored-paths", "negation", "ignore.js")));
+            });
+
+            it("should not ignore a negated pattern", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const ignorePath = getFixturePath("ignored-paths", ".eslintignoreWithNegation");
+                const engine = new ESLint({ ignorePath, cwd });
+
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "negation", "unignore.js")));
+            });
+        });
+
+        describe("with --ignore-path option and --ignore-pattern option", () => {
+            it("should return false for ignored file when unignored with ignore pattern", async () => {
+                const cwd = getFixturePath("ignored-paths");
+                const engine = new ESLint({
+                    ignorePath: getFixturePath("ignored-paths", ".eslintignore"),
+                    overrideConfig: {
+                        ignorePatterns: "!sampleignorepattern"
+                    },
+                    cwd
+                });
+
+                assert(!await engine.isPathIgnored(getFixturePath("ignored-paths", "sampleignorepattern")));
+            });
+        });
+
+        it("should throw if non-string value is given to 'filePath' parameter", async () => {
+            const eslint = new ESLint();
+
+            await assert.rejects(() => eslint.isPathIgnored(null), /'filePath' must be a non-empty string/u);
+        });
+    });
+
+    describe("loadFormatter()", () => {
+        it("should return a formatter object when a bundled formatter is requested", async () => {
+            const engine = new ESLint();
+            const formatter = await engine.loadFormatter("compact");
+
+            assert.strictEqual(typeof formatter, "object");
+            assert.strictEqual(typeof formatter.format, "function");
+        });
+
+        it("should return a formatter object when no argument is passed", async () => {
+            const engine = new ESLint();
+            const formatter = await engine.loadFormatter();
+
+            assert.strictEqual(typeof formatter, "object");
+            assert.strictEqual(typeof formatter.format, "function");
+        });
+
+        it("should return a formatter object when a custom formatter is requested", async () => {
+            const engine = new ESLint();
+            const formatter = await engine.loadFormatter(getFixturePath("formatters", "simple.js"));
+
+            assert.strictEqual(typeof formatter, "object");
+            assert.strictEqual(typeof formatter.format, "function");
+        });
+
+        it("should return a formatter object when a custom formatter is requested, also if the path has backslashes", async () => {
+            const engine = new ESLint({
+                cwd: path.join(fixtureDir, "..")
+            });
+            const formatter = await engine.loadFormatter(".\\fixtures\\formatters\\simple.js");
+
+            assert.strictEqual(typeof formatter, "object");
+            assert.strictEqual(typeof formatter.format, "function");
+        });
+
+        it("should return a formatter object when a formatter prefixed with eslint-formatter is requested", async () => {
+            const engine = new ESLint({
+                cwd: getFixturePath("cli-engine")
+            });
+            const formatter = await engine.loadFormatter("bar");
+
+            assert.strictEqual(typeof formatter, "object");
+            assert.strictEqual(typeof formatter.format, "function");
+        });
+
+        it("should return a formatter object when a formatter is requested, also when the eslint-formatter prefix is included in the format argument", async () => {
+            const engine = new ESLint({
+                cwd: getFixturePath("cli-engine")
+            });
+            const formatter = await engine.loadFormatter("eslint-formatter-bar");
+
+            assert.strictEqual(typeof formatter, "object");
+            assert.strictEqual(typeof formatter.format, "function");
+        });
+
+        it("should return a formatter object when a formatter is requested within a scoped npm package", async () => {
+            const engine = new ESLint({
+                cwd: getFixturePath("cli-engine")
+            });
+            const formatter = await engine.loadFormatter("@somenamespace/foo");
+
+            assert.strictEqual(typeof formatter, "object");
+            assert.strictEqual(typeof formatter.format, "function");
+        });
+
+        it("should return a formatter object when a formatter is requested within a scoped npm package, also when the eslint-formatter prefix is included in the format argument", async () => {
+            const engine = new ESLint({
+                cwd: getFixturePath("cli-engine")
+            });
+            const formatter = await engine.loadFormatter("@somenamespace/eslint-formatter-foo");
+
+            assert.strictEqual(typeof formatter, "object");
+            assert.strictEqual(typeof formatter.format, "function");
+        });
+
+        it("should throw if a customer formatter doesn't exist", async () => {
+            const engine = new ESLint();
+            const formatterPath = getFixturePath("formatters", "doesntexist.js");
+            const fullFormatterPath = path.resolve(formatterPath);
+
+            await assert.rejects(async () => {
+                await engine.loadFormatter(formatterPath);
+            }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`), "u"));
+        });
+
+        it("should throw if a built-in formatter doesn't exist", async () => {
+            const engine = new ESLint();
+            const fullFormatterPath = path.resolve(__dirname, "../../../lib/cli-engine/formatters/special");
+
+            await assert.rejects(async () => {
+                await engine.loadFormatter("special");
+            }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${fullFormatterPath}\nError: Cannot find module '${fullFormatterPath}'`), "u"));
+        });
+
+        it("should throw if the required formatter exists but has an error", async () => {
+            const engine = new ESLint();
+            const formatterPath = getFixturePath("formatters", "broken.js");
+
+            await assert.rejects(async () => {
+                await engine.loadFormatter(formatterPath);
+            }, new RegExp(escapeStringRegExp(`There was a problem loading formatter: ${formatterPath}\nError: Cannot find module 'this-module-does-not-exist'`), "u"));
+        });
+
+        it("should throw if a non-string formatter name is passed", async () => {
+            const engine = new ESLint();
+
+            await assert.rejects(async () => {
+                await engine.loadFormatter(5);
+            }, /'name' must be a string/u);
+        });
+    });
+
+    describe("getErrorResults()", () => {
+        it("should report 5 error messages when looking for errors only", async () => {
+            process.chdir(originalDir);
+            const engine = new ESLint();
+            const results = await engine.lintText("var foo = 'bar';");
+            const errorResults = ESLint.getErrorResults(results);
+
+            assert.strictEqual(errorResults[0].messages.length, 5);
+            assert.strictEqual(errorResults[0].errorCount, 5);
+            assert.strictEqual(errorResults[0].fixableErrorCount, 3);
+            assert.strictEqual(errorResults[0].fixableWarningCount, 0);
+            assert.strictEqual(errorResults[0].messages[0].ruleId, "strict");
+            assert.strictEqual(errorResults[0].messages[0].severity, 2);
+            assert.strictEqual(errorResults[0].messages[1].ruleId, "no-var");
+            assert.strictEqual(errorResults[0].messages[1].severity, 2);
+            assert.strictEqual(errorResults[0].messages[2].ruleId, "no-unused-vars");
+            assert.strictEqual(errorResults[0].messages[2].severity, 2);
+            assert.strictEqual(errorResults[0].messages[3].ruleId, "quotes");
+            assert.strictEqual(errorResults[0].messages[3].severity, 2);
+            assert.strictEqual(errorResults[0].messages[4].ruleId, "eol-last");
+            assert.strictEqual(errorResults[0].messages[4].severity, 2);
+        });
+
+        it("should not mutate passed report parameter", async () => {
+            process.chdir(originalDir);
+            const engine = new ESLint({
+                overrideConfig: {
+                    rules: { quotes: [1, "double"] }
+                }
+            });
+            const results = await engine.lintText("var foo = 'bar';");
+            const reportResultsLength = results[0].messages.length;
+
+            ESLint.getErrorResults(results);
+
+            assert.strictEqual(results[0].messages.length, reportResultsLength);
+        });
+
+        it("should report a warningCount of 0 when looking for errors only", async () => {
+            process.chdir(originalDir);
+            const engine = new ESLint();
+            const results = await engine.lintText("var foo = 'bar';");
+            const errorResults = ESLint.getErrorResults(results);
+
+            assert.strictEqual(errorResults[0].warningCount, 0);
+            assert.strictEqual(errorResults[0].fixableWarningCount, 0);
+        });
+
+        it("should return 0 error or warning messages even when the file has warnings", async () => {
+            const engine = new ESLint({
+                ignorePath: path.join(fixtureDir, ".eslintignore"),
+                cwd: path.join(fixtureDir, "..")
+            });
+            const options = {
+                filePath: "fixtures/passing.js",
+                warnIgnored: true
+            };
+            const results = await engine.lintText("var bar = foo;", options);
+            const errorReport = ESLint.getErrorResults(results);
+
+            assert.strictEqual(errorReport.length, 0);
+            assert.strictEqual(results.length, 1);
+            assert.strictEqual(results[0].errorCount, 0);
+            assert.strictEqual(results[0].warningCount, 1);
+        });
+
+        it("should return source code of file in the `source` property", async () => {
+            process.chdir(originalDir);
+            const engine = new ESLint({
+                useEslintrc: false,
+                overrideConfig: {
+                    rules: { quotes: [2, "double"] }
+                }
+            });
+            const results = await engine.lintText("var foo = 'bar';");
+            const errorResults = ESLint.getErrorResults(results);
+
+            assert.strictEqual(errorResults[0].messages.length, 1);
+            assert.strictEqual(errorResults[0].source, "var foo = 'bar';");
+        });
+
+        it("should contain `output` property after fixes", async () => {
+            process.chdir(originalDir);
+            const engine = new ESLint({
+                useEslintrc: false,
+                fix: true,
+                overrideConfig: {
+                    rules: {
+                        semi: 2,
+                        "no-console": 2
+                    }
+                }
+            });
+            const results = await engine.lintText("console.log('foo')");
+            const errorResults = ESLint.getErrorResults(results);
+
+            assert.strictEqual(errorResults[0].messages.length, 1);
+            assert.strictEqual(errorResults[0].output, "console.log('foo');");
+        });
+    });
+
+    describe("outputFixes()", () => {
+        afterEach(() => {
+            sinon.verifyAndRestore();
+        });
+
+        it("should call fs.writeFile() for each result with output", async () => {
+            const fakeFS = leche.fake(fs);
+            const spy = fakeFS.writeFile = sinon.spy(callLastArgument);
+            const localESLint = proxyquire("../../../lib/eslint/eslint", {
+                fs: fakeFS
+            }).ESLint;
+            const results = [
+                {
+                    filePath: path.resolve("foo.js"),
+                    output: "bar"
+                },
+                {
+                    filePath: path.resolve("bar.js"),
+                    output: "baz"
+                }
+            ];
+
+            await localESLint.outputFixes(results);
+
+            assert.strictEqual(spy.callCount, 2);
+            assert(spy.firstCall.calledWithExactly(path.resolve("foo.js"), "bar", sinon.match.func), "First call was incorrect.");
+            assert(spy.secondCall.calledWithExactly(path.resolve("bar.js"), "baz", sinon.match.func), "Second call was incorrect.");
+        });
+
+        it("should call fs.writeFile() for each result with output and not at all for a result without output", async () => {
+            const fakeFS = leche.fake(fs);
+            const spy = fakeFS.writeFile = sinon.spy(callLastArgument);
+            const localESLint = proxyquire("../../../lib/eslint/eslint", {
+                fs: fakeFS
+            }).ESLint;
+            const results = [
+                {
+                    filePath: path.resolve("foo.js"),
+                    output: "bar"
+                },
+                {
+                    filePath: path.resolve("abc.js")
+                },
+                {
+                    filePath: path.resolve("bar.js"),
+                    output: "baz"
+                }
+            ];
+
+            await localESLint.outputFixes(results);
+
+            assert.strictEqual(spy.callCount, 2);
+            assert(spy.firstCall.calledWithExactly(path.resolve("foo.js"), "bar", sinon.match.func), "First call was incorrect.");
+            assert(spy.secondCall.calledWithExactly(path.resolve("bar.js"), "baz", sinon.match.func), "Second call was incorrect.");
+        });
+
+        it("should throw if non object array is given to 'results' parameter", async () => {
+            await assert.rejects(() => ESLint.outputFixes(null), /'results' must be an array/u);
+            await assert.rejects(() => ESLint.outputFixes([null]), /'results' must include only objects/u);
+        });
+    });
+
+    describe("when evaluating code with comments to change config when allowInlineConfig is disabled", () => {
+        it("should report a violation for disabling rules", async () => {
+            const code = [
+                "alert('test'); // eslint-disable-line no-alert"
+            ].join("\n");
+            const config = {
+                ignore: true,
+                allowInlineConfig: false,
+                overrideConfig: {
+                    env: { browser: true },
+                    rules: {
+                        "eol-last": 0,
+                        "no-alert": 1,
+                        "no-trailing-spaces": 0,
+                        strict: 0,
+                        quotes: 0
+                    }
+                }
+            };
+            const eslintCLI = new ESLint(config);
+            const results = await eslintCLI.lintText(code);
+            const messages = results[0].messages;
+
+            assert.strictEqual(messages.length, 1);
+            assert.strictEqual(messages[0].ruleId, "no-alert");
+        });
+
+        it("should not report a violation by default", async () => {
+            const code = [
+                "alert('test'); // eslint-disable-line no-alert"
+            ].join("\n");
+            const config = {
+                ignore: true,
+                allowInlineConfig: true,
+                overrideConfig: {
+                    env: { browser: true },
+                    rules: {
+                        "eol-last": 0,
+                        "no-alert": 1,
+                        "no-trailing-spaces": 0,
+                        strict: 0,
+                        quotes: 0
+                    }
+                }
+            };
+            const eslintCLI = new ESLint(config);
+            const results = await eslintCLI.lintText(code);
+            const messages = results[0].messages;
+
+            assert.strictEqual(messages.length, 0);
+        });
+    });
+
+    describe("when evaluating code when reportUnusedDisableDirectives is enabled", () => {
+        it("should report problems for unused eslint-disable directives", async () => {
+            const eslint = new ESLint({ useEslintrc: false, reportUnusedDisableDirectives: "error" });
+
+            assert.deepStrictEqual(
+                await eslint.lintText("/* eslint-disable */"),
+                [
+                    {
+                        filePath: "<text>",
+                        messages: [
+                            {
+                                ruleId: null,
+                                message: "Unused eslint-disable directive (no problems were reported).",
+                                line: 1,
+                                column: 1,
+                                severity: 2,
+                                nodeType: null
+                            }
+                        ],
+                        errorCount: 1,
+                        warningCount: 0,
+                        fixableErrorCount: 0,
+                        fixableWarningCount: 0,
+                        source: "/* eslint-disable */",
+                        usedDeprecatedRules: []
+                    }
+                ]
+            );
+        });
+    });
+
+    describe("when retreiving version number", () => {
+        it("should return current version number", () => {
+            const eslintCLI = require("../../../lib/eslint").ESLint;
+            const version = eslintCLI.version;
+
+            assert.strictEqual(typeof version, "string");
+            assert(parseInt(version[0], 10) >= 3);
+        });
+    });
+
+    describe("mutability", () => {
+        describe("plugins", () => {
+            it("Loading plugin in one instance doesn't mutate to another instance", async () => {
+                const filePath = getFixturePath("single-quoted.js");
+                const engine1 = eslintWithPlugins({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    overrideConfig: {
+                        plugins: ["example"],
+                        rules: { "example/example-rule": 1 }
+                    }
+                });
+                const engine2 = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false
+                });
+                const fileConfig1 = await engine1.calculateConfigForFile(filePath);
+                const fileConfig2 = await engine2.calculateConfigForFile(filePath);
+
+                // plugin
+                assert.deepStrictEqual(fileConfig1.plugins, ["example"], "Plugin is present for engine 1");
+                assert.deepStrictEqual(fileConfig2.plugins, [], "Plugin is not present for engine 2");
+            });
+        });
+
+        describe("rules", () => {
+            it("Loading rules in one instance doesn't mutate to another instance", async () => {
+                const filePath = getFixturePath("single-quoted.js");
+                const engine1 = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false,
+                    overrideConfig: { rules: { "example/example-rule": 1 } }
+                });
+                const engine2 = new ESLint({
+                    cwd: path.join(fixtureDir, ".."),
+                    useEslintrc: false
+                });
+                const fileConfig1 = await engine1.calculateConfigForFile(filePath);
+                const fileConfig2 = await engine2.calculateConfigForFile(filePath);
+
+                // plugin
+                assert.deepStrictEqual(fileConfig1.rules["example/example-rule"], [1], "example is present for engine 1");
+                assert.strictEqual(fileConfig2.rules["example/example-rule"], void 0, "example is not present for engine 2");
+            });
+        });
+    });
+
+    describe("with ignorePatterns config", () => {
+        const root = getFixturePath("cli-engine/ignore-patterns");
+
+        /** @type {typeof ESLint} */
+        let InMemoryESLint;
+
+        describe("ignorePatterns can add an ignore pattern ('foo.js').", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({
+                            ignorePatterns: "foo.js"
+                        }),
+                        "foo.js": "",
+                        "bar.js": "",
+                        "subdir/foo.js": "",
+                        "subdir/bar.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), true);
+                assert.strictEqual(await engine.isPathIgnored("subdir/foo.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("bar.js"), false);
+                assert.strictEqual(await engine.isPathIgnored("subdir/bar.js"), false);
+            });
+
+            it("'lintFiles()' should not verify 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar.js"),
+                    path.join(root, "subdir/bar.js")
+                ]);
+            });
+        });
+
+        describe("ignorePatterns can add ignore patterns ('foo.js', '/bar.js').", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({
+                            ignorePatterns: ["foo.js", "/bar.js"]
+                        }),
+                        "foo.js": "",
+                        "bar.js": "",
+                        "baz.js": "",
+                        "subdir/foo.js": "",
+                        "subdir/bar.js": "",
+                        "subdir/baz.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), true);
+                assert.strictEqual(await engine.isPathIgnored("subdir/foo.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'true' for '/bar.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("bar.js"), true);
+                assert.strictEqual(await engine.isPathIgnored("subdir/bar.js"), false);
+            });
+
+            it("'lintFiles()' should not verify 'foo.js' and '/bar.js'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "baz.js"),
+                    path.join(root, "subdir/bar.js"),
+                    path.join(root, "subdir/baz.js")
+                ]);
+            });
+        });
+
+        describe("ignorePatterns can unignore '/node_modules/foo'.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({
+                            ignorePatterns: "!/node_modules/foo"
+                        }),
+                        "node_modules/foo/index.js": "",
+                        "node_modules/foo/.dot.js": "",
+                        "node_modules/bar/index.js": "",
+                        "foo.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'node_modules/foo/index.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("node_modules/foo/index.js"), false);
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'node_modules/foo/.dot.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("node_modules/foo/.dot.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'node_modules/bar/index.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("node_modules/bar/index.js"), true);
+            });
+
+            it("'lintFiles()' should verify 'node_modules/foo/index.js'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "foo.js"),
+                    path.join(root, "node_modules/foo/index.js")
+                ]);
+            });
+        });
+
+        describe("ignorePatterns can unignore '.eslintrc.js'.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.js": `module.exports = ${JSON.stringify({
+                            ignorePatterns: "!.eslintrc.js"
+                        })}`,
+                        "foo.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'false' for '.eslintrc.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored(".eslintrc.js"), false);
+            });
+
+            it("'lintFiles()' should verify '.eslintrc.js'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, ".eslintrc.js"),
+                    path.join(root, "foo.js")
+                ]);
+            });
+        });
+
+        describe(".eslintignore can re-ignore files that are unignored by ignorePatterns.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.js": `module.exports = ${JSON.stringify({
+                            ignorePatterns: "!.*"
+                        })}`,
+                        ".eslintignore": ".foo*",
+                        ".foo.js": "",
+                        ".bar.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'true' for re-ignored '.foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored(".foo.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'false' for unignored '.bar.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored(".bar.js"), false);
+            });
+
+            it("'lintFiles()' should not verify re-ignored '.foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, ".bar.js"),
+                    path.join(root, ".eslintrc.js")
+                ]);
+            });
+        });
+
+        describe(".eslintignore can unignore files that are ignored by ignorePatterns.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.js": `module.exports = ${JSON.stringify({
+                            ignorePatterns: "*.js"
+                        })}`,
+                        ".eslintignore": "!foo.js",
+                        "foo.js": "",
+                        "bar.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), false);
+            });
+
+            it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("bar.js"), true);
+            });
+
+            it("'lintFiles()' should verify unignored 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "foo.js")
+                ]);
+            });
+        });
+
+        describe("ignorePatterns in the config file in a child directory affects to only in the directory.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({
+                            ignorePatterns: "foo.js"
+                        }),
+                        "subdir/.eslintrc.json": JSON.stringify({
+                            ignorePatterns: "bar.js"
+                        }),
+                        "foo.js": "",
+                        "bar.js": "",
+                        "subdir/foo.js": "",
+                        "subdir/bar.js": "",
+                        "subdir/subsubdir/foo.js": "",
+                        "subdir/subsubdir/bar.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), true);
+                assert.strictEqual(await engine.isPathIgnored("subdir/foo.js"), true);
+                assert.strictEqual(await engine.isPathIgnored("subdir/subsubdir/foo.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'bar.js' in 'subdir'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("subdir/bar.js"), true);
+                assert.strictEqual(await engine.isPathIgnored("subdir/subsubdir/bar.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'bar.js' in the outside of 'subdir'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("bar.js"), false);
+            });
+
+            it("'lintFiles()' should verify 'bar.js' in the outside of 'subdir'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar.js")
+                ]);
+            });
+        });
+
+        describe("ignorePatterns in the config file in a child directory can unignore the ignored files in the parent directory's config.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({
+                            ignorePatterns: "foo.js"
+                        }),
+                        "subdir/.eslintrc.json": JSON.stringify({
+                            ignorePatterns: "!foo.js"
+                        }),
+                        "foo.js": "",
+                        "subdir/foo.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("subdir/foo.js"), false);
+            });
+
+            it("'lintFiles()' should verify 'foo.js' in the child directory.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "subdir/foo.js")
+                ]);
+            });
+        });
+
+        describe(".eslintignore can unignore files that are ignored by ignorePatterns in the config file in the child directory.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({}),
+                        "subdir/.eslintrc.json": JSON.stringify({
+                            ignorePatterns: "*.js"
+                        }),
+                        ".eslintignore": "!foo.js",
+                        "foo.js": "",
+                        "subdir/foo.js": "",
+                        "subdir/bar.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'false' for unignored 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), false);
+                assert.strictEqual(await engine.isPathIgnored("subdir/foo.js"), false);
+            });
+
+            it("'isPathIgnored()' should return 'true' for ignored 'bar.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("subdir/bar.js"), true);
+            });
+
+            it("'lintFiles()' should verify unignored 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "foo.js"),
+                    path.join(root, "subdir/foo.js")
+                ]);
+            });
+        });
+
+        describe("if the config in a child directory has 'root:true', ignorePatterns in the config file in the parent directory should not be used.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({
+                            ignorePatterns: "foo.js"
+                        }),
+                        "subdir/.eslintrc.json": JSON.stringify({
+                            root: true,
+                            ignorePatterns: "bar.js"
+                        }),
+                        "foo.js": "",
+                        "bar.js": "",
+                        "subdir/foo.js": "",
+                        "subdir/bar.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'foo.js' in the root directory.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("bar.js"), false);
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'foo.js' in the child directory.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("subdir/foo.js"), false);
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("subdir/bar.js"), true);
+            });
+
+            it("'lintFiles()' should verify 'bar.js' in the root directory and 'foo.js' in the child directory.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar.js"),
+                    path.join(root, "subdir/foo.js")
+                ]);
+            });
+        });
+
+        describe("even if the config in a child directory has 'root:true', .eslintignore should be used.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({}),
+                        "subdir/.eslintrc.json": JSON.stringify({
+                            root: true,
+                            ignorePatterns: "bar.js"
+                        }),
+                        ".eslintignore": "foo.js",
+                        "foo.js": "",
+                        "bar.js": "",
+                        "subdir/foo.js": "",
+                        "subdir/bar.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), true);
+                assert.strictEqual(await engine.isPathIgnored("subdir/foo.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'bar.js' in the root directory.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("bar.js"), false);
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'bar.js' in the child directory.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("subdir/bar.js"), true);
+            });
+
+            it("'lintFiles()' should verify 'bar.js' in the root directory.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar.js")
+                ]);
+            });
+        });
+
+        describe("ignorePatterns in the shareable config should be used.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
+                            ignorePatterns: "foo.js"
+                        })}`,
+                        ".eslintrc.json": JSON.stringify({
+                            extends: "one"
+                        }),
+                        "foo.js": "",
+                        "bar.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("bar.js"), false);
+            });
+
+            it("'lintFiles()' should verify 'bar.js'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar.js")
+                ]);
+            });
+        });
+
+        describe("ignorePatterns in the shareable config should be relative to the entry config file.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
+                            ignorePatterns: "/foo.js"
+                        })}`,
+                        ".eslintrc.json": JSON.stringify({
+                            extends: "one"
+                        }),
+                        "foo.js": "",
+                        "subdir/foo.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'subdir/foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("subdir/foo.js"), false);
+            });
+
+            it("'lintFiles()' should verify 'subdir/foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "subdir/foo.js")
+                ]);
+            });
+        });
+
+        describe("ignorePatterns in a config file can unignore the files which are ignored by ignorePatterns in the shareable config.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
+                            ignorePatterns: "*.js"
+                        })}`,
+                        ".eslintrc.json": JSON.stringify({
+                            extends: "one",
+                            ignorePatterns: "!bar.js"
+                        }),
+                        "foo.js": "",
+                        "bar.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'true' for 'foo.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), true);
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'bar.js'.", async () => {
+                const engine = new InMemoryESLint();
+
+                assert.strictEqual(await engine.isPathIgnored("bar.js"), false);
+            });
+
+            it("'lintFiles()' should verify 'bar.js'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar.js")
+                ]);
+            });
+        });
+
+        describe("ignorePatterns in a config file should not be used if --no-ignore option was given.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({
+                            ignorePatterns: "*.js"
+                        }),
+                        "foo.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'isPathIgnored()' should return 'false' for 'foo.js'.", async () => {
+                const engine = new InMemoryESLint({ ignore: false });
+
+                assert.strictEqual(await engine.isPathIgnored("foo.js"), false);
+            });
+
+            it("'lintFiles()' should verify 'foo.js'.", async () => {
+                const engine = new InMemoryESLint({ ignore: false });
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "foo.js")
+                ]);
+            });
+        });
+
+        describe("ignorePatterns in overrides section is not allowed.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.js": `module.exports = ${JSON.stringify({
+                            overrides: [
+                                {
+                                    files: "*.js",
+                                    ignorePatterns: "foo.js"
+                                }
+                            ]
+                        })}`,
+                        "foo.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("should throw a configuration error.", async () => {
+                await assert.rejects(async () => {
+                    const engine = new InMemoryESLint();
+
+                    await engine.lintFiles("*.js");
+                }, /Unexpected top-level property "overrides\[0\]\.ignorePatterns"/u);
+            });
+        });
+    });
+
+    describe("'overrides[].files' adds lint targets", () => {
+        const root = getFixturePath("cli-engine/additional-lint-targets");
+        let InMemoryESLint;
+
+        describe("if { files: 'foo/*.txt', excludedFiles: '**/ignore.txt' } is present,", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({
+                            overrides: [
+                                {
+                                    files: "foo/*.txt",
+                                    excludedFiles: "**/ignore.txt"
+                                }
+                            ]
+                        }),
+                        "foo/nested/test.txt": "",
+                        "foo/test.js": "",
+                        "foo/test.txt": "",
+                        "foo/ignore.txt": "",
+                        "bar/test.js": "",
+                        "bar/test.txt": "",
+                        "bar/ignore.txt": "",
+                        "test.js": "",
+                        "test.txt": "",
+                        "ignore.txt": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' with a directory path should contain 'foo/test.txt'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("."))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar/test.js"),
+                    path.join(root, "foo/test.js"),
+                    path.join(root, "foo/test.txt"),
+                    path.join(root, "test.js")
+                ]);
+            });
+
+            it("'lintFiles()' with a glob pattern '*.js' should not contain 'foo/test.txt'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar/test.js"),
+                    path.join(root, "foo/test.js"),
+                    path.join(root, "test.js")
+                ]);
+            });
+        });
+
+        describe("if { files: 'foo/**/*.txt' } is present,", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({
+                            overrides: [
+                                {
+                                    files: "foo/**/*.txt"
+                                }
+                            ]
+                        }),
+                        "foo/nested/test.txt": "",
+                        "foo/test.js": "",
+                        "foo/test.txt": "",
+                        "bar/test.js": "",
+                        "bar/test.txt": "",
+                        "test.js": "",
+                        "test.txt": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("."))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar/test.js"),
+                    path.join(root, "foo/nested/test.txt"),
+                    path.join(root, "foo/test.js"),
+                    path.join(root, "foo/test.txt"),
+                    path.join(root, "test.js")
+                ]);
+            });
+        });
+
+        describe("if { files: 'foo/**/*' } is present,", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        ".eslintrc.json": JSON.stringify({
+                            overrides: [
+                                {
+                                    files: "foo/**/*"
+                                }
+                            ]
+                        }),
+                        "foo/nested/test.txt": "",
+                        "foo/test.js": "",
+                        "foo/test.txt": "",
+                        "bar/test.js": "",
+                        "bar/test.txt": "",
+                        "test.js": "",
+                        "test.txt": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' with a directory path should NOT contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("."))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar/test.js"),
+                    path.join(root, "foo/test.js"),
+                    path.join(root, "test.js")
+                ]);
+            });
+        });
+
+        describe("if { files: 'foo/**/*.txt' } is present in a shareable config,", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-config-foo/index.js": `module.exports = ${JSON.stringify({
+                            overrides: [
+                                {
+                                    files: "foo/**/*.txt"
+                                }
+                            ]
+                        })}`,
+                        ".eslintrc.json": JSON.stringify({
+                            extends: "foo"
+                        }),
+                        "foo/nested/test.txt": "",
+                        "foo/test.js": "",
+                        "foo/test.txt": "",
+                        "bar/test.js": "",
+                        "bar/test.txt": "",
+                        "test.js": "",
+                        "test.txt": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("."))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar/test.js"),
+                    path.join(root, "foo/nested/test.txt"),
+                    path.join(root, "foo/test.js"),
+                    path.join(root, "foo/test.txt"),
+                    path.join(root, "test.js")
+                ]);
+            });
+        });
+
+        describe("if { files: 'foo/**/*.txt' } is present in a plugin config,", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-plugin-foo/index.js": `exports.configs = ${JSON.stringify({
+                            bar: {
+                                overrides: [
+                                    {
+                                        files: "foo/**/*.txt"
+                                    }
+                                ]
+                            }
+                        })}`,
+                        ".eslintrc.json": JSON.stringify({
+                            extends: "plugin:foo/bar"
+                        }),
+                        "foo/nested/test.txt": "",
+                        "foo/test.js": "",
+                        "foo/test.txt": "",
+                        "bar/test.js": "",
+                        "bar/test.txt": "",
+                        "test.js": "",
+                        "test.txt": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' with a directory path should contain 'foo/test.txt' and 'foo/nested/test.txt'.", async () => {
+                const engine = new InMemoryESLint();
+                const filePaths = (await engine.lintFiles("."))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(filePaths, [
+                    path.join(root, "bar/test.js"),
+                    path.join(root, "foo/nested/test.txt"),
+                    path.join(root, "foo/test.js"),
+                    path.join(root, "foo/test.txt"),
+                    path.join(root, "test.js")
+                ]);
+            });
+        });
+    });
+
+    describe("'ignorePatterns', 'overrides[].files', and 'overrides[].excludedFiles' of the configuration that the '--config' option provided should be resolved from CWD.", () => {
+        const root = getFixturePath("cli-engine/config-and-overrides-files");
+
+        /** @type {ESLint} */
+        let InMemoryESLint;
+
+        describe("if { files: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/myconf/.eslintrc.json": JSON.stringify({
+                            overrides: [
+                                {
+                                    files: "foo/*.js",
+                                    rules: {
+                                        eqeqeq: "error"
+                                    }
+                                }
+                            ]
+                        }),
+                        "node_modules/myconf/foo/test.js": "a == b",
+                        "foo/test.js": "a == b"
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' with 'foo/test.js' should use the override entry.", async () => {
+                const engine = new InMemoryESLint({
+                    overrideConfigFile: "node_modules/myconf/.eslintrc.json",
+                    cwd: root,
+                    ignore: false,
+                    useEslintrc: false
+                });
+                const results = await engine.lintFiles("foo/test.js");
+
+                // Expected to be an 'eqeqeq' error because the file matches to `$CWD/foo/*.js`.
+                assert.deepStrictEqual(results, [
+                    {
+                        errorCount: 1,
+                        filePath: path.join(root, "foo/test.js"),
+                        fixableErrorCount: 0,
+                        fixableWarningCount: 0,
+                        messages: [
+                            {
+                                column: 3,
+                                endColumn: 5,
+                                endLine: 1,
+                                line: 1,
+                                message: "Expected '===' and instead saw '=='.",
+                                messageId: "unexpected",
+                                nodeType: "BinaryExpression",
+                                ruleId: "eqeqeq",
+                                severity: 2
+                            }
+                        ],
+                        source: "a == b",
+                        usedDeprecatedRules: [],
+                        warningCount: 0
+                    }
+                ]);
+            });
+
+            it("'lintFiles()' with 'node_modules/myconf/foo/test.js' should NOT use the override entry.", async () => {
+                const engine = new InMemoryESLint({
+                    overrideConfigFile: "node_modules/myconf/.eslintrc.json",
+                    cwd: root,
+                    ignore: false,
+                    useEslintrc: false
+                });
+                const results = await engine.lintFiles("node_modules/myconf/foo/test.js");
+
+                // Expected to be no errors because the file doesn't match to `$CWD/foo/*.js`.
+                assert.deepStrictEqual(results, [
+                    {
+                        errorCount: 0,
+                        filePath: path.join(root, "node_modules/myconf/foo/test.js"),
+                        fixableErrorCount: 0,
+                        fixableWarningCount: 0,
+                        messages: [],
+                        usedDeprecatedRules: [],
+                        warningCount: 0
+                    }
+                ]);
+            });
+        });
+
+        describe("if { files: '*', excludedFiles: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/myconf/.eslintrc.json": JSON.stringify({
+                            overrides: [
+                                {
+                                    files: "*",
+                                    excludedFiles: "foo/*.js",
+                                    rules: {
+                                        eqeqeq: "error"
+                                    }
+                                }
+                            ]
+                        }),
+                        "node_modules/myconf/foo/test.js": "a == b",
+                        "foo/test.js": "a == b"
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' with 'foo/test.js' should NOT use the override entry.", async () => {
+                const engine = new InMemoryESLint({
+                    overrideConfigFile: "node_modules/myconf/.eslintrc.json",
+                    cwd: root,
+                    ignore: false,
+                    useEslintrc: false
+                });
+                const results = await engine.lintFiles("foo/test.js");
+
+                // Expected to be no errors because the file matches to `$CWD/foo/*.js`.
+                assert.deepStrictEqual(results, [
+                    {
+                        errorCount: 0,
+                        filePath: path.join(root, "foo/test.js"),
+                        fixableErrorCount: 0,
+                        fixableWarningCount: 0,
+                        messages: [],
+                        usedDeprecatedRules: [],
+                        warningCount: 0
+                    }
+                ]);
+            });
+
+            it("'lintFiles()' with 'node_modules/myconf/foo/test.js' should use the override entry.", async () => {
+                const engine = new InMemoryESLint({
+                    overrideConfigFile: "node_modules/myconf/.eslintrc.json",
+                    cwd: root,
+                    ignore: false,
+                    useEslintrc: false
+                });
+                const results = await engine.lintFiles("node_modules/myconf/foo/test.js");
+
+                // Expected to be an 'eqeqeq' error because the file doesn't match to `$CWD/foo/*.js`.
+                assert.deepStrictEqual(results, [
+                    {
+                        errorCount: 1,
+                        filePath: path.join(root, "node_modules/myconf/foo/test.js"),
+                        fixableErrorCount: 0,
+                        fixableWarningCount: 0,
+                        messages: [
+                            {
+                                column: 3,
+                                endColumn: 5,
+                                endLine: 1,
+                                line: 1,
+                                message: "Expected '===' and instead saw '=='.",
+                                messageId: "unexpected",
+                                nodeType: "BinaryExpression",
+                                ruleId: "eqeqeq",
+                                severity: 2
+                            }
+                        ],
+                        source: "a == b",
+                        usedDeprecatedRules: [],
+                        warningCount: 0
+                    }
+                ]);
+            });
+        });
+
+        describe("if { ignorePatterns: 'foo/*.txt', ... } is present by '--config node_modules/myconf/.eslintrc.json',", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/myconf/.eslintrc.json": JSON.stringify({
+                            ignorePatterns: ["!/node_modules/myconf", "foo/*.js"],
+                            rules: {
+                                eqeqeq: "error"
+                            }
+                        }),
+                        "node_modules/myconf/foo/test.js": "a == b",
+                        "foo/test.js": "a == b"
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' with '**/*.js' should iterate 'node_modules/myconf/foo/test.js' but not 'foo/test.js'.", async () => {
+                const engine = new InMemoryESLint({
+                    overrideConfigFile: "node_modules/myconf/.eslintrc.json",
+                    cwd: root,
+                    useEslintrc: false
+                });
+                const files = (await engine.lintFiles("**/*.js"))
+                    .map(r => r.filePath)
+                    .sort();
+
+                assert.deepStrictEqual(files, [
+                    path.join(root, "node_modules/myconf/foo/test.js")
+                ]);
+            });
+        });
+    });
+
+    describe("plugin conflicts", () => {
+        let uid = 0;
+        let root = "";
+
+        beforeEach(() => {
+            root = getFixturePath(`eslint/plugin-conflicts-${++uid}`);
+        });
+
+        /** @type {typeof ESLint} */
+        let InMemoryESLint;
+
+        /**
+         * Verify thrown errors.
+         * @param {() => Promise<any>} f The function to run and throw.
+         * @param {Record<string, any>} props The properties to verify.
+         * @returns {Promise<void>} void
+         */
+        async function assertThrows(f, props) {
+            try {
+                await f();
+            } catch (error) {
+                for (const [key, value] of Object.entries(props)) {
+                    assert.deepStrictEqual(error[key], value, key);
+                }
+                return;
+            }
+
+            assert.fail("Function should throw an error, but not.");
+        }
+
+        describe("between a config file and linear extendees.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-plugin-foo/index.js": "",
+                        "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
+                        "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
+                            extends: ["two"],
+                            plugins: ["foo"]
+                        })}`,
+                        "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
+                        "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
+                            plugins: ["foo"]
+                        })}`,
+                        ".eslintrc.json": JSON.stringify({
+                            extends: ["one"],
+                            plugins: ["foo"]
+                        }),
+                        "test.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", async () => {
+                const engine = new InMemoryESLint({ cwd: root });
+
+                await engine.lintFiles("test.js");
+            });
+        });
+
+        describe("between a config file and same-depth extendees.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-plugin-foo/index.js": "",
+                        "node_modules/eslint-config-one/node_modules/eslint-plugin-foo/index.js": "",
+                        "node_modules/eslint-config-one/index.js": `module.exports = ${JSON.stringify({
+                            plugins: ["foo"]
+                        })}`,
+                        "node_modules/eslint-config-two/node_modules/eslint-plugin-foo/index.js": "",
+                        "node_modules/eslint-config-two/index.js": `module.exports = ${JSON.stringify({
+                            plugins: ["foo"]
+                        })}`,
+                        ".eslintrc.json": JSON.stringify({
+                            extends: ["one", "two"],
+                            plugins: ["foo"]
+                        }),
+                        "test.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file.)", async () => {
+                const engine = new InMemoryESLint({ cwd: root });
+
+                await engine.lintFiles("test.js");
+            });
+        });
+
+        describe("between two config files in different directories, with single node_modules.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-plugin-foo/index.js": "",
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "subdir/.eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "subdir/test.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file, but there are two entry config files, but node_modules directory is unique.)", async () => {
+                const engine = new InMemoryESLint({ cwd: root });
+
+                await engine.lintFiles("subdir/test.js");
+            });
+        });
+
+        describe("between two config files in different directories, with multiple node_modules.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-plugin-foo/index.js": "",
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "subdir/node_modules/eslint-plugin-foo/index.js": "",
+                        "subdir/.eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "subdir/test.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' should throw plugin-conflict error. (Load the plugin from the base directory of the entry config file, but there are two entry config files.)", async () => {
+                const engine = new InMemoryESLint({ cwd: root });
+
+                await assertThrows(
+                    () => engine.lintFiles("subdir/test.js"),
+                    {
+                        message: `Plugin "foo" was conflicted between "subdir${path.sep}.eslintrc.json" and ".eslintrc.json".`,
+                        messageTemplate: "plugin-conflict",
+                        messageData: {
+                            pluginId: "foo",
+                            plugins: [
+                                {
+                                    filePath: path.join(root, "subdir/node_modules/eslint-plugin-foo/index.js"),
+                                    importerName: `subdir${path.sep}.eslintrc.json`
+                                },
+                                {
+                                    filePath: path.join(root, "node_modules/eslint-plugin-foo/index.js"),
+                                    importerName: ".eslintrc.json"
+                                }
+                            ]
+                        }
+                    }
+                );
+            });
+        });
+
+        describe("between '--config' option and a regular config file, with single node_modules.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-plugin-foo/index.js": "",
+                        "node_modules/mine/.eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "test.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file, but there are two entry config files, but node_modules directory is unique.)", async () => {
+                const engine = new InMemoryESLint({
+                    cwd: root,
+                    overrideConfigFile: "node_modules/mine/.eslintrc.json"
+                });
+
+                await engine.lintFiles("test.js");
+            });
+        });
+
+        describe("between '--config' option and a regular config file, with multiple node_modules.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-plugin-foo/index.js": "",
+                        "node_modules/mine/node_modules/eslint-plugin-foo/index.js": "",
+                        "node_modules/mine/.eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "test.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' should throw plugin-conflict error. (Load the plugin from the base directory of the entry config file, but there are two entry config files.)", async () => {
+                const engine = new InMemoryESLint({
+                    cwd: root,
+                    overrideConfigFile: "node_modules/mine/.eslintrc.json"
+                });
+
+                await assertThrows(
+                    () => engine.lintFiles("test.js"),
+                    {
+                        message: "Plugin \"foo\" was conflicted between \"--config\" and \".eslintrc.json\".",
+                        messageTemplate: "plugin-conflict",
+                        messageData: {
+                            pluginId: "foo",
+                            plugins: [
+                                {
+                                    filePath: path.join(root, "node_modules/mine/node_modules/eslint-plugin-foo/index.js"),
+                                    importerName: "--config"
+                                },
+                                {
+                                    filePath: path.join(root, "node_modules/eslint-plugin-foo/index.js"),
+                                    importerName: ".eslintrc.json"
+                                }
+                            ]
+                        }
+                    }
+                );
+            });
+        });
+
+        describe("between '--plugin' option and a regular config file, with single node_modules.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-plugin-foo/index.js": "",
+                        "subdir/.eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "subdir/test.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file, but node_modules directory is unique.)", async () => {
+                const engine = new InMemoryESLint({
+                    cwd: root,
+                    overrideConfig: { plugins: ["foo"] }
+                });
+
+                await engine.lintFiles("subdir/test.js");
+            });
+        });
+
+        describe("between '--plugin' option and a regular config file, with multiple node_modules.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-plugin-foo/index.js": "",
+                        "subdir/node_modules/eslint-plugin-foo/index.js": "",
+                        "subdir/.eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "subdir/test.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' should throw plugin-conflict error. (Load the plugin from both CWD and the base directory of the entry config file.)", async () => {
+                const engine = new InMemoryESLint({
+                    cwd: root,
+                    overrideConfig: { plugins: ["foo"] }
+                });
+
+                await assertThrows(
+                    () => engine.lintFiles("subdir/test.js"),
+                    {
+                        message: `Plugin "foo" was conflicted between "CLIOptions" and "subdir${path.sep}.eslintrc.json".`,
+                        messageTemplate: "plugin-conflict",
+                        messageData: {
+                            pluginId: "foo",
+                            plugins: [
+                                {
+                                    filePath: path.join(root, "node_modules/eslint-plugin-foo/index.js"),
+                                    importerName: "CLIOptions"
+                                },
+                                {
+                                    filePath: path.join(root, "subdir/node_modules/eslint-plugin-foo/index.js"),
+                                    importerName: `subdir${path.sep}.eslintrc.json`
+                                }
+                            ]
+                        }
+                    }
+                );
+            });
+        });
+
+        describe("'--resolve-plugins-relative-to' option overrides the location that ESLint load plugins from.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "node_modules/eslint-plugin-foo/index.js": "",
+                        ".eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "subdir/node_modules/eslint-plugin-foo/index.js": "",
+                        "subdir/.eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "subdir/test.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from '--resolve-plugins-relative-to'.)", async () => {
+                const engine = new InMemoryESLint({
+                    cwd: root,
+                    resolvePluginsRelativeTo: root
+                });
+
+                await engine.lintFiles("subdir/test.js");
+            });
+        });
+
+        describe("between two config files with different target files.", () => {
+            beforeEach(() => {
+                InMemoryESLint = defineESLintWithInMemoryFileSystem({
+                    cwd: () => root,
+                    files: {
+                        "one/node_modules/eslint-plugin-foo/index.js": "",
+                        "one/.eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "one/test.js": "",
+                        "two/node_modules/eslint-plugin-foo/index.js": "",
+                        "two/.eslintrc.json": JSON.stringify({
+                            plugins: ["foo"]
+                        }),
+                        "two/test.js": ""
+                    }
+                }).ESLint;
+            });
+
+            it("'lintFiles()' should NOT throw plugin-conflict error. (Load the plugin from the base directory of the entry config file for each target file. Not related to each other.)", async () => {
+                const engine = new InMemoryESLint({ cwd: root });
+                const results = await engine.lintFiles("*/test.js");
+
+                assert.strictEqual(results.length, 2);
+            });
+        });
+    });
+});
index 3ce766a12833f0549c06e82cbb7720d87cae2c15..1fa2b0476dea016e6676d59f1e76b052da17edeb 100644 (file)
@@ -12,7 +12,8 @@
 const assert = require("chai").assert,
     autoconfig = require("../../../lib/init/autoconfig"),
     sourceCodeUtils = require("../../../lib/init/source-code-utils"),
-    baseDefaultOptions = require("../../../conf/default-cli-options");
+    baseDefaultOptions = require("../../../conf/default-cli-options"),
+    recommendedConfig = require("../../conf/eslint-recommended");
 
 const defaultOptions = Object.assign({}, baseDefaultOptions, { cwd: process.cwd() });
 
@@ -328,4 +329,43 @@ describe("autoconfig", () => {
             });
         });
     });
+
+    describe("extendFromRecommended()", () => {
+        it("should return a configuration which has `extends` key with Array type value", () => {
+            const oldConfig = { extends: [], rules: {} };
+            const newConfig = autoconfig.extendFromRecommended(oldConfig);
+
+            assert.exists(newConfig.extends);
+            assert.isArray(newConfig.extends);
+        });
+
+        it("should return a configuration which has array property `extends`", () => {
+            const oldConfig = { extends: [], rules: {} };
+            const newConfig = autoconfig.extendFromRecommended(oldConfig);
+
+            assert.include(newConfig.extends, "eslint:recommended");
+        });
+
+        it("should return a configuration which preserves the previous extending configurations", () => {
+            const oldConfig = { extends: ["previous:configuration1", "previous:configuration2"], rules: {} };
+            const newConfig = autoconfig.extendFromRecommended(oldConfig);
+
+            assert.includeMembers(newConfig.extends, oldConfig.extends);
+        });
+
+        it("should return a configuration which has `eslint:recommended` at the first of `extends`", () => {
+            const oldConfig = { extends: ["previous:configuration1", "previous:configuration2"], rules: {} };
+            const newConfig = autoconfig.extendFromRecommended(oldConfig);
+            const [firstExtendInNewConfig] = newConfig.extends;
+
+            assert.strictEqual(firstExtendInNewConfig, "eslint:recommended");
+        });
+
+        it("should return a configuration which not includes rules configured in `eslint:recommended`", () => {
+            const oldConfig = { extends: [], rules: { ...recommendedConfig.rules } };
+            const newConfig = autoconfig.extendFromRecommended(oldConfig);
+
+            assert.notInclude(newConfig.rules, oldConfig.rules);
+        });
+    });
 });
index 3393ae2befaf9094860cf7920bc204401278c500..5f4690adfa8539a8a4e01b3d5df4b1760d3feb35 100644 (file)
@@ -15,6 +15,7 @@ const assert = require("chai").assert,
     os = require("os"),
     sinon = require("sinon"),
     sh = require("shelljs"),
+    espree = require("espree"),
     autoconfig = require("../../../lib/init/autoconfig"),
     npmUtils = require("../../../lib/init/npm-utils");
 
@@ -138,7 +139,7 @@ describe("configInitializer", () => {
                 assert.strictEqual(config.env.es6, true);
                 assert.strictEqual(config.globals.Atomics, "readonly");
                 assert.strictEqual(config.globals.SharedArrayBuffer, "readonly");
-                assert.strictEqual(config.parserOptions.ecmaVersion, 2018);
+                assert.strictEqual(config.parserOptions.ecmaVersion, espree.latestEcmaVersion);
                 assert.strictEqual(config.parserOptions.sourceType, "module");
                 assert.strictEqual(config.env.browser, true);
                 assert.strictEqual(config.extends, "eslint:recommended");
@@ -156,7 +157,7 @@ describe("configInitializer", () => {
                 const config = init.processAnswers(answers);
 
                 assert.strictEqual(config.parserOptions.ecmaFeatures.jsx, true);
-                assert.strictEqual(config.parserOptions.ecmaVersion, 2018);
+                assert.strictEqual(config.parserOptions.ecmaVersion, espree.latestEcmaVersion);
                 assert.deepStrictEqual(config.plugins, ["react"]);
             });
 
@@ -164,7 +165,7 @@ describe("configInitializer", () => {
                 answers.framework = "vue";
                 const config = init.processAnswers(answers);
 
-                assert.strictEqual(config.parserOptions.ecmaVersion, 2018);
+                assert.strictEqual(config.parserOptions.ecmaVersion, espree.latestEcmaVersion);
                 assert.deepStrictEqual(config.plugins, ["vue"]);
                 assert.deepStrictEqual(config.extends, ["eslint:recommended", "plugin:vue/essential"]);
             });
index d0326bd13304fb33be2d72a57289df2284d101b3..8465796a367f1c4c76df87a263f9e2896ee2c5a7 100644 (file)
@@ -14,7 +14,7 @@ const
     sinon = require("sinon"),
     npmUtils = require("../../../lib/init/npm-utils"),
     log = require("../../../lib/shared/logging"),
-    { defineInMemoryFs } = require("../_utils");
+    { defineInMemoryFs } = require("../../_utils");
 
 const proxyquire = require("proxyquire").noCallThru().noPreserveCache();
 
index 9c0ae9ffc409dfd51a33218d2ae13236336afd2f..0c4fdd18328fb031cca4725320606d858b702b4a 100644 (file)
@@ -50,7 +50,7 @@ function getOrderOfTraversing(codePath, options, callback) {
     codePath.traverseSegments(options, (segment, controller) => {
         retv.push(segment.id);
         if (callback) {
-            callback(segment, controller); // eslint-disable-line callback-return
+            callback(segment, controller); // eslint-disable-line node/callback-return
         }
     });
 
index 74d231ed1ff7d7816636c1d975a5fd1b2dec6a6b..56d028e5c62908c423bc341888ab1fcd0835f92b 100644 (file)
@@ -2733,18 +2733,48 @@ describe("Linter", () => {
     });
 
     describe("when evaluating code with comments which have colon in its value", () => {
-        const code = "/* eslint max-len: [2, 100, 2, {ignoreUrls: true, ignorePattern: \"data:image\\/|\\s*require\\s*\\(|^\\s*loader\\.lazy|-\\*-\"}] */\nalert('test');";
+        const code = String.raw`
+/* eslint max-len: [2, 100, 2, {ignoreUrls: true, ignorePattern: "data:image\\/|\\s*require\\s*\\(|^\\s*loader\\.lazy|-\\*-"}] */
+alert('test');
+`;
 
         it("should not parse errors, should report a violation", () => {
             const messages = linter.verify(code, {}, filename);
 
             assert.strictEqual(messages.length, 1);
             assert.strictEqual(messages[0].ruleId, "max-len");
-            assert.strictEqual(messages[0].message, "This line has a length of 122. Maximum allowed is 100.");
+            assert.strictEqual(messages[0].message, "This line has a length of 129. Maximum allowed is 100.");
             assert.include(messages[0].nodeType, "Program");
         });
     });
 
+    describe("when evaluating code with comments that contain escape sequences", () => {
+        const code = String.raw`
+/* eslint max-len: ["error", 1, { ignoreComments: true, ignorePattern: "console\\.log\\(" }] */
+console.log("test");
+consolexlog("test2");
+var a = "test2";
+`;
+
+        it("should validate correctly", () => {
+            const config = { rules: {} };
+            const messages = linter.verify(code, config, filename);
+            const [message1, message2] = messages;
+
+            assert.strictEqual(messages.length, 2);
+            assert.strictEqual(message1.ruleId, "max-len");
+            assert.strictEqual(message1.message, "This line has a length of 21. Maximum allowed is 1.");
+            assert.strictEqual(message1.line, 4);
+            assert.strictEqual(message1.column, 1);
+            assert.include(message1.nodeType, "Program");
+            assert.strictEqual(message2.ruleId, "max-len");
+            assert.strictEqual(message2.message, "This line has a length of 16. Maximum allowed is 1.");
+            assert.strictEqual(message2.line, 5);
+            assert.strictEqual(message2.column, 1);
+            assert.include(message2.nodeType, "Program");
+        });
+    });
+
     describe("when evaluating a file with a shebang", () => {
         const code = "#!bin/program\n\nvar foo;;";
 
index 940804aeeefee7db7a9ea69220fcd576234b20fa..c84e46d9afd26deb72b450bd4a449201d8ab3088 100644 (file)
@@ -79,11 +79,10 @@ describe("options", () => {
             assert.strictEqual(currentOptions.ext[1], ".js");
         });
 
-        it("should return an array one item when not passed", () => {
+        it("should not exist when not passed", () => {
             const currentOptions = options.parse("");
 
-            assert.isArray(currentOptions.ext);
-            assert.strictEqual(currentOptions.ext[0], ".js");
+            assert.notProperty(currentOptions, "ext");
         });
     });
 
index 65a06da85d922794a15f09f5aa71ac559a61c504..fedc237d64ce2dc89d1b14a251301b0b953cf765 100644 (file)
@@ -1829,7 +1829,7 @@ describe("RuleTester", () => {
                     invalid: []
                 }
             );
-        }, /A fatal parsing error occurred in autofix/u);
+        }, /A fatal parsing error occurred in autofix.\nError: .+\nAutofix output:\n.+/u);
     });
 
     describe("sanitize test cases", () => {
index d20c365dbc4edb34bd52a7b4eae0f53c84f08534..90ee8213b7780d8c4c2c995d011df2d497d687d6 100644 (file)
@@ -39,6 +39,7 @@ ruleTester.run("array-bracket-newline", rule, {
         "var foo = [\nfunction foo() {\nreturn dosomething();\n}\n];",
         "var foo = [/* \nany comment\n */];",
         "var foo = [/* single line multiline comment for no real reason */];",
+        "var foo = [[1,2]]",
 
         // "always"
         { code: "var foo = [\n];", options: ["always"] },
@@ -47,9 +48,37 @@ ruleTester.run("array-bracket-newline", rule, {
         { code: "var foo = [\n/* any */\n1\n];", options: ["always"] },
         { code: "var foo = [\n1, 2\n];", options: ["always"] },
         { code: "var foo = [\n1, 2 // any comment\n];", options: ["always"] },
-        { code: "var foo = [\n1, 2 /* any comment */\n];", options: ["always"] },
+        {
+            code: "var foo = [\n1, 2 /* any comment */\n];",
+            options: ["always"]
+        },
         { code: "var foo = [\n1,\n2\n];", options: ["always"] },
-        { code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];", options: ["always"] },
+        {
+            code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            options: ["always"]
+        },
+        {
+            code: `
+            var foo = [
+                [
+                    1,2
+                ]
+            ]
+            `,
+            options: ["always"]
+        },
+        {
+            code: `
+            var foo = [
+                0,
+                [
+                    1,2
+                ],
+                3
+            ]
+            `,
+            options: ["always"]
+        },
 
         // "never"
         { code: "var foo = [];", options: ["never"] },
@@ -58,7 +87,14 @@ ruleTester.run("array-bracket-newline", rule, {
         { code: "var foo = [1, 2];", options: ["never"] },
         { code: "var foo = [1,\n2];", options: ["never"] },
         { code: "var foo = [1,\n/* any comment */\n2];", options: ["never"] },
-        { code: "var foo = [function foo() {\ndosomething();\n}];", options: ["never"] },
+        {
+            code: "var foo = [function foo() {\ndosomething();\n}];",
+            options: ["never"]
+        },
+        {
+            code: "var foo = [[1,2],3];",
+            options: ["never"]
+        },
 
         // "consistent"
         { code: "var a = []", options: ["consistent"] },
@@ -69,67 +105,177 @@ ruleTester.run("array-bracket-newline", rule, {
         { code: "var a = [/**/\n1\n]", options: ["consistent"] },
         { code: "var a = [/*\n*/1\n]", options: ["consistent"] },
         { code: "var a = [//\n]", options: ["consistent"] },
+        {
+            code: `var a = [
+                [1,2]
+            ]`,
+            options: ["consistent"]
+        },
+        {
+            code: `var a = [
+                [[1,2]]
+            ]`,
+            options: ["consistent"]
+        },
 
         // { multiline: true }
         { code: "var foo = [];", options: [{ multiline: true }] },
         { code: "var foo = [1];", options: [{ multiline: true }] },
-        { code: "var foo = /* any comment */[1];", options: [{ multiline: true }] },
-        { code: "var foo = /* any comment */\n[1];", options: [{ multiline: true }] },
+        {
+            code: "var foo = /* any comment */[1];",
+            options: [{ multiline: true }]
+        },
+        {
+            code: "var foo = /* any comment */\n[1];",
+            options: [{ multiline: true }]
+        },
         { code: "var foo = [1, 2];", options: [{ multiline: true }] },
-        { code: "var foo = [ // any comment\n1, 2\n];", options: [{ multiline: true }] },
-        { code: "var foo = [\n// any comment\n1, 2\n];", options: [{ multiline: true }] },
-        { code: "var foo = [\n1, 2\n// any comment\n];", options: [{ multiline: true }] },
+        {
+            code: "var foo = [ // any comment\n1, 2\n];",
+            options: [{ multiline: true }]
+        },
+        {
+            code: "var foo = [\n// any comment\n1, 2\n];",
+            options: [{ multiline: true }]
+        },
+        {
+            code: "var foo = [\n1, 2\n// any comment\n];",
+            options: [{ multiline: true }]
+        },
         { code: "var foo = [\n1,\n2\n];", options: [{ multiline: true }] },
-        { code: "var foo = [\nfunction foo() {\nreturn dosomething();\n}\n];", options: [{ multiline: true }] },
-        { code: "var foo = [/* \nany comment\n */];", options: [{ multiline: true }] },
+        {
+            code: "var foo = [\nfunction foo() {\nreturn dosomething();\n}\n];",
+            options: [{ multiline: true }]
+        },
+        {
+            code: "var foo = [/* \nany comment\n */];",
+            options: [{ multiline: true }]
+        },
+        {
+            code: "var foo = [\n1,\n2,\n[3,4],\n];",
+            options: [{ multiline: true }]
+        },
+        {
+            code: "var foo = [\n1,\n2,\n[\n3,\n4\n],\n];",
+            options: [{ multiline: true }]
+        },
 
         // { multiline: false }
         { code: "var foo = [];", options: [{ multiline: false }] },
         { code: "var foo = [1];", options: [{ multiline: false }] },
-        { code: "var foo = [1]/* any comment*/;", options: [{ multiline: false }] },
-        { code: "var foo = [1]\n/* any comment*/\n;", options: [{ multiline: false }] },
+        {
+            code: "var foo = [1]/* any comment*/;",
+            options: [{ multiline: false }]
+        },
+        {
+            code: "var foo = [1]\n/* any comment*/\n;",
+            options: [{ multiline: false }]
+        },
         { code: "var foo = [1, 2];", options: [{ multiline: false }] },
         { code: "var foo = [1,\n2];", options: [{ multiline: false }] },
-        { code: "var foo = [function foo() {\nreturn dosomething();\n}];", options: [{ multiline: false }] },
+        {
+            code: "var foo = [function foo() {\nreturn dosomething();\n}];",
+            options: [{ multiline: false }]
+        },
+        { code: "var foo = [1,\n2,[3,\n4]];", options: [{ multiline: false }] },
 
         // { minItems: 2 }
         { code: "var foo = [];", options: [{ minItems: 2 }] },
         { code: "var foo = [1];", options: [{ minItems: 2 }] },
         { code: "var foo = [\n1, 2\n];", options: [{ minItems: 2 }] },
         { code: "var foo = [\n1,\n2\n];", options: [{ minItems: 2 }] },
-        { code: "var foo = [function foo() {\ndosomething();\n}];", options: [{ minItems: 2 }] },
+        {
+            code: "var foo = [function foo() {\ndosomething();\n}];",
+            options: [{ minItems: 2 }]
+        },
+        {
+            code: `var foo = [
+                1,[
+                    2,3
+                ]
+            ];`,
+            options: [{ minItems: 2 }]
+        },
+        {
+            code: `var foo = [[
+                1,2
+            ]]`,
+            options: [{ minItems: 2 }]
+        },
 
         // { minItems: 0 }
         { code: "var foo = [\n];", options: [{ minItems: 0 }] },
         { code: "var foo = [\n1\n];", options: [{ minItems: 0 }] },
         { code: "var foo = [\n1, 2\n];", options: [{ minItems: 0 }] },
         { code: "var foo = [\n1,\n2\n];", options: [{ minItems: 0 }] },
-        { code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];", options: [{ minItems: 0 }] },
+        {
+            code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            options: [{ minItems: 0 }]
+        },
 
         // { minItems: null }
         { code: "var foo = [];", options: [{ minItems: null }] },
         { code: "var foo = [1];", options: [{ minItems: null }] },
         { code: "var foo = [1, 2];", options: [{ minItems: null }] },
         { code: "var foo = [1,\n2];", options: [{ minItems: null }] },
-        { code: "var foo = [function foo() {\ndosomething();\n}];", options: [{ minItems: null }] },
+        {
+            code: "var foo = [function foo() {\ndosomething();\n}];",
+            options: [{ minItems: null }]
+        },
 
         // { multiline: true, minItems: null }
-        { code: "var foo = [];", options: [{ multiline: true, minItems: null }] },
-        { code: "var foo = [1];", options: [{ multiline: true, minItems: null }] },
-        { code: "var foo = [1, 2];", options: [{ multiline: true, minItems: null }] },
-        { code: "var foo = [\n1,\n2\n];", options: [{ multiline: true, minItems: null }] },
-        { code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];", options: [{ multiline: true, minItems: null }] },
+        {
+            code: "var foo = [];",
+            options: [{ multiline: true, minItems: null }]
+        },
+        {
+            code: "var foo = [1];",
+            options: [{ multiline: true, minItems: null }]
+        },
+        {
+            code: "var foo = [1, 2];",
+            options: [{ multiline: true, minItems: null }]
+        },
+        {
+            code: "var foo = [\n1,\n2\n];",
+            options: [{ multiline: true, minItems: null }]
+        },
+        {
+            code: "var foo = [\nfunction foo() {\ndosomething();\n}\n];",
+            options: [{ multiline: true, minItems: null }]
+        },
 
         // { multiline: true, minItems: 2 }
         { code: "var a = [];", options: [{ multiline: true, minItems: 2 }] },
         { code: "var b = [1];", options: [{ multiline: true, minItems: 2 }] },
-        { code: "var b = [ // any comment\n1\n];", options: [{ multiline: true, minItems: 2 }] },
-        { code: "var b = [ /* any comment */ 1];", options: [{ multiline: true, minItems: 2 }] },
-        { code: "var c = [\n1, 2\n];", options: [{ multiline: true, minItems: 2 }] },
-        { code: "var c = [\n/* any comment */1, 2\n];", options: [{ multiline: true, minItems: 2 }] },
-        { code: "var c = [\n1, /* any comment */ 2\n];", options: [{ multiline: true, minItems: 2 }] },
-        { code: "var d = [\n1,\n2\n];", options: [{ multiline: true, minItems: 2 }] },
-        { code: "var e = [\nfunction foo() {\ndosomething();\n}\n];", options: [{ multiline: true, minItems: 2 }] },
+        {
+            code: "var b = [ // any comment\n1\n];",
+            options: [{ multiline: true, minItems: 2 }]
+        },
+        {
+            code: "var b = [ /* any comment */ 1];",
+            options: [{ multiline: true, minItems: 2 }]
+        },
+        {
+            code: "var c = [\n1, 2\n];",
+            options: [{ multiline: true, minItems: 2 }]
+        },
+        {
+            code: "var c = [\n/* any comment */1, 2\n];",
+            options: [{ multiline: true, minItems: 2 }]
+        },
+        {
+            code: "var c = [\n1, /* any comment */ 2\n];",
+            options: [{ multiline: true, minItems: 2 }]
+        },
+        {
+            code: "var d = [\n1,\n2\n];",
+            options: [{ multiline: true, minItems: 2 }]
+        },
+        {
+            code: "var e = [\nfunction foo() {\ndosomething();\n}\n];",
+            options: [{ multiline: true, minItems: 2 }]
+        },
 
         /*
          * ArrayPattern
@@ -137,53 +283,262 @@ ruleTester.run("array-bracket-newline", rule, {
          */
         { code: "var [] = foo", parserOptions: { ecmaVersion: 6 } },
         { code: "var [a] = foo;", parserOptions: { ecmaVersion: 6 } },
-        { code: "var /* any comment */[a] = foo;", parserOptions: { ecmaVersion: 6 } },
-        { code: "var /* any comment */\n[a] = foo;", parserOptions: { ecmaVersion: 6 } },
+        {
+            code: "var /* any comment */[a] = foo;",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var /* any comment */\n[a] = foo;",
+            parserOptions: { ecmaVersion: 6 }
+        },
         { code: "var [a, b] = foo;", parserOptions: { ecmaVersion: 6 } },
-        { code: "var [ // any comment\na, b\n] = foo;", parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\n// any comment\na, b\n] = foo;", parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\na, b\n// any comment\n] = foo;", parserOptions: { ecmaVersion: 6 } },
+        {
+            code: "var [ // any comment\na, b\n] = foo;",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\n// any comment\na, b\n] = foo;",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\na, b\n// any comment\n] = foo;",
+            parserOptions: { ecmaVersion: 6 }
+        },
         { code: "var [\na,\nb\n] = foo;", parserOptions: { ecmaVersion: 6 } },
 
         // "always"
-        { code: "var [\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\na\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\n// any\na\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\n/* any */\na\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\na, b\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\na, b // any comment\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\na, b /* any comment */\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\na,\nb\n] = foo;", options: ["always"], parserOptions: { ecmaVersion: 6 } },
+        {
+            code: "var [\n] = foo;",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\na\n] = foo;",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\n// any\na\n] = foo;",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\n/* any */\na\n] = foo;",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\na, b\n] = foo;",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\na, b // any comment\n] = foo;",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\na, b /* any comment */\n] = foo;",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\na,\nb\n] = foo;",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 6 }
+        },
 
         // "consistent"
-        { code: "var [] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [a] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\na\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [//\na\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [/**/\na\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [/*\n*/a\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [//\n] = foo", options: ["consistent"], parserOptions: { ecmaVersion: 6 } },
+        {
+            code: "var [] = foo",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\n] = foo",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [a] = foo",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\na\n] = foo",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [//\na\n] = foo",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [/**/\na\n] = foo",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [/*\n*/a\n] = foo",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [//\n] = foo",
+            options: ["consistent"],
+            parserOptions: { ecmaVersion: 6 }
+        },
 
         // { multiline: true }
-        { code: "var [] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [a] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
-        { code: "var /* any comment */[a] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
-        { code: "var /* any comment */\n[a] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [a, b] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [ // any comment\na, b\n] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\n// any comment\na, b\n] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\na, b\n// any comment\n] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } },
-        { code: "var [\na,\nb\n] = foo;", options: [{ multiline: true }], parserOptions: { ecmaVersion: 6 } }
-
+        {
+            code: "var [] = foo;",
+            options: [{ multiline: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [a] = foo;",
+            options: [{ multiline: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var /* any comment */[a] = foo;",
+            options: [{ multiline: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var /* any comment */\n[a] = foo;",
+            options: [{ multiline: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [a, b] = foo;",
+            options: [{ multiline: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [ // any comment\na, b\n] = foo;",
+            options: [{ multiline: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\n// any comment\na, b\n] = foo;",
+            options: [{ multiline: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\na, b\n// any comment\n] = foo;",
+            options: [{ multiline: true }],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var [\na,\nb\n] = foo;",
+            options: [{ multiline: true }],
+            parserOptions: { ecmaVersion: 6 }
+        }
     ],
 
     invalid: [
 
+        // default : { mutliline : true}
+        {
+            code: `var foo = [
+                [1,2]
+            ]`,
+            output: "var foo = [[1,2]]",
+            errors: [
+                {
+                    messageId: "unexpectedOpeningLinebreak",
+                    type: "ArrayExpression",
+                    line: 1,
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
+                },
+                {
+                    messageId: "unexpectedClosingLinebreak",
+                    type: "ArrayExpression",
+                    line: 3,
+                    column: 13,
+                    endLine: 3,
+                    endColumn: 14
+                }
+            ]
+        },
+        {
+            code: "var foo = [[2,\n3]]",
+            output: "var foo = [\n[\n2,\n3\n]\n]",
+            errors: [
+                {
+                    line: 1,
+                    column: 11,
+                    messageId: "missingOpeningLinebreak",
+                    endLine: 1,
+                    endColumn: 12
+                },
+                {
+                    line: 1,
+                    column: 12,
+                    messageId: "missingOpeningLinebreak",
+                    endLine: 1,
+                    endColumn: 13
+                },
+                {
+                    line: 2,
+                    column: 2,
+                    messageId: "missingClosingLinebreak",
+                    endLine: 2,
+                    endColumn: 3
+                },
+                {
+                    line: 2,
+                    column: 3,
+                    messageId: "missingClosingLinebreak",
+                    endLine: 2,
+                    endColumn: 4
+                }
+            ]
+        },
+
         /*
          * ArrayExpression
          * "always"
          */
+        {
+            code: "var foo = [[1,2]]",
+            output: "var foo = [\n[\n1,2\n]\n]",
+            options: ["always"],
+            errors: [
+                {
+                    line: 1,
+                    column: 11,
+                    messageId: "missingOpeningLinebreak",
+                    endLine: 1,
+                    endColumn: 12
+                },
+                {
+                    line: 1,
+                    column: 12,
+                    messageId: "missingOpeningLinebreak",
+                    endLine: 1,
+                    endColumn: 13
+                },
+                {
+                    line: 1,
+                    column: 16,
+                    messageId: "missingClosingLinebreak",
+                    endLine: 1,
+                    endColumn: 17
+                },
+                {
+                    line: 1,
+                    column: 17,
+                    messageId: "missingClosingLinebreak",
+                    endLine: 1,
+                    endColumn: 18
+                }
+            ]
+        },
         {
             code: "var foo = [];",
             output: "var foo = [\n];",
@@ -349,6 +704,21 @@ ruleTester.run("array-bracket-newline", rule, {
         },
 
         // "never"
+        {
+            code: `var foo = [[
+                1,2],3];`,
+            output: "var foo = [[1,2],3];",
+            options: ["never"],
+            errors: [
+                {
+                    line: 1,
+                    column: 12,
+                    messageId: "unexpectedOpeningLinebreak",
+                    endLine: 1,
+                    endColumn: 13
+                }
+            ]
+        },
         {
             code: "var foo = [\n];",
             output: "var foo = [];",
@@ -507,6 +877,35 @@ ruleTester.run("array-bracket-newline", rule, {
         },
 
         // "consistent"
+        {
+            code: `var a = [[1,2]
+            ]`,
+            output: "var a = [[1,2]]",
+            options: ["consistent"],
+            errors: [
+                {
+                    line: 2,
+                    column: 13,
+                    messageId: "unexpectedClosingLinebreak",
+                    endLine: 2,
+                    endColumn: 14
+                }
+            ]
+        },
+        {
+            code: "var a = [\n[\n[1,2]]\n]",
+            output: "var a = [\n[\n[1,2]\n]\n]",
+            options: ["consistent"],
+            errors: [
+                {
+                    line: 3,
+                    column: 6,
+                    messageId: "missingClosingLinebreak",
+                    endLine: 3,
+                    endColumn: 7
+                }
+            ]
+        },
         {
             code: "var foo = [\n1]",
             output: "var foo = [\n1\n]",
@@ -670,6 +1069,34 @@ ruleTester.run("array-bracket-newline", rule, {
         },
 
         // { minItems: 2 }
+        {
+            code: "var foo = [1,[\n2,3\n]\n];",
+            output: "var foo = [\n1,[\n2,3\n]\n];",
+            options: [{ minItems: 2 }],
+            errors: [
+                {
+                    line: 1,
+                    column: 11,
+                    messageId: "missingOpeningLinebreak",
+                    endLine: 1,
+                    endColumn: 12
+                }
+            ]
+        },
+        {
+            code: "var foo = [[1,2\n]]",
+            output: "var foo = [[\n1,2\n]]",
+            options: [{ minItems: 2 }],
+            errors: [
+                {
+                    line: 1,
+                    column: 12,
+                    messageId: "missingOpeningLinebreak",
+                    endLine: 1,
+                    endColumn: 13
+                }
+            ]
+        },
         {
             code: "var foo = [\n];",
             output: "var foo = [];",
@@ -841,7 +1268,6 @@ ruleTester.run("array-bracket-newline", rule, {
                     line: 2,
                     column: 2
                 }
-
             ]
         },
         {
@@ -1580,6 +2006,5 @@ ruleTester.run("array-bracket-newline", rule, {
                 }
             ]
         }
-
     ]
 });
index 71731de587987f8665e13c0258a9a5648ead3edb..24b40cb5204365f2eb5e420dd75927a204323736 100644 (file)
@@ -147,7 +147,7 @@ ruleTester.run("array-callback-return", rule, {
         { code: "foo[`every`](function foo() {})", parserOptions: { ecmaVersion: 6 }, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] },
         { code: "foo.every(() => {})", parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected to return a value in arrow function.", column: 14 }] },
         { code: "foo.every(function() { if (a) return true; })", errors: [{ message: "Expected to return a value at the end of function.", column: 11 }] },
-        { code: "foo.every(function cb() { if (a) return true; })", errors: [{ message: "Expected to return a value at the end of function 'cb'.", column: 20 }] },
+        { code: "foo.every(function cb() { if (a) return true; })", errors: [{ message: "Expected to return a value at the end of function 'cb'.", column: 11 }] },
         { code: "foo.every(function() { switch (a) { case 0: break; default: return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function" } }] },
         { code: "foo.every(function foo() { switch (a) { case 0: break; default: return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function 'foo'" } }] },
         { code: "foo.every(function() { try { bar(); } catch (err) { return true; } })", errors: [{ messageId: "expectedAtEnd", data: { name: "function" } }] },
@@ -163,7 +163,7 @@ ruleTester.run("array-callback-return", rule, {
         { code: "foo.every(a ? function() {} : function() {})", errors: ["Expected to return a value in function.", "Expected to return a value in function."] },
         { code: "foo.every(a ? function foo() {} : function bar() {})", errors: ["Expected to return a value in function 'foo'.", "Expected to return a value in function 'bar'."] },
         { code: "foo.every(function(){ return function() {}; }())", errors: [{ message: "Expected to return a value in function.", column: 30 }] },
-        { code: "foo.every(function(){ return function foo() {}; }())", errors: [{ message: "Expected to return a value in function 'foo'.", column: 39 }] },
+        { code: "foo.every(function(){ return function foo() {}; }())", errors: [{ message: "Expected to return a value in function 'foo'.", column: 30 }] },
         { code: "foo.every(() => {})", options: [{ allowImplicit: false }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected to return a value in arrow function." }] },
         { code: "foo.every(() => {})", options: [{ allowImplicit: true }], parserOptions: { ecmaVersion: 6 }, errors: [{ message: "Expected to return a value in arrow function." }] },
 
@@ -198,7 +198,250 @@ ruleTester.run("array-callback-return", rule, {
         { code: "foo.every(function() {})", options: checkForEachOptions, errors: [{ messageId: "expectedInside", data: { name: "function" } }] },
         { code: "foo.filter(function foo() {})", options: checkForEachOptions, errors: [{ messageId: "expectedInside", data: { name: "function 'foo'" } }] },
         { code: "foo.filter(function foo() { return; })", options: checkForEachOptions, errors: [{ messageId: "expectedReturnValue", data: { name: "Function 'foo'" } }] },
-        { code: "foo.every(cb || function() {})", options: checkForEachOptions, errors: ["Expected to return a value in function."] }
+        { code: "foo.every(cb || function() {})", options: checkForEachOptions, errors: ["Expected to return a value in function."] },
 
+        // full location tests
+        {
+            code: "foo.filter(bar => { baz(); } )",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "arrow function" },
+                type: "ArrowFunctionExpression",
+                line: 1,
+                column: 16,
+                endLine: 1,
+                endColumn: 18
+            }]
+        },
+        {
+            code: "foo.filter(\n() => {} )",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "arrow function" },
+                type: "ArrowFunctionExpression",
+                line: 2,
+                column: 4,
+                endLine: 2,
+                endColumn: 6
+            }]
+        },
+        {
+            code: "foo.filter(bar || ((baz) => {}) )",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "arrow function" },
+                type: "ArrowFunctionExpression",
+                line: 1,
+                column: 26,
+                endLine: 1,
+                endColumn: 28
+            }]
+        },
+        {
+            code: "foo.filter(bar => { return; })",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "expectedReturnValue",
+                data: { name: "Arrow function" },
+                type: "ReturnStatement",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 28
+            }]
+        },
+        {
+            code: "Array.from(foo, bar => { bar })",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "arrow function" },
+                type: "ArrowFunctionExpression",
+                line: 1,
+                column: 21,
+                endLine: 1,
+                endColumn: 23
+            }]
+        },
+        {
+            code: "foo.forEach(bar => bar)",
+            options: checkForEachOptions,
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "expectedNoReturnValue",
+                data: { name: "Arrow function" },
+                type: "ArrowFunctionExpression",
+                line: 1,
+                column: 17,
+                endLine: 1,
+                endColumn: 19
+            }]
+        },
+        {
+            code: "foo.forEach((function () { return (bar) => bar; })())",
+            options: checkForEachOptions,
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "expectedNoReturnValue",
+                data: { name: "Arrow function" },
+                type: "ArrowFunctionExpression",
+                line: 1,
+                column: 41,
+                endLine: 1,
+                endColumn: 43
+            }]
+        },
+        {
+            code: "foo.forEach((() => {\n return bar => bar; })())",
+            options: checkForEachOptions,
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "expectedNoReturnValue",
+                data: { name: "Arrow function" },
+                type: "ArrowFunctionExpression",
+                line: 2,
+                column: 13,
+                endLine: 2,
+                endColumn: 15
+            }]
+        },
+        {
+            code: "foo.forEach((bar) => { if (bar) { return; } else { return bar ; } })",
+            options: checkForEachOptions,
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "expectedNoReturnValue",
+                data: { name: "Arrow function" },
+                type: "ReturnStatement",
+                line: 1,
+                column: 52,
+                endLine: 1,
+                endColumn: 64
+            }]
+        },
+        {
+            code: "foo.filter(function(){})",
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "function" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 12,
+                endLine: 1,
+                endColumn: 20
+            }]
+        },
+        {
+            code: "foo.filter(function (){})",
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "function" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 12,
+                endLine: 1,
+                endColumn: 21
+            }]
+        },
+        {
+            code: "foo.filter(function\n(){})",
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "function" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 12,
+                endLine: 2,
+                endColumn: 1
+            }]
+        },
+        {
+            code: "foo.filter(function bar(){})",
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "function 'bar'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 12,
+                endLine: 1,
+                endColumn: 24
+            }]
+        },
+        {
+            code: "foo.filter(function bar  (){})",
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "function 'bar'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 12,
+                endLine: 1,
+                endColumn: 26
+            }]
+        },
+        {
+            code: "foo.filter(function\n bar() {})",
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "function 'bar'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 12,
+                endLine: 2,
+                endColumn: 5
+            }]
+        },
+        {
+            code: "Array.from(foo, function bar(){})",
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "function 'bar'" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 17,
+                endLine: 1,
+                endColumn: 29
+            }]
+        },
+        {
+            code: "Array.from(foo, bar ? function (){} : baz)",
+            errors: [{
+                messageId: "expectedInside",
+                data: { name: "function" },
+                type: "FunctionExpression",
+                line: 1,
+                column: 23,
+                endLine: 1,
+                endColumn: 32
+            }]
+        },
+        {
+            code: "foo.filter(function bar() { return \n })",
+            errors: [{
+                messageId: "expectedReturnValue",
+                data: { name: "Function 'bar'" },
+                type: "ReturnStatement",
+                line: 1,
+                column: 29,
+                endLine: 1,
+                endColumn: 35
+            }]
+        },
+        {
+            code: "foo.forEach(function () { \nif (baz) return bar\nelse return\n })",
+            options: checkForEachOptions,
+            errors: [{
+                messageId: "expectedNoReturnValue",
+                data: { name: "Function" },
+                type: "ReturnStatement",
+                line: 2,
+                column: 10,
+                endLine: 2,
+                endColumn: 20
+            }]
+        }
     ]
 });
index b17af83763d166acbfce3e6bebed0ab9a98a48ee..195b5be45f539855ed161902e0c71e21cd8176cb 100644 (file)
@@ -43,6 +43,8 @@ ruleTester.run("array-element-newline", rule, {
         "var foo = [1\n, 2\n, 3];",
         "var foo = [1,\n2,\n,\n3];",
         "var foo = [\nfunction foo() {\ndosomething();\n},\nfunction bar() {\nosomething();\n}\n];",
+        "var foo = [1,\n[2,\n3],\n4]",
+        "var foo = [[],\n[\n[]]]",
 
         { code: "var foo = [];", options: ["always"] },
         { code: "var foo = [1];", options: ["always"] },
@@ -54,6 +56,7 @@ ruleTester.run("array-element-newline", rule, {
         { code: "var foo = [1,\n2 // any comment\n];", options: ["always"] },
         { code: "var foo = [1,\n2,\n3];", options: ["always"] },
         { code: "var foo = [\nfunction foo() {\ndosomething();\n},\nfunction bar() {\ndosomething();\n}\n];", options: ["always"] },
+        { code: "var foo = [\n[1,\n2],\n3,\n[\n4]]", options: ["always"] },
 
         // "never"
         { code: "var foo = [];", options: ["never"] },
@@ -65,6 +68,8 @@ ruleTester.run("array-element-newline", rule, {
         { code: "var foo = [1, 2, 3];", options: ["never"] },
         { code: "var foo = [1, (\n2\n), 3];", options: ["never"] },
         { code: "var foo = [\nfunction foo() {\ndosomething();\n}, function bar() {\ndosomething();\n}\n];", options: ["never"] },
+        { code: "var foo = [\n[1,2],3,[4]\n]", options: ["never"] },
+        { code: "var foo = [[1,2\n],3,[4\n]\n]", options: ["never"] },
 
         // "consistent"
         { code: "var foo = [];", options: ["consistent"] },
@@ -82,6 +87,9 @@ ruleTester.run("array-element-newline", rule, {
         { code: "var foo = [\nfunction foo() {\ndosomething();\n}, function bar() {\ndosomething();\n}\n];", options: ["consistent"] },
         { code: "var foo = [\nfunction foo() {\ndosomething();\n},\nfunction bar() {\ndosomething();\n},\nfunction bar() {\ndosomething();\n}];", options: ["consistent"] },
         { code: "var foo = [\nfunction foo() {\ndosomething();\n}, function bar() {\ndosomething();\n}, function bar() {\ndosomething();\n}];", options: ["consistent"] },
+        { code: "var foo = [1,\n[\n2,3,\n]\n];", options: ["consistent"] },
+        { code: "var foo = [\n1,\n[2\n,3\n,]\n];", options: ["consistent"] },
+        { code: "var foo = [\n1,[2,\n3]];", options: ["consistent"] },
 
         // { multiline: true }
         { code: "var foo = [];", options: [{ multiline: true }] },
@@ -89,6 +97,7 @@ ruleTester.run("array-element-newline", rule, {
         { code: "var foo = [1, 2];", options: [{ multiline: true }] },
         { code: "var foo = [1, 2, 3];", options: [{ multiline: true }] },
         { code: "var f = [\nfunction foo() {\ndosomething();\n},\nfunction bar() {\ndosomething();\n}\n];", options: [{ multiline: true }] },
+        { code: "var foo = [\n1,\n2,\n3,\n[\n]\n];", options: [{ multiline: true }] },
 
         // { minItems: null }
         { code: "var foo = [];", options: [{ minItems: null }] },
@@ -96,6 +105,7 @@ ruleTester.run("array-element-newline", rule, {
         { code: "var foo = [1, 2];", options: [{ minItems: null }] },
         { code: "var foo = [1, 2, 3];", options: [{ minItems: null }] },
         { code: "var foo = [\nfunction foo() {\ndosomething();\n}, function bar() {\ndosomething();\n}\n];", options: [{ minItems: null }] },
+        { code: "var foo = [1, 2, 3, [[],1,[[]]]];", options: [{ minItems: null }] },
 
         // { minItems: 0 }
         { code: "var foo = [];", options: [{ minItems: 0 }] },
@@ -103,6 +113,7 @@ ruleTester.run("array-element-newline", rule, {
         { code: "var foo = [1,\n2];", options: [{ minItems: 0 }] },
         { code: "var foo = [1,\n2,\n3];", options: [{ minItems: 0 }] },
         { code: "var foo = [\nfunction foo() {\ndosomething();\n},\nfunction bar() {\ndosomething();\n}\n];", options: [{ minItems: 0 }] },
+        { code: "var foo = [\n1, \n2, \n3,\n[\n[],\n[]],\n[]];", options: [{ minItems: 0 }] },
 
         // { minItems: 3 }
         { code: "var foo = [];", options: [{ minItems: 3 }] },
@@ -110,6 +121,7 @@ ruleTester.run("array-element-newline", rule, {
         { code: "var foo = [1, 2];", options: [{ minItems: 3 }] },
         { code: "var foo = [1,\n2,\n3];", options: [{ minItems: 3 }] },
         { code: "var foo = [\nfunction foo() {\ndosomething();\n}, function bar() {\ndosomething();\n}\n];", options: [{ minItems: 3 }] },
+        { code: "var foo = [[1,2],[[\n1,\n2,\n3]]];", options: [{ minItems: 3 }] },
 
         // { multiline: true, minItems: 3 }
         { code: "var foo = [];", options: [{ multiline: true, minItems: 3 }] },
@@ -130,6 +142,10 @@ ruleTester.run("array-element-newline", rule, {
         { code: "var [// any comment \na,\nb] = foo;", parserOptions: { ecmaVersion: 6 } },
         { code: "var [a,\nb // any comment\n] = foo;", parserOptions: { ecmaVersion: 6 } },
         { code: "var [a,\nb,\nb] = foo;", parserOptions: { ecmaVersion: 6 } },
+        { code: "var [\na,\n[\nb,\nc]] = foo;", parserOptions: { ecmaVersion: 6 } },
+
+        // "never"
+        { code: "var [a,[b,c]] = foo;", options: ["never"], parserOptions: { ecmaVersion: 6 } },
 
         // { minItems: 3 }
         { code: "var [] = foo;", options: [{ minItems: 3 }], parserOptions: { ecmaVersion: 6 } },
@@ -144,6 +160,19 @@ ruleTester.run("array-element-newline", rule, {
         { code: "var [a, b] = [1,\n2]", options: [{ ArrayExpression: "always", ArrayPattern: "never" }], parserOptions: { ecmaVersion: 6 } }],
 
     invalid: [
+        {
+            code: "var foo = [\n1,[2,\n3]]",
+            output: "var foo = [\n1,\n[2,\n3]]",
+            errors: [
+                {
+                    line: 2,
+                    column: 3,
+                    messageId: "missingLineBreak",
+                    endLine: 2,
+                    endColumn: 3
+                }
+            ]
+        },
 
         /*
          * ArrayExpression
@@ -363,6 +392,18 @@ ruleTester.run("array-element-newline", rule, {
                 }
             ]
         },
+        {
+            code: "var foo = [\n[1,\n2],\n3,[\n4]]",
+            output: "var foo = [\n[1,\n2],\n3,\n[\n4]]",
+            options: ["always"],
+            errors: [
+                {
+                    line: 4,
+                    column: 3,
+                    messageId: "missingLineBreak"
+                }
+            ]
+        },
 
         // "never"
         {
@@ -471,6 +512,19 @@ ruleTester.run("array-element-newline", rule, {
             ]
         },
 
+        {
+            code: "var foo = [[1,\n2\n],3,[4\n]\n]",
+            output: "var foo = [[1, 2\n],3,[4\n]\n]",
+            options: ["never"],
+            errors: [
+                {
+                    line: 1,
+                    column: 15,
+                    messageId: "unexpectedLineBreak"
+                }
+            ]
+        },
+
         // "consistent"
         {
             code: "var foo = [1,\n2, 3];",
@@ -552,6 +606,23 @@ ruleTester.run("array-element-newline", rule, {
                 }
             ]
         },
+        {
+            code: "var foo = [\n1,[2,3,\n[]],\n[]\n];",
+            output: "var foo = [\n1,\n[2,\n3,\n[]],\n[]\n];",
+            options: ["consistent"],
+            errors: [
+                {
+                    line: 2,
+                    column: 3,
+                    messageId: "missingLineBreak"
+                },
+                {
+                    line: 2,
+                    column: 6,
+                    messageId: "missingLineBreak"
+                }
+            ]
+        },
 
         // { multiline: true }
         {
@@ -590,6 +661,23 @@ ruleTester.run("array-element-newline", rule, {
                 }
             ]
         },
+        {
+            code: "var foo = [\n1,2,3,\n[\n]\n];",
+            output: "var foo = [\n1,\n2,\n3,\n[\n]\n];",
+            options: [{ multiline: true }],
+            errors: [
+                {
+                    line: 2,
+                    column: 3,
+                    messageId: "missingLineBreak"
+                },
+                {
+                    line: 2,
+                    column: 5,
+                    messageId: "missingLineBreak"
+                }
+            ]
+        },
 
         // { minItems: null }
         {
index 5aa401f914a4c66e7144289297d551807badfecc..1eb30825489c875c102e3bc7143731a188662daa 100644 (file)
@@ -292,7 +292,9 @@ ruleTester.run("comma-style", rule, {
             output: "var foo = 1,\nbar = 2;",
             errors: [{
                 messageId: "expectedCommaLast",
-                type: "VariableDeclarator"
+                type: "VariableDeclarator",
+                column: 1,
+                endColumn: 2
             }]
         },
         {
@@ -473,7 +475,9 @@ ruleTester.run("comma-style", rule, {
             options: ["first"],
             errors: [{
                 messageId: "expectedCommaFirst",
-                type: "VariableDeclarator"
+                type: "VariableDeclarator",
+                column: 12,
+                endColumn: 13
             }]
         },
         {
@@ -590,7 +594,9 @@ ruleTester.run("comma-style", rule, {
             output: "var foo = [\n(bar\n),\nbaz\n];",
             errors: [{
                 messageId: "unexpectedLineBeforeAndAfterComma",
-                type: "Identifier"
+                type: "Identifier",
+                column: 1,
+                endColumn: 2
             }]
         },
         {
index d276ae9fc2f146a201a8ad464b18a009d92aea6e..0774ec4d0c89f260ba53cde39bad6b6afce0c6c2 100644 (file)
@@ -226,99 +226,99 @@ ruleTester.run("func-call-spacing", rule, {
         {
             code: "f ();",
             output: "f();",
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f (a, b);",
             output: "f(a, b);",
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f.b ();",
             output: "f.b();",
-            errors: [{ messageId: "unexpected", type: "CallExpression", column: 3 }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression", column: 3 }]
         },
         {
             code: "f.b().c ();",
             output: "f.b().c();",
-            errors: [{ messageId: "unexpected", type: "CallExpression", column: 7 }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression", column: 7 }]
         },
         {
             code: "f() ()",
             output: "f()()",
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "(function() {} ())",
             output: "(function() {}())",
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "var f = new Foo ()",
             output: "var f = new Foo()",
-            errors: [{ messageId: "unexpected", type: "NewExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "NewExpression" }]
         },
         {
             code: "f ( (0) )",
             output: "f( (0) )",
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f(0) (1)",
             output: "f(0)(1)",
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "(f) (0)",
             output: "(f)(0)",
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f ();\n t   ();",
             output: "f();\n t();",
             errors: [
-                { messageId: "unexpected", type: "CallExpression" },
-                { messageId: "unexpected", type: "CallExpression" }
+                { messageId: "unexpectedWhitespace", type: "CallExpression" },
+                { messageId: "unexpectedWhitespace", type: "CallExpression" }
             ]
         },
         {
             code: "import (source);",
             output: "import(source);",
             parserOptions: { ecmaVersion: 2020 },
-            errors: [{ messageId: "unexpected", type: "ImportExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "ImportExpression" }]
         },
 
         // https://github.com/eslint/eslint/issues/7787
         {
             code: "f\n();",
             output: null, // no change
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f\r();",
             output: null, // no change
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f\u2028();",
             output: null, // no change
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f\u2029();",
             output: null, // no change
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f\r\n();",
             output: null, // no change
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "import\n(source);",
             output: null,
             parserOptions: { ecmaVersion: 2020 },
-            errors: [{ messageId: "unexpected", type: "ImportExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "ImportExpression" }]
         },
 
         // "never"
@@ -326,69 +326,69 @@ ruleTester.run("func-call-spacing", rule, {
             code: "f ();",
             output: "f();",
             options: ["never"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f (a, b);",
             output: "f(a, b);",
             options: ["never"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f.b ();",
             output: "f.b();",
             options: ["never"],
-            errors: [{ messageId: "unexpected", type: "CallExpression", column: 3 }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression", column: 3 }]
         },
         {
             code: "f.b().c ();",
             output: "f.b().c();",
             options: ["never"],
-            errors: [{ messageId: "unexpected", type: "CallExpression", column: 7 }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression", column: 7 }]
         },
         {
             code: "f() ()",
             output: "f()()",
             options: ["never"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "(function() {} ())",
             output: "(function() {}())",
             options: ["never"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "var f = new Foo ()",
             output: "var f = new Foo()",
             options: ["never"],
-            errors: [{ messageId: "unexpected", type: "NewExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "NewExpression" }]
         },
         {
             code: "f ( (0) )",
             output: "f( (0) )",
             options: ["never"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f(0) (1)",
             output: "f(0)(1)",
             options: ["never"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "(f) (0)",
             output: "(f)(0)",
             options: ["never"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "CallExpression" }]
         },
         {
             code: "f ();\n t   ();",
             output: "f();\n t();",
             options: ["never"],
             errors: [
-                { messageId: "unexpected", type: "CallExpression" },
-                { messageId: "unexpected", type: "CallExpression" }
+                { messageId: "unexpectedWhitespace", type: "CallExpression" },
+                { messageId: "unexpectedWhitespace", type: "CallExpression" }
             ]
         },
         {
@@ -396,7 +396,7 @@ ruleTester.run("func-call-spacing", rule, {
             output: "import(source);",
             options: ["never"],
             parserOptions: { ecmaVersion: 2020 },
-            errors: [{ messageId: "unexpected", type: "ImportExpression" }]
+            errors: [{ messageId: "unexpectedWhitespace", type: "ImportExpression" }]
         },
 
         // https://github.com/eslint/eslint/issues/7787
@@ -406,7 +406,7 @@ ruleTester.run("func-call-spacing", rule, {
             options: ["never"],
             errors: [
                 {
-                    messageId: "unexpected",
+                    messageId: "unexpectedWhitespace",
                     type: "CallExpression"
                 }
             ]
@@ -421,7 +421,7 @@ ruleTester.run("func-call-spacing", rule, {
             options: ["never"],
             errors: [
                 {
-                    messageId: "unexpected",
+                    messageId: "unexpectedWhitespace",
                     type: "CallExpression",
                     line: 2,
                     column: 23
@@ -437,7 +437,7 @@ ruleTester.run("func-call-spacing", rule, {
             options: ["never"],
             errors: [
                 {
-                    messageId: "unexpected",
+                    messageId: "unexpectedWhitespace",
                     type: "CallExpression",
                     line: 1,
                     column: 9
@@ -453,7 +453,7 @@ ruleTester.run("func-call-spacing", rule, {
             options: ["never"],
             errors: [
                 {
-                    messageId: "unexpected",
+                    messageId: "unexpectedWhitespace",
                     type: "CallExpression",
                     line: 1,
                     column: 9
@@ -466,7 +466,7 @@ ruleTester.run("func-call-spacing", rule, {
             options: ["never"],
             errors: [
                 {
-                    messageId: "unexpected",
+                    messageId: "unexpectedWhitespace",
                     type: "CallExpression"
                 }
             ]
@@ -477,7 +477,7 @@ ruleTester.run("func-call-spacing", rule, {
             options: ["never"],
             errors: [
                 {
-                    messageId: "unexpected",
+                    messageId: "unexpectedWhitespace",
                     type: "CallExpression"
                 }
             ]
@@ -488,7 +488,7 @@ ruleTester.run("func-call-spacing", rule, {
             options: ["never"],
             errors: [
                 {
-                    messageId: "unexpected",
+                    messageId: "unexpectedWhitespace",
                     type: "CallExpression"
                 }
             ]
@@ -499,7 +499,7 @@ ruleTester.run("func-call-spacing", rule, {
             options: ["never"],
             errors: [
                 {
-                    messageId: "unexpected",
+                    messageId: "unexpectedWhitespace",
                     type: "CallExpression"
                 }
             ]
@@ -516,7 +516,7 @@ ruleTester.run("func-call-spacing", rule, {
             code: "f\n();",
             output: "f ();",
             options: ["always"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedNewline", type: "CallExpression" }]
         },
         {
             code: "f(a, b);",
@@ -528,7 +528,7 @@ ruleTester.run("func-call-spacing", rule, {
             code: "f\n(a, b);",
             output: "f (a, b);",
             options: ["always"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedNewline", type: "CallExpression" }]
         },
         {
             code: "f.b();",
@@ -540,7 +540,7 @@ ruleTester.run("func-call-spacing", rule, {
             code: "f.b\n();",
             output: "f.b ();",
             options: ["always"],
-            errors: [{ messageId: "unexpected", type: "CallExpression", column: 3 }]
+            errors: [{ messageId: "unexpectedNewline", type: "CallExpression", column: 3 }]
         },
         {
             code: "f.b().c ();",
@@ -552,7 +552,7 @@ ruleTester.run("func-call-spacing", rule, {
             code: "f.b\n().c ();",
             output: "f.b ().c ();",
             options: ["always"],
-            errors: [{ messageId: "unexpected", type: "CallExpression", column: 3 }]
+            errors: [{ messageId: "unexpectedNewline", type: "CallExpression", column: 3 }]
         },
         {
             code: "f() ()",
@@ -564,14 +564,14 @@ ruleTester.run("func-call-spacing", rule, {
             code: "f\n() ()",
             output: "f () ()",
             options: ["always"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedNewline", type: "CallExpression" }]
         },
         {
             code: "f\n()()",
             output: "f () ()",
             options: ["always"],
             errors: [
-                { messageId: "unexpected", type: "CallExpression" },
+                { messageId: "unexpectedNewline", type: "CallExpression" },
                 { messageId: "missing", type: "CallExpression" }
             ]
         },
@@ -625,25 +625,25 @@ ruleTester.run("func-call-spacing", rule, {
             code: "f\r();",
             output: "f ();",
             options: ["always"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedNewline", type: "CallExpression" }]
         },
         {
             code: "f\u2028();",
             output: "f ();",
             options: ["always"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedNewline", type: "CallExpression" }]
         },
         {
             code: "f\u2029();",
             output: "f ();",
             options: ["always"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedNewline", type: "CallExpression" }]
         },
         {
             code: "f\r\n();",
             output: "f ();",
             options: ["always"],
-            errors: [{ messageId: "unexpected", type: "CallExpression" }]
+            errors: [{ messageId: "unexpectedNewline", type: "CallExpression" }]
         },
 
         // "always", "allowNewlines": true
index 082e584aeb5c94369c19e616ab004112d807a0a5..ea181650dee7836086e06515796e7ebd145c4179 100644 (file)
@@ -81,9 +81,56 @@ ruleTester.run("getter-return", rule, {
          * test obj: get
          * option: {allowImplicit: false}
          */
-        { code: "var foo = { get bar() {} };", errors: [expectedError] },
-        { code: "var foo = { get bar(){if(baz) {return true;}} };", errors: [expectedAlwaysError] },
-        { code: "var foo = { get bar() { ~function () {return true;}} };", errors: [expectedError] },
+        {
+            code: "var foo = { get bar() {} };",
+            errors: [{
+                ...expectedError,
+                line: 1,
+                column: 13,
+                endLine: 1,
+                endColumn: 20
+            }]
+        },
+        {
+            code: "var foo = { get\n bar () {} };",
+            errors: [{
+                ...expectedError,
+                line: 1,
+                column: 13,
+                endLine: 2,
+                endColumn: 6
+            }]
+        },
+        {
+            code: "var foo = { get bar(){if(baz) {return true;}} };",
+            errors: [{
+                ...expectedAlwaysError,
+                line: 1,
+                column: 13,
+                endLine: 1,
+                endColumn: 20
+            }]
+        },
+        {
+            code: "var foo = { get bar() { ~function () {return true;}} };",
+            errors: [{
+                ...expectedError,
+                line: 1,
+                column: 13,
+                endLine: 1,
+                endColumn: 20
+            }]
+        },
+        {
+            code: "var foo = { get bar() { return; } };",
+            errors: [{
+                ...expectedError,
+                line: 1,
+                column: 25,
+                endLine: 1,
+                endColumn: 32
+            }]
+        },
 
         // option: {allowImplicit: true}
         { code: "var foo = { get bar() {} };", options, errors: [expectedError] },
@@ -93,7 +140,27 @@ ruleTester.run("getter-return", rule, {
          * test class: get
          * option: {allowImplicit: false}
          */
-        { code: "class foo { get bar(){} }", errors: [expectedError] },
+        {
+            code: "class foo { get bar(){} }",
+            errors: [{
+                ...expectedError,
+                line: 1,
+                column: 13,
+                endLine: 1,
+                endColumn: 20
+            }]
+        },
+        {
+            code: "var foo = class {\n  static get\nbar(){} }",
+            errors: [{
+                messageId: "expected",
+                data: { name: "static getter 'bar'" },
+                line: 2,
+                column: 3,
+                endLine: 3,
+                endColumn: 4
+            }]
+        },
         { code: "class foo { get bar(){ if (baz) { return true; }}}", errors: [expectedAlwaysError] },
         { code: "class foo { get bar(){ ~function () { return true; }()}}", errors: [expectedError] },
 
@@ -105,8 +172,50 @@ ruleTester.run("getter-return", rule, {
          * test object.defineProperty(s)
          * option: {allowImplicit: false}
          */
-        { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", errors: [{ messageId: "expected", data: { name: "method 'get'" } }] },
-        { code: "Object.defineProperty(foo, \"bar\", { get: () => {}});", errors: [{ messageId: "expected", data: { name: "arrow function 'get'" } }] },
+        {
+            code: "Object.defineProperty(foo, 'bar', { get: function (){}});",
+            errors: [{
+                messageId: "expected",
+                data: { name: "method 'get'" },
+                line: 1,
+                column: 37,
+                endLine: 1,
+                endColumn: 51
+            }]
+        },
+        {
+            code: "Object.defineProperty(foo, 'bar', { get: function getfoo (){}});",
+            errors: [{
+                messageId: "expected",
+                data: { name: "method 'getfoo'" },
+                line: 1,
+                column: 37,
+                endLine: 1,
+                endColumn: 58
+            }]
+        },
+        {
+            code: "Object.defineProperty(foo, 'bar', { get(){} });",
+            errors: [{
+                messageId: "expected",
+                data: { name: "method 'get'" },
+                line: 1,
+                column: 37,
+                endLine: 1,
+                endColumn: 40
+            }]
+        },
+        {
+            code: "Object.defineProperty(foo, 'bar', { get: () => {}});",
+            errors: [{
+                messageId: "expected",
+                data: { name: "arrow function 'get'" },
+                line: 1,
+                column: 45,
+                endLine: 1,
+                endColumn: 47
+            }]
+        },
         { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ messageId: "expectedAlways" }] },
         { code: "Object.defineProperty(foo, \"bar\", { get: function (){ ~function () { return true; }()}});", errors: [{ messageId: "expected" }] },
         { code: "Object.defineProperties(foo, { bar: { get: function () {}} });", options, errors: [{ messageId: "expected" }] },
index 3d40beeb578e19f404cef437df822a4f7c47a720..a900924373f70a7ba8d29386de70a33c7332b261 100644 (file)
@@ -367,7 +367,7 @@ ruleTester.run("id-blacklist", rule, {
                     column: 5
                 },
 
-                // reports each occurence of local identifier, although it's renamed in this export specifier
+                // reports each occurrence of local identifier, although it's renamed in this export specifier
                 {
                     messageId: "blacklisted",
                     data: { name: "foo" },
index 089424e1c477631cf39395cc0a37cbce6a12a5cf..c65d4750a7da58a6cf173eb1c3138d9fdd786d93 100644 (file)
@@ -10,7 +10,7 @@
 
 const rule = require("../../../lib/rules/implicit-arrow-linebreak");
 const { RuleTester } = require("../../../lib/rule-tester");
-const { unIndent } = require("../_utils");
+const { unIndent } = require("../../_utils");
 
 const EXPECTED_LINEBREAK = { messageId: "expected" };
 const UNEXPECTED_LINEBREAK = { messageId: "unexpected" };
index 7496da218d175cfedcb95fcef1d2346f21b49975..56589be51693c3abc04c67bed52f9f1de3669452 100644 (file)
@@ -21,7 +21,7 @@ const path = require("path");
 const fixture = fs.readFileSync(path.join(__dirname, "../../fixtures/rules/indent/indent-invalid-fixture-1.js"), "utf8");
 const fixedFixture = fs.readFileSync(path.join(__dirname, "../../fixtures/rules/indent/indent-valid-fixture-1.js"), "utf8");
 const parser = require("../../fixtures/fixture-parser");
-const { unIndent } = require("../_utils");
+const { unIndent } = require("../../_utils");
 
 
 /**
@@ -5590,9 +5590,9 @@ ruleTester.run("indent", rule, {
                         \${a} \${b}
                         template
                         literal
-                        \`(() => {        
+                        \`(() => {
                     foo();
-                    
+
                     tagTwo\`multiline
                             template
                             literal
@@ -5609,12 +5609,12 @@ ruleTester.run("indent", rule, {
                 tagOne\`multiline
                     template
                     literal
-                    \${a} \${b}\`({        
+                    \${a} \${b}\`({
                     foo: 1,
                     bar: tagTwo\`multiline
                         template
                         literal\`(() => {
-                        
+
                         baz();
                     })
                 });
@@ -5651,7 +5651,7 @@ ruleTester.run("indent", rule, {
             code: unIndent`
                 foo
                     .bar
-                    .baz\` template 
+                    .baz\` template
                         literal \`(() => {
                         baz();
                     })
@@ -11207,9 +11207,9 @@ ruleTester.run("indent", rule, {
                 tagOne\`multiline \${a} \${b}
                         template
                         literal
-                        \`(() => {        
+                        \`(() => {
                 foo();
-                    
+
                     tagTwo\`multiline
                             template
                             literal
@@ -11223,9 +11223,9 @@ ruleTester.run("indent", rule, {
                 tagOne\`multiline \${a} \${b}
                         template
                         literal
-                        \`(() => {        
+                        \`(() => {
                     foo();
-                    
+
                     tagTwo\`multiline
                             template
                             literal
@@ -11250,7 +11250,7 @@ ruleTester.run("indent", rule, {
                 bar: tagTwo\`multiline
                         template
                         literal\`(() => {
-                        
+
                 baz();
                     })
                 });
@@ -11263,7 +11263,7 @@ ruleTester.run("indent", rule, {
                     bar: tagTwo\`multiline
                         template
                         literal\`(() => {
-                        
+
                         baz();
                     })
                 });
index 9971facf18cb47be18f91dd399393abead303f47..f7f5ccab2b7f13e7a23d1fb2f14a0726c09558f6 100644 (file)
@@ -34,7 +34,7 @@ const NEITHER = { before: false, after: false };
  *         after: false,
  *         overrides: {as: {before: true, after: true}}
  *     }
- * @param {string} keyword A keyword to be overriden.
+ * @param {string} keyword A keyword to be overridden.
  * @param {Object} value A value to override.
  * @returns {Object} An option object to test an "overrides" option.
  */
index 706bca1983cddea4d5b8ed123eb86e7b858eb7e6..ec85c4bf6fd0eb2e878b89a55ac90c5a5648a84a 100644 (file)
@@ -74,15 +74,105 @@ ruleTester.run("new-cap", rule, {
         { code: "var x = foo.Bar(42);", options: [{ capIsNew: false, properties: false }] }
     ],
     invalid: [
-        { code: "var x = new c();", errors: [{ messageId: "lower", type: "NewExpression" }] },
-        { code: "var x = new φ;", errors: [{ messageId: "lower", type: "NewExpression" }] },
-        { code: "var x = new a.b.c;", errors: [{ messageId: "lower", type: "NewExpression" }] },
-        { code: "var x = new a.b['c'];", errors: [{ messageId: "lower", type: "NewExpression" }] },
-        { code: "var b = Foo();", errors: [{ messageId: "upper", type: "CallExpression" }] },
-        { code: "var b = a.Foo();", errors: [{ messageId: "upper", type: "CallExpression" }] },
-        { code: "var b = a['Foo']();", errors: [{ messageId: "upper", type: "CallExpression" }] },
-        { code: "var b = a.Date.UTC();", errors: [{ messageId: "upper", type: "CallExpression" }] },
-        { code: "var b = UTC();", errors: [{ messageId: "upper", type: "CallExpression" }] },
+        {
+            code: "var x = new c();",
+            errors: [{
+                messageId: "lower",
+                type: "NewExpression",
+                line: 1,
+                column: 13,
+                endLine: 1,
+                endColumn: 14
+            }]
+        },
+        {
+            code: "var x = new φ;",
+            errors: [{
+                messageId: "lower",
+                type: "NewExpression",
+                line: 1,
+                column: 13,
+                endLine: 1,
+                endColumn: 14
+            }]
+        },
+        {
+            code: "var x = new a.b.c;",
+            errors: [{
+                messageId: "lower",
+                type: "NewExpression",
+                line: 1,
+                column: 17,
+                endLine: 1,
+                endColumn: 18
+            }]
+        },
+        {
+            code: "var x = new a.b['c'];",
+            errors: [{
+                messageId: "lower",
+                type: "NewExpression",
+                line: 1,
+                column: 17,
+                endLine: 1,
+                endColumn: 20
+            }]
+        },
+        {
+            code: "var b = Foo();",
+            errors: [{
+                messageId: "upper",
+                type: "CallExpression",
+                line: 1,
+                column: 9,
+                endLine: 1,
+                endColumn: 12
+            }]
+        },
+        {
+            code: "var b = a.Foo();",
+            errors: [{
+                messageId: "upper",
+                type: "CallExpression",
+                line: 1,
+                column: 11,
+                endLine: 1,
+                endColumn: 14
+            }]
+        },
+        {
+            code: "var b = a['Foo']();",
+            errors: [{
+                messageId: "upper",
+                type: "CallExpression",
+                line: 1,
+                column: 11,
+                endLine: 1,
+                endColumn: 16
+            }]
+        },
+        {
+            code: "var b = a.Date.UTC();",
+            errors: [{
+                messageId: "upper",
+                type: "CallExpression",
+                line: 1,
+                column: 16,
+                endLine: 1,
+                endColumn: 19
+            }]
+        },
+        {
+            code: "var b = UTC();",
+            errors: [{
+                messageId: "upper",
+                type: "CallExpression",
+                line: 1,
+                column: 9,
+                endLine: 1,
+                endColumn: 12
+            }]
+        },
         {
             code: "var a = B.C();",
             errors: [
@@ -90,7 +180,9 @@ ruleTester.run("new-cap", rule, {
                     messageId: "upper",
                     type: "CallExpression",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 }
             ]
         },
@@ -101,7 +193,9 @@ ruleTester.run("new-cap", rule, {
                     messageId: "upper",
                     type: "CallExpression",
                     line: 2,
-                    column: 2
+                    column: 2,
+                    endLine: 2,
+                    endColumn: 3
                 }
             ]
         },
@@ -112,7 +206,9 @@ ruleTester.run("new-cap", rule, {
                     messageId: "lower",
                     type: "NewExpression",
                     line: 1,
-                    column: 15
+                    column: 15,
+                    endLine: 1,
+                    endColumn: 16
                 }
             ]
         },
@@ -123,7 +219,9 @@ ruleTester.run("new-cap", rule, {
                     messageId: "lower",
                     type: "NewExpression",
                     line: 2,
-                    column: 1
+                    column: 1,
+                    endLine: 2,
+                    endColumn: 2
                 }
             ]
         },
@@ -134,7 +232,51 @@ ruleTester.run("new-cap", rule, {
                     messageId: "lower",
                     type: "NewExpression",
                     line: 1,
-                    column: 13
+                    column: 13,
+                    endLine: 1,
+                    endColumn: 14
+                }
+            ]
+        },
+        {
+            code: "var a = new b[ ( 'foo' ) ]();",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "lower",
+                    type: "NewExpression",
+                    line: 1,
+                    column: 18,
+                    endLine: 1,
+                    endColumn: 23
+                }
+            ]
+        },
+        {
+            code: "var a = new b[`foo`];",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "lower",
+                    type: "NewExpression",
+                    line: 1,
+                    column: 15,
+                    endLine: 1,
+                    endColumn: 20
+                }
+            ]
+        },
+        {
+            code: "var a = b[`\\\nFoo`]();",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "upper",
+                    type: "CallExpression",
+                    line: 1,
+                    column: 11,
+                    endLine: 2,
+                    endColumn: 5
                 }
             ]
         },
index a0eefd2e790e4e23b676b0336b6554958657f658..28d45c69b820ee4caae48ca280dc1dab7d47fbb1 100644 (file)
@@ -30,47 +30,92 @@ ruleTester.run("newline-per-chained-call", rule, {
         code: "_\n.chain({}).map(foo).filter(bar).value();",
         output: "_\n.chain({}).map(foo)\n.filter(bar)\n.value();",
         errors: [{
-            messageId: "expected", data: { callee: ".filter" }
+            messageId: "expected",
+            data: { callee: ".filter" },
+            line: 2,
+            column: 20,
+            endLine: 2,
+            endColumn: 27
         }, {
-            messageId: "expected", data: { callee: ".value" }
+            messageId: "expected",
+            data: { callee: ".value" },
+            line: 2,
+            column: 32,
+            endLine: 2,
+            endColumn: 38
         }]
     }, {
         code: "_\n.chain({})\n.map(foo)\n.filter(bar).value();",
         output: "_\n.chain({})\n.map(foo)\n.filter(bar)\n.value();",
         errors: [{
-            messageId: "expected", data: { callee: ".value" }
+            messageId: "expected",
+            data: { callee: ".value" },
+            line: 4,
+            column: 13,
+            endLine: 4,
+            endColumn: 19
         }]
     }, {
         code: "a().b().c().e.d()",
         output: "a().b()\n.c().e.d()",
         errors: [{
-            messageId: "expected", data: { callee: ".c" }
+            messageId: "expected",
+            data: { callee: ".c" },
+            line: 1,
+            column: 8,
+            endLine: 1,
+            endColumn: 10
         }]
     }, {
         code: "a.b.c().e().d()",
         output: "a.b.c().e()\n.d()",
         errors: [{
-            messageId: "expected", data: { callee: ".d" }
+            messageId: "expected",
+            data: { callee: ".d" },
+            line: 1,
+            column: 12,
+            endLine: 1,
+            endColumn: 14
         }]
     }, {
         code: "_.chain({}).map(a).value(); ",
         output: "_.chain({}).map(a)\n.value(); ",
         errors: [{
-            messageId: "expected", data: { callee: ".value" }
+            messageId: "expected",
+            data: { callee: ".value" },
+            line: 1,
+            column: 19,
+            endLine: 1,
+            endColumn: 25
         }]
     }, {
         code: "var a = m1.m2();\n var b = m1.m2().m3().m4().m5();",
         output: "var a = m1.m2();\n var b = m1.m2().m3()\n.m4()\n.m5();",
         errors: [{
-            messageId: "expected", data: { callee: ".m4" }
+            messageId: "expected",
+            data: { callee: ".m4" },
+            line: 2,
+            column: 22,
+            endLine: 2,
+            endColumn: 25
         }, {
-            messageId: "expected", data: { callee: ".m5" }
+            messageId: "expected",
+            data: { callee: ".m5" },
+            line: 2,
+            column: 27,
+            endLine: 2,
+            endColumn: 30
         }]
     }, {
         code: "var a = m1.m2();\n var b = m1.m2().m3()\n.m4().m5();",
         output: "var a = m1.m2();\n var b = m1.m2().m3()\n.m4()\n.m5();",
         errors: [{
-            messageId: "expected", data: { callee: ".m5" }
+            messageId: "expected",
+            data: { callee: ".m5" },
+            line: 3,
+            column: 6,
+            endLine: 3,
+            endColumn: 9
         }]
     }, {
         code: "var a = m1().m2\n.m3().m4().m5().m6().m7();",
@@ -79,9 +124,19 @@ ruleTester.run("newline-per-chained-call", rule, {
             ignoreChainWithDepth: 3
         }],
         errors: [{
-            messageId: "expected", data: { callee: ".m6" }
+            messageId: "expected",
+            data: { callee: ".m6" },
+            line: 2,
+            column: 16,
+            endLine: 2,
+            endColumn: 19
         }, {
-            messageId: "expected", data: { callee: ".m7" }
+            messageId: "expected",
+            data: { callee: ".m7" },
+            line: 2,
+            column: 21,
+            endLine: 2,
+            endColumn: 24
         }]
     }, {
         code: [
@@ -145,9 +200,19 @@ ruleTester.run("newline-per-chained-call", rule, {
             ".end();"
         ].join("\n"),
         errors: [{
-            messageId: "expected", data: { callee: ".on" }
+            messageId: "expected",
+            data: { callee: ".on" },
+            line: 16,
+            column: 3,
+            endLine: 16,
+            endColumn: 6
         }, {
-            messageId: "expected", data: { callee: ".end" }
+            messageId: "expected",
+            data: { callee: ".end" },
+            line: 27,
+            column: 3,
+            endLine: 27,
+            endColumn: 7
         }]
     }, {
         code: [
@@ -163,34 +228,117 @@ ruleTester.run("newline-per-chained-call", rule, {
             "    'method4']()"
         ].join("\n"),
         errors: [{
-            messageId: "expected", data: { callee: "['method' + n]" }
+            messageId: "expected",
+            data: { callee: "['method' + n]" },
+            line: 1,
+            column: 29,
+            endLine: 1,
+            endColumn: 43
         }, {
-            messageId: "expected", data: { callee: "[aCondition ?" }
+            messageId: "expected",
+            data: { callee: "[aCondition ?" },
+            line: 1,
+            column: 45,
+            endLine: 3,
+            endColumn: 15
         }]
     }, {
         code: "foo.bar()['foo' + \u2029 + 'bar']()",
         output: "foo.bar()\n['foo' + \u2029 + 'bar']()",
         options: [{ ignoreChainWithDepth: 1 }],
-        errors: [{ messageId: "expected", data: { callee: "['foo' + " } }]
+        errors: [{
+            messageId: "expected",
+            data: { callee: "['foo' + " },
+            line: 1,
+            column: 10,
+            endLine: 2,
+            endColumn: 10
+        }]
     }, {
         code: "foo.bar()[(biz)]()",
         output: "foo.bar()\n[(biz)]()",
         options: [{ ignoreChainWithDepth: 1 }],
-        errors: [{ messageId: "expected", data: { callee: "[biz]" } }]
+        errors: [{
+            messageId: "expected",
+            data: { callee: "[biz]" },
+            line: 1,
+            column: 10,
+            endLine: 1,
+            endColumn: 17
+        }]
     }, {
         code: "(foo).bar().biz()",
         output: "(foo).bar()\n.biz()",
         options: [{ ignoreChainWithDepth: 1 }],
-        errors: [{ messageId: "expected", data: { callee: ".biz" } }]
+        errors: [{
+            messageId: "expected",
+            data: { callee: ".biz" },
+            line: 1,
+            column: 12,
+            endLine: 1,
+            endColumn: 16
+        }]
     }, {
         code: "foo.bar(). /* comment */ biz()",
         output: "foo.bar()\n. /* comment */ biz()",
         options: [{ ignoreChainWithDepth: 1 }],
-        errors: [{ messageId: "expected", data: { callee: ".biz" } }]
+        errors: [{
+            messageId: "expected",
+            data: { callee: ".biz" },
+            line: 1,
+            column: 10,
+            endLine: 1,
+            endColumn: 29
+        }]
     }, {
         code: "foo.bar() /* comment */ .biz()",
         output: "foo.bar() /* comment */ \n.biz()",
         options: [{ ignoreChainWithDepth: 1 }],
-        errors: [{ messageId: "expected", data: { callee: ".biz" } }]
+        errors: [{
+            messageId: "expected",
+            data: { callee: ".biz" },
+            line: 1,
+            column: 25,
+            endLine: 1,
+            endColumn: 29
+        }]
+    }, {
+        code: "((foo.bar()) . baz()).quux();",
+        output: "((foo.bar()) \n. baz())\n.quux();",
+        options: [{ ignoreChainWithDepth: 1 }],
+        errors: [{
+            messageId: "expected",
+            data: { callee: ".baz" },
+            line: 1,
+            column: 14,
+            endLine: 1,
+            endColumn: 19
+        }, {
+            messageId: "expected",
+            data: { callee: ".quux" },
+            line: 1,
+            column: 22,
+            endLine: 1,
+            endColumn: 27
+        }]
+    }, {
+        code: "((foo.bar()) [a + b] ()) [(c + d)]()",
+        output: "((foo.bar()) \n[a + b] ()) \n[(c + d)]()",
+        options: [{ ignoreChainWithDepth: 1 }],
+        errors: [{
+            messageId: "expected",
+            data: { callee: "[a + b]" },
+            line: 1,
+            column: 14,
+            endLine: 1,
+            endColumn: 21
+        }, {
+            messageId: "expected",
+            data: { callee: "[c + d]" },
+            line: 1,
+            column: 26,
+            endLine: 1,
+            endColumn: 35
+        }]
     }]
 });
index c43ec4a0cb89f16742e107bc64558e2377f0913a..f42c2325f25cb569db4e9e476913de33ddfa7485 100644 (file)
@@ -312,5 +312,66 @@ ruleTester.run("no-empty-function", rule, [
         }
 
     ],
-    invalid: []
+    invalid: [
+
+        // location tests
+        {
+            code: "function foo() {}",
+            errors: [{
+                messageId: "unexpected",
+                data: { name: "function 'foo'" },
+                line: 1,
+                column: 16,
+                endLine: 1,
+                endColumn: 18
+            }]
+        },
+        {
+            code: "var foo = function () {\n}",
+            errors: [{
+                messageId: "unexpected",
+                data: { name: "function" },
+                line: 1,
+                column: 23,
+                endLine: 2,
+                endColumn: 2
+            }]
+        },
+        {
+            code: "var foo = () => { \n\n  }",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "unexpected",
+                data: { name: "arrow function" },
+                line: 1,
+                column: 17,
+                endLine: 3,
+                endColumn: 4
+            }]
+        },
+        {
+            code: "var obj = {\n\tfoo() {\n\t}\n}",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "unexpected",
+                data: { name: "method 'foo'" },
+                line: 2,
+                column: 8,
+                endLine: 3,
+                endColumn: 3
+            }]
+        },
+        {
+            code: "class A { foo() { } }",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "unexpected",
+                data: { name: "method 'foo'" },
+                line: 1,
+                column: 17,
+                endLine: 1,
+                endColumn: 20
+            }]
+        }
+    ]
 }));
index 13df7dc1ed1aeddd00c76dae196ea68b56231d4d..5062857e699d1d640494c97236b6b44dec91c25c 100644 (file)
@@ -530,13 +530,17 @@ ruleTester.run("no-extra-parens", rule, {
         "() => ({ foo: 1 }).foo",
         "() => ({ foo: 1 }.foo().bar).baz.qux()",
         "() => ({ foo: 1 }.foo().bar + baz)",
+        {
+            code: "export default (a, b)",
+            parserOptions: { sourceType: "module" }
+        },
         {
             code: "export default (function(){}).foo",
-            parserOptions: { ecmaVersion: 6, sourceType: "module" }
+            parserOptions: { sourceType: "module" }
         },
         {
             code: "export default (class{}).foo",
-            parserOptions: { ecmaVersion: 6, sourceType: "module" }
+            parserOptions: { sourceType: "module" }
         },
         "({}).hasOwnProperty.call(foo, bar)",
         "({}) ? foo() : bar()",
@@ -1358,6 +1362,55 @@ ruleTester.run("no-extra-parens", rule, {
             "UpdateExpression",
             1
         ),
+        invalid(
+            "export default ((a, b))",
+            "export default (a, b)",
+            "SequenceExpression",
+            1,
+            { parserOptions: { sourceType: "module" } }
+        ),
+        invalid(
+            "export default (() => {})",
+            "export default () => {}",
+            "ArrowFunctionExpression",
+            1,
+            { parserOptions: { sourceType: "module" } }
+        ),
+        invalid(
+            "export default ((a, b) => a + b)",
+            "export default (a, b) => a + b",
+            "ArrowFunctionExpression",
+            1,
+            { parserOptions: { sourceType: "module" } }
+        ),
+        invalid(
+            "export default (a => a)",
+            "export default a => a",
+            "ArrowFunctionExpression",
+            1,
+            { parserOptions: { sourceType: "module" } }
+        ),
+        invalid(
+            "export default (a = b)",
+            "export default a = b",
+            "AssignmentExpression",
+            1,
+            { parserOptions: { sourceType: "module" } }
+        ),
+        invalid(
+            "export default (a ? b : c)",
+            "export default a ? b : c",
+            "ConditionalExpression",
+            1,
+            { parserOptions: { sourceType: "module" } }
+        ),
+        invalid(
+            "export default (a)",
+            "export default a",
+            "Identifier",
+            1,
+            { parserOptions: { sourceType: "module" } }
+        ),
         invalid(
             "for (foo of(bar));",
             "for (foo of bar);",
index 0cd1d188ae0b4d3d048199b9c8f08a1f67638fff..1c712f450f016b66688e562dd328a8a6689d96cd 100644 (file)
@@ -150,7 +150,7 @@ ruleTester.run("no-implied-eval", rule, {
         { code: "window.window.setTimeout(`foo${bar}`)", parserOptions: { ecmaVersion: 6 }, env: { browser: true }, errors: [expectedError] },
         { code: "global.global.setTimeout(`foo${bar}`)", parserOptions: { ecmaVersion: 6 }, env: { node: true }, errors: [expectedError] },
 
-        // string concatination
+        // string concatenation
         { code: "setTimeout('foo' + bar)", errors: [expectedError] },
         { code: "setTimeout(foo + 'bar')", errors: [expectedError] },
         { code: "setTimeout(`foo` + bar)", parserOptions: { ecmaVersion: 6 }, errors: [expectedError] },
index d255824619ec79bcef767588c64523a709f1021e..a9f70fd3f5ef5037a7bd9031da6ba5adecdc9fde 100644 (file)
@@ -45,74 +45,233 @@ ruleTester.run("no-inner-declarations", rule, {
             code: "var x = {doSomething() {var foo;}}",
             options: ["both"],
             parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "export var foo;",
+            options: ["both"],
+            parserOptions: { sourceType: "module", ecmaVersion: 6 }
+        },
+        {
+            code: "export function bar() {}",
+            options: ["both"],
+            parserOptions: { sourceType: "module", ecmaVersion: 6 }
+        },
+        {
+            code: "export default function baz() {}",
+            options: ["both"],
+            parserOptions: { sourceType: "module", ecmaVersion: 6 }
+        },
+        {
+            code: "exports.foo = () => {}",
+            options: ["both"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "exports.foo = function(){}",
+            options: ["both"]
+        },
+        {
+            code: "module.exports = function foo(){}",
+            options: ["both"]
         }
 
     ],
 
     // Examples of code that should trigger the rule
-    invalid: [{
-        code: "if (test) { function doSomething() { } }",
-        options: ["both"],
-        errors: [{
-            messageId: "moveDeclToRoot",
-            data: {
-                type: "function",
-                body: "program"
-            },
-            type: "FunctionDeclaration"
-        }]
-    }, {
-        code: "function doSomething() { do { function somethingElse() { } } while (test); }",
-        errors: [{
-            messageId: "moveDeclToRoot",
-            data: {
-                type: "function",
-                body: "function body"
-            },
-            type: "FunctionDeclaration"
-        }]
-    }, {
-        code: "(function() { if (test) { function doSomething() { } } }());",
-        errors: [{
-            messageId: "moveDeclToRoot",
-            data: {
-                type: "function",
-                body: "function body"
-            },
-            type: "FunctionDeclaration"
-        }]
-    }, {
-        code: "while (test) { var foo; }",
-        options: ["both"],
-        errors: [{
-            messageId: "moveDeclToRoot",
-            data: {
-                type: "variable",
-                body: "program"
-            },
-            type: "VariableDeclaration"
-        }]
-    }, {
-        code: "function doSomething() { if (test) { var foo = 42; } }",
-        options: ["both"],
-        errors: [{
-            messageId: "moveDeclToRoot",
-            data: {
-                type: "variable",
-                body: "function body"
-            },
-            type: "VariableDeclaration"
-        }]
-    }, {
-        code: "(function() { if (test) { var foo; } }());",
-        options: ["both"],
-        errors: [{
-            messageId: "moveDeclToRoot",
-            data: {
-                type: "variable",
-                body: "function body"
-            },
-            type: "VariableDeclaration"
-        }]
-    }]
+    invalid: [
+        {
+            code: "if (test) { function doSomething() { } }",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "function",
+                    body: "program"
+                },
+                type: "FunctionDeclaration"
+            }]
+        }, {
+            code: "if (foo) var a; ",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "program"
+                },
+                type: "VariableDeclaration"
+            }]
+        }, {
+            code: "if (foo) /* some comments */ var a; ",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "program"
+                },
+                type: "VariableDeclaration"
+            }]
+        }, {
+            code: "if (foo){ function f(){ if(bar){ var a; } } }",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "function",
+                    body: "program"
+                },
+                type: "FunctionDeclaration"
+            }, {
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "function body"
+                },
+                type: "VariableDeclaration"
+            }]
+        }, {
+            code: "if (foo) function f(){ if(bar) var a; } ",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "function",
+                    body: "program"
+                },
+                type: "FunctionDeclaration"
+            }, {
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "function body"
+                },
+                type: "VariableDeclaration"
+            }]
+        }, {
+            code: "if (foo) { var fn = function(){} } ",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "program"
+                },
+                type: "VariableDeclaration"
+            }]
+        },
+        {
+            code: "if (foo)  function f(){} ",
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "function",
+                    body: "program"
+                },
+                type: "FunctionDeclaration"
+            }]
+        },
+        {
+            code: "function bar() { if (foo) function f(){}; }",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "function",
+                    body: "function body"
+                },
+                type: "FunctionDeclaration"
+            }]
+        },
+        {
+            code: "function bar() { if (foo) var a; }",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "function body"
+                },
+                type: "VariableDeclaration"
+            }]
+        },
+        {
+            code: "if (foo){ var a; }",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "program"
+                },
+                type: "VariableDeclaration"
+            }]
+        }, {
+            code: "function doSomething() { do { function somethingElse() { } } while (test); }",
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "function",
+                    body: "function body"
+                },
+                type: "FunctionDeclaration"
+            }]
+        }, {
+            code: "(function() { if (test) { function doSomething() { } } }());",
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "function",
+                    body: "function body"
+                },
+                type: "FunctionDeclaration"
+            }]
+        }, {
+            code: "while (test) { var foo; }",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "program"
+                },
+                type: "VariableDeclaration"
+            }]
+        }, {
+            code: "function doSomething() { if (test) { var foo = 42; } }",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "function body"
+                },
+                type: "VariableDeclaration"
+            }]
+        }, {
+            code: "(function() { if (test) { var foo; } }());",
+            options: ["both"],
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "function body"
+                },
+                type: "VariableDeclaration"
+            }]
+        }, {
+            code: "const doSomething = () => { if (test) { var foo = 42; } }",
+            options: ["both"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{
+                messageId: "moveDeclToRoot",
+                data: {
+                    type: "variable",
+                    body: "function body"
+                },
+                type: "VariableDeclaration"
+            }]
+        }
+
+    ]
 });
index 667da7c43970ab63b4d57e585f6f7d1ba94837d0..0e8f5eb99573a141f404fee3a7096d00e33c08ad 100644 (file)
@@ -20,15 +20,50 @@ const ruleTester = new RuleTester();
 
 ruleTester.run("no-new-object", rule, {
     valid: [
-        "var foo = new foo.Object()"
+        "var myObject = {};",
+        "var myObject = new CustomObject();",
+        "var foo = new foo.Object()",
+        `var Object = function Object() {};
+            new Object();`,
+        `var x = something ? MyClass : Object;
+        var y = new x();`,
+        {
+            code: `
+        class Object {
+            constructor(){
+
+            }
+        }
+        new Object();
+        `,
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: `
+        import { Object } from './'
+        new Object();
+        `,
+            parserOptions: { ecmaVersion: 6, sourceType: "module" }
+        }
     ],
     invalid: [
         {
             code: "var foo = new Object()",
-            errors: [{
-                messageId: "preferLiteral",
-                type: "NewExpression"
-            }]
+            errors: [
+                {
+                    messageId: "preferLiteral",
+                    type: "NewExpression"
+                }
+            ]
+        },
+        {
+            code: "new Object();",
+            errors: [{ messageId: "preferLiteral", type: "NewExpression" }]
+        },
+        {
+            code: "const a = new Object()",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [{ messageId: "preferLiteral", type: "NewExpression" }]
         }
     ]
 });
index e9d0c585edc45107eb9f3aef64f029689e662196..600503c2de0c5c74514fba29d9729bf178ec7c5c 100644 (file)
@@ -52,6 +52,19 @@ ruleTester.run("no-return-assign", rule, {
         {
             code: "() => (result = a * b)",
             options: ["except-parens"]
+        },
+        "const foo = (a,b,c) => ((a = b), c)",
+        `function foo(){
+            return (a = b)
+        }`,
+        `function bar(){
+            return function foo(){
+                return (a = b) && c
+            }
+        }`,
+        {
+            code: "const foo = (a) => (b) => (a = b)",
+            parserOptions: { ecmaVersion: 6 }
         }
     ],
     invalid: [
@@ -79,7 +92,12 @@ ruleTester.run("no-return-assign", rule, {
         },
         {
             code: "() => result = a * b",
-            errors: [{ messageId: "arrowAssignment", type: "ArrowFunctionExpression" }]
+            errors: [
+                {
+                    messageId: "arrowAssignment",
+                    type: "ArrowFunctionExpression"
+                }
+            ]
         },
         {
             code: "function x() { return result = a * b; };",
@@ -95,6 +113,68 @@ ruleTester.run("no-return-assign", rule, {
             code: "function x() { return result || (result = a * b); };",
             options: ["always"],
             errors: [{ messageId: "returnAssignment", type: "ReturnStatement" }]
+        },
+        {
+            code: `function foo(){
+                return a = b
+            }`,
+            errors: [{ messageId: "returnAssignment", type: "ReturnStatement" }]
+        },
+        {
+            code: `function doSomething() {
+                return foo = bar && foo > 0;
+            }`,
+            errors: [{ messageId: "returnAssignment", type: "ReturnStatement" }]
+        },
+        {
+            code: `function doSomething() {
+                return foo = function(){
+                    return (bar = bar1)
+                }
+            }`,
+            errors: [{ messageId: "returnAssignment", type: "ReturnStatement" }]
+        },
+        {
+            code: `function doSomething() {
+                return foo = () => a
+            }`,
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "returnAssignment",
+                    type: "ReturnStatement"
+                }
+            ]
+        },
+        {
+            code: `function doSomething() {
+                return () => a = () => b
+            }`,
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "arrowAssignment",
+                    type: "ArrowFunctionExpression"
+                }
+            ]
+        },
+        {
+            code: `function foo(a){
+                return function bar(b){
+                    return a = b
+                }
+            }`,
+            errors: [{ messageId: "returnAssignment", type: "ReturnStatement" }]
+        },
+        {
+            code: "const foo = (a) => (b) => a = b",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "arrowAssignment",
+                    type: "ArrowFunctionExpression"
+                }
+            ]
         }
     ]
 });
index 6d0eba33ca58b2ec14f16cdf4fd43894172bcd9e..29d05a9215b1f9b3fdd8967b2345c27cd3e0704d 100644 (file)
@@ -43,6 +43,18 @@ ruleTester.run("no-unexpected-multiline", rule, {
             code: "x\n.y\nz `Valid Test Case`",
             parserOptions: { ecmaVersion: 6 }
         },
+        {
+            code: "f(x\n)`Valid Test Case`",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "x.\ny `Valid Test Case`",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "(x\n)`Valid Test Case`",
+            parserOptions: { ecmaVersion: 6 }
+        },
         `
             foo
             / bar /2
@@ -118,8 +130,9 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 messageId: "function",
                 line: 2,
-                column: 1
-
+                column: 1,
+                endLine: 2,
+                endColumn: 2
             }]
         },
         {
@@ -127,6 +140,8 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 line: 2,
                 column: 1,
+                endLine: 2,
+                endColumn: 2,
                 messageId: "function"
             }]
         },
@@ -135,6 +150,8 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 line: 2,
                 column: 1,
+                endLine: 2,
+                endColumn: 2,
                 messageId: "function"
             }]
         },
@@ -143,6 +160,8 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 line: 2,
                 column: 1,
+                endLine: 2,
+                endColumn: 2,
                 messageId: "property"
             }]
         },
@@ -151,6 +170,8 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 line: 2,
                 column: 5,
+                endLine: 2,
+                endColumn: 6,
                 messageId: "function"
             }]
         },
@@ -159,6 +180,8 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 line: 2,
                 column: 3,
+                endLine: 2,
+                endColumn: 4,
                 messageId: "property"
             }]
         },
@@ -166,8 +189,10 @@ ruleTester.run("no-unexpected-multiline", rule, {
             code: "let x = function() {}\n `hello`",
             parserOptions: { ecmaVersion: 6 },
             errors: [{
-                line: 1,
-                column: 9,
+                line: 2,
+                column: 2,
+                endLine: 2,
+                endColumn: 3,
                 messageId: "taggedTemplate"
             }]
         },
@@ -175,8 +200,10 @@ ruleTester.run("no-unexpected-multiline", rule, {
             code: "let x = function() {}\nx\n`hello`",
             parserOptions: { ecmaVersion: 6 },
             errors: [{
-                line: 2,
+                line: 3,
                 column: 1,
+                endLine: 3,
+                endColumn: 2,
                 messageId: "taggedTemplate"
             }]
         },
@@ -184,8 +211,10 @@ ruleTester.run("no-unexpected-multiline", rule, {
             code: "x\n.y\nz\n`Invalid Test Case`",
             parserOptions: { ecmaVersion: 6 },
             errors: [{
-                line: 3,
+                line: 4,
                 column: 1,
+                endLine: 4,
+                endColumn: 2,
                 messageId: "taggedTemplate"
             }]
         },
@@ -197,6 +226,8 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 line: 3,
                 column: 17,
+                endLine: 3,
+                endColumn: 18,
                 messageId: "division"
             }]
         },
@@ -208,6 +239,8 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 line: 3,
                 column: 17,
+                endLine: 3,
+                endColumn: 18,
                 messageId: "division"
             }]
         },
@@ -219,6 +252,8 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 line: 3,
                 column: 17,
+                endLine: 3,
+                endColumn: 18,
                 messageId: "division"
             }]
         },
@@ -230,6 +265,8 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 line: 3,
                 column: 17,
+                endLine: 3,
+                endColumn: 18,
                 messageId: "division"
             }]
         },
@@ -241,24 +278,28 @@ ruleTester.run("no-unexpected-multiline", rule, {
             errors: [{
                 line: 3,
                 column: 17,
+                endLine: 3,
+                endColumn: 18,
                 messageId: "division"
             }]
         },
 
         // https://github.com/eslint/eslint/issues/11650
         {
-            code: `
-                const x = aaaa<
-                    test
-                >/*
-                test
-                */\`foo\`
-            `,
+            code: [
+                "const x = aaaa<",
+                "  test",
+                ">/*",
+                "test",
+                "*/`foo`"
+            ].join("\n"),
             parser: require.resolve("../../fixtures/parsers/typescript-parsers/tagged-template-with-generic/tagged-template-with-generic-and-comment"),
             errors: [
                 {
-                    line: 1,
-                    column: 11,
+                    line: 5,
+                    column: 3,
+                    endLine: 5,
+                    endColumn: 4,
                     messageId: "taggedTemplate"
                 }
             ]
index 9376266623be16425c95f9ae84b5e8bd669806a4..c15b88f18172b777f3bc8b586738ccca7cbef4b7 100644 (file)
@@ -42,7 +42,25 @@ ruleTester.run("no-useless-concat", rule, {
         {
             code: "'a' + 'b'",
             errors: [
-                { messageId: "unexpectedConcat" }
+                {
+                    messageId: "unexpectedConcat",
+                    line: 1,
+                    column: 5,
+                    endLine: 1,
+                    endColumn: 6
+                }
+            ]
+        },
+        {
+            code: "'a' +\n'b' + 'c'",
+            errors: [
+                {
+                    messageId: "unexpectedConcat",
+                    line: 2,
+                    column: 5,
+                    endLine: 2,
+                    endColumn: 6
+                }
             ]
         },
         {
@@ -57,12 +75,16 @@ ruleTester.run("no-useless-concat", rule, {
                 {
                     messageId: "unexpectedConcat",
                     line: 1,
-                    column: 5
+                    column: 5,
+                    endLine: 1,
+                    endColumn: 6
                 },
                 {
                     messageId: "unexpectedConcat",
                     line: 1,
-                    column: 11
+                    column: 11,
+                    endLine: 1,
+                    endColumn: 12
                 }
             ]
         },
index b9b81329f91df7f580d86c7e184834f2d661f451..01a72f4e6f0a3259e949da7cf1354331fbbb89a2 100644 (file)
@@ -11,7 +11,7 @@
 
 const rule = require("../../../lib/rules/object-shorthand"),
     { RuleTester } = require("../../../lib/rule-tester");
-const { unIndent } = require("../_utils");
+const { unIndent } = require("../../_utils");
 
 //------------------------------------------------------------------------------
 // Tests
index bc1923939792addeda9224f4d2c08fd62e125924..09187fad6d9edbbb1f598e07d0b124786b6fc43f 100644 (file)
@@ -136,7 +136,8 @@ ruleTester.run("space-before-function-paren", rule, {
                     type: "FunctionDeclaration",
                     messageId: "missingSpace",
                     line: 1,
-                    column: 13
+                    column: 13,
+                    endColumn: 14
                 }
             ]
         },
@@ -148,7 +149,8 @@ ruleTester.run("space-before-function-paren", rule, {
                     type: "FunctionDeclaration",
                     messageId: "missingSpace",
                     line: 1,
-                    column: 13
+                    column: 18,
+                    endColumn: 19
                 }
             ]
         },
@@ -230,7 +232,8 @@ ruleTester.run("space-before-function-paren", rule, {
                     type: "FunctionDeclaration",
                     messageId: "unexpectedSpace",
                     line: 1,
-                    column: 13
+                    column: 13,
+                    endColumn: 14
                 }
             ]
         },
@@ -273,6 +276,20 @@ ruleTester.run("space-before-function-paren", rule, {
                 }
             ]
         },
+        {
+            code: "function foo  () {}",
+            output: "function foo() {}",
+            options: ["never"],
+            errors: [
+                {
+                    type: "FunctionDeclaration",
+                    messageId: "unexpectedSpace",
+                    line: 1,
+                    column: 13,
+                    endColumn: 15
+                }
+            ]
+        },
         {
             code: "function foo//\n() {}",
             output: null,
@@ -282,7 +299,9 @@ ruleTester.run("space-before-function-paren", rule, {
                     type: "FunctionDeclaration",
                     messageId: "unexpectedSpace",
                     line: 1,
-                    column: 13
+                    column: 13,
+                    endLine: 2,
+                    endColumn: 1
                 }
             ]
         },
@@ -321,7 +340,8 @@ ruleTester.run("space-before-function-paren", rule, {
                     type: "FunctionExpression",
                     messageId: "unexpectedSpace",
                     line: 1,
-                    column: 19
+                    column: 19,
+                    endColumn: 20
                 }
             ]
         },
index c0d76ca9b7ce0d8458d2780e3afcb344322357fa..43449401873ea466f41b62907cbc33fb4fe9dc5b 100644 (file)
@@ -21,148 +21,314 @@ ruleTester.run("yoda", rule, {
     valid: [
 
         // "never" mode
-        { code: "if (value === \"red\") {}", options: ["never"] },
+        { code: 'if (value === "red") {}', options: ["never"] },
         { code: "if (value === value) {}", options: ["never"] },
         { code: "if (value != 5) {}", options: ["never"] },
         { code: "if (5 & foo) {}", options: ["never"] },
         { code: "if (5 === 4) {}", options: ["never"] },
-        { code: "if (value === `red`) {}", options: ["never"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (`red` === `red`) {}", options: ["never"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (`${foo}` === `red`) {}", options: ["never"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (`${\"\"}` === `red`) {}", options: ["never"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (`${\"red\"}` === foo) {}", options: ["never"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (b > `a` && b > `a`) {}", options: ["never"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (`b` > `a` && \"b\" > \"a\") {}", options: ["never"], parserOptions: { ecmaVersion: 2015 } },
+        {
+            code: "if (value === `red`) {}",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if (`red` === `red`) {}",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if (`${foo}` === `red`) {}",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: 'if (`${""}` === `red`) {}',
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: 'if (`${"red"}` === foo) {}',
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if (b > `a` && b > `a`) {}",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: 'if (`b` > `a` && "b" > "a") {}',
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
 
         // "always" mode
-        { code: "if (\"blue\" === value) {}", options: ["always"] },
+        { code: 'if ("blue" === value) {}', options: ["always"] },
         { code: "if (value === value) {}", options: ["always"] },
         { code: "if (4 != value) {}", options: ["always"] },
         { code: "if (foo & 4) {}", options: ["always"] },
         { code: "if (5 === 4) {}", options: ["always"] },
-        { code: "if (`red` === value) {}", options: ["always"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (`red` === `red`) {}", options: ["always"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (`red` === `${foo}`) {}", options: ["always"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (`red` === `${\"\"}`) {}", options: ["always"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (foo === `${\"red\"}`) {}", options: ["always"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (`a` > b && `a` > b) {}", options: ["always"], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (`b` > `a` && \"b\" > \"a\") {}", options: ["always"], parserOptions: { ecmaVersion: 2015 } },
+        {
+            code: "if (`red` === value) {}",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if (`red` === `red`) {}",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if (`red` === `${foo}`) {}",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: 'if (`red` === `${""}`) {}',
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: 'if (foo === `${"red"}`) {}',
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if (`a` > b && `a` > b) {}",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: 'if (`b` > `a` && "b" > "a") {}',
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
 
         // Range exception
         {
-            code: "if (0 < x && x <= 1) {}",
+            code: 'if ("a" < x && x < MAX ) {}',
             options: ["never", { exceptRange: true }]
-        }, {
-            code: "if (x < 0 || 1 <= x) {}",
+        },
+        {
+            code: "if (1 < x && x < MAX ) {}",
+            options: ["never", { exceptRange: true }]
+        },
+        {
+            code: "if ('a' < x && x < MAX ) {}",
+            options: ["never", { exceptRange: true }]
+        },
+        {
+            code: "if (x < `x` || `x` <= x) {}",
+            options: ["never", { exceptRange: true }],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if (0 < x && x <= 1) {}",
             options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if (0 <= x && x < 1) {}",
             options: ["always", { exceptRange: true }]
-        }, {
-            code: "if (x <= 'bar' || 'foo' < x) {}",
-            options: ["always", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if ('blue' < x.y && x.y < 'green') {}",
             options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if (0 < x[``] && x[``] < 100) {}",
             options: ["never", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2015 }
-        }, {
+        },
+        {
             code: "if (0 < x[''] && x[``] < 100) {}",
             options: ["never", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2015 }
-        }, {
+        },
+        {
+            code:
+                "if (a < 4 || (b[c[0]].d['e'] < 0 || 1 <= b[c[0]].d['e'])) {}",
+            options: ["never", { exceptRange: true }]
+        },
+        {
             code: "if (0 <= x['y'] && x['y'] <= 100) {}",
             options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if (a < 0 && (0 < b && b < 1)) {}",
             options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if ((0 < a && a < 1) && b < 0) {}",
             options: ["never", { exceptRange: true }]
-        }, {
-            code: "if (a < 4 || (b[c[0]].d['e'] < 0 || 1 <= b[c[0]].d['e'])) {}",
-            options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if (-1 < x && x < 0) {}",
             options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if (0 <= this.prop && this.prop <= 1) {}",
             options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if (0 <= index && index < list.length) {}",
             options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if (ZERO <= index && index < 100) {}",
             options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if (value <= MIN || 10 < value) {}",
             options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if (value <= 0 || MAX < value) {}",
             options: ["never", { exceptRange: true }]
-        }, {
-            code: "if (0 <= a.b && a[\"b\"] <= 100) {}",
+        },
+        {
+            code: 'if (0 <= a.b && a["b"] <= 100) {}',
             options: ["never", { exceptRange: true }]
-        }, {
+        },
+        {
             code: "if (0 <= a.b && a[`b`] <= 100) {}",
             options: ["never", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2015 }
-        }, {
+        },
+        {
             code: "if (-1n < x && x <= 1n) {}",
             options: ["never", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2020 }
-        }, {
-            code: "if (x < -1n || 1n <= x) {}",
-            options: ["never", { exceptRange: true }],
-            parserOptions: { ecmaVersion: 2020 }
-        }, {
+        },
+        {
             code: "if (-1n <= x && x < 1n) {}",
             options: ["always", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2020 }
-        }, {
-            code: "if (x < -1n || 1n <= x) {}",
-            options: ["always", { exceptRange: true }],
-            parserOptions: { ecmaVersion: 2020 }
-        }, {
+        },
+        {
             code: "if (x < `1` || `1` < x) {}",
             options: ["always", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2020 }
-        }, {
+        },
+        {
             code: "if (1 <= a['/(?<zero>0)/'] && a[/(?<zero>0)/] <= 100) {}",
             options: ["never", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2018 }
-        }, {
+        },
+        {
             code: "if (x <= `bar` || `foo` < x) {}",
             options: ["always", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2015 }
-        }, {
+        },
+        {
+            code: "if ('a' < x && x < MAX ) {}",
+            options: ["always", { exceptRange: true }],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if ('a' < x && x < MAX ) {}",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if (MIN < x && x < 'a' ) {}",
+            options: ["never", { exceptRange: true }],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if (MIN < x && x < 'a' ) {}",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
             code: "if (`blue` < x.y && x.y < `green`) {}",
             options: ["never", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2015 }
-        }, {
+        },
+        {
             code: "if (0 <= x[`y`] && x[`y`] <= 100) {}",
             options: ["never", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2015 }
-        }, {
-            code: "if (0 <= x[`y`] && x[\"y\"] <= 100) {}",
+        },
+        {
+            code: 'if (0 <= x[`y`] && x["y"] <= 100) {}',
             options: ["never", { exceptRange: true }],
             parserOptions: { ecmaVersion: 2015 }
         },
+        {
+            code: "if ('a' <= x && x < 'b') {}",
+            options: ["never", { exceptRange: true }]
+        },
+        {
+            code: "if (x < -1n || 1n <= x) {}",
+            options: ["never", { exceptRange: true }],
+            parserOptions: { ecmaVersion: 2020 }
+        },
+        {
+            code: "if (x < -1n || 1n <= x) {}",
+            options: ["always", { exceptRange: true }],
+            parserOptions: { ecmaVersion: 2020 }
+        },
+        {
+            code: "if (1 < a && a <= 2) {}",
+            options: ["never", { exceptRange: true }]
+        },
+        {
+            code: "if (x < -1 || 1 < x) {}",
+            options: ["never", { exceptRange: true }]
+        },
+        {
+            code: "if (x <= 'bar' || 'foo' < x) {}",
+            options: ["always", { exceptRange: true }]
+        },
+        {
+            code: "if (x < 0 || 1 <= x) {}",
+            options: ["never", { exceptRange: true }]
+        },
+        {
+            code: "if('a' <= x && x < MAX) {}",
+            options: ["never", { exceptRange: true }]
+        },
 
         // onlyEquality
-        { code: "if (0 < x && x <= 1) {}", options: ["never", { onlyEquality: true }] },
-        { code: "if (x !== 'foo' && 'foo' !== x) {}", options: ["never", { onlyEquality: true }] },
-        { code: "if (x < 2 && x !== -3) {}", options: ["always", { onlyEquality: true }] },
-        { code: "if (x !== `foo` && `foo` !== x) {}", options: ["never", { onlyEquality: true }], parserOptions: { ecmaVersion: 2015 } },
-        { code: "if (x < `2` && x !== `-3`) {}", options: ["always", { onlyEquality: true }], parserOptions: { ecmaVersion: 2015 } }
+        {
+            code: "if (0 < x && x <= 1) {}",
+            options: ["never", { onlyEquality: true }]
+        },
+        {
+            code: "if (x !== 'foo' && 'foo' !== x) {}",
+            options: ["never", { onlyEquality: true }]
+        },
+        {
+            code: "if (x < 2 && x !== -3) {}",
+            options: ["always", { onlyEquality: true }]
+        },
+        {
+            code: "if (x !== `foo` && `foo` !== x) {}",
+            options: ["never", { onlyEquality: true }],
+            parserOptions: { ecmaVersion: 2015 }
+        },
+        {
+            code: "if (x < `2` && x !== `-3`) {}",
+            options: ["always", { onlyEquality: true }],
+            parserOptions: { ecmaVersion: 2015 }
+        }
     ],
     invalid: [
-
         {
-            code: "if (\"red\" == value) {}",
-            output: "if (value == \"red\") {}",
+            code: "if (x <= 'foo' || 'bar' < x) {}",
+            output: "if ('foo' >= x || 'bar' < x) {}",
+            options: ["always", { exceptRange: true }],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "left", operator: "<=" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: 'if ("red" == value) {}',
+            output: 'if (value == "red") {}',
             options: ["never"],
             errors: [
                 {
@@ -222,8 +388,8 @@ ruleTester.run("yoda", rule, {
             ]
         },
         {
-            code: "if (\"red\" <= value) {}",
-            output: "if (value >= \"red\") {}",
+            code: 'if ("red" <= value) {}',
+            output: 'if (value >= "red") {}',
             options: ["never"],
             errors: [
                 {
@@ -260,8 +426,8 @@ ruleTester.run("yoda", rule, {
             ]
         },
         {
-            code: "if (`red` <= `${\"red\"}`) {}",
-            output: "if (`${\"red\"}` >= `red`) {}",
+            code: 'if (`red` <= `${"red"}`) {}',
+            output: 'if (`${"red"}` >= `red`) {}',
             options: ["never"],
             parserOptions: { ecmaVersion: 2015 },
             errors: [
@@ -321,8 +487,8 @@ ruleTester.run("yoda", rule, {
             ]
         },
         {
-            code: "if (value == \"red\") {}",
-            output: "if (\"red\" == value) {}",
+            code: 'if (value == "red") {}',
+            output: 'if ("red" == value) {}',
             options: ["always"],
             errors: [
                 {
@@ -371,8 +537,8 @@ ruleTester.run("yoda", rule, {
             ]
         },
         {
-            code: "if (`${\"red\"}` <= `red`) {}",
-            output: "if (`red` >= `${\"red\"}`) {}",
+            code: 'if (`${"red"}` <= `red`) {}',
+            output: 'if (`red` >= `${"red"}`) {}',
             options: ["always"],
             parserOptions: { ecmaVersion: 2015 },
             errors: [
@@ -480,6 +646,19 @@ ruleTester.run("yoda", rule, {
                 }
             ]
         },
+        {
+            code: "if (`green` < x.y && x.y < `blue`) {}",
+            output: "if (x.y > `green` && x.y < `blue`) {}",
+            options: ["never", { exceptRange: true }],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
         {
             code: "if (0 <= a[b] && a['b'] < 1) {}",
             output: "if (a[b] >= 0 && a['b'] < 1) {}",
@@ -641,19 +820,6 @@ ruleTester.run("yoda", rule, {
                 }
             ]
         },
-        {
-            code: "if (`green` < x.y && x.y < `blue`) {}",
-            output: "if (x.y > `green` && x.y < `blue`) {}",
-            options: ["never", { exceptRange: true }],
-            parserOptions: { ecmaVersion: 2015 },
-            errors: [
-                {
-                    messageId: "expected",
-                    data: { expectedSide: "right", operator: "<" },
-                    type: "BinaryExpression"
-                }
-            ]
-        },
         {
             code: "if (3 == a) {}",
             output: "if (a == 3) {}",
@@ -992,6 +1158,67 @@ ruleTester.run("yoda", rule, {
                     type: "BinaryExpression"
                 }
             ]
+        },
+        {
+            code: "if (`green` < x.y && x.y < `blue`) {}",
+            output: "if (`green` < x.y && `blue` > x.y) {}",
+            options: ["always", { exceptRange: true }],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "left", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "if('a' <= x && x < 'b') {}",
+            output: "if('a' <= x && 'b' > x) {}",
+            options: ["always"],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "left", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "if ('b' <= x && x < 'a') {}",
+            output: "if (x >= 'b' && x < 'a') {}",
+            options: ["never", { exceptRange: true }],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<=" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "if('a' <= x && x < 1) {}",
+            output: "if(x >= 'a' && x < 1) {}",
+            options: ["never", { exceptRange: true }],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<=" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "if (0 < a && b < max) {}",
+            output: "if (a > 0 && b < max) {}",
+            options: ["never", { exceptRange: true }],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
         }
     ]
 });
index 79c50a414ac9925f4bef3bc293ddc671081e07ac..76ca7c7ca2871f92a4a8480a7009f3ef3c604ae9 100644 (file)
@@ -12,7 +12,7 @@
 const assert = require("chai").assert;
 const sinon = require("sinon");
 const spawn = require("cross-spawn");
-const { unIndent } = require("../_utils");
+const { unIndent } = require("../../_utils");
 const RuntimeInfo = require("../../../lib/shared/runtime-info");
 const log = require("../../../lib/shared/logging");
 const packageJson = require("../../../package.json");
index 6ebb5fb4980b246894f5738cb98e0b957c111fa6..f79d6ed15ffb47823dde390cc3b5f9c681ab29f3 100644 (file)
@@ -1111,7 +1111,7 @@ var state    = require("./state.js").state;
 var style    = require("./style.js");
 
 // We need this module here because environments such as IE and Rhino
-// don't necessarilly expose the 'console' API and browserify uses
+// don't necessarily expose the 'console' API and browserify uses
 // it to log things. It's a sad state of affair, really.
 var console = require("console-browserify");
 
@@ -1169,7 +1169,7 @@ var JSHINT = (function () {
                        immed       : true, // if immediate invocations must be wrapped in parens
                        iterator    : true, // if the `__iterator__` property should be allowed
                        jquery      : true, // if jQuery globals should be predefined
-                       lastsemic   : true, // if semicolons may be ommitted for the trailing
+                       lastsemic   : true, // if semicolons may be omitted for the trailing
                                            // statements inside of a one-line blocks.
                        laxbreak    : true, // if line breaks should not be checked
                        laxcomma    : true, // if line breaks should not be checked around commas
@@ -7466,7 +7466,7 @@ Lexer.prototype = {
        },
 
        /*
-        * Scan for any occurence of mixed tabs and spaces. If smarttabs option
+        * Scan for any occurrence of mixed tabs and spaces. If smarttabs option
         * is on, ignore tabs followed by spaces.
         *
         * Tabs followed by one space followed by a block comment are allowed.
@@ -7594,7 +7594,7 @@ Lexer.prototype = {
 
        /*
         * Produce the next token. This function is called by advance() to get
-        * the next token. It retuns a token in a JSLint-compatible format.
+        * the next token. It returns a token in a JSLint-compatible format.
         */
        token: function () {
                /*jshint loopfunc:true */
index cb7b803ef7bb42cac90048c03352c57da6b66d8a..554756bd16878606b562970e06de80396bdc3423 100755 (executable)
@@ -1496,7 +1496,7 @@ var store = __webpack_require__(26);
 (module.exports = function (key, value) {
   return store[key] || (store[key] = value !== undefined ? value : {});
 })('versions', []).push({
-  version: '3.6.4',
+  version: '3.6.5',
   mode: IS_PURE ? 'pure' : 'global',
   copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
 });
@@ -9509,7 +9509,7 @@ if (!set || !clear) {
     channel.port1.onmessage = listener;
     defer = bind(port.postMessage, port, 1); // Browsers with postMessage, skip WebWorkers
     // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
-  } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts && !fails(post)) {
+  } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts && !fails(post) && location.protocol !== 'file:') {
     defer = post;
     global.addEventListener('message', listener, false); // IE8-
   } else if (ONREADYSTATECHANGE in createElement('script')) {
@@ -13041,7 +13041,7 @@ var INVALID_SCHEME = 'Invalid scheme';
 var INVALID_HOST = 'Invalid host';
 var INVALID_PORT = 'Invalid port';
 var ALPHA = /[A-Za-z]/;
-var ALPHANUMERIC = /[\d+\-.A-Za-z]/;
+var ALPHANUMERIC = /[\d+-.A-Za-z]/;
 var DIGIT = /\d/;
 var HEX_START = /^(0x|0X)/;
 var OCT = /^[0-7]+$/;
@@ -16778,7 +16778,7 @@ class Linter {
         supportsAutofix
       } = processor;
       const disableFixes = options.disableFixes || !supportsAutofix;
-      return this._verifyWithProcessor(textOrSourceCode, config, _objectSpread({}, options, {
+      return this._verifyWithProcessor(textOrSourceCode, config, _objectSpread(_objectSpread({}, options), {}, {
         disableFixes,
         postprocess,
         preprocess
@@ -16827,13 +16827,13 @@ class Linter {
 
       if (configForRecursive && path.extname(blockName) !== originalExtname) {
         debug("Resolving configuration again because the file extension was changed.");
-        return this._verifyWithConfigArray(blockText, configForRecursive, _objectSpread({}, options, {
+        return this._verifyWithConfigArray(blockText, configForRecursive, _objectSpread(_objectSpread({}, options), {}, {
           filename: blockName
         }));
       } // Does lint.
 
 
-      return this._verifyWithoutProcessors(blockText, config, _objectSpread({}, options, {
+      return this._verifyWithoutProcessors(blockText, config, _objectSpread(_objectSpread({}, options), {}, {
         filename: blockName
       }));
     });
@@ -18967,7 +18967,7 @@ module.exports = {
 /* 383 */
 /***/ (function(module) {
 
-module.exports = JSON.parse("{\"_from\":\"estraverse@^4.1.1\",\"_id\":\"estraverse@4.3.0\",\"_inBundle\":false,\"_integrity\":\"sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==\",\"_location\":\"/estraverse\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"estraverse@^4.1.1\",\"name\":\"estraverse\",\"escapedName\":\"estraverse\",\"rawSpec\":\"^4.1.1\",\"saveSpec\":null,\"fetchSpec\":\"^4.1.1\"},\"_requiredBy\":[\"/babel-eslint/eslint-scope\",\"/eslint-scope\",\"/esrecurse\",\"/webpack/eslint-scope\"],\"_resolved\":\"https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz\",\"_shasum\":\"398ad3f3c5a24948be7725e83d11a7de28cdbd1d\",\"_spec\":\"estraverse@^4.1.1\",\"_where\":\"/home/dcsapak/git/pve-eslint/eslint-v7.0.0-alpha.3/node_modules/eslint-scope\",\"bugs\":{\"url\":\"https://github.com/estools/estraverse/issues\"},\"bundleDependencies\":false,\"deprecated\":false,\"description\":\"ECMAScript JS AST traversal functions\",\"devDependencies\":{\"babel-preset-env\":\"^1.6.1\",\"babel-register\":\"^6.3.13\",\"chai\":\"^2.1.1\",\"espree\":\"^1.11.0\",\"gulp\":\"^3.8.10\",\"gulp-bump\":\"^0.2.2\",\"gulp-filter\":\"^2.0.0\",\"gulp-git\":\"^1.0.1\",\"gulp-tag-version\":\"^1.3.0\",\"jshint\":\"^2.5.6\",\"mocha\":\"^2.1.0\"},\"engines\":{\"node\":\">=4.0\"},\"homepage\":\"https://github.com/estools/estraverse\",\"license\":\"BSD-2-Clause\",\"main\":\"estraverse.js\",\"maintainers\":[{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"http://github.com/Constellation\"}],\"name\":\"estraverse\",\"repository\":{\"type\":\"git\",\"url\":\"git+ssh://git@github.com/estools/estraverse.git\"},\"scripts\":{\"lint\":\"jshint estraverse.js\",\"test\":\"npm run-script lint && npm run-script unit-test\",\"unit-test\":\"mocha --compilers js:babel-register\"},\"version\":\"4.3.0\"}");
+module.exports = JSON.parse("{\"_from\":\"estraverse@^4.1.1\",\"_id\":\"estraverse@4.3.0\",\"_inBundle\":false,\"_integrity\":\"sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==\",\"_location\":\"/estraverse\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"estraverse@^4.1.1\",\"name\":\"estraverse\",\"escapedName\":\"estraverse\",\"rawSpec\":\"^4.1.1\",\"saveSpec\":null,\"fetchSpec\":\"^4.1.1\"},\"_requiredBy\":[\"/babel-eslint/eslint-scope\",\"/eslint-scope\",\"/esrecurse\",\"/webpack/eslint-scope\"],\"_resolved\":\"https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz\",\"_shasum\":\"398ad3f3c5a24948be7725e83d11a7de28cdbd1d\",\"_spec\":\"estraverse@^4.1.1\",\"_where\":\"/home/dcsapak/git/pve-eslint/eslint-v7.0.0/node_modules/eslint-scope\",\"bugs\":{\"url\":\"https://github.com/estools/estraverse/issues\"},\"bundleDependencies\":false,\"deprecated\":false,\"description\":\"ECMAScript JS AST traversal functions\",\"devDependencies\":{\"babel-preset-env\":\"^1.6.1\",\"babel-register\":\"^6.3.13\",\"chai\":\"^2.1.1\",\"espree\":\"^1.11.0\",\"gulp\":\"^3.8.10\",\"gulp-bump\":\"^0.2.2\",\"gulp-filter\":\"^2.0.0\",\"gulp-git\":\"^1.0.1\",\"gulp-tag-version\":\"^1.3.0\",\"jshint\":\"^2.5.6\",\"mocha\":\"^2.1.0\"},\"engines\":{\"node\":\">=4.0\"},\"homepage\":\"https://github.com/estools/estraverse\",\"license\":\"BSD-2-Clause\",\"main\":\"estraverse.js\",\"maintainers\":[{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"http://github.com/Constellation\"}],\"name\":\"estraverse\",\"repository\":{\"type\":\"git\",\"url\":\"git+ssh://git@github.com/estools/estraverse.git\"},\"scripts\":{\"lint\":\"jshint estraverse.js\",\"test\":\"npm run-script lint && npm run-script unit-test\",\"unit-test\":\"mocha --compilers js:babel-register\"},\"version\":\"4.3.0\"}");
 
 /***/ }),
 /* 384 */
@@ -20026,7 +20026,7 @@ module.exports = Referencer;
 /* 389 */
 /***/ (function(module) {
 
-module.exports = JSON.parse("{\"_from\":\"esrecurse@^4.1.0\",\"_id\":\"esrecurse@4.2.1\",\"_inBundle\":false,\"_integrity\":\"sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==\",\"_location\":\"/esrecurse\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"esrecurse@^4.1.0\",\"name\":\"esrecurse\",\"escapedName\":\"esrecurse\",\"rawSpec\":\"^4.1.0\",\"saveSpec\":null,\"fetchSpec\":\"^4.1.0\"},\"_requiredBy\":[\"/babel-eslint/eslint-scope\",\"/eslint-scope\",\"/webpack/eslint-scope\"],\"_resolved\":\"https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz\",\"_shasum\":\"007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf\",\"_spec\":\"esrecurse@^4.1.0\",\"_where\":\"/home/dcsapak/git/pve-eslint/eslint-v7.0.0-alpha.3/node_modules/eslint-scope\",\"babel\":{\"presets\":[\"es2015\"]},\"bugs\":{\"url\":\"https://github.com/estools/esrecurse/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"estraverse\":\"^4.1.0\"},\"deprecated\":false,\"description\":\"ECMAScript AST recursive visitor\",\"devDependencies\":{\"babel-cli\":\"^6.24.1\",\"babel-eslint\":\"^7.2.3\",\"babel-preset-es2015\":\"^6.24.1\",\"babel-register\":\"^6.24.1\",\"chai\":\"^4.0.2\",\"esprima\":\"^4.0.0\",\"gulp\":\"^3.9.0\",\"gulp-bump\":\"^2.7.0\",\"gulp-eslint\":\"^4.0.0\",\"gulp-filter\":\"^5.0.0\",\"gulp-git\":\"^2.4.1\",\"gulp-mocha\":\"^4.3.1\",\"gulp-tag-version\":\"^1.2.1\",\"jsdoc\":\"^3.3.0-alpha10\",\"minimist\":\"^1.1.0\"},\"engines\":{\"node\":\">=4.0\"},\"homepage\":\"https://github.com/estools/esrecurse\",\"license\":\"BSD-2-Clause\",\"main\":\"esrecurse.js\",\"maintainers\":[{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"https://github.com/Constellation\"}],\"name\":\"esrecurse\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/estools/esrecurse.git\"},\"scripts\":{\"lint\":\"gulp lint\",\"test\":\"gulp travis\",\"unit-test\":\"gulp test\"},\"version\":\"4.2.1\"}");
+module.exports = JSON.parse("{\"_from\":\"esrecurse@^4.1.0\",\"_id\":\"esrecurse@4.2.1\",\"_inBundle\":false,\"_integrity\":\"sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==\",\"_location\":\"/esrecurse\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"esrecurse@^4.1.0\",\"name\":\"esrecurse\",\"escapedName\":\"esrecurse\",\"rawSpec\":\"^4.1.0\",\"saveSpec\":null,\"fetchSpec\":\"^4.1.0\"},\"_requiredBy\":[\"/babel-eslint/eslint-scope\",\"/eslint-scope\",\"/webpack/eslint-scope\"],\"_resolved\":\"https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz\",\"_shasum\":\"007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf\",\"_spec\":\"esrecurse@^4.1.0\",\"_where\":\"/home/dcsapak/git/pve-eslint/eslint-v7.0.0/node_modules/eslint-scope\",\"babel\":{\"presets\":[\"es2015\"]},\"bugs\":{\"url\":\"https://github.com/estools/esrecurse/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"estraverse\":\"^4.1.0\"},\"deprecated\":false,\"description\":\"ECMAScript AST recursive visitor\",\"devDependencies\":{\"babel-cli\":\"^6.24.1\",\"babel-eslint\":\"^7.2.3\",\"babel-preset-es2015\":\"^6.24.1\",\"babel-register\":\"^6.24.1\",\"chai\":\"^4.0.2\",\"esprima\":\"^4.0.0\",\"gulp\":\"^3.9.0\",\"gulp-bump\":\"^2.7.0\",\"gulp-eslint\":\"^4.0.0\",\"gulp-filter\":\"^5.0.0\",\"gulp-git\":\"^2.4.1\",\"gulp-mocha\":\"^4.3.1\",\"gulp-tag-version\":\"^1.2.1\",\"jsdoc\":\"^3.3.0-alpha10\",\"minimist\":\"^1.1.0\"},\"engines\":{\"node\":\">=4.0\"},\"homepage\":\"https://github.com/estools/esrecurse\",\"license\":\"BSD-2-Clause\",\"main\":\"esrecurse.js\",\"maintainers\":[{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"https://github.com/Constellation\"}],\"name\":\"esrecurse\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/estools/esrecurse.git\"},\"scripts\":{\"lint\":\"gulp lint\",\"test\":\"gulp travis\",\"unit-test\":\"gulp test\"},\"version\":\"4.2.1\"}");
 
 /***/ }),
 /* 390 */
@@ -20177,7 +20177,7 @@ module.exports = PatternVisitor;
 /* 391 */
 /***/ (function(module) {
 
-module.exports = JSON.parse("{\"_from\":\"eslint-scope@^5.0.0\",\"_id\":\"eslint-scope@5.0.0\",\"_inBundle\":false,\"_integrity\":\"sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==\",\"_location\":\"/eslint-scope\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"eslint-scope@^5.0.0\",\"name\":\"eslint-scope\",\"escapedName\":\"eslint-scope\",\"rawSpec\":\"^5.0.0\",\"saveSpec\":null,\"fetchSpec\":\"^5.0.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz\",\"_shasum\":\"e87c8887c73e8d1ec84f1ca591645c358bfc8fb9\",\"_spec\":\"eslint-scope@^5.0.0\",\"_where\":\"/home/dcsapak/git/pve-eslint/eslint-v7.0.0-alpha.3\",\"bugs\":{\"url\":\"https://github.com/eslint/eslint-scope/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"esrecurse\":\"^4.1.0\",\"estraverse\":\"^4.1.1\"},\"deprecated\":false,\"description\":\"ECMAScript scope analyzer for ESLint\",\"devDependencies\":{\"@typescript-eslint/parser\":\"^1.11.0\",\"chai\":\"^4.2.0\",\"eslint\":\"^6.0.1\",\"eslint-config-eslint\":\"^5.0.1\",\"eslint-plugin-node\":\"^9.1.0\",\"eslint-release\":\"^1.0.0\",\"espree\":\"^6.0.0\",\"istanbul\":\"^0.4.5\",\"mocha\":\"^6.1.4\",\"npm-license\":\"^0.3.3\",\"shelljs\":\"^0.8.3\",\"typescript\":\"^3.5.2\"},\"engines\":{\"node\":\">=8.0.0\"},\"files\":[\"LICENSE\",\"README.md\",\"lib\"],\"homepage\":\"http://github.com/eslint/eslint-scope\",\"license\":\"BSD-2-Clause\",\"main\":\"lib/index.js\",\"name\":\"eslint-scope\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/eslint-scope.git\"},\"scripts\":{\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"node Makefile.js lint\",\"publish-release\":\"eslint-publish-release\",\"test\":\"node Makefile.js test\"},\"version\":\"5.0.0\"}");
+module.exports = JSON.parse("{\"_from\":\"eslint-scope@^5.0.0\",\"_id\":\"eslint-scope@5.0.0\",\"_inBundle\":false,\"_integrity\":\"sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==\",\"_location\":\"/eslint-scope\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"eslint-scope@^5.0.0\",\"name\":\"eslint-scope\",\"escapedName\":\"eslint-scope\",\"rawSpec\":\"^5.0.0\",\"saveSpec\":null,\"fetchSpec\":\"^5.0.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz\",\"_shasum\":\"e87c8887c73e8d1ec84f1ca591645c358bfc8fb9\",\"_spec\":\"eslint-scope@^5.0.0\",\"_where\":\"/home/dcsapak/git/pve-eslint/eslint-v7.0.0\",\"bugs\":{\"url\":\"https://github.com/eslint/eslint-scope/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"esrecurse\":\"^4.1.0\",\"estraverse\":\"^4.1.1\"},\"deprecated\":false,\"description\":\"ECMAScript scope analyzer for ESLint\",\"devDependencies\":{\"@typescript-eslint/parser\":\"^1.11.0\",\"chai\":\"^4.2.0\",\"eslint\":\"^6.0.1\",\"eslint-config-eslint\":\"^5.0.1\",\"eslint-plugin-node\":\"^9.1.0\",\"eslint-release\":\"^1.0.0\",\"espree\":\"^6.0.0\",\"istanbul\":\"^0.4.5\",\"mocha\":\"^6.1.4\",\"npm-license\":\"^0.3.3\",\"shelljs\":\"^0.8.3\",\"typescript\":\"^3.5.2\"},\"engines\":{\"node\":\">=8.0.0\"},\"files\":[\"LICENSE\",\"README.md\",\"lib\"],\"homepage\":\"http://github.com/eslint/eslint-scope\",\"license\":\"BSD-2-Clause\",\"main\":\"lib/index.js\",\"name\":\"eslint-scope\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/eslint-scope.git\"},\"scripts\":{\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"node Makefile.js lint\",\"publish-release\":\"eslint-publish-release\",\"test\":\"node Makefile.js test\"},\"version\":\"5.0.0\"}");
 
 /***/ }),
 /* 392 */
@@ -20481,8 +20481,8 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
   // code point above 128.
   // Generated by `bin/generate-identifier-regex.js`.
 
-  var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7c6\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab67\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
-  var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
+  var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08c7\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d04-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31bf\u31f0-\u31ff\u3400-\u4dbf\u4e00-\u9ffc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7ca\ua7f5-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab69\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
+  var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b55-\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d81-\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1abf\u1ac0\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua82c\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f";
   var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]");
   var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]");
   nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; // These are a run-length and offset encoded representation of the
@@ -20492,9 +20492,9 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
   // generated by bin/generate-identifier-regex.js
   // eslint-disable-next-line comma-spacing
 
-  var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 477, 28, 11, 0, 9, 21, 155, 22, 13, 52, 76, 44, 33, 24, 27, 35, 30, 0, 12, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 0, 33, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 230, 43, 117, 63, 32, 0, 161, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 35, 56, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 270, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 754, 9486, 286, 50, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 2357, 44, 11, 6, 17, 0, 370, 43, 1301, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42710, 42, 4148, 12, 221, 3, 5761, 15, 7472, 3104, 541]; // eslint-disable-next-line comma-spacing
+  var astralIdentifierStartCodes = [0, 11, 2, 25, 2, 18, 2, 1, 2, 14, 3, 13, 35, 122, 70, 52, 268, 28, 4, 48, 48, 31, 14, 29, 6, 37, 11, 29, 3, 35, 5, 7, 2, 4, 43, 157, 19, 35, 5, 35, 5, 39, 9, 51, 157, 310, 10, 21, 11, 7, 153, 5, 3, 0, 2, 43, 2, 1, 4, 0, 3, 22, 11, 22, 10, 30, 66, 18, 2, 1, 11, 21, 11, 25, 71, 55, 7, 1, 65, 0, 16, 3, 2, 2, 2, 28, 43, 28, 4, 28, 36, 7, 2, 27, 28, 53, 11, 21, 11, 18, 14, 17, 111, 72, 56, 50, 14, 50, 14, 35, 349, 41, 7, 1, 79, 28, 11, 0, 9, 21, 107, 20, 28, 22, 13, 52, 76, 44, 33, 24, 27, 35, 30, 0, 3, 0, 9, 34, 4, 0, 13, 47, 15, 3, 22, 0, 2, 0, 36, 17, 2, 24, 85, 6, 2, 0, 2, 3, 2, 14, 2, 9, 8, 46, 39, 7, 3, 1, 3, 21, 2, 6, 2, 1, 2, 4, 4, 0, 19, 0, 13, 4, 159, 52, 19, 3, 21, 2, 31, 47, 21, 1, 2, 0, 185, 46, 42, 3, 37, 47, 21, 0, 60, 42, 14, 0, 72, 26, 230, 43, 117, 63, 32, 7, 3, 0, 3, 7, 2, 1, 2, 23, 16, 0, 2, 0, 95, 7, 3, 38, 17, 0, 2, 0, 29, 0, 11, 39, 8, 0, 22, 0, 12, 45, 20, 0, 35, 56, 264, 8, 2, 36, 18, 0, 50, 29, 113, 6, 2, 1, 2, 37, 22, 0, 26, 5, 2, 1, 2, 31, 15, 0, 328, 18, 190, 0, 80, 921, 103, 110, 18, 195, 2749, 1070, 4050, 582, 8634, 568, 8, 30, 114, 29, 19, 47, 17, 3, 32, 20, 6, 18, 689, 63, 129, 74, 6, 0, 67, 12, 65, 1, 2, 0, 29, 6135, 9, 1237, 43, 8, 8952, 286, 50, 2, 18, 3, 9, 395, 2309, 106, 6, 12, 4, 8, 8, 9, 5991, 84, 2, 70, 2, 1, 3, 0, 3, 1, 3, 3, 2, 11, 2, 0, 2, 6, 2, 64, 2, 3, 3, 7, 2, 6, 2, 27, 2, 3, 2, 4, 2, 0, 4, 6, 2, 339, 3, 24, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 30, 2, 24, 2, 7, 2357, 44, 11, 6, 17, 0, 370, 43, 1301, 196, 60, 67, 8, 0, 1205, 3, 2, 26, 2, 1, 2, 0, 3, 0, 2, 9, 2, 3, 2, 0, 2, 0, 7, 0, 5, 0, 2, 0, 2, 0, 2, 2, 2, 1, 2, 0, 3, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, 3, 3, 2, 6, 2, 3, 2, 3, 2, 0, 2, 9, 2, 16, 6, 2, 2, 4, 2, 16, 4421, 42717, 35, 4148, 12, 221, 3, 5761, 15, 7472, 3104, 541, 1507, 4938]; // eslint-disable-next-line comma-spacing
 
-  var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 525, 10, 176, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 4, 9, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 232, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 135, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 19723, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 419, 13, 1495, 6, 110, 6, 6, 9, 792487, 239]; // This has a complexity linear to the value of the code. The
+  var astralIdentifierCodes = [509, 0, 227, 0, 150, 4, 294, 9, 1368, 2, 2, 1, 6, 3, 41, 2, 5, 0, 166, 1, 574, 3, 9, 9, 370, 1, 154, 10, 176, 2, 54, 14, 32, 9, 16, 3, 46, 10, 54, 9, 7, 2, 37, 13, 2, 9, 6, 1, 45, 0, 13, 2, 49, 13, 9, 3, 2, 11, 83, 11, 7, 0, 161, 11, 6, 9, 7, 3, 56, 1, 2, 6, 3, 1, 3, 2, 10, 0, 11, 1, 3, 6, 4, 4, 193, 17, 10, 9, 5, 0, 82, 19, 13, 9, 214, 6, 3, 8, 28, 1, 83, 16, 16, 9, 82, 12, 9, 9, 84, 14, 5, 9, 243, 14, 166, 9, 71, 5, 2, 1, 3, 3, 2, 0, 2, 1, 13, 9, 120, 6, 3, 6, 4, 0, 29, 9, 41, 6, 2, 3, 9, 0, 10, 10, 47, 15, 406, 7, 2, 7, 17, 9, 57, 21, 2, 13, 123, 5, 4, 0, 2, 1, 2, 6, 2, 0, 9, 9, 49, 4, 2, 1, 2, 4, 9, 9, 330, 3, 19306, 9, 135, 4, 60, 6, 26, 9, 1014, 0, 2, 54, 8, 3, 82, 0, 12, 1, 19628, 1, 5319, 4, 4, 5, 9, 7, 3, 6, 31, 3, 149, 2, 1418, 49, 513, 54, 5, 49, 9, 0, 15, 0, 23, 4, 2, 14, 1361, 6, 2, 16, 3, 6, 2, 1, 2, 4, 262, 6, 10, 9, 419, 13, 1495, 6, 110, 6, 6, 9, 4759, 9, 787719, 239]; // This has a complexity linear to the value of the code. The
   // assumption is that looking up astral identifier characters is
   // rare.
 
@@ -20724,6 +20724,7 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     starstar: new TokenType("**", {
       beforeExpr: true
     }),
+    coalesce: binop("??", 1),
     // Keyword token types.
     _break: kw("break"),
     _case: kw("case", beforeExpr),
@@ -21202,7 +21203,11 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
       }
 
       if ((match[1] || match[2]) === "use strict") {
-        return true;
+        skipWhiteSpace.lastIndex = start + match[0].length;
+        var spaceAfter = skipWhiteSpace.exec(this.input),
+            end = spaceAfter.index + spaceAfter[0].length;
+        var next = this.input.charAt(end);
+        return next === ";" || next === "}" || lineBreak.test(spaceAfter[0]) && !(/[(`.[+\-/*%<>=,?^&]/.test(next) || next === "!" && this.input.charAt(end + 1) === "=");
       }
 
       start += match[0].length; // Skip semicolon, if any.
@@ -21547,7 +21552,7 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
           var next = this.pos + skip[0].length,
               nextCh = this.input.charCodeAt(next);
 
-          if (nextCh === 40) // '('
+          if (nextCh === 40 || nextCh === 46) // '(' or '.'
             {
               return this.parseExpressionStatement(node, this.parseExpression());
             }
@@ -21951,7 +21956,7 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
   // function bodies).
 
 
-  pp$1.parseBlock = function (createNewLexicalScope, node) {
+  pp$1.parseBlock = function (createNewLexicalScope, node, exitStrict) {
     if (createNewLexicalScope === void 0) createNewLexicalScope = true;
     if (node === void 0) node = this.startNode();
     node.body = [];
@@ -21961,11 +21966,17 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
       this.enterScope(0);
     }
 
-    while (!this.eat(types.braceR)) {
+    while (this.type !== types.braceR) {
       var stmt = this.parseStatement(null);
       node.body.push(stmt);
     }
 
+    if (exitStrict) {
+      this.strict = false;
+    }
+
+    this.next();
+
     if (createNewLexicalScope) {
       this.exitScope();
     }
@@ -22118,7 +22129,7 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     classBody.body = [];
     this.expect(types.braceL);
 
-    while (!this.eat(types.braceR)) {
+    while (this.type !== types.braceR) {
       var element = this.parseClassElement(node.superClass !== null);
 
       if (element) {
@@ -22134,8 +22145,9 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
       }
     }
 
-    node.body = this.finishNode(classBody, "ClassBody");
     this.strict = oldStrict;
+    this.next();
+    node.body = this.finishNode(classBody, "ClassBody");
     return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression");
   };
 
@@ -22261,6 +22273,15 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     this.next(); // export * from '...'
 
     if (this.eat(types.star)) {
+      if (this.options.ecmaVersion >= 11) {
+        if (this.eatContextual("as")) {
+          node.exported = this.parseIdent(true);
+          this.checkExport(exports, node.exported.name, this.lastTokStart);
+        } else {
+          node.exported = null;
+        }
+      }
+
       this.expectContextual("from");
 
       if (this.type !== types.string) {
@@ -23034,12 +23055,25 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     if (prec != null && (!noIn || this.type !== types._in)) {
       if (prec > minPrec) {
         var logical = this.type === types.logicalOR || this.type === types.logicalAND;
+        var coalesce = this.type === types.coalesce;
+
+        if (coalesce) {
+          // Handle the precedence of `tt.coalesce` as equal to the range of logical expressions.
+          // In other words, `node.right` shouldn't contain logical expressions in order to check the mixed error.
+          prec = types.logicalAND.binop;
+        }
+
         var op = this.value;
         this.next();
         var startPos = this.start,
             startLoc = this.startLoc;
         var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn);
-        var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical);
+        var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical || coalesce);
+
+        if (logical && this.type === types.coalesce || coalesce && (this.type === types.logicalOR || this.type === types.logicalAND)) {
+          this.raiseRecoverable(this.start, "Logical expressions and coalesce expressions cannot be mixed. Wrap either by parentheses");
+        }
+
         return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn);
       }
     }
@@ -23133,7 +23167,7 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
   };
 
   pp$3.parseSubscripts = function (base, startPos, startLoc, noCalls) {
-    var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && this.lastTokEnd === base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async";
+    var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && this.lastTokEnd === base.end && !this.canInsertSemicolon() && base.end - base.start === 5 && this.potentialArrowAt === base.start;
 
     while (true) {
       var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow);
@@ -23350,13 +23384,23 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
   };
 
   pp$3.parseExprImport = function () {
-    var node = this.startNode();
-    this.next(); // skip `import`
+    var node = this.startNode(); // Consume `import` as an identifier for `import.meta`.
+    // Because `this.parseIdent(true)` doesn't check escape sequences, it needs the check of `this.containsEsc`.
+
+    if (this.containsEsc) {
+      this.raiseRecoverable(this.start, "Escape sequence in keyword import");
+    }
+
+    var meta = this.parseIdent(true);
 
     switch (this.type) {
       case types.parenL:
         return this.parseDynamicImport(node);
 
+      case types.dot:
+        node.meta = meta;
+        return this.parseImportMeta(node);
+
       default:
         this.unexpected();
     }
@@ -23381,6 +23425,27 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     return this.finishNode(node, "ImportExpression");
   };
 
+  pp$3.parseImportMeta = function (node) {
+    this.next(); // skip `.`
+
+    var containsEsc = this.containsEsc;
+    node.property = this.parseIdent(true);
+
+    if (node.property.name !== "meta") {
+      this.raiseRecoverable(node.property.start, "The only valid meta property for import is 'import.meta'");
+    }
+
+    if (containsEsc) {
+      this.raiseRecoverable(node.start, "'import.meta' must not contain escaped characters");
+    }
+
+    if (this.options.sourceType !== "module") {
+      this.raiseRecoverable(node.start, "Cannot use 'import.meta' outside a module");
+    }
+
+    return this.finishNode(node, "MetaProperty");
+  };
+
   pp$3.parseLiteral = function (value) {
     var node = this.startNode();
     node.value = value;
@@ -23513,12 +23578,16 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
       var containsEsc = this.containsEsc;
       node.property = this.parseIdent(true);
 
-      if (node.property.name !== "target" || containsEsc) {
-        this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target");
+      if (node.property.name !== "target") {
+        this.raiseRecoverable(node.property.start, "The only valid meta property for new is 'new.target'");
+      }
+
+      if (containsEsc) {
+        this.raiseRecoverable(node.start, "'new.target' must not contain escaped characters");
       }
 
       if (!this.inNonArrowFunction()) {
-        this.raiseRecoverable(node.start, "new.target can only be used in functions");
+        this.raiseRecoverable(node.start, "'new.target' can only be used in functions");
       }
 
       return this.finishNode(node, "MetaProperty");
@@ -23886,20 +23955,19 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
       // if a let/const declaration in the function clashes with one of the params.
 
 
-      this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params));
-      node.body = this.parseBlock(false);
+      this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)); // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
+
+      if (this.strict && node.id) {
+        this.checkLVal(node.id, BIND_OUTSIDE);
+      }
+
+      node.body = this.parseBlock(false, undefined, useStrict && !oldStrict);
       node.expression = false;
       this.adaptDirectivePrologue(node.body.body);
       this.labels = oldLabels;
     }
 
-    this.exitScope(); // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval'
-
-    if (this.strict && node.id) {
-      this.checkLVal(node.id, BIND_OUTSIDE);
-    }
-
-    this.strict = oldStrict;
+    this.exitScope();
   };
 
   pp$3.isSimpleParamList = function (params) {
@@ -24497,7 +24565,8 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
   // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair).
 
 
-  RegExpValidationState.prototype.at = function at(i) {
+  RegExpValidationState.prototype.at = function at(i, forceU) {
+    if (forceU === void 0) forceU = false;
     var s = this.source;
     var l = s.length;
 
@@ -24507,7 +24576,7 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
 
     var c = s.charCodeAt(i);
 
-    if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
+    if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) {
       return c;
     }
 
@@ -24515,7 +24584,8 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     return next >= 0xDC00 && next <= 0xDFFF ? (c << 10) + next - 0x35FDC00 : c;
   };
 
-  RegExpValidationState.prototype.nextIndex = function nextIndex(i) {
+  RegExpValidationState.prototype.nextIndex = function nextIndex(i, forceU) {
+    if (forceU === void 0) forceU = false;
     var s = this.source;
     var l = s.length;
 
@@ -24526,28 +24596,33 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     var c = s.charCodeAt(i),
         next;
 
-    if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) {
+    if (!(forceU || this.switchU) || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l || (next = s.charCodeAt(i + 1)) < 0xDC00 || next > 0xDFFF) {
       return i + 1;
     }
 
     return i + 2;
   };
 
-  RegExpValidationState.prototype.current = function current() {
-    return this.at(this.pos);
+  RegExpValidationState.prototype.current = function current(forceU) {
+    if (forceU === void 0) forceU = false;
+    return this.at(this.pos, forceU);
   };
 
-  RegExpValidationState.prototype.lookahead = function lookahead() {
-    return this.at(this.nextIndex(this.pos));
+  RegExpValidationState.prototype.lookahead = function lookahead(forceU) {
+    if (forceU === void 0) forceU = false;
+    return this.at(this.nextIndex(this.pos, forceU), forceU);
   };
 
-  RegExpValidationState.prototype.advance = function advance() {
-    this.pos = this.nextIndex(this.pos);
+  RegExpValidationState.prototype.advance = function advance(forceU) {
+    if (forceU === void 0) forceU = false;
+    this.pos = this.nextIndex(this.pos, forceU);
   };
 
-  RegExpValidationState.prototype.eat = function eat(ch) {
-    if (this.current() === ch) {
-      this.advance();
+  RegExpValidationState.prototype.eat = function eat(ch, forceU) {
+    if (forceU === void 0) forceU = false;
+
+    if (this.current(forceU) === ch) {
+      this.advance(forceU);
       return true;
     }
 
@@ -24997,9 +25072,9 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
       }
 
     return false;
-  }; // GroupSpecifier[U] ::
+  }; // GroupSpecifier ::
   //   [empty]
-  //   `?` GroupName[?U]
+  //   `?` GroupName
 
 
   pp$8.regexp_groupSpecifier = function (state) {
@@ -25017,8 +25092,8 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
 
       state.raise("Invalid group");
     }
-  }; // GroupName[U] ::
-  //   `<` RegExpIdentifierName[?U] `>`
+  }; // GroupName ::
+  //   `<` RegExpIdentifierName `>`
   // Note: this updates `state.lastStringValue` property with the eaten name.
 
 
@@ -25038,9 +25113,9 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     }
 
     return false;
-  }; // RegExpIdentifierName[U] ::
-  //   RegExpIdentifierStart[?U]
-  //   RegExpIdentifierName[?U] RegExpIdentifierPart[?U]
+  }; // RegExpIdentifierName ::
+  //   RegExpIdentifierStart
+  //   RegExpIdentifierName RegExpIdentifierPart
   // Note: this updates `state.lastStringValue` property with the eaten name.
 
 
@@ -25058,21 +25133,22 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     }
 
     return false;
-  }; // RegExpIdentifierStart[U] ::
+  }; // RegExpIdentifierStart ::
   //   UnicodeIDStart
   //   `$`
   //   `_`
-  //   `\` RegExpUnicodeEscapeSequence[?U]
+  //   `\` RegExpUnicodeEscapeSequence[+U]
 
 
   pp$8.regexp_eatRegExpIdentifierStart = function (state) {
     var start = state.pos;
-    var ch = state.current();
-    state.advance();
+    var forceU = this.options.ecmaVersion >= 11;
+    var ch = state.current(forceU);
+    state.advance(forceU);
 
     if (ch === 0x5C
     /* \ */
-    && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
+    && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
       ch = state.lastIntValue;
     }
 
@@ -25090,23 +25166,24 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     /* $ */
     || ch === 0x5F;
     /* _ */
-  } // RegExpIdentifierPart[U] ::
+  } // RegExpIdentifierPart ::
   //   UnicodeIDContinue
   //   `$`
   //   `_`
-  //   `\` RegExpUnicodeEscapeSequence[?U]
+  //   `\` RegExpUnicodeEscapeSequence[+U]
   //   <ZWNJ>
   //   <ZWJ>
 
 
   pp$8.regexp_eatRegExpIdentifierPart = function (state) {
     var start = state.pos;
-    var ch = state.current();
-    state.advance();
+    var forceU = this.options.ecmaVersion >= 11;
+    var ch = state.current(forceU);
+    state.advance(forceU);
 
     if (ch === 0x5C
     /* \ */
-    && this.regexp_eatRegExpUnicodeEscapeSequence(state)) {
+    && this.regexp_eatRegExpUnicodeEscapeSequence(state, forceU)) {
       ch = state.lastIntValue;
     }
 
@@ -25192,7 +25269,7 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
 
 
   pp$8.regexp_eatCharacterEscape = function (state) {
-    return this.regexp_eatControlEscape(state) || this.regexp_eatCControlLetter(state) || this.regexp_eatZero(state) || this.regexp_eatHexEscapeSequence(state) || this.regexp_eatRegExpUnicodeEscapeSequence(state) || !state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state) || this.regexp_eatIdentityEscape(state);
+    return this.regexp_eatControlEscape(state) || this.regexp_eatCControlLetter(state) || this.regexp_eatZero(state) || this.regexp_eatHexEscapeSequence(state) || this.regexp_eatRegExpUnicodeEscapeSequence(state, false) || !state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state) || this.regexp_eatIdentityEscape(state);
   };
 
   pp$8.regexp_eatCControlLetter = function (state) {
@@ -25306,8 +25383,10 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
   } // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence
 
 
-  pp$8.regexp_eatRegExpUnicodeEscapeSequence = function (state) {
+  pp$8.regexp_eatRegExpUnicodeEscapeSequence = function (state, forceU) {
+    if (forceU === void 0) forceU = false;
     var start = state.pos;
+    var switchU = forceU || state.switchU;
 
     if (state.eat(0x75
     /* u */
@@ -25315,7 +25394,7 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
       if (this.regexp_eatFixedHexDigits(state, 4)) {
         var lead = state.lastIntValue;
 
-        if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) {
+        if (switchU && lead >= 0xD800 && lead <= 0xDBFF) {
           var leadSurrogateEnd = state.pos;
 
           if (state.eat(0x5C
@@ -25338,7 +25417,7 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
         return true;
       }
 
-      if (state.switchU && state.eat(0x7B
+      if (switchU && state.eat(0x7B
       /* { */
       ) && this.regexp_eatHexDigits(state) && state.eat(0x7D
       /* } */
@@ -25346,7 +25425,7 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
         return true;
       }
 
-      if (state.switchU) {
+      if (switchU) {
         state.raise("Invalid unicode escape");
       }
 
@@ -26247,6 +26326,19 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
     return this.finishOp(code === 61 ? types.eq : types.prefix, 1);
   };
 
+  pp$9.readToken_question = function () {
+    // '?'
+    if (this.options.ecmaVersion >= 11) {
+      var next = this.input.charCodeAt(this.pos + 1);
+
+      if (next === 63) {
+        return this.finishOp(types.coalesce, 2);
+      }
+    }
+
+    return this.finishOp(types.question, 1);
+  };
+
   pp$9.getTokenFromCode = function (code) {
     switch (code) {
       // The interpretation of a dot depends on whether it is followed
@@ -26292,10 +26384,6 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
         ++this.pos;
         return this.finishToken(types.colon);
 
-      case 63:
-        ++this.pos;
-        return this.finishToken(types.question);
-
       case 96:
         // '`'
         if (this.options.ecmaVersion < 6) {
@@ -26384,6 +26472,10 @@ exports.supportedEcmaVersions = getSupportedEcmaVersions();
         // '=!'
         return this.readToken_eq_excl(code);
 
+      case 63:
+        // '?'
+        return this.readToken_question();
+
       case 126:
         // '~'
         return this.finishOp(types.prefix, 1);
@@ -28500,7 +28592,7 @@ module.exports = {
 /* 402 */
 /***/ (function(module) {
 
-module.exports = JSON.parse("{\"_from\":\"espree@^6.2.1\",\"_id\":\"espree@6.2.1\",\"_inBundle\":false,\"_integrity\":\"sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==\",\"_location\":\"/espree\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"espree@^6.2.1\",\"name\":\"espree\",\"escapedName\":\"espree\",\"rawSpec\":\"^6.2.1\",\"saveSpec\":null,\"fetchSpec\":\"^6.2.1\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/espree/-/espree-6.2.1.tgz\",\"_shasum\":\"77fc72e1fd744a2052c20f38a5b575832e82734a\",\"_spec\":\"espree@^6.2.1\",\"_where\":\"/home/dcsapak/git/pve-eslint/eslint-v7.0.0-alpha.3\",\"author\":{\"name\":\"Nicholas C. Zakas\",\"email\":\"nicholas+npm@nczconsulting.com\"},\"bugs\":{\"url\":\"http://github.com/eslint/espree.git\"},\"bundleDependencies\":false,\"dependencies\":{\"acorn\":\"^7.1.1\",\"acorn-jsx\":\"^5.2.0\",\"eslint-visitor-keys\":\"^1.1.0\"},\"deprecated\":false,\"description\":\"An Esprima-compatible JavaScript parser built on Acorn\",\"devDependencies\":{\"browserify\":\"^16.5.0\",\"chai\":\"^4.2.0\",\"eslint\":\"^6.0.1\",\"eslint-config-eslint\":\"^5.0.1\",\"eslint-plugin-node\":\"^9.1.0\",\"eslint-release\":\"^1.0.0\",\"esprima\":\"latest\",\"esprima-fb\":\"^8001.2001.0-dev-harmony-fb\",\"json-diff\":\"^0.5.4\",\"leche\":\"^2.3.0\",\"mocha\":\"^6.2.0\",\"nyc\":\"^14.1.1\",\"regenerate\":\"^1.4.0\",\"shelljs\":\"^0.3.0\",\"shelljs-nodecli\":\"^0.1.1\",\"unicode-6.3.0\":\"^0.7.5\"},\"engines\":{\"node\":\">=6.0.0\"},\"files\":[\"lib\",\"espree.js\"],\"homepage\":\"https://github.com/eslint/espree\",\"keywords\":[\"ast\",\"ecmascript\",\"javascript\",\"parser\",\"syntax\",\"acorn\"],\"license\":\"BSD-2-Clause\",\"main\":\"espree.js\",\"name\":\"espree\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/espree.git\"},\"scripts\":{\"browserify\":\"node Makefile.js browserify\",\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-regex\":\"node tools/generate-identifier-regex.js\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"node Makefile.js lint\",\"publish-release\":\"eslint-publish-release\",\"test\":\"npm run-script lint && node Makefile.js test\"},\"version\":\"6.2.1\"}");
+module.exports = JSON.parse("{\"_from\":\"espree@^7.0.0\",\"_id\":\"espree@7.0.0\",\"_inBundle\":false,\"_integrity\":\"sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw==\",\"_location\":\"/espree\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"espree@^7.0.0\",\"name\":\"espree\",\"escapedName\":\"espree\",\"rawSpec\":\"^7.0.0\",\"saveSpec\":null,\"fetchSpec\":\"^7.0.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/espree/-/espree-7.0.0.tgz\",\"_shasum\":\"8a7a60f218e69f120a842dc24c5a88aa7748a74e\",\"_spec\":\"espree@^7.0.0\",\"_where\":\"/home/dcsapak/git/pve-eslint/eslint-v7.0.0\",\"author\":{\"name\":\"Nicholas C. Zakas\",\"email\":\"nicholas+npm@nczconsulting.com\"},\"bugs\":{\"url\":\"http://github.com/eslint/espree.git\"},\"bundleDependencies\":false,\"dependencies\":{\"acorn\":\"^7.1.1\",\"acorn-jsx\":\"^5.2.0\",\"eslint-visitor-keys\":\"^1.1.0\"},\"deprecated\":false,\"description\":\"An Esprima-compatible JavaScript parser built on Acorn\",\"devDependencies\":{\"browserify\":\"^16.5.0\",\"chai\":\"^4.2.0\",\"eslint\":\"^6.0.1\",\"eslint-config-eslint\":\"^5.0.1\",\"eslint-plugin-node\":\"^9.1.0\",\"eslint-release\":\"^1.0.0\",\"esprima\":\"latest\",\"esprima-fb\":\"^8001.2001.0-dev-harmony-fb\",\"json-diff\":\"^0.5.4\",\"leche\":\"^2.3.0\",\"mocha\":\"^6.2.0\",\"nyc\":\"^14.1.1\",\"regenerate\":\"^1.4.0\",\"shelljs\":\"^0.3.0\",\"shelljs-nodecli\":\"^0.1.1\",\"unicode-6.3.0\":\"^0.7.5\"},\"engines\":{\"node\":\"^10.12.0 || >=12.0.0\"},\"files\":[\"lib\",\"espree.js\"],\"homepage\":\"https://github.com/eslint/espree\",\"keywords\":[\"ast\",\"ecmascript\",\"javascript\",\"parser\",\"syntax\",\"acorn\"],\"license\":\"BSD-2-Clause\",\"main\":\"espree.js\",\"name\":\"espree\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/espree.git\"},\"scripts\":{\"browserify\":\"node Makefile.js browserify\",\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-regex\":\"node tools/generate-identifier-regex.js\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"node Makefile.js lint\",\"publish-release\":\"eslint-publish-release\",\"sync-docs\":\"node Makefile.js docs\",\"test\":\"npm run-script lint && node Makefile.js test\"},\"version\":\"7.0.0\"}");
 
 /***/ }),
 /* 403 */
@@ -45720,13 +45812,13 @@ module.exports = new Map(Object.entries({
     }
   },
   es2017: {
-    globals: _objectSpread({}, newGlobals2015, {}, newGlobals2017),
+    globals: _objectSpread(_objectSpread({}, newGlobals2015), newGlobals2017),
     parserOptions: {
       ecmaVersion: 8
     }
   },
   es2020: {
-    globals: _objectSpread({}, newGlobals2015, {}, newGlobals2017, {}, newGlobals2020),
+    globals: _objectSpread(_objectSpread(_objectSpread({}, newGlobals2015), newGlobals2017), newGlobals2020),
     parserOptions: {
       ecmaVersion: 11
     }
@@ -45836,7 +45928,7 @@ module.exports = JSON.parse("{\"builtin\":{\"Array\":false,\"ArrayBuffer\":false
 /* 408 */
 /***/ (function(module) {
 
-module.exports = JSON.parse("{\"name\":\"eslint\",\"version\":\"7.0.0-alpha.3\",\"author\":\"Nicholas C. Zakas <nicholas+npm@nczconsulting.com>\",\"description\":\"An AST-based pattern checker for JavaScript.\",\"bin\":{\"eslint\":\"./bin/eslint.js\"},\"main\":\"./lib/api.js\",\"scripts\":{\"test\":\"node Makefile.js test\",\"test:cli\":\"mocha\",\"lint\":\"node Makefile.js lint\",\"fix\":\"node Makefile.js lint -- fix\",\"fuzz\":\"node Makefile.js fuzz\",\"generate-release\":\"node Makefile.js generateRelease\",\"generate-alpharelease\":\"node Makefile.js generatePrerelease -- alpha\",\"generate-betarelease\":\"node Makefile.js generatePrerelease -- beta\",\"generate-rcrelease\":\"node Makefile.js generatePrerelease -- rc\",\"publish-release\":\"node Makefile.js publishRelease\",\"docs\":\"node Makefile.js docs\",\"gensite\":\"node Makefile.js gensite\",\"webpack\":\"node Makefile.js webpack\",\"perf\":\"node Makefile.js perf\"},\"gitHooks\":{\"pre-commit\":\"lint-staged\"},\"lint-staged\":{\"*.js\":[\"eslint --fix\",\"git add\"],\"*.md\":\"markdownlint\"},\"files\":[\"LICENSE\",\"README.md\",\"bin\",\"conf\",\"lib\",\"messages\"],\"repository\":\"eslint/eslint\",\"funding\":\"https://opencollective.com/eslint\",\"homepage\":\"https://eslint.org\",\"bugs\":\"https://github.com/eslint/eslint/issues/\",\"dependencies\":{\"@babel/code-frame\":\"^7.0.0\",\"ajv\":\"^6.10.0\",\"chalk\":\"^3.0.0\",\"cross-spawn\":\"^7.0.1\",\"debug\":\"^4.0.1\",\"doctrine\":\"^3.0.0\",\"eslint-scope\":\"^5.0.0\",\"eslint-utils\":\"^2.0.0\",\"eslint-visitor-keys\":\"^1.1.0\",\"espree\":\"^6.2.1\",\"esquery\":\"^1.2.0\",\"esutils\":\"^2.0.2\",\"file-entry-cache\":\"^5.0.1\",\"functional-red-black-tree\":\"^1.0.1\",\"glob-parent\":\"^5.0.0\",\"globals\":\"^12.1.0\",\"ignore\":\"^4.0.6\",\"import-fresh\":\"^3.0.0\",\"imurmurhash\":\"^0.1.4\",\"inquirer\":\"^7.0.0\",\"is-glob\":\"^4.0.0\",\"js-yaml\":\"^3.13.1\",\"json-stable-stringify-without-jsonify\":\"^1.0.1\",\"levn\":\"^0.3.0\",\"lodash\":\"^4.17.14\",\"minimatch\":\"^3.0.4\",\"natural-compare\":\"^1.4.0\",\"optionator\":\"^0.8.3\",\"progress\":\"^2.0.0\",\"regexpp\":\"^3.0.0\",\"semver\":\"^7.1.1\",\"strip-ansi\":\"^6.0.0\",\"strip-json-comments\":\"^3.0.1\",\"table\":\"^5.2.3\",\"text-table\":\"^0.2.0\",\"v8-compile-cache\":\"^2.0.3\"},\"devDependencies\":{\"@babel/core\":\"^7.4.3\",\"@babel/preset-env\":\"^7.4.3\",\"acorn\":\"^7.1.1\",\"babel-loader\":\"^8.0.5\",\"chai\":\"^4.0.1\",\"cheerio\":\"^0.22.0\",\"common-tags\":\"^1.8.0\",\"core-js\":\"^3.1.3\",\"dateformat\":\"^3.0.3\",\"ejs\":\"^2.6.1\",\"eslint\":\"file:.\",\"eslint-config-eslint\":\"file:packages/eslint-config-eslint\",\"eslint-plugin-eslint-plugin\":\"^2.2.1\",\"eslint-plugin-internal-rules\":\"file:tools/internal-rules\",\"eslint-plugin-jsdoc\":\"^15.9.5\",\"eslint-plugin-node\":\"^9.0.0\",\"eslint-release\":\"^1.2.0\",\"eslump\":\"^2.0.0\",\"esprima\":\"^4.0.1\",\"glob\":\"^7.1.3\",\"jsdoc\":\"^3.5.5\",\"karma\":\"^4.0.1\",\"karma-chrome-launcher\":\"^2.2.0\",\"karma-mocha\":\"^1.3.0\",\"karma-mocha-reporter\":\"^2.2.3\",\"karma-webpack\":\"^4.0.0-rc.6\",\"leche\":\"^2.2.3\",\"lint-staged\":\"^8.1.5\",\"load-perf\":\"^0.2.0\",\"markdownlint\":\"^0.15.0\",\"markdownlint-cli\":\"^0.17.0\",\"memfs\":\"^3.0.1\",\"mocha\":\"^6.1.2\",\"mocha-junit-reporter\":\"^1.23.0\",\"npm-license\":\"^0.3.3\",\"nyc\":\"^14.1.1\",\"proxyquire\":\"^2.0.1\",\"puppeteer\":\"^1.18.0\",\"recast\":\"^0.18.1\",\"regenerator-runtime\":\"^0.13.2\",\"shelljs\":\"^0.8.2\",\"sinon\":\"^7.3.2\",\"temp\":\"^0.9.0\",\"webpack\":\"^4.35.0\",\"webpack-cli\":\"^3.3.5\",\"yorkie\":\"^2.0.0\"},\"keywords\":[\"ast\",\"lint\",\"javascript\",\"ecmascript\",\"espree\"],\"license\":\"MIT\",\"engines\":{\"node\":\"^10.12.0 || >=12.0.0\"}}");
+module.exports = JSON.parse("{\"name\":\"eslint\",\"version\":\"7.0.0\",\"author\":\"Nicholas C. Zakas <nicholas+npm@nczconsulting.com>\",\"description\":\"An AST-based pattern checker for JavaScript.\",\"bin\":{\"eslint\":\"./bin/eslint.js\"},\"main\":\"./lib/api.js\",\"scripts\":{\"test\":\"node Makefile.js test\",\"test:cli\":\"mocha\",\"lint\":\"node Makefile.js lint\",\"fix\":\"node Makefile.js lint -- fix\",\"fuzz\":\"node Makefile.js fuzz\",\"generate-release\":\"node Makefile.js generateRelease\",\"generate-alpharelease\":\"node Makefile.js generatePrerelease -- alpha\",\"generate-betarelease\":\"node Makefile.js generatePrerelease -- beta\",\"generate-rcrelease\":\"node Makefile.js generatePrerelease -- rc\",\"publish-release\":\"node Makefile.js publishRelease\",\"docs\":\"node Makefile.js docs\",\"gensite\":\"node Makefile.js gensite\",\"webpack\":\"node Makefile.js webpack\",\"perf\":\"node Makefile.js perf\"},\"gitHooks\":{\"pre-commit\":\"lint-staged\"},\"lint-staged\":{\"*.js\":[\"eslint --fix\",\"git add\"],\"*.md\":\"markdownlint\"},\"files\":[\"LICENSE\",\"README.md\",\"bin\",\"conf\",\"lib\",\"messages\"],\"repository\":\"eslint/eslint\",\"funding\":\"https://opencollective.com/eslint\",\"homepage\":\"https://eslint.org\",\"bugs\":\"https://github.com/eslint/eslint/issues/\",\"dependencies\":{\"@babel/code-frame\":\"^7.0.0\",\"ajv\":\"^6.10.0\",\"chalk\":\"^4.0.0\",\"cross-spawn\":\"^7.0.2\",\"debug\":\"^4.0.1\",\"doctrine\":\"^3.0.0\",\"eslint-scope\":\"^5.0.0\",\"eslint-utils\":\"^2.0.0\",\"eslint-visitor-keys\":\"^1.1.0\",\"espree\":\"^7.0.0\",\"esquery\":\"^1.2.0\",\"esutils\":\"^2.0.2\",\"file-entry-cache\":\"^5.0.1\",\"functional-red-black-tree\":\"^1.0.1\",\"glob-parent\":\"^5.0.0\",\"globals\":\"^12.1.0\",\"ignore\":\"^4.0.6\",\"import-fresh\":\"^3.0.0\",\"imurmurhash\":\"^0.1.4\",\"inquirer\":\"^7.0.0\",\"is-glob\":\"^4.0.0\",\"js-yaml\":\"^3.13.1\",\"json-stable-stringify-without-jsonify\":\"^1.0.1\",\"levn\":\"^0.4.1\",\"lodash\":\"^4.17.14\",\"minimatch\":\"^3.0.4\",\"natural-compare\":\"^1.4.0\",\"optionator\":\"^0.9.1\",\"progress\":\"^2.0.0\",\"regexpp\":\"^3.1.0\",\"semver\":\"^7.2.1\",\"strip-ansi\":\"^6.0.0\",\"strip-json-comments\":\"^3.1.0\",\"table\":\"^5.2.3\",\"text-table\":\"^0.2.0\",\"v8-compile-cache\":\"^2.0.3\"},\"devDependencies\":{\"@babel/core\":\"^7.4.3\",\"@babel/preset-env\":\"^7.4.3\",\"acorn\":\"^7.1.1\",\"babel-loader\":\"^8.0.5\",\"chai\":\"^4.0.1\",\"cheerio\":\"^0.22.0\",\"common-tags\":\"^1.8.0\",\"core-js\":\"^3.1.3\",\"dateformat\":\"^3.0.3\",\"ejs\":\"^3.0.2\",\"escape-string-regexp\":\"^3.0.0\",\"eslint\":\"file:.\",\"eslint-config-eslint\":\"file:packages/eslint-config-eslint\",\"eslint-plugin-eslint-plugin\":\"^2.2.1\",\"eslint-plugin-internal-rules\":\"file:tools/internal-rules\",\"eslint-plugin-jsdoc\":\"^22.1.0\",\"eslint-plugin-node\":\"^11.1.0\",\"eslint-release\":\"^2.0.0\",\"eslump\":\"^2.0.0\",\"esprima\":\"^4.0.1\",\"glob\":\"^7.1.6\",\"jsdoc\":\"^3.5.5\",\"karma\":\"^4.0.1\",\"karma-chrome-launcher\":\"^3.1.0\",\"karma-mocha\":\"^1.3.0\",\"karma-mocha-reporter\":\"^2.2.3\",\"karma-webpack\":\"^4.0.0-rc.6\",\"leche\":\"^2.2.3\",\"lint-staged\":\"^10.1.2\",\"load-perf\":\"^0.2.0\",\"markdownlint\":\"^0.19.0\",\"markdownlint-cli\":\"^0.22.0\",\"memfs\":\"^3.0.1\",\"mocha\":\"^7.1.1\",\"mocha-junit-reporter\":\"^1.23.0\",\"npm-license\":\"^0.3.3\",\"nyc\":\"^15.0.1\",\"proxyquire\":\"^2.0.1\",\"puppeteer\":\"^2.1.1\",\"recast\":\"^0.19.0\",\"regenerator-runtime\":\"^0.13.2\",\"shelljs\":\"^0.8.2\",\"sinon\":\"^9.0.1\",\"temp\":\"^0.9.0\",\"webpack\":\"^4.35.0\",\"webpack-cli\":\"^3.3.5\",\"yorkie\":\"^2.0.0\"},\"keywords\":[\"ast\",\"lint\",\"javascript\",\"ecmascript\",\"espree\"],\"license\":\"MIT\",\"engines\":{\"node\":\"^10.12.0 || >=12.0.0\"}}");
 
 /***/ }),
 /* 409 */
@@ -50735,24 +50827,6 @@ const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|flatMap|forEach|map|redu
 function isReachable(segment) {
   return segment.reachable;
 }
-/**
- * Gets a readable location.
- *
- * - FunctionExpression -> the function name or `function` keyword.
- * - ArrowFunctionExpression -> `=>` token.
- * @param {ASTNode} node A function node to get.
- * @param {SourceCode} sourceCode A source code to get tokens.
- * @returns {ASTNode|Token} The node or the token of a location.
- */
-
-
-function getLocation(node, sourceCode) {
-  if (node.type === "ArrowFunctionExpression") {
-    return sourceCode.getTokenBefore(node.body);
-  }
-
-  return node.id || node;
-}
 /**
  * Checks a given node is a MemberExpression node which has the specified name's
  * property.
@@ -50883,6 +50957,7 @@ module.exports = {
       allowImplicit: false,
       checkForEach: false
     };
+    const sourceCode = context.getSourceCode();
     let funcInfo = {
       arrayMethodName: null,
       upper: null,
@@ -50919,11 +50994,11 @@ module.exports = {
       }
 
       if (messageId) {
-        let name = astUtils.getFunctionNameWithKind(funcInfo.node);
+        let name = astUtils.getFunctionNameWithKind(node);
         name = messageId === "expectedNoReturnValue" ? lodash.upperFirst(name) : name;
         context.report({
           node,
-          loc: getLocation(node, context.getSourceCode()).loc.start,
+          loc: astUtils.getFunctionHeadLoc(node, sourceCode),
           messageId,
           data: {
             name
@@ -52332,6 +52407,8 @@ module.exports = {
 
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/callback-return"],
     type: "suggestion",
     docs: {
       description: "require `return` statements after callbacks",
@@ -53861,26 +53938,21 @@ module.exports = {
 
         context.report({
           node: reportItem,
-          loc: {
-            line: commaToken.loc.end.line,
-            column: commaToken.loc.start.column
-          },
+          loc: commaToken.loc,
           messageId: "unexpectedLineBeforeAndAfterComma",
           fix: getFixerFunction(styleType, previousItemToken, commaToken, currentItemToken)
         });
       } else if (style === "first" && !astUtils.isTokenOnSameLine(commaToken, currentItemToken)) {
         context.report({
           node: reportItem,
+          loc: commaToken.loc,
           messageId: "expectedCommaFirst",
           fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken)
         });
       } else if (style === "last" && astUtils.isTokenOnSameLine(commaToken, currentItemToken)) {
         context.report({
           node: reportItem,
-          loc: {
-            line: commaToken.loc.end.line,
-            column: commaToken.loc.end.column
-          },
+          loc: commaToken.loc,
           messageId: "expectedCommaLast",
           fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken)
         });
@@ -56521,7 +56593,8 @@ module.exports = {
       }]
     },
     messages: {
-      unexpected: "Unexpected newline between function name and paren.",
+      unexpectedWhitespace: "Unexpected whitespace between function name and paren.",
+      unexpectedNewline: "Unexpected newline between function name and paren.",
       missing: "Missing space between function name and paren."
     }
   },
@@ -56572,7 +56645,7 @@ module.exports = {
         context.report({
           node,
           loc: leftToken.loc.start,
-          messageId: "unexpected",
+          messageId: "unexpectedWhitespace",
 
           fix(fixer) {
             /*
@@ -56602,7 +56675,7 @@ module.exports = {
         context.report({
           node,
           loc: leftToken.loc.start,
-          messageId: "unexpected",
+          messageId: "unexpectedNewline",
 
           fix(fixer) {
             return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ");
@@ -57803,18 +57876,6 @@ const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u;
 
 function isReachable(segment) {
   return segment.reachable;
-}
-/**
- * Gets a readable location.
- *
- * - FunctionExpression -> the function name or `function` keyword.
- * @param {ASTNode} node A function node to get.
- * @returns {ASTNode|Token} The node or the token of a location.
- */
-
-
-function getId(node) {
-  return node.id || node;
 } //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -57850,6 +57911,7 @@ module.exports = {
     const options = context.options[0] || {
       allowImplicit: false
     };
+    const sourceCode = context.getSourceCode();
     let funcInfo = {
       upper: null,
       codePath: null,
@@ -57871,7 +57933,7 @@ module.exports = {
       if (funcInfo.shouldCheck && funcInfo.codePath.currentSegments.some(isReachable)) {
         context.report({
           node,
-          loc: getId(node).loc.start,
+          loc: astUtils.getFunctionHeadLoc(node, sourceCode),
           messageId: funcInfo.hasReturn ? "expectedAlways" : "expected",
           data: {
             name: astUtils.getFunctionNameWithKind(funcInfo.node)
@@ -57996,6 +58058,8 @@ function isShadowed(scope, node) {
 
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/global-require"],
     type: "suggestion",
     docs: {
       description: "require `require()` calls to be placed at top-level module scope",
@@ -58344,6 +58408,8 @@ module.exports = {
 
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/handle-callback-err"],
     type: "suggestion",
     docs: {
       description: "require error handling in callbacks",
@@ -63010,7 +63076,7 @@ function isSingleLine(node) {
 /**
  * Checks whether the properties on a single line.
  * @param {ASTNode[]} properties List of Property AST nodes.
- * @returns {boolean} True if all properies is on a single line.
+ * @returns {boolean} True if all properties is on a single line.
  */
 
 
@@ -67469,7 +67535,7 @@ module.exports = {
 
       context.report({
         node,
-        loc: callee.loc.start,
+        loc: callee.loc,
         messageId
       });
     } //--------------------------------------------------------------------------
@@ -68163,16 +68229,19 @@ module.exports = {
         }
 
         if (depth > ignoreChainWithDepth && astUtils.isTokenOnSameLine(callee.object, callee.property)) {
+          const firstTokenAfterObject = sourceCode.getTokenAfter(callee.object, astUtils.isNotClosingParenToken);
           context.report({
             node: callee.property,
-            loc: callee.property.loc.start,
+            loc: {
+              start: firstTokenAfterObject.loc.start,
+              end: callee.loc.end
+            },
             messageId: "expected",
             data: {
               callee: getPropertyText(callee)
             },
 
             fix(fixer) {
-              const firstTokenAfterObject = sourceCode.getTokenAfter(callee.object, astUtils.isNotClosingParenToken);
               return fixer.insertTextBefore(firstTokenAfterObject, "\n");
             }
 
@@ -68654,6 +68723,8 @@ module.exports = {
 
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/no-deprecated-api"],
     type: "problem",
     docs: {
       description: "disallow use of the `Buffer()` constructor",
@@ -69896,8 +69967,8 @@ __webpack_require__.r(__webpack_exports__);
 /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "visitRegExpAST", function() { return visitRegExpAST; });
 /*! @author Toru Nagashima <https://github.com/mysticatea> */
 var ast = /*#__PURE__*/Object.freeze({});
-let largeIdStartPattern = null;
-let largeIdContinuePattern = null;
+let largeIdStartRanges = undefined;
+let largeIdContinueRanges = undefined;
 
 function isIdStart(cp) {
   if (cp < 0x41) return false;
@@ -69919,111 +69990,93 @@ function isIdContinue(cp) {
 }
 
 function isLargeIdStart(cp) {
-  if (!largeIdStartPattern) {
-    largeIdStartPattern = new RegExp("^[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1" + "\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377" + "\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1" + "\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559" + "\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a" + "\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef" + "\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1" + "\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824" + "\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd" + "\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980" + "\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2" + "\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1" + "\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28" + "\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39" + "\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91" + "\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd" + "\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10" + "\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d" + "\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a" + "\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f" + "\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c" + "\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a" + "\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8" + "\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1" + "\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d" + "\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96" + "\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30" + "\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a" + "\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd" + "\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47" + "\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055" + "\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081" + "\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248" + "\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288" + "\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0" + "\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315" + "\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd" + "\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea" + "\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731" + "\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7" + "\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5" + "\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab" + "\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33" + "\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5" + "\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88" + "\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3" + "\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d" + "\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d" + "\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4" + "\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec" + "\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102" + "\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128" + "\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188" + "\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee" + "\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f" + "\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6" + "\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6" + "\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035" + "\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa" + "\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba" + "\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c" + "\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b" + "\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f" + "\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7c6\ua7f7-\ua801" + "\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873" + "\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925" + "\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4" + "\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42" + "\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1" + "\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd" + "\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e" + "\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a" + "\uab5c-\uab67\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6" + "\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06" + "\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c" + "\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d" + "\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74" + "\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe" + "\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc" + "\u{10000}-\u{1000b}\u{1000d}-\u{10026}\u{10028}-\u{1003a}" + "\u{1003c}\u{1003d}\u{1003f}-\u{1004d}\u{10050}-\u{1005d}" + "\u{10080}-\u{100fa}\u{10140}-\u{10174}\u{10280}-\u{1029c}" + "\u{102a0}-\u{102d0}\u{10300}-\u{1031f}\u{1032d}-\u{1034a}" + "\u{10350}-\u{10375}\u{10380}-\u{1039d}\u{103a0}-\u{103c3}" + "\u{103c8}-\u{103cf}\u{103d1}-\u{103d5}\u{10400}-\u{1049d}" + "\u{104b0}-\u{104d3}\u{104d8}-\u{104fb}\u{10500}-\u{10527}" + "\u{10530}-\u{10563}\u{10600}-\u{10736}\u{10740}-\u{10755}" + "\u{10760}-\u{10767}\u{10800}-\u{10805}\u{10808}" + "\u{1080a}-\u{10835}\u{10837}\u{10838}\u{1083c}" + "\u{1083f}-\u{10855}\u{10860}-\u{10876}\u{10880}-\u{1089e}" + "\u{108e0}-\u{108f2}\u{108f4}\u{108f5}\u{10900}-\u{10915}" + "\u{10920}-\u{10939}\u{10980}-\u{109b7}\u{109be}\u{109bf}" + "\u{10a00}\u{10a10}-\u{10a13}\u{10a15}-\u{10a17}" + "\u{10a19}-\u{10a35}\u{10a60}-\u{10a7c}\u{10a80}-\u{10a9c}" + "\u{10ac0}-\u{10ac7}\u{10ac9}-\u{10ae4}\u{10b00}-\u{10b35}" + "\u{10b40}-\u{10b55}\u{10b60}-\u{10b72}\u{10b80}-\u{10b91}" + "\u{10c00}-\u{10c48}\u{10c80}-\u{10cb2}\u{10cc0}-\u{10cf2}" + "\u{10d00}-\u{10d23}\u{10f00}-\u{10f1c}\u{10f27}" + "\u{10f30}-\u{10f45}\u{10fe0}-\u{10ff6}\u{11003}-\u{11037}" + "\u{11083}-\u{110af}\u{110d0}-\u{110e8}\u{11103}-\u{11126}" + "\u{11144}\u{11150}-\u{11172}\u{11176}\u{11183}-\u{111b2}" + "\u{111c1}-\u{111c4}\u{111da}\u{111dc}\u{11200}-\u{11211}" + "\u{11213}-\u{1122b}\u{11280}-\u{11286}\u{11288}" + "\u{1128a}-\u{1128d}\u{1128f}-\u{1129d}\u{1129f}-\u{112a8}" + "\u{112b0}-\u{112de}\u{11305}-\u{1130c}\u{1130f}\u{11310}" + "\u{11313}-\u{11328}\u{1132a}-\u{11330}\u{11332}\u{11333}" + "\u{11335}-\u{11339}\u{1133d}\u{11350}\u{1135d}-\u{11361}" + "\u{11400}-\u{11434}\u{11447}-\u{1144a}\u{1145f}" + "\u{11480}-\u{114af}\u{114c4}\u{114c5}\u{114c7}" + "\u{11580}-\u{115ae}\u{115d8}-\u{115db}\u{11600}-\u{1162f}" + "\u{11644}\u{11680}-\u{116aa}\u{116b8}\u{11700}-\u{1171a}" + "\u{11800}-\u{1182b}\u{118a0}-\u{118df}\u{118ff}" + "\u{119a0}-\u{119a7}\u{119aa}-\u{119d0}\u{119e1}\u{119e3}" + "\u{11a00}\u{11a0b}-\u{11a32}\u{11a3a}\u{11a50}" + "\u{11a5c}-\u{11a89}\u{11a9d}\u{11ac0}-\u{11af8}" + "\u{11c00}-\u{11c08}\u{11c0a}-\u{11c2e}\u{11c40}" + "\u{11c72}-\u{11c8f}\u{11d00}-\u{11d06}\u{11d08}\u{11d09}" + "\u{11d0b}-\u{11d30}\u{11d46}\u{11d60}-\u{11d65}" + "\u{11d67}\u{11d68}\u{11d6a}-\u{11d89}\u{11d98}" + "\u{11ee0}-\u{11ef2}\u{12000}-\u{12399}\u{12400}-\u{1246e}" + "\u{12480}-\u{12543}\u{13000}-\u{1342e}\u{14400}-\u{14646}" + "\u{16800}-\u{16a38}\u{16a40}-\u{16a5e}\u{16ad0}-\u{16aed}" + "\u{16b00}-\u{16b2f}\u{16b40}-\u{16b43}\u{16b63}-\u{16b77}" + "\u{16b7d}-\u{16b8f}\u{16e40}-\u{16e7f}\u{16f00}-\u{16f4a}" + "\u{16f50}\u{16f93}-\u{16f9f}\u{16fe0}\u{16fe1}\u{16fe3}" + "\u{17000}-\u{187f7}\u{18800}-\u{18af2}\u{1b000}-\u{1b11e}" + "\u{1b150}-\u{1b152}\u{1b164}-\u{1b167}\u{1b170}-\u{1b2fb}" + "\u{1bc00}-\u{1bc6a}\u{1bc70}-\u{1bc7c}\u{1bc80}-\u{1bc88}" + "\u{1bc90}-\u{1bc99}\u{1d400}-\u{1d454}\u{1d456}-\u{1d49c}" + "\u{1d49e}\u{1d49f}\u{1d4a2}\u{1d4a5}\u{1d4a6}" + "\u{1d4a9}-\u{1d4ac}\u{1d4ae}-\u{1d4b9}\u{1d4bb}" + "\u{1d4bd}-\u{1d4c3}\u{1d4c5}-\u{1d505}\u{1d507}-\u{1d50a}" + "\u{1d50d}-\u{1d514}\u{1d516}-\u{1d51c}\u{1d51e}-\u{1d539}" + "\u{1d53b}-\u{1d53e}\u{1d540}-\u{1d544}\u{1d546}" + "\u{1d54a}-\u{1d550}\u{1d552}-\u{1d6a5}\u{1d6a8}-\u{1d6c0}" + "\u{1d6c2}-\u{1d6da}\u{1d6dc}-\u{1d6fa}\u{1d6fc}-\u{1d714}" + "\u{1d716}-\u{1d734}\u{1d736}-\u{1d74e}\u{1d750}-\u{1d76e}" + "\u{1d770}-\u{1d788}\u{1d78a}-\u{1d7a8}\u{1d7aa}-\u{1d7c2}" + "\u{1d7c4}-\u{1d7cb}\u{1e100}-\u{1e12c}\u{1e137}-\u{1e13d}" + "\u{1e14e}\u{1e2c0}-\u{1e2eb}\u{1e800}-\u{1e8c4}" + "\u{1e900}-\u{1e943}\u{1e94b}\u{1ee00}-\u{1ee03}" + "\u{1ee05}-\u{1ee1f}\u{1ee21}\u{1ee22}\u{1ee24}\u{1ee27}" + "\u{1ee29}-\u{1ee32}\u{1ee34}-\u{1ee37}\u{1ee39}\u{1ee3b}" + "\u{1ee42}\u{1ee47}\u{1ee49}\u{1ee4b}\u{1ee4d}-\u{1ee4f}" + "\u{1ee51}\u{1ee52}\u{1ee54}\u{1ee57}\u{1ee59}\u{1ee5b}" + "\u{1ee5d}\u{1ee5f}\u{1ee61}\u{1ee62}\u{1ee64}" + "\u{1ee67}-\u{1ee6a}\u{1ee6c}-\u{1ee72}\u{1ee74}-\u{1ee77}" + "\u{1ee79}-\u{1ee7c}\u{1ee7e}\u{1ee80}-\u{1ee89}" + "\u{1ee8b}-\u{1ee9b}\u{1eea1}-\u{1eea3}\u{1eea5}-\u{1eea9}" + "\u{1eeab}-\u{1eebb}\u{20000}-\u{2a6d6}\u{2a700}-\u{2b734}" + "\u{2b740}-\u{2b81d}\u{2b820}-\u{2cea1}\u{2ceb0}-\u{2ebe0}" + "\u{2f800}-\u{2fa1d}]$", "u");
-  }
-
-  return largeIdStartPattern.test(String.fromCodePoint(cp));
+  return isInRange(cp, largeIdStartRanges || (largeIdStartRanges = initLargeIdStartRanges()));
 }
 
 function isLargeIdContinue(cp) {
-  if (!largeIdContinuePattern) {
-    largeIdContinuePattern = new RegExp("^[\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf" + "\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669" + "\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed" + "\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9" + "\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827" + "\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903" + "\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963" + "\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8" + "\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe" + "\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d" + "\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5" + "\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef" + "\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48" + "\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82" + "\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef" + "\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d" + "\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc" + "\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6" + "\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c" + "\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63" + "\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6" + "\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a" + "\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd" + "\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39" + "\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97" + "\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059" + "\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074" + "\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371" + "\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773" + "\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819" + "\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da" + "\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89" + "\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44" + "\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad" + "\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49" + "\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4" + "\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054" + "\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f" + "\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f" + "\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b" + "\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9" + "\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953" + "\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9" + "\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d" + "\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1" + "\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed" + "\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34" + "\ufe4d-\ufe4f\uff10-\uff19\uff3f\u{101fd}\u{102e0}" + "\u{10376}-\u{1037a}\u{104a0}-\u{104a9}\u{10a01}-\u{10a03}" + "\u{10a05}\u{10a06}\u{10a0c}-\u{10a0f}\u{10a38}-\u{10a3a}" + "\u{10a3f}\u{10ae5}\u{10ae6}\u{10d24}-\u{10d27}" + "\u{10d30}-\u{10d39}\u{10f46}-\u{10f50}\u{11000}-\u{11002}" + "\u{11038}-\u{11046}\u{11066}-\u{1106f}\u{1107f}-\u{11082}" + "\u{110b0}-\u{110ba}\u{110f0}-\u{110f9}\u{11100}-\u{11102}" + "\u{11127}-\u{11134}\u{11136}-\u{1113f}\u{11145}\u{11146}" + "\u{11173}\u{11180}-\u{11182}\u{111b3}-\u{111c0}" + "\u{111c9}-\u{111cc}\u{111d0}-\u{111d9}\u{1122c}-\u{11237}" + "\u{1123e}\u{112df}-\u{112ea}\u{112f0}-\u{112f9}" + "\u{11300}-\u{11303}\u{1133b}\u{1133c}\u{1133e}-\u{11344}" + "\u{11347}\u{11348}\u{1134b}-\u{1134d}\u{11357}" + "\u{11362}\u{11363}\u{11366}-\u{1136c}\u{11370}-\u{11374}" + "\u{11435}-\u{11446}\u{11450}-\u{11459}\u{1145e}" + "\u{114b0}-\u{114c3}\u{114d0}-\u{114d9}\u{115af}-\u{115b5}" + "\u{115b8}-\u{115c0}\u{115dc}\u{115dd}\u{11630}-\u{11640}" + "\u{11650}-\u{11659}\u{116ab}-\u{116b7}\u{116c0}-\u{116c9}" + "\u{1171d}-\u{1172b}\u{11730}-\u{11739}\u{1182c}-\u{1183a}" + "\u{118e0}-\u{118e9}\u{119d1}-\u{119d7}\u{119da}-\u{119e0}" + "\u{119e4}\u{11a01}-\u{11a0a}\u{11a33}-\u{11a39}" + "\u{11a3b}-\u{11a3e}\u{11a47}\u{11a51}-\u{11a5b}" + "\u{11a8a}-\u{11a99}\u{11c2f}-\u{11c36}\u{11c38}-\u{11c3f}" + "\u{11c50}-\u{11c59}\u{11c92}-\u{11ca7}\u{11ca9}-\u{11cb6}" + "\u{11d31}-\u{11d36}\u{11d3a}\u{11d3c}\u{11d3d}" + "\u{11d3f}-\u{11d45}\u{11d47}\u{11d50}-\u{11d59}" + "\u{11d8a}-\u{11d8e}\u{11d90}\u{11d91}\u{11d93}-\u{11d97}" + "\u{11da0}-\u{11da9}\u{11ef3}-\u{11ef6}\u{16a60}-\u{16a69}" + "\u{16af0}-\u{16af4}\u{16b30}-\u{16b36}\u{16b50}-\u{16b59}" + "\u{16f4f}\u{16f51}-\u{16f87}\u{16f8f}-\u{16f92}" + "\u{1bc9d}\u{1bc9e}\u{1d165}-\u{1d169}\u{1d16d}-\u{1d172}" + "\u{1d17b}-\u{1d182}\u{1d185}-\u{1d18b}\u{1d1aa}-\u{1d1ad}" + "\u{1d242}-\u{1d244}\u{1d7ce}-\u{1d7ff}\u{1da00}-\u{1da36}" + "\u{1da3b}-\u{1da6c}\u{1da75}\u{1da84}\u{1da9b}-\u{1da9f}" + "\u{1daa1}-\u{1daaf}\u{1e000}-\u{1e006}\u{1e008}-\u{1e018}" + "\u{1e01b}-\u{1e021}\u{1e023}\u{1e024}\u{1e026}-\u{1e02a}" + "\u{1e130}-\u{1e136}\u{1e140}-\u{1e149}\u{1e2ec}-\u{1e2f9}" + "\u{1e8d0}-\u{1e8d6}\u{1e944}-\u{1e94a}\u{1e950}-\u{1e959}" + "\u{e0100}-\u{e01ef}]$", "u");
-  }
+  return isInRange(cp, largeIdContinueRanges || (largeIdContinueRanges = initLargeIdContinueRanges()));
+}
 
-  return largeIdContinuePattern.test(String.fromCodePoint(cp));
+function initLargeIdStartRanges() {
+  return restoreRanges("170 0 11 0 5 0 6 22 2 30 2 457 5 11 15 4 8 0 2 0 130 4 2 1 3 3 2 0 7 0 2 2 2 0 2 19 2 82 2 138 9 165 2 37 3 0 7 40 72 26 5 3 46 42 36 1 2 98 2 0 16 1 8 1 11 2 3 0 17 0 2 29 30 88 12 0 25 32 10 1 5 0 6 21 5 0 10 0 4 0 24 24 8 10 54 20 2 17 61 53 4 0 19 0 8 9 16 15 5 7 3 1 3 21 2 6 2 0 4 3 4 0 17 0 14 1 2 2 15 1 11 0 9 5 5 1 3 21 2 6 2 1 2 1 2 1 32 3 2 0 20 2 17 8 2 2 2 21 2 6 2 1 2 4 4 0 19 0 16 1 24 0 12 7 3 1 3 21 2 6 2 1 2 4 4 0 31 1 2 2 16 0 18 0 2 5 4 2 2 3 4 1 2 0 2 1 4 1 4 2 4 11 23 0 53 7 2 2 2 22 2 15 4 0 27 2 6 1 31 0 5 7 2 2 2 22 2 9 2 4 4 0 33 0 2 1 16 1 18 8 2 2 2 40 3 0 17 0 6 2 9 2 25 5 6 17 4 23 2 8 2 0 3 6 59 47 2 1 13 6 59 1 2 0 2 4 2 23 2 0 2 9 2 1 10 0 3 4 2 0 22 3 33 0 64 7 2 35 28 4 116 42 21 0 17 5 5 3 4 0 4 1 8 2 5 12 13 0 18 37 2 0 6 0 3 42 2 332 2 3 3 6 2 0 2 3 3 40 2 3 3 32 2 3 3 6 2 0 2 3 3 14 2 56 2 3 3 66 38 15 17 85 3 5 4 619 3 16 2 25 6 74 4 10 8 12 2 3 15 17 15 17 15 12 2 2 16 51 36 0 5 0 68 88 8 40 2 0 6 69 11 30 50 29 3 4 12 43 5 25 55 22 10 52 83 0 94 46 18 6 56 29 14 1 11 43 27 35 42 2 11 35 3 8 8 42 3 2 42 3 2 5 2 1 4 0 6 191 65 277 3 5 3 37 3 5 3 7 2 0 2 0 2 0 2 30 3 52 2 6 2 0 4 2 2 6 4 3 3 5 5 12 6 2 2 6 117 0 14 0 17 12 102 0 5 0 3 9 2 0 3 5 7 0 2 0 2 0 2 15 3 3 6 4 5 0 18 40 2680 46 2 46 2 132 7 3 4 1 13 37 2 0 6 0 3 55 8 0 17 22 10 6 2 6 2 6 2 6 2 6 2 6 2 6 2 6 551 2 26 8 8 4 3 4 5 85 5 4 2 89 2 3 6 42 2 93 18 31 49 15 513 6591 65 20988 4 1164 68 45 3 268 4 15 11 1 21 46 17 30 3 79 40 8 3 102 3 52 3 8 43 12 2 2 2 3 2 22 30 51 15 49 63 5 4 0 2 1 12 27 11 22 26 28 8 46 29 0 17 4 2 9 11 4 2 40 24 2 2 7 21 22 4 0 4 49 2 0 4 1 3 4 3 0 2 0 25 2 3 10 8 2 13 5 3 5 3 5 10 6 2 6 2 42 2 13 7 114 30 11171 13 22 5 48 8453 365 3 105 39 6 13 4 6 0 2 9 2 12 2 4 2 0 2 1 2 1 2 107 34 362 19 63 3 53 41 11 117 4 2 134 37 25 7 25 12 88 4 5 3 5 3 5 3 2 36 11 2 25 2 18 2 1 2 14 3 13 35 122 70 52 268 28 4 48 48 31 14 29 6 37 11 29 3 35 5 7 2 4 43 157 19 35 5 35 5 39 9 51 157 310 10 21 11 7 153 5 3 0 2 43 2 1 4 0 3 22 11 22 10 30 66 18 2 1 11 21 11 25 71 55 7 1 65 0 16 3 2 2 2 28 43 28 4 28 36 7 2 27 28 53 11 21 11 18 14 17 111 72 56 50 14 50 14 35 349 41 7 1 79 28 11 0 9 21 107 20 28 22 13 52 76 44 33 24 27 35 30 0 3 0 9 34 4 0 13 47 15 3 22 0 2 0 36 17 2 24 85 6 2 0 2 3 2 14 2 9 8 46 39 7 3 1 3 21 2 6 2 1 2 4 4 0 19 0 13 4 159 52 19 3 21 2 31 47 21 1 2 0 185 46 42 3 37 47 21 0 60 42 14 0 72 26 230 43 117 63 32 7 3 0 3 7 2 1 2 23 16 0 2 0 95 7 3 38 17 0 2 0 29 0 11 39 8 0 22 0 12 45 20 0 35 56 264 8 2 36 18 0 50 29 113 6 2 1 2 37 22 0 26 5 2 1 2 31 15 0 328 18 190 0 80 921 103 110 18 195 2749 1070 4050 582 8634 568 8 30 114 29 19 47 17 3 32 20 6 18 689 63 129 74 6 0 67 12 65 1 2 0 29 6135 9 1237 43 8 8952 286 50 2 18 3 9 395 2309 106 6 12 4 8 8 9 5991 84 2 70 2 1 3 0 3 1 3 3 2 11 2 0 2 6 2 64 2 3 3 7 2 6 2 27 2 3 2 4 2 0 4 6 2 339 3 24 2 24 2 30 2 24 2 30 2 24 2 30 2 24 2 30 2 24 2 7 2357 44 11 6 17 0 370 43 1301 196 60 67 8 0 1205 3 2 26 2 1 2 0 3 0 2 9 2 3 2 0 2 0 7 0 5 0 2 0 2 0 2 2 2 1 2 0 3 0 2 0 2 0 2 0 2 0 2 1 2 0 3 3 2 6 2 3 2 3 2 0 2 9 2 16 6 2 2 4 2 16 4421 42717 35 4148 12 221 3 5761 15 7472 3104 541 1507 4938");
 }
 
-const gcNamePattern = /^(?:General_Category|gc)$/u;
-const scNamePattern = /^(?:Script(?:_Extensions)?|scx?)$/u;
-const gcValuePatterns = {
-  es2018: null,
-  es2019: null,
-  es2020: null
-};
-const scValuePatterns = {
-  es2018: null,
-  es2019: null,
-  es2020: null
-};
-const binPropertyPatterns = {
-  es2018: null,
-  es2019: null,
-  es2020: null
-};
+function initLargeIdContinueRanges() {
+  return restoreRanges("183 0 585 111 24 0 252 4 266 44 2 0 2 1 2 1 2 0 73 10 49 30 7 0 102 6 3 5 3 1 2 3 3 9 24 0 31 26 92 10 16 9 34 8 10 0 25 3 2 8 2 2 2 4 44 2 120 14 2 32 55 2 2 17 2 6 11 1 3 9 18 2 57 0 2 6 3 1 3 2 10 0 11 1 3 9 15 0 3 2 57 0 2 4 5 1 3 2 4 0 21 11 4 0 12 2 57 0 2 7 2 2 2 2 21 1 3 9 11 5 2 2 57 0 2 6 3 1 3 2 8 2 11 1 3 9 19 0 60 4 4 2 2 3 10 0 15 9 17 4 58 6 2 2 2 3 8 1 12 1 3 9 18 2 57 0 2 6 2 2 2 3 8 1 12 1 3 9 17 3 56 1 2 6 2 2 2 3 10 0 11 1 3 9 18 2 71 0 5 5 2 0 2 7 7 9 3 1 62 0 3 6 13 7 2 9 88 0 3 8 12 5 3 9 63 1 7 9 12 0 2 0 2 0 5 1 50 19 2 1 6 10 2 35 10 0 101 19 2 9 13 3 5 2 2 2 3 6 4 3 14 11 2 14 704 2 10 8 929 2 30 2 30 1 31 1 65 31 10 0 3 9 34 2 3 9 144 0 119 11 5 11 11 9 129 10 61 4 58 9 2 28 3 10 7 9 23 13 2 1 64 4 48 16 12 9 18 8 13 2 31 12 3 9 45 13 49 19 9 9 7 9 119 2 2 20 5 0 7 0 3 2 199 57 2 4 576 1 20 0 124 12 5 0 4 11 3071 2 142 0 97 31 555 5 106 1 30086 9 70 0 5 9 33 1 81 1 273 0 4 0 5 0 24 4 5 0 84 1 51 17 11 9 7 17 14 10 29 7 26 12 45 3 48 13 16 9 12 0 11 9 48 13 13 0 9 1 3 9 34 2 51 0 2 2 3 1 6 1 2 0 42 4 6 1 237 7 2 1 3 9 20261 0 738 15 17 15 4 1 25 2 193 9 38 0 702 0 227 0 150 4 294 9 1368 2 2 1 6 3 41 2 5 0 166 1 574 3 9 9 370 1 154 10 176 2 54 14 32 9 16 3 46 10 54 9 7 2 37 13 2 9 6 1 45 0 13 2 49 13 9 3 2 11 83 11 7 0 161 11 6 9 7 3 56 1 2 6 3 1 3 2 10 0 11 1 3 6 4 4 193 17 10 9 5 0 82 19 13 9 214 6 3 8 28 1 83 16 16 9 82 12 9 9 84 14 5 9 243 14 166 9 71 5 2 1 3 3 2 0 2 1 13 9 120 6 3 6 4 0 29 9 41 6 2 3 9 0 10 10 47 15 406 7 2 7 17 9 57 21 2 13 123 5 4 0 2 1 2 6 2 0 9 9 49 4 2 1 2 4 9 9 330 3 19306 9 135 4 60 6 26 9 1014 0 2 54 8 3 82 0 12 1 19628 1 5319 4 4 5 9 7 3 6 31 3 149 2 1418 49 513 54 5 49 9 0 15 0 23 4 2 14 1361 6 2 16 3 6 2 1 2 4 262 6 10 9 419 13 1495 6 110 6 6 9 4759 9 787719 239");
+}
 
-function isValidUnicodeProperty(version, name, value) {
-  if (gcNamePattern.test(name)) {
-    if (version >= 2018) {
-      if (!gcValuePatterns.es2018) {
-        gcValuePatterns.es2018 = new RegExp("^(?:C|Cased_Letter|Cc|Cf|Close_Punctuation|Cn|Co|" + "Combining_Mark|Connector_Punctuation|Control|Cs|" + "Currency_Symbol|Dash_Punctuation|Decimal_Number|" + "Enclosing_Mark|Final_Punctuation|Format|" + "Initial_Punctuation|L|LC|Letter|Letter_Number|" + "Line_Separator|Ll|Lm|Lo|Lowercase_Letter|Lt|Lu|M|" + "Mark|Math_Symbol|Mc|Me|Mn|Modifier_Letter|" + "Modifier_Symbol|N|Nd|Nl|No|Nonspacing_Mark|Number|" + "Open_Punctuation|Other|Other_Letter|Other_Number|" + "Other_Punctuation|Other_Symbol|P|" + "Paragraph_Separator|Pc|Pd|Pe|Pf|Pi|Po|Private_Use|" + "Ps|Punctuation|S|Sc|Separator|Sk|Sm|So|" + "Space_Separator|Spacing_Mark|Surrogate|Symbol|" + "Titlecase_Letter|Unassigned|Uppercase_Letter|Z|Zl|" + "Zp|Zs|cntrl|digit|punct)$", "u");
-      }
+function isInRange(cp, ranges) {
+  let l = 0,
+      r = ranges.length / 2 | 0,
+      i = 0,
+      min = 0,
+      max = 0;
 
-      if (gcValuePatterns.es2018.test(value)) {
-        return true;
-      }
+  while (l < r) {
+    i = (l + r) / 2 | 0;
+    min = ranges[2 * i];
+    max = ranges[2 * i + 1];
+
+    if (cp < min) {
+      r = i;
+    } else if (cp > max) {
+      l = i + 1;
+    } else {
+      return true;
     }
   }
 
-  if (scNamePattern.test(name)) {
-    if (version >= 2018) {
-      if (!scValuePatterns.es2018) {
-        scValuePatterns.es2018 = new RegExp("^(?:Adlam|Adlm|Aghb|Ahom|Anatolian_Hieroglyphs|Arab|" + "Arabic|Armenian|Armi|Armn|Avestan|Avst|Bali|" + "Balinese|Bamu|Bamum|Bass|Bassa_Vah|Batak|Batk|Beng|" + "Bengali|Bhaiksuki|Bhks|Bopo|Bopomofo|Brah|Brahmi|" + "Brai|Braille|Bugi|Buginese|Buhd|Buhid|Cakm|" + "Canadian_Aboriginal|Cans|Cari|Carian|" + "Caucasian_Albanian|Chakma|Cham|Cher|Cherokee|Common|" + "Copt|Coptic|Cprt|Cuneiform|Cypriot|Cyrillic|Cyrl|" + "Deseret|Deva|Devanagari|Dsrt|Dupl|Duployan|Egyp|" + "Egyptian_Hieroglyphs|Elba|Elbasan|Ethi|Ethiopic|" + "Geor|Georgian|Glag|Glagolitic|Gonm|Goth|Gothic|Gran|" + "Grantha|Greek|Grek|Gujarati|Gujr|Gurmukhi|Guru|Han|" + "Hang|Hangul|Hani|Hano|Hanunoo|Hatr|Hatran|Hebr|" + "Hebrew|Hira|Hiragana|Hluw|Hmng|Hung|" + "Imperial_Aramaic|Inherited|Inscriptional_Pahlavi|" + "Inscriptional_Parthian|Ital|Java|Javanese|Kaithi|" + "Kali|Kana|Kannada|Katakana|Kayah_Li|Khar|Kharoshthi|" + "Khmer|Khmr|Khoj|Khojki|Khudawadi|Knda|Kthi|Lana|Lao|" + "Laoo|Latin|Latn|Lepc|Lepcha|Limb|Limbu|Lina|Linb|" + "Linear_A|Linear_B|Lisu|Lyci|Lycian|Lydi|Lydian|" + "Mahajani|Mahj|Malayalam|Mand|Mandaic|Mani|" + "Manichaean|Marc|Marchen|Masaram_Gondi|Meetei_Mayek|" + "Mend|Mende_Kikakui|Merc|Mero|Meroitic_Cursive|" + "Meroitic_Hieroglyphs|Miao|Mlym|Modi|Mong|Mongolian|" + "Mro|Mroo|Mtei|Mult|Multani|Myanmar|Mymr|Nabataean|" + "Narb|Nbat|New_Tai_Lue|Newa|Nko|Nkoo|Nshu|Nushu|Ogam|" + "Ogham|Ol_Chiki|Olck|Old_Hungarian|Old_Italic|" + "Old_North_Arabian|Old_Permic|Old_Persian|" + "Old_South_Arabian|Old_Turkic|Oriya|Orkh|Orya|Osage|" + "Osge|Osma|Osmanya|Pahawh_Hmong|Palm|Palmyrene|" + "Pau_Cin_Hau|Pauc|Perm|Phag|Phags_Pa|Phli|Phlp|Phnx|" + "Phoenician|Plrd|Prti|Psalter_Pahlavi|Qaac|Qaai|" + "Rejang|Rjng|Runic|Runr|Samaritan|Samr|Sarb|Saur|" + "Saurashtra|Sgnw|Sharada|Shavian|Shaw|Shrd|Sidd|" + "Siddham|SignWriting|Sind|Sinh|Sinhala|Sora|" + "Sora_Sompeng|Soyo|Soyombo|Sund|Sundanese|Sylo|" + "Syloti_Nagri|Syrc|Syriac|Tagalog|Tagb|Tagbanwa|" + "Tai_Le|Tai_Tham|Tai_Viet|Takr|Takri|Tale|Talu|Tamil|" + "Taml|Tang|Tangut|Tavt|Telu|Telugu|Tfng|Tglg|Thaa|" + "Thaana|Thai|Tibetan|Tibt|Tifinagh|Tirh|Tirhuta|Ugar|" + "Ugaritic|Vai|Vaii|Wara|Warang_Citi|Xpeo|Xsux|Yi|" + "Yiii|Zanabazar_Square|Zanb|Zinh|Zyyy)$", "u");
-      }
+  return false;
+}
 
-      if (scValuePatterns.es2018.test(value)) {
-        return true;
-      }
-    }
+function restoreRanges(data) {
+  let last = 0;
+  return data.split(" ").map(s => last += parseInt(s, 10) | 0);
+}
 
-    if (version >= 2019) {
-      if (!scValuePatterns.es2019) {
-        scValuePatterns.es2019 = new RegExp("^(?:Dogr|Dogra|Gong|Gunjala_Gondi|Hanifi_Rohingya|" + "Maka|Makasar|Medefaidrin|Medf|Old_Sogdian|Rohg|Sogd|" + "Sogdian|Sogo)$", "u");
-      }
+class DataSet {
+  constructor(raw2018, raw2019, raw2020) {
+    this._raw2018 = raw2018;
+    this._raw2019 = raw2019;
+    this._raw2020 = raw2020;
+  }
 
-      if (scValuePatterns.es2019.test(value)) {
-        return true;
-      }
-    }
+  get es2018() {
+    return this._set2018 || (this._set2018 = new Set(this._raw2018.split(" ")));
+  }
 
-    if (version >= 2020) {
-      if (!scValuePatterns.es2020) {
-        scValuePatterns.es2020 = new RegExp("^(?:Hmnp|Nand|Nandinagari|Nyiakeng_Puachue_Hmong|" + "Wancho|Wcho)$", "u");
-      }
+  get es2019() {
+    return this._set2019 || (this._set2019 = new Set(this._raw2019.split(" ")));
+  }
 
-      if (scValuePatterns.es2020.test(value)) {
-        return true;
-      }
-    }
+  get es2020() {
+    return this._set2020 || (this._set2020 = new Set(this._raw2020.split(" ")));
   }
 
-  return false;
 }
 
-function isValidLoneUnicodeProperty(version, value) {
-  if (version >= 2018) {
-    if (!binPropertyPatterns.es2018) {
-      binPropertyPatterns.es2018 = new RegExp("^(?:AHex|ASCII|ASCII_Hex_Digit|Alpha|Alphabetic|Any|" + "Assigned|Bidi_C|Bidi_Control|Bidi_M|Bidi_Mirrored|CI|" + "CWCF|CWCM|CWKCF|CWL|CWT|CWU|Case_Ignorable|Cased|" + "Changes_When_Casefolded|Changes_When_Casemapped|" + "Changes_When_Lowercased|Changes_When_NFKC_Casefolded|" + "Changes_When_Titlecased|Changes_When_Uppercased|DI|Dash|" + "Default_Ignorable_Code_Point|Dep|Deprecated|Dia|" + "Diacritic|Emoji|Emoji_Component|Emoji_Modifier|" + "Emoji_Modifier_Base|Emoji_Presentation|Ext|Extender|" + "Gr_Base|Gr_Ext|Grapheme_Base|Grapheme_Extend|Hex|" + "Hex_Digit|IDC|IDS|IDSB|IDST|IDS_Binary_Operator|" + "IDS_Trinary_Operator|ID_Continue|ID_Start|Ideo|" + "Ideographic|Join_C|Join_Control|LOE|" + "Logical_Order_Exception|Lower|Lowercase|Math|NChar|" + "Noncharacter_Code_Point|Pat_Syn|Pat_WS|Pattern_Syntax|" + "Pattern_White_Space|QMark|Quotation_Mark|RI|Radical|" + "Regional_Indicator|SD|STerm|Sentence_Terminal|" + "Soft_Dotted|Term|Terminal_Punctuation|UIdeo|" + "Unified_Ideograph|Upper|Uppercase|VS|Variation_Selector|" + "White_Space|XIDC|XIDS|XID_Continue|XID_Start|space)$", "u");
-    }
+const gcNameSet = new Set(["General_Category", "gc"]);
+const scNameSet = new Set(["Script", "Script_Extensions", "sc", "scx"]);
+const gcValueSets = new DataSet("C Cased_Letter Cc Cf Close_Punctuation Cn Co Combining_Mark Connector_Punctuation Control Cs Currency_Symbol Dash_Punctuation Decimal_Number Enclosing_Mark Final_Punctuation Format Initial_Punctuation L LC Letter Letter_Number Line_Separator Ll Lm Lo Lowercase_Letter Lt Lu M Mark Math_Symbol Mc Me Mn Modifier_Letter Modifier_Symbol N Nd Nl No Nonspacing_Mark Number Open_Punctuation Other Other_Letter Other_Number Other_Punctuation Other_Symbol P Paragraph_Separator Pc Pd Pe Pf Pi Po Private_Use Ps Punctuation S Sc Separator Sk Sm So Space_Separator Spacing_Mark Surrogate Symbol Titlecase_Letter Unassigned Uppercase_Letter Z Zl Zp Zs cntrl digit punct", "", "");
+const scValueSets = new DataSet("Adlam Adlm Aghb Ahom Anatolian_Hieroglyphs Arab Arabic Armenian Armi Armn Avestan Avst Bali Balinese Bamu Bamum Bass Bassa_Vah Batak Batk Beng Bengali Bhaiksuki Bhks Bopo Bopomofo Brah Brahmi Brai Braille Bugi Buginese Buhd Buhid Cakm Canadian_Aboriginal Cans Cari Carian Caucasian_Albanian Chakma Cham Cher Cherokee Common Copt Coptic Cprt Cuneiform Cypriot Cyrillic Cyrl Deseret Deva Devanagari Dsrt Dupl Duployan Egyp Egyptian_Hieroglyphs Elba Elbasan Ethi Ethiopic Geor Georgian Glag Glagolitic Gonm Goth Gothic Gran Grantha Greek Grek Gujarati Gujr Gurmukhi Guru Han Hang Hangul Hani Hano Hanunoo Hatr Hatran Hebr Hebrew Hira Hiragana Hluw Hmng Hung Imperial_Aramaic Inherited Inscriptional_Pahlavi Inscriptional_Parthian Ital Java Javanese Kaithi Kali Kana Kannada Katakana Kayah_Li Khar Kharoshthi Khmer Khmr Khoj Khojki Khudawadi Knda Kthi Lana Lao Laoo Latin Latn Lepc Lepcha Limb Limbu Lina Linb Linear_A Linear_B Lisu Lyci Lycian Lydi Lydian Mahajani Mahj Malayalam Mand Mandaic Mani Manichaean Marc Marchen Masaram_Gondi Meetei_Mayek Mend Mende_Kikakui Merc Mero Meroitic_Cursive Meroitic_Hieroglyphs Miao Mlym Modi Mong Mongolian Mro Mroo Mtei Mult Multani Myanmar Mymr Nabataean Narb Nbat New_Tai_Lue Newa Nko Nkoo Nshu Nushu Ogam Ogham Ol_Chiki Olck Old_Hungarian Old_Italic Old_North_Arabian Old_Permic Old_Persian Old_South_Arabian Old_Turkic Oriya Orkh Orya Osage Osge Osma Osmanya Pahawh_Hmong Palm Palmyrene Pau_Cin_Hau Pauc Perm Phag Phags_Pa Phli Phlp Phnx Phoenician Plrd Prti Psalter_Pahlavi Qaac Qaai Rejang Rjng Runic Runr Samaritan Samr Sarb Saur Saurashtra Sgnw Sharada Shavian Shaw Shrd Sidd Siddham SignWriting Sind Sinh Sinhala Sora Sora_Sompeng Soyo Soyombo Sund Sundanese Sylo Syloti_Nagri Syrc Syriac Tagalog Tagb Tagbanwa Tai_Le Tai_Tham Tai_Viet Takr Takri Tale Talu Tamil Taml Tang Tangut Tavt Telu Telugu Tfng Tglg Thaa Thaana Thai Tibetan Tibt Tifinagh Tirh Tirhuta Ugar Ugaritic Vai Vaii Wara Warang_Citi Xpeo Xsux Yi Yiii Zanabazar_Square Zanb Zinh Zyyy", "Dogr Dogra Gong Gunjala_Gondi Hanifi_Rohingya Maka Makasar Medefaidrin Medf Old_Sogdian Rohg Sogd Sogdian Sogo", "Elym Elymaic Hmnp Nand Nandinagari Nyiakeng_Puachue_Hmong Wancho Wcho");
+const binPropertySets = new DataSet("AHex ASCII ASCII_Hex_Digit Alpha Alphabetic Any Assigned Bidi_C Bidi_Control Bidi_M Bidi_Mirrored CI CWCF CWCM CWKCF CWL CWT CWU Case_Ignorable Cased Changes_When_Casefolded Changes_When_Casemapped Changes_When_Lowercased Changes_When_NFKC_Casefolded Changes_When_Titlecased Changes_When_Uppercased DI Dash Default_Ignorable_Code_Point Dep Deprecated Dia Diacritic Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Ext Extender Gr_Base Gr_Ext Grapheme_Base Grapheme_Extend Hex Hex_Digit IDC IDS IDSB IDST IDS_Binary_Operator IDS_Trinary_Operator ID_Continue ID_Start Ideo Ideographic Join_C Join_Control LOE Logical_Order_Exception Lower Lowercase Math NChar Noncharacter_Code_Point Pat_Syn Pat_WS Pattern_Syntax Pattern_White_Space QMark Quotation_Mark RI Radical Regional_Indicator SD STerm Sentence_Terminal Soft_Dotted Term Terminal_Punctuation UIdeo Unified_Ideograph Upper Uppercase VS Variation_Selector White_Space XIDC XIDS XID_Continue XID_Start space", "Extended_Pictographic", "");
 
-    if (binPropertyPatterns.es2018.test(value)) {
-      return true;
-    }
+function isValidUnicodeProperty(version, name, value) {
+  if (gcNameSet.has(name)) {
+    return version >= 2018 && gcValueSets.es2018.has(value);
   }
 
-  if (version >= 2019) {
-    if (!binPropertyPatterns.es2019) {
-      binPropertyPatterns.es2019 = new RegExp("^(?:Extended_Pictographic)$", "u");
-    }
-
-    if (binPropertyPatterns.es2019.test(value)) {
-      return true;
-    }
+  if (scNameSet.has(name)) {
+    return version >= 2018 && scValueSets.es2018.has(value) || version >= 2019 && scValueSets.es2019.has(value) || version >= 2020 && scValueSets.es2020.has(value);
   }
 
   return false;
 }
 
+function isValidLoneUnicodeProperty(version, value) {
+  return version >= 2018 && binPropertySets.es2018.has(value) || version >= 2019 && binPropertySets.es2019.has(value);
+}
+
 const Backspace = 0x08;
 const CharacterTabulation = 0x09;
 const LineFeed = 0x0a;
@@ -70128,6 +70181,18 @@ function digitToInt(code) {
   return code - DigitZero;
 }
 
+function isLeadSurrogate(code) {
+  return code >= 0xd800 && code <= 0xdbff;
+}
+
+function isTrailSurrogate(code) {
+  return code >= 0xdc00 && code <= 0xdfff;
+}
+
+function combineSurrogatePair(lead, trail) {
+  return (lead - 0xd800) * 0x400 + (trail - 0xdc00) + 0x10000;
+}
+
 const legacyImpl = {
   at(s, end, i) {
     return i < end ? s.charCodeAt(i) : -1;
@@ -70369,12 +70434,12 @@ class RegExpValidator {
     this._uFlag = uFlag && this.ecmaVersion >= 2015;
     this._nFlag = uFlag && this.ecmaVersion >= 2018;
     this.reset(source, start, end);
-    this.pattern();
+    this.consumePattern();
 
     if (!this._nFlag && this.ecmaVersion >= 2018 && this._groupNames.size > 0) {
       this._nFlag = true;
       this.rewind(start);
-      this.pattern();
+      this.consumePattern();
     }
   }
 
@@ -70625,7 +70690,7 @@ class RegExpValidator {
     return this.index !== start;
   }
 
-  pattern() {
+  consumePattern() {
     const start = this.index;
     this._numCapturingParens = this.countCapturingParens();
 
@@ -70634,7 +70699,7 @@ class RegExpValidator {
     this._backreferenceNames.clear();
 
     this.onPatternEnter(start);
-    this.disjunction();
+    this.consumeDisjunction();
     const cp = this.currentCodePoint;
 
     if (this.currentCodePoint !== -1) {
@@ -70690,17 +70755,16 @@ class RegExpValidator {
     return count;
   }
 
-  disjunction() {
+  consumeDisjunction() {
     const start = this.index;
     let i = 0;
     this.onDisjunctionEnter(start);
-    this.alternative(i++);
 
-    while (this.eat(VerticalLine)) {
-      this.alternative(i++);
-    }
+    do {
+      this.consumeAlternative(i++);
+    } while (this.eat(VerticalLine));
 
-    if (this.eatQuantifier(true)) {
+    if (this.consumeQuantifier(true)) {
       this.raise("Nothing to repeat");
     }
 
@@ -70711,33 +70775,29 @@ class RegExpValidator {
     this.onDisjunctionLeave(start, this.index);
   }
 
-  alternative(i) {
+  consumeAlternative(i) {
     const start = this.index;
     this.onAlternativeEnter(start, i);
 
-    while (this.currentCodePoint !== -1 && this.eatTerm()) {}
+    while (this.currentCodePoint !== -1 && this.consumeTerm()) {}
 
     this.onAlternativeLeave(start, this.index, i);
   }
 
-  eatTerm() {
-    if (this.eatAssertion()) {
-      if (this._lastAssertionIsQuantifiable) {
-        this.eatQuantifier();
-      }
-
-      return true;
+  consumeTerm() {
+    if (this._uFlag || this.strict) {
+      return this.consumeAssertion() || this.consumeAtom() && this.consumeOptionalQuantifier();
     }
 
-    if (this.strict ? this.eatAtom() : this.eatExtendedAtom()) {
-      this.eatQuantifier();
-      return true;
-    }
+    return this.consumeAssertion() && (!this._lastAssertionIsQuantifiable || this.consumeOptionalQuantifier()) || this.consumeExtendedAtom() && this.consumeOptionalQuantifier();
+  }
 
-    return false;
+  consumeOptionalQuantifier() {
+    this.consumeQuantifier();
+    return true;
   }
 
-  eatAssertion() {
+  consumeAssertion() {
     const start = this.index;
     this._lastAssertionIsQuantifiable = false;
 
@@ -70768,7 +70828,7 @@ class RegExpValidator {
       if (this.eat(EqualsSign) || (negate = this.eat(ExclamationMark))) {
         const kind = lookbehind ? "lookbehind" : "lookahead";
         this.onLookaroundAssertionEnter(start, kind, negate);
-        this.disjunction();
+        this.consumeDisjunction();
 
         if (!this.eat(RightParenthesis)) {
           this.raise("Unterminated group");
@@ -70785,7 +70845,7 @@ class RegExpValidator {
     return false;
   }
 
-  eatQuantifier(noError = false) {
+  consumeQuantifier(noConsume = false) {
     const start = this.index;
     let min = 0;
     let max = 0;
@@ -70800,7 +70860,7 @@ class RegExpValidator {
     } else if (this.eat(QuestionMark)) {
       min = 0;
       max = 1;
-    } else if (this.eatBracedQuantifier(noError)) {
+    } else if (this.eatBracedQuantifier(noConsume)) {
       min = this._lastMinValue;
       max = this._lastMaxValue;
     } else {
@@ -70809,7 +70869,7 @@ class RegExpValidator {
 
     greedy = !this.eat(QuestionMark);
 
-    if (!noError) {
+    if (!noConsume) {
       this.onQuantifier(start, this.index, min, max, greedy);
     }
 
@@ -70839,7 +70899,7 @@ class RegExpValidator {
         }
       }
 
-      if (!noError && this.strict) {
+      if (!noError && (this._uFlag || this.strict)) {
         this.raise("Incomplete quantifier");
       }
 
@@ -70849,11 +70909,11 @@ class RegExpValidator {
     return false;
   }
 
-  eatAtom() {
-    return this.eatPatternCharacter() || this.eatDot() || this.eatReverseSolidusAtomEscape() || this.eatCharacterClass() || this.eatUncapturingGroup() || this.eatCapturingGroup();
+  consumeAtom() {
+    return this.consumePatternCharacter() || this.consumeDot() || this.consumeReverseSolidusAtomEscape() || this.consumeCharacterClass() || this.consumeUncapturingGroup() || this.consumeCapturingGroup();
   }
 
-  eatDot() {
+  consumeDot() {
     if (this.eat(FullStop)) {
       this.onAnyCharacterSet(this.index - 1, this.index, "any");
       return true;
@@ -70862,11 +70922,11 @@ class RegExpValidator {
     return false;
   }
 
-  eatReverseSolidusAtomEscape() {
+  consumeReverseSolidusAtomEscape() {
     const start = this.index;
 
     if (this.eat(ReverseSolidus)) {
-      if (this.eatAtomEscape()) {
+      if (this.consumeAtomEscape()) {
         return true;
       }
 
@@ -70876,12 +70936,12 @@ class RegExpValidator {
     return false;
   }
 
-  eatUncapturingGroup() {
+  consumeUncapturingGroup() {
     const start = this.index;
 
     if (this.eat3(LeftParenthesis, QuestionMark, Colon)) {
       this.onGroupEnter(start);
-      this.disjunction();
+      this.consumeDisjunction();
 
       if (!this.eat(RightParenthesis)) {
         this.raise("Unterminated group");
@@ -70894,21 +70954,22 @@ class RegExpValidator {
     return false;
   }
 
-  eatCapturingGroup() {
+  consumeCapturingGroup() {
     const start = this.index;
 
     if (this.eat(LeftParenthesis)) {
-      this._lastStrValue = "";
+      let name = null;
 
       if (this.ecmaVersion >= 2018) {
-        this.groupSpecifier();
+        if (this.consumeGroupSpecifier()) {
+          name = this._lastStrValue;
+        }
       } else if (this.currentCodePoint === QuestionMark) {
         this.raise("Invalid group");
       }
 
-      const name = this._lastStrValue || null;
       this.onCapturingGroupEnter(start, name);
-      this.disjunction();
+      this.consumeDisjunction();
 
       if (!this.eat(RightParenthesis)) {
         this.raise("Unterminated group");
@@ -70921,22 +70982,24 @@ class RegExpValidator {
     return false;
   }
 
-  eatExtendedAtom() {
-    return this.eatDot() || this.eatReverseSolidusAtomEscape() || this.eatReverseSolidusFollowedByC() || this.eatCharacterClass() || this.eatUncapturingGroup() || this.eatCapturingGroup() || this.eatInvalidBracedQuantifier() || this.eatExtendedPatternCharacter();
+  consumeExtendedAtom() {
+    return this.consumeDot() || this.consumeReverseSolidusAtomEscape() || this.consumeReverseSolidusFollowedByC() || this.consumeCharacterClass() || this.consumeUncapturingGroup() || this.consumeCapturingGroup() || this.consumeInvalidBracedQuantifier() || this.consumeExtendedPatternCharacter();
   }
 
-  eatReverseSolidusFollowedByC() {
+  consumeReverseSolidusFollowedByC() {
+    const start = this.index;
+
     if (this.currentCodePoint === ReverseSolidus && this.nextCodePoint === LatinSmallLetterC) {
       this._lastIntValue = this.currentCodePoint;
       this.advance();
-      this.onCharacter(this.index - 1, this.index, ReverseSolidus);
+      this.onCharacter(start, this.index, ReverseSolidus);
       return true;
     }
 
     return false;
   }
 
-  eatInvalidBracedQuantifier() {
+  consumeInvalidBracedQuantifier() {
     if (this.eatBracedQuantifier(true)) {
       this.raise("Nothing to repeat");
     }
@@ -70944,17 +71007,7 @@ class RegExpValidator {
     return false;
   }
 
-  eatSyntaxCharacter() {
-    if (isSyntaxCharacter(this.currentCodePoint)) {
-      this._lastIntValue = this.currentCodePoint;
-      this.advance();
-      return true;
-    }
-
-    return false;
-  }
-
-  eatPatternCharacter() {
+  consumePatternCharacter() {
     const start = this.index;
     const cp = this.currentCodePoint;
 
@@ -70967,7 +71020,7 @@ class RegExpValidator {
     return false;
   }
 
-  eatExtendedPatternCharacter() {
+  consumeExtendedPatternCharacter() {
     const start = this.index;
     const cp = this.currentCodePoint;
 
@@ -70980,15 +71033,13 @@ class RegExpValidator {
     return false;
   }
 
-  groupSpecifier() {
-    this._lastStrValue = "";
-
+  consumeGroupSpecifier() {
     if (this.eat(QuestionMark)) {
       if (this.eatGroupName()) {
         if (!this._groupNames.has(this._lastStrValue)) {
           this._groupNames.add(this._lastStrValue);
 
-          return;
+          return true;
         }
 
         this.raise("Duplicate capture group name");
@@ -70996,114 +71047,110 @@ class RegExpValidator {
 
       this.raise("Invalid group");
     }
-  }
 
-  eatGroupName() {
-    this._lastStrValue = "";
+    return false;
+  }
 
-    if (this.eat(LessThanSign)) {
-      if (this.eatRegExpIdentifierName() && this.eat(GreaterThanSign)) {
-        return true;
-      }
+  consumeAtomEscape() {
+    if (this.consumeBackreference() || this.consumeCharacterClassEscape() || this.consumeCharacterEscape() || this._nFlag && this.consumeKGroupName()) {
+      return true;
+    }
 
-      this.raise("Invalid capture group name");
+    if (this.strict || this._uFlag) {
+      this.raise("Invalid escape");
     }
 
     return false;
   }
 
-  eatRegExpIdentifierName() {
-    this._lastStrValue = "";
+  consumeBackreference() {
+    const start = this.index;
 
-    if (this.eatRegExpIdentifierStart()) {
-      this._lastStrValue += String.fromCodePoint(this._lastIntValue);
+    if (this.eatDecimalEscape()) {
+      const n = this._lastIntValue;
 
-      while (this.eatRegExpIdentifierPart()) {
-        this._lastStrValue += String.fromCodePoint(this._lastIntValue);
+      if (n <= this._numCapturingParens) {
+        this.onBackreference(start - 1, this.index, n);
+        return true;
       }
 
-      return true;
+      if (this.strict || this._uFlag) {
+        this.raise("Invalid escape");
+      }
+
+      this.rewind(start);
     }
 
     return false;
   }
 
-  eatRegExpIdentifierStart() {
+  consumeCharacterClassEscape() {
     const start = this.index;
-    let cp = this.currentCodePoint;
-    this.advance();
 
-    if (cp === ReverseSolidus && this.eatRegExpUnicodeEscapeSequence()) {
-      cp = this._lastIntValue;
+    if (this.eat(LatinSmallLetterD)) {
+      this._lastIntValue = -1;
+      this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
+      return true;
     }
 
-    if (isRegExpIdentifierStart(cp)) {
-      this._lastIntValue = cp;
+    if (this.eat(LatinCapitalLetterD)) {
+      this._lastIntValue = -1;
+      this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
       return true;
     }
 
-    if (this.index !== start) {
-      this.rewind(start);
+    if (this.eat(LatinSmallLetterS)) {
+      this._lastIntValue = -1;
+      this.onEscapeCharacterSet(start - 1, this.index, "space", false);
+      return true;
     }
 
-    return false;
-  }
-
-  eatRegExpIdentifierPart() {
-    const start = this.index;
-    let cp = this.currentCodePoint;
-    this.advance();
-
-    if (cp === ReverseSolidus && this.eatRegExpUnicodeEscapeSequence()) {
-      cp = this._lastIntValue;
+    if (this.eat(LatinCapitalLetterS)) {
+      this._lastIntValue = -1;
+      this.onEscapeCharacterSet(start - 1, this.index, "space", true);
+      return true;
     }
 
-    if (isRegExpIdentifierPart(cp)) {
-      this._lastIntValue = cp;
+    if (this.eat(LatinSmallLetterW)) {
+      this._lastIntValue = -1;
+      this.onEscapeCharacterSet(start - 1, this.index, "word", false);
       return true;
     }
 
-    if (this.index !== start) {
-      this.rewind(start);
+    if (this.eat(LatinCapitalLetterW)) {
+      this._lastIntValue = -1;
+      this.onEscapeCharacterSet(start - 1, this.index, "word", true);
+      return true;
     }
 
-    return false;
-  }
+    let negate = false;
 
-  eatAtomEscape() {
-    if (this.eatBackreference() || this.eatCharacterClassEscape() || this.eatCharacterEscape() || this._nFlag && this.eatKGroupName()) {
-      return true;
-    }
+    if (this._uFlag && this.ecmaVersion >= 2018 && (this.eat(LatinSmallLetterP) || (negate = this.eat(LatinCapitalLetterP)))) {
+      this._lastIntValue = -1;
 
-    if (this.strict || this._uFlag) {
-      this.raise("Invalid escape");
+      if (this.eat(LeftCurlyBracket) && this.eatUnicodePropertyValueExpression() && this.eat(RightCurlyBracket)) {
+        this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
+        return true;
+      }
+
+      this.raise("Invalid property name");
     }
 
     return false;
   }
 
-  eatBackreference() {
+  consumeCharacterEscape() {
     const start = this.index;
 
-    if (this.eatDecimalEscape()) {
-      const n = this._lastIntValue;
-
-      if (n <= this._numCapturingParens) {
-        this.onBackreference(start - 1, this.index, n);
-        return true;
-      }
-
-      if (this.strict) {
-        this.raise("Invalid escape");
-      }
-
-      this.rewind(start);
+    if (this.eatControlEscape() || this.eatCControlLetter() || this.eatZero() || this.eatHexEscapeSequence() || this.eatRegExpUnicodeEscapeSequence() || !this.strict && !this._uFlag && this.eatLegacyOctalEscapeSequence() || this.eatIdentityEscape()) {
+      this.onCharacter(start - 1, this.index, this._lastIntValue);
+      return true;
     }
 
     return false;
   }
 
-  eatKGroupName() {
+  consumeKGroupName() {
     const start = this.index;
 
     if (this.eat(LatinSmallLetterK)) {
@@ -71122,14 +71169,198 @@ class RegExpValidator {
     return false;
   }
 
-  eatCharacterEscape() {
+  consumeCharacterClass() {
     const start = this.index;
 
-    if (this.eatControlEscape() || this.eatCControlLetter() || this.eatZero() || this.eatHexEscapeSequence() || this.eatRegExpUnicodeEscapeSequence() || !this.strict && this.eatLegacyOctalEscapeSequence() || this.eatIdentityEscape()) {
+    if (this.eat(LeftSquareBracket)) {
+      const negate = this.eat(CircumflexAccent);
+      this.onCharacterClassEnter(start, negate);
+      this.consumeClassRanges();
+
+      if (!this.eat(RightSquareBracket)) {
+        this.raise("Unterminated character class");
+      }
+
+      this.onCharacterClassLeave(start, this.index, negate);
+      return true;
+    }
+
+    return false;
+  }
+
+  consumeClassRanges() {
+    const strict = this.strict || this._uFlag;
+
+    for (;;) {
+      const rangeStart = this.index;
+
+      if (!this.consumeClassAtom()) {
+        break;
+      }
+
+      const min = this._lastIntValue;
+
+      if (!this.eat(HyphenMinus)) {
+        continue;
+      }
+
+      this.onCharacter(this.index - 1, this.index, HyphenMinus);
+
+      if (!this.consumeClassAtom()) {
+        break;
+      }
+
+      const max = this._lastIntValue;
+
+      if (min === -1 || max === -1) {
+        if (strict) {
+          this.raise("Invalid character class");
+        }
+
+        continue;
+      }
+
+      if (min > max) {
+        this.raise("Range out of order in character class");
+      }
+
+      this.onCharacterClassRange(rangeStart, this.index, min, max);
+    }
+  }
+
+  consumeClassAtom() {
+    const start = this.index;
+    const cp = this.currentCodePoint;
+
+    if (cp !== -1 && cp !== ReverseSolidus && cp !== RightSquareBracket) {
+      this.advance();
+      this._lastIntValue = cp;
+      this.onCharacter(start, this.index, this._lastIntValue);
+      return true;
+    }
+
+    if (this.eat(ReverseSolidus)) {
+      if (this.consumeClassEscape()) {
+        return true;
+      }
+
+      if (!this.strict && this.currentCodePoint === LatinSmallLetterC) {
+        this._lastIntValue = ReverseSolidus;
+        this.onCharacter(start, this.index, this._lastIntValue);
+        return true;
+      }
+
+      if (this.strict || this._uFlag) {
+        this.raise("Invalid escape");
+      }
+
+      this.rewind(start);
+    }
+
+    return false;
+  }
+
+  consumeClassEscape() {
+    const start = this.index;
+
+    if (this.eat(LatinSmallLetterB)) {
+      this._lastIntValue = Backspace;
+      this.onCharacter(start - 1, this.index, this._lastIntValue);
+      return true;
+    }
+
+    if (this._uFlag && this.eat(HyphenMinus)) {
+      this._lastIntValue = HyphenMinus;
       this.onCharacter(start - 1, this.index, this._lastIntValue);
       return true;
     }
 
+    let cp = 0;
+
+    if (!this.strict && !this._uFlag && this.currentCodePoint === LatinSmallLetterC && (isDecimalDigit(cp = this.nextCodePoint) || cp === LowLine)) {
+      this.advance();
+      this.advance();
+      this._lastIntValue = cp % 0x20;
+      this.onCharacter(start - 1, this.index, this._lastIntValue);
+      return true;
+    }
+
+    return this.consumeCharacterClassEscape() || this.consumeCharacterEscape();
+  }
+
+  eatGroupName() {
+    if (this.eat(LessThanSign)) {
+      if (this.eatRegExpIdentifierName() && this.eat(GreaterThanSign)) {
+        return true;
+      }
+
+      this.raise("Invalid capture group name");
+    }
+
+    return false;
+  }
+
+  eatRegExpIdentifierName() {
+    if (this.eatRegExpIdentifierStart()) {
+      this._lastStrValue = String.fromCodePoint(this._lastIntValue);
+
+      while (this.eatRegExpIdentifierPart()) {
+        this._lastStrValue += String.fromCodePoint(this._lastIntValue);
+      }
+
+      return true;
+    }
+
+    return false;
+  }
+
+  eatRegExpIdentifierStart() {
+    const start = this.index;
+    const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
+    let cp = this.currentCodePoint;
+    this.advance();
+
+    if (cp === ReverseSolidus && this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
+      cp = this._lastIntValue;
+    } else if (forceUFlag && isLeadSurrogate(cp) && isTrailSurrogate(this.currentCodePoint)) {
+      cp = combineSurrogatePair(cp, this.currentCodePoint);
+      this.advance();
+    }
+
+    if (isRegExpIdentifierStart(cp)) {
+      this._lastIntValue = cp;
+      return true;
+    }
+
+    if (this.index !== start) {
+      this.rewind(start);
+    }
+
+    return false;
+  }
+
+  eatRegExpIdentifierPart() {
+    const start = this.index;
+    const forceUFlag = !this._uFlag && this.ecmaVersion >= 2020;
+    let cp = this.currentCodePoint;
+    this.advance();
+
+    if (cp === ReverseSolidus && this.eatRegExpUnicodeEscapeSequence(forceUFlag)) {
+      cp = this._lastIntValue;
+    } else if (forceUFlag && isLeadSurrogate(cp) && isTrailSurrogate(this.currentCodePoint)) {
+      cp = combineSurrogatePair(cp, this.currentCodePoint);
+      this.advance();
+    }
+
+    if (isRegExpIdentifierPart(cp)) {
+      this._lastIntValue = cp;
+      return true;
+    }
+
+    if (this.index !== start) {
+      this.rewind(start);
+    }
+
     return false;
   }
 
@@ -71158,8 +71389,8 @@ class RegExpValidator {
   }
 
   eatControlEscape() {
-    if (this.eat(LatinSmallLetterT)) {
-      this._lastIntValue = CharacterTabulation;
+    if (this.eat(LatinSmallLetterF)) {
+      this._lastIntValue = FormFeed;
       return true;
     }
 
@@ -71168,18 +71399,18 @@ class RegExpValidator {
       return true;
     }
 
-    if (this.eat(LatinSmallLetterV)) {
-      this._lastIntValue = LineTabulation;
+    if (this.eat(LatinSmallLetterR)) {
+      this._lastIntValue = CarriageReturn;
       return true;
     }
 
-    if (this.eat(LatinSmallLetterF)) {
-      this._lastIntValue = FormFeed;
+    if (this.eat(LatinSmallLetterT)) {
+      this._lastIntValue = CharacterTabulation;
       return true;
     }
 
-    if (this.eat(LatinSmallLetterR)) {
-      this._lastIntValue = CarriageReturn;
+    if (this.eat(LatinSmallLetterV)) {
+      this._lastIntValue = LineTabulation;
       return true;
     }
 
@@ -71198,38 +71429,38 @@ class RegExpValidator {
     return false;
   }
 
-  eatRegExpUnicodeEscapeSequence() {
+  eatRegExpUnicodeEscapeSequence(forceUFlag = false) {
     const start = this.index;
+    const uFlag = forceUFlag || this._uFlag;
 
     if (this.eat(LatinSmallLetterU)) {
-      if (this.eatFixedHexDigits(4)) {
-        const lead = this._lastIntValue;
+      if (uFlag && this.eatRegExpUnicodeSurrogatePairEscape() || this.eatFixedHexDigits(4) || uFlag && this.eatRegExpUnicodeCodePointEscape()) {
+        return true;
+      }
 
-        if (this._uFlag && lead >= 0xd800 && lead <= 0xdbff) {
-          const leadSurrogateEnd = this.index;
+      if (this.strict || uFlag) {
+        this.raise("Invalid unicode escape");
+      }
 
-          if (this.eat(ReverseSolidus) && this.eat(LatinSmallLetterU) && this.eatFixedHexDigits(4)) {
-            const trail = this._lastIntValue;
+      this.rewind(start);
+    }
 
-            if (trail >= 0xdc00 && trail <= 0xdfff) {
-              this._lastIntValue = (lead - 0xd800) * 0x400 + (trail - 0xdc00) + 0x10000;
-              return true;
-            }
-          }
+    return false;
+  }
 
-          this.rewind(leadSurrogateEnd);
-          this._lastIntValue = lead;
-        }
+  eatRegExpUnicodeSurrogatePairEscape() {
+    const start = this.index;
 
-        return true;
-      }
+    if (this.eatFixedHexDigits(4)) {
+      const lead = this._lastIntValue;
 
-      if (this._uFlag && this.eat(LeftCurlyBracket) && this.eatHexDigits() && this.eat(RightCurlyBracket) && isValidUnicode(this._lastIntValue)) {
-        return true;
-      }
+      if (isLeadSurrogate(lead) && this.eat(ReverseSolidus) && this.eat(LatinSmallLetterU) && this.eatFixedHexDigits(4)) {
+        const trail = this._lastIntValue;
 
-      if (this.strict || this._uFlag) {
-        this.raise("Invalid unicode escape");
+        if (isTrailSurrogate(trail)) {
+          this._lastIntValue = combineSurrogatePair(lead, trail);
+          return true;
+        }
       }
 
       this.rewind(start);
@@ -71238,22 +71469,22 @@ class RegExpValidator {
     return false;
   }
 
-  eatIdentityEscape() {
-    if (this._uFlag) {
-      if (this.eatSyntaxCharacter()) {
-        return true;
-      }
-
-      if (this.eat(Solidus)) {
-        this._lastIntValue = Solidus;
-        return true;
-      }
+  eatRegExpUnicodeCodePointEscape() {
+    const start = this.index;
 
-      return false;
+    if (this.eat(LeftCurlyBracket) && this.eatHexDigits() && this.eat(RightCurlyBracket) && isValidUnicode(this._lastIntValue)) {
+      return true;
     }
 
-    if (this.isValidIdentityEscape(this.currentCodePoint)) {
-      this._lastIntValue = this.currentCodePoint;
+    this.rewind(start);
+    return false;
+  }
+
+  eatIdentityEscape() {
+    const cp = this.currentCodePoint;
+
+    if (this.isValidIdentityEscape(cp)) {
+      this._lastIntValue = cp;
       this.advance();
       return true;
     }
@@ -71266,11 +71497,19 @@ class RegExpValidator {
       return false;
     }
 
+    if (this._uFlag) {
+      return isSyntaxCharacter(cp) || cp === Solidus;
+    }
+
     if (this.strict) {
       return !isIdContinue(cp);
     }
 
-    return cp !== LatinSmallLetterC && (!this._nFlag || cp !== LatinSmallLetterK);
+    if (this._nFlag) {
+      return !(cp === LatinSmallLetterC || cp === LatinSmallLetterK);
+    }
+
+    return cp !== LatinSmallLetterC;
   }
 
   eatDecimalEscape() {
@@ -71289,61 +71528,6 @@ class RegExpValidator {
     return false;
   }
 
-  eatCharacterClassEscape() {
-    const start = this.index;
-
-    if (this.eat(LatinSmallLetterD)) {
-      this._lastIntValue = -1;
-      this.onEscapeCharacterSet(start - 1, this.index, "digit", false);
-      return true;
-    }
-
-    if (this.eat(LatinCapitalLetterD)) {
-      this._lastIntValue = -1;
-      this.onEscapeCharacterSet(start - 1, this.index, "digit", true);
-      return true;
-    }
-
-    if (this.eat(LatinSmallLetterS)) {
-      this._lastIntValue = -1;
-      this.onEscapeCharacterSet(start - 1, this.index, "space", false);
-      return true;
-    }
-
-    if (this.eat(LatinCapitalLetterS)) {
-      this._lastIntValue = -1;
-      this.onEscapeCharacterSet(start - 1, this.index, "space", true);
-      return true;
-    }
-
-    if (this.eat(LatinSmallLetterW)) {
-      this._lastIntValue = -1;
-      this.onEscapeCharacterSet(start - 1, this.index, "word", false);
-      return true;
-    }
-
-    if (this.eat(LatinCapitalLetterW)) {
-      this._lastIntValue = -1;
-      this.onEscapeCharacterSet(start - 1, this.index, "word", true);
-      return true;
-    }
-
-    let negate = false;
-
-    if (this._uFlag && this.ecmaVersion >= 2018 && (this.eat(LatinSmallLetterP) || (negate = this.eat(LatinCapitalLetterP)))) {
-      this._lastIntValue = -1;
-
-      if (this.eat(LeftCurlyBracket) && this.eatUnicodePropertyValueExpression() && this.eat(RightCurlyBracket)) {
-        this.onUnicodePropertyCharacterSet(start - 1, this.index, "property", this._lastKeyValue, this._lastValValue || null, negate);
-        return true;
-      }
-
-      this.raise("Invalid property name");
-    }
-
-    return false;
-  }
-
   eatUnicodePropertyValueExpression() {
     const start = this.index;
 
@@ -71410,120 +71594,6 @@ class RegExpValidator {
     return this.eatUnicodePropertyValue();
   }
 
-  eatCharacterClass() {
-    const start = this.index;
-
-    if (this.eat(LeftSquareBracket)) {
-      const negate = this.eat(CircumflexAccent);
-      this.onCharacterClassEnter(start, negate);
-      this.classRanges();
-
-      if (!this.eat(RightSquareBracket)) {
-        this.raise("Unterminated character class");
-      }
-
-      this.onCharacterClassLeave(start, this.index, negate);
-      return true;
-    }
-
-    return false;
-  }
-
-  classRanges() {
-    let start = this.index;
-
-    while (this.eatClassAtom()) {
-      const left = this._lastIntValue;
-      const hyphenStart = this.index;
-
-      if (this.eat(HyphenMinus)) {
-        this.onCharacter(hyphenStart, this.index, HyphenMinus);
-
-        if (this.eatClassAtom()) {
-          const right = this._lastIntValue;
-
-          if (left === -1 || right === -1) {
-            if (this.strict) {
-              this.raise("Invalid character class");
-            }
-          } else if (left > right) {
-            this.raise("Range out of order in character class");
-          } else {
-            this.onCharacterClassRange(start, this.index, left, right);
-          }
-        }
-      }
-
-      start = this.index;
-    }
-  }
-
-  eatClassAtom() {
-    const start = this.index;
-
-    if (this.eat(ReverseSolidus)) {
-      if (this.eatClassEscape()) {
-        return true;
-      }
-
-      if (this._uFlag) {
-        this.raise("Invalid escape");
-      }
-
-      this.rewind(start);
-    }
-
-    const cp = this.currentCodePoint;
-
-    if (cp !== -1 && cp !== RightSquareBracket) {
-      this.advance();
-      this._lastIntValue = cp;
-      this.onCharacter(start, this.index, cp);
-      return true;
-    }
-
-    return false;
-  }
-
-  eatClassEscape() {
-    const start = this.index;
-
-    if (this.eat(LatinSmallLetterB)) {
-      this._lastIntValue = Backspace;
-      this.onCharacter(start - 1, this.index, Backspace);
-      return true;
-    }
-
-    if (this._uFlag && this.eat(HyphenMinus)) {
-      this._lastIntValue = HyphenMinus;
-      this.onCharacter(start - 1, this.index, HyphenMinus);
-      return true;
-    }
-
-    if (!this._uFlag && this.eat(LatinSmallLetterC)) {
-      if (this.eatClassControlLetter()) {
-        this.onCharacter(start - 1, this.index, this._lastIntValue);
-        return true;
-      }
-
-      this.rewind(start);
-    }
-
-    return this.eatCharacterClassEscape() || this.eatCharacterEscape();
-  }
-
-  eatClassControlLetter() {
-    const cp = this.currentCodePoint;
-
-    if (isDecimalDigit(cp) || cp === LowLine) {
-      this.advance();
-      this._lastIntValue = cp % 0x20;
-      return true;
-    }
-
-    return false;
-  }
-
   eatHexEscapeSequence() {
     const start = this.index;
 
@@ -71532,7 +71602,7 @@ class RegExpValidator {
         return true;
       }
 
-      if (this._uFlag) {
+      if (this._uFlag || this.strict) {
         this.raise("Invalid escape");
       }
 
@@ -73949,7 +74019,7 @@ module.exports = {
       if (allowed.indexOf(kind) === -1 && node.body.type === "BlockStatement" && node.body.body.length === 0 && innerComments.length === 0) {
         context.report({
           node,
-          loc: node.body.loc.start,
+          loc: node.body.loc,
           messageId: "unexpected",
           data: {
             name
@@ -77570,7 +77640,9 @@ module.exports = {
         tokensToIgnore.add(secondToken);
       }
 
-      if (hasExcessParens(node)) {
+      const hasExtraParens = node.parent.type === "ExportDefaultDeclaration" ? hasExcessParensWithPrecedence(node, PRECEDENCE_OF_ASSIGNMENT_EXPR) : hasExcessParens(node);
+
+      if (hasExtraParens) {
         report(node);
       }
     }
@@ -79424,9 +79496,16 @@ module.exports = {
  * @author Brandon Mills
  */
  //------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = __webpack_require__(426); //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
 
+
+const validParent = new Set(["Program", "ExportNamedDeclaration", "ExportDefaultDeclaration"]);
+const validBlockStatementParent = new Set(["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]);
 module.exports = {
   meta: {
     type: "problem",
@@ -79445,48 +79524,31 @@ module.exports = {
   },
 
   create(context) {
-    /**
-     * Find the nearest Program or Function ancestor node.
-     * @returns {Object} Ancestor's type and distance from node.
-     */
-    function nearestBody() {
-      const ancestors = context.getAncestors();
-      let ancestor = ancestors.pop(),
-          generation = 1;
-
-      while (ancestor && ["Program", "FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"].indexOf(ancestor.type) < 0) {
-        generation += 1;
-        ancestor = ancestors.pop();
-      }
-
-      return {
-        // Type of containing ancestor
-        type: ancestor.type,
-        // Separation between ancestor and node
-        distance: generation
-      };
-    }
     /**
      * Ensure that a given node is at a program or function body's root.
      * @param {ASTNode} node Declaration node to check.
      * @returns {void}
      */
-
-
     function check(node) {
-      const body = nearestBody(),
-            valid = body.type === "Program" && body.distance === 1 || body.distance === 2;
+      const parent = node.parent;
 
-      if (!valid) {
-        context.report({
-          node,
-          messageId: "moveDeclToRoot",
-          data: {
-            type: node.type === "FunctionDeclaration" ? "function" : "variable",
-            body: body.type === "Program" ? "program" : "function body"
-          }
-        });
+      if (parent.type === "BlockStatement" && validBlockStatementParent.has(parent.parent.type)) {
+        return;
+      }
+
+      if (validParent.has(parent.type)) {
+        return;
       }
+
+      const upperFunction = astUtils.getUpperFunction(parent);
+      context.report({
+        node,
+        messageId: "moveDeclToRoot",
+        data: {
+          type: node.type === "FunctionDeclaration" ? "function" : "variable",
+          body: upperFunction === null ? "program" : "function body"
+        }
+      });
     }
 
     return {
@@ -80353,7 +80415,7 @@ module.exports = {
       });
     }
     /**
-     * Checks for any ocurrence of a BlockStatement in a place where lists of statements can appear
+     * Checks for any occurrence of a BlockStatement in a place where lists of statements can appear
      * @param {ASTNode} node The node to check
      * @returns {boolean} True if the node is a lone block.
      */
@@ -81433,6 +81495,8 @@ module.exports = {
 
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/no-mixed-requires"],
     type: "suggestion",
     docs: {
       description: "disallow `require` calls to be mixed with regular variable declarations",
@@ -82510,9 +82574,14 @@ module.exports = {
  * @author Matt DuVall <http://www.mattduvall.com/>
  */
  //------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = __webpack_require__(426); //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
 
+
 module.exports = {
   meta: {
     type: "suggestion",
@@ -82531,6 +82600,12 @@ module.exports = {
   create(context) {
     return {
       NewExpression(node) {
+        const variable = astUtils.getVariableByName(context.getScope(), node.callee.name);
+
+        if (variable && variable.identifiers.length > 0) {
+          return;
+        }
+
         if (node.callee.name === "Object") {
           context.report({
             node,
@@ -82559,6 +82634,8 @@ module.exports = {
 
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/no-new-require"],
     type: "suggestion",
     docs: {
       description: "disallow `new` operators with calls to `require`",
@@ -83125,6 +83202,8 @@ module.exports = {
 
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/no-path-concat"],
     type: "suggestion",
     docs: {
       description: "disallow string concatenation with `__dirname` and `__filename`",
@@ -83277,6 +83356,8 @@ module.exports = {
 
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/no-process-env"],
     type: "suggestion",
     docs: {
       description: "disallow the use of `process.env`",
@@ -83324,6 +83405,8 @@ module.exports = {
 
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/no-process-exit"],
     type: "suggestion",
     docs: {
       description: "disallow the use of `process.exit()`",
@@ -84636,6 +84719,8 @@ const arrayOfStringsOrObjects = {
 };
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/no-restricted-require"],
     type: "suggestion",
     docs: {
       description: "disallow specified modules when loaded by `require`",
@@ -86251,6 +86336,8 @@ module.exports = {
 
 module.exports = {
   meta: {
+    deprecated: true,
+    replacedBy: ["node/no-sync"],
     type: "suggestion",
     docs: {
       description: "disallow synchronous methods",
@@ -87490,11 +87577,8 @@ module.exports = {
       if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) {
         context.report({
           node,
-          loc: openParen.loc.start,
-          messageId,
-          data: {
-            char: openParen.value
-          }
+          loc: openParen.loc,
+          messageId
         });
       }
     } //--------------------------------------------------------------------------
@@ -87512,22 +87596,25 @@ module.exports = {
       },
 
       TaggedTemplateExpression(node) {
-        if (node.tag.loc.end.line === node.quasi.loc.start.line) {
-          return;
-        } // handle generics type parameters on template tags
-
+        const {
+          quasi
+        } = node; // handles common tags, parenthesized tags, and typescript's generic type arguments
 
-        const tokenBefore = sourceCode.getTokenBefore(node.quasi);
+        const tokenBefore = sourceCode.getTokenBefore(quasi);
 
-        if (tokenBefore.loc.end.line === node.quasi.loc.start.line) {
-          return;
+        if (tokenBefore.loc.end.line !== quasi.loc.start.line) {
+          context.report({
+            node,
+            loc: {
+              start: quasi.loc.start,
+              end: {
+                line: quasi.loc.start.line,
+                column: quasi.loc.start.column + 1
+              }
+            },
+            messageId: "taggedTemplate"
+          });
         }
-
-        context.report({
-          node,
-          loc: node.loc.start,
-          messageId: "taggedTemplate"
-        });
       },
 
       CallExpression(node) {
@@ -90380,7 +90467,7 @@ module.exports = {
           const operatorToken = sourceCode.getFirstTokenBetween(left, right, isConcatOperatorToken);
           context.report({
             node,
-            loc: operatorToken.loc.start,
+            loc: operatorToken.loc,
             messageId: "unexpectedConcat"
           });
         }
@@ -101092,7 +101179,10 @@ module.exports = {
       if (hasSpacing && functionConfig === "never") {
         context.report({
           node,
-          loc: leftToken.loc.end,
+          loc: {
+            start: leftToken.loc.end,
+            end: rightToken.loc.start
+          },
           messageId: "unexpectedSpace",
 
           fix(fixer) {
@@ -101109,7 +101199,7 @@ module.exports = {
       } else if (!hasSpacing && functionConfig === "always") {
         context.report({
           node,
-          loc: leftToken.loc.end,
+          loc: rightToken.loc,
           messageId: "missingSpace",
           fix: fixer => fixer.insertTextAfter(leftToken, " ")
         });
@@ -106319,7 +106409,7 @@ module.exports = {
 /* 719 */
 /***/ (function(module) {
 
-module.exports = JSON.parse("{\"_from\":\"doctrine@^3.0.0\",\"_id\":\"doctrine@3.0.0\",\"_inBundle\":false,\"_integrity\":\"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==\",\"_location\":\"/doctrine\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"doctrine@^3.0.0\",\"name\":\"doctrine\",\"escapedName\":\"doctrine\",\"rawSpec\":\"^3.0.0\",\"saveSpec\":null,\"fetchSpec\":\"^3.0.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz\",\"_shasum\":\"addebead72a6574db783639dc87a121773973961\",\"_spec\":\"doctrine@^3.0.0\",\"_where\":\"/home/dcsapak/git/pve-eslint/eslint-v7.0.0-alpha.3\",\"bugs\":{\"url\":\"https://github.com/eslint/doctrine/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"esutils\":\"^2.0.2\"},\"deprecated\":false,\"description\":\"JSDoc parser\",\"devDependencies\":{\"coveralls\":\"^3.0.1\",\"dateformat\":\"^1.0.11\",\"eslint\":\"^1.10.3\",\"eslint-release\":\"^1.0.0\",\"linefix\":\"^0.1.1\",\"mocha\":\"^3.4.2\",\"npm-license\":\"^0.3.1\",\"nyc\":\"^10.3.2\",\"semver\":\"^5.0.3\",\"shelljs\":\"^0.5.3\",\"shelljs-nodecli\":\"^0.1.1\",\"should\":\"^5.0.1\"},\"directories\":{\"lib\":\"./lib\"},\"engines\":{\"node\":\">=6.0.0\"},\"files\":[\"lib\"],\"homepage\":\"https://github.com/eslint/doctrine\",\"license\":\"Apache-2.0\",\"main\":\"lib/doctrine.js\",\"maintainers\":[{\"name\":\"Nicholas C. Zakas\",\"email\":\"nicholas+npm@nczconsulting.com\",\"url\":\"https://www.nczonline.net\"},{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"https://github.com/Constellation\"}],\"name\":\"doctrine\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/doctrine.git\"},\"scripts\":{\"coveralls\":\"nyc report --reporter=text-lcov | coveralls\",\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"eslint lib/\",\"pretest\":\"npm run lint\",\"publish-release\":\"eslint-publish-release\",\"test\":\"nyc mocha\"},\"version\":\"3.0.0\"}");
+module.exports = JSON.parse("{\"_from\":\"doctrine@^3.0.0\",\"_id\":\"doctrine@3.0.0\",\"_inBundle\":false,\"_integrity\":\"sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==\",\"_location\":\"/doctrine\",\"_phantomChildren\":{},\"_requested\":{\"type\":\"range\",\"registry\":true,\"raw\":\"doctrine@^3.0.0\",\"name\":\"doctrine\",\"escapedName\":\"doctrine\",\"rawSpec\":\"^3.0.0\",\"saveSpec\":null,\"fetchSpec\":\"^3.0.0\"},\"_requiredBy\":[\"/\",\"/eslint\"],\"_resolved\":\"https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz\",\"_shasum\":\"addebead72a6574db783639dc87a121773973961\",\"_spec\":\"doctrine@^3.0.0\",\"_where\":\"/home/dcsapak/git/pve-eslint/eslint-v7.0.0\",\"bugs\":{\"url\":\"https://github.com/eslint/doctrine/issues\"},\"bundleDependencies\":false,\"dependencies\":{\"esutils\":\"^2.0.2\"},\"deprecated\":false,\"description\":\"JSDoc parser\",\"devDependencies\":{\"coveralls\":\"^3.0.1\",\"dateformat\":\"^1.0.11\",\"eslint\":\"^1.10.3\",\"eslint-release\":\"^1.0.0\",\"linefix\":\"^0.1.1\",\"mocha\":\"^3.4.2\",\"npm-license\":\"^0.3.1\",\"nyc\":\"^10.3.2\",\"semver\":\"^5.0.3\",\"shelljs\":\"^0.5.3\",\"shelljs-nodecli\":\"^0.1.1\",\"should\":\"^5.0.1\"},\"directories\":{\"lib\":\"./lib\"},\"engines\":{\"node\":\">=6.0.0\"},\"files\":[\"lib\"],\"homepage\":\"https://github.com/eslint/doctrine\",\"license\":\"Apache-2.0\",\"main\":\"lib/doctrine.js\",\"maintainers\":[{\"name\":\"Nicholas C. Zakas\",\"email\":\"nicholas+npm@nczconsulting.com\",\"url\":\"https://www.nczonline.net\"},{\"name\":\"Yusuke Suzuki\",\"email\":\"utatane.tea@gmail.com\",\"url\":\"https://github.com/Constellation\"}],\"name\":\"doctrine\",\"repository\":{\"type\":\"git\",\"url\":\"git+https://github.com/eslint/doctrine.git\"},\"scripts\":{\"coveralls\":\"nyc report --reporter=text-lcov | coveralls\",\"generate-alpharelease\":\"eslint-generate-prerelease alpha\",\"generate-betarelease\":\"eslint-generate-prerelease beta\",\"generate-rcrelease\":\"eslint-generate-prerelease rc\",\"generate-release\":\"eslint-generate-release\",\"lint\":\"eslint lib/\",\"pretest\":\"npm run lint\",\"publish-release\":\"eslint-publish-release\",\"test\":\"nyc mocha\"},\"version\":\"3.0.0\"}");
 
 /***/ }),
 /* 720 */
@@ -107019,20 +107109,17 @@ function looksLikeLiteral(node) {
 /**
  * Attempts to derive a Literal node from nodes that are treated like literals.
  * @param {ASTNode} node Node to normalize.
- * @param {number} [defaultValue] The default value to be returned if the node
- *                                is not a Literal.
  * @returns {ASTNode} One of the following options.
  *  1. The original node if the node is already a Literal
  *  2. A normalized Literal node with the negative number as the value if the
  *     node represents a negative number literal.
  *  3. A normalized Literal node with the string as the value if the node is
  *     a Template Literal without expression.
- *  4. The Literal node which has the `defaultValue` argument if it exists.
- *  5. Otherwise `null`.
+ *  4. Otherwise `null`.
  */
 
 
-function getNormalizedLiteral(node, defaultValue) {
+function getNormalizedLiteral(node) {
   if (node.type === "Literal") {
     return node;
   }
@@ -107053,14 +107140,6 @@ function getNormalizedLiteral(node, defaultValue) {
     };
   }
 
-  if (defaultValue) {
-    return {
-      type: "Literal",
-      value: defaultValue,
-      raw: String(defaultValue)
-    };
-  }
-
   return null;
 }
 /**
@@ -107119,7 +107198,7 @@ module.exports = {
   meta: {
     type: "suggestion",
     docs: {
-      description: "require or disallow \"Yoda\" conditions",
+      description: 'require or disallow "Yoda" conditions',
       category: "Best Practices",
       recommended: false,
       url: "https://eslint.org/docs/rules/yoda"
@@ -107172,8 +107251,24 @@ module.exports = {
        */
 
       function isBetweenTest() {
-        let leftLiteral, rightLiteral;
-        return node.operator === "&&" && (leftLiteral = getNormalizedLiteral(left.left)) && (rightLiteral = getNormalizedLiteral(right.right, Number.POSITIVE_INFINITY)) && leftLiteral.value <= rightLiteral.value && same(left.right, right.left);
+        if (node.operator === "&&" && same(left.right, right.left)) {
+          const leftLiteral = getNormalizedLiteral(left.left);
+          const rightLiteral = getNormalizedLiteral(right.right);
+
+          if (leftLiteral === null && rightLiteral === null) {
+            return false;
+          }
+
+          if (rightLiteral === null || leftLiteral === null) {
+            return true;
+          }
+
+          if (leftLiteral.value <= rightLiteral.value) {
+            return true;
+          }
+        }
+
+        return false;
       }
       /**
        * Determines whether node is of the form `x < 0 || 1 <= x`.
@@ -107182,8 +107277,24 @@ module.exports = {
 
 
       function isOutsideTest() {
-        let leftLiteral, rightLiteral;
-        return node.operator === "||" && (leftLiteral = getNormalizedLiteral(left.right, Number.NEGATIVE_INFINITY)) && (rightLiteral = getNormalizedLiteral(right.left)) && leftLiteral.value <= rightLiteral.value && same(left.left, right.right);
+        if (node.operator === "||" && same(left.left, right.right)) {
+          const leftLiteral = getNormalizedLiteral(left.right);
+          const rightLiteral = getNormalizedLiteral(right.left);
+
+          if (leftLiteral === null && rightLiteral === null) {
+            return false;
+          }
+
+          if (rightLiteral === null || leftLiteral === null) {
+            return true;
+          }
+
+          if (leftLiteral.value <= rightLiteral.value) {
+            return true;
+          }
+        }
+
+        return false;
       }
       /**
        * Determines whether node is wrapped in parentheses.
@@ -120712,13 +120823,13 @@ module.exports = class ConfigCommentParser {
 /* 799 */
 /***/ (function(module, exports, __webpack_require__) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 (function () {
   var parseString, cast, parseType, VERSION, parsedTypeParse, parse;
   parseString = __webpack_require__(800);
   cast = __webpack_require__(807);
   parseType = __webpack_require__(808).parseType;
-  VERSION = '0.3.0';
+  VERSION = '0.4.1';
 
   parsedTypeParse = function parsedTypeParse(parsedType, string, options) {
     options == null && (options = {});
@@ -120742,7 +120853,7 @@ module.exports = class ConfigCommentParser {
 /* 800 */
 /***/ (function(module, exports, __webpack_require__) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 (function () {
   var reject, special, tokenRegex;
   reject = __webpack_require__(801).reject;
@@ -120867,7 +120978,7 @@ module.exports = class ConfigCommentParser {
     options == null && (options = {});
 
     if (!options.explicit && types.length === 1 && types[0].type === 'String') {
-      return "'" + string.replace(/\\'/g, "\\\\'") + "'";
+      return string;
     }
 
     tokens = reject(not$, string.split(tokenRegex));
@@ -120889,7 +121000,7 @@ module.exports = class ConfigCommentParser {
 /* 801 */
 /***/ (function(module, exports, __webpack_require__) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 var Func,
     List,
     Obj,
@@ -121066,7 +121177,7 @@ prelude.even = Num.even;
 prelude.odd = Num.odd;
 prelude.gcd = Num.gcd;
 prelude.lcm = Num.lcm;
-prelude.VERSION = '1.1.2';
+prelude.VERSION = '1.2.1';
 module.exports = prelude;
 
 function curry$(f, bound) {
@@ -121086,14 +121197,13 @@ function curry$(f, bound) {
 /* 802 */
 /***/ (function(module, exports) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 var apply,
     curry,
     flip,
     fix,
     over,
     memoize,
-    slice$ = [].slice,
     toString$ = {}.toString;
 apply = curry$(function (f, list) {
   return f.apply(null, list);
@@ -121127,8 +121237,14 @@ memoize = function memoize(f) {
   var memo;
   memo = {};
   return function () {
-    var args, key, arg;
-    args = slice$.call(arguments);
+    var args, res$, i$, to$, key, arg;
+    res$ = [];
+
+    for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
+      res$.push(arguments[i$]);
+    }
+
+    args = res$;
 
     key = function () {
       var i$,
@@ -121174,12 +121290,13 @@ function curry$(f, bound) {
 /* 803 */
 /***/ (function(module, exports) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 var each,
     map,
     compact,
     filter,
     reject,
+    remove,
     partition,
     find,
     head,
@@ -121244,8 +121361,7 @@ var each,
     elemIndices,
     findIndex,
     findIndices,
-    toString$ = {}.toString,
-    slice$ = [].slice;
+    toString$ = {}.toString;
 
 each = curry$(function (f, xs) {
   var i$, len$, x;
@@ -121320,6 +121436,17 @@ reject = curry$(function (f, xs) {
 
   return results$;
 });
+remove = curry$(function (el, xs) {
+  var i, x$;
+  i = elemIndex(el, xs);
+  x$ = xs.slice();
+
+  if (i != null) {
+    x$.splice(i, 1);
+  }
+
+  return x$;
+});
 partition = curry$(function (f, xs) {
   var passed, failed, i$, len$, x;
   passed = [];
@@ -121497,8 +121624,14 @@ _flatten = function flatten(xs) {
 };
 
 difference = function difference(xs) {
-  var yss, results, i$, len$, x, j$, len1$, ys;
-  yss = slice$.call(arguments, 1);
+  var yss, res$, i$, to$, results, len$, x, j$, len1$, ys;
+  res$ = [];
+
+  for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
+    res$.push(arguments[i$]);
+  }
+
+  yss = res$;
   results = [];
 
   outer: for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
@@ -121519,8 +121652,14 @@ difference = function difference(xs) {
 };
 
 intersection = function intersection(xs) {
-  var yss, results, i$, len$, x, j$, len1$, ys;
-  yss = slice$.call(arguments, 1);
+  var yss, res$, i$, to$, results, len$, x, j$, len1$, ys;
+  res$ = [];
+
+  for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
+    res$.push(arguments[i$]);
+  }
+
+  yss = res$;
   results = [];
 
   outer: for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
@@ -121541,8 +121680,14 @@ intersection = function intersection(xs) {
 };
 
 union = function union() {
-  var xss, results, i$, len$, xs, j$, len1$, x;
-  xss = slice$.call(arguments);
+  var xss, res$, i$, to$, results, len$, xs, j$, len1$, x;
+  res$ = [];
+
+  for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
+    res$.push(arguments[i$]);
+  }
+
+  xss = res$;
   results = [];
 
   for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
@@ -121904,8 +122049,10 @@ zipWith = curry$(function (f, xs, ys) {
 
 zipAll = function zipAll() {
   var xss,
-      minLength,
+      res$,
       i$,
+      to$,
+      minLength,
       len$,
       xs,
       ref$,
@@ -121913,7 +122060,13 @@ zipAll = function zipAll() {
       lresult$,
       j$,
       results$ = [];
-  xss = slice$.call(arguments);
+  res$ = [];
+
+  for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
+    res$.push(arguments[i$]);
+  }
+
+  xss = res$;
   minLength = undefined;
 
   for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
@@ -121938,14 +122091,22 @@ zipAll = function zipAll() {
 
 zipAllWith = function zipAllWith(f) {
   var xss,
-      minLength,
+      res$,
       i$,
+      to$,
+      minLength,
       len$,
       xs,
       ref$,
       i,
       results$ = [];
-  xss = slice$.call(arguments, 1);
+  res$ = [];
+
+  for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
+    res$.push(arguments[i$]);
+  }
+
+  xss = res$;
   minLength = undefined;
 
   for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
@@ -122048,6 +122209,7 @@ module.exports = {
   filter: filter,
   compact: compact,
   reject: reject,
+  remove: remove,
   partition: partition,
   find: find,
   head: head,
@@ -122158,7 +122320,7 @@ function not$(x) {
 /* 804 */
 /***/ (function(module, exports) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 var values, keys, pairsToObj, objToPairs, listsToObj, objToLists, empty, each, map, compact, filter, reject, partition, find;
 
 values = function values(object) {
@@ -122378,7 +122540,7 @@ function curry$(f, bound) {
 /* 805 */
 /***/ (function(module, exports) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 var split, join, lines, unlines, words, unwords, chars, unchars, reverse, repeat, capitalize, camelize, dasherize;
 split = curry$(function (sep, str) {
   return str.split(sep);
@@ -122489,7 +122651,7 @@ function curry$(f, bound) {
 /* 806 */
 /***/ (function(module, exports) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 var max, min, negate, abs, signum, quot, rem, div, mod, recip, pi, tau, exp, sqrt, ln, pow, sin, tan, cos, asin, acos, atan, atan2, truncate, round, ceiling, floor, isItNaN, even, odd, gcd, lcm;
 max = curry$(function (x$, y$) {
   return x$ > y$ ? x$ : y$;
@@ -122638,7 +122800,7 @@ function curry$(f, bound) {
 /* 807 */
 /***/ (function(module, exports, __webpack_require__) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 (function () {
   var parsedTypeCheck,
       types,
@@ -122836,7 +122998,7 @@ function curry$(f, bound) {
       }, options);
     },
     String: function String(it) {
-      var that;
+      var replace, that;
 
       if (toString$.call(it).slice(8, -1) !== 'String') {
         return {
@@ -122844,15 +123006,48 @@ function curry$(f, bound) {
         };
       }
 
+      replace = function replace(value, quote) {
+        return value.replace(/\\([^u]|u[0-9a-fA-F]{4})/g, function (all, escaped) {
+          switch (escaped[0]) {
+            case quote:
+              return quote;
+
+            case '\\':
+              return '\\';
+
+            case 'b':
+              return '\b';
+
+            case 'f':
+              return '\f';
+
+            case 'n':
+              return '\n';
+
+            case 'r':
+              return '\r';
+
+            case 't':
+              return '\t';
+
+            case 'u':
+              return JSON.parse("\"" + all + "\"");
+
+            default:
+              return escaped;
+          }
+        });
+      };
+
       if (that = it.match(/^'([\s\S]*)'$/)) {
         return {
           type: 'Just',
-          value: that[1].replace(/\\'/g, "'")
+          value: replace(that[1], "'")
         };
       } else if (that = it.match(/^"([\s\S]*)"$/)) {
         return {
           type: 'Just',
-          value: that[1].replace(/\\"/g, '"')
+          value: replace(that[1], '"')
         };
       } else {
         return {
@@ -123003,17 +123198,23 @@ function curry$(f, bound) {
     throw new Error("Value " + JSON.stringify(node) + " does not type check against " + JSON.stringify(types) + ".");
   }
 
-  module.exports = typesCast;
+  module.exports = function (node, types, options) {
+    if (!options.explicit && types.length === 1 && types[0].type === 'String') {
+      return node;
+    }
+
+    return typesCast(node, types, options);
+  };
 }).call(this);
 
 /***/ }),
 /* 808 */
 /***/ (function(module, exports, __webpack_require__) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 (function () {
   var VERSION, parseType, parsedTypeCheck, typeCheck;
-  VERSION = '0.3.2';
+  VERSION = '0.4.0';
   parseType = __webpack_require__(809);
   parsedTypeCheck = __webpack_require__(810);
 
@@ -123033,7 +123234,7 @@ function curry$(f, bound) {
 /* 809 */
 /***/ (function(module, exports) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 (function () {
   var identifierRegex, tokenRegex;
   identifierRegex = /[\$\w]+/;
@@ -123201,7 +123402,7 @@ function curry$(f, bound) {
   }
 
   function consumeTypes(tokens) {
-    var lookahead, types, typesSoFar, typeObj, type;
+    var lookahead, types, typesSoFar, typeObj, type, structure;
 
     if ('::' === peek(tokens)) {
       throw new Error("No comment before comment separator '::' found.");
@@ -123231,13 +123432,15 @@ function curry$(f, bound) {
     }
 
     for (;;) {
-      typeObj = consumeType(tokens), type = typeObj.type;
+      typeObj = consumeType(tokens), type = typeObj.type, structure = typeObj.structure;
 
       if (!typesSoFar[type]) {
         types.push(typeObj);
       }
 
-      typesSoFar[type] = true;
+      if (structure == null) {
+        typesSoFar[type] = true;
+      }
 
       if (!maybeConsumeOp(tokens, '|')) {
         break;
@@ -123284,7 +123487,7 @@ function curry$(f, bound) {
 /* 810 */
 /***/ (function(module, exports, __webpack_require__) {
 
-// Generated by LiveScript 1.4.0
+// Generated by LiveScript 1.6.0
 (function () {
   var ref$,
       any,
@@ -123292,7 +123495,6 @@ function curry$(f, bound) {
       isItNaN,
       types,
       defaultType,
-      customTypes,
       toString$ = {}.toString;
   ref$ = __webpack_require__(801), any = ref$.any, all = ref$.all, isItNaN = ref$.isItNaN;
   types = {
@@ -123330,20 +123532,20 @@ function curry$(f, bound) {
     tuple: 'Array'
   };
 
-  function checkArray(input, type) {
+  function checkArray(input, type, options) {
     return all(function (it) {
-      return checkMultiple(it, type.of);
+      return checkMultiple(it, type.of, options);
     }, input);
   }
 
-  function checkTuple(input, type) {
+  function checkTuple(input, type, options) {
     var i, i$, ref$, len$, types;
     i = 0;
 
     for (i$ = 0, len$ = (ref$ = type.of).length; i$ < len$; ++i$) {
       types = ref$[i$];
 
-      if (!checkMultiple(input[i], types)) {
+      if (!checkMultiple(input[i], types, options)) {
         return false;
       }
 
@@ -123353,7 +123555,7 @@ function curry$(f, bound) {
     return input.length <= i;
   }
 
-  function checkFields(input, type) {
+  function checkFields(input, type, options) {
     var inputKeys, numInputKeys, k, numOfKeys, key, ref$, types;
     inputKeys = {};
     numInputKeys = 0;
@@ -123368,7 +123570,7 @@ function curry$(f, bound) {
     for (key in ref$ = type.of) {
       types = ref$[key];
 
-      if (!checkMultiple(input[key], types)) {
+      if (!checkMultiple(input[key], types, options)) {
         return false;
       }
 
@@ -123380,24 +123582,24 @@ function curry$(f, bound) {
     return type.subset || numInputKeys === numOfKeys;
   }
 
-  function checkStructure(input, type) {
+  function checkStructure(input, type, options) {
     if (!(input instanceof Object)) {
       return false;
     }
 
     switch (type.structure) {
       case 'fields':
-        return checkFields(input, type);
+        return checkFields(input, type, options);
 
       case 'array':
-        return checkArray(input, type);
+        return checkArray(input, type, options);
 
       case 'tuple':
-        return checkTuple(input, type);
+        return checkTuple(input, type, options);
     }
   }
 
-  function check(input, typeObj) {
+  function check(input, typeObj, options) {
     var type, structure, setting, that;
     type = typeObj.type, structure = typeObj.structure;
 
@@ -123406,12 +123608,12 @@ function curry$(f, bound) {
         return true;
       }
 
-      setting = customTypes[type] || types[type];
+      setting = options.customTypes[type] || types[type];
 
       if (setting) {
-        return setting.typeOf === toString$.call(input).slice(8, -1) && setting.validate(input);
+        return (setting.typeOf === void 8 || setting.typeOf === toString$.call(input).slice(8, -1)) && setting.validate(input);
       } else {
-        return type === toString$.call(input).slice(8, -1) && (!structure || checkStructure(input, typeObj));
+        return type === toString$.call(input).slice(8, -1) && (!structure || checkStructure(input, typeObj, options));
       }
     } else if (structure) {
       if (that = defaultType[structure]) {
@@ -123420,26 +123622,30 @@ function curry$(f, bound) {
         }
       }
 
-      return checkStructure(input, typeObj);
+      return checkStructure(input, typeObj, options);
     } else {
       throw new Error("No type defined. Input: " + input + ".");
     }
   }
 
-  function checkMultiple(input, types) {
+  function checkMultiple(input, types, options) {
     if (toString$.call(types).slice(8, -1) !== 'Array') {
       throw new Error("Types must be in an array. Input: " + input + ".");
     }
 
     return any(function (it) {
-      return check(input, it);
+      return check(input, it, options);
     }, types);
   }
 
   module.exports = function (parsedType, input, options) {
     options == null && (options = {});
-    customTypes = options.customTypes || {};
-    return checkMultiple(input, parsedType);
+
+    if (options.customTypes == null) {
+      options.customTypes = {};
+    }
+
+    return checkMultiple(input, parsedType, options);
   };
 }).call(this);
 
@@ -123770,17 +123976,79 @@ module.exports = NodeEventGenerator;
 }(this, function () {
   "use strict";
 
+  function e(t) {
+    return (e = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (e) {
+      return typeof e;
+    } : function (e) {
+      return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e;
+    })(t);
+  }
+
+  function t(e, t) {
+    return function (e) {
+      if (Array.isArray(e)) return e;
+    }(e) || function (e, t) {
+      if ("undefined" == typeof Symbol || !(Symbol.iterator in Object(e))) return;
+      var r = [],
+          n = !0,
+          o = !1,
+          a = void 0;
+
+      try {
+        for (var s, i = e[Symbol.iterator](); !(n = (s = i.next()).done) && (r.push(s.value), !t || r.length !== t); n = !0);
+      } catch (e) {
+        o = !0, a = e;
+      } finally {
+        try {
+          n || null == i.return || i.return();
+        } finally {
+          if (o) throw a;
+        }
+      }
+
+      return r;
+    }(e, t) || n(e, t) || function () {
+      throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+    }();
+  }
+
+  function r(e) {
+    return function (e) {
+      if (Array.isArray(e)) return o(e);
+    }(e) || function (e) {
+      if ("undefined" != typeof Symbol && Symbol.iterator in Object(e)) return Array.from(e);
+    }(e) || n(e) || function () {
+      throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
+    }();
+  }
+
+  function n(e, t) {
+    if (e) {
+      if ("string" == typeof e) return o(e, t);
+      var r = Object.prototype.toString.call(e).slice(8, -1);
+      return "Object" === r && e.constructor && (r = e.constructor.name), "Map" === r || "Set" === r ? Array.from(r) : "Arguments" === r || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r) ? o(e, t) : void 0;
+    }
+  }
+
+  function o(e, t) {
+    (null == t || t > e.length) && (t = e.length);
+
+    for (var r = 0, n = new Array(t); r < t; r++) n[r] = e[r];
+
+    return n;
+  }
+
   "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self && self;
 
-  function e(e, t) {
+  function a(e, t) {
     return e(t = {
       exports: {}
     }, t.exports), t.exports;
   }
 
-  var t = e(function (e, t) {
+  var s = a(function (e, t) {
     !function e(t) {
-      var r, n, s, o, a, i;
+      var r, n, o, a, s, i;
 
       function l(e) {
         var t,
@@ -123800,9 +124068,9 @@ module.exports = NodeEventGenerator;
         this.node = e, this.path = t, this.wrap = r, this.ref = n;
       }
 
-      function p() {}
+      function f() {}
 
-      function f(e) {
+      function p(e) {
         return null != e && "object" == typeof e && "string" == typeof e.type;
       }
 
@@ -123811,17 +124079,23 @@ module.exports = NodeEventGenerator;
       }
 
       function d(e, t) {
-        return new p().traverse(e, t);
+        for (var r = e.length - 1; r >= 0; --r) if (e[r].node === t) return !0;
+
+        return !1;
       }
 
-      function x(e, t) {
+      function y(e, t) {
+        return new f().traverse(e, t);
+      }
+
+      function m(e, t) {
         var r;
         return r = function (e, t) {
-          var r, n, s, o;
+          var r, n, o, a;
 
-          for (n = e.length, s = 0; n;) t(e[o = s + (r = n >>> 1)]) ? n = r : (s = o + 1, n -= r + 1);
+          for (n = e.length, o = 0; n;) t(e[a = o + (r = n >>> 1)]) ? n = r : (o = a + 1, n -= r + 1);
 
-          return s;
+          return o;
         }(t, function (t) {
           return t.range[0] > e.range[0];
         }), e.extendedRange = [e.range[0], e.range[1]], r !== t.length && (e.extendedRange[1] = t[r].range[0]), (r -= 1) >= 0 && (e.extendedRange[0] = t[r].range[1]), e;
@@ -123900,7 +124174,7 @@ module.exports = NodeEventGenerator;
         WhileStatement: "WhileStatement",
         WithStatement: "WithStatement",
         YieldExpression: "YieldExpression"
-      }, s = {
+      }, o = {
         AssignmentExpression: ["left", "right"],
         AssignmentPattern: ["left", "right"],
         ArrayExpression: ["elements"],
@@ -123974,120 +124248,123 @@ module.exports = NodeEventGenerator;
         WithStatement: ["object", "body"],
         YieldExpression: ["argument"]
       }, n = {
-        Break: o = {},
-        Skip: a = {},
+        Break: a = {},
+        Skip: s = {},
         Remove: i = {}
       }, u.prototype.replace = function (e) {
         this.parent[this.key] = e;
       }, u.prototype.remove = function () {
         return Array.isArray(this.parent) ? (this.parent.splice(this.key, 1), !0) : (this.replace(null), !1);
-      }, p.prototype.path = function () {
-        var e, t, r, n, s;
+      }, f.prototype.path = function () {
+        var e, t, r, n, o;
 
-        function o(e, t) {
+        function a(e, t) {
           if (Array.isArray(t)) for (r = 0, n = t.length; r < n; ++r) e.push(t[r]);else e.push(t);
         }
 
         if (!this.__current.path) return null;
 
-        for (s = [], e = 2, t = this.__leavelist.length; e < t; ++e) o(s, this.__leavelist[e].path);
+        for (o = [], e = 2, t = this.__leavelist.length; e < t; ++e) a(o, this.__leavelist[e].path);
 
-        return o(s, this.__current.path), s;
-      }, p.prototype.type = function () {
+        return a(o, this.__current.path), o;
+      }, f.prototype.type = function () {
         return this.current().type || this.__current.wrap;
-      }, p.prototype.parents = function () {
+      }, f.prototype.parents = function () {
         var e, t, r;
 
         for (r = [], e = 1, t = this.__leavelist.length; e < t; ++e) r.push(this.__leavelist[e].node);
 
         return r;
-      }, p.prototype.current = function () {
+      }, f.prototype.current = function () {
         return this.__current.node;
-      }, p.prototype.__execute = function (e, t) {
+      }, f.prototype.__execute = function (e, t) {
         var r, n;
         return n = void 0, r = this.__current, this.__current = t, this.__state = null, e && (n = e.call(this, t.node, this.__leavelist[this.__leavelist.length - 1].node)), this.__current = r, n;
-      }, p.prototype.notify = function (e) {
+      }, f.prototype.notify = function (e) {
         this.__state = e;
-      }, p.prototype.skip = function () {
+      }, f.prototype.skip = function () {
+        this.notify(s);
+      }, f.prototype.break = function () {
         this.notify(a);
-      }, p.prototype.break = function () {
-        this.notify(o);
-      }, p.prototype.remove = function () {
+      }, f.prototype.remove = function () {
         this.notify(i);
-      }, p.prototype.__initialize = function (e, t) {
-        this.visitor = t, this.root = e, this.__worklist = [], this.__leavelist = [], this.__current = null, this.__state = null, this.__fallback = null, "iteration" === t.fallback ? this.__fallback = Object.keys : "function" == typeof t.fallback && (this.__fallback = t.fallback), this.__keys = s, t.keys && (this.__keys = Object.assign(Object.create(this.__keys), t.keys));
-      }, p.prototype.traverse = function (e, t) {
-        var r, n, s, i, l, u, p, d, x, m, y, g;
+      }, f.prototype.__initialize = function (e, t) {
+        this.visitor = t, this.root = e, this.__worklist = [], this.__leavelist = [], this.__current = null, this.__state = null, this.__fallback = null, "iteration" === t.fallback ? this.__fallback = Object.keys : "function" == typeof t.fallback && (this.__fallback = t.fallback), this.__keys = o, t.keys && (this.__keys = Object.assign(Object.create(this.__keys), t.keys));
+      }, f.prototype.traverse = function (e, t) {
+        var r, n, o, i, l, u, f, y, m, x, g, v;
 
-        for (this.__initialize(e, t), g = {}, r = this.__worklist, n = this.__leavelist, r.push(new c(e, null, null, null)), n.push(new c(null, null, null, null)); r.length;) if ((s = r.pop()) !== g) {
-          if (s.node) {
-            if (u = this.__execute(t.enter, s), this.__state === o || u === o) return;
-            if (r.push(g), n.push(s), this.__state === a || u === a) continue;
+        for (this.__initialize(e, t), v = {}, r = this.__worklist, n = this.__leavelist, r.push(new c(e, null, null, null)), n.push(new c(null, null, null, null)); r.length;) if ((o = r.pop()) !== v) {
+          if (o.node) {
+            if (u = this.__execute(t.enter, o), this.__state === a || u === a) return;
+            if (r.push(v), n.push(o), this.__state === s || u === s) continue;
 
-            if (l = (i = s.node).type || s.wrap, !(m = this.__keys[l])) {
+            if (l = (i = o.node).type || o.wrap, !(x = this.__keys[l])) {
               if (!this.__fallback) throw new Error("Unknown node type " + l + ".");
-              m = this.__fallback(i);
+              x = this.__fallback(i);
             }
 
-            for (d = m.length; (d -= 1) >= 0;) if (y = i[p = m[d]]) if (Array.isArray(y)) {
-              for (x = y.length; (x -= 1) >= 0;) if (y[x]) {
-                if (h(l, m[d])) s = new c(y[x], [p, x], "Property", null);else {
-                  if (!f(y[x])) continue;
-                  s = new c(y[x], [p, x], null, null);
+            for (y = x.length; (y -= 1) >= 0;) if (g = i[f = x[y]]) if (Array.isArray(g)) {
+              for (m = g.length; (m -= 1) >= 0;) if (g[m] && !d(n, g[m])) {
+                if (h(l, x[y])) o = new c(g[m], [f, m], "Property", null);else {
+                  if (!p(g[m])) continue;
+                  o = new c(g[m], [f, m], null, null);
                 }
-                r.push(s);
+                r.push(o);
               }
-            } else f(y) && r.push(new c(y, p, null, null));
+            } else if (p(g)) {
+              if (d(n, g)) continue;
+              r.push(new c(g, f, null, null));
+            }
           }
-        } else if (s = n.pop(), u = this.__execute(t.leave, s), this.__state === o || u === o) return;
-      }, p.prototype.replace = function (e, t) {
-        var r, n, s, l, p, d, x, m, y, g, v, A, E;
+        } else if (o = n.pop(), u = this.__execute(t.leave, o), this.__state === a || u === a) return;
+      }, f.prototype.replace = function (e, t) {
+        var r, n, o, l, f, d, y, m, x, g, v, A, b;
 
-        function _(e) {
-          var t, n, s, o;
-          if (e.ref.remove()) for (n = e.ref.key, o = e.ref.parent, t = r.length; t--;) if ((s = r[t]).ref && s.ref.parent === o) {
-            if (s.ref.key < n) break;
-            --s.ref.key;
+        function E(e) {
+          var t, n, o, a;
+          if (e.ref.remove()) for (n = e.ref.key, a = e.ref.parent, t = r.length; t--;) if ((o = r[t]).ref && o.ref.parent === a) {
+            if (o.ref.key < n) break;
+            --o.ref.key;
           }
         }
 
         for (this.__initialize(e, t), v = {}, r = this.__worklist, n = this.__leavelist, d = new c(e, null, null, new u(A = {
           root: e
         }, "root")), r.push(d), n.push(d); r.length;) if ((d = r.pop()) !== v) {
-          if (void 0 !== (p = this.__execute(t.enter, d)) && p !== o && p !== a && p !== i && (d.ref.replace(p), d.node = p), this.__state !== i && p !== i || (_(d), d.node = null), this.__state === o || p === o) return A.root;
+          if (void 0 !== (f = this.__execute(t.enter, d)) && f !== a && f !== s && f !== i && (d.ref.replace(f), d.node = f), this.__state !== i && f !== i || (E(d), d.node = null), this.__state === a || f === a) return A.root;
 
-          if ((s = d.node) && (r.push(v), n.push(d), this.__state !== a && p !== a)) {
-            if (l = s.type || d.wrap, !(y = this.__keys[l])) {
+          if ((o = d.node) && (r.push(v), n.push(d), this.__state !== s && f !== s)) {
+            if (l = o.type || d.wrap, !(x = this.__keys[l])) {
               if (!this.__fallback) throw new Error("Unknown node type " + l + ".");
-              y = this.__fallback(s);
+              x = this.__fallback(o);
             }
 
-            for (x = y.length; (x -= 1) >= 0;) if (g = s[E = y[x]]) if (Array.isArray(g)) {
+            for (y = x.length; (y -= 1) >= 0;) if (g = o[b = x[y]]) if (Array.isArray(g)) {
               for (m = g.length; (m -= 1) >= 0;) if (g[m]) {
-                if (h(l, y[x])) d = new c(g[m], [E, m], "Property", new u(g, m));else {
-                  if (!f(g[m])) continue;
-                  d = new c(g[m], [E, m], null, new u(g, m));
+                if (h(l, x[y])) d = new c(g[m], [b, m], "Property", new u(g, m));else {
+                  if (!p(g[m])) continue;
+                  d = new c(g[m], [b, m], null, new u(g, m));
                 }
                 r.push(d);
               }
-            } else f(g) && r.push(new c(g, E, null, new u(s, E)));
+            } else p(g) && r.push(new c(g, b, null, new u(o, b)));
           }
-        } else if (d = n.pop(), void 0 !== (p = this.__execute(t.leave, d)) && p !== o && p !== a && p !== i && d.ref.replace(p), this.__state !== i && p !== i || _(d), this.__state === o || p === o) return A.root;
+        } else if (d = n.pop(), void 0 !== (f = this.__execute(t.leave, d)) && f !== a && f !== s && f !== i && d.ref.replace(f), this.__state !== i && f !== i || E(d), this.__state === a || f === a) return A.root;
 
         return A.root;
-      }, t.Syntax = r, t.traverse = d, t.replace = function (e, t) {
-        return new p().replace(e, t);
+      }, t.Syntax = r, t.traverse = y, t.replace = function (e, t) {
+        return new f().replace(e, t);
       }, t.attachComments = function (e, t, r) {
-        var s,
-            o,
+        var o,
             a,
+            s,
             i,
             u = [];
         if (!e.range) throw new Error("attachComments needs range information");
 
         if (!r.length) {
           if (t.length) {
-            for (a = 0, o = t.length; a < o; a += 1) (s = l(t[a])).extendedRange = [0, e.range[0]], u.push(s);
+            for (s = 0, a = t.length; s < a; s += 1) (o = l(t[s])).extendedRange = [0, e.range[0]], u.push(o);
 
             e.leadingComments = u;
           }
@@ -124095,30 +124372,30 @@ module.exports = NodeEventGenerator;
           return e;
         }
 
-        for (a = 0, o = t.length; a < o; a += 1) u.push(x(l(t[a]), r));
+        for (s = 0, a = t.length; s < a; s += 1) u.push(m(l(t[s]), r));
 
-        return i = 0, d(e, {
+        return i = 0, y(e, {
           enter: function enter(e) {
             for (var t; i < u.length && !((t = u[i]).extendedRange[1] > e.range[0]);) t.extendedRange[1] === e.range[0] ? (e.leadingComments || (e.leadingComments = []), e.leadingComments.push(t), u.splice(i, 1)) : i += 1;
 
             return i === u.length ? n.Break : u[i].extendedRange[0] > e.range[1] ? n.Skip : void 0;
           }
-        }), i = 0, d(e, {
+        }), i = 0, y(e, {
           leave: function leave(e) {
             for (var t; i < u.length && (t = u[i], !(e.range[1] < t.extendedRange[0]));) e.range[1] === t.extendedRange[0] ? (e.trailingComments || (e.trailingComments = []), e.trailingComments.push(t), u.splice(i, 1)) : i += 1;
 
             return i === u.length ? n.Break : u[i].extendedRange[0] > e.range[1] ? n.Skip : void 0;
           }
         }), e;
-      }, t.VisitorKeys = s, t.VisitorOption = n, t.Controller = p, t.cloneEnvironment = function () {
+      }, t.VisitorKeys = o, t.VisitorOption = n, t.Controller = f, t.cloneEnvironment = function () {
         return e({});
       }, t;
     }(t);
   }),
-      r = e(function (e) {
+      i = a(function (e) {
     e.exports && (e.exports = function () {
-      function e(t, r, n, s) {
-        this.message = t, this.expected = r, this.found = n, this.location = s, this.name = "SyntaxError", "function" == typeof Error.captureStackTrace && Error.captureStackTrace(this, e);
+      function e(t, r, n, o) {
+        this.message = t, this.expected = r, this.found = n, this.location = o, this.name = "SyntaxError", "function" == typeof Error.captureStackTrace && Error.captureStackTrace(this, e);
       }
 
       return function (e, t) {
@@ -124130,13 +124407,13 @@ module.exports = NodeEventGenerator;
       }(e, Error), e.buildMessage = function (e, t) {
         var r = {
           literal: function literal(e) {
-            return '"' + s(e.text) + '"';
+            return '"' + o(e.text) + '"';
           },
           class: function _class(e) {
             var t,
                 r = "";
 
-            for (t = 0; t < e.parts.length; t++) r += e.parts[t] instanceof Array ? o(e.parts[t][0]) + "-" + o(e.parts[t][1]) : o(e.parts[t]);
+            for (t = 0; t < e.parts.length; t++) r += e.parts[t] instanceof Array ? a(e.parts[t][0]) + "-" + a(e.parts[t][1]) : a(e.parts[t]);
 
             return "[" + (e.inverted ? "^" : "") + r + "]";
           },
@@ -124155,7 +124432,7 @@ module.exports = NodeEventGenerator;
           return e.charCodeAt(0).toString(16).toUpperCase();
         }
 
-        function s(e) {
+        function o(e) {
           return e.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function (e) {
             return "\\x0" + n(e);
           }).replace(/[\x10-\x1F\x7F-\x9F]/g, function (e) {
@@ -124163,7 +124440,7 @@ module.exports = NodeEventGenerator;
           });
         }
 
-        function o(e) {
+        function a(e) {
           return e.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function (e) {
             return "\\x0" + n(e);
           }).replace(/[\x10-\x1F\x7F-\x9F]/g, function (e) {
@@ -124174,29 +124451,29 @@ module.exports = NodeEventGenerator;
         return "Expected " + function (e) {
           var t,
               n,
-              s,
-              o = new Array(e.length);
+              o,
+              a = new Array(e.length);
 
-          for (t = 0; t < e.length; t++) o[t] = (s = e[t], r[s.type](s));
+          for (t = 0; t < e.length; t++) a[t] = (o = e[t], r[o.type](o));
 
-          if (o.sort(), o.length > 0) {
-            for (t = 1, n = 1; t < o.length; t++) o[t - 1] !== o[t] && (o[n] = o[t], n++);
+          if (a.sort(), a.length > 0) {
+            for (t = 1, n = 1; t < a.length; t++) a[t - 1] !== a[t] && (a[n] = a[t], n++);
 
-            o.length = n;
+            a.length = n;
           }
 
-          switch (o.length) {
+          switch (a.length) {
             case 1:
-              return o[0];
+              return a[0];
 
             case 2:
-              return o[0] + " or " + o[1];
+              return a[0] + " or " + a[1];
 
             default:
-              return o.slice(0, -1).join(", ") + ", or " + o[o.length - 1];
+              return a.slice(0, -1).join(", ") + ", or " + a[a.length - 1];
           }
         }(e) + " but " + function (e) {
-          return e ? '"' + s(e) + '"' : "end of input";
+          return e ? '"' + o(e) + '"' : "end of input";
         }(t) + " found.";
       }, {
         SyntaxError: e,
@@ -124204,37 +124481,37 @@ module.exports = NodeEventGenerator;
           r = void 0 !== r ? r : {};
 
           var n,
-              s,
               o,
               a,
+              s,
               i = {},
               l = {
-            start: Ee
+            start: be
           },
-              u = Ee,
+              u = be,
               c = me(" ", !1),
-              p = /^[^ [\],():#!=><~+.]/,
-              f = ye([" ", "[", "]", ",", "(", ")", ":", "#", "!", "=", ">", "<", "~", "+", "."], !0, !1),
+              f = /^[^ [\],():#!=><~+.]/,
+              p = xe([" ", "[", "]", ",", "(", ")", ":", "#", "!", "=", ">", "<", "~", "+", "."], !0, !1),
               h = function h(e) {
             return e.join("");
           },
               d = me(">", !1),
-              x = me("~", !1),
+              y = me("~", !1),
               m = me("+", !1),
-              y = me(",", !1),
+              x = me(",", !1),
               g = me("!", !1),
               v = me("*", !1),
               A = me("#", !1),
-              E = me("[", !1),
-              _ = me("]", !1),
-              b = /^[><!]/,
-              S = ye([">", "<", "!"], !1, !1),
-              C = me("=", !1),
-              w = function w(e) {
+              b = me("[", !1),
+              E = me("]", !1),
+              S = /^[><!]/,
+              _ = xe([">", "<", "!"], !1, !1),
+              w = me("=", !1),
+              C = function C(e) {
             return (e || "") + "=";
           },
               P = /^[><]/,
-              k = ye([">", "<"], !1, !1),
+              k = xe([">", "<"], !1, !1),
               D = me(".", !1),
               I = function I(e, t, r) {
             return {
@@ -124246,7 +124523,7 @@ module.exports = NodeEventGenerator;
           },
               j = me('"', !1),
               F = /^[^\\"]/,
-              T = ye(["\\", '"'], !0, !1),
+              T = xe(["\\", '"'], !0, !1),
               L = me("\\", !1),
               R = {
             type: "any"
@@ -124286,39 +124563,39 @@ module.exports = NodeEventGenerator;
           },
               M = me("'", !1),
               U = /^[^\\']/,
-              V = ye(["\\", "'"], !0, !1),
+              V = xe(["\\", "'"], !0, !1),
               q = /^[0-9]/,
-              N = ye([["0", "9"]], !1, !1),
+              N = xe([["0", "9"]], !1, !1),
               W = me("type(", !1),
-              $ = /^[^ )]/,
-              G = ye([" ", ")"], !0, !1),
-              z = me(")", !1),
-              K = /^[imsu]/,
-              H = ye(["i", "m", "s", "u"], !1, !1),
-              Y = me("/", !1),
+              G = /^[^ )]/,
+              z = xe([" ", ")"], !0, !1),
+              K = me(")", !1),
+              H = /^[imsu]/,
+              Y = xe(["i", "m", "s", "u"], !1, !1),
+              $ = me("/", !1),
               J = /^[^\/]/,
-              Q = ye(["/"], !0, !1),
+              Q = xe(["/"], !0, !1),
               X = me(":not(", !1),
               Z = me(":matches(", !1),
               ee = me(":has(", !1),
               te = me(":first-child", !1),
               re = me(":last-child", !1),
               ne = me(":nth-child(", !1),
-              se = me(":nth-last-child(", !1),
-              oe = me(":", !1),
-              ae = me("statement", !0),
+              oe = me(":nth-last-child(", !1),
+              ae = me(":", !1),
+              se = me("statement", !0),
               ie = me("expression", !0),
               le = me("declaration", !0),
               ue = me("function", !0),
               ce = me("pattern", !0),
-              pe = 0,
-              fe = [{
+              fe = 0,
+              pe = [{
             line: 1,
             column: 1
           }],
               he = 0,
               de = [],
-              xe = {};
+              ye = {};
 
           if ("startRule" in r) {
             if (!(r.startRule in l)) throw new Error("Can't start parsing from rule \"" + r.startRule + '".');
@@ -124333,7 +124610,7 @@ module.exports = NodeEventGenerator;
             };
           }
 
-          function ye(e, t, r) {
+          function xe(e, t, r) {
             return {
               type: "class",
               parts: e,
@@ -124344,17 +124621,17 @@ module.exports = NodeEventGenerator;
 
           function ge(e) {
             var r,
-                n = fe[e];
+                n = pe[e];
             if (n) return n;
 
-            for (r = e - 1; !fe[r];) r--;
+            for (r = e - 1; !pe[r];) r--;
 
             for (n = {
-              line: (n = fe[r]).line,
+              line: (n = pe[r]).line,
               column: n.column
             }; r < e;) 10 === t.charCodeAt(r) ? (n.line++, n.column = 1) : n.column++, r++;
 
-            return fe[e] = n, n;
+            return pe[e] = n, n;
           }
 
           function ve(e, t) {
@@ -124375,119 +124652,119 @@ module.exports = NodeEventGenerator;
           }
 
           function Ae(e) {
-            pe < he || (pe > he && (he = pe, de = []), de.push(e));
+            fe < he || (fe > he && (he = fe, de = []), de.push(e));
           }
 
-          function Ee() {
+          function be() {
             var e,
                 t,
                 r,
                 n,
-                s = 30 * pe + 0,
-                o = xe[s];
-            return o ? (pe = o.nextPos, o.result) : (e = pe, (t = _e()) !== i && (r = Ce()) !== i && _e() !== i ? e = t = 1 === (n = r).length ? n[0] : {
+                o = 30 * fe + 0,
+                a = ye[o];
+            return a ? (fe = a.nextPos, a.result) : (e = fe, (t = Ee()) !== i && (r = we()) !== i && Ee() !== i ? e = t = 1 === (n = r).length ? n[0] : {
               type: "matches",
               selectors: n
-            } : (pe = e, e = i), e === i && (e = pe, (t = _e()) !== i && (t = void 0), e = t), xe[s] = {
-              nextPos: pe,
+            } : (fe = e, e = i), e === i && (e = fe, (t = Ee()) !== i && (t = void 0), e = t), ye[o] = {
+              nextPos: fe,
               result: e
             }, e);
           }
 
-          function _e() {
+          function Ee() {
             var e,
                 r,
-                n = 30 * pe + 1,
-                s = xe[n];
-            if (s) return pe = s.nextPos, s.result;
+                n = 30 * fe + 1,
+                o = ye[n];
+            if (o) return fe = o.nextPos, o.result;
 
-            for (e = [], 32 === t.charCodeAt(pe) ? (r = " ", pe++) : (r = i, Ae(c)); r !== i;) e.push(r), 32 === t.charCodeAt(pe) ? (r = " ", pe++) : (r = i, Ae(c));
+            for (e = [], 32 === t.charCodeAt(fe) ? (r = " ", fe++) : (r = i, Ae(c)); r !== i;) e.push(r), 32 === t.charCodeAt(fe) ? (r = " ", fe++) : (r = i, Ae(c));
 
-            return xe[n] = {
-              nextPos: pe,
+            return ye[n] = {
+              nextPos: fe,
               result: e
             }, e;
           }
 
-          function be() {
+          function Se() {
             var e,
                 r,
                 n,
-                s = 30 * pe + 2,
-                o = xe[s];
-            if (o) return pe = o.nextPos, o.result;
-            if (r = [], p.test(t.charAt(pe)) ? (n = t.charAt(pe), pe++) : (n = i, Ae(f)), n !== i) for (; n !== i;) r.push(n), p.test(t.charAt(pe)) ? (n = t.charAt(pe), pe++) : (n = i, Ae(f));else r = i;
-            return r !== i && (r = h(r)), e = r, xe[s] = {
-              nextPos: pe,
+                o = 30 * fe + 2,
+                a = ye[o];
+            if (a) return fe = a.nextPos, a.result;
+            if (r = [], f.test(t.charAt(fe)) ? (n = t.charAt(fe), fe++) : (n = i, Ae(p)), n !== i) for (; n !== i;) r.push(n), f.test(t.charAt(fe)) ? (n = t.charAt(fe), fe++) : (n = i, Ae(p));else r = i;
+            return r !== i && (r = h(r)), e = r, ye[o] = {
+              nextPos: fe,
               result: e
             }, e;
           }
 
-          function Se() {
+          function _e() {
             var e,
                 r,
                 n,
-                s = 30 * pe + 3,
-                o = xe[s];
-            return o ? (pe = o.nextPos, o.result) : (e = pe, (r = _e()) !== i ? (62 === t.charCodeAt(pe) ? (n = ">", pe++) : (n = i, Ae(d)), n !== i && _e() !== i ? e = r = "child" : (pe = e, e = i)) : (pe = e, e = i), e === i && (e = pe, (r = _e()) !== i ? (126 === t.charCodeAt(pe) ? (n = "~", pe++) : (n = i, Ae(x)), n !== i && _e() !== i ? e = r = "sibling" : (pe = e, e = i)) : (pe = e, e = i), e === i && (e = pe, (r = _e()) !== i ? (43 === t.charCodeAt(pe) ? (n = "+", pe++) : (n = i, Ae(m)), n !== i && _e() !== i ? e = r = "adjacent" : (pe = e, e = i)) : (pe = e, e = i), e === i && (e = pe, 32 === t.charCodeAt(pe) ? (r = " ", pe++) : (r = i, Ae(c)), r !== i && (n = _e()) !== i ? e = r = "descendant" : (pe = e, e = i)))), xe[s] = {
-              nextPos: pe,
+                o = 30 * fe + 3,
+                a = ye[o];
+            return a ? (fe = a.nextPos, a.result) : (e = fe, (r = Ee()) !== i ? (62 === t.charCodeAt(fe) ? (n = ">", fe++) : (n = i, Ae(d)), n !== i && Ee() !== i ? e = r = "child" : (fe = e, e = i)) : (fe = e, e = i), e === i && (e = fe, (r = Ee()) !== i ? (126 === t.charCodeAt(fe) ? (n = "~", fe++) : (n = i, Ae(y)), n !== i && Ee() !== i ? e = r = "sibling" : (fe = e, e = i)) : (fe = e, e = i), e === i && (e = fe, (r = Ee()) !== i ? (43 === t.charCodeAt(fe) ? (n = "+", fe++) : (n = i, Ae(m)), n !== i && Ee() !== i ? e = r = "adjacent" : (fe = e, e = i)) : (fe = e, e = i), e === i && (e = fe, 32 === t.charCodeAt(fe) ? (r = " ", fe++) : (r = i, Ae(c)), r !== i && (n = Ee()) !== i ? e = r = "descendant" : (fe = e, e = i)))), ye[o] = {
+              nextPos: fe,
               result: e
             }, e);
           }
 
-          function Ce() {
+          function we() {
             var e,
                 r,
                 n,
-                s,
                 o,
                 a,
+                s,
                 l,
                 u,
-                c = 30 * pe + 4,
-                p = xe[c];
-            if (p) return pe = p.nextPos, p.result;
+                c = 30 * fe + 4,
+                f = ye[c];
+            if (f) return fe = f.nextPos, f.result;
 
-            if (e = pe, (r = we()) !== i) {
-              for (n = [], s = pe, (o = _e()) !== i ? (44 === t.charCodeAt(pe) ? (a = ",", pe++) : (a = i, Ae(y)), a !== i && (l = _e()) !== i && (u = we()) !== i ? s = o = [o, a, l, u] : (pe = s, s = i)) : (pe = s, s = i); s !== i;) n.push(s), s = pe, (o = _e()) !== i ? (44 === t.charCodeAt(pe) ? (a = ",", pe++) : (a = i, Ae(y)), a !== i && (l = _e()) !== i && (u = we()) !== i ? s = o = [o, a, l, u] : (pe = s, s = i)) : (pe = s, s = i);
+            if (e = fe, (r = Ce()) !== i) {
+              for (n = [], o = fe, (a = Ee()) !== i ? (44 === t.charCodeAt(fe) ? (s = ",", fe++) : (s = i, Ae(x)), s !== i && (l = Ee()) !== i && (u = Ce()) !== i ? o = a = [a, s, l, u] : (fe = o, o = i)) : (fe = o, o = i); o !== i;) n.push(o), o = fe, (a = Ee()) !== i ? (44 === t.charCodeAt(fe) ? (s = ",", fe++) : (s = i, Ae(x)), s !== i && (l = Ee()) !== i && (u = Ce()) !== i ? o = a = [a, s, l, u] : (fe = o, o = i)) : (fe = o, o = i);
 
               n !== i ? e = r = [r].concat(n.map(function (e) {
                 return e[3];
-              })) : (pe = e, e = i);
-            } else pe = e, e = i;
+              })) : (fe = e, e = i);
+            } else fe = e, e = i;
 
-            return xe[c] = {
-              nextPos: pe,
+            return ye[c] = {
+              nextPos: fe,
               result: e
             }, e;
           }
 
-          function we() {
+          function Ce() {
             var e,
                 t,
                 r,
                 n,
-                s,
                 o,
                 a,
-                l = 30 * pe + 5,
-                u = xe[l];
-            if (u) return pe = u.nextPos, u.result;
+                s,
+                l = 30 * fe + 5,
+                u = ye[l];
+            if (u) return fe = u.nextPos, u.result;
 
-            if (e = pe, (t = Pe()) !== i) {
-              for (r = [], n = pe, (s = Se()) !== i && (o = Pe()) !== i ? n = s = [s, o] : (pe = n, n = i); n !== i;) r.push(n), n = pe, (s = Se()) !== i && (o = Pe()) !== i ? n = s = [s, o] : (pe = n, n = i);
+            if (e = fe, (t = Pe()) !== i) {
+              for (r = [], n = fe, (o = _e()) !== i && (a = Pe()) !== i ? n = o = [o, a] : (fe = n, n = i); n !== i;) r.push(n), n = fe, (o = _e()) !== i && (a = Pe()) !== i ? n = o = [o, a] : (fe = n, n = i);
 
-              r !== i ? (a = t, e = t = r.reduce(function (e, t) {
+              r !== i ? (s = t, e = t = r.reduce(function (e, t) {
                 return {
                   type: t[0],
                   left: e,
                   right: t[1]
                 };
-              }, a)) : (pe = e, e = i);
-            } else pe = e, e = i;
+              }, s)) : (fe = e, e = i);
+            } else fe = e, e = i;
 
-            return xe[l] = {
-              nextPos: pe,
+            return ye[l] = {
+              nextPos: fe,
               result: e
             }, e;
           }
@@ -124496,363 +124773,363 @@ module.exports = NodeEventGenerator;
             var e,
                 r,
                 n,
+                o,
+                a,
                 s,
-                o = 30 * pe + 6,
-                a = xe[o];
-            if (a) return pe = a.nextPos, a.result;
-
-            if (e = pe, 33 === t.charCodeAt(pe) ? (r = "!", pe++) : (r = i, Ae(g)), r === i && (r = null), r !== i) {
-              if (n = [], (s = ke()) !== i) for (; s !== i;) n.push(s), s = ke();else n = i;
-              n !== i ? e = r = function (e, t) {
-                const r = 1 === t.length ? t[0] : {
-                  type: "compound",
-                  selectors: t
-                };
-                return e && (r.subject = !0), r;
-              }(r, n) : (pe = e, e = i);
-            } else pe = e, e = i;
-
-            return xe[o] = {
-              nextPos: pe,
+                l,
+                u = 30 * fe + 6,
+                c = ye[u];
+            if (c) return fe = c.nextPos, c.result;
+
+            if (e = fe, 33 === t.charCodeAt(fe) ? (r = "!", fe++) : (r = i, Ae(g)), r === i && (r = null), r !== i) {
+              if (n = [], (o = ke()) !== i) for (; o !== i;) n.push(o), o = ke();else n = i;
+              n !== i ? (a = r, l = 1 === (s = n).length ? s[0] : {
+                type: "compound",
+                selectors: s
+              }, a && (l.subject = !0), e = r = l) : (fe = e, e = i);
+            } else fe = e, e = i;
+
+            return ye[u] = {
+              nextPos: fe,
               result: e
             }, e;
           }
 
           function ke() {
             var e,
-                r = 30 * pe + 7,
-                n = xe[r];
-            return n ? (pe = n.nextPos, n.result) : ((e = function () {
+                r = 30 * fe + 7,
+                n = ye[r];
+            return n ? (fe = n.nextPos, n.result) : ((e = function () {
               var e,
                   r,
-                  n = 30 * pe + 8,
-                  s = xe[n];
-              return s ? (pe = s.nextPos, s.result) : (42 === t.charCodeAt(pe) ? (r = "*", pe++) : (r = i, Ae(v)), r !== i && (r = {
+                  n = 30 * fe + 8,
+                  o = ye[n];
+              return o ? (fe = o.nextPos, o.result) : (42 === t.charCodeAt(fe) ? (r = "*", fe++) : (r = i, Ae(v)), r !== i && (r = {
                 type: "wildcard",
                 value: r
-              }), e = r, xe[n] = {
-                nextPos: pe,
+              }), e = r, ye[n] = {
+                nextPos: fe,
                 result: e
               }, e);
             }()) === i && (e = function () {
               var e,
                   r,
                   n,
-                  s = 30 * pe + 9,
-                  o = xe[s];
-              return o ? (pe = o.nextPos, o.result) : (e = pe, 35 === t.charCodeAt(pe) ? (r = "#", pe++) : (r = i, Ae(A)), r === i && (r = null), r !== i && (n = be()) !== i ? e = r = {
+                  o = 30 * fe + 9,
+                  a = ye[o];
+              return a ? (fe = a.nextPos, a.result) : (e = fe, 35 === t.charCodeAt(fe) ? (r = "#", fe++) : (r = i, Ae(A)), r === i && (r = null), r !== i && (n = Se()) !== i ? e = r = {
                 type: "identifier",
                 value: n
-              } : (pe = e, e = i), xe[s] = {
-                nextPos: pe,
+              } : (fe = e, e = i), ye[o] = {
+                nextPos: fe,
                 result: e
               }, e);
             }()) === i && (e = function () {
               var e,
                   r,
                   n,
-                  s,
-                  o = 30 * pe + 10,
-                  a = xe[o];
-              return a ? (pe = a.nextPos, a.result) : (e = pe, 91 === t.charCodeAt(pe) ? (r = "[", pe++) : (r = i, Ae(E)), r !== i && _e() !== i && (n = function () {
+                  o,
+                  a = 30 * fe + 10,
+                  s = ye[a];
+              return s ? (fe = s.nextPos, s.result) : (e = fe, 91 === t.charCodeAt(fe) ? (r = "[", fe++) : (r = i, Ae(b)), r !== i && Ee() !== i && (n = function () {
                 var e,
                     r,
                     n,
-                    s,
-                    o = 30 * pe + 14,
-                    a = xe[o];
-                return a ? (pe = a.nextPos, a.result) : (e = pe, (r = De()) !== i && _e() !== i && (n = function () {
+                    o,
+                    a = 30 * fe + 14,
+                    s = ye[a];
+                return s ? (fe = s.nextPos, s.result) : (e = fe, (r = De()) !== i && Ee() !== i && (n = function () {
                   var e,
                       r,
                       n,
-                      s = 30 * pe + 12,
-                      o = xe[s];
-                  return o ? (pe = o.nextPos, o.result) : (e = pe, 33 === t.charCodeAt(pe) ? (r = "!", pe++) : (r = i, Ae(g)), r === i && (r = null), r !== i ? (61 === t.charCodeAt(pe) ? (n = "=", pe++) : (n = i, Ae(C)), n !== i ? (r = w(r), e = r) : (pe = e, e = i)) : (pe = e, e = i), xe[s] = {
-                    nextPos: pe,
+                      o = 30 * fe + 12,
+                      a = ye[o];
+                  return a ? (fe = a.nextPos, a.result) : (e = fe, 33 === t.charCodeAt(fe) ? (r = "!", fe++) : (r = i, Ae(g)), r === i && (r = null), r !== i ? (61 === t.charCodeAt(fe) ? (n = "=", fe++) : (n = i, Ae(w)), n !== i ? (r = C(r), e = r) : (fe = e, e = i)) : (fe = e, e = i), ye[o] = {
+                    nextPos: fe,
                     result: e
                   }, e);
-                }()) !== i && _e() !== i ? ((s = function () {
+                }()) !== i && Ee() !== i ? ((o = function () {
                   var e,
                       r,
                       n,
-                      s,
                       o,
-                      a = 30 * pe + 18,
-                      l = xe[a];
-                  if (l) return pe = l.nextPos, l.result;
-                  if (e = pe, "type(" === t.substr(pe, 5) ? (r = "type(", pe += 5) : (r = i, Ae(W)), r !== i) {
-                    if (_e() !== i) {
-                      if (n = [], $.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(G)), s !== i) for (; s !== i;) n.push(s), $.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(G));else n = i;
-                      n !== i && (s = _e()) !== i ? (41 === t.charCodeAt(pe) ? (o = ")", pe++) : (o = i, Ae(z)), o !== i ? (r = {
+                      a,
+                      s = 30 * fe + 18,
+                      l = ye[s];
+                  if (l) return fe = l.nextPos, l.result;
+                  if (e = fe, "type(" === t.substr(fe, 5) ? (r = "type(", fe += 5) : (r = i, Ae(W)), r !== i) {
+                    if (Ee() !== i) {
+                      if (n = [], G.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(z)), o !== i) for (; o !== i;) n.push(o), G.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(z));else n = i;
+                      n !== i && (o = Ee()) !== i ? (41 === t.charCodeAt(fe) ? (a = ")", fe++) : (a = i, Ae(K)), a !== i ? (r = {
                         type: "type",
                         value: n.join("")
-                      }, e = r) : (pe = e, e = i)) : (pe = e, e = i);
-                    } else pe = e, e = i;
-                  } else pe = e, e = i;
-                  return xe[a] = {
-                    nextPos: pe,
+                      }, e = r) : (fe = e, e = i)) : (fe = e, e = i);
+                    } else fe = e, e = i;
+                  } else fe = e, e = i;
+                  return ye[s] = {
+                    nextPos: fe,
                     result: e
                   }, e;
-                }()) === i && (s = function () {
+                }()) === i && (o = function () {
                   var e,
                       r,
                       n,
-                      s,
                       o,
                       a,
-                      l = 30 * pe + 20,
-                      u = xe[l];
-                  if (u) return pe = u.nextPos, u.result;
+                      s,
+                      l = 30 * fe + 20,
+                      u = ye[l];
+                  if (u) return fe = u.nextPos, u.result;
 
-                  if (e = pe, 47 === t.charCodeAt(pe) ? (r = "/", pe++) : (r = i, Ae(Y)), r !== i) {
-                    if (n = [], J.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(Q)), s !== i) for (; s !== i;) n.push(s), J.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(Q));else n = i;
-                    n !== i ? (47 === t.charCodeAt(pe) ? (s = "/", pe++) : (s = i, Ae(Y)), s !== i ? ((o = function () {
+                  if (e = fe, 47 === t.charCodeAt(fe) ? (r = "/", fe++) : (r = i, Ae($)), r !== i) {
+                    if (n = [], J.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(Q)), o !== i) for (; o !== i;) n.push(o), J.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(Q));else n = i;
+                    n !== i ? (47 === t.charCodeAt(fe) ? (o = "/", fe++) : (o = i, Ae($)), o !== i ? ((a = function () {
                       var e,
                           r,
-                          n = 30 * pe + 19,
-                          s = xe[n];
-                      if (s) return pe = s.nextPos, s.result;
-                      if (e = [], K.test(t.charAt(pe)) ? (r = t.charAt(pe), pe++) : (r = i, Ae(H)), r !== i) for (; r !== i;) e.push(r), K.test(t.charAt(pe)) ? (r = t.charAt(pe), pe++) : (r = i, Ae(H));else e = i;
-                      return xe[n] = {
-                        nextPos: pe,
+                          n = 30 * fe + 19,
+                          o = ye[n];
+                      if (o) return fe = o.nextPos, o.result;
+                      if (e = [], H.test(t.charAt(fe)) ? (r = t.charAt(fe), fe++) : (r = i, Ae(Y)), r !== i) for (; r !== i;) e.push(r), H.test(t.charAt(fe)) ? (r = t.charAt(fe), fe++) : (r = i, Ae(Y));else e = i;
+                      return ye[n] = {
+                        nextPos: fe,
                         result: e
                       }, e;
-                    }()) === i && (o = null), o !== i ? (a = o, r = {
+                    }()) === i && (a = null), a !== i ? (s = a, r = {
                       type: "regexp",
-                      value: new RegExp(n.join(""), a ? a.join("") : "")
-                    }, e = r) : (pe = e, e = i)) : (pe = e, e = i)) : (pe = e, e = i);
-                  } else pe = e, e = i;
+                      value: new RegExp(n.join(""), s ? s.join("") : "")
+                    }, e = r) : (fe = e, e = i)) : (fe = e, e = i)) : (fe = e, e = i);
+                  } else fe = e, e = i;
 
-                  return xe[l] = {
-                    nextPos: pe,
+                  return ye[l] = {
+                    nextPos: fe,
                     result: e
                   }, e;
-                }()), s !== i ? (r = I(r, n, s), e = r) : (pe = e, e = i)) : (pe = e, e = i), e === i && (e = pe, (r = De()) !== i && _e() !== i && (n = function () {
+                }()), o !== i ? (r = I(r, n, o), e = r) : (fe = e, e = i)) : (fe = e, e = i), e === i && (e = fe, (r = De()) !== i && Ee() !== i && (n = function () {
                   var e,
                       r,
                       n,
-                      s = 30 * pe + 11,
-                      o = xe[s];
-                  return o ? (pe = o.nextPos, o.result) : (e = pe, b.test(t.charAt(pe)) ? (r = t.charAt(pe), pe++) : (r = i, Ae(S)), r === i && (r = null), r !== i ? (61 === t.charCodeAt(pe) ? (n = "=", pe++) : (n = i, Ae(C)), n !== i ? (r = w(r), e = r) : (pe = e, e = i)) : (pe = e, e = i), e === i && (P.test(t.charAt(pe)) ? (e = t.charAt(pe), pe++) : (e = i, Ae(k))), xe[s] = {
-                    nextPos: pe,
+                      o = 30 * fe + 11,
+                      a = ye[o];
+                  return a ? (fe = a.nextPos, a.result) : (e = fe, S.test(t.charAt(fe)) ? (r = t.charAt(fe), fe++) : (r = i, Ae(_)), r === i && (r = null), r !== i ? (61 === t.charCodeAt(fe) ? (n = "=", fe++) : (n = i, Ae(w)), n !== i ? (r = C(r), e = r) : (fe = e, e = i)) : (fe = e, e = i), e === i && (P.test(t.charAt(fe)) ? (e = t.charAt(fe), fe++) : (e = i, Ae(k))), ye[o] = {
+                    nextPos: fe,
                     result: e
                   }, e);
-                }()) !== i && _e() !== i ? ((s = function () {
+                }()) !== i && Ee() !== i ? ((o = function () {
                   var e,
                       r,
                       n,
-                      s,
                       o,
                       a,
-                      l = 30 * pe + 15,
-                      u = xe[l];
-                  if (u) return pe = u.nextPos, u.result;
+                      s,
+                      l = 30 * fe + 15,
+                      u = ye[l];
+                  if (u) return fe = u.nextPos, u.result;
 
-                  if (e = pe, 34 === t.charCodeAt(pe) ? (r = '"', pe++) : (r = i, Ae(j)), r !== i) {
-                    for (n = [], F.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(T)), s === i && (s = pe, 92 === t.charCodeAt(pe) ? (o = "\\", pe++) : (o = i, Ae(L)), o !== i ? (t.length > pe ? (a = t.charAt(pe), pe++) : (a = i, Ae(R)), a !== i ? (o = O(o, a), s = o) : (pe = s, s = i)) : (pe = s, s = i)); s !== i;) n.push(s), F.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(T)), s === i && (s = pe, 92 === t.charCodeAt(pe) ? (o = "\\", pe++) : (o = i, Ae(L)), o !== i ? (t.length > pe ? (a = t.charAt(pe), pe++) : (a = i, Ae(R)), a !== i ? (o = O(o, a), s = o) : (pe = s, s = i)) : (pe = s, s = i));
+                  if (e = fe, 34 === t.charCodeAt(fe) ? (r = '"', fe++) : (r = i, Ae(j)), r !== i) {
+                    for (n = [], F.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(T)), o === i && (o = fe, 92 === t.charCodeAt(fe) ? (a = "\\", fe++) : (a = i, Ae(L)), a !== i ? (t.length > fe ? (s = t.charAt(fe), fe++) : (s = i, Ae(R)), s !== i ? (a = O(a, s), o = a) : (fe = o, o = i)) : (fe = o, o = i)); o !== i;) n.push(o), F.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(T)), o === i && (o = fe, 92 === t.charCodeAt(fe) ? (a = "\\", fe++) : (a = i, Ae(L)), a !== i ? (t.length > fe ? (s = t.charAt(fe), fe++) : (s = i, Ae(R)), s !== i ? (a = O(a, s), o = a) : (fe = o, o = i)) : (fe = o, o = i));
 
-                    n !== i ? (34 === t.charCodeAt(pe) ? (s = '"', pe++) : (s = i, Ae(j)), s !== i ? (r = B(n), e = r) : (pe = e, e = i)) : (pe = e, e = i);
-                  } else pe = e, e = i;
+                    n !== i ? (34 === t.charCodeAt(fe) ? (o = '"', fe++) : (o = i, Ae(j)), o !== i ? (r = B(n), e = r) : (fe = e, e = i)) : (fe = e, e = i);
+                  } else fe = e, e = i;
 
-                  if (e === i) if (e = pe, 39 === t.charCodeAt(pe) ? (r = "'", pe++) : (r = i, Ae(M)), r !== i) {
-                    for (n = [], U.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(V)), s === i && (s = pe, 92 === t.charCodeAt(pe) ? (o = "\\", pe++) : (o = i, Ae(L)), o !== i ? (t.length > pe ? (a = t.charAt(pe), pe++) : (a = i, Ae(R)), a !== i ? (o = O(o, a), s = o) : (pe = s, s = i)) : (pe = s, s = i)); s !== i;) n.push(s), U.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(V)), s === i && (s = pe, 92 === t.charCodeAt(pe) ? (o = "\\", pe++) : (o = i, Ae(L)), o !== i ? (t.length > pe ? (a = t.charAt(pe), pe++) : (a = i, Ae(R)), a !== i ? (o = O(o, a), s = o) : (pe = s, s = i)) : (pe = s, s = i));
+                  if (e === i) if (e = fe, 39 === t.charCodeAt(fe) ? (r = "'", fe++) : (r = i, Ae(M)), r !== i) {
+                    for (n = [], U.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(V)), o === i && (o = fe, 92 === t.charCodeAt(fe) ? (a = "\\", fe++) : (a = i, Ae(L)), a !== i ? (t.length > fe ? (s = t.charAt(fe), fe++) : (s = i, Ae(R)), s !== i ? (a = O(a, s), o = a) : (fe = o, o = i)) : (fe = o, o = i)); o !== i;) n.push(o), U.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(V)), o === i && (o = fe, 92 === t.charCodeAt(fe) ? (a = "\\", fe++) : (a = i, Ae(L)), a !== i ? (t.length > fe ? (s = t.charAt(fe), fe++) : (s = i, Ae(R)), s !== i ? (a = O(a, s), o = a) : (fe = o, o = i)) : (fe = o, o = i));
 
-                    n !== i ? (39 === t.charCodeAt(pe) ? (s = "'", pe++) : (s = i, Ae(M)), s !== i ? (r = B(n), e = r) : (pe = e, e = i)) : (pe = e, e = i);
-                  } else pe = e, e = i;
-                  return xe[l] = {
-                    nextPos: pe,
+                    n !== i ? (39 === t.charCodeAt(fe) ? (o = "'", fe++) : (o = i, Ae(M)), o !== i ? (r = B(n), e = r) : (fe = e, e = i)) : (fe = e, e = i);
+                  } else fe = e, e = i;
+                  return ye[l] = {
+                    nextPos: fe,
                     result: e
                   }, e;
-                }()) === i && (s = function () {
+                }()) === i && (o = function () {
                   var e,
                       r,
                       n,
+                      o,
+                      a,
                       s,
-                      o = 30 * pe + 16,
-                      a = xe[o];
-                  if (a) return pe = a.nextPos, a.result;
-
-                  for (e = pe, r = pe, n = [], q.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(N)); s !== i;) n.push(s), q.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(N));
-
-                  if (n !== i ? (46 === t.charCodeAt(pe) ? (s = ".", pe++) : (s = i, Ae(D)), s !== i ? r = n = [n, s] : (pe = r, r = i)) : (pe = r, r = i), r === i && (r = null), r !== i) {
-                    if (n = [], q.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(N)), s !== i) for (; s !== i;) n.push(s), q.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(N));else n = i;
-                    n !== i ? (r = function (e, t) {
-                      const r = e ? [].concat.apply([], e).join("") : "";
-                      return {
-                        type: "literal",
-                        value: parseFloat(r + t.join(""))
-                      };
-                    }(r, n), e = r) : (pe = e, e = i);
-                  } else pe = e, e = i;
-
-                  return xe[o] = {
-                    nextPos: pe,
+                      l,
+                      u = 30 * fe + 16,
+                      c = ye[u];
+                  if (c) return fe = c.nextPos, c.result;
+
+                  for (e = fe, r = fe, n = [], q.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(N)); o !== i;) n.push(o), q.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(N));
+
+                  if (n !== i ? (46 === t.charCodeAt(fe) ? (o = ".", fe++) : (o = i, Ae(D)), o !== i ? r = n = [n, o] : (fe = r, r = i)) : (fe = r, r = i), r === i && (r = null), r !== i) {
+                    if (n = [], q.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(N)), o !== i) for (; o !== i;) n.push(o), q.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(N));else n = i;
+                    n !== i ? (s = n, l = (a = r) ? [].concat.apply([], a).join("") : "", r = {
+                      type: "literal",
+                      value: parseFloat(l + s.join(""))
+                    }, e = r) : (fe = e, e = i);
+                  } else fe = e, e = i;
+
+                  return ye[u] = {
+                    nextPos: fe,
                     result: e
                   }, e;
-                }()) === i && (s = function () {
+                }()) === i && (o = function () {
                   var e,
                       t,
-                      r = 30 * pe + 17,
-                      n = xe[r];
-                  return n ? (pe = n.nextPos, n.result) : ((t = be()) !== i && (t = {
+                      r = 30 * fe + 17,
+                      n = ye[r];
+                  return n ? (fe = n.nextPos, n.result) : ((t = Se()) !== i && (t = {
                     type: "literal",
                     value: t
-                  }), e = t, xe[r] = {
-                    nextPos: pe,
+                  }), e = t, ye[r] = {
+                    nextPos: fe,
                     result: e
                   }, e);
-                }()), s !== i ? (r = I(r, n, s), e = r) : (pe = e, e = i)) : (pe = e, e = i), e === i && (e = pe, (r = De()) !== i && (r = {
+                }()), o !== i ? (r = I(r, n, o), e = r) : (fe = e, e = i)) : (fe = e, e = i), e === i && (e = fe, (r = De()) !== i && (r = {
                   type: "attribute",
                   name: r
-                }), e = r)), xe[o] = {
-                  nextPos: pe,
+                }), e = r)), ye[a] = {
+                  nextPos: fe,
                   result: e
                 }, e);
-              }()) !== i && _e() !== i ? (93 === t.charCodeAt(pe) ? (s = "]", pe++) : (s = i, Ae(_)), s !== i ? e = r = n : (pe = e, e = i)) : (pe = e, e = i), xe[o] = {
-                nextPos: pe,
+              }()) !== i && Ee() !== i ? (93 === t.charCodeAt(fe) ? (o = "]", fe++) : (o = i, Ae(E)), o !== i ? e = r = n : (fe = e, e = i)) : (fe = e, e = i), ye[a] = {
+                nextPos: fe,
                 result: e
               }, e);
             }()) === i && (e = function () {
               var e,
                   r,
                   n,
-                  s,
                   o,
                   a,
+                  s,
                   l,
                   u,
-                  c = 30 * pe + 21,
-                  p = xe[c];
-              if (p) return pe = p.nextPos, p.result;
-              if (e = pe, 46 === t.charCodeAt(pe) ? (r = ".", pe++) : (r = i, Ae(D)), r !== i) {
-                if ((n = be()) !== i) {
-                  for (s = [], o = pe, 46 === t.charCodeAt(pe) ? (a = ".", pe++) : (a = i, Ae(D)), a !== i && (l = be()) !== i ? o = a = [a, l] : (pe = o, o = i); o !== i;) s.push(o), o = pe, 46 === t.charCodeAt(pe) ? (a = ".", pe++) : (a = i, Ae(D)), a !== i && (l = be()) !== i ? o = a = [a, l] : (pe = o, o = i);
-
-                  s !== i ? (u = n, r = {
+                  c = 30 * fe + 21,
+                  f = ye[c];
+              if (f) return fe = f.nextPos, f.result;
+              if (e = fe, 46 === t.charCodeAt(fe) ? (r = ".", fe++) : (r = i, Ae(D)), r !== i) {
+                if ((n = Se()) !== i) {
+                  for (o = [], a = fe, 46 === t.charCodeAt(fe) ? (s = ".", fe++) : (s = i, Ae(D)), s !== i && (l = Se()) !== i ? a = s = [s, l] : (fe = a, a = i); a !== i;) o.push(a), a = fe, 46 === t.charCodeAt(fe) ? (s = ".", fe++) : (s = i, Ae(D)), s !== i && (l = Se()) !== i ? a = s = [s, l] : (fe = a, a = i);
+
+                  o !== i ? (u = n, r = {
                     type: "field",
-                    name: s.reduce(function (e, t) {
+                    name: o.reduce(function (e, t) {
                       return e + t[0] + t[1];
                     }, u)
-                  }, e = r) : (pe = e, e = i);
-                } else pe = e, e = i;
-              } else pe = e, e = i;
-              return xe[c] = {
-                nextPos: pe,
+                  }, e = r) : (fe = e, e = i);
+                } else fe = e, e = i;
+              } else fe = e, e = i;
+              return ye[c] = {
+                nextPos: fe,
                 result: e
               }, e;
             }()) === i && (e = function () {
               var e,
                   r,
                   n,
-                  s,
-                  o = 30 * pe + 22,
-                  a = xe[o];
-              return a ? (pe = a.nextPos, a.result) : (e = pe, ":not(" === t.substr(pe, 5) ? (r = ":not(", pe += 5) : (r = i, Ae(X)), r !== i && _e() !== i && (n = Ce()) !== i && _e() !== i ? (41 === t.charCodeAt(pe) ? (s = ")", pe++) : (s = i, Ae(z)), s !== i ? e = r = {
+                  o,
+                  a = 30 * fe + 22,
+                  s = ye[a];
+              return s ? (fe = s.nextPos, s.result) : (e = fe, ":not(" === t.substr(fe, 5) ? (r = ":not(", fe += 5) : (r = i, Ae(X)), r !== i && Ee() !== i && (n = we()) !== i && Ee() !== i ? (41 === t.charCodeAt(fe) ? (o = ")", fe++) : (o = i, Ae(K)), o !== i ? e = r = {
                 type: "not",
                 selectors: n
-              } : (pe = e, e = i)) : (pe = e, e = i), xe[o] = {
-                nextPos: pe,
+              } : (fe = e, e = i)) : (fe = e, e = i), ye[a] = {
+                nextPos: fe,
                 result: e
               }, e);
             }()) === i && (e = function () {
               var e,
                   r,
                   n,
-                  s,
-                  o = 30 * pe + 23,
-                  a = xe[o];
-              return a ? (pe = a.nextPos, a.result) : (e = pe, ":matches(" === t.substr(pe, 9) ? (r = ":matches(", pe += 9) : (r = i, Ae(Z)), r !== i && _e() !== i && (n = Ce()) !== i && _e() !== i ? (41 === t.charCodeAt(pe) ? (s = ")", pe++) : (s = i, Ae(z)), s !== i ? e = r = {
+                  o,
+                  a = 30 * fe + 23,
+                  s = ye[a];
+              return s ? (fe = s.nextPos, s.result) : (e = fe, ":matches(" === t.substr(fe, 9) ? (r = ":matches(", fe += 9) : (r = i, Ae(Z)), r !== i && Ee() !== i && (n = we()) !== i && Ee() !== i ? (41 === t.charCodeAt(fe) ? (o = ")", fe++) : (o = i, Ae(K)), o !== i ? e = r = {
                 type: "matches",
                 selectors: n
-              } : (pe = e, e = i)) : (pe = e, e = i), xe[o] = {
-                nextPos: pe,
+              } : (fe = e, e = i)) : (fe = e, e = i), ye[a] = {
+                nextPos: fe,
                 result: e
               }, e);
             }()) === i && (e = function () {
               var e,
                   r,
                   n,
-                  s,
-                  o = 30 * pe + 24,
-                  a = xe[o];
-              return a ? (pe = a.nextPos, a.result) : (e = pe, ":has(" === t.substr(pe, 5) ? (r = ":has(", pe += 5) : (r = i, Ae(ee)), r !== i && _e() !== i && (n = Ce()) !== i && _e() !== i ? (41 === t.charCodeAt(pe) ? (s = ")", pe++) : (s = i, Ae(z)), s !== i ? e = r = {
+                  o,
+                  a = 30 * fe + 24,
+                  s = ye[a];
+              return s ? (fe = s.nextPos, s.result) : (e = fe, ":has(" === t.substr(fe, 5) ? (r = ":has(", fe += 5) : (r = i, Ae(ee)), r !== i && Ee() !== i && (n = we()) !== i && Ee() !== i ? (41 === t.charCodeAt(fe) ? (o = ")", fe++) : (o = i, Ae(K)), o !== i ? e = r = {
                 type: "has",
                 selectors: n
-              } : (pe = e, e = i)) : (pe = e, e = i), xe[o] = {
-                nextPos: pe,
+              } : (fe = e, e = i)) : (fe = e, e = i), ye[a] = {
+                nextPos: fe,
                 result: e
               }, e);
             }()) === i && (e = function () {
               var e,
                   r,
-                  n = 30 * pe + 25,
-                  s = xe[n];
-              return s ? (pe = s.nextPos, s.result) : (":first-child" === t.substr(pe, 12) ? (r = ":first-child", pe += 12) : (r = i, Ae(te)), r !== i && (r = Ie(1)), e = r, xe[n] = {
-                nextPos: pe,
+                  n = 30 * fe + 25,
+                  o = ye[n];
+              return o ? (fe = o.nextPos, o.result) : (":first-child" === t.substr(fe, 12) ? (r = ":first-child", fe += 12) : (r = i, Ae(te)), r !== i && (r = Ie(1)), e = r, ye[n] = {
+                nextPos: fe,
                 result: e
               }, e);
             }()) === i && (e = function () {
               var e,
                   r,
-                  n = 30 * pe + 26,
-                  s = xe[n];
-              return s ? (pe = s.nextPos, s.result) : (":last-child" === t.substr(pe, 11) ? (r = ":last-child", pe += 11) : (r = i, Ae(re)), r !== i && (r = je(1)), e = r, xe[n] = {
-                nextPos: pe,
+                  n = 30 * fe + 26,
+                  o = ye[n];
+              return o ? (fe = o.nextPos, o.result) : (":last-child" === t.substr(fe, 11) ? (r = ":last-child", fe += 11) : (r = i, Ae(re)), r !== i && (r = je(1)), e = r, ye[n] = {
+                nextPos: fe,
                 result: e
               }, e);
             }()) === i && (e = function () {
               var e,
                   r,
                   n,
-                  s,
                   o,
-                  a = 30 * pe + 27,
-                  l = xe[a];
-              if (l) return pe = l.nextPos, l.result;
-              if (e = pe, ":nth-child(" === t.substr(pe, 11) ? (r = ":nth-child(", pe += 11) : (r = i, Ae(ne)), r !== i) {
-                if (_e() !== i) {
-                  if (n = [], q.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(N)), s !== i) for (; s !== i;) n.push(s), q.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(N));else n = i;
-                  n !== i && (s = _e()) !== i ? (41 === t.charCodeAt(pe) ? (o = ")", pe++) : (o = i, Ae(z)), o !== i ? (r = Ie(parseInt(n.join(""), 10)), e = r) : (pe = e, e = i)) : (pe = e, e = i);
-                } else pe = e, e = i;
-              } else pe = e, e = i;
-              return xe[a] = {
-                nextPos: pe,
+                  a,
+                  s = 30 * fe + 27,
+                  l = ye[s];
+              if (l) return fe = l.nextPos, l.result;
+              if (e = fe, ":nth-child(" === t.substr(fe, 11) ? (r = ":nth-child(", fe += 11) : (r = i, Ae(ne)), r !== i) {
+                if (Ee() !== i) {
+                  if (n = [], q.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(N)), o !== i) for (; o !== i;) n.push(o), q.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(N));else n = i;
+                  n !== i && (o = Ee()) !== i ? (41 === t.charCodeAt(fe) ? (a = ")", fe++) : (a = i, Ae(K)), a !== i ? (r = Ie(parseInt(n.join(""), 10)), e = r) : (fe = e, e = i)) : (fe = e, e = i);
+                } else fe = e, e = i;
+              } else fe = e, e = i;
+              return ye[s] = {
+                nextPos: fe,
                 result: e
               }, e;
             }()) === i && (e = function () {
               var e,
                   r,
                   n,
-                  s,
                   o,
-                  a = 30 * pe + 28,
-                  l = xe[a];
-              if (l) return pe = l.nextPos, l.result;
-              if (e = pe, ":nth-last-child(" === t.substr(pe, 16) ? (r = ":nth-last-child(", pe += 16) : (r = i, Ae(se)), r !== i) {
-                if (_e() !== i) {
-                  if (n = [], q.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(N)), s !== i) for (; s !== i;) n.push(s), q.test(t.charAt(pe)) ? (s = t.charAt(pe), pe++) : (s = i, Ae(N));else n = i;
-                  n !== i && (s = _e()) !== i ? (41 === t.charCodeAt(pe) ? (o = ")", pe++) : (o = i, Ae(z)), o !== i ? (r = je(parseInt(n.join(""), 10)), e = r) : (pe = e, e = i)) : (pe = e, e = i);
-                } else pe = e, e = i;
-              } else pe = e, e = i;
-              return xe[a] = {
-                nextPos: pe,
+                  a,
+                  s = 30 * fe + 28,
+                  l = ye[s];
+              if (l) return fe = l.nextPos, l.result;
+              if (e = fe, ":nth-last-child(" === t.substr(fe, 16) ? (r = ":nth-last-child(", fe += 16) : (r = i, Ae(oe)), r !== i) {
+                if (Ee() !== i) {
+                  if (n = [], q.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(N)), o !== i) for (; o !== i;) n.push(o), q.test(t.charAt(fe)) ? (o = t.charAt(fe), fe++) : (o = i, Ae(N));else n = i;
+                  n !== i && (o = Ee()) !== i ? (41 === t.charCodeAt(fe) ? (a = ")", fe++) : (a = i, Ae(K)), a !== i ? (r = je(parseInt(n.join(""), 10)), e = r) : (fe = e, e = i)) : (fe = e, e = i);
+                } else fe = e, e = i;
+              } else fe = e, e = i;
+              return ye[s] = {
+                nextPos: fe,
                 result: e
               }, e;
             }()) === i && (e = function () {
               var e,
                   r,
                   n,
-                  s = 30 * pe + 29,
-                  o = xe[s];
-              return o ? (pe = o.nextPos, o.result) : (e = pe, 58 === t.charCodeAt(pe) ? (r = ":", pe++) : (r = i, Ae(oe)), r !== i ? ("statement" === t.substr(pe, 9).toLowerCase() ? (n = t.substr(pe, 9), pe += 9) : (n = i, Ae(ae)), n === i && ("expression" === t.substr(pe, 10).toLowerCase() ? (n = t.substr(pe, 10), pe += 10) : (n = i, Ae(ie)), n === i && ("declaration" === t.substr(pe, 11).toLowerCase() ? (n = t.substr(pe, 11), pe += 11) : (n = i, Ae(le)), n === i && ("function" === t.substr(pe, 8).toLowerCase() ? (n = t.substr(pe, 8), pe += 8) : (n = i, Ae(ue)), n === i && ("pattern" === t.substr(pe, 7).toLowerCase() ? (n = t.substr(pe, 7), pe += 7) : (n = i, Ae(ce)))))), n !== i ? e = r = {
+                  o = 30 * fe + 29,
+                  a = ye[o];
+              return a ? (fe = a.nextPos, a.result) : (e = fe, 58 === t.charCodeAt(fe) ? (r = ":", fe++) : (r = i, Ae(ae)), r !== i ? ("statement" === t.substr(fe, 9).toLowerCase() ? (n = t.substr(fe, 9), fe += 9) : (n = i, Ae(se)), n === i && ("expression" === t.substr(fe, 10).toLowerCase() ? (n = t.substr(fe, 10), fe += 10) : (n = i, Ae(ie)), n === i && ("declaration" === t.substr(fe, 11).toLowerCase() ? (n = t.substr(fe, 11), fe += 11) : (n = i, Ae(le)), n === i && ("function" === t.substr(fe, 8).toLowerCase() ? (n = t.substr(fe, 8), fe += 8) : (n = i, Ae(ue)), n === i && ("pattern" === t.substr(fe, 7).toLowerCase() ? (n = t.substr(fe, 7), fe += 7) : (n = i, Ae(ce)))))), n !== i ? e = r = {
                 type: "class",
                 name: n
-              } : (pe = e, e = i)) : (pe = e, e = i), xe[s] = {
-                nextPos: pe,
+              } : (fe = e, e = i)) : (fe = e, e = i), ye[o] = {
+                nextPos: fe,
                 result: e
               }, e);
-            }()), xe[r] = {
-              nextPos: pe,
+            }()), ye[r] = {
+              nextPos: fe,
               result: e
             }, e);
           }
@@ -124861,12 +125138,12 @@ module.exports = NodeEventGenerator;
             var e,
                 r,
                 n,
-                s = 30 * pe + 13,
-                o = xe[s];
-            if (o) return pe = o.nextPos, o.result;
-            if (r = [], (n = be()) === i && (46 === t.charCodeAt(pe) ? (n = ".", pe++) : (n = i, Ae(D))), n !== i) for (; n !== i;) r.push(n), (n = be()) === i && (46 === t.charCodeAt(pe) ? (n = ".", pe++) : (n = i, Ae(D)));else r = i;
-            return r !== i && (r = h(r)), e = r, xe[s] = {
-              nextPos: pe,
+                o = 30 * fe + 13,
+                a = ye[o];
+            if (a) return fe = a.nextPos, a.result;
+            if (r = [], (n = Se()) === i && (46 === t.charCodeAt(fe) ? (n = ".", fe++) : (n = i, Ae(D))), n !== i) for (; n !== i;) r.push(n), (n = Se()) === i && (46 === t.charCodeAt(fe) ? (n = ".", fe++) : (n = i, Ae(D)));else r = i;
+            return r !== i && (r = h(r)), e = r, ye[o] = {
+              nextPos: fe,
               result: e
             }, e;
           }
@@ -124891,182 +125168,177 @@ module.exports = NodeEventGenerator;
             };
           }
 
-          if ((n = u()) !== i && pe === t.length) return n;
-          throw n !== i && pe < t.length && Ae({
+          if ((n = u()) !== i && fe === t.length) return n;
+          throw n !== i && fe < t.length && Ae({
             type: "end"
-          }), s = de, o = he < t.length ? t.charAt(he) : null, a = he < t.length ? ve(he, he + 1) : ve(he, he), new e(e.buildMessage(s, o), s, o, a);
+          }), o = de, a = he < t.length ? t.charAt(he) : null, s = he < t.length ? ve(he, he + 1) : ve(he, he), new e(e.buildMessage(o, a), o, a, s);
         }
       };
     }());
   });
 
-  function n(e, r, i) {
+  function l(t, r, n) {
     if (!r) return !0;
-    if (!e) return !1;
+    if (!t) return !1;
 
-    switch (i || (i = []), r.type) {
+    switch (n || (n = []), r.type) {
       case "wildcard":
         return !0;
 
       case "identifier":
-        return r.value.toLowerCase() === e.type.toLowerCase();
+        return r.value.toLowerCase() === t.type.toLowerCase();
 
       case "field":
-        {
-          const t = r.name.split(".");
-          return function e(t, r, n) {
-            if (0 === n.length) return t === r;
-            if (null == r) return !1;
-            const s = r[n[0]],
-                  o = n.slice(1);
+        var o = r.name.split("."),
+            a = n[o.length - 1];
+        return function e(t, r, n) {
+          if (0 === n.length) return t === r;
+          if (null == r) return !1;
+          var o = r[n[0]],
+              a = n.slice(1);
 
-            if (Array.isArray(s)) {
-              for (let r = 0, n = s.length; r < n; ++r) if (e(t, s[r], o)) return !0;
+          if (Array.isArray(o)) {
+            for (var s = 0, i = o.length; s < i; ++s) if (e(t, o[s], a)) return !0;
 
-              return !1;
-            }
+            return !1;
+          }
 
-            return e(t, s, o);
-          }(e, i[t.length - 1], t);
-        }
+          return e(t, o, a);
+        }(t, a, o);
 
       case "matches":
-        for (let t = 0, s = r.selectors.length; t < s; ++t) if (n(e, r.selectors[t], i)) return !0;
+        for (var i = 0, p = r.selectors.length; i < p; ++i) if (l(t, r.selectors[i], n)) return !0;
 
         return !1;
 
       case "compound":
-        for (let t = 0, s = r.selectors.length; t < s; ++t) if (!n(e, r.selectors[t], i)) return !1;
+        for (var h = 0, d = r.selectors.length; h < d; ++h) if (!l(t, r.selectors[h], n)) return !1;
 
         return !0;
 
       case "not":
-        for (let t = 0, s = r.selectors.length; t < s; ++t) if (n(e, r.selectors[t], i)) return !1;
+        for (var y = 0, m = r.selectors.length; y < m; ++y) if (l(t, r.selectors[y], n)) return !1;
 
         return !0;
 
       case "has":
-        {
-          const s = [];
-
-          for (let o = 0, a = r.selectors.length; o < a; ++o) {
-            const a = [];
-            t.traverse(e, {
-              enter(e, t) {
-                null != t && a.unshift(t), n(e, r.selectors[o], a) && s.push(e);
+        var x = function () {
+          for (var e = [], n = function n(_n, o) {
+            var a = [];
+            s.traverse(t, {
+              enter: function enter(t, o) {
+                null != o && a.unshift(o), l(t, r.selectors[_n], a) && e.push(t);
               },
-
-              leave() {
+              leave: function leave() {
                 a.shift();
               },
-
               fallback: "iteration"
             });
-          }
+          }, o = 0, a = r.selectors.length; o < a; ++o) n(o);
 
-          return 0 !== s.length;
-        }
+          return {
+            v: 0 !== e.length
+          };
+        }();
+
+        if ("object" === e(x)) return x.v;
 
       case "child":
-        return !!n(e, r.right, i) && n(i[0], r.left, i.slice(1));
+        return !!l(t, r.right, n) && l(n[0], r.left, n.slice(1));
 
       case "descendant":
-        if (n(e, r.right, i)) for (let e = 0, t = i.length; e < t; ++e) if (n(i[e], r.left, i.slice(e + 1))) return !0;
+        if (l(t, r.right, n)) for (var g = 0, v = n.length; g < v; ++g) if (l(n[g], r.left, n.slice(g + 1))) return !0;
         return !1;
 
       case "attribute":
-        {
-          const t = function (e, t) {
-            const r = t.split(".");
-
-            for (let t = 0; t < r.length; t++) {
-              if (null == e) return e;
-              e = e[r[t]];
-            }
-
-            return e;
-          }(e, r.name);
+        var A = function (e, t) {
+          for (var r = t.split("."), n = 0; n < r.length; n++) {
+            if (null == e) return e;
+            e = e[r[n]];
+          }
 
-          switch (r.operator) {
-            case void 0:
-              return null != t;
+          return e;
+        }(t, r.name);
 
-            case "=":
-              switch (r.value.type) {
-                case "regexp":
-                  return "string" == typeof t && r.value.value.test(t);
+        switch (r.operator) {
+          case void 0:
+            return null != A;
 
-                case "literal":
-                  return "".concat(r.value.value) === "".concat(t);
+          case "=":
+            switch (r.value.type) {
+              case "regexp":
+                return "string" == typeof A && r.value.value.test(A);
 
-                case "type":
-                  return r.value.value === typeof t;
-              }
+              case "literal":
+                return "".concat(r.value.value) === "".concat(A);
 
-              throw new Error("Unknown selector value type: ".concat(r.value.type));
+              case "type":
+                return r.value.value === e(A);
+            }
 
-            case "!=":
-              switch (r.value.type) {
-                case "regexp":
-                  return !r.value.value.test(t);
+            throw new Error("Unknown selector value type: ".concat(r.value.type));
 
-                case "literal":
-                  return "".concat(r.value.value) !== "".concat(t);
+          case "!=":
+            switch (r.value.type) {
+              case "regexp":
+                return !r.value.value.test(A);
 
-                case "type":
-                  return r.value.value !== typeof t;
-              }
+              case "literal":
+                return "".concat(r.value.value) !== "".concat(A);
 
-              throw new Error("Unknown selector value type: ".concat(r.value.type));
+              case "type":
+                return r.value.value !== e(A);
+            }
 
-            case "<=":
-              return t <= r.value.value;
+            throw new Error("Unknown selector value type: ".concat(r.value.type));
 
-            case "<":
-              return t < r.value.value;
+          case "<=":
+            return A <= r.value.value;
 
-            case ">":
-              return t > r.value.value;
+          case "<":
+            return A < r.value.value;
 
-            case ">=":
-              return t >= r.value.value;
-          }
+          case ">":
+            return A > r.value.value;
 
-          throw new Error("Unknown operator: ".concat(r.operator));
+          case ">=":
+            return A >= r.value.value;
         }
 
+        throw new Error("Unknown operator: ".concat(r.operator));
+
       case "sibling":
-        return n(e, r.right, i) && s(e, r.left, i, "LEFT_SIDE") || r.left.subject && n(e, r.left, i) && s(e, r.right, i, "RIGHT_SIDE");
+        return l(t, r.right, n) && u(t, r.left, n, "LEFT_SIDE") || r.left.subject && l(t, r.left, n) && u(t, r.right, n, "RIGHT_SIDE");
 
       case "adjacent":
-        return n(e, r.right, i) && o(e, r.left, i, "LEFT_SIDE") || r.right.subject && n(e, r.left, i) && o(e, r.right, i, "RIGHT_SIDE");
+        return l(t, r.right, n) && c(t, r.left, n, "LEFT_SIDE") || r.right.subject && l(t, r.left, n) && c(t, r.right, n, "RIGHT_SIDE");
 
       case "nth-child":
-        return n(e, r.right, i) && a(e, i, function () {
+        return l(t, r.right, n) && f(t, n, function () {
           return r.index.value - 1;
         });
 
       case "nth-last-child":
-        return n(e, r.right, i) && a(e, i, function (e) {
+        return l(t, r.right, n) && f(t, n, function (e) {
           return e - r.index.value;
         });
 
       case "class":
         switch (r.name.toLowerCase()) {
           case "statement":
-            if ("Statement" === e.type.slice(-9)) return !0;
+            if ("Statement" === t.type.slice(-9)) return !0;
 
           case "declaration":
-            return "Declaration" === e.type.slice(-11);
+            return "Declaration" === t.type.slice(-11);
 
           case "pattern":
-            if ("Pattern" === e.type.slice(-7)) return !0;
+            if ("Pattern" === t.type.slice(-7)) return !0;
 
           case "expression":
-            return "Expression" === e.type.slice(-10) || "Literal" === e.type.slice(-7) || "Identifier" === e.type && (0 === i.length || "MetaProperty" !== i[0].type) || "MetaProperty" === e.type;
+            return "Expression" === t.type.slice(-10) || "Literal" === t.type.slice(-7) || "Identifier" === t.type && (0 === n.length || "MetaProperty" !== n[0].type) || "MetaProperty" === t.type;
 
           case "function":
-            return "FunctionDeclaration" === e.type || "FunctionExpression" === e.type || "ArrowFunctionExpression" === e.type;
+            return "FunctionDeclaration" === t.type || "FunctionExpression" === t.type || "ArrowFunctionExpression" === t.type;
         }
 
         throw new Error("Unknown class name: ".concat(r.name));
@@ -125075,104 +125347,118 @@ module.exports = NodeEventGenerator;
     throw new Error("Unknown selector type: ".concat(r.type));
   }
 
-  function s(e, r, s, o) {
-    const [a] = s;
+  function u(e, r, n, o) {
+    var a = t(n, 1)[0];
     if (!a) return !1;
-    const i = t.VisitorKeys[a.type];
 
-    for (let t = 0, l = i.length; t < l; ++t) {
-      const l = a[i[t]];
+    for (var i = s.VisitorKeys[a.type], u = 0, c = i.length; u < c; ++u) {
+      var f = a[i[u]];
 
-      if (Array.isArray(l)) {
-        const t = l.indexOf(e);
-        if (t < 0) continue;
-        let a, i;
-        "LEFT_SIDE" === o ? (a = 0, i = t) : (a = t + 1, i = l.length);
+      if (Array.isArray(f)) {
+        var p = f.indexOf(e);
+        if (p < 0) continue;
+        var h = void 0,
+            d = void 0;
+        "LEFT_SIDE" === o ? (h = 0, d = p) : (h = p + 1, d = f.length);
 
-        for (let e = a; e < i; ++e) if (n(l[e], r, s)) return !0;
+        for (var y = h; y < d; ++y) if (l(f[y], r, n)) return !0;
       }
     }
 
     return !1;
   }
 
-  function o(e, r, s, o) {
-    const [a] = s;
+  function c(e, r, n, o) {
+    var a = t(n, 1)[0];
     if (!a) return !1;
-    const i = t.VisitorKeys[a.type];
 
-    for (let t = 0, l = i.length; t < l; ++t) {
-      const l = a[i[t]];
+    for (var i = s.VisitorKeys[a.type], u = 0, c = i.length; u < c; ++u) {
+      var f = a[i[u]];
 
-      if (Array.isArray(l)) {
-        const t = l.indexOf(e);
-        if (t < 0) continue;
-        if ("LEFT_SIDE" === o && t > 0 && n(l[t - 1], r, s)) return !0;
-        if ("RIGHT_SIDE" === o && t < l.length - 1 && n(l[t + 1], r, s)) return !0;
+      if (Array.isArray(f)) {
+        var p = f.indexOf(e);
+        if (p < 0) continue;
+        if ("LEFT_SIDE" === o && p > 0 && l(f[p - 1], r, n)) return !0;
+        if ("RIGHT_SIDE" === o && p < f.length - 1 && l(f[p + 1], r, n)) return !0;
       }
     }
 
     return !1;
   }
 
-  function a(e, r, n) {
-    const [s] = r;
-    if (!s) return !1;
-    const o = t.VisitorKeys[s.type];
+  function f(e, r, n) {
+    var o = t(r, 1)[0];
+    if (!o) return !1;
 
-    for (let t = 0, r = o.length; t < r; ++t) {
-      const r = s[o[t]];
+    for (var a = s.VisitorKeys[o.type], i = 0, l = a.length; i < l; ++i) {
+      var u = o[a[i]];
 
-      if (Array.isArray(r)) {
-        const t = r.indexOf(e);
-        if (t >= 0 && t === n(r.length)) return !0;
+      if (Array.isArray(u)) {
+        var c = u.indexOf(e);
+        if (c >= 0 && c === n(u.length)) return !0;
       }
     }
 
     return !1;
   }
 
-  function i(e, r) {
-    const s = [],
-          o = [];
-    if (!r) return o;
+  function p(n, o) {
+    if (null == n || "object" != e(n)) return [];
+    null == o && (o = n);
 
-    const a = function e(t, r) {
-      if (null == t || "object" != typeof t) return [];
-      null == r && (r = t);
-      const n = t.subject ? [r] : [];
+    for (var a = n.subject ? [o] : [], s = 0, i = function (e) {
+      for (var t = [], r = Object.keys(e), n = 0; n < r.length; n++) t.push([r[n], e[r[n]]]);
 
-      for (const [s, o] of Object.entries(t)) n.push(...e(o, "left" === s ? o : r));
-
-      return n;
-    }(r);
+      return t;
+    }(n); s < i.length; s++) {
+      var l = t(i[s], 2),
+          u = l[0],
+          c = l[1];
+      a.push.apply(a, r(p(c, "left" === u ? c : o)));
+    }
 
-    return t.traverse(e, {
-      enter(e, t) {
-        if (null != t && s.unshift(t), n(e, r, s)) if (a.length) for (let t = 0, r = a.length; t < r; ++t) {
-          n(e, a[t], s) && o.push(e);
+    return a;
+  }
 
-          for (let e = 0, r = s.length; e < r; ++e) n(s[e], a[t], s.slice(e + 1)) && o.push(s[e]);
-        } else o.push(e);
-      },
+  function h(e, t, r) {
+    if (t) {
+      var n = [],
+          o = p(t);
+      s.traverse(e, {
+        enter: function enter(e, a) {
+          if (null != a && n.unshift(a), l(e, t, n)) if (o.length) for (var s = 0, i = o.length; s < i; ++s) {
+            l(e, o[s], n) && r(e, a, n);
 
-      leave() {
-        s.shift();
-      },
+            for (var u = 0, c = n.length; u < c; ++u) {
+              var f = n.slice(u + 1);
+              l(n[u], o[s], f) && r(n[u], a, f);
+            }
+          } else r(e, a, n);
+        },
+        leave: function leave() {
+          n.shift();
+        },
+        fallback: "iteration"
+      });
+    }
+  }
 
-      fallback: "iteration"
-    }), o;
+  function d(e, t) {
+    var r = [];
+    return h(e, t, function (e) {
+      r.push(e);
+    }), r;
   }
 
-  function l(e) {
-    return r.parse(e);
+  function y(e) {
+    return i.parse(e);
   }
 
-  function u(e, t) {
-    return i(e, l(t));
+  function m(e, t) {
+    return d(e, y(t));
   }
 
-  return u.parse = l, u.match = i, u.matches = n, u.query = u, u;
+  return m.parse = y, m.match = d, m.traverse = h, m.matches = l, m.query = m, m;
 });
 
 /***/ }),
@@ -125396,7 +125682,7 @@ function mapSuggestions(descriptor, sourceCode, messages) {
 
   return descriptor.suggest.map(suggestInfo => {
     const computedDesc = suggestInfo.desc || messages[suggestInfo.messageId];
-    return _objectSpread({}, suggestInfo, {
+    return _objectSpread(_objectSpread({}, suggestInfo), {}, {
       desc: interpolate(computedDesc, suggestInfo.data),
       fix: normalizeFixes(suggestInfo, sourceCode)
     });
@@ -126247,6 +126533,8 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]); //----------
 
 /** @typedef {import("../shared/types").ConfigData} ConfigData */
 
+/** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
+
 /** @typedef {import("../shared/types").LintMessage} LintMessage */
 
 /** @typedef {import("../shared/types").ParserOptions} ParserOptions */
@@ -126264,29 +126552,29 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]); //----------
 /**
  * The options to configure a CLI engine with.
  * @typedef {Object} CLIEngineOptions
- * @property {boolean} allowInlineConfig Enable or disable inline configuration comments.
- * @property {ConfigData} baseConfig Base config object, extended by all configs used with this CLIEngine instance
- * @property {boolean} cache Enable result caching.
- * @property {string} cacheLocation The cache file to use instead of .eslintcache.
- * @property {string} configFile The configuration file to use.
- * @property {string} cwd The value to use for the current working directory.
- * @property {string[]} envs An array of environments to load.
- * @property {string[]|null} extensions An array of file extensions to check.
- * @property {boolean|Function} fix Execute in autofix mode. If a function, should return a boolean.
- * @property {string[]} fixTypes Array of rule types to apply fixes for.
- * @property {string[]} globals An array of global variables to declare.
- * @property {boolean} ignore False disables use of .eslintignore.
- * @property {string} ignorePath The ignore file to use instead of .eslintignore.
- * @property {string|string[]} ignorePattern One or more glob patterns to ignore.
- * @property {boolean} useEslintrc False disables looking for .eslintrc
- * @property {string} parser The name of the parser to use.
- * @property {ParserOptions} parserOptions An object of parserOption settings to use.
- * @property {string[]} plugins An array of plugins to load.
- * @property {Record<string,RuleConf>} rules An object of rules to use.
- * @property {string[]} rulePaths An array of directories to load custom rules from.
- * @property {boolean} reportUnusedDisableDirectives `true` adds reports for unused eslint-disable directives
- * @property {boolean} globInputPaths Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
- * @property {string} resolvePluginsRelativeTo The folder where plugins should be resolved from, defaulting to the CWD
+ * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
+ * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this CLIEngine instance
+ * @property {boolean} [cache] Enable result caching.
+ * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
+ * @property {string} [configFile] The configuration file to use.
+ * @property {string} [cwd] The value to use for the current working directory.
+ * @property {string[]} [envs] An array of environments to load.
+ * @property {string[]|null} [extensions] An array of file extensions to check.
+ * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
+ * @property {string[]} [fixTypes] Array of rule types to apply fixes for.
+ * @property {string[]} [globals] An array of global variables to declare.
+ * @property {boolean} [ignore] False disables use of .eslintignore.
+ * @property {string} [ignorePath] The ignore file to use instead of .eslintignore.
+ * @property {string|string[]} [ignorePattern] One or more glob patterns to ignore.
+ * @property {boolean} [useEslintrc] False disables looking for .eslintrc
+ * @property {string} [parser] The name of the parser to use.
+ * @property {ParserOptions} [parserOptions] An object of parserOption settings to use.
+ * @property {string[]} [plugins] An array of plugins to load.
+ * @property {Record<string,RuleConf>} [rules] An object of rules to use.
+ * @property {string[]} [rulePaths] An array of directories to load custom rules from.
+ * @property {boolean} [reportUnusedDisableDirectives] `true` adds reports for unused eslint-disable directives
+ * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
+ * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD
  */
 
 /**
@@ -126302,13 +126590,6 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]); //----------
  * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
  */
 
-/**
- * Information of deprecated rules.
- * @typedef {Object} DeprecatedRuleInfo
- * @property {string} ruleId The rule ID.
- * @property {string[]} replacedBy The rule IDs that replace this deprecated rule.
- */
-
 /**
  * Linting results.
  * @typedef {Object} LintReport
@@ -126837,7 +127118,7 @@ class CLIEngine {
       const filteredMessages = result.messages.filter(isErrorMessage);
 
       if (filteredMessages.length > 0) {
-        filtered.push(_objectSpread({}, result, {
+        filtered.push(_objectSpread(_objectSpread({}, result), {}, {
           messages: filteredMessages,
           errorCount: filteredMessages.length,
           warningCount: 0,
@@ -127010,15 +127291,22 @@ class CLIEngine {
 
     if (lintResultCache) {
       lintResultCache.reconcile();
-    } // Collect used deprecated rules.
-
+    }
 
-    const usedDeprecatedRules = Array.from(iterateRuleDeprecationWarnings(lastConfigArrays));
     debug("Linting complete in: ".concat(Date.now() - startTime, "ms"));
-    return _objectSpread({
+    let usedDeprecatedRules;
+    return _objectSpread(_objectSpread({
       results
-    }, calculateStatsPerRun(results), {
-      usedDeprecatedRules
+    }, calculateStatsPerRun(results)), {}, {
+      // Initialize it lazily because CLI and `ESLint` API don't use it.
+      get usedDeprecatedRules() {
+        if (!usedDeprecatedRules) {
+          usedDeprecatedRules = Array.from(iterateRuleDeprecationWarnings(lastConfigArrays));
+        }
+
+        return usedDeprecatedRules;
+      }
+
     });
   }
   /**
@@ -127075,15 +127363,22 @@ class CLIEngine {
         fileEnumerator,
         linter
       }));
-    } // Collect used deprecated rules.
-
+    }
 
-    const usedDeprecatedRules = Array.from(iterateRuleDeprecationWarnings(lastConfigArrays));
     debug("Linting complete in: ".concat(Date.now() - startTime, "ms"));
-    return _objectSpread({
+    let usedDeprecatedRules;
+    return _objectSpread(_objectSpread({
       results
-    }, calculateStatsPerRun(results), {
-      usedDeprecatedRules
+    }, calculateStatsPerRun(results)), {}, {
+      // Initialize it lazily because CLI and `ESLint` API don't use it.
+      get usedDeprecatedRules() {
+        if (!usedDeprecatedRules) {
+          usedDeprecatedRules = Array.from(iterateRuleDeprecationWarnings(lastConfigArrays));
+        }
+
+        return usedDeprecatedRules;
+      }
+
     });
   }
   /**
@@ -127137,11 +127432,10 @@ class CLIEngine {
     return defaultIgnores(absolutePath);
   }
   /**
-   * Returns the formatter representing the given format or null if no formatter
-   * with the given name can be found.
+   * Returns the formatter representing the given format or null if the `format` is not a string.
    * @param {string} [format] The name of the format to load or the path to a
    *      custom formatter.
-   * @returns {Function} The formatter function or null if not found.
+   * @returns {(Function|null)} The formatter function or null if the `format` is not a string.
    */
 
 
@@ -127358,6 +127652,7 @@ const Module = __webpack_require__(828);
  * `Module.createRequire` is added in v12.2.0. It supports URL as well.
  * We only support the case where the argument is a filepath, not a URL.
  */
+// eslint-disable-next-line node/no-unsupported-features/node-builtins, node/no-deprecated-api
 
 
 const createRequire = Module.createRequire || Module.createRequireFromPath;
@@ -127704,6 +127999,18 @@ class CascadingConfigArrayFactory {
     debug("Load config files for ".concat(directoryPath, "."));
     return this._finalizeConfigArray(this._loadConfigInAncestors(directoryPath), directoryPath, ignoreNotFoundError);
   }
+  /**
+   * Set the config data to override all configs.
+   * Require to call `clearCache()` method after this method is called.
+   * @param {ConfigData} configData The config data to override all configs.
+   * @returns {void}
+   */
+
+
+  setOverrideConfig(configData) {
+    const slots = internalSlotsMap.get(this);
+    slots.cliConfigData = configData;
+  }
   /**
    * Clear config cache.
    * @returns {void}
@@ -128626,7 +128933,7 @@ class ConfigArrayFactory {
     }; // Flatten `overries`.
 
     for (let i = 0; i < overrideList.length; ++i) {
-      yield* this._normalizeObjectConfigData(overrideList[i], _objectSpread({}, ctx, {
+      yield* this._normalizeObjectConfigData(overrideList[i], _objectSpread(_objectSpread({}, ctx), {}, {
         name: "".concat(ctx.name, "#overrides[").concat(i, "]")
       }));
     }
@@ -128669,14 +128976,14 @@ class ConfigArrayFactory {
 
   _loadExtendedBuiltInConfig(extendName, ctx) {
     if (extendName === "eslint:recommended") {
-      return this._loadConfigData(_objectSpread({}, ctx, {
+      return this._loadConfigData(_objectSpread(_objectSpread({}, ctx), {}, {
         filePath: eslintRecommendedPath,
         name: "".concat(ctx.name, " \xBB ").concat(extendName)
       }));
     }
 
     if (extendName === "eslint:all") {
-      return this._loadConfigData(_objectSpread({}, ctx, {
+      return this._loadConfigData(_objectSpread(_objectSpread({}, ctx), {}, {
         filePath: eslintAllPath,
         name: "".concat(ctx.name, " \xBB ").concat(extendName)
       }));
@@ -128707,8 +129014,8 @@ class ConfigArrayFactory {
     const configData = plugin.definition && plugin.definition.configs[configName];
 
     if (configData) {
-      return this._normalizeConfigData(configData, _objectSpread({}, ctx, {
-        filePath: plugin.filePath,
+      return this._normalizeConfigData(configData, _objectSpread(_objectSpread({}, ctx), {}, {
+        filePath: plugin.filePath || ctx.filePath,
         name: "".concat(ctx.name, " \xBB plugin:").concat(plugin.id, "/").concat(configName)
       }));
     }
@@ -128753,7 +129060,7 @@ class ConfigArrayFactory {
     }
 
     writeDebugLogForLoading(request, relativeTo, filePath);
-    return this._loadConfigData(_objectSpread({}, ctx, {
+    return this._loadConfigData(_objectSpread(_objectSpread({}, ctx), {}, {
       filePath,
       name: "".concat(ctx.name, " \xBB ").concat(request)
     }));
@@ -128866,7 +129173,8 @@ class ConfigArrayFactory {
     if (plugin) {
       return new ConfigDependency({
         definition: normalizePlugin(plugin),
-        filePath: ctx.filePath,
+        filePath: "",
+        // It's unknown where the plugin came from.
         id,
         importerName: ctx.name,
         importerPath: ctx.filePath
@@ -128943,7 +129251,7 @@ class ConfigArrayFactory {
           yield* this._normalizeObjectConfigData({
             files: ["*".concat(processorId)],
             processor: "".concat(pluginId, "/").concat(processorId)
-          }, _objectSpread({}, ctx, {
+          }, _objectSpread(_objectSpread({}, ctx), {}, {
             type: "implicit-processor",
             name: "".concat(ctx.name, "#processors[\"").concat(pluginId, "/").concat(processorId, "\"]")
           }));
@@ -129162,6 +129470,10 @@ const isEscaped = (jsonString, quotePosition) => {
 };
 
 module.exports = (jsonString, options = {}) => {
+  if (typeof jsonString !== 'string') {
+    throw new TypeError("Expected argument `jsonString` to be a `string`, got `".concat(typeof jsonString, "`"));
+  }
+
   const strip = options.whitespace === false ? stripWithoutWhitespace : stripWithWhitespace;
   let insideString = false;
   let insideComment = false;
@@ -129384,7 +129696,7 @@ function getMatchedIndices(elements, filePath) {
   for (let i = elements.length - 1; i >= 0; --i) {
     const element = elements[i];
 
-    if (!element.criteria || element.criteria.test(filePath)) {
+    if (!element.criteria || filePath && element.criteria.test(filePath)) {
       indices.push(i);
     }
   }
@@ -130067,7 +130379,13 @@ function getCommonAncestorPath(sourcePaths) {
     }
   }
 
-  return result || path.sep;
+  let resolvedResult = result || path.sep; // if Windows common ancestor is root of drive must have trailing slash to be absolute.
+
+  if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
+    resolvedResult += path.sep;
+  }
+
+  return resolvedResult;
 }
 /**
  * Make relative path.
@@ -130342,7 +130660,7 @@ class ConfigDependency {
     const obj = this[util.inspect.custom](); // Display `error.message` (`Error#message` is unenumerable).
 
     if (obj.error instanceof Error) {
-      obj.error = _objectSpread({}, obj.error, {
+      obj.error = _objectSpread(_objectSpread({}, obj.error), {}, {
         message: obj.error.message
       });
     }
@@ -130459,7 +130777,7 @@ function toMatcher(patterns) {
   return patterns.map(pattern => {
     if (/^\.[/\\]/u.test(pattern)) {
       return new Minimatch(pattern.slice(2), // `./*.js` should not match with `subdir/foo.js`
-      _objectSpread({}, minimatchOpts, {
+      _objectSpread(_objectSpread({}, minimatchOpts), {}, {
         matchBase: false
       }));
     }
@@ -130596,7 +130914,7 @@ class OverrideTester {
 
   toJSON() {
     if (this.patterns.length === 1) {
-      return _objectSpread({}, patternToJson(this.patterns[0]), {
+      return _objectSpread(_objectSpread({}, patternToJson(this.patterns[0])), {}, {
         basePath: this.basePath
       });
     }
@@ -144700,7 +145018,7 @@ class FileEnumerator {
         : this.isTargetPath(filePath, config);
 
         if (matched) {
-          const ignored = this._isIgnoredFile(filePath, _objectSpread({}, options, {
+          const ignored = this._isIgnoredFile(filePath, _objectSpread(_objectSpread({}, options), {}, {
             config
           }));
 
@@ -144722,7 +145040,7 @@ class FileEnumerator {
           });
         }
 
-        const ignored = this._isIgnoredFile(filePath + path.sep, _objectSpread({}, options, {
+        const ignored = this._isIgnoredFile(filePath + path.sep, _objectSpread(_objectSpread({}, options), {}, {
           config
         }));
 
@@ -145980,7 +146298,7 @@ function mkdirP(p, opts, f, made) {
   var xfs = opts.fs || fs;
 
   if (mode === undefined) {
-    mode = _0777 & ~process.umask();
+    mode = _0777;
   }
 
   if (!made) made = null;
@@ -146027,7 +146345,7 @@ mkdirP.sync = function sync(p, opts, made) {
   var xfs = opts.fs || fs;
 
   if (mode === undefined) {
-    mode = _0777 & ~process.umask();
+    mode = _0777;
   }
 
   if (!made) made = null;