diff --git a/docs/rules/id-blacklist.md b/docs/rules/id-denylist.md similarity index 67% rename from docs/rules/id-blacklist.md rename to docs/rules/id-denylist.md index a7685c4c2f2..040f26e894c 100644 --- a/docs/rules/id-blacklist.md +++ b/docs/rules/id-denylist.md @@ -1,20 +1,20 @@ -# disallow specified identifiers (id-blacklist) +# disallow specified identifiers (id-denylist) > "There are only two hard things in Computer Science: cache invalidation and naming things." — Phil Karlton -Bad names can lead to hard-to-decipher code. Generic names, such as `data`, don't infer much about the code and the values it receives. This rule allows you to configure a blacklist of bad identifier names, that you don't want to see in your code. +Generic names can lead to hard-to-decipher code. This rule allows you to specify a deny list of disallowed identifier names to avoid this practice. ## Rule Details This rule disallows specified identifiers in assignments and `function` definitions. -This rule will catch blacklisted identifiers that are: +This rule will catch disallowed identifiers that are: - variable declarations - function declarations - object properties assigned to during object creation -It will not catch blacklisted identifiers that are: +It will not catch disallowed identifiers that are: - function calls (so you can still use functions you do not have control over) - object properties (so you can still use objects you do not have control over) @@ -27,14 +27,14 @@ For example, to restrict the use of common generic identifiers: ```json { - "id-blacklist": ["error", "data", "err", "e", "cb", "callback"] + "id-denylist": ["error", "data", "err", "e", "cb", "callback"] } ``` Examples of **incorrect** code for this rule with sample `"data", "callback"` restricted identifiers: ```js -/*eslint id-blacklist: ["error", "data", "callback"] */ +/*eslint id-denylist: ["error", "data", "callback"] */ var data = {...}; @@ -54,7 +54,7 @@ var itemSet = { Examples of **correct** code for this rule with sample `"data", "callback"` restricted identifiers: ```js -/*eslint id-blacklist: ["error", "data", "callback"] */ +/*eslint id-denylist: ["error", "data", "callback"] */ var encodingOptions = {...}; @@ -79,4 +79,4 @@ foo.data; // all property names that are not assignments are ignored ## When Not To Use It -You can turn this rule off if you are happy for identifiers to be named freely. +You can turn this rule off if you do not want to restrict the use of certain identifiers. diff --git a/lib/rules/id-blacklist.js b/lib/rules/id-denylist.js similarity index 89% rename from lib/rules/id-blacklist.js rename to lib/rules/id-denylist.js index d77a35d41b6..112fd8a9d55 100644 --- a/lib/rules/id-blacklist.js +++ b/lib/rules/id-denylist.js @@ -1,6 +1,6 @@ /** * @fileoverview Rule that warns when identifier names that are - * blacklisted in the configuration are used. + * specified in the configuration are used. * @author Keith Cirkel (http://keithcirkel.co.uk) */ @@ -117,7 +117,7 @@ module.exports = { description: "disallow specified identifiers", category: "Stylistic Issues", recommended: false, - url: "https://eslint.org/docs/rules/id-blacklist" + url: "https://eslint.org/docs/rules/id-denylist" }, schema: { @@ -128,25 +128,25 @@ module.exports = { uniqueItems: true }, messages: { - blacklisted: "Identifier '{{name}}' is blacklisted." + restricted: "Identifier '{{name}}' is restricted." } }, create(context) { - const blacklist = new Set(context.options); + const denyList = new Set(context.options); const reportedNodes = new Set(); let globalScope; /** - * Checks whether the given name is blacklisted. + * Checks whether the given name is restricted. * @param {string} name The name to check. - * @returns {boolean} `true` if the name is blacklisted. + * @returns {boolean} `true` if the name is restricted. * @private */ - function isBlacklisted(name) { - return blacklist.has(name); + function isRestricted(name) { + return denyList.has(name); } /** @@ -172,8 +172,8 @@ module.exports = { /* * Member access has special rules for checking property names. - * Read access to a property with a blacklisted name is allowed, because it can be on an object that user has no control over. - * Write access isn't allowed, because it potentially creates a new property with a blacklisted name. + * Read access to a property with a restricted name is allowed, because it can be on an object that user has no control over. + * Write access isn't allowed, because it potentially creates a new property with a restricted name. */ if ( parent.type === "MemberExpression" && @@ -205,7 +205,7 @@ module.exports = { if (!reportedNodes.has(node)) { context.report({ node, - messageId: "blacklisted", + messageId: "restricted", data: { name: node.name } @@ -221,7 +221,7 @@ module.exports = { }, Identifier(node) { - if (isBlacklisted(node.name) && shouldCheck(node)) { + if (isRestricted(node.name) && shouldCheck(node)) { report(node); } } diff --git a/lib/rules/index.js b/lib/rules/index.js index 567cd4a0eca..e34d090899a 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -56,7 +56,10 @@ module.exports = new LazyLoadingRuleMap(Object.entries({ "grouped-accessor-pairs": () => require("./grouped-accessor-pairs"), "guard-for-in": () => require("./guard-for-in"), "handle-callback-err": () => require("./handle-callback-err"), - "id-blacklist": () => require("./id-blacklist"), + + // Renamed to id-denylist. + "id-blacklist": () => require("./id-denylist"), + "id-denylist": () => require("./id-denylist"), "id-length": () => require("./id-length"), "id-match": () => require("./id-match"), "implicit-arrow-linebreak": () => require("./implicit-arrow-linebreak"), diff --git a/tests/lib/rules/id-blacklist.js b/tests/lib/rules/id-blacklist.js index 6c3f729e17a..e69de29bb2d 100644 --- a/tests/lib/rules/id-blacklist.js +++ b/tests/lib/rules/id-blacklist.js @@ -1,1359 +0,0 @@ -/** - * @fileoverview Tests for id-blacklist rule. - * @author Keith Cirkel - */ - -"use strict"; - -//------------------------------------------------------------------------------ -// Requirements -//------------------------------------------------------------------------------ - -const rule = require("../../../lib/rules/id-blacklist"), - { RuleTester } = require("../../../lib/rule-tester"); - -//------------------------------------------------------------------------------ -// Tests -//------------------------------------------------------------------------------ - -const ruleTester = new RuleTester(); -const error = { messageId: "blacklisted", type: "Identifier" }; - -ruleTester.run("id-blacklist", rule, { - valid: [ - { - code: "foo = \"bar\"", - options: ["bar"] - }, - { - code: "bar = \"bar\"", - options: ["foo"] - }, - { - code: "foo = \"bar\"", - options: ["f", "fo", "fooo", "bar"] - }, - { - code: "function foo(){}", - options: ["bar"] - }, - { - code: "foo()", - options: ["f", "fo", "fooo", "bar"] - }, - { - code: "import { foo as bar } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" } - }, - { - code: "export { foo as bar } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" } - }, - { - code: "foo.bar()", - options: ["f", "fo", "fooo", "b", "ba", "baz"] - }, - { - code: "var foo = bar.baz;", - options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz"] - }, - { - code: "var foo = bar.baz.bing;", - options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] - }, - { - code: "foo.bar.baz = bing.bong.bash;", - options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] - }, - { - code: "if (foo.bar) {}", - options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] - }, - { - code: "var obj = { key: foo.bar };", - options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] - }, - { - code: "const {foo: bar} = baz", - options: ["foo"], - parserOptions: { ecmaVersion: 6 } - }, - { - code: "const {foo: {bar: baz}} = qux", - options: ["foo", "bar"], - parserOptions: { ecmaVersion: 6 } - }, - { - code: "function foo({ bar: baz }) {}", - options: ["bar"], - parserOptions: { ecmaVersion: 6 } - }, - { - code: "function foo({ bar: {baz: qux} }) {}", - options: ["bar", "baz"], - parserOptions: { ecmaVersion: 6 } - }, - { - code: "function foo({baz} = obj.qux) {}", - options: ["qux"], - parserOptions: { ecmaVersion: 6 } - }, - { - code: "function foo({ foo: {baz} = obj.qux }) {}", - options: ["qux"], - parserOptions: { ecmaVersion: 6 } - }, - { - code: "({a: bar = obj.baz});", - options: ["baz"], - parserOptions: { ecmaVersion: 6 } - }, - { - code: "({foo: {a: bar = obj.baz}} = qux);", - options: ["baz"], - parserOptions: { ecmaVersion: 6 } - }, - { - code: "var arr = [foo.bar];", - options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] - }, - { - code: "[foo.bar]", - options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] - }, - { - code: "[foo.bar.nesting]", - options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] - }, - { - code: "if (foo.bar === bar.baz) { [foo.bar] }", - options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] - }, - { - code: "var myArray = new Array(); var myDate = new Date();", - options: ["array", "date", "mydate", "myarray", "new", "var"] - }, - { - code: "foo()", - options: ["foo"] - }, - { - code: "foo.bar()", - options: ["bar"] - }, - { - code: "foo.bar", - options: ["bar"] - }, - { - code: "({foo: obj.bar.bar.bar.baz} = {});", - options: ["foo", "bar"], - parserOptions: { ecmaVersion: 6 } - }, - { - code: "({[obj.bar]: a = baz} = qux);", - options: ["bar"], - parserOptions: { ecmaVersion: 6 } - }, - - // references to global variables - { - code: "Number.parseInt()", - options: ["Number"] - }, - { - code: "x = Number.NaN;", - options: ["Number"] - }, - { - code: "var foo = undefined;", - options: ["undefined"] - }, - { - code: "if (foo === undefined);", - options: ["undefined"] - }, - { - code: "obj[undefined] = 5;", // creates obj["undefined"]. It should be disallowed, but the rule doesn't know values of globals and can't control computed access. - options: ["undefined"] - }, - { - code: "foo = { [myGlobal]: 1 };", - options: ["myGlobal"], - parserOptions: { ecmaVersion: 6 }, - globals: { myGlobal: "readonly" } - }, - { - code: "({ myGlobal } = foo);", // writability doesn't affect the logic, it's always assumed that user doesn't have control over the names of globals. - options: ["myGlobal"], - parserOptions: { ecmaVersion: 6 }, - globals: { myGlobal: "writable" } - }, - { - code: "/* global myGlobal: readonly */ myGlobal = 5;", - options: ["myGlobal"] - }, - { - code: "var foo = [Map];", - options: ["Map"], - env: { es6: true } - }, - { - code: "var foo = { bar: window.baz };", - options: ["window"], - env: { browser: true } - } - ], - invalid: [ - { - code: "foo = \"bar\"", - options: ["foo"], - errors: [ - error - ] - }, - { - code: "bar = \"bar\"", - options: ["bar"], - errors: [ - error - ] - }, - { - code: "foo = \"bar\"", - options: ["f", "fo", "foo", "bar"], - errors: [ - error - ] - }, - { - code: "function foo(){}", - options: ["f", "fo", "foo", "bar"], - errors: [ - error - ] - }, - { - code: "import foo from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [ - error - ] - }, - { - code: "import * as foo from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [ - error - ] - }, - { - code: "export * as foo from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 2020, sourceType: "module" }, - errors: [ - error - ] - }, - { - code: "import { foo } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [ - error - ] - }, - { - code: "import { foo as bar } from 'mod'", - options: ["bar"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 17 - }] - }, - { - code: "import { foo as bar } from 'mod'", - options: ["foo", "bar"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 17 - }] - }, - { - code: "import { foo as foo } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 17 - }] - }, - { - code: "import { foo, foo as bar } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 10 - }] - }, - { - code: "import { foo as bar, foo } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 22 - }] - }, - { - code: "import foo, { foo as bar } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 8 - }] - }, - { - code: "var foo; export { foo as bar };", - options: ["bar"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 26 - }] - }, - { - code: "var foo; export { foo };", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 5 - }, - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 19 - } - ] - }, - { - code: "var foo; export { foo as bar };", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 5 - }, - - // reports each occurrence of local identifier, although it's renamed in this export specifier - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 19 - } - ] - }, - { - code: "var foo; export { foo as foo };", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 5 - }, - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 19 - }, - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 26 - } - ] - }, - { - code: "var foo; export { foo as bar };", - options: ["foo", "bar"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 5 - }, - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 19 - }, - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 26 - } - ] - }, - { - code: "export { foo } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [ - error - ] - }, - { - code: "export { foo as bar } from 'mod'", - options: ["bar"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 17 - }] - }, - { - code: "export { foo as bar } from 'mod'", - options: ["foo", "bar"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 17 - }] - }, - { - code: "export { foo as foo } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 17 - }] - }, - { - code: "export { foo, foo as bar } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 10 - }] - }, - { - code: "export { foo as bar, foo } from 'mod'", - options: ["foo"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 22 - }] - }, - { - code: "foo.bar()", - options: ["f", "fo", "foo", "b", "ba", "baz"], - errors: [ - error - ] - }, - { - code: "foo[bar] = baz;", - options: ["bar"], - errors: [{ - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier" - }] - }, - { - code: "baz = foo[bar];", - options: ["bar"], - errors: [{ - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier" - }] - }, - { - code: "var foo = bar.baz;", - options: ["f", "fo", "foo", "b", "ba", "barr", "bazz"], - errors: [ - error - ] - }, - { - code: "var foo = bar.baz;", - options: ["f", "fo", "fooo", "b", "ba", "bar", "bazz"], - errors: [ - error - ] - }, - { - code: "if (foo.bar) {}", - options: ["f", "fo", "foo", "b", "ba", "barr", "bazz", "bingg"], - errors: [ - error - ] - }, - { - code: "var obj = { key: foo.bar };", - options: ["obj"], - errors: [ - error - ] - }, - { - code: "var obj = { key: foo.bar };", - options: ["key"], - errors: [ - error - ] - }, - { - code: "var obj = { key: foo.bar };", - options: ["foo"], - errors: [ - error - ] - }, - { - code: "var arr = [foo.bar];", - options: ["arr"], - errors: [ - error - ] - }, - { - code: "var arr = [foo.bar];", - options: ["foo"], - errors: [ - error - ] - }, - { - code: "[foo.bar]", - options: ["f", "fo", "foo", "b", "ba", "barr", "bazz", "bingg"], - errors: [ - error - ] - }, - { - code: "if (foo.bar === bar.baz) { [bing.baz] }", - options: ["f", "fo", "foo", "b", "ba", "barr", "bazz", "bingg"], - errors: [ - error - ] - }, - { - code: "if (foo.bar === bar.baz) { [foo.bar] }", - options: ["f", "fo", "fooo", "b", "ba", "bar", "bazz", "bingg"], - errors: [ - error - ] - }, - { - code: "var myArray = new Array(); var myDate = new Date();", - options: ["array", "date", "myDate", "myarray", "new", "var"], - errors: [ - error - ] - }, - { - code: "var myArray = new Array(); var myDate = new Date();", - options: ["array", "date", "mydate", "myArray", "new", "var"], - errors: [ - error - ] - }, - { - code: "foo.bar = 1", - options: ["bar"], - errors: [ - error - ] - }, - { - code: "foo.bar.baz = 1", - options: ["bar", "baz"], - errors: [ - error - ] - }, - { - code: "const {foo} = baz", - options: ["foo"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 8 - } - ] - }, - { - code: "const {foo: bar} = baz", - options: ["foo", "bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 13 - } - ] - }, - { - code: "const {[foo]: bar} = baz", - options: ["foo", "bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 9 - }, - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 15 - } - ] - }, - { - code: "const {foo: {bar: baz}} = qux", - options: ["foo", "bar", "baz"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "baz" }, - type: "Identifier", - column: 19 - } - ] - }, - { - code: "const {foo: {[bar]: baz}} = qux", - options: ["foo", "bar", "baz"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 15 - }, - { - messageId: "blacklisted", - data: { name: "baz" }, - type: "Identifier", - column: 21 - } - ] - }, - { - code: "const {[foo]: {[bar]: baz}} = qux", - options: ["foo", "bar", "baz"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 9 - }, - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 17 - }, - { - messageId: "blacklisted", - data: { name: "baz" }, - type: "Identifier", - column: 23 - } - ] - }, - { - code: "function foo({ bar: baz }) {}", - options: ["bar", "baz"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "baz" }, - type: "Identifier", - column: 21 - } - ] - }, - { - code: "function foo({ bar: {baz: qux} }) {}", - options: ["bar", "baz", "qux"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "qux" }, - type: "Identifier", - column: 27 - } - ] - }, - { - code: "({foo: obj.bar} = baz);", - options: ["foo", "bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 12 - } - ] - }, - { - code: "({foo: obj.bar.bar.bar.baz} = {});", - options: ["foo", "bar", "baz"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "baz" }, - type: "Identifier", - column: 24 - } - ] - }, - { - code: "({[foo]: obj.bar} = baz);", - options: ["foo", "bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 4 - }, - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 14 - } - ] - }, - { - code: "({foo: { a: obj.bar }} = baz);", - options: ["bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 17 - } - ] - }, - { - code: "({a: obj.bar = baz} = qux);", - options: ["bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 10 - } - ] - }, - { - code: "({a: obj.bar.bar.baz = obj.qux} = obj.qux);", - options: ["a", "bar", "baz", "qux"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "baz" }, - type: "Identifier", - column: 18 - } - ] - }, - { - code: "({a: obj[bar] = obj.qux} = obj.qux);", - options: ["a", "bar", "baz", "qux"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 10 - } - ] - }, - { - code: "({a: [obj.bar] = baz} = qux);", - options: ["bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 11 - } - ] - }, - { - code: "({foo: { a: obj.bar = baz}} = qux);", - options: ["bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 17 - } - ] - }, - { - code: "({foo: { [a]: obj.bar }} = baz);", - options: ["bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 19 - } - ] - }, - { - code: "({...obj.bar} = baz);", - options: ["bar"], - parserOptions: { ecmaVersion: 9 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 10 - } - ] - }, - { - code: "([obj.bar] = baz);", - options: ["bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 7 - } - ] - }, - { - code: "const [bar] = baz;", - options: ["bar"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "bar" }, - type: "Identifier", - column: 8 - } - ] - }, - - // not a reference to a global variable, because it isn't a reference to a variable - { - code: "foo.undefined = 1;", - options: ["undefined"], - errors: [ - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier" - } - ] - }, - { - code: "var foo = { undefined: 1 };", - options: ["undefined"], - errors: [ - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier" - } - ] - }, - { - code: "var foo = { undefined: undefined };", - options: ["undefined"], - errors: [ - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier", - column: 13 - } - ] - }, - { - code: "var foo = { Number() {} };", - options: ["Number"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier" - } - ] - }, - { - code: "class Foo { Number() {} }", - options: ["Number"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier" - } - ] - }, - { - code: "myGlobal: while(foo) { break myGlobal; } ", - options: ["myGlobal"], - globals: { myGlobal: "readonly" }, - errors: [ - { - messageId: "blacklisted", - data: { name: "myGlobal" }, - type: "Identifier", - column: 1 - }, - { - messageId: "blacklisted", - data: { name: "myGlobal" }, - type: "Identifier", - column: 30 - } - ] - }, - - // globals declared in the given source code are not excluded from consideration - { - code: "const foo = 1; bar = foo;", - options: ["foo"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 7 - }, - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 22 - } - ] - }, - { - code: "let foo; foo = bar;", - options: ["foo"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 5 - }, - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 10 - } - ] - }, - { - code: "bar = foo; var foo;", - options: ["foo"], - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 7 - }, - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 16 - } - ] - }, - { - code: "function foo() {} var bar = foo;", - options: ["foo"], - errors: [ - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 10 - }, - { - messageId: "blacklisted", - data: { name: "foo" }, - type: "Identifier", - column: 29 - } - ] - }, - { - code: "class Foo {} var bar = Foo;", - options: ["Foo"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "Foo" }, - type: "Identifier", - column: 7 - }, - { - messageId: "blacklisted", - data: { name: "Foo" }, - type: "Identifier", - column: 24 - } - ] - }, - - // redeclared globals are not excluded from consideration - { - code: "let undefined; undefined = 1;", - options: ["undefined"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier", - column: 5 - }, - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier", - column: 16 - } - ] - }, - { - code: "foo = undefined; var undefined;", - options: ["undefined"], - errors: [ - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier", - column: 7 - }, - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier", - column: 22 - } - ] - }, - { - code: "function undefined(){} x = undefined;", - options: ["undefined"], - errors: [ - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier", - column: 10 - }, - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier", - column: 28 - } - ] - }, - { - code: "class Number {} x = Number.NaN;", - options: ["Number"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier", - column: 7 - }, - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier", - column: 21 - } - ] - }, - - /* - * Assignment to a property with a blacklisted name isn't allowed, in general. - * In this case, that restriction prevents creating a global variable with a blacklisted name. - */ - { - code: "/* globals myGlobal */ window.myGlobal = 5; foo = myGlobal;", - options: ["myGlobal"], - env: { browser: true }, - errors: [ - { - messageId: "blacklisted", - data: { name: "myGlobal" }, - type: "Identifier", - column: 31 - } - ] - }, - - // disabled global variables - { - code: "var foo = undefined;", - options: ["undefined"], - globals: { undefined: "off" }, - errors: [ - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier" - } - ] - }, - { - code: "/* globals Number: off */ Number.parseInt()", - options: ["Number"], - errors: [ - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier" - } - ] - }, - { - code: "var foo = [Map];", // this actually isn't a disabled global: it was never enabled because es6 environment isn't enabled - options: ["Map"], - errors: [ - { - messageId: "blacklisted", - data: { name: "Map" }, - type: "Identifier" - } - ] - }, - - // shadowed global variables - { - code: "if (foo) { let undefined; bar = undefined; }", - options: ["undefined"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier", - column: 16 - }, - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier", - column: 33 - } - ] - }, - { - code: "function foo(Number) { var x = Number.NaN; }", - options: ["Number"], - errors: [ - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier", - column: 14 - }, - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier", - column: 32 - } - ] - }, - { - code: "function foo() { var myGlobal; x = myGlobal; }", - options: ["myGlobal"], - globals: { myGlobal: "readonly" }, - errors: [ - { - messageId: "blacklisted", - data: { name: "myGlobal" }, - type: "Identifier", - column: 22 - }, - { - messageId: "blacklisted", - data: { name: "myGlobal" }, - type: "Identifier", - column: 36 - } - ] - }, - { - code: "function foo(bar) { return Number.parseInt(bar); } const Number = 1;", - options: ["Number"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [ - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier", - column: 28 - }, - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier", - column: 58 - } - ] - }, - { - code: "import Number from 'myNumber'; const foo = Number.parseInt(bar);", - options: ["Number"], - parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [ - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier", - column: 8 - }, - { - messageId: "blacklisted", - data: { name: "Number" }, - type: "Identifier", - column: 44 - } - ] - }, - { - code: "var foo = function undefined() {};", - options: ["undefined"], - errors: [ - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier" - } - ] - }, - - // this is a reference to a global variable, but at the same time creates a property with a blacklisted name - { - code: "var foo = { undefined }", - options: ["undefined"], - parserOptions: { ecmaVersion: 6 }, - errors: [ - { - messageId: "blacklisted", - data: { name: "undefined" }, - type: "Identifier" - } - ] - } - ] -}); diff --git a/tests/lib/rules/id-denylist.js b/tests/lib/rules/id-denylist.js new file mode 100644 index 00000000000..6da179d99ff --- /dev/null +++ b/tests/lib/rules/id-denylist.js @@ -0,0 +1,1359 @@ +/** + * @fileoverview Tests for id-denylist rule. + * @author Keith Cirkel + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/id-denylist"), + { RuleTester } = require("../../../lib/rule-tester"); + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); +const error = { messageId: "restricted", type: "Identifier" }; + +ruleTester.run("id-denylist", rule, { + valid: [ + { + code: "foo = \"bar\"", + options: ["bar"] + }, + { + code: "bar = \"bar\"", + options: ["foo"] + }, + { + code: "foo = \"bar\"", + options: ["f", "fo", "fooo", "bar"] + }, + { + code: "function foo(){}", + options: ["bar"] + }, + { + code: "foo()", + options: ["f", "fo", "fooo", "bar"] + }, + { + code: "import { foo as bar } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" } + }, + { + code: "export { foo as bar } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" } + }, + { + code: "foo.bar()", + options: ["f", "fo", "fooo", "b", "ba", "baz"] + }, + { + code: "var foo = bar.baz;", + options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz"] + }, + { + code: "var foo = bar.baz.bing;", + options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] + }, + { + code: "foo.bar.baz = bing.bong.bash;", + options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] + }, + { + code: "if (foo.bar) {}", + options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] + }, + { + code: "var obj = { key: foo.bar };", + options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] + }, + { + code: "const {foo: bar} = baz", + options: ["foo"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "const {foo: {bar: baz}} = qux", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "function foo({ bar: baz }) {}", + options: ["bar"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "function foo({ bar: {baz: qux} }) {}", + options: ["bar", "baz"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "function foo({baz} = obj.qux) {}", + options: ["qux"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "function foo({ foo: {baz} = obj.qux }) {}", + options: ["qux"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "({a: bar = obj.baz});", + options: ["baz"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "({foo: {a: bar = obj.baz}} = qux);", + options: ["baz"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "var arr = [foo.bar];", + options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] + }, + { + code: "[foo.bar]", + options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] + }, + { + code: "[foo.bar.nesting]", + options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] + }, + { + code: "if (foo.bar === bar.baz) { [foo.bar] }", + options: ["f", "fo", "fooo", "b", "ba", "barr", "bazz", "bingg"] + }, + { + code: "var myArray = new Array(); var myDate = new Date();", + options: ["array", "date", "mydate", "myarray", "new", "var"] + }, + { + code: "foo()", + options: ["foo"] + }, + { + code: "foo.bar()", + options: ["bar"] + }, + { + code: "foo.bar", + options: ["bar"] + }, + { + code: "({foo: obj.bar.bar.bar.baz} = {});", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "({[obj.bar]: a = baz} = qux);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 } + }, + + // references to global variables + { + code: "Number.parseInt()", + options: ["Number"] + }, + { + code: "x = Number.NaN;", + options: ["Number"] + }, + { + code: "var foo = undefined;", + options: ["undefined"] + }, + { + code: "if (foo === undefined);", + options: ["undefined"] + }, + { + code: "obj[undefined] = 5;", // creates obj["undefined"]. It should be disallowed, but the rule doesn't know values of globals and can't control computed access. + options: ["undefined"] + }, + { + code: "foo = { [myGlobal]: 1 };", + options: ["myGlobal"], + parserOptions: { ecmaVersion: 6 }, + globals: { myGlobal: "readonly" } + }, + { + code: "({ myGlobal } = foo);", // writability doesn't affect the logic, it's always assumed that user doesn't have control over the names of globals. + options: ["myGlobal"], + parserOptions: { ecmaVersion: 6 }, + globals: { myGlobal: "writable" } + }, + { + code: "/* global myGlobal: readonly */ myGlobal = 5;", + options: ["myGlobal"] + }, + { + code: "var foo = [Map];", + options: ["Map"], + env: { es6: true } + }, + { + code: "var foo = { bar: window.baz };", + options: ["window"], + env: { browser: true } + } + ], + invalid: [ + { + code: "foo = \"bar\"", + options: ["foo"], + errors: [ + error + ] + }, + { + code: "bar = \"bar\"", + options: ["bar"], + errors: [ + error + ] + }, + { + code: "foo = \"bar\"", + options: ["f", "fo", "foo", "bar"], + errors: [ + error + ] + }, + { + code: "function foo(){}", + options: ["f", "fo", "foo", "bar"], + errors: [ + error + ] + }, + { + code: "import foo from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + error + ] + }, + { + code: "import * as foo from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + error + ] + }, + { + code: "export * as foo from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 2020, sourceType: "module" }, + errors: [ + error + ] + }, + { + code: "import { foo } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + error + ] + }, + { + code: "import { foo as bar } from 'mod'", + options: ["bar"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 17 + }] + }, + { + code: "import { foo as bar } from 'mod'", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 17 + }] + }, + { + code: "import { foo as foo } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 17 + }] + }, + { + code: "import { foo, foo as bar } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 10 + }] + }, + { + code: "import { foo as bar, foo } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 22 + }] + }, + { + code: "import foo, { foo as bar } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 8 + }] + }, + { + code: "var foo; export { foo as bar };", + options: ["bar"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 26 + }] + }, + { + code: "var foo; export { foo };", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 5 + }, + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 19 + } + ] + }, + { + code: "var foo; export { foo as bar };", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 5 + }, + + // reports each occurrence of local identifier, although it's renamed in this export specifier + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 19 + } + ] + }, + { + code: "var foo; export { foo as foo };", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 5 + }, + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 19 + }, + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 26 + } + ] + }, + { + code: "var foo; export { foo as bar };", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 5 + }, + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 19 + }, + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 26 + } + ] + }, + { + code: "export { foo } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + error + ] + }, + { + code: "export { foo as bar } from 'mod'", + options: ["bar"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 17 + }] + }, + { + code: "export { foo as bar } from 'mod'", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 17 + }] + }, + { + code: "export { foo as foo } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 17 + }] + }, + { + code: "export { foo, foo as bar } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 10 + }] + }, + { + code: "export { foo as bar, foo } from 'mod'", + options: ["foo"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [{ + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 22 + }] + }, + { + code: "foo.bar()", + options: ["f", "fo", "foo", "b", "ba", "baz"], + errors: [ + error + ] + }, + { + code: "foo[bar] = baz;", + options: ["bar"], + errors: [{ + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier" + }] + }, + { + code: "baz = foo[bar];", + options: ["bar"], + errors: [{ + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier" + }] + }, + { + code: "var foo = bar.baz;", + options: ["f", "fo", "foo", "b", "ba", "barr", "bazz"], + errors: [ + error + ] + }, + { + code: "var foo = bar.baz;", + options: ["f", "fo", "fooo", "b", "ba", "bar", "bazz"], + errors: [ + error + ] + }, + { + code: "if (foo.bar) {}", + options: ["f", "fo", "foo", "b", "ba", "barr", "bazz", "bingg"], + errors: [ + error + ] + }, + { + code: "var obj = { key: foo.bar };", + options: ["obj"], + errors: [ + error + ] + }, + { + code: "var obj = { key: foo.bar };", + options: ["key"], + errors: [ + error + ] + }, + { + code: "var obj = { key: foo.bar };", + options: ["foo"], + errors: [ + error + ] + }, + { + code: "var arr = [foo.bar];", + options: ["arr"], + errors: [ + error + ] + }, + { + code: "var arr = [foo.bar];", + options: ["foo"], + errors: [ + error + ] + }, + { + code: "[foo.bar]", + options: ["f", "fo", "foo", "b", "ba", "barr", "bazz", "bingg"], + errors: [ + error + ] + }, + { + code: "if (foo.bar === bar.baz) { [bing.baz] }", + options: ["f", "fo", "foo", "b", "ba", "barr", "bazz", "bingg"], + errors: [ + error + ] + }, + { + code: "if (foo.bar === bar.baz) { [foo.bar] }", + options: ["f", "fo", "fooo", "b", "ba", "bar", "bazz", "bingg"], + errors: [ + error + ] + }, + { + code: "var myArray = new Array(); var myDate = new Date();", + options: ["array", "date", "myDate", "myarray", "new", "var"], + errors: [ + error + ] + }, + { + code: "var myArray = new Array(); var myDate = new Date();", + options: ["array", "date", "mydate", "myArray", "new", "var"], + errors: [ + error + ] + }, + { + code: "foo.bar = 1", + options: ["bar"], + errors: [ + error + ] + }, + { + code: "foo.bar.baz = 1", + options: ["bar", "baz"], + errors: [ + error + ] + }, + { + code: "const {foo} = baz", + options: ["foo"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 8 + } + ] + }, + { + code: "const {foo: bar} = baz", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 13 + } + ] + }, + { + code: "const {[foo]: bar} = baz", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 9 + }, + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 15 + } + ] + }, + { + code: "const {foo: {bar: baz}} = qux", + options: ["foo", "bar", "baz"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "baz" }, + type: "Identifier", + column: 19 + } + ] + }, + { + code: "const {foo: {[bar]: baz}} = qux", + options: ["foo", "bar", "baz"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 15 + }, + { + messageId: "restricted", + data: { name: "baz" }, + type: "Identifier", + column: 21 + } + ] + }, + { + code: "const {[foo]: {[bar]: baz}} = qux", + options: ["foo", "bar", "baz"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 9 + }, + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 17 + }, + { + messageId: "restricted", + data: { name: "baz" }, + type: "Identifier", + column: 23 + } + ] + }, + { + code: "function foo({ bar: baz }) {}", + options: ["bar", "baz"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "baz" }, + type: "Identifier", + column: 21 + } + ] + }, + { + code: "function foo({ bar: {baz: qux} }) {}", + options: ["bar", "baz", "qux"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "qux" }, + type: "Identifier", + column: 27 + } + ] + }, + { + code: "({foo: obj.bar} = baz);", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 12 + } + ] + }, + { + code: "({foo: obj.bar.bar.bar.baz} = {});", + options: ["foo", "bar", "baz"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "baz" }, + type: "Identifier", + column: 24 + } + ] + }, + { + code: "({[foo]: obj.bar} = baz);", + options: ["foo", "bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 4 + }, + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 14 + } + ] + }, + { + code: "({foo: { a: obj.bar }} = baz);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 17 + } + ] + }, + { + code: "({a: obj.bar = baz} = qux);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 10 + } + ] + }, + { + code: "({a: obj.bar.bar.baz = obj.qux} = obj.qux);", + options: ["a", "bar", "baz", "qux"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "baz" }, + type: "Identifier", + column: 18 + } + ] + }, + { + code: "({a: obj[bar] = obj.qux} = obj.qux);", + options: ["a", "bar", "baz", "qux"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 10 + } + ] + }, + { + code: "({a: [obj.bar] = baz} = qux);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 11 + } + ] + }, + { + code: "({foo: { a: obj.bar = baz}} = qux);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 17 + } + ] + }, + { + code: "({foo: { [a]: obj.bar }} = baz);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 19 + } + ] + }, + { + code: "({...obj.bar} = baz);", + options: ["bar"], + parserOptions: { ecmaVersion: 9 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 10 + } + ] + }, + { + code: "([obj.bar] = baz);", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 7 + } + ] + }, + { + code: "const [bar] = baz;", + options: ["bar"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "bar" }, + type: "Identifier", + column: 8 + } + ] + }, + + // not a reference to a global variable, because it isn't a reference to a variable + { + code: "foo.undefined = 1;", + options: ["undefined"], + errors: [ + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier" + } + ] + }, + { + code: "var foo = { undefined: 1 };", + options: ["undefined"], + errors: [ + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier" + } + ] + }, + { + code: "var foo = { undefined: undefined };", + options: ["undefined"], + errors: [ + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier", + column: 13 + } + ] + }, + { + code: "var foo = { Number() {} };", + options: ["Number"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier" + } + ] + }, + { + code: "class Foo { Number() {} }", + options: ["Number"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier" + } + ] + }, + { + code: "myGlobal: while(foo) { break myGlobal; } ", + options: ["myGlobal"], + globals: { myGlobal: "readonly" }, + errors: [ + { + messageId: "restricted", + data: { name: "myGlobal" }, + type: "Identifier", + column: 1 + }, + { + messageId: "restricted", + data: { name: "myGlobal" }, + type: "Identifier", + column: 30 + } + ] + }, + + // globals declared in the given source code are not excluded from consideration + { + code: "const foo = 1; bar = foo;", + options: ["foo"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 7 + }, + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 22 + } + ] + }, + { + code: "let foo; foo = bar;", + options: ["foo"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 5 + }, + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 10 + } + ] + }, + { + code: "bar = foo; var foo;", + options: ["foo"], + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 7 + }, + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 16 + } + ] + }, + { + code: "function foo() {} var bar = foo;", + options: ["foo"], + errors: [ + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 10 + }, + { + messageId: "restricted", + data: { name: "foo" }, + type: "Identifier", + column: 29 + } + ] + }, + { + code: "class Foo {} var bar = Foo;", + options: ["Foo"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "Foo" }, + type: "Identifier", + column: 7 + }, + { + messageId: "restricted", + data: { name: "Foo" }, + type: "Identifier", + column: 24 + } + ] + }, + + // redeclared globals are not excluded from consideration + { + code: "let undefined; undefined = 1;", + options: ["undefined"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier", + column: 5 + }, + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier", + column: 16 + } + ] + }, + { + code: "foo = undefined; var undefined;", + options: ["undefined"], + errors: [ + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier", + column: 7 + }, + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier", + column: 22 + } + ] + }, + { + code: "function undefined(){} x = undefined;", + options: ["undefined"], + errors: [ + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier", + column: 10 + }, + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier", + column: 28 + } + ] + }, + { + code: "class Number {} x = Number.NaN;", + options: ["Number"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier", + column: 7 + }, + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier", + column: 21 + } + ] + }, + + /* + * Assignment to a property with a restricted name isn't allowed, in general. + * In this case, that restriction prevents creating a global variable with a restricted name. + */ + { + code: "/* globals myGlobal */ window.myGlobal = 5; foo = myGlobal;", + options: ["myGlobal"], + env: { browser: true }, + errors: [ + { + messageId: "restricted", + data: { name: "myGlobal" }, + type: "Identifier", + column: 31 + } + ] + }, + + // disabled global variables + { + code: "var foo = undefined;", + options: ["undefined"], + globals: { undefined: "off" }, + errors: [ + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier" + } + ] + }, + { + code: "/* globals Number: off */ Number.parseInt()", + options: ["Number"], + errors: [ + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier" + } + ] + }, + { + code: "var foo = [Map];", // this actually isn't a disabled global: it was never enabled because es6 environment isn't enabled + options: ["Map"], + errors: [ + { + messageId: "restricted", + data: { name: "Map" }, + type: "Identifier" + } + ] + }, + + // shadowed global variables + { + code: "if (foo) { let undefined; bar = undefined; }", + options: ["undefined"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier", + column: 16 + }, + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier", + column: 33 + } + ] + }, + { + code: "function foo(Number) { var x = Number.NaN; }", + options: ["Number"], + errors: [ + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier", + column: 14 + }, + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier", + column: 32 + } + ] + }, + { + code: "function foo() { var myGlobal; x = myGlobal; }", + options: ["myGlobal"], + globals: { myGlobal: "readonly" }, + errors: [ + { + messageId: "restricted", + data: { name: "myGlobal" }, + type: "Identifier", + column: 22 + }, + { + messageId: "restricted", + data: { name: "myGlobal" }, + type: "Identifier", + column: 36 + } + ] + }, + { + code: "function foo(bar) { return Number.parseInt(bar); } const Number = 1;", + options: ["Number"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier", + column: 28 + }, + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier", + column: 58 + } + ] + }, + { + code: "import Number from 'myNumber'; const foo = Number.parseInt(bar);", + options: ["Number"], + parserOptions: { ecmaVersion: 6, sourceType: "module" }, + errors: [ + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier", + column: 8 + }, + { + messageId: "restricted", + data: { name: "Number" }, + type: "Identifier", + column: 44 + } + ] + }, + { + code: "var foo = function undefined() {};", + options: ["undefined"], + errors: [ + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier" + } + ] + }, + + // this is a reference to a global variable, but at the same time creates a property with a restricted name + { + code: "var foo = { undefined }", + options: ["undefined"], + parserOptions: { ecmaVersion: 6 }, + errors: [ + { + messageId: "restricted", + data: { name: "undefined" }, + type: "Identifier" + } + ] + } + ] +}); diff --git a/tools/rule-types.json b/tools/rule-types.json index 6f2e6a834b3..2421b9fdaad 100644 --- a/tools/rule-types.json +++ b/tools/rule-types.json @@ -43,7 +43,7 @@ "grouped-accessor-pairs": "suggestion", "guard-for-in": "suggestion", "handle-callback-err": "suggestion", - "id-blacklist": "suggestion", + "id-denylist": "suggestion", "id-length": "suggestion", "id-match": "suggestion", "implicit-arrow-linebreak": "layout", @@ -280,4 +280,4 @@ "wrap-regex": "layout", "yield-star-spacing": "layout", "yoda": "suggestion" -} \ No newline at end of file +}