eslint 8.36.0 → 8.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/config/default-config.js +1 -4
- package/lib/config/flat-config-array.js +11 -12
- package/lib/config/flat-config-schema.js +4 -18
- package/lib/linter/linter.js +5 -30
- package/lib/rule-tester/flat-rule-tester.js +1 -1
- package/lib/rule-tester/rule-tester.js +1 -1
- package/lib/rules/camelcase.js +3 -2
- package/lib/rules/consistent-this.js +4 -2
- package/lib/rules/global-require.js +3 -1
- package/lib/rules/handle-callback-err.js +2 -1
- package/lib/rules/id-blacklist.js +3 -2
- package/lib/rules/id-denylist.js +3 -2
- package/lib/rules/id-match.js +3 -2
- package/lib/rules/logical-assignment-operators.js +3 -3
- package/lib/rules/no-alert.js +3 -1
- package/lib/rules/no-catch-shadow.js +3 -1
- package/lib/rules/no-console.js +3 -2
- package/lib/rules/no-constant-binary-expression.js +4 -2
- package/lib/rules/no-constant-condition.js +3 -2
- package/lib/rules/no-else-return.js +13 -12
- package/lib/rules/no-eval.js +4 -4
- package/lib/rules/no-extend-native.js +3 -2
- package/lib/rules/no-global-assign.js +3 -2
- package/lib/rules/no-implicit-globals.js +3 -2
- package/lib/rules/no-implied-eval.js +4 -3
- package/lib/rules/no-import-assign.js +3 -1
- package/lib/rules/no-invalid-this.js +2 -2
- package/lib/rules/no-label-var.js +2 -1
- package/lib/rules/no-lone-blocks.js +3 -2
- package/lib/rules/no-loop-func.js +3 -1
- package/lib/rules/no-misleading-character-class.js +11 -40
- package/lib/rules/no-native-reassign.js +3 -2
- package/lib/rules/no-new-func.js +7 -6
- package/lib/rules/no-new-native-nonconstructor.js +8 -6
- package/lib/rules/no-new-object.js +4 -1
- package/lib/rules/no-new-symbol.js +8 -6
- package/lib/rules/no-obj-calls.js +7 -5
- package/lib/rules/no-promise-executor-return.js +2 -1
- package/lib/rules/no-redeclare.js +3 -3
- package/lib/rules/no-regex-spaces.js +3 -1
- package/lib/rules/no-restricted-globals.js +4 -2
- package/lib/rules/no-setter-return.js +2 -1
- package/lib/rules/no-shadow.js +3 -2
- package/lib/rules/no-undef-init.js +1 -1
- package/lib/rules/no-undef.js +3 -2
- package/lib/rules/no-undefined.js +4 -2
- package/lib/rules/no-unmodified-loop-condition.js +2 -2
- package/lib/rules/no-unused-vars.js +1 -1
- package/lib/rules/no-use-before-define.js +3 -2
- package/lib/rules/no-useless-backreference.js +7 -5
- package/lib/rules/object-shorthand.js +3 -2
- package/lib/rules/prefer-arrow-callback.js +1 -1
- package/lib/rules/prefer-exponentiation-operator.js +4 -4
- package/lib/rules/prefer-named-capture-group.js +6 -6
- package/lib/rules/prefer-object-has-own.js +4 -2
- package/lib/rules/prefer-object-spread.js +11 -11
- package/lib/rules/prefer-regex-literals.js +24 -25
- package/lib/rules/prefer-rest-params.js +5 -2
- package/lib/rules/radix.js +11 -11
- package/lib/rules/require-atomic-updates.js +2 -2
- package/lib/rules/require-unicode-regexp.js +62 -6
- package/lib/rules/symbol-description.js +7 -5
- package/lib/rules/utils/regular-expressions.js +42 -0
- package/lib/rules/valid-typeof.js +3 -3
- package/lib/source-code/source-code.js +51 -0
- package/lib/source-code/token-store/utils.js +14 -4
- package/package.json +5 -5
@@ -19,9 +19,6 @@ exports.defaultConfig = [
|
|
19
19
|
{
|
20
20
|
plugins: {
|
21
21
|
"@": {
|
22
|
-
parsers: {
|
23
|
-
espree: require("espree")
|
24
|
-
},
|
25
22
|
|
26
23
|
/*
|
27
24
|
* Because we try to delay loading rules until absolutely
|
@@ -43,7 +40,7 @@ exports.defaultConfig = [
|
|
43
40
|
languageOptions: {
|
44
41
|
sourceType: "module",
|
45
42
|
ecmaVersion: "latest",
|
46
|
-
parser: "
|
43
|
+
parser: require("espree"),
|
47
44
|
parserOptions: {}
|
48
45
|
}
|
49
46
|
},
|
@@ -192,17 +192,7 @@ class FlatConfigArray extends ConfigArray {
|
|
192
192
|
if (languageOptions && languageOptions.parser) {
|
193
193
|
const { parser } = languageOptions;
|
194
194
|
|
195
|
-
if (typeof parser === "
|
196
|
-
const { pluginName, objectName: localParserName } = splitPluginIdentifier(parser);
|
197
|
-
|
198
|
-
parserName = parser;
|
199
|
-
|
200
|
-
if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[localParserName]) {
|
201
|
-
throw new TypeError(`Key "parser": Could not find "${localParserName}" in plugin "${pluginName}".`);
|
202
|
-
}
|
203
|
-
|
204
|
-
languageOptions.parser = plugins[pluginName].parsers[localParserName];
|
205
|
-
} else if (typeof parser === "object") {
|
195
|
+
if (typeof parser === "object") {
|
206
196
|
parserName = getObjectId(parser);
|
207
197
|
|
208
198
|
if (!parserName) {
|
@@ -255,7 +245,16 @@ class FlatConfigArray extends ConfigArray {
|
|
255
245
|
|
256
246
|
return {
|
257
247
|
...this,
|
258
|
-
plugins: Object.
|
248
|
+
plugins: Object.entries(plugins).map(([namespace, plugin]) => {
|
249
|
+
|
250
|
+
const pluginId = getObjectId(plugin);
|
251
|
+
|
252
|
+
if (!pluginId) {
|
253
|
+
return namespace;
|
254
|
+
}
|
255
|
+
|
256
|
+
return `${namespace}:${pluginId}`;
|
257
|
+
}),
|
259
258
|
languageOptions: {
|
260
259
|
...languageOptions,
|
261
260
|
parser: parserName
|
@@ -179,18 +179,6 @@ function assertIsObject(value) {
|
|
179
179
|
}
|
180
180
|
}
|
181
181
|
|
182
|
-
/**
|
183
|
-
* Validates that a value is an object or a string.
|
184
|
-
* @param {any} value The value to check.
|
185
|
-
* @returns {void}
|
186
|
-
* @throws {TypeError} If the value isn't an object or a string.
|
187
|
-
*/
|
188
|
-
function assertIsObjectOrString(value) {
|
189
|
-
if ((!value || typeof value !== "object") && typeof value !== "string") {
|
190
|
-
throw new TypeError("Expected an object or string.");
|
191
|
-
}
|
192
|
-
}
|
193
|
-
|
194
182
|
//-----------------------------------------------------------------------------
|
195
183
|
// Low-Level Schemas
|
196
184
|
//-----------------------------------------------------------------------------
|
@@ -242,15 +230,13 @@ const globalsSchema = {
|
|
242
230
|
const parserSchema = {
|
243
231
|
merge: "replace",
|
244
232
|
validate(value) {
|
245
|
-
assertIsObjectOrString(value);
|
246
233
|
|
247
|
-
if (
|
248
|
-
|
234
|
+
if (!value || typeof value !== "object" ||
|
235
|
+
(typeof value.parse !== "function" && typeof value.parseForESLint !== "function")
|
236
|
+
) {
|
237
|
+
throw new TypeError("Expected object with parse() or parseForESLint() method.");
|
249
238
|
}
|
250
239
|
|
251
|
-
if (typeof value === "string") {
|
252
|
-
assertIsPluginMemberName(value);
|
253
|
-
}
|
254
240
|
}
|
255
241
|
};
|
256
242
|
|
package/lib/linter/linter.js
CHANGED
@@ -857,47 +857,22 @@ function parse(text, languageOptions, filePath) {
|
|
857
857
|
}
|
858
858
|
}
|
859
859
|
|
860
|
-
/**
|
861
|
-
* Gets the scope for the current node
|
862
|
-
* @param {ScopeManager} scopeManager The scope manager for this AST
|
863
|
-
* @param {ASTNode} currentNode The node to get the scope of
|
864
|
-
* @returns {eslint-scope.Scope} The scope information for this node
|
865
|
-
*/
|
866
|
-
function getScope(scopeManager, currentNode) {
|
867
|
-
|
868
|
-
// On Program node, get the outermost scope to avoid return Node.js special function scope or ES modules scope.
|
869
|
-
const inner = currentNode.type !== "Program";
|
870
|
-
|
871
|
-
for (let node = currentNode; node; node = node.parent) {
|
872
|
-
const scope = scopeManager.acquire(node, inner);
|
873
|
-
|
874
|
-
if (scope) {
|
875
|
-
if (scope.type === "function-expression-name") {
|
876
|
-
return scope.childScopes[0];
|
877
|
-
}
|
878
|
-
return scope;
|
879
|
-
}
|
880
|
-
}
|
881
|
-
|
882
|
-
return scopeManager.scopes[0];
|
883
|
-
}
|
884
|
-
|
885
860
|
/**
|
886
861
|
* Marks a variable as used in the current scope
|
887
|
-
* @param {
|
862
|
+
* @param {SourceCode} sourceCode The source code for the currently linted file.
|
888
863
|
* @param {ASTNode} currentNode The node currently being traversed
|
889
864
|
* @param {LanguageOptions} languageOptions The options used to parse this text
|
890
865
|
* @param {string} name The name of the variable that should be marked as used.
|
891
866
|
* @returns {boolean} True if the variable was found and marked as used, false if not.
|
892
867
|
*/
|
893
|
-
function markVariableAsUsed(
|
868
|
+
function markVariableAsUsed(sourceCode, currentNode, languageOptions, name) {
|
894
869
|
const parserOptions = languageOptions.parserOptions;
|
895
870
|
const sourceType = languageOptions.sourceType;
|
896
871
|
const hasGlobalReturn =
|
897
872
|
(parserOptions.ecmaFeatures && parserOptions.ecmaFeatures.globalReturn) ||
|
898
873
|
sourceType === "commonjs";
|
899
874
|
const specialScope = hasGlobalReturn || sourceType === "module";
|
900
|
-
const currentScope = getScope(
|
875
|
+
const currentScope = sourceCode.getScope(currentNode);
|
901
876
|
|
902
877
|
// Special Node.js scope means we need to start one level deeper
|
903
878
|
const initialScope = currentScope.type === "global" && specialScope ? currentScope.childScopes[0] : currentScope;
|
@@ -1026,9 +1001,9 @@ function runRules(sourceCode, configuredRules, ruleMapper, parserName, languageO
|
|
1026
1001
|
getCwd: () => cwd,
|
1027
1002
|
getFilename: () => filename,
|
1028
1003
|
getPhysicalFilename: () => physicalFilename || filename,
|
1029
|
-
getScope: () => getScope(
|
1004
|
+
getScope: () => sourceCode.getScope(currentNode),
|
1030
1005
|
getSourceCode: () => sourceCode,
|
1031
|
-
markVariableAsUsed: name => markVariableAsUsed(sourceCode
|
1006
|
+
markVariableAsUsed: name => markVariableAsUsed(sourceCode, currentNode, languageOptions, name),
|
1032
1007
|
parserOptions: {
|
1033
1008
|
...languageOptions.parserOptions
|
1034
1009
|
},
|
@@ -345,7 +345,7 @@ class FlatRuleTester {
|
|
345
345
|
* @returns {void}
|
346
346
|
*/
|
347
347
|
static setDefaultConfig(config) {
|
348
|
-
if (typeof config !== "object") {
|
348
|
+
if (typeof config !== "object" || config === null) {
|
349
349
|
throw new TypeError("FlatRuleTester.setDefaultConfig: config must be an object");
|
350
350
|
}
|
351
351
|
sharedDefaultConfig = config;
|
@@ -412,7 +412,7 @@ class RuleTester {
|
|
412
412
|
* @returns {void}
|
413
413
|
*/
|
414
414
|
static setDefaultConfig(config) {
|
415
|
-
if (typeof config !== "object") {
|
415
|
+
if (typeof config !== "object" || config === null) {
|
416
416
|
throw new TypeError("RuleTester.setDefaultConfig: config must be an object");
|
417
417
|
}
|
418
418
|
defaultConfig = config;
|
package/lib/rules/camelcase.js
CHANGED
@@ -73,6 +73,7 @@ module.exports = {
|
|
73
73
|
const ignoreImports = options.ignoreImports;
|
74
74
|
const ignoreGlobals = options.ignoreGlobals;
|
75
75
|
const allow = options.allow || [];
|
76
|
+
const sourceCode = context.getSourceCode();
|
76
77
|
|
77
78
|
//--------------------------------------------------------------------------
|
78
79
|
// Helpers
|
@@ -245,8 +246,8 @@ module.exports = {
|
|
245
246
|
return {
|
246
247
|
|
247
248
|
// Report camelcase of global variable references ------------------
|
248
|
-
Program() {
|
249
|
-
const scope =
|
249
|
+
Program(node) {
|
250
|
+
const scope = sourceCode.getScope(node);
|
250
251
|
|
251
252
|
if (!ignoreGlobals) {
|
252
253
|
|
@@ -36,6 +36,7 @@ module.exports = {
|
|
36
36
|
|
37
37
|
create(context) {
|
38
38
|
let aliases = [];
|
39
|
+
const sourceCode = context.getSourceCode();
|
39
40
|
|
40
41
|
if (context.options.length === 0) {
|
41
42
|
aliases.push("that");
|
@@ -115,10 +116,11 @@ module.exports = {
|
|
115
116
|
|
116
117
|
/**
|
117
118
|
* Check each alias to ensure that is was assigned to the correct value.
|
119
|
+
* @param {ASTNode} node The node that represents the scope to check.
|
118
120
|
* @returns {void}
|
119
121
|
*/
|
120
|
-
function ensureWasAssigned() {
|
121
|
-
const scope =
|
122
|
+
function ensureWasAssigned(node) {
|
123
|
+
const scope = sourceCode.getScope(node);
|
122
124
|
|
123
125
|
aliases.forEach(alias => {
|
124
126
|
checkWasAssigned(alias, scope);
|
@@ -71,9 +71,11 @@ module.exports = {
|
|
71
71
|
},
|
72
72
|
|
73
73
|
create(context) {
|
74
|
+
const sourceCode = context.getSourceCode();
|
75
|
+
|
74
76
|
return {
|
75
77
|
CallExpression(node) {
|
76
|
-
const currentScope =
|
78
|
+
const currentScope = sourceCode.getScope(node);
|
77
79
|
|
78
80
|
if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) {
|
79
81
|
const isGoodRequire = context.getAncestors().every(parent => ACCEPTABLE_PARENTS.has(parent.type));
|
@@ -38,6 +38,7 @@ module.exports = {
|
|
38
38
|
create(context) {
|
39
39
|
|
40
40
|
const errorArgument = context.options[0] || "err";
|
41
|
+
const sourceCode = context.getSourceCode();
|
41
42
|
|
42
43
|
/**
|
43
44
|
* Checks if the given argument should be interpreted as a regexp pattern.
|
@@ -79,7 +80,7 @@ module.exports = {
|
|
79
80
|
* @returns {void}
|
80
81
|
*/
|
81
82
|
function checkForError(node) {
|
82
|
-
const scope =
|
83
|
+
const scope = sourceCode.getScope(node),
|
83
84
|
parameters = getParameters(scope),
|
84
85
|
firstParameter = parameters[0];
|
85
86
|
|
@@ -140,6 +140,7 @@ module.exports = {
|
|
140
140
|
|
141
141
|
const denyList = new Set(context.options);
|
142
142
|
const reportedNodes = new Set();
|
143
|
+
const sourceCode = context.getSourceCode();
|
143
144
|
|
144
145
|
let globalScope;
|
145
146
|
|
@@ -231,8 +232,8 @@ module.exports = {
|
|
231
232
|
|
232
233
|
return {
|
233
234
|
|
234
|
-
Program() {
|
235
|
-
globalScope =
|
235
|
+
Program(node) {
|
236
|
+
globalScope = sourceCode.getScope(node);
|
236
237
|
},
|
237
238
|
|
238
239
|
Identifier(node) {
|
package/lib/rules/id-denylist.js
CHANGED
@@ -121,6 +121,7 @@ module.exports = {
|
|
121
121
|
|
122
122
|
const denyList = new Set(context.options);
|
123
123
|
const reportedNodes = new Set();
|
124
|
+
const sourceCode = context.getSourceCode();
|
124
125
|
|
125
126
|
let globalScope;
|
126
127
|
|
@@ -210,8 +211,8 @@ module.exports = {
|
|
210
211
|
|
211
212
|
return {
|
212
213
|
|
213
|
-
Program() {
|
214
|
-
globalScope =
|
214
|
+
Program(node) {
|
215
|
+
globalScope = sourceCode.getScope(node);
|
215
216
|
},
|
216
217
|
|
217
218
|
[[
|
package/lib/rules/id-match.js
CHANGED
@@ -67,6 +67,7 @@ module.exports = {
|
|
67
67
|
onlyDeclarations = !!options.onlyDeclarations,
|
68
68
|
ignoreDestructuring = !!options.ignoreDestructuring;
|
69
69
|
|
70
|
+
const sourceCode = context.getSourceCode();
|
70
71
|
let globalScope;
|
71
72
|
|
72
73
|
//--------------------------------------------------------------------------
|
@@ -170,8 +171,8 @@ module.exports = {
|
|
170
171
|
|
171
172
|
return {
|
172
173
|
|
173
|
-
Program() {
|
174
|
-
globalScope =
|
174
|
+
Program(node) {
|
175
|
+
globalScope = sourceCode.getScope(node);
|
175
176
|
},
|
176
177
|
|
177
178
|
Identifier(node) {
|
@@ -159,7 +159,7 @@ module.exports = {
|
|
159
159
|
type: "suggestion",
|
160
160
|
|
161
161
|
docs: {
|
162
|
-
description: "Require or disallow logical assignment
|
162
|
+
description: "Require or disallow logical assignment operator shorthand",
|
163
163
|
recommended: false,
|
164
164
|
url: "https://eslint.org/docs/rules/logical-assignment-operators"
|
165
165
|
},
|
@@ -206,7 +206,7 @@ module.exports = {
|
|
206
206
|
const mode = context.options[0] === "never" ? "never" : "always";
|
207
207
|
const checkIf = mode === "always" && context.options.length > 1 && context.options[1].enforceForIfStatements;
|
208
208
|
const sourceCode = context.getSourceCode();
|
209
|
-
const isStrict =
|
209
|
+
const isStrict = sourceCode.getScope(sourceCode.ast).isStrict;
|
210
210
|
|
211
211
|
/**
|
212
212
|
* Returns false if the access could be a getter
|
@@ -409,7 +409,7 @@ module.exports = {
|
|
409
409
|
}
|
410
410
|
|
411
411
|
const body = hasBody ? ifNode.consequent.body[0] : ifNode.consequent;
|
412
|
-
const scope =
|
412
|
+
const scope = sourceCode.getScope(ifNode);
|
413
413
|
const existence = getExistence(ifNode.test, scope);
|
414
414
|
|
415
415
|
if (
|
package/lib/rules/no-alert.js
CHANGED
@@ -101,10 +101,12 @@ module.exports = {
|
|
101
101
|
},
|
102
102
|
|
103
103
|
create(context) {
|
104
|
+
const sourceCode = context.getSourceCode();
|
105
|
+
|
104
106
|
return {
|
105
107
|
CallExpression(node) {
|
106
108
|
const callee = skipChainExpression(node.callee),
|
107
|
-
currentScope =
|
109
|
+
currentScope = sourceCode.getScope(node);
|
108
110
|
|
109
111
|
// without window.
|
110
112
|
if (callee.type === "Identifier") {
|
@@ -39,6 +39,8 @@ module.exports = {
|
|
39
39
|
|
40
40
|
create(context) {
|
41
41
|
|
42
|
+
const sourceCode = context.getSourceCode();
|
43
|
+
|
42
44
|
//--------------------------------------------------------------------------
|
43
45
|
// Helpers
|
44
46
|
//--------------------------------------------------------------------------
|
@@ -60,7 +62,7 @@ module.exports = {
|
|
60
62
|
return {
|
61
63
|
|
62
64
|
"CatchClause[param!=null]"(node) {
|
63
|
-
let scope =
|
65
|
+
let scope = sourceCode.getScope(node);
|
64
66
|
|
65
67
|
/*
|
66
68
|
* When ecmaVersion >= 6, CatchClause creates its own scope
|
package/lib/rules/no-console.js
CHANGED
@@ -51,6 +51,7 @@ module.exports = {
|
|
51
51
|
create(context) {
|
52
52
|
const options = context.options[0] || {};
|
53
53
|
const allowed = options.allow || [];
|
54
|
+
const sourceCode = context.getSourceCode();
|
54
55
|
|
55
56
|
/**
|
56
57
|
* Checks whether the given reference is 'console' or not.
|
@@ -109,8 +110,8 @@ module.exports = {
|
|
109
110
|
}
|
110
111
|
|
111
112
|
return {
|
112
|
-
"Program:exit"() {
|
113
|
-
const scope =
|
113
|
+
"Program:exit"(node) {
|
114
|
+
const scope = sourceCode.getScope(node);
|
114
115
|
const consoleVar = astUtils.getVariableByName(scope, "console");
|
115
116
|
const shadowed = consoleVar && consoleVar.defs.length > 0;
|
116
117
|
|
@@ -453,10 +453,12 @@ module.exports = {
|
|
453
453
|
},
|
454
454
|
|
455
455
|
create(context) {
|
456
|
+
const sourceCode = context.getSourceCode();
|
457
|
+
|
456
458
|
return {
|
457
459
|
LogicalExpression(node) {
|
458
460
|
const { operator, left } = node;
|
459
|
-
const scope =
|
461
|
+
const scope = sourceCode.getScope(node);
|
460
462
|
|
461
463
|
if ((operator === "&&" || operator === "||") && isConstant(scope, left, true)) {
|
462
464
|
context.report({ node: left, messageId: "constantShortCircuit", data: { property: "truthiness", operator } });
|
@@ -465,7 +467,7 @@ module.exports = {
|
|
465
467
|
}
|
466
468
|
},
|
467
469
|
BinaryExpression(node) {
|
468
|
-
const scope =
|
470
|
+
const scope = sourceCode.getScope(node);
|
469
471
|
const { right, left, operator } = node;
|
470
472
|
const rightConstantOperand = findBinaryExpressionConstantOperand(scope, left, right, operator);
|
471
473
|
const leftConstantOperand = findBinaryExpressionConstantOperand(scope, right, left, operator);
|
@@ -48,6 +48,7 @@ module.exports = {
|
|
48
48
|
const options = context.options[0] || {},
|
49
49
|
checkLoops = options.checkLoops !== false,
|
50
50
|
loopSetStack = [];
|
51
|
+
const sourceCode = context.getSourceCode();
|
51
52
|
|
52
53
|
let loopsInCurrentScope = new Set();
|
53
54
|
|
@@ -62,7 +63,7 @@ module.exports = {
|
|
62
63
|
* @private
|
63
64
|
*/
|
64
65
|
function trackConstantConditionLoop(node) {
|
65
|
-
if (node.test && isConstant(
|
66
|
+
if (node.test && isConstant(sourceCode.getScope(node), node.test, true)) {
|
66
67
|
loopsInCurrentScope.add(node);
|
67
68
|
}
|
68
69
|
}
|
@@ -87,7 +88,7 @@ module.exports = {
|
|
87
88
|
* @private
|
88
89
|
*/
|
89
90
|
function reportIfConstant(node) {
|
90
|
-
if (node.test && isConstant(
|
91
|
+
if (node.test && isConstant(sourceCode.getScope(node), node.test, true)) {
|
91
92
|
context.report({ node: node.test, messageId: "unexpected" });
|
92
93
|
}
|
93
94
|
}
|
@@ -47,6 +47,8 @@ module.exports = {
|
|
47
47
|
|
48
48
|
create(context) {
|
49
49
|
|
50
|
+
const sourceCode = context.getSourceCode();
|
51
|
+
|
50
52
|
//--------------------------------------------------------------------------
|
51
53
|
// Helpers
|
52
54
|
//--------------------------------------------------------------------------
|
@@ -169,25 +171,24 @@ module.exports = {
|
|
169
171
|
|
170
172
|
/**
|
171
173
|
* Display the context report if rule is violated
|
172
|
-
* @param {Node}
|
174
|
+
* @param {Node} elseNode The 'else' node
|
173
175
|
* @returns {void}
|
174
176
|
*/
|
175
|
-
function displayReport(
|
176
|
-
const currentScope =
|
177
|
+
function displayReport(elseNode) {
|
178
|
+
const currentScope = sourceCode.getScope(elseNode.parent);
|
177
179
|
|
178
180
|
context.report({
|
179
|
-
node,
|
181
|
+
node: elseNode,
|
180
182
|
messageId: "unexpected",
|
181
183
|
fix(fixer) {
|
182
184
|
|
183
|
-
if (!isSafeFromNameCollisions(
|
185
|
+
if (!isSafeFromNameCollisions(elseNode, currentScope)) {
|
184
186
|
return null;
|
185
187
|
}
|
186
188
|
|
187
|
-
const
|
188
|
-
const startToken = sourceCode.getFirstToken(node);
|
189
|
+
const startToken = sourceCode.getFirstToken(elseNode);
|
189
190
|
const elseToken = sourceCode.getTokenBefore(startToken);
|
190
|
-
const source = sourceCode.getText(
|
191
|
+
const source = sourceCode.getText(elseNode);
|
191
192
|
const lastIfToken = sourceCode.getTokenBefore(elseToken);
|
192
193
|
let fixedSource, firstTokenOfElseBlock;
|
193
194
|
|
@@ -203,14 +204,14 @@ module.exports = {
|
|
203
204
|
* safe to remove the else keyword, because ASI will not add a semicolon
|
204
205
|
* after the if block
|
205
206
|
*/
|
206
|
-
const ifBlockMaybeUnsafe =
|
207
|
+
const ifBlockMaybeUnsafe = elseNode.parent.consequent.type !== "BlockStatement" && lastIfToken.value !== ";";
|
207
208
|
const elseBlockUnsafe = /^[([/+`-]/u.test(firstTokenOfElseBlock.value);
|
208
209
|
|
209
210
|
if (ifBlockMaybeUnsafe && elseBlockUnsafe) {
|
210
211
|
return null;
|
211
212
|
}
|
212
213
|
|
213
|
-
const endToken = sourceCode.getLastToken(
|
214
|
+
const endToken = sourceCode.getLastToken(elseNode);
|
214
215
|
const lastTokenOfElseBlock = sourceCode.getTokenBefore(endToken);
|
215
216
|
|
216
217
|
if (lastTokenOfElseBlock.value !== ";") {
|
@@ -244,8 +245,8 @@ module.exports = {
|
|
244
245
|
* Also, to avoid name collisions between two else blocks.
|
245
246
|
*/
|
246
247
|
return new FixTracker(fixer, sourceCode)
|
247
|
-
.retainEnclosingFunction(
|
248
|
-
.replaceTextRange([elseToken.range[0],
|
248
|
+
.retainEnclosingFunction(elseNode)
|
249
|
+
.replaceTextRange([elseToken.range[0], elseNode.range[1]], fixedSource);
|
249
250
|
}
|
250
251
|
});
|
251
252
|
}
|
package/lib/rules/no-eval.js
CHANGED
@@ -84,7 +84,7 @@ module.exports = {
|
|
84
84
|
* @returns {void}
|
85
85
|
*/
|
86
86
|
function enterThisScope(node) {
|
87
|
-
const strict =
|
87
|
+
const strict = sourceCode.getScope(node).isStrict;
|
88
88
|
|
89
89
|
funcInfo = {
|
90
90
|
upper: funcInfo,
|
@@ -221,7 +221,7 @@ module.exports = {
|
|
221
221
|
},
|
222
222
|
|
223
223
|
Program(node) {
|
224
|
-
const scope =
|
224
|
+
const scope = sourceCode.getScope(node),
|
225
225
|
features = context.parserOptions.ecmaFeatures || {},
|
226
226
|
strict =
|
227
227
|
scope.isStrict ||
|
@@ -239,8 +239,8 @@ module.exports = {
|
|
239
239
|
};
|
240
240
|
},
|
241
241
|
|
242
|
-
"Program:exit"() {
|
243
|
-
const globalScope =
|
242
|
+
"Program:exit"(node) {
|
243
|
+
const globalScope = sourceCode.getScope(node);
|
244
244
|
|
245
245
|
exitThisScope();
|
246
246
|
reportAccessingEval(globalScope);
|
@@ -51,6 +51,7 @@ module.exports = {
|
|
51
51
|
create(context) {
|
52
52
|
|
53
53
|
const config = context.options[0] || {};
|
54
|
+
const sourceCode = context.getSourceCode();
|
54
55
|
const exceptions = new Set(config.exceptions || []);
|
55
56
|
const modifiedBuiltins = new Set(
|
56
57
|
Object.keys(globals.builtin)
|
@@ -159,8 +160,8 @@ module.exports = {
|
|
159
160
|
|
160
161
|
return {
|
161
162
|
|
162
|
-
"Program:exit"() {
|
163
|
-
const globalScope =
|
163
|
+
"Program:exit"(node) {
|
164
|
+
const globalScope = sourceCode.getScope(node);
|
164
165
|
|
165
166
|
modifiedBuiltins.forEach(builtin => {
|
166
167
|
const builtinVar = globalScope.set.get(builtin);
|
@@ -41,6 +41,7 @@ module.exports = {
|
|
41
41
|
|
42
42
|
create(context) {
|
43
43
|
const config = context.options[0];
|
44
|
+
const sourceCode = context.getSourceCode();
|
44
45
|
const exceptions = (config && config.exceptions) || [];
|
45
46
|
|
46
47
|
/**
|
@@ -84,8 +85,8 @@ module.exports = {
|
|
84
85
|
}
|
85
86
|
|
86
87
|
return {
|
87
|
-
Program() {
|
88
|
-
const globalScope =
|
88
|
+
Program(node) {
|
89
|
+
const globalScope = sourceCode.getScope(node);
|
89
90
|
|
90
91
|
globalScope.variables.forEach(checkVariable);
|
91
92
|
}
|
@@ -43,6 +43,7 @@ module.exports = {
|
|
43
43
|
create(context) {
|
44
44
|
|
45
45
|
const checkLexicalBindings = context.options[0] && context.options[0].lexicalBindings === true;
|
46
|
+
const sourceCode = context.getSourceCode();
|
46
47
|
|
47
48
|
/**
|
48
49
|
* Reports the node.
|
@@ -62,8 +63,8 @@ module.exports = {
|
|
62
63
|
}
|
63
64
|
|
64
65
|
return {
|
65
|
-
Program() {
|
66
|
-
const scope =
|
66
|
+
Program(node) {
|
67
|
+
const scope = sourceCode.getScope(node);
|
67
68
|
|
68
69
|
scope.variables.forEach(variable => {
|
69
70
|
|
@@ -37,6 +37,7 @@ module.exports = {
|
|
37
37
|
create(context) {
|
38
38
|
const GLOBAL_CANDIDATES = Object.freeze(["global", "window", "globalThis"]);
|
39
39
|
const EVAL_LIKE_FUNC_PATTERN = /^(?:set(?:Interval|Timeout)|execScript)$/u;
|
40
|
+
const sourceCode = context.getSourceCode();
|
40
41
|
|
41
42
|
/**
|
42
43
|
* Checks whether a node is evaluated as a string or not.
|
@@ -66,7 +67,7 @@ module.exports = {
|
|
66
67
|
|
67
68
|
if (firstArgument) {
|
68
69
|
|
69
|
-
const staticValue = getStaticValue(firstArgument,
|
70
|
+
const staticValue = getStaticValue(firstArgument, sourceCode.getScope(node));
|
70
71
|
const isStaticString = staticValue && typeof staticValue.value === "string";
|
71
72
|
const isString = isStaticString || isEvaluatedString(firstArgument);
|
72
73
|
|
@@ -117,8 +118,8 @@ module.exports = {
|
|
117
118
|
reportImpliedEvalCallExpression(node);
|
118
119
|
}
|
119
120
|
},
|
120
|
-
"Program:exit"() {
|
121
|
-
const globalScope =
|
121
|
+
"Program:exit"(node) {
|
122
|
+
const globalScope = sourceCode.getScope(node);
|
122
123
|
|
123
124
|
GLOBAL_CANDIDATES
|
124
125
|
.map(candidate => astUtils.getVariableByName(globalScope, candidate))
|
@@ -194,9 +194,11 @@ module.exports = {
|
|
194
194
|
},
|
195
195
|
|
196
196
|
create(context) {
|
197
|
+
const sourceCode = context.getSourceCode();
|
198
|
+
|
197
199
|
return {
|
198
200
|
ImportDeclaration(node) {
|
199
|
-
const scope =
|
201
|
+
const scope = sourceCode.getScope(node);
|
200
202
|
|
201
203
|
for (const variable of context.getDeclaredVariables(node)) {
|
202
204
|
const shouldCheckMembers = variable.defs.some(
|