eslint 8.32.0 → 8.34.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/README.md
CHANGED
@@ -10,10 +10,10 @@
|
|
10
10
|
# ESLint
|
11
11
|
|
12
12
|
[Website](https://eslint.org) |
|
13
|
-
[
|
13
|
+
[Configure ESLint](https://eslint.org/docs/latest/use/configure) |
|
14
14
|
[Rules](https://eslint.org/docs/rules/) |
|
15
|
-
[
|
16
|
-
[
|
15
|
+
[Contribute to ESLint](https://eslint.org/docs/latest/contribute) |
|
16
|
+
[Report Bugs](https://eslint.org/docs/latest/contribute/report-bugs) |
|
17
17
|
[Code of Conduct](https://eslint.org/conduct) |
|
18
18
|
[Twitter](https://twitter.com/geteslint) |
|
19
19
|
[Mailing List](https://groups.google.com/group/eslint) |
|
@@ -59,7 +59,7 @@ After that, you can run ESLint on any file or directory like this:
|
|
59
59
|
|
60
60
|
## Configuration
|
61
61
|
|
62
|
-
After running `npm init @eslint/config`, you'll have
|
62
|
+
After running `npm init @eslint/config`, you'll have an `.eslintrc` file in your directory. In it, you'll see some rules configured like this:
|
63
63
|
|
64
64
|
```json
|
65
65
|
{
|
@@ -294,7 +294,7 @@ The following companies, organizations, and individuals support ESLint's ongoing
|
|
294
294
|
<p><a href="#"><img src="https://images.opencollective.com/2021-frameworks-fund/logo.png" alt="Chrome Frameworks Fund" height="undefined"></a> <a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
|
295
295
|
<p><a href="https://ridicorp.com/career/"><img src="https://images.opencollective.com/ridi-corporation/175dcf3/logo.png" alt="RIDI" height="96"></a> <a href="https://engineering.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a></p><h3>Silver Sponsors</h3>
|
296
296
|
<p><a href="https://sentry.io"><img src="https://avatars.githubusercontent.com/u/1396951?v=4" alt="Sentry" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a></p><h3>Bronze Sponsors</h3>
|
297
|
-
<p><a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://quickbookstoolhub.com"><img src="https://avatars.githubusercontent.com/u/95090305?u=e5bc398ef775c9ed19f955c675cdc1fb6abf01df&v=4" alt="QuickBooks Tool hub" height="32"></a></p>
|
297
|
+
<p><a href="https://paydaysay.com/"><img src="https://images.opencollective.com/payday-say-organization/9cd2467/logo.png" alt="PayDay Say" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://nx.dev"><img src="https://images.opencollective.com/nx/0efbe42/logo.png" alt="Nx (by Nrwl)" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://transloadit.com/"><img src="https://avatars.githubusercontent.com/u/125754?v=4" alt="Transloadit" height="32"></a> <a href="https://www.ignitionapp.com"><img src="https://avatars.githubusercontent.com/u/5753491?v=4" alt="Ignition" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a> <a href="https://quickbookstoolhub.com"><img src="https://avatars.githubusercontent.com/u/95090305?u=e5bc398ef775c9ed19f955c675cdc1fb6abf01df&v=4" alt="QuickBooks Tool hub" height="32"></a></p>
|
298
298
|
<!--sponsorsend-->
|
299
299
|
|
300
300
|
## Technology Sponsors
|
@@ -568,41 +568,6 @@ async function findFiles({
|
|
568
568
|
];
|
569
569
|
}
|
570
570
|
|
571
|
-
|
572
|
-
/**
|
573
|
-
* Checks whether a file exists at the given location
|
574
|
-
* @param {string} resolvedPath A path from the CWD
|
575
|
-
* @throws {Error} As thrown by `fs.statSync` or `fs.isFile`.
|
576
|
-
* @returns {boolean} `true` if a file exists
|
577
|
-
*/
|
578
|
-
function fileExists(resolvedPath) {
|
579
|
-
try {
|
580
|
-
return fs.statSync(resolvedPath).isFile();
|
581
|
-
} catch (error) {
|
582
|
-
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
583
|
-
return false;
|
584
|
-
}
|
585
|
-
throw error;
|
586
|
-
}
|
587
|
-
}
|
588
|
-
|
589
|
-
/**
|
590
|
-
* Checks whether a directory exists at the given location
|
591
|
-
* @param {string} resolvedPath A path from the CWD
|
592
|
-
* @throws {Error} As thrown by `fs.statSync` or `fs.isDirectory`.
|
593
|
-
* @returns {boolean} `true` if a directory exists
|
594
|
-
*/
|
595
|
-
function directoryExists(resolvedPath) {
|
596
|
-
try {
|
597
|
-
return fs.statSync(resolvedPath).isDirectory();
|
598
|
-
} catch (error) {
|
599
|
-
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
600
|
-
return false;
|
601
|
-
}
|
602
|
-
throw error;
|
603
|
-
}
|
604
|
-
}
|
605
|
-
|
606
571
|
//-----------------------------------------------------------------------------
|
607
572
|
// Results-related Helpers
|
608
573
|
//-----------------------------------------------------------------------------
|
@@ -924,8 +889,6 @@ function getCacheFile(cacheFile, cwd) {
|
|
924
889
|
|
925
890
|
module.exports = {
|
926
891
|
isGlobPattern,
|
927
|
-
directoryExists,
|
928
|
-
fileExists,
|
929
892
|
findFiles,
|
930
893
|
|
931
894
|
isNonEmptyString,
|
@@ -16,7 +16,7 @@ const astUtils = require("./utils/ast-utils");
|
|
16
16
|
//------------------------------------------------------------------------------
|
17
17
|
|
18
18
|
const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u;
|
19
|
-
const TARGET_METHODS = /^(?:every|filter|find(?:Last)?(?:Index)?|flatMap|forEach|map|reduce(?:Right)?|some|sort)$/u;
|
19
|
+
const TARGET_METHODS = /^(?:every|filter|find(?:Last)?(?:Index)?|flatMap|forEach|map|reduce(?:Right)?|some|sort|toSorted)$/u;
|
20
20
|
|
21
21
|
/**
|
22
22
|
* Checks a given code path segment is reachable.
|
@@ -766,6 +766,38 @@ module.exports = {
|
|
766
766
|
return false;
|
767
767
|
}
|
768
768
|
|
769
|
+
/**
|
770
|
+
* Checks if the left-hand side of an assignment is an identifier, the operator is one of
|
771
|
+
* `=`, `&&=`, `||=` or `??=` and the right-hand side is an anonymous class or function.
|
772
|
+
*
|
773
|
+
* As per https://tc39.es/ecma262/#sec-assignment-operators-runtime-semantics-evaluation, an
|
774
|
+
* assignment involving one of the operators `=`, `&&=`, `||=` or `??=` where the right-hand
|
775
|
+
* side is an anonymous class or function and the left-hand side is an *unparenthesized*
|
776
|
+
* identifier has different semantics than other assignments.
|
777
|
+
* Specifically, when an expression like `foo = function () {}` is evaluated, `foo.name`
|
778
|
+
* will be set to the string "foo", i.e. the identifier name. The same thing does not happen
|
779
|
+
* when evaluating `(foo) = function () {}`.
|
780
|
+
* Since the parenthesizing of the identifier in the left-hand side is significant in this
|
781
|
+
* special case, the parentheses, if present, should not be flagged as unnecessary.
|
782
|
+
* @param {ASTNode} node an AssignmentExpression node.
|
783
|
+
* @returns {boolean} `true` if the left-hand side of the assignment is an identifier, the
|
784
|
+
* operator is one of `=`, `&&=`, `||=` or `??=` and the right-hand side is an anonymous
|
785
|
+
* class or function; otherwise, `false`.
|
786
|
+
*/
|
787
|
+
function isAnonymousFunctionAssignmentException({ left, operator, right }) {
|
788
|
+
if (left.type === "Identifier" && ["=", "&&=", "||=", "??="].includes(operator)) {
|
789
|
+
const rhsType = right.type;
|
790
|
+
|
791
|
+
if (rhsType === "ArrowFunctionExpression") {
|
792
|
+
return true;
|
793
|
+
}
|
794
|
+
if ((rhsType === "FunctionExpression" || rhsType === "ClassExpression") && !right.id) {
|
795
|
+
return true;
|
796
|
+
}
|
797
|
+
}
|
798
|
+
return false;
|
799
|
+
}
|
800
|
+
|
769
801
|
return {
|
770
802
|
ArrayExpression(node) {
|
771
803
|
node.elements
|
@@ -804,7 +836,8 @@ module.exports = {
|
|
804
836
|
},
|
805
837
|
|
806
838
|
AssignmentExpression(node) {
|
807
|
-
if (canBeAssignmentTarget(node.left) && hasExcessParens(node.left)
|
839
|
+
if (canBeAssignmentTarget(node.left) && hasExcessParens(node.left) &&
|
840
|
+
(!isAnonymousFunctionAssignmentException(node) || isParenthesisedTwice(node.left))) {
|
808
841
|
report(node.left);
|
809
842
|
}
|
810
843
|
|
@@ -27,27 +27,78 @@ module.exports = {
|
|
27
27
|
},
|
28
28
|
|
29
29
|
schema: [{
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
anyOf: [
|
31
|
+
{
|
32
|
+
type: "object",
|
33
|
+
properties: {
|
34
|
+
restrictedNamedExports: {
|
35
|
+
type: "array",
|
36
|
+
items: {
|
37
|
+
type: "string"
|
38
|
+
},
|
39
|
+
uniqueItems: true
|
40
|
+
}
|
36
41
|
},
|
37
|
-
|
42
|
+
additionalProperties: false
|
43
|
+
},
|
44
|
+
{
|
45
|
+
type: "object",
|
46
|
+
properties: {
|
47
|
+
restrictedNamedExports: {
|
48
|
+
type: "array",
|
49
|
+
items: {
|
50
|
+
type: "string",
|
51
|
+
pattern: "^(?!default$)"
|
52
|
+
},
|
53
|
+
uniqueItems: true
|
54
|
+
},
|
55
|
+
restrictDefaultExports: {
|
56
|
+
type: "object",
|
57
|
+
properties: {
|
58
|
+
|
59
|
+
// Allow/Disallow `export default foo; export default 42; export default function foo() {}` format
|
60
|
+
direct: {
|
61
|
+
type: "boolean"
|
62
|
+
},
|
63
|
+
|
64
|
+
// Allow/Disallow `export { foo as default };` declarations
|
65
|
+
named: {
|
66
|
+
type: "boolean"
|
67
|
+
},
|
68
|
+
|
69
|
+
// Allow/Disallow `export { default } from "mod"; export { default as default } from "mod";` declarations
|
70
|
+
defaultFrom: {
|
71
|
+
type: "boolean"
|
72
|
+
},
|
73
|
+
|
74
|
+
// Allow/Disallow `export { foo as default } from "mod";` declarations
|
75
|
+
namedFrom: {
|
76
|
+
type: "boolean"
|
77
|
+
},
|
78
|
+
|
79
|
+
// Allow/Disallow `export * as default from "mod"`; declarations
|
80
|
+
namespaceFrom: {
|
81
|
+
type: "boolean"
|
82
|
+
}
|
83
|
+
},
|
84
|
+
additionalProperties: false
|
85
|
+
}
|
86
|
+
},
|
87
|
+
additionalProperties: false
|
38
88
|
}
|
39
|
-
|
40
|
-
additionalProperties: false
|
89
|
+
]
|
41
90
|
}],
|
42
91
|
|
43
92
|
messages: {
|
44
|
-
restrictedNamed: "'{{name}}' is restricted from being used as an exported name."
|
93
|
+
restrictedNamed: "'{{name}}' is restricted from being used as an exported name.",
|
94
|
+
restrictedDefault: "Exporting 'default' is restricted."
|
45
95
|
}
|
46
96
|
},
|
47
97
|
|
48
98
|
create(context) {
|
49
99
|
|
50
100
|
const restrictedNames = new Set(context.options[0] && context.options[0].restrictedNamedExports);
|
101
|
+
const restrictDefaultExports = context.options[0] && context.options[0].restrictDefaultExports;
|
51
102
|
|
52
103
|
/**
|
53
104
|
* Checks and reports given exported name.
|
@@ -63,6 +114,42 @@ module.exports = {
|
|
63
114
|
messageId: "restrictedNamed",
|
64
115
|
data: { name }
|
65
116
|
});
|
117
|
+
return;
|
118
|
+
}
|
119
|
+
|
120
|
+
if (name === "default") {
|
121
|
+
if (node.parent.type === "ExportAllDeclaration") {
|
122
|
+
if (restrictDefaultExports && restrictDefaultExports.namespaceFrom) {
|
123
|
+
context.report({
|
124
|
+
node,
|
125
|
+
messageId: "restrictedDefault"
|
126
|
+
});
|
127
|
+
}
|
128
|
+
|
129
|
+
} else { // ExportSpecifier
|
130
|
+
const isSourceSpecified = !!node.parent.parent.source;
|
131
|
+
const specifierLocalName = astUtils.getModuleExportName(node.parent.local);
|
132
|
+
|
133
|
+
if (!isSourceSpecified && restrictDefaultExports && restrictDefaultExports.named) {
|
134
|
+
context.report({
|
135
|
+
node,
|
136
|
+
messageId: "restrictedDefault"
|
137
|
+
});
|
138
|
+
return;
|
139
|
+
}
|
140
|
+
|
141
|
+
if (isSourceSpecified && restrictDefaultExports) {
|
142
|
+
if (
|
143
|
+
(specifierLocalName === "default" && restrictDefaultExports.defaultFrom) ||
|
144
|
+
(specifierLocalName !== "default" && restrictDefaultExports.namedFrom)
|
145
|
+
) {
|
146
|
+
context.report({
|
147
|
+
node,
|
148
|
+
messageId: "restrictedDefault"
|
149
|
+
});
|
150
|
+
}
|
151
|
+
}
|
152
|
+
}
|
66
153
|
}
|
67
154
|
}
|
68
155
|
|
@@ -73,6 +160,15 @@ module.exports = {
|
|
73
160
|
}
|
74
161
|
},
|
75
162
|
|
163
|
+
ExportDefaultDeclaration(node) {
|
164
|
+
if (restrictDefaultExports && restrictDefaultExports.direct) {
|
165
|
+
context.report({
|
166
|
+
node,
|
167
|
+
messageId: "restrictedDefault"
|
168
|
+
});
|
169
|
+
}
|
170
|
+
},
|
171
|
+
|
76
172
|
ExportNamedDeclaration(node) {
|
77
173
|
const declaration = node.declaration;
|
78
174
|
|