eslint 8.5.0 → 8.9.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.
@@ -977,10 +977,10 @@ class RuleTester {
977
977
  * This creates a mocha test suite and pipes all supplied info through
978
978
  * one of the templates above.
979
979
  */
980
- RuleTester.describe(ruleName, () => {
981
- RuleTester.describe("valid", () => {
980
+ this.constructor.describe(ruleName, () => {
981
+ this.constructor.describe("valid", () => {
982
982
  test.valid.forEach(valid => {
983
- RuleTester[valid.only ? "itOnly" : "it"](
983
+ this.constructor[valid.only ? "itOnly" : "it"](
984
984
  sanitize(typeof valid === "object" ? valid.name || valid.code : valid),
985
985
  () => {
986
986
  testValidTemplate(valid);
@@ -989,9 +989,9 @@ class RuleTester {
989
989
  });
990
990
  });
991
991
 
992
- RuleTester.describe("invalid", () => {
992
+ this.constructor.describe("invalid", () => {
993
993
  test.invalid.forEach(invalid => {
994
- RuleTester[invalid.only ? "itOnly" : "it"](
994
+ this.constructor[invalid.only ? "itOnly" : "it"](
995
995
  sanitize(invalid.name || invalid.code),
996
996
  () => {
997
997
  testInvalidTemplate(invalid);
@@ -5,6 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("./utils/ast-utils");
13
+
8
14
  //------------------------------------------------------------------------------
9
15
  // Rule Definition
10
16
  //------------------------------------------------------------------------------
@@ -165,7 +171,7 @@ module.exports = {
165
171
  case "ImportSpecifier":
166
172
  return (
167
173
  parent.local === node &&
168
- parent.imported.name === localName
174
+ astUtils.getModuleExportName(parent.imported) === localName
169
175
  );
170
176
 
171
177
  default:
@@ -227,9 +227,13 @@ module.exports = {
227
227
  return null;
228
228
  }
229
229
 
230
+ const rightParen = node.params.length
231
+ ? sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isClosingParenToken)
232
+ : sourceCode.getTokenAfter(firstToken);
233
+
230
234
  return {
231
235
  leftParen: firstToken,
232
- rightParen: sourceCode.getTokenBefore(node.body, astUtils.isClosingParenToken)
236
+ rightParen
233
237
  };
234
238
  }
235
239
 
@@ -211,6 +211,17 @@ module.exports = {
211
211
  }
212
212
  }
213
213
 
214
+ // For https://github.com/eslint/eslint/issues/15123
215
+ } else if (
216
+ parent.type === "Property" &&
217
+ parent.parent.type === "ObjectExpression" &&
218
+ parent.key === node &&
219
+ !parent.computed
220
+ ) {
221
+ if (checkProperties && isInvalid(name)) {
222
+ report(node);
223
+ }
224
+
214
225
  /*
215
226
  * Properties have their own rules, and
216
227
  * AssignmentPattern nodes can be treated like Properties:
@@ -239,7 +250,7 @@ module.exports = {
239
250
  }
240
251
 
241
252
  // never check properties or always ignore destructuring
242
- if (!checkProperties || (ignoreDestructuring && isInsideObjectPattern(node))) {
253
+ if ((!checkProperties && !parent.computed) || (ignoreDestructuring && isInsideObjectPattern(node))) {
243
254
  return;
244
255
  }
245
256
 
@@ -469,6 +469,7 @@ module.exports = {
469
469
  const asToken = sourceCode.getTokenBefore(node.exported);
470
470
 
471
471
  checkSpacingBefore(asToken, PREV_TOKEN_M);
472
+ checkSpacingAfter(asToken, NEXT_TOKEN_M);
472
473
  }
473
474
 
474
475
  if (node.source) {
@@ -479,6 +480,35 @@ module.exports = {
479
480
  }
480
481
  }
481
482
 
483
+ /**
484
+ * Reports `as` keyword of a given node if usage of spacing around this
485
+ * keyword is invalid.
486
+ * @param {ASTNode} node An `ImportSpecifier` node to check.
487
+ * @returns {void}
488
+ */
489
+ function checkSpacingForImportSpecifier(node) {
490
+ if (node.imported.range[0] !== node.local.range[0]) {
491
+ const asToken = sourceCode.getTokenBefore(node.local);
492
+
493
+ checkSpacingBefore(asToken, PREV_TOKEN_M);
494
+ }
495
+ }
496
+
497
+ /**
498
+ * Reports `as` keyword of a given node if usage of spacing around this
499
+ * keyword is invalid.
500
+ * @param {ASTNode} node An `ExportSpecifier` node to check.
501
+ * @returns {void}
502
+ */
503
+ function checkSpacingForExportSpecifier(node) {
504
+ if (node.local.range[0] !== node.exported.range[0]) {
505
+ const asToken = sourceCode.getTokenBefore(node.exported);
506
+
507
+ checkSpacingBefore(asToken, PREV_TOKEN_M);
508
+ checkSpacingAfter(asToken, NEXT_TOKEN_M);
509
+ }
510
+ }
511
+
482
512
  /**
483
513
  * Reports `as` keyword of a given node if usage of spacing around this
484
514
  * keyword is invalid.
@@ -588,6 +618,8 @@ module.exports = {
588
618
  YieldExpression: checkSpacingBeforeFirstToken,
589
619
 
590
620
  // Others
621
+ ImportSpecifier: checkSpacingForImportSpecifier,
622
+ ExportSpecifier: checkSpacingForExportSpecifier,
591
623
  ImportNamespaceSpecifier: checkSpacingForImportNamespaceSpecifier,
592
624
  MethodDefinition: checkSpacingForProperty,
593
625
  PropertyDefinition: checkSpacingForProperty,
@@ -124,7 +124,8 @@ module.exports = {
124
124
  * Checks if a node has a constant truthiness value.
125
125
  * @param {ASTNode} node The AST node to check.
126
126
  * @param {boolean} inBooleanPosition `false` if checking branch of a condition.
127
- * `true` in all other cases
127
+ * `true` in all other cases. When `false`, checks if -- for both string and
128
+ * number -- if coerced to that type, the value will be constant.
128
129
  * @returns {Bool} true when node's truthiness is constant
129
130
  * @private
130
131
  */
@@ -138,15 +139,31 @@ module.exports = {
138
139
  case "Literal":
139
140
  case "ArrowFunctionExpression":
140
141
  case "FunctionExpression":
141
- case "ObjectExpression":
142
+ return true;
142
143
  case "ClassExpression":
144
+ case "ObjectExpression":
145
+
146
+ /**
147
+ * In theory objects like:
148
+ *
149
+ * `{toString: () => a}`
150
+ * `{valueOf: () => a}`
151
+ *
152
+ * Or a classes like:
153
+ *
154
+ * `class { static toString() { return a } }`
155
+ * `class { static valueOf() { return a } }`
156
+ *
157
+ * Are not constant verifiably when `inBooleanPosition` is
158
+ * false, but it's an edge case we've opted not to handle.
159
+ */
143
160
  return true;
144
161
  case "TemplateLiteral":
145
162
  return (inBooleanPosition && node.quasis.some(quasi => quasi.value.cooked.length)) ||
146
- node.expressions.every(exp => isConstant(exp, inBooleanPosition));
163
+ node.expressions.every(exp => isConstant(exp, false));
147
164
 
148
165
  case "ArrayExpression": {
149
- if (node.parent.type === "BinaryExpression" && node.parent.operator === "+") {
166
+ if (!inBooleanPosition) {
150
167
  return node.elements.every(element => isConstant(element, false));
151
168
  }
152
169
  return true;
@@ -196,6 +213,8 @@ module.exports = {
196
213
 
197
214
  case "SequenceExpression":
198
215
  return isConstant(node.expressions[node.expressions.length - 1], inBooleanPosition);
216
+ case "SpreadElement":
217
+ return isConstant(node.argument, inBooleanPosition);
199
218
 
200
219
  // no default
201
220
  }
@@ -11,6 +11,21 @@
11
11
 
12
12
  const astUtils = require("./utils/ast-utils");
13
13
 
14
+ //------------------------------------------------------------------------------
15
+ // Helpers
16
+ //------------------------------------------------------------------------------
17
+
18
+ /**
19
+ * Determines if the given code path is a code path with lexical `this` binding.
20
+ * That is, if `this` within the code path refers to `this` of surrounding code path.
21
+ * @param {CodePath} codePath Code path.
22
+ * @param {ASTNode} node Node that started the code path.
23
+ * @returns {boolean} `true` if it is a code path with lexical `this` binding.
24
+ */
25
+ function isCodePathWithLexicalThis(codePath, node) {
26
+ return codePath.origin === "function" && node.type === "ArrowFunctionExpression";
27
+ }
28
+
14
29
  //------------------------------------------------------------------------------
15
30
  // Rule Definition
16
31
  //------------------------------------------------------------------------------
@@ -72,71 +87,53 @@ module.exports = {
72
87
  return current;
73
88
  };
74
89
 
75
- /**
76
- * Pushs new checking context into the stack.
77
- *
78
- * The checking context is not initialized yet.
79
- * Because most functions don't have `this` keyword.
80
- * When `this` keyword was found, the checking context is initialized.
81
- * @param {ASTNode} node A function node that was entered.
82
- * @returns {void}
83
- */
84
- function enterFunction(node) {
85
-
86
- // `this` can be invalid only under strict mode.
87
- stack.push({
88
- init: !context.getScope().isStrict,
89
- node,
90
- valid: true
91
- });
92
- }
90
+ return {
93
91
 
94
- /**
95
- * Pops the current checking context from the stack.
96
- * @returns {void}
97
- */
98
- function exitFunction() {
99
- stack.pop();
100
- }
92
+ onCodePathStart(codePath, node) {
93
+ if (isCodePathWithLexicalThis(codePath, node)) {
94
+ return;
95
+ }
101
96
 
102
- return {
97
+ if (codePath.origin === "program") {
98
+ const scope = context.getScope();
99
+ const features = context.parserOptions.ecmaFeatures || {};
100
+
101
+ stack.push({
102
+ init: true,
103
+ node,
104
+ valid: !(
105
+ scope.isStrict ||
106
+ node.sourceType === "module" ||
107
+ (features.globalReturn && scope.childScopes[0].isStrict)
108
+ )
109
+ });
103
110
 
104
- /*
105
- * `this` is invalid only under strict mode.
106
- * Modules is always strict mode.
107
- */
108
- Program(node) {
109
- const scope = context.getScope(),
110
- features = context.parserOptions.ecmaFeatures || {};
111
+ return;
112
+ }
111
113
 
114
+ /*
115
+ * `init: false` means that `valid` isn't determined yet.
116
+ * Most functions don't use `this`, and the calculation for `valid`
117
+ * is relatively costly, so we'll calculate it lazily when the first
118
+ * `this` within the function is traversed. A special case are non-strict
119
+ * functions, because `this` refers to the global object and therefore is
120
+ * always valid, so we can set `init: true` right away.
121
+ */
112
122
  stack.push({
113
- init: true,
123
+ init: !context.getScope().isStrict,
114
124
  node,
115
- valid: !(
116
- scope.isStrict ||
117
- node.sourceType === "module" ||
118
- (features.globalReturn && scope.childScopes[0].isStrict)
119
- )
125
+ valid: true
120
126
  });
121
127
  },
122
128
 
123
- "Program:exit"() {
129
+ onCodePathEnd(codePath, node) {
130
+ if (isCodePathWithLexicalThis(codePath, node)) {
131
+ return;
132
+ }
133
+
124
134
  stack.pop();
125
135
  },
126
136
 
127
- FunctionDeclaration: enterFunction,
128
- "FunctionDeclaration:exit": exitFunction,
129
- FunctionExpression: enterFunction,
130
- "FunctionExpression:exit": exitFunction,
131
-
132
- // Field initializers are implicit functions.
133
- "PropertyDefinition > *.value": enterFunction,
134
- "PropertyDefinition > *.value:exit": exitFunction,
135
-
136
- // Class static blocks are implicit functions.
137
- StaticBlock: enterFunction,
138
- "StaticBlock:exit": exitFunction,
139
-
140
137
  // Reports if `this` of the current context is invalid.
141
138
  ThisExpression(node) {
142
139
  const current = stack.getCurrent();
@@ -5,6 +5,12 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ //------------------------------------------------------------------------------
9
+ // Requirements
10
+ //------------------------------------------------------------------------------
11
+
12
+ const astUtils = require("./utils/ast-utils");
13
+
8
14
  //------------------------------------------------------------------------------
9
15
  // Rule Definition
10
16
  //------------------------------------------------------------------------------
@@ -44,12 +50,12 @@ module.exports = {
44
50
  const restrictedNames = new Set(context.options[0] && context.options[0].restrictedNamedExports);
45
51
 
46
52
  /**
47
- * Checks and reports given exported identifier.
48
- * @param {ASTNode} node exported `Identifier` node to check.
53
+ * Checks and reports given exported name.
54
+ * @param {ASTNode} node exported `Identifier` or string `Literal` node to check.
49
55
  * @returns {void}
50
56
  */
51
57
  function checkExportedName(node) {
52
- const name = node.name;
58
+ const name = astUtils.getModuleExportName(node);
53
59
 
54
60
  if (restrictedNames.has(name)) {
55
61
  context.report({
@@ -4,6 +4,12 @@
4
4
  */
5
5
  "use strict";
6
6
 
7
+ //------------------------------------------------------------------------------
8
+ // Requirements
9
+ //------------------------------------------------------------------------------
10
+
11
+ const astUtils = require("./utils/ast-utils");
12
+
7
13
  //------------------------------------------------------------------------------
8
14
  // Rule Definition
9
15
  //------------------------------------------------------------------------------
@@ -63,6 +69,9 @@ const arrayOfStringsOrObjectPatterns = {
63
69
  message: {
64
70
  type: "string",
65
71
  minLength: 1
72
+ },
73
+ caseSensitive: {
74
+ type: "boolean"
66
75
  }
67
76
  },
68
77
  additionalProperties: false,
@@ -142,10 +151,18 @@ module.exports = {
142
151
  }, {});
143
152
 
144
153
  // Handle patterns too, either as strings or groups
145
- const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
146
- const restrictedPatternGroups = restrictedPatterns.length > 0 && typeof restrictedPatterns[0] === "string"
147
- ? [{ matcher: ignore().add(restrictedPatterns) }]
148
- : restrictedPatterns.map(({ group, message }) => ({ matcher: ignore().add(group), customMessage: message }));
154
+ let restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
155
+
156
+ // standardize to array of objects if we have an array of strings
157
+ if (restrictedPatterns.length > 0 && typeof restrictedPatterns[0] === "string") {
158
+ restrictedPatterns = [{ group: restrictedPatterns }];
159
+ }
160
+
161
+ // relative paths are supported for this rule
162
+ const restrictedPatternGroups = restrictedPatterns.map(({ group, message, caseSensitive }) => ({
163
+ matcher: ignore({ allowRelativePaths: true, ignorecase: !caseSensitive }).add(group),
164
+ customMessage: message
165
+ }));
149
166
 
150
167
  // if no imports are restricted we don't need to check
151
168
  if (Object.keys(restrictedPaths).length === 0 && restrictedPatternGroups.length === 0) {
@@ -269,12 +286,12 @@ module.exports = {
269
286
  } else if (specifier.type === "ImportNamespaceSpecifier") {
270
287
  name = "*";
271
288
  } else if (specifier.imported) {
272
- name = specifier.imported.name;
289
+ name = astUtils.getModuleExportName(specifier.imported);
273
290
  } else if (specifier.local) {
274
- name = specifier.local.name;
291
+ name = astUtils.getModuleExportName(specifier.local);
275
292
  }
276
293
 
277
- if (name) {
294
+ if (typeof name === "string") {
278
295
  if (importNames.has(name)) {
279
296
  importNames.get(name).push(specifierData);
280
297
  } else {
@@ -103,7 +103,8 @@ module.exports = {
103
103
  return {};
104
104
  }
105
105
 
106
- const ig = ignore().add(restrictedPatterns);
106
+ // relative paths are supported for this rule
107
+ const ig = ignore({ allowRelativePaths: true }).add(restrictedPatterns);
107
108
 
108
109
 
109
110
  /**
@@ -174,7 +174,7 @@ module.exports = {
174
174
 
175
175
  return {
176
176
  AssignmentExpression(node) {
177
- if (node.operator === "=") {
177
+ if (["=", "&&=", "||=", "??="].includes(node.operator)) {
178
178
  eachSelfAssignment(node.left, node.right, props, report);
179
179
  }
180
180
  }
@@ -132,8 +132,10 @@ module.exports = {
132
132
  return;
133
133
  }
134
134
 
135
- if (node.imported.name === node.local.name &&
136
- node.imported.range[0] !== node.local.range[0]) {
135
+ if (
136
+ node.imported.range[0] !== node.local.range[0] &&
137
+ astUtils.getModuleExportName(node.imported) === node.local.name
138
+ ) {
137
139
  reportError(node, node.imported, "Import");
138
140
  }
139
141
  }
@@ -148,8 +150,10 @@ module.exports = {
148
150
  return;
149
151
  }
150
152
 
151
- if (node.local.name === node.exported.name &&
152
- node.local.range[0] !== node.exported.range[0]) {
153
+ if (
154
+ node.local.range[0] !== node.exported.range[0] &&
155
+ astUtils.getModuleExportName(node.local) === astUtils.getModuleExportName(node.exported)
156
+ ) {
153
157
  reportError(node, node.local, "Export");
154
158
  }
155
159
 
@@ -223,9 +223,20 @@ module.exports = {
223
223
  // ModuleSpecifier.
224
224
  case "ImportDeclaration":
225
225
  case "ExportNamedDeclaration":
226
- case "ExportAllDeclaration":
227
226
  return parent.source === node;
228
227
 
228
+ // ModuleExportName or ModuleSpecifier.
229
+ case "ExportAllDeclaration":
230
+ return parent.exported === node || parent.source === node;
231
+
232
+ // ModuleExportName.
233
+ case "ImportSpecifier":
234
+ return parent.imported === node;
235
+
236
+ // ModuleExportName.
237
+ case "ExportSpecifier":
238
+ return parent.local === node || parent.exported === node;
239
+
229
240
  // Others don't allow.
230
241
  default:
231
242
  return false;
@@ -769,6 +769,25 @@ function getSwitchCaseColonToken(node, sourceCode) {
769
769
  return sourceCode.getFirstToken(node, 1);
770
770
  }
771
771
 
772
+ /**
773
+ * Gets ESM module export name represented by the given node.
774
+ * @param {ASTNode} node `Identifier` or string `Literal` node in a position
775
+ * that represents a module export name:
776
+ * - `ImportSpecifier#imported`
777
+ * - `ExportSpecifier#local` (if it is a re-export from another module)
778
+ * - `ExportSpecifier#exported`
779
+ * - `ExportAllDeclaration#exported`
780
+ * @returns {string} The module export name.
781
+ */
782
+ function getModuleExportName(node) {
783
+ if (node.type === "Identifier") {
784
+ return node.name;
785
+ }
786
+
787
+ // string literal
788
+ return node.value;
789
+ }
790
+
772
791
  //------------------------------------------------------------------------------
773
792
  // Public Interface
774
793
  //------------------------------------------------------------------------------
@@ -1898,5 +1917,6 @@ module.exports = {
1898
1917
  equalLiteralValue,
1899
1918
  isSameReference,
1900
1919
  isLogicalAssignmentOperator,
1901
- getSwitchCaseColonToken
1920
+ getSwitchCaseColonToken,
1921
+ getModuleExportName
1902
1922
  };
@@ -105,6 +105,21 @@ module.exports = {};
105
105
  * @property {Array<{desc?: string, messageId?: string, fix: {range: [number, number], text: string}}>} [suggestions] Information for suggestions.
106
106
  */
107
107
 
108
+ /**
109
+ * @typedef {Object} SuppressedLintMessage
110
+ * @property {number|undefined} column The 1-based column number.
111
+ * @property {number} [endColumn] The 1-based column number of the end location.
112
+ * @property {number} [endLine] The 1-based line number of the end location.
113
+ * @property {boolean} fatal If `true` then this is a fatal error.
114
+ * @property {{range:[number,number], text:string}} [fix] Information for autofix.
115
+ * @property {number|undefined} line The 1-based line number.
116
+ * @property {string} message The error message.
117
+ * @property {string|null} ruleId The ID of the rule which makes this message.
118
+ * @property {0|1|2} severity The severity of this message.
119
+ * @property {Array<{kind: string, justification: string}>} suppressions The suppression info.
120
+ * @property {Array<{desc?: string, messageId?: string, fix: {range: [number, number], text: string}}>} [suggestions] Information for suggestions.
121
+ */
122
+
108
123
  /**
109
124
  * @typedef {Object} SuggestionResult
110
125
  * @property {string} desc A short description.
@@ -6,7 +6,7 @@ module.exports = function(it) {
6
6
  return `
7
7
  ESLint couldn't find a configuration file. To set up a configuration file for this project, please run:
8
8
 
9
- eslint --init
9
+ npm init @eslint/config
10
10
 
11
11
  ESLint looked for configuration files in ${directoryPath} and its ancestors. If it found none, it then looked in your home directory.
12
12
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint",
3
- "version": "8.5.0",
3
+ "version": "8.9.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,19 +47,18 @@
47
47
  "homepage": "https://eslint.org",
48
48
  "bugs": "https://github.com/eslint/eslint/issues/",
49
49
  "dependencies": {
50
- "@eslint/eslintrc": "^1.0.5",
50
+ "@eslint/eslintrc": "^1.1.0",
51
51
  "@humanwhocodes/config-array": "^0.9.2",
52
52
  "ajv": "^6.10.0",
53
53
  "chalk": "^4.0.0",
54
54
  "cross-spawn": "^7.0.2",
55
55
  "debug": "^4.3.2",
56
56
  "doctrine": "^3.0.0",
57
- "enquirer": "^2.3.5",
58
57
  "escape-string-regexp": "^4.0.0",
59
- "eslint-scope": "^7.1.0",
58
+ "eslint-scope": "^7.1.1",
60
59
  "eslint-utils": "^3.0.0",
61
- "eslint-visitor-keys": "^3.1.0",
62
- "espree": "^9.2.0",
60
+ "eslint-visitor-keys": "^3.3.0",
61
+ "espree": "^9.3.1",
63
62
  "esquery": "^1.4.0",
64
63
  "esutils": "^2.0.2",
65
64
  "fast-deep-equal": "^3.1.3",
@@ -67,7 +66,7 @@
67
66
  "functional-red-black-tree": "^1.0.1",
68
67
  "glob-parent": "^6.0.1",
69
68
  "globals": "^13.6.0",
70
- "ignore": "^4.0.6",
69
+ "ignore": "^5.2.0",
71
70
  "import-fresh": "^3.0.0",
72
71
  "imurmurhash": "^0.1.4",
73
72
  "is-glob": "^4.0.0",
@@ -78,9 +77,7 @@
78
77
  "minimatch": "^3.0.4",
79
78
  "natural-compare": "^1.4.0",
80
79
  "optionator": "^0.9.1",
81
- "progress": "^2.0.0",
82
80
  "regexpp": "^3.2.0",
83
- "semver": "^7.2.1",
84
81
  "strip-ansi": "^6.0.1",
85
82
  "strip-json-comments": "^3.1.0",
86
83
  "text-table": "^0.2.0",
@@ -118,16 +115,19 @@
118
115
  "load-perf": "^0.2.0",
119
116
  "markdownlint": "^0.24.0",
120
117
  "markdownlint-cli": "^0.30.0",
118
+ "marked": "^4.0.8",
121
119
  "memfs": "^3.0.1",
122
120
  "mocha": "^8.3.2",
123
121
  "mocha-junit-reporter": "^2.0.0",
124
122
  "node-polyfill-webpack-plugin": "^1.0.3",
125
123
  "npm-license": "^0.3.3",
126
124
  "nyc": "^15.0.1",
125
+ "progress": "^2.0.3",
127
126
  "proxyquire": "^2.0.1",
128
127
  "puppeteer": "^9.1.1",
129
128
  "recast": "^0.20.4",
130
129
  "regenerator-runtime": "^0.13.2",
130
+ "semver": "^7.3.5",
131
131
  "shelljs": "^0.8.2",
132
132
  "sinon": "^11.0.0",
133
133
  "temp": "^0.9.0",