eslint 7.12.1 → 7.16.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/CHANGELOG.md CHANGED
@@ -1,3 +1,47 @@
1
+ v7.16.0 - December 18, 2020
2
+
3
+ * [`a62ad6f`](https://github.com/eslint/eslint/commit/a62ad6f03151358b93b5fede022a30d67310705c) Update: fix false negative of no-extra-parens with NewExpression (#13930) (Milos Djermanovic)
4
+ * [`f85b4c7`](https://github.com/eslint/eslint/commit/f85b4c72668c95c79fdb342b74dbd53d21baa93f) Fix: require-atomic-updates false positive across await (fixes #11954) (#13915) (buhi)
5
+ * [`301d0c0`](https://github.com/eslint/eslint/commit/301d0c05229dbd6cfb1045d716524e8ec46fa2c1) Fix: no-constant-condition false positives with unary expressions (#13927) (Milos Djermanovic)
6
+ * [`555c128`](https://github.com/eslint/eslint/commit/555c128b49ae6d9c100a9f8429416417edb40d13) Fix: false positive with await and ** in no-extra-parens (fixes #12739) (#13923) (Milos Djermanovic)
7
+ * [`d93c935`](https://github.com/eslint/eslint/commit/d93c9350361d2aa1a1976c553e47ab399e51e8c9) Docs: update JSON Schema links (#13936) (Milos Djermanovic)
8
+ * [`8d0c93a`](https://github.com/eslint/eslint/commit/8d0c93a7ef9449c7b7d082bbb4b7d8465b0d6bac) Upgrade: table@6.0.4 (#13920) (Rouven Weßling)
9
+ * [`9247683`](https://github.com/eslint/eslint/commit/924768377a4935a95a6ff3866f9545a5a6178b53) Docs: Remove for deleted npm run profile script (#13931) (Brandon Mills)
10
+ * [`ab240d4`](https://github.com/eslint/eslint/commit/ab240d49833b4e6e594667c1abe5b0caa8a9cf70) Fix: prefer-exponentiation-operator invalid autofix with await (#13924) (Milos Djermanovic)
11
+ * [`dc76911`](https://github.com/eslint/eslint/commit/dc7691103554a99bdb2142561cb507f50f547e3b) Chore: Add .pre-commit-hooks.yaml file (#13628) (Álvaro Mondéjar)
12
+ * [`2124e1b`](https://github.com/eslint/eslint/commit/2124e1b5dad30a905dc26bde9da472bf622d3f50) Docs: Fix wrong rule name (#13913) (noisyboy25)
13
+ * [`06b5809`](https://github.com/eslint/eslint/commit/06b58096975935ec016d96dd5f333f059c270f26) Sponsors: Sync README with website (ESLint Jenkins)
14
+ * [`26fc12f`](https://github.com/eslint/eslint/commit/26fc12f88109af9d4081bf0e16364c411bce3009) Docs: Update README team and sponsors (ESLint Jenkins)
15
+
16
+ v7.15.0 - December 5, 2020
17
+
18
+ * [`5c11aab`](https://github.com/eslint/eslint/commit/5c11aabbe8249aeb8cad29bc6a33fc20c8c683ef) Upgrade: @eslint/esintrc and espree for bug fixes (refs #13878) (#13908) (Brandon Mills)
19
+ * [`0eb7957`](https://github.com/eslint/eslint/commit/0eb7957e27fd521317bd5c8479ce7abc1399169c) Upgrade: file-entry-cache@6.0.0 (#13877) (Rouven Weßling)
20
+ * [`683ad00`](https://github.com/eslint/eslint/commit/683ad00c41e1ae4d889deff82b2a94318e8c2129) New: no-unsafe-optional-chaining rule (fixes #13431) (#13859) (YeonJuan)
21
+ * [`cbc57fb`](https://github.com/eslint/eslint/commit/cbc57fb7d07c00663ed5781f5e6bc8f534cc2d76) Fix: one-var autofixing for export (fixes #13834) (#13891) (Anix)
22
+ * [`110cf96`](https://github.com/eslint/eslint/commit/110cf962d05625a8a1bf7b5f4ec2194db150eb32) Docs: Fix a broken link in working-with-rules.md (#13875) (Anton Niklasson)
23
+
24
+ v7.14.0 - November 20, 2020
25
+
26
+ * [`5f09073`](https://github.com/eslint/eslint/commit/5f0907399a9666dec78c74384c8969c01483c30e) Update: fix 'skip' options in no-irregular-whitespace (fixes #13852) (#13853) (Milos Djermanovic)
27
+ * [`1861b40`](https://github.com/eslint/eslint/commit/1861b4086f1018f43ab19744d866d5da986c500d) Docs: correct the function-call-argument-newline 'default' descriptions (#13866) (Trevin Hofmann)
28
+ * [`98c00c4`](https://github.com/eslint/eslint/commit/98c00c41d2aecb3a990393d430694f4ce6b47de5) New: Add no-nonoctal-decimal-escape rule (fixes #13765) (#13845) (Milos Djermanovic)
29
+ * [`95d2fe6`](https://github.com/eslint/eslint/commit/95d2fe6057498fc1cc2193d28c8c2d1593224b33) Chore: remove eslint comment from no-octal-escape tests (#13846) (Milos Djermanovic)
30
+ * [`2004b7e`](https://github.com/eslint/eslint/commit/2004b7ecd3db0d4e7376cc3344246f7b9ada5801) Fix: enable debug logs for @eslint/eslintrc (fixes #13850) (#13861) (Milos Djermanovic)
31
+ * [`d2239a1`](https://github.com/eslint/eslint/commit/d2239a1fdec452e24ede04e990d16d42516fa538) Fix: no-useless-constructor crash on bodyless constructor (fixes #13830) (#13842) (Ari Perkkiö)
32
+ * [`eda0aa1`](https://github.com/eslint/eslint/commit/eda0aa18498dd85eb618873e8e0f4ac97032cfca) Docs: no-restricted-imports is only for static imports (#13863) (Robat Williams)
33
+ * [`042ae44`](https://github.com/eslint/eslint/commit/042ae44682a8a6c5037d920689124e2304056dd8) Docs: Fix JS syntax and doc URL in working-with-custom-formatters.md (#13828) (Raphael LANG)
34
+ * [`038dc73`](https://github.com/eslint/eslint/commit/038dc73c99ae68eae2035ef303f3a947053c8f05) Chore: Test on Node.js 15 (#13844) (Brandon Mills)
35
+ * [`37a06d6`](https://github.com/eslint/eslint/commit/37a06d633d3669f0f43236141dc43465b8bc7ec5) Sponsors: Sync README with website (ESLint Jenkins)
36
+
37
+ v7.13.0 - November 6, 2020
38
+
39
+ * [`254e00f`](https://github.com/eslint/eslint/commit/254e00fea8745ff5a8bcc8cb874fcfd02996d81b) New: Configurable List Size For Per-Rule Performance Metrics (#13812) (Bryan Mishkin)
40
+ * [`6c3c710`](https://github.com/eslint/eslint/commit/6c3c710ade7cd8654990f1adb55b58f038eab92d) Docs: fix broken url in docs (#13815) (SaintMalik)
41
+ * [`4a09149`](https://github.com/eslint/eslint/commit/4a091495a236d231a5065ece972719a0c4dd1b77) Sponsors: Sync README with website (ESLint Jenkins)
42
+ * [`fb6fcbf`](https://github.com/eslint/eslint/commit/fb6fcbfe0a8c41b92f0a33ab90f159037bd195e2) Docs: Fix reference to Code of Conduct (#13797) (Tobias Nießen)
43
+ * [`1b89ebe`](https://github.com/eslint/eslint/commit/1b89ebe1bdbef7de6001100945b8f71429df302c) Sponsors: Sync README with website (ESLint Jenkins)
44
+
1
45
  v7.12.1 - October 26, 2020
2
46
 
3
47
  * [`08f33e8`](https://github.com/eslint/eslint/commit/08f33e8b9a353c3183be6f937785db7a30fb90eb) Upgrade: @eslint/eslintrc to fix rule schema validation (fixes #13793) (#13794) (Brandon Mills)
package/README.md CHANGED
@@ -14,7 +14,7 @@
14
14
  [Rules](https://eslint.org/docs/rules/) |
15
15
  [Contributing](https://eslint.org/docs/developer-guide/contributing) |
16
16
  [Reporting Bugs](https://eslint.org/docs/developer-guide/contributing/reporting-bugs) |
17
- [Code of Conduct](https://js.foundation/community/code-of-conduct) |
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) |
20
20
  [Chat Room](https://eslint.org/chat)
@@ -85,7 +85,7 @@ The three error levels allow you fine-grained control over how ESLint applies ru
85
85
 
86
86
  ## <a name="code-of-conduct"></a>Code of Conduct
87
87
 
88
- ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
88
+ ESLint adheres to the [JS Foundation Code of Conduct](https://eslint.org/conduct).
89
89
 
90
90
  ## <a name="filing-issues"></a>Filing Issues
91
91
 
@@ -207,11 +207,6 @@ Brandon Mills
207
207
  Toru Nagashima
208
208
  </a>
209
209
  </td><td align="center" valign="top" width="11%">
210
- <a href="https://github.com/kaicataldo">
211
- <img src="https://github.com/kaicataldo.png?s=75" width="75" height="75"><br />
212
- Kai Cataldo
213
- </a>
214
- </td><td align="center" valign="top" width="11%">
215
210
  <a href="https://github.com/mdjermanovic">
216
211
  <img src="https://github.com/mdjermanovic.png?s=75" width="75" height="75"><br />
217
212
  Milos Djermanovic
@@ -265,9 +260,9 @@ The following companies, organizations, and individuals support ESLint's ongoing
265
260
  <!--sponsorsstart-->
266
261
  <h3>Platinum Sponsors</h3>
267
262
  <p><a href="https://automattic.com"><img src="https://images.opencollective.com/photomatt/ff91f0b/logo.png" alt="Automattic" height="undefined"></a></p><h3>Gold Sponsors</h3>
268
- <p><a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/e780cd4/logo.png" alt="Shopify" height="96"></a> <a href="https://www.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://aka.ms/microsoftfossfund"><img src="https://avatars1.githubusercontent.com/u/67931232?u=7fddc652a464d7151b97e8f108392af7d54fa3e8&v=4" alt="Microsoft FOSS Fund Sponsorships" height="96"></a></p><h3>Silver Sponsors</h3>
263
+ <p><a href="https://google.com/chrome"><img src="https://images.opencollective.com/chrome/dc55bd4/logo.png" alt="Chrome's Web Framework & Tools Performance Fund" height="96"></a> <a href="https://www.shopify.com"><img src="https://images.opencollective.com/shopify/e780cd4/logo.png" alt="Shopify" height="96"></a> <a href="https://www.salesforce.com"><img src="https://images.opencollective.com/salesforce/ca8f997/logo.png" alt="Salesforce" height="96"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="96"></a> <a href="https://aka.ms/microsoftfossfund"><img src="https://avatars1.githubusercontent.com/u/67931232?u=7fddc652a464d7151b97e8f108392af7d54fa3e8&v=4" alt="Microsoft FOSS Fund Sponsorships" height="96"></a></p><h3>Silver Sponsors</h3>
269
264
  <p><a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://www.ampproject.org/"><img src="https://images.opencollective.com/amp/c8a3b25/logo.png" alt="AMP Project" height="64"></a></p><h3>Bronze Sponsors</h3>
270
- <p><a href="https://writersperhour.com"><img src="https://images.opencollective.com/writersperhour/5787d4b/logo.png" alt="Writers Per Hour" height="32"></a> <a href="https://www.betacalendars.com/printable-calendar"><img src="https://images.opencollective.com/betacalendars/9334b33/logo.png" alt="2021 calendar" height="32"></a> <a href="https://buy.fineproxy.org/eng/"><img src="https://images.opencollective.com/buy-fineproxy-org/2002c40/logo.png" alt="Buy.Fineproxy.Org" height="32"></a> <a href="https://www.veikkaajat.com"><img src="https://images.opencollective.com/veikkaajat/b92b427/logo.png" alt="Veikkaajat.com" 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="null"><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.marfeel.com/"><img src="https://images.opencollective.com/marfeel/4b88e30/logo.png" alt="Marfeel" height="32"></a> <a href="https://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
265
+ <p><a href="https://writersperhour.com"><img src="https://images.opencollective.com/writersperhour/5787d4b/logo.png" alt="Writers Per Hour" height="32"></a> <a href="https://www.betacalendars.com/printable-calendar"><img src="https://images.opencollective.com/betacalendars/9334b33/logo.png" alt="2021 calendar" height="32"></a> <a href="https://buy.fineproxy.org/eng/"><img src="https://images.opencollective.com/buy-fineproxy-org/b282e39/logo.png" alt="Buy.Fineproxy.Org" height="32"></a> <a href="https://www.veikkaajat.com"><img src="https://images.opencollective.com/veikkaajat/3777f94/logo.png" alt="Veikkaajat.com" 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="null"><img src="https://images.opencollective.com/bugsnag-stability-monitoring/c2cef36/logo.png" alt="Bugsnag Stability Monitoring" height="32"></a> <a href="https://mixpanel.com"><img src="https://images.opencollective.com/mixpanel/cd682f7/logo.png" alt="Mixpanel" height="32"></a> <a href="https://www.vpsserver.com"><img src="https://images.opencollective.com/vpsservercom/logo.png" alt="VPS Server" height="32"></a> <a href="https://icons8.com"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8: free icons, photos, illustrations, and music" height="32"></a> <a href="https://discordapp.com"><img src="https://images.opencollective.com/discordapp/7e3d9a9/logo.png" alt="Discord" height="32"></a> <a href="https://themeisle.com"><img src="https://images.opencollective.com/themeisle/d5592fe/logo.png" alt="ThemeIsle" height="32"></a> <a href="https://www.firesticktricks.com"><img src="https://images.opencollective.com/fire-stick-tricks/b8fbe2c/logo.png" alt="Fire Stick Tricks" height="32"></a></p>
271
266
  <!--sponsorsend-->
272
267
 
273
268
  ## <a name="technology-sponsors"></a>Technology Sponsors
package/bin/eslint.js CHANGED
@@ -14,7 +14,7 @@ require("v8-compile-cache");
14
14
 
15
15
  // must do this initialization *before* other requires in order to work
16
16
  if (process.argv.includes("--debug")) {
17
- require("debug").enable("eslint:*,-eslint:code-path");
17
+ require("debug").enable("eslint:*,-eslint:code-path,eslintrc:*");
18
18
  }
19
19
 
20
20
  //------------------------------------------------------------------------------
@@ -44,6 +44,26 @@ const enabled = !!process.env.TIMING;
44
44
  const HEADERS = ["Rule", "Time (ms)", "Relative"];
45
45
  const ALIGN = [alignLeft, alignRight, alignRight];
46
46
 
47
+ /**
48
+ * Decide how many rules to show in the output list.
49
+ * @returns {number} the number of rules to show
50
+ */
51
+ function getListSize() {
52
+ const MINIMUM_SIZE = 10;
53
+
54
+ if (typeof process.env.TIMING !== "string") {
55
+ return MINIMUM_SIZE;
56
+ }
57
+
58
+ if (process.env.TIMING.toLowerCase() === "all") {
59
+ return Number.POSITIVE_INFINITY;
60
+ }
61
+
62
+ const TIMING_ENV_VAR_AS_INTEGER = Number.parseInt(process.env.TIMING, 10);
63
+
64
+ return TIMING_ENV_VAR_AS_INTEGER > 10 ? TIMING_ENV_VAR_AS_INTEGER : MINIMUM_SIZE;
65
+ }
66
+
47
67
  /* istanbul ignore next */
48
68
  /**
49
69
  * display the data
@@ -61,7 +81,7 @@ function display(data) {
61
81
  return [key, time];
62
82
  })
63
83
  .sort((a, b) => b[1] - a[1])
64
- .slice(0, 10);
84
+ .slice(0, getListSize());
65
85
 
66
86
  rows.forEach(row => {
67
87
  row.push(`${(row[1] * 100 / total).toFixed(1)}%`);
@@ -133,7 +153,8 @@ module.exports = (function() {
133
153
 
134
154
  return {
135
155
  time,
136
- enabled
156
+ enabled,
157
+ getListSize
137
158
  };
138
159
 
139
160
  }());
@@ -169,6 +169,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
169
169
  "no-new-require": () => require("./no-new-require"),
170
170
  "no-new-symbol": () => require("./no-new-symbol"),
171
171
  "no-new-wrappers": () => require("./no-new-wrappers"),
172
+ "no-nonoctal-decimal-escape": () => require("./no-nonoctal-decimal-escape"),
172
173
  "no-obj-calls": () => require("./no-obj-calls"),
173
174
  "no-octal": () => require("./no-octal"),
174
175
  "no-octal-escape": () => require("./no-octal-escape"),
@@ -217,6 +218,7 @@ module.exports = new LazyLoadingRuleMap(Object.entries({
217
218
  "no-unreachable-loop": () => require("./no-unreachable-loop"),
218
219
  "no-unsafe-finally": () => require("./no-unsafe-finally"),
219
220
  "no-unsafe-negation": () => require("./no-unsafe-negation"),
221
+ "no-unsafe-optional-chaining": () => require("./no-unsafe-optional-chaining"),
220
222
  "no-unused-expressions": () => require("./no-unused-expressions"),
221
223
  "no-unused-labels": () => require("./no-unused-labels"),
222
224
  "no-unused-vars": () => require("./no-unused-vars"),
@@ -147,12 +147,18 @@ module.exports = {
147
147
  }
148
148
 
149
149
  case "UnaryExpression":
150
- if (node.operator === "void") {
150
+ if (
151
+ node.operator === "void" ||
152
+ node.operator === "typeof" && inBooleanPosition
153
+ ) {
151
154
  return true;
152
155
  }
153
156
 
154
- return (node.operator === "typeof" && inBooleanPosition) ||
155
- isConstant(node.argument, true);
157
+ if (node.operator === "!") {
158
+ return isConstant(node.argument, true);
159
+ }
160
+
161
+ return isConstant(node.argument, false);
156
162
 
157
163
  case "BinaryExpression":
158
164
  return isConstant(node.left, false) &&
@@ -472,20 +472,34 @@ module.exports = {
472
472
  const callee = node.callee;
473
473
 
474
474
  if (hasExcessParensWithPrecedence(callee, precedence(node))) {
475
- const hasNewParensException = callee.type === "NewExpression" && !isNewExpressionWithParens(callee);
476
-
477
475
  if (
478
476
  hasDoubleExcessParens(callee) ||
479
- !isIIFE(node) &&
480
- !hasNewParensException &&
481
477
  !(
482
-
483
- // Allow extra parens around a new expression if they are intervening parentheses.
484
- node.type === "NewExpression" &&
485
- callee.type === "MemberExpression" &&
486
- doesMemberExpressionContainCallExpression(callee)
487
- ) &&
488
- !(!node.optional && callee.type === "ChainExpression")
478
+ isIIFE(node) ||
479
+
480
+ // (new A)(); new (new A)();
481
+ (
482
+ callee.type === "NewExpression" &&
483
+ !isNewExpressionWithParens(callee) &&
484
+ !(
485
+ node.type === "NewExpression" &&
486
+ !isNewExpressionWithParens(node)
487
+ )
488
+ ) ||
489
+
490
+ // new (a().b)(); new (a.b().c);
491
+ (
492
+ node.type === "NewExpression" &&
493
+ callee.type === "MemberExpression" &&
494
+ doesMemberExpressionContainCallExpression(callee)
495
+ ) ||
496
+
497
+ // (a?.b)(); (a?.())();
498
+ (
499
+ !node.optional &&
500
+ callee.type === "ChainExpression"
501
+ )
502
+ )
489
503
  ) {
490
504
  report(node.callee);
491
505
  }
@@ -511,7 +525,7 @@ module.exports = {
511
525
 
512
526
  if (!shouldSkipLeft && hasExcessParens(node.left)) {
513
527
  if (
514
- !(node.left.type === "UnaryExpression" && isExponentiation) &&
528
+ !(["AwaitExpression", "UnaryExpression"].includes(node.left.type) && isExponentiation) &&
515
529
  !astUtils.isMixedLogicalAndCoalesceExpressions(node.left, node) &&
516
530
  (leftPrecedence > prec || (leftPrecedence === prec && !isExponentiation)) ||
517
531
  isParenthesisedTwice(node.left)
@@ -82,7 +82,7 @@ module.exports = {
82
82
  const commentNodes = sourceCode.getAllComments();
83
83
 
84
84
  /**
85
- * Removes errors that occur inside a string node
85
+ * Removes errors that occur inside the given node
86
86
  * @param {ASTNode} node to check for matching errors.
87
87
  * @returns {void}
88
88
  * @private
@@ -91,14 +91,12 @@ module.exports = {
91
91
  const locStart = node.loc.start;
92
92
  const locEnd = node.loc.end;
93
93
 
94
- errors = errors.filter(({ loc: { start: errorLoc } }) => {
95
- if (errorLoc.line >= locStart.line && errorLoc.line <= locEnd.line) {
96
- if (errorLoc.column >= locStart.column && (errorLoc.column <= locEnd.column || errorLoc.line < locEnd.line)) {
97
- return false;
98
- }
99
- }
100
- return true;
101
- });
94
+ errors = errors.filter(({ loc: { start: errorLocStart } }) => (
95
+ errorLocStart.line < locStart.line ||
96
+ errorLocStart.line === locStart.line && errorLocStart.column < locStart.column ||
97
+ errorLocStart.line === locEnd.line && errorLocStart.column >= locEnd.column ||
98
+ errorLocStart.line > locEnd.line
99
+ ));
102
100
  }
103
101
 
104
102
  /**
@@ -0,0 +1,147 @@
1
+ /**
2
+ * @fileoverview Rule to disallow `\8` and `\9` escape sequences in string literals.
3
+ * @author Milos Djermanovic
4
+ */
5
+
6
+ "use strict";
7
+
8
+ //------------------------------------------------------------------------------
9
+ // Helpers
10
+ //------------------------------------------------------------------------------
11
+
12
+ const QUICK_TEST_REGEX = /\\[89]/u;
13
+
14
+ /**
15
+ * Returns unicode escape sequence that represents the given character.
16
+ * @param {string} character A single code unit.
17
+ * @returns {string} "\uXXXX" sequence.
18
+ */
19
+ function getUnicodeEscape(character) {
20
+ return `\\u${character.charCodeAt(0).toString(16).padStart(4, "0")}`;
21
+ }
22
+
23
+ //------------------------------------------------------------------------------
24
+ // Rule Definition
25
+ //------------------------------------------------------------------------------
26
+
27
+ module.exports = {
28
+ meta: {
29
+ type: "suggestion",
30
+
31
+ docs: {
32
+ description: "disallow `\\8` and `\\9` escape sequences in string literals",
33
+ category: "Best Practices",
34
+ recommended: false,
35
+ url: "https://eslint.org/docs/rules/no-nonoctal-decimal-escape",
36
+ suggestion: true
37
+ },
38
+
39
+ schema: [],
40
+
41
+ messages: {
42
+ decimalEscape: "Don't use '{{decimalEscape}}' escape sequence.",
43
+
44
+ // suggestions
45
+ refactor: "Replace '{{original}}' with '{{replacement}}'. This maintains the current functionality.",
46
+ escapeBackslash: "Replace '{{original}}' with '{{replacement}}' to include the actual backslash character."
47
+ }
48
+ },
49
+
50
+ create(context) {
51
+ const sourceCode = context.getSourceCode();
52
+
53
+ /**
54
+ * Creates a new Suggestion object.
55
+ * @param {string} messageId "refactor" or "escapeBackslash".
56
+ * @param {int[]} range The range to replace.
57
+ * @param {string} replacement New text for the range.
58
+ * @returns {Object} Suggestion
59
+ */
60
+ function createSuggestion(messageId, range, replacement) {
61
+ return {
62
+ messageId,
63
+ data: {
64
+ original: sourceCode.getText().slice(...range),
65
+ replacement
66
+ },
67
+ fix(fixer) {
68
+ return fixer.replaceTextRange(range, replacement);
69
+ }
70
+ };
71
+ }
72
+
73
+ return {
74
+ Literal(node) {
75
+ if (typeof node.value !== "string") {
76
+ return;
77
+ }
78
+
79
+ if (!QUICK_TEST_REGEX.test(node.raw)) {
80
+ return;
81
+ }
82
+
83
+ const regex = /(?:[^\\]|(?<previousEscape>\\.))*?(?<decimalEscape>\\[89])/suy;
84
+ let match;
85
+
86
+ while ((match = regex.exec(node.raw))) {
87
+ const { previousEscape, decimalEscape } = match.groups;
88
+ const decimalEscapeRangeEnd = node.range[0] + match.index + match[0].length;
89
+ const decimalEscapeRangeStart = decimalEscapeRangeEnd - decimalEscape.length;
90
+ const decimalEscapeRange = [decimalEscapeRangeStart, decimalEscapeRangeEnd];
91
+ const suggest = [];
92
+
93
+ // When `regex` is matched, `previousEscape` can only capture characters adjacent to `decimalEscape`
94
+ if (previousEscape === "\\0") {
95
+
96
+ /*
97
+ * Now we have a NULL escape "\0" immediately followed by a decimal escape, e.g.: "\0\8".
98
+ * Fixing this to "\08" would turn "\0" into a legacy octal escape. To avoid producing
99
+ * an octal escape while fixing a decimal escape, we provide different suggestions.
100
+ */
101
+ suggest.push(
102
+ createSuggestion( // "\0\8" -> "\u00008"
103
+ "refactor",
104
+ [decimalEscapeRangeStart - previousEscape.length, decimalEscapeRangeEnd],
105
+ `${getUnicodeEscape("\0")}${decimalEscape[1]}`
106
+ ),
107
+ createSuggestion( // "\8" -> "\u0038"
108
+ "refactor",
109
+ decimalEscapeRange,
110
+ getUnicodeEscape(decimalEscape[1])
111
+ )
112
+ );
113
+ } else {
114
+ suggest.push(
115
+ createSuggestion( // "\8" -> "8"
116
+ "refactor",
117
+ decimalEscapeRange,
118
+ decimalEscape[1]
119
+ )
120
+ );
121
+ }
122
+
123
+ suggest.push(
124
+ createSuggestion( // "\8" -> "\\8"
125
+ "escapeBackslash",
126
+ decimalEscapeRange,
127
+ `\\${decimalEscape}`
128
+ )
129
+ );
130
+
131
+ context.report({
132
+ node,
133
+ loc: {
134
+ start: sourceCode.getLocFromIndex(decimalEscapeRangeStart),
135
+ end: sourceCode.getLocFromIndex(decimalEscapeRangeEnd)
136
+ },
137
+ messageId: "decimalEscape",
138
+ data: {
139
+ decimalEscape
140
+ },
141
+ suggest
142
+ });
143
+ }
144
+ }
145
+ };
146
+ }
147
+ };
@@ -0,0 +1,205 @@
1
+ /**
2
+ * @fileoverview Rule to disallow unsafe optional chaining
3
+ * @author Yeon JuAn
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const UNSAFE_ARITHMETIC_OPERATORS = new Set(["+", "-", "/", "*", "%", "**"]);
9
+ const UNSAFE_ASSIGNMENT_OPERATORS = new Set(["+=", "-=", "/=", "*=", "%=", "**="]);
10
+ const UNSAFE_RELATIONAL_OPERATORS = new Set(["in", "instanceof"]);
11
+
12
+ /**
13
+ * Checks whether a node is a destructuring pattern or not
14
+ * @param {ASTNode} node node to check
15
+ * @returns {boolean} `true` if a node is a destructuring pattern, otherwise `false`
16
+ */
17
+ function isDestructuringPattern(node) {
18
+ return node.type === "ObjectPattern" || node.type === "ArrayPattern";
19
+ }
20
+
21
+ module.exports = {
22
+ meta: {
23
+ type: "problem",
24
+
25
+ docs: {
26
+ description: "disallow use of optional chaining in contexts where the `undefined` value is not allowed",
27
+ category: "Possible Errors",
28
+ recommended: false,
29
+ url: "https://eslint.org/docs/rules/no-unsafe-optional-chaining"
30
+ },
31
+ schema: [{
32
+ type: "object",
33
+ properties: {
34
+ disallowArithmeticOperators: {
35
+ type: "boolean",
36
+ default: false
37
+ }
38
+ },
39
+ additionalProperties: false
40
+ }],
41
+ fixable: null,
42
+ messages: {
43
+ unsafeOptionalChain: "Unsafe usage of optional chaining. If it short-circuits with 'undefined' the evaluation will throw TypeError.",
44
+ unsafeArithmetic: "Unsafe arithmetic operation on optional chaining. It can result in NaN."
45
+ }
46
+ },
47
+
48
+ create(context) {
49
+ const options = context.options[0] || {};
50
+ const disallowArithmeticOperators = (options.disallowArithmeticOperators) || false;
51
+
52
+ /**
53
+ * Reports unsafe usage of optional chaining
54
+ * @param {ASTNode} node node to report
55
+ * @returns {void}
56
+ */
57
+ function reportUnsafeUsage(node) {
58
+ context.report({
59
+ messageId: "unsafeOptionalChain",
60
+ node
61
+ });
62
+ }
63
+
64
+ /**
65
+ * Reports unsafe arithmetic operation on optional chaining
66
+ * @param {ASTNode} node node to report
67
+ * @returns {void}
68
+ */
69
+ function reportUnsafeArithmetic(node) {
70
+ context.report({
71
+ messageId: "unsafeArithmetic",
72
+ node
73
+ });
74
+ }
75
+
76
+ /**
77
+ * Checks and reports if a node can short-circuit with `undefined` by optional chaining.
78
+ * @param {ASTNode} [node] node to check
79
+ * @param {Function} reportFunc report function
80
+ * @returns {void}
81
+ */
82
+ function checkUndefinedShortCircuit(node, reportFunc) {
83
+ if (!node) {
84
+ return;
85
+ }
86
+ switch (node.type) {
87
+ case "LogicalExpression":
88
+ if (node.operator === "||" || node.operator === "??") {
89
+ checkUndefinedShortCircuit(node.right, reportFunc);
90
+ } else if (node.operator === "&&") {
91
+ checkUndefinedShortCircuit(node.left, reportFunc);
92
+ checkUndefinedShortCircuit(node.right, reportFunc);
93
+ }
94
+ break;
95
+ case "SequenceExpression":
96
+ checkUndefinedShortCircuit(
97
+ node.expressions[node.expressions.length - 1],
98
+ reportFunc
99
+ );
100
+ break;
101
+ case "ConditionalExpression":
102
+ checkUndefinedShortCircuit(node.consequent, reportFunc);
103
+ checkUndefinedShortCircuit(node.alternate, reportFunc);
104
+ break;
105
+ case "AwaitExpression":
106
+ checkUndefinedShortCircuit(node.argument, reportFunc);
107
+ break;
108
+ case "ChainExpression":
109
+ reportFunc(node);
110
+ break;
111
+ default:
112
+ break;
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Checks unsafe usage of optional chaining
118
+ * @param {ASTNode} node node to check
119
+ * @returns {void}
120
+ */
121
+ function checkUnsafeUsage(node) {
122
+ checkUndefinedShortCircuit(node, reportUnsafeUsage);
123
+ }
124
+
125
+ /**
126
+ * Checks unsafe arithmetic operations on optional chaining
127
+ * @param {ASTNode} node node to check
128
+ * @returns {void}
129
+ */
130
+ function checkUnsafeArithmetic(node) {
131
+ checkUndefinedShortCircuit(node, reportUnsafeArithmetic);
132
+ }
133
+
134
+ return {
135
+ "AssignmentExpression, AssignmentPattern"(node) {
136
+ if (isDestructuringPattern(node.left)) {
137
+ checkUnsafeUsage(node.right);
138
+ }
139
+ },
140
+ "ClassDeclaration, ClassExpression"(node) {
141
+ checkUnsafeUsage(node.superClass);
142
+ },
143
+ CallExpression(node) {
144
+ if (!node.optional) {
145
+ checkUnsafeUsage(node.callee);
146
+ }
147
+ },
148
+ NewExpression(node) {
149
+ checkUnsafeUsage(node.callee);
150
+ },
151
+ VariableDeclarator(node) {
152
+ if (isDestructuringPattern(node.id)) {
153
+ checkUnsafeUsage(node.init);
154
+ }
155
+ },
156
+ MemberExpression(node) {
157
+ if (!node.optional) {
158
+ checkUnsafeUsage(node.object);
159
+ }
160
+ },
161
+ TaggedTemplateExpression(node) {
162
+ checkUnsafeUsage(node.tag);
163
+ },
164
+ ForOfStatement(node) {
165
+ checkUnsafeUsage(node.right);
166
+ },
167
+ SpreadElement(node) {
168
+ if (node.parent && node.parent.type !== "ObjectExpression") {
169
+ checkUnsafeUsage(node.argument);
170
+ }
171
+ },
172
+ BinaryExpression(node) {
173
+ if (UNSAFE_RELATIONAL_OPERATORS.has(node.operator)) {
174
+ checkUnsafeUsage(node.right);
175
+ }
176
+ if (
177
+ disallowArithmeticOperators &&
178
+ UNSAFE_ARITHMETIC_OPERATORS.has(node.operator)
179
+ ) {
180
+ checkUnsafeArithmetic(node.right);
181
+ checkUnsafeArithmetic(node.left);
182
+ }
183
+ },
184
+ WithStatement(node) {
185
+ checkUnsafeUsage(node.object);
186
+ },
187
+ UnaryExpression(node) {
188
+ if (
189
+ disallowArithmeticOperators &&
190
+ UNSAFE_ARITHMETIC_OPERATORS.has(node.operator)
191
+ ) {
192
+ checkUnsafeArithmetic(node.argument);
193
+ }
194
+ },
195
+ AssignmentExpression(node) {
196
+ if (
197
+ disallowArithmeticOperators &&
198
+ UNSAFE_ASSIGNMENT_OPERATORS.has(node.operator)
199
+ ) {
200
+ checkUnsafeArithmetic(node.right);
201
+ }
202
+ }
203
+ };
204
+ }
205
+ };
@@ -162,6 +162,14 @@ module.exports = {
162
162
  return;
163
163
  }
164
164
 
165
+ /*
166
+ * Prevent crashing on parsers which do not require class constructor
167
+ * to have a body, e.g. typescript and flow
168
+ */
169
+ if (!node.value.body) {
170
+ return;
171
+ }
172
+
165
173
  const body = node.value.body.body;
166
174
  const ctorParams = node.value.params;
167
175
  const superClass = node.parent.parent.superClass;
@@ -314,12 +314,14 @@ module.exports = {
314
314
  return null;
315
315
  }
316
316
 
317
+ const exportPlacement = declaration.parent.type === "ExportNamedDeclaration" ? "export " : "";
318
+
317
319
  /*
318
320
  * `var x,y`
319
321
  * tokenAfterDeclarator ^^ afterComma
320
322
  */
321
323
  if (afterComma.range[0] === tokenAfterDeclarator.range[1]) {
322
- return fixer.replaceText(tokenAfterDeclarator, `; ${declaration.kind} `);
324
+ return fixer.replaceText(tokenAfterDeclarator, `; ${exportPlacement}${declaration.kind} `);
323
325
  }
324
326
 
325
327
  /*
@@ -341,11 +343,11 @@ module.exports = {
341
343
 
342
344
  return fixer.replaceTextRange(
343
345
  [tokenAfterDeclarator.range[0], lastComment.range[0]],
344
- `;${sourceCode.text.slice(tokenAfterDeclarator.range[1], lastComment.range[0])}${declaration.kind} `
346
+ `;${sourceCode.text.slice(tokenAfterDeclarator.range[1], lastComment.range[0])}${exportPlacement}${declaration.kind} `
345
347
  );
346
348
  }
347
349
 
348
- return fixer.replaceText(tokenAfterDeclarator, `; ${declaration.kind}`);
350
+ return fixer.replaceText(tokenAfterDeclarator, `; ${exportPlacement}${declaration.kind}`);
349
351
  }).filter(x => x);
350
352
  }
351
353
 
@@ -30,6 +30,7 @@ function doesBaseNeedParens(base) {
30
30
  astUtils.getPrecedence(base) <= PRECEDENCE_OF_EXPONENTIATION_EXPR ||
31
31
 
32
32
  // An unary operator cannot be used immediately before an exponentiation expression
33
+ base.type === "AwaitExpression" ||
33
34
  base.type === "UnaryExpression"
34
35
  );
35
36
  }
@@ -113,6 +113,9 @@ class SegmentInfo {
113
113
 
114
114
  if (info) {
115
115
  info.freshReadVariableNames.add(variableName);
116
+
117
+ // If a variable is freshly read again, then it's no more out-dated.
118
+ info.outdatedReadVariableNames.delete(variableName);
116
119
  }
117
120
  }
118
121
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "7.12.1",
3
+ "version": "7.16.0",
4
4
  "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
5
5
  "description": "An AST-based pattern checker for JavaScript.",
6
6
  "bin": {
@@ -47,7 +47,7 @@
47
47
  "bugs": "https://github.com/eslint/eslint/issues/",
48
48
  "dependencies": {
49
49
  "@babel/code-frame": "^7.0.0",
50
- "@eslint/eslintrc": "^0.2.1",
50
+ "@eslint/eslintrc": "^0.2.2",
51
51
  "ajv": "^6.10.0",
52
52
  "chalk": "^4.0.0",
53
53
  "cross-spawn": "^7.0.2",
@@ -57,10 +57,10 @@
57
57
  "eslint-scope": "^5.1.1",
58
58
  "eslint-utils": "^2.1.0",
59
59
  "eslint-visitor-keys": "^2.0.0",
60
- "espree": "^7.3.0",
60
+ "espree": "^7.3.1",
61
61
  "esquery": "^1.2.0",
62
62
  "esutils": "^2.0.2",
63
- "file-entry-cache": "^5.0.1",
63
+ "file-entry-cache": "^6.0.0",
64
64
  "functional-red-black-tree": "^1.0.1",
65
65
  "glob-parent": "^5.0.0",
66
66
  "globals": "^12.1.0",
@@ -80,7 +80,7 @@
80
80
  "semver": "^7.2.1",
81
81
  "strip-ansi": "^6.0.0",
82
82
  "strip-json-comments": "^3.1.0",
83
- "table": "^5.2.3",
83
+ "table": "^6.0.4",
84
84
  "text-table": "^0.2.0",
85
85
  "v8-compile-cache": "^2.0.3"
86
86
  },