Repository: eslint/eslint (js)

Issue:
no-var fixed to incorrect code
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).

    This template is for bug reports. If you are here for another reason, please see below:

    1. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
    2. To request a rule change: https://eslint.org/docs/developer-guide/contributing/rule-changes
    3. To request a change that is not a bug fix, rule change, or new rule: https://eslint.org/docs/developer-guide/contributing/changes
    4. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint

    Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->

**Tell us about your environment**

* **ESLint Version:** v5.14.1/master
* **Node Version:** n/a
* **npm Version:** n/a

**What parser (default, Babel-ESLint, etc.) are you using?**
`@typescript-eslint/parser`
**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```js
{rules: {no-var: 2}}
```

</details>

**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**

<!-- Paste the source code below: -->
```js
declare var __IS_PRODUCTION__: boolean;
```

<!-- Paste the command you used to run ESLint: -->
```bash

```

**What did you expect to happen?**
not fixed to incorrect code

**What actually happened? Please include the actual, raw output from ESLint.**
```ts
let var __IS_PRODUCTION__: boolean;
```

**Are you willing to submit a pull request to fix this bug?**
yes

Pull request:
Fix: no-var fixed to incorrect code (fixes #11441)
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[ ] Documentation update
[x] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**
fixes #11441 

**Is there anything you'd like reviewers to focus on?**

the issue is related to typescript.
should this be a bugfix, or enhancement?

Patch:
diff --git a/README.md b/README.md
index 59ee57fc8..dbd2a5d47 100644
--- a/README.md
+++ b/README.md
@@ -86,9 +86,11 @@ Before filing an issue, please be sure to read the guidelines for what you're re
 
 ### I'm using JSCS, should I migrate to ESLint?
 
-Maybe, depending on how much you need it. [JSCS has reached end of life](https://eslint.org/blog/2016/07/jscs-end-of-life), but if it is working for you then there is no reason to move yet. There are still [a few issues](https://github.com/eslint/eslint/milestones/JSCS%20Compatibility) pending. We’ll announce when all of the changes necessary to support JSCS users in ESLint are complete and will start encouraging JSCS users to switch to ESLint at that time.
+Yes. [JSCS has reached end of life](https://eslint.org/blog/2016/07/jscs-end-of-life) and is no longer supported.
 
-If you are having issues with JSCS, you can try to move to ESLint. Have a look at our [migration guide](https://eslint.org/docs/user-guide/migrating-from-jscs).
+We have prepared a [migration guide](https://eslint.org/docs/user-guide/migrating-from-jscs) to help you convert your JSCS settings to an ESLint configuration.
+
+We are now at or near 100% compatibility with JSCS. If you try ESLint and believe we are not yet compatible with a JSCS rule/configuration, please create an issue (mentioning that it is a JSCS compatibility issue) and we will evaluate it as per our normal process.
 
 ### Does Prettier replace ESLint?
 
@@ -243,9 +245,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.gitkraken.com/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Fgitkraken.com&height=96" alt="GitKraken" height="96"></a> <a href="https://code.facebook.com/projects/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Fres.cloudinary.com%2Fopencollective%2Fimage%2Fupload%2Fv1508519428%2FS9gk78AS_400x400_fulq2l.jpg&height=96" alt="Facebook Open Source" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Fopencollective-production.s3-us-west-1.amazonaws.com%2Fbbdb9cc0-3b5d-11e9-9537-ad85092287b8.png&height=96" alt="Badoo" height="96"></a></p><h3>Silver Sponsors</h3>
+<p><a href="https://www.gitkraken.com/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Fgitkraken.com&height=96" alt="GitKraken" height="96"></a> <a href="https://code.facebook.com/projects/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Fres.cloudinary.com%2Fopencollective%2Fimage%2Fupload%2Fv1508519428%2FS9gk78AS_400x400_fulq2l.jpg&height=96" alt="Facebook Open Source" height="96"></a> <a href="https://badoo.com/team?utm_source=eslint"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Fopencollective-production.s3-us-west-1.amazonaws.com%2Fbbdb9cc0-3b5d-11e9-9537-ad85092287b8.png&height=96" alt="Badoo" height="96"></a> <a href="http://salesforce.com"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Fsalesforce.com&height=96" alt="Salesforce" height="96"></a></p><h3>Silver Sponsors</h3>
 <p><a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Fopencollective-production.s3-us-west-1.amazonaws.com%2F68ed8b70-ebf2-11e6-9958-cb7e79408c56.png&height=96" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
-<p><a href="http://faithlife.com/ref/about"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Ffaithlife.com&height=96" alt="Faithlife" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Fjsheroes.io&height=96" alt="JSHeroes " height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Ffiresticktricks.com&height=96" alt="Fire Stick Tricks" height="32"></a></p>
+<p><a href="http://faithlife.com/ref/about"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Ffaithlife.com&height=96" alt="Faithlife" height="32"></a> <a href="https://jsheroes.io/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Fjsheroes.io&height=96" alt="JSHeroes " height="32"></a> <a href="http://www.firesticktricks.com"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Ffiresticktricks.com&height=96" alt="Fire Stick Tricks" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Fmarfeel.com&height=96" alt="Marfeel" height="32"></a> <a href="https://usave.co.uk/utilities/broadband/"><img src="https://images.opencollective.com/proxy/images/?src=https%3A%2F%2Flogo.clearbit.com%2Fusave.co.uk&height=96" alt="Usave" height="32"></a></p>
 <!--sponsorsend-->
 
 ## Technology Sponsors
diff --git a/lib/cli-engine.js b/lib/cli-engine.js
index 7eaa97946..1f4020338 100644
--- a/lib/cli-engine.js
+++ b/lib/cli-engine.js
@@ -543,13 +543,14 @@ class CLIEngine {
 
             if (filteredMessages.length > 0) {
                 filtered.push(
-                    Object.assign(result, {
+                    {
+                        ...result,
                         messages: filteredMessages,
                         errorCount: filteredMessages.length,
                         warningCount: 0,
                         fixableErrorCount: result.fixableErrorCount,
                         fixableWarningCount: 0
-                    })
+                    }
                 );
             }
         });
diff --git a/lib/config/config-validator.js b/lib/config/config-validator.js
index 4db7cd563..c6d106e60 100644
--- a/lib/config/config-validator.js
+++ b/lib/config/config-validator.js
@@ -10,12 +10,12 @@
 //------------------------------------------------------------------------------
 
 const path = require("path"),
-    ajv = require("../util/ajv"),
     lodash = require("lodash"),
     configSchema = require("../../conf/config-schema.js"),
     util = require("util"),
     ConfigOps = require("./config-ops");
 
+const ajv = require("../util/ajv")();
 const ruleValidators = new WeakMap();
 
 //------------------------------------------------------------------------------
diff --git a/lib/rules/line-comment-position.js b/lib/rules/line-comment-position.js
index 9a91d4302..d2af56e8a 100644
--- a/lib/rules/line-comment-position.js
+++ b/lib/rules/line-comment-position.js
@@ -31,8 +31,7 @@ module.exports = {
                         type: "object",
                         properties: {
                             position: {
-                                enum: ["above", "beside"],
-                                default: "above"
+                                enum: ["above", "beside"]
                             },
                             ignorePattern: {
                                 type: "string"
diff --git a/lib/rules/max-len.js b/lib/rules/max-len.js
index 438e38b0a..24ceeffb3 100644
--- a/lib/rules/max-len.js
+++ b/lib/rules/max-len.js
@@ -14,8 +14,7 @@ const OPTIONS_SCHEMA = {
     properties: {
         code: {
             type: "integer",
-            minimum: 0,
-            default: 80
+            minimum: 0
         },
         comments: {
             type: "integer",
@@ -23,35 +22,28 @@ const OPTIONS_SCHEMA = {
         },
         tabWidth: {
             type: "integer",
-            minimum: 0,
-            default: 4
+            minimum: 0
         },
         ignorePattern: {
             type: "string"
         },
         ignoreComments: {
-            type: "boolean",
-            default: false
+            type: "boolean"
         },
         ignoreStrings: {
-            type: "boolean",
-            default: false
+            type: "boolean"
         },
         ignoreUrls: {
-            type: "boolean",
-            default: false
+            type: "boolean"
         },
         ignoreTemplateLiterals: {
-            type: "boolean",
-            default: false
+            type: "boolean"
         },
         ignoreRegExpLiterals: {
-            type: "boolean",
-            default: false
+            type: "boolean"
         },
         ignoreTrailingComments: {
-            type: "boolean",
-            default: false
+            type: "boolean"
         }
     },
     additionalProperties: false
@@ -141,14 +133,14 @@ module.exports = {
             options.tabWidth = context.options[1];
         }
 
-        const maxLength = options.code || 80,
-            tabWidth = options.tabWidth || 4,
-            ignoreComments = options.ignoreComments || false,
-            ignoreStrings = options.ignoreStrings || false,
-            ignoreTemplateLiterals = options.ignoreTemplateLiterals || false,
-            ignoreRegExpLiterals = options.ignoreRegExpLiterals || false,
-            ignoreTrailingComments = options.ignoreTrailingComments || options.ignoreComments || false,
-            ignoreUrls = options.ignoreUrls || false,
+        const maxLength = typeof options.code === "number" ? options.code : 80,
+            tabWidth = typeof options.tabWidth === "number" ? options.tabWidth : 4,
+            ignoreComments = !!options.ignoreComments,
+            ignoreStrings = !!options.ignoreStrings,
+            ignoreTemplateLiterals = !!options.ignoreTemplateLiterals,
+            ignoreRegExpLiterals = !!options.ignoreRegExpLiterals,
+            ignoreTrailingComments = !!options.ignoreTrailingComments || !!options.ignoreComments,
+            ignoreUrls = !!options.ignoreUrls,
             maxCommentLength = options.comments;
         let ignorePattern = options.ignorePattern || null;
 
diff --git a/lib/rules/max-lines-per-function.js b/lib/rules/max-lines-per-function.js
index 3b2f656fb..5abb3f0b8 100644
--- a/lib/rules/max-lines-per-function.js
+++ b/lib/rules/max-lines-per-function.js
@@ -19,20 +19,16 @@ const OPTIONS_SCHEMA = {
     properties: {
         max: {
             type: "integer",
-            minimum: 0,
-            default: 50
+            minimum: 0
         },
         skipComments: {
-            type: "boolean",
-            default: false
+            type: "boolean"
         },
         skipBlankLines: {
-            type: "boolean",
-            default: false
+            type: "boolean"
         },
         IIFEs: {
-            type: "boolean",
-            default: false
+            type: "boolean"
         }
     },
     additionalProperties: false
@@ -101,10 +97,10 @@ module.exports = {
         let IIFEs = false;
 
         if (typeof option === "object") {
-            maxLines = option.max;
-            skipComments = option.skipComments;
-            skipBlankLines = option.skipBlankLines;
-            IIFEs = option.IIFEs;
+            maxLines = typeof option.max === "number" ? option.max : 50;
+            skipComments = !!option.skipComments;
+            skipBlankLines = !!option.skipBlankLines;
+            IIFEs = !!option.IIFEs;
         } else if (typeof option === "number") {
             maxLines = option;
         }
diff --git a/lib/rules/no-loop-func.js b/lib/rules/no-loop-func.js
index e6063806a..f4531f3a7 100644
--- a/lib/rules/no-loop-func.js
+++ b/lib/rules/no-loop-func.js
@@ -157,13 +157,17 @@ module.exports = {
         type: "suggestion",
 
         docs: {
-            description: "disallow `function` declarations and expressions inside loop statements",
+            description: "disallow function declarations that contain unsafe references inside loop statements",
             category: "Best Practices",
             recommended: false,
             url: "https://eslint.org/docs/rules/no-loop-func"
         },
 
-        schema: []
+        schema: [],
+
+        messages: {
+            unsafeRefs: "Function declared in a loop contains unsafe references to variable(s) {{ varNames }}."
+        }
     },
 
     create(context) {
@@ -185,11 +189,14 @@ module.exports = {
             }
 
             const references = context.getScope().through;
-
-            if (references.length > 0 &&
-                !references.every(isSafe.bind(null, loopNode))
-            ) {
-                context.report({ node, message: "Don't make functions within a loop." });
+            const unsafeRefs = references.filter(r => !isSafe(loopNode, r)).map(r => r.identifier.name);
+
+            if (unsafeRefs.length > 0) {
+                context.report({
+                    node,
+                    messageId: "unsafeRefs",
+                    data: { varNames: `'${unsafeRefs.join("', '")}'` }
+                });
             }
         }
 
diff --git a/lib/rules/no-var.js b/lib/rules/no-var.js
index 83681a7aa..0978de634 100644
--- a/lib/rules/no-var.js
+++ b/lib/rules/no-var.js
@@ -305,17 +305,16 @@ module.exports = {
          * @returns {void}
          */
         function report(node) {
-            const varToken = sourceCode.getFirstToken(node);
-
             context.report({
                 node,
                 message: "Unexpected var, use let or const instead.",
 
                 fix(fixer) {
-                    if (canFix(node)) {
-                        return fixer.replaceText(varToken, "let");
-                    }
-                    return null;
+                    const varToken = sourceCode.getFirstToken(node, { filter: t => t.value === "var" });
+
+                    return canFix(node)
+                        ? fixer.replaceText(varToken, "let")
+                        : null;
                 }
             });
         }
diff --git a/lib/rules/object-shorthand.js b/lib/rules/object-shorthand.js
index 31010f0e7..6fa1b1834 100644
--- a/lib/rules/object-shorthand.js
+++ b/lib/rules/object-shorthand.js
@@ -113,6 +113,8 @@ module.exports = {
         // Helpers
         //--------------------------------------------------------------------------
 
+        const CTOR_PREFIX_REGEX = /[^_$0-9]/u;
+
         /**
          * Determines if the first character of the name is a capital letter.
          * @param {string} name The name of the node to evaluate.
@@ -120,7 +122,14 @@ module.exports = {
          * @private
          */
         function isConstructor(name) {
-            const firstChar = name.charAt(0);
+            const match = CTOR_PREFIX_REGEX.exec(name);
+
+            // Not a constructor if name has no characters apart from '_', '$' and digits e.g. '_', '$$', '_8'
+            if (!match) {
+                return false;
+            }
+
+            const firstChar = name.charAt(match.index);
 
             return firstChar === firstChar.toUpperCase();
         }
diff --git a/lib/rules/one-var.js b/lib/rules/one-var.js
index 0571cd338..e79461ce4 100644
--- a/lib/rules/one-var.js
+++ b/lib/rules/one-var.js
@@ -32,8 +32,7 @@ module.exports = {
                         type: "object",
                         properties: {
                             separateRequires: {
-                                type: "boolean",
-                                default: false
+                                type: "boolean"
                             },
                             var: {
                                 enum: ["always", "never", "consecutive"]
@@ -77,7 +76,7 @@ module.exports = {
             options.let = { uninitialized: mode, initialized: mode };
             options.const = { uninitialized: mode, initialized: mode };
         } else if (typeof mode === "object") { // options configuration is an object
-            options.separateRequires = mode.separateRequires;
+            options.separateRequires = !!mode.separateRequires;
             options.var = { uninitialized: mode.var, initialized: mode.var };
             options.let = { uninitialized: mode.let, initialized: mode.let };
             options.const = { uninitialized: mode.const, initialized: mode.const };
diff --git a/lib/util/ajv.js b/lib/util/ajv.js
index ecf0ebd17..3fb0fbdd3 100644
--- a/lib/util/ajv.js
+++ b/lib/util/ajv.js
@@ -15,17 +15,20 @@ const Ajv = require("ajv"),
 // Public Interface
 //------------------------------------------------------------------------------
 
-const ajv = new Ajv({
-    meta: false,
-    useDefaults: true,
-    validateSchema: false,
-    missingRefs: "ignore",
-    verbose: true,
-    schemaId: "auto"
-});
+module.exports = (additionalOptions = {}) => {
+    const ajv = new Ajv({
+        meta: false,
+        useDefaults: true,
+        validateSchema: false,
+        missingRefs: "ignore",
+        verbose: true,
+        schemaId: "auto",
+        ...additionalOptions
+    });
 
-ajv.addMetaSchema(metaSchema);
-// eslint-disable-next-line no-underscore-dangle
-ajv._opts.defaultMeta = metaSchema.id;
+    ajv.addMetaSchema(metaSchema);
+    // eslint-disable-next-line no-underscore-dangle
+    ajv._opts.defaultMeta = metaSchema.id;
 
-module.exports = ajv;
+    return ajv;
+};
diff --git a/package.json b/package.json
index 9bf5ff6d9..d478057ab 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
   "bugs": "https://github.com/eslint/eslint/issues/",
   "dependencies": {
     "@babel/code-frame": "^7.0.0",
-    "ajv": "^6.9.1",
+    "ajv": "^6.10.0",
     "chalk": "^2.1.0",
     "cross-spawn": "^6.0.5",
     "debug": "^4.0.1",
@@ -55,7 +55,7 @@
     "import-fresh": "^3.0.0",
     "imurmurhash": "^0.1.4",
     "inquirer": "^6.2.2",
-    "js-yaml": "^3.13.0",
+    "js-yaml": "^3.13.1",
     "json-stable-stringify-without-jsonify": "^1.0.1",
     "levn": "^0.3.0",
     "lodash": "^4.17.11",
@@ -72,16 +72,16 @@
     "text-table": "^0.2.0"
   },
   "devDependencies": {
-    "@babel/core": "^7.2.2",
-    "@babel/polyfill": "^7.2.5",
-    "@babel/preset-env": "^7.3.1",
+    "@babel/core": "^7.4.3",
+    "@babel/polyfill": "^7.4.3",
+    "@babel/preset-env": "^7.4.3",
     "babel-loader": "^8.0.5",
     "beefy": "^2.1.8",
-    "brfs": "^2.0.0",
+    "brfs": "^2.0.2",
     "chai": "^4.0.1",
     "cheerio": "^0.22.0",
     "common-tags": "^1.8.0",
-    "coveralls": "^3.0.1",
+    "coveralls": "^3.0.3",
     "dateformat": "^3.0.3",
     "ejs": "^2.6.1",
     "eslint-config-eslint": "file:packages/eslint-config-eslint",
@@ -99,19 +99,19 @@
     "karma-webpack": "^4.0.0-rc.6",
     "leche": "^2.2.3",
     "load-perf": "^0.2.0",
-    "markdownlint": "^0.12.0",
-    "mocha": "^5.0.5",
+    "markdownlint": "^0.13.0",
+    "mocha": "^6.1.2",
     "mock-fs": "^4.8.0",
     "npm-license": "^0.3.3",
     "nyc": "^13.3.0",
     "proxyquire": "^2.0.1",
-    "puppeteer": "^1.12.2",
+    "puppeteer": "^1.14.0",
     "shelljs": "^0.8.2",
     "sinon": "^3.3.0",
     "temp": "^0.9.0",
     "through": "^2.3.8",
-    "webpack": "^4.29.3",
-    "webpack-cli": "^3.2.3"
+    "webpack": "^4.29.6",
+    "webpack-cli": "^3.3.0"
   },
   "keywords": [
     "ast",


Test patch:
diff --git a/lib/testers/rule-tester.js b/lib/testers/rule-tester.js
index b0bfeac97..2cad541ce 100644
--- a/lib/testers/rule-tester.js
+++ b/lib/testers/rule-tester.js
@@ -45,12 +45,13 @@ const lodash = require("lodash"),
     path = require("path"),
     util = require("util"),
     validator = require("../config/config-validator"),
-    ajv = require("../util/ajv"),
     Linter = require("../linter"),
     Environments = require("../config/environments"),
     SourceCodeFixer = require("../util/source-code-fixer"),
     interpolate = require("../util/interpolate");
 
+const ajv = require("../util/ajv")({ strictDefaults: true });
+
 //------------------------------------------------------------------------------
 // Private Members
 //------------------------------------------------------------------------------
@@ -383,6 +384,18 @@ class RuleTester {
 
                     throw new Error([`Schema for rule ${ruleName} is invalid:`, errors]);
                 }
+
+                /*
+                 * `ajv.validateSchema` checks for errors in the structure of the schema (by comparing the schema against a "meta-schema"),
+                 * and it reports those errors individually. However, there are other types of schema errors that only occur when compiling
+                 * the schema (e.g. using invalid defaults in a schema), and only one of these errors can be reported at a time. As a result,
+                 * the schema is compiled here separately from checking for `validateSchema` errors.
+                 */
+                try {
+                    ajv.compile(schema);
+                } catch (err) {
+                    throw new Error(`Schema for rule ${ruleName} is invalid: ${err.message}`);
+                }
             }
 
             validator.validate(config, ruleMap.get.bind(ruleMap), new Environments(), "rule-tester");
diff --git a/tests/conf/config-schema.js b/tests/conf/config-schema.js
index 3fdb4bb03..09fa86061 100644
--- a/tests/conf/config-schema.js
+++ b/tests/conf/config-schema.js
@@ -9,10 +9,11 @@
 // Requirements
 //------------------------------------------------------------------------------
 
-const ajv = require("../../lib/util/ajv"),
-    configSchema = require("../../conf/config-schema.js"),
+const configSchema = require("../../conf/config-schema.js"),
     assert = require("assert");
 
+const ajv = require("../../lib/util/ajv")();
+
 //------------------------------------------------------------------------------
 // Tests
 //------------------------------------------------------------------------------
diff --git a/tests/fixtures/parsers/typescript-parsers/declare-var.js b/tests/fixtures/parsers/typescript-parsers/declare-var.js
new file mode 100644
index 000000000..68736259e
--- /dev/null
+++ b/tests/fixtures/parsers/typescript-parsers/declare-var.js
@@ -0,0 +1,215 @@
+"use strict";
+
+/*
+ * Parsed on astexplorer.net using @typescript-eslint/parser@1.4.2
+ *
+ * Source:
+ * declare var foo = 2;
+ */
+
+exports.parse = () => ({
+  "type": "Program",
+  "body": [
+    {
+      "type": "VariableDeclaration",
+      "declarations": [
+        {
+          "type": "VariableDeclarator",
+          "id": {
+            "type": "Identifier",
+            "name": "foo",
+            "range": [
+              12,
+              15
+            ],
+            "loc": {
+              "start": {
+                "line": 1,
+                "column": 12
+              },
+              "end": {
+                "line": 1,
+                "column": 15
+              }
+            }
+          },
+          "init": {
+            "type": "Literal",
+            "value": 2,
+            "raw": "2",
+            "range": [
+              18,
+              19
+            ],
+            "loc": {
+              "start": {
+                "line": 1,
+                "column": 18
+              },
+              "end": {
+                "line": 1,
+                "column": 19
+              }
+            }
+          },
+          "range": [
+            12,
+            19
+          ],
+          "loc": {
+            "start": {
+              "line": 1,
+              "column": 12
+            },
+            "end": {
+              "line": 1,
+              "column": 19
+            }
+          }
+        }
+      ],
+      "kind": "var",
+      "range": [
+        0,
+        20
+      ],
+      "loc": {
+        "start": {
+          "line": 1,
+          "column": 0
+        },
+        "end": {
+          "line": 1,
+          "column": 20
+        }
+      },
+      "declare": true
+    }
+  ],
+  "sourceType": "module",
+  "range": [
+    0,
+    20
+  ],
+  "loc": {
+    "start": {
+      "line": 1,
+      "column": 0
+    },
+    "end": {
+      "line": 1,
+      "column": 20
+    }
+  },
+  "tokens": [
+    {
+      "type": "Identifier",
+      "value": "declare",
+      "range": [
+        0,
+        7
+      ],
+      "loc": {
+        "start": {
+          "line": 1,
+          "column": 0
+        },
+        "end": {
+          "line": 1,
+          "column": 7
+        }
+      }
+    },
+    {
+      "type": "Keyword",
+      "value": "var",
+      "range": [
+        8,
+        11
+      ],
+      "loc": {
+        "start": {
+          "line": 1,
+          "column": 8
+        },
+        "end": {
+          "line": 1,
+          "column": 11
+        }
+      }
+    },
+    {
+      "type": "Identifier",
+      "value": "foo",
+      "range": [
+        12,
+        15
+      ],
+      "loc": {
+        "start": {
+          "line": 1,
+          "column": 12
+        },
+        "end": {
+          "line": 1,
+          "column": 15
+        }
+      }
+    },
+    {
+      "type": "Punctuator",
+      "value": "=",
+      "range": [
+        16,
+        17
+      ],
+      "loc": {
+        "start": {
+          "line": 1,
+          "column": 16
+        },
+        "end": {
+          "line": 1,
+          "column": 17
+        }
+      }
+    },
+    {
+      "type": "Numeric",
+      "value": "2",
+      "range": [
+        18,
+        19
+      ],
+      "loc": {
+        "start": {
+          "line": 1,
+          "column": 18
+        },
+        "end": {
+          "line": 1,
+          "column": 19
+        }
+      }
+    },
+    {
+      "type": "Punctuator",
+      "value": ";",
+      "range": [
+        19,
+        20
+      ],
+      "loc": {
+        "start": {
+          "line": 1,
+          "column": 19
+        },
+        "end": {
+          "line": 1,
+          "column": 20
+        }
+      }
+    }
+  ],
+  "comments": []
+});
diff --git a/tests/lib/cli-engine.js b/tests/lib/cli-engine.js
index d871bf662..cff648d49 100644
--- a/tests/lib/cli-engine.js
+++ b/tests/lib/cli-engine.js
@@ -3111,6 +3111,20 @@ describe("CLIEngine", () => {
             assert.strictEqual(errorResults[0].messages[4].severity, 2);
         });
 
+        it("should not mutate passed report.results parameter", () => {
+            process.chdir(originalDir);
+            const engine = new CLIEngine({
+                rules: { quotes: [1, "double"] }
+            });
+
+            const report = engine.executeOnText("var foo = 'bar';");
+            const reportResultsLength = report.results[0].messages.length;
+
+            CLIEngine.getErrorResults(report.results);
+
+            assert.lengthOf(report.results[0].messages, reportResultsLength);
+        });
+
         it("should report a warningCount of 0 when looking for errors only", () => {
 
             process.chdir(originalDir);
diff --git a/tests/lib/rules/max-len.js b/tests/lib/rules/max-len.js
index 41b0efe9b..0af7965b6 100644
--- a/tests/lib/rules/max-len.js
+++ b/tests/lib/rules/max-len.js
@@ -184,6 +184,11 @@ ruleTester.run("max-len", rule, {
         {
             code: "var longNameLongName = '𝌆𝌆'",
             options: [5, { ignorePattern: "𝌆{2}" }]
+        },
+
+        {
+            code: "\tfoo",
+            options: [4, { tabWidth: 0 }]
         }
     ],
 
@@ -625,6 +630,20 @@ ruleTester.run("max-len", rule, {
                     column: 1
                 }
             ]
+        },
+
+        {
+            code: "a",
+            options: [0],
+            errors: [
+                {
+                    messageId: "max",
+                    data: { lineNumber: 1, maxLength: 0 },
+                    type: "Program",
+                    line: 1,
+                    column: 1
+                }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/max-lines-per-function.js b/tests/lib/rules/max-lines-per-function.js
index 9046a1406..2879c2b62 100644
--- a/tests/lib/rules/max-lines-per-function.js
+++ b/tests/lib/rules/max-lines-per-function.js
@@ -205,6 +205,15 @@ if ( x === y ) {
             ]
         },
 
+        // Test that option defaults work as expected
+        {
+            code: `() => {${"foo\n".repeat(60)}}`,
+            options: [{}],
+            errors: [
+                { messageId: "exceed", data: { name: "arrow function", lineCount: 61, maxLines: 50 } }
+            ]
+        },
+
         // Test skipBlankLines: false
         {
             code: "function name() {\nvar x = 5;\n\t\n \n\nvar x = 2;\n}",
diff --git a/tests/lib/rules/no-loop-func.js b/tests/lib/rules/no-loop-func.js
index 08ccd1c5d..843cdaa8a 100644
--- a/tests/lib/rules/no-loop-func.js
+++ b/tests/lib/rules/no-loop-func.js
@@ -16,8 +16,7 @@ const rule = require("../../../lib/rules/no-loop-func"),
 // Tests
 //------------------------------------------------------------------------------
 
-const ruleTester = new RuleTester(),
-    expectedErrorMessage = "Don't make functions within a loop.";
+const ruleTester = new RuleTester();
 
 ruleTester.run("no-loop-func", rule, {
     valid: [
@@ -117,117 +116,121 @@ ruleTester.run("no-loop-func", rule, {
     invalid: [
         {
             code: "for (var i=0; i<l; i++) { (function() { i; }) }",
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "FunctionExpression" }]
+        },
+        {
+            code: "for (var i=0; i<l; i++) { for (var j=0; j<m; j++) { (function() { i+j; }) } }",
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i', 'j'" }, type: "FunctionExpression" }]
         },
         {
             code: "for (var i in {}) { (function() { i; }) }",
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "FunctionExpression" }]
         },
         {
             code: "for (var i of {}) { (function() { i; }) }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "FunctionExpression" }]
         },
         {
             code: "for (var i=0; i < l; i++) { (() => { i; }) }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "ArrowFunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "ArrowFunctionExpression" }]
         },
         {
             code: "for (var i=0; i < l; i++) { var a = function() { i; } }",
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "FunctionExpression" }]
         },
         {
             code: "for (var i=0; i < l; i++) { function a() { i; }; a(); }",
-            errors: [{ message: expectedErrorMessage, type: "FunctionDeclaration" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "FunctionDeclaration" }]
         },
         {
             code: "for (var i=0; (function() { i; })(), i<l; i++) { }",
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "FunctionExpression" }]
         },
         {
             code: "for (var i=0; i<l; (function() { i; })(), i++) { }",
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "FunctionExpression" }]
         },
         {
             code: "while(i) { (function() { i; }) }",
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "FunctionExpression" }]
         },
         {
             code: "do { (function() { i; }) } while (i)",
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "FunctionExpression" }]
         },
 
         // Warns functions which are using modified variables.
         {
             code: "let a; for (let i=0; i<l; i++) { a = 1; (function() { a; });}",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "FunctionExpression" }]
         },
         {
             code: "let a; for (let i in {}) { (function() { a; }); a = 1; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "FunctionExpression" }]
         },
         {
             code: "let a; for (let i of {}) { (function() { a; }); } a = 1; ",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "FunctionExpression" }]
         },
         {
             code: "let a; for (let i=0; i<l; i++) { (function() { (function() { a; }); }); a = 1; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "FunctionExpression" }]
         },
         {
             code: "let a; for (let i in {}) { a = 1; function foo() { (function() { a; }); } }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionDeclaration" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "FunctionDeclaration" }]
         },
         {
             code: "let a; for (let i of {}) { (() => { (function() { a; }); }); } a = 1;",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "ArrowFunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "ArrowFunctionExpression" }]
         },
         {
             code: "for (var i = 0; i < 10; ++i) { for (let x in xs.filter(x => x != i)) {  } }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "ArrowFunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'i'" }, type: "ArrowFunctionExpression" }]
         },
         {
             code: "for (let x of xs) { let a; for (let y of ys) { a = 1; (function() { a; }); } }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "FunctionExpression" }]
         },
         {
             code: "for (var x of xs) { for (let y of ys) { (function() { x; }); } }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'x'" }, type: "FunctionExpression" }]
         },
         {
             code: "for (var x of xs) { (function() { x; }); }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'x'" }, type: "FunctionExpression" }]
         },
         {
             code: "var a; for (let x of xs) { a = 1; (function() { a; }); }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "FunctionExpression" }]
         },
         {
             code: "var a; for (let x of xs) { (function() { a; }); a = 1; }",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "FunctionExpression" }]
         },
         {
             code: "let a; function foo() { a = 10; } for (let x of xs) { (function() { a; }); } foo();",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "FunctionExpression" }]
         },
         {
             code: "let a; function foo() { a = 10; for (let x of xs) { (function() { a; }); } } foo();",
             parserOptions: { ecmaVersion: 6 },
-            errors: [{ message: expectedErrorMessage, type: "FunctionExpression" }]
+            errors: [{ messageId: "unsafeRefs", data: { varNames: "'a'" }, type: "FunctionExpression" }]
         }
     ]
 });
diff --git a/tests/lib/rules/no-var.js b/tests/lib/rules/no-var.js
index 98b3be5e5..beffe2749 100644
--- a/tests/lib/rules/no-var.js
+++ b/tests/lib/rules/no-var.js
@@ -298,6 +298,15 @@ ruleTester.run("no-var", rule, {
             output: "let foo = 1",
             parserOptions: { sourceType: "module" },
             errors: ["Unexpected var, use let or const instead."]
+        },
+
+        // https://github.com/eslint/eslint/issues/11594
+        {
+            code: "declare var foo = 2;",
+            output: "declare let foo = 2;",
+            parser: require.resolve("../../fixtures/parsers/typescript-parsers/declare-var"),
+            parserOptions: { sourceType: "module" },
+            errors: ["Unexpected var, use let or const instead."]
         }
     ]
 });
diff --git a/tests/lib/rules/object-shorthand.js b/tests/lib/rules/object-shorthand.js
index 19d235290..72bd7ba6e 100644
--- a/tests/lib/rules/object-shorthand.js
+++ b/tests/lib/rules/object-shorthand.js
@@ -131,6 +131,22 @@ ruleTester.run("object-shorthand", rule, {
             code: "var x = {ConstructorFunction: function(){}, a: b}",
             options: ["always", { ignoreConstructors: true }]
         },
+        {
+            code: "var x = {_ConstructorFunction: function(){}, a: b}",
+            options: ["always", { ignoreConstructors: true }]
+        },
+        {
+            code: "var x = {$ConstructorFunction: function(){}, a: b}",
+            options: ["always", { ignoreConstructors: true }]
+        },
+        {
+            code: "var x = {__ConstructorFunction: function(){}, a: b}",
+            options: ["always", { ignoreConstructors: true }]
+        },
+        {
+            code: "var x = {_0ConstructorFunction: function(){}, a: b}",
+            options: ["always", { ignoreConstructors: true }]
+        },
         {
             code: "var x = {notConstructorFunction(){}, b: c}",
             options: ["always", { ignoreConstructors: true }]
@@ -139,6 +155,22 @@ ruleTester.run("object-shorthand", rule, {
             code: "var x = {ConstructorFunction: function(){}, a: b}",
             options: ["methods", { ignoreConstructors: true }]
         },
+        {
+            code: "var x = {_ConstructorFunction: function(){}, a: b}",
+            options: ["methods", { ignoreConstructors: true }]
+        },
+        {
+            code: "var x = {$ConstructorFunction: function(){}, a: b}",
+            options: ["methods", { ignoreConstructors: true }]
+        },
+        {
+            code: "var x = {__ConstructorFunction: function(){}, a: b}",
+            options: ["methods", { ignoreConstructors: true }]
+        },
+        {
+            code: "var x = {_0ConstructorFunction: function(){}, a: b}",
+            options: ["methods", { ignoreConstructors: true }]
+        },
         {
             code: "var x = {notConstructorFunction(){}, b: c}",
             options: ["methods", { ignoreConstructors: true }]
@@ -708,6 +740,46 @@ ruleTester.run("object-shorthand", rule, {
             errors: [LONGFORM_PROPERTY_ERROR]
         },
 
+        // ignoreConstructors
+        {
+            code: "var x = {y: function() {}}",
+            output: "var x = {y() {}}",
+            options: ["methods", { ignoreConstructors: true }],
+            errors: [METHOD_ERROR]
+        },
+        {
+
+            // https://github.com/eslint/eslint/issues/11595
+            code: "var x = {_y: function() {}}",
+            output: "var x = {_y() {}}",
+            options: ["methods", { ignoreConstructors: true }],
+            errors: [METHOD_ERROR]
+        },
+        {
+
+            // https://github.com/eslint/eslint/issues/11595
+            code: "var x = {$y: function() {}}",
+            output: "var x = {$y() {}}",
+            options: ["methods", { ignoreConstructors: true }],
+            errors: [METHOD_ERROR]
+        },
+        {
+
+            // https://github.com/eslint/eslint/issues/11595
+            code: "var x = {__y: function() {}}",
+            output: "var x = {__y() {}}",
+            options: ["methods", { ignoreConstructors: true }],
+            errors: [METHOD_ERROR]
+        },
+        {
+
+            // https://github.com/eslint/eslint/issues/11595
+            code: "var x = {_0y: function() {}}",
+            output: "var x = {_0y() {}}",
+            options: ["methods", { ignoreConstructors: true }],
+            errors: [METHOD_ERROR]
+        },
+
         // avoidQuotes
         {
             code: "var x = {a: a}",
diff --git a/tests/lib/testers/rule-tester.js b/tests/lib/testers/rule-tester.js
index 875925ccc..2ff61f1a5 100644
--- a/tests/lib/testers/rule-tester.js
+++ b/tests/lib/testers/rule-tester.js
@@ -659,6 +659,43 @@ describe("RuleTester", () => {
 
     });
 
+    it("should disallow invalid defaults in rules", () => {
+        const ruleWithInvalidDefaults = {
+            meta: {
+                schema: [
+                    {
+                        oneOf: [
+                            { enum: ["foo"] },
+                            {
+                                type: "object",
+                                properties: {
+                                    foo: {
+                                        enum: ["foo", "bar"],
+                                        default: "foo"
+                                    }
+                                },
+                                additionalProperties: false
+                            }
+                        ]
+                    }
+                ]
+            },
+            create: () => ({})
+        };
+
+        assert.throws(() => {
+            ruleTester.run("invalid-defaults", ruleWithInvalidDefaults, {
+                valid: [
+                    {
+                        code: "foo",
+                        options: [{}]
+                    }
+                ],
+                invalid: []
+            });
+        }, /Schema for rule invalid-defaults is invalid: default is ignored for: data1\.foo/u);
+    });
+
     it("throw an error when an unknown config option is included", () => {
         assert.throws(() => {
             ruleTester.run("no-eval", require("../../fixtures/testers/rule-tester/no-eval"), {