eslint 9.2.0 → 9.4.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.
@@ -9,140 +9,16 @@
9
9
  // Helpers
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- /**
13
- * Gets the containing loop node of a specified node.
14
- *
15
- * We don't need to check nested functions, so this ignores those.
16
- * `Scope.through` contains references of nested functions.
17
- * @param {ASTNode} node An AST node to get.
18
- * @returns {ASTNode|null} The containing loop node of the specified node, or
19
- * `null`.
20
- */
21
- function getContainingLoopNode(node) {
22
- for (let currentNode = node; currentNode.parent; currentNode = currentNode.parent) {
23
- const parent = currentNode.parent;
24
-
25
- switch (parent.type) {
26
- case "WhileStatement":
27
- case "DoWhileStatement":
28
- return parent;
29
-
30
- case "ForStatement":
31
-
32
- // `init` is outside of the loop.
33
- if (parent.init !== currentNode) {
34
- return parent;
35
- }
36
- break;
37
-
38
- case "ForInStatement":
39
- case "ForOfStatement":
40
-
41
- // `right` is outside of the loop.
42
- if (parent.right !== currentNode) {
43
- return parent;
44
- }
45
- break;
46
-
47
- case "ArrowFunctionExpression":
48
- case "FunctionExpression":
49
- case "FunctionDeclaration":
50
-
51
- // We don't need to check nested functions.
52
- return null;
53
-
54
- default:
55
- break;
56
- }
57
- }
58
-
59
- return null;
60
- }
61
12
 
62
13
  /**
63
- * Gets the containing loop node of a given node.
64
- * If the loop was nested, this returns the most outer loop.
65
- * @param {ASTNode} node A node to get. This is a loop node.
66
- * @param {ASTNode|null} excludedNode A node that the result node should not
67
- * include.
68
- * @returns {ASTNode} The most outer loop node.
14
+ * Identifies is a node is a FunctionExpression which is part of an IIFE
15
+ * @param {ASTNode} node Node to test
16
+ * @returns {boolean} True if it's an IIFE
69
17
  */
70
- function getTopLoopNode(node, excludedNode) {
71
- const border = excludedNode ? excludedNode.range[1] : 0;
72
- let retv = node;
73
- let containingLoopNode = node;
74
-
75
- while (containingLoopNode && containingLoopNode.range[0] >= border) {
76
- retv = containingLoopNode;
77
- containingLoopNode = getContainingLoopNode(containingLoopNode);
78
- }
79
-
80
- return retv;
18
+ function isIIFE(node) {
19
+ return (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") && node.parent && node.parent.type === "CallExpression" && node.parent.callee === node;
81
20
  }
82
21
 
83
- /**
84
- * Checks whether a given reference which refers to an upper scope's variable is
85
- * safe or not.
86
- * @param {ASTNode} loopNode A containing loop node.
87
- * @param {eslint-scope.Reference} reference A reference to check.
88
- * @returns {boolean} `true` if the reference is safe or not.
89
- */
90
- function isSafe(loopNode, reference) {
91
- const variable = reference.resolved;
92
- const definition = variable && variable.defs[0];
93
- const declaration = definition && definition.parent;
94
- const kind = (declaration && declaration.type === "VariableDeclaration")
95
- ? declaration.kind
96
- : "";
97
-
98
- // Variables which are declared by `const` is safe.
99
- if (kind === "const") {
100
- return true;
101
- }
102
-
103
- /*
104
- * Variables which are declared by `let` in the loop is safe.
105
- * It's a different instance from the next loop step's.
106
- */
107
- if (kind === "let" &&
108
- declaration.range[0] > loopNode.range[0] &&
109
- declaration.range[1] < loopNode.range[1]
110
- ) {
111
- return true;
112
- }
113
-
114
- /*
115
- * WriteReferences which exist after this border are unsafe because those
116
- * can modify the variable.
117
- */
118
- const border = getTopLoopNode(
119
- loopNode,
120
- (kind === "let") ? declaration : null
121
- ).range[0];
122
-
123
- /**
124
- * Checks whether a given reference is safe or not.
125
- * The reference is every reference of the upper scope's variable we are
126
- * looking now.
127
- *
128
- * It's safe if the reference matches one of the following condition.
129
- * - is readonly.
130
- * - doesn't exist inside a local function and after the border.
131
- * @param {eslint-scope.Reference} upperRef A reference to check.
132
- * @returns {boolean} `true` if the reference is safe.
133
- */
134
- function isSafeReference(upperRef) {
135
- const id = upperRef.identifier;
136
-
137
- return (
138
- !upperRef.isWrite() ||
139
- variable.scope.variableScope === upperRef.from.variableScope &&
140
- id.range[0] < border
141
- );
142
- }
143
-
144
- return Boolean(variable) && variable.references.every(isSafeReference);
145
- }
146
22
 
147
23
  //------------------------------------------------------------------------------
148
24
  // Rule Definition
@@ -168,8 +44,147 @@ module.exports = {
168
44
 
169
45
  create(context) {
170
46
 
47
+ const SKIPPED_IIFE_NODES = new Set();
171
48
  const sourceCode = context.sourceCode;
172
49
 
50
+ /**
51
+ * Gets the containing loop node of a specified node.
52
+ *
53
+ * We don't need to check nested functions, so this ignores those, with the exception of IIFE.
54
+ * `Scope.through` contains references of nested functions.
55
+ * @param {ASTNode} node An AST node to get.
56
+ * @returns {ASTNode|null} The containing loop node of the specified node, or
57
+ * `null`.
58
+ */
59
+ function getContainingLoopNode(node) {
60
+ for (let currentNode = node; currentNode.parent; currentNode = currentNode.parent) {
61
+ const parent = currentNode.parent;
62
+
63
+ switch (parent.type) {
64
+ case "WhileStatement":
65
+ case "DoWhileStatement":
66
+ return parent;
67
+
68
+ case "ForStatement":
69
+
70
+ // `init` is outside of the loop.
71
+ if (parent.init !== currentNode) {
72
+ return parent;
73
+ }
74
+ break;
75
+
76
+ case "ForInStatement":
77
+ case "ForOfStatement":
78
+
79
+ // `right` is outside of the loop.
80
+ if (parent.right !== currentNode) {
81
+ return parent;
82
+ }
83
+ break;
84
+
85
+ case "ArrowFunctionExpression":
86
+ case "FunctionExpression":
87
+ case "FunctionDeclaration":
88
+
89
+ // We need to check nested functions only in case of IIFE.
90
+ if (SKIPPED_IIFE_NODES.has(parent)) {
91
+ break;
92
+ }
93
+
94
+ return null;
95
+ default:
96
+ break;
97
+ }
98
+ }
99
+
100
+ return null;
101
+ }
102
+
103
+ /**
104
+ * Gets the containing loop node of a given node.
105
+ * If the loop was nested, this returns the most outer loop.
106
+ * @param {ASTNode} node A node to get. This is a loop node.
107
+ * @param {ASTNode|null} excludedNode A node that the result node should not
108
+ * include.
109
+ * @returns {ASTNode} The most outer loop node.
110
+ */
111
+ function getTopLoopNode(node, excludedNode) {
112
+ const border = excludedNode ? excludedNode.range[1] : 0;
113
+ let retv = node;
114
+ let containingLoopNode = node;
115
+
116
+ while (containingLoopNode && containingLoopNode.range[0] >= border) {
117
+ retv = containingLoopNode;
118
+ containingLoopNode = getContainingLoopNode(containingLoopNode);
119
+ }
120
+
121
+ return retv;
122
+ }
123
+
124
+ /**
125
+ * Checks whether a given reference which refers to an upper scope's variable is
126
+ * safe or not.
127
+ * @param {ASTNode} loopNode A containing loop node.
128
+ * @param {eslint-scope.Reference} reference A reference to check.
129
+ * @returns {boolean} `true` if the reference is safe or not.
130
+ */
131
+ function isSafe(loopNode, reference) {
132
+ const variable = reference.resolved;
133
+ const definition = variable && variable.defs[0];
134
+ const declaration = definition && definition.parent;
135
+ const kind = (declaration && declaration.type === "VariableDeclaration")
136
+ ? declaration.kind
137
+ : "";
138
+
139
+ // Variables which are declared by `const` is safe.
140
+ if (kind === "const") {
141
+ return true;
142
+ }
143
+
144
+ /*
145
+ * Variables which are declared by `let` in the loop is safe.
146
+ * It's a different instance from the next loop step's.
147
+ */
148
+ if (kind === "let" &&
149
+ declaration.range[0] > loopNode.range[0] &&
150
+ declaration.range[1] < loopNode.range[1]
151
+ ) {
152
+ return true;
153
+ }
154
+
155
+ /*
156
+ * WriteReferences which exist after this border are unsafe because those
157
+ * can modify the variable.
158
+ */
159
+ const border = getTopLoopNode(
160
+ loopNode,
161
+ (kind === "let") ? declaration : null
162
+ ).range[0];
163
+
164
+ /**
165
+ * Checks whether a given reference is safe or not.
166
+ * The reference is every reference of the upper scope's variable we are
167
+ * looking now.
168
+ *
169
+ * It's safe if the reference matches one of the following condition.
170
+ * - is readonly.
171
+ * - doesn't exist inside a local function and after the border.
172
+ * @param {eslint-scope.Reference} upperRef A reference to check.
173
+ * @returns {boolean} `true` if the reference is safe.
174
+ */
175
+ function isSafeReference(upperRef) {
176
+ const id = upperRef.identifier;
177
+
178
+ return (
179
+ !upperRef.isWrite() ||
180
+ variable.scope.variableScope === upperRef.from.variableScope &&
181
+ id.range[0] < border
182
+ );
183
+ }
184
+
185
+ return Boolean(variable) && variable.references.every(isSafeReference);
186
+ }
187
+
173
188
  /**
174
189
  * Reports functions which match the following condition:
175
190
  *
@@ -186,6 +201,23 @@ module.exports = {
186
201
  }
187
202
 
188
203
  const references = sourceCode.getScope(node).through;
204
+
205
+ // Check if the function is not asynchronous or a generator function
206
+ if (!(node.async || node.generator)) {
207
+ if (isIIFE(node)) {
208
+
209
+ const isFunctionExpression = node.type === "FunctionExpression";
210
+
211
+ // Check if the function is referenced elsewhere in the code
212
+ const isFunctionReferenced = isFunctionExpression && node.id ? references.some(r => r.identifier.name === node.id.name) : false;
213
+
214
+ if (!isFunctionReferenced) {
215
+ SKIPPED_IIFE_NODES.add(node);
216
+ return;
217
+ }
218
+ }
219
+ }
220
+
189
221
  const unsafeRefs = references.filter(r => r.resolved && !isSafe(loopNode, r)).map(r => r.identifier.name);
190
222
 
191
223
  if (unsafeRefs.length > 0) {
@@ -85,12 +85,10 @@ function isUnicodeCodePointEscape(char) {
85
85
  const findCharacterSequences = {
86
86
  *surrogatePairWithoutUFlag(chars) {
87
87
  for (const [index, char] of chars.entries()) {
88
- if (index === 0) {
89
- continue;
90
- }
91
88
  const previous = chars[index - 1];
92
89
 
93
90
  if (
91
+ previous && char &&
94
92
  isSurrogatePair(previous.value, char.value) &&
95
93
  !isUnicodeCodePointEscape(previous) &&
96
94
  !isUnicodeCodePointEscape(char)
@@ -102,12 +100,10 @@ const findCharacterSequences = {
102
100
 
103
101
  *surrogatePair(chars) {
104
102
  for (const [index, char] of chars.entries()) {
105
- if (index === 0) {
106
- continue;
107
- }
108
103
  const previous = chars[index - 1];
109
104
 
110
105
  if (
106
+ previous && char &&
111
107
  isSurrogatePair(previous.value, char.value) &&
112
108
  (
113
109
  isUnicodeCodePointEscape(previous) ||
@@ -119,14 +115,17 @@ const findCharacterSequences = {
119
115
  }
120
116
  },
121
117
 
122
- *combiningClass(chars) {
118
+ *combiningClass(chars, unfilteredChars) {
119
+
120
+ /*
121
+ * When `allowEscape` is `true`, a combined character should only be allowed if the combining mark appears as an escape sequence.
122
+ * This means that the base character should be considered even if it's escaped.
123
+ */
123
124
  for (const [index, char] of chars.entries()) {
124
- if (index === 0) {
125
- continue;
126
- }
127
- const previous = chars[index - 1];
125
+ const previous = unfilteredChars[index - 1];
128
126
 
129
127
  if (
128
+ previous && char &&
130
129
  isCombiningCharacter(char.value) &&
131
130
  !isCombiningCharacter(previous.value)
132
131
  ) {
@@ -137,12 +136,10 @@ const findCharacterSequences = {
137
136
 
138
137
  *emojiModifier(chars) {
139
138
  for (const [index, char] of chars.entries()) {
140
- if (index === 0) {
141
- continue;
142
- }
143
139
  const previous = chars[index - 1];
144
140
 
145
141
  if (
142
+ previous && char &&
146
143
  isEmojiModifier(char.value) &&
147
144
  !isEmojiModifier(previous.value)
148
145
  ) {
@@ -153,12 +150,10 @@ const findCharacterSequences = {
153
150
 
154
151
  *regionalIndicatorSymbol(chars) {
155
152
  for (const [index, char] of chars.entries()) {
156
- if (index === 0) {
157
- continue;
158
- }
159
153
  const previous = chars[index - 1];
160
154
 
161
155
  if (
156
+ previous && char &&
162
157
  isRegionalIndicatorSymbol(char.value) &&
163
158
  isRegionalIndicatorSymbol(previous.value)
164
159
  ) {
@@ -171,17 +166,18 @@ const findCharacterSequences = {
171
166
  let sequence = null;
172
167
 
173
168
  for (const [index, char] of chars.entries()) {
174
- if (index === 0 || index === chars.length - 1) {
175
- continue;
176
- }
169
+ const previous = chars[index - 1];
170
+ const next = chars[index + 1];
171
+
177
172
  if (
173
+ previous && char && next &&
178
174
  char.value === 0x200d &&
179
- chars[index - 1].value !== 0x200d &&
180
- chars[index + 1].value !== 0x200d
175
+ previous.value !== 0x200d &&
176
+ next.value !== 0x200d
181
177
  ) {
182
178
  if (sequence) {
183
- if (sequence.at(-1) === chars[index - 1]) {
184
- sequence.push(char, chars[index + 1]); // append to the sequence
179
+ if (sequence.at(-1) === previous) {
180
+ sequence.push(char, next); // append to the sequence
185
181
  } else {
186
182
  yield sequence;
187
183
  sequence = chars.slice(index - 1, index + 2);
@@ -227,6 +223,41 @@ function getStaticValueOrRegex(node, initialScope) {
227
223
  return staticValue;
228
224
  }
229
225
 
226
+ /**
227
+ * Checks whether a specified regexpp character is represented as an acceptable escape sequence.
228
+ * This function requires the source text of the character to be known.
229
+ * @param {Character} char Character to check.
230
+ * @param {string} charSource Source text of the character to check.
231
+ * @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
232
+ */
233
+ function checkForAcceptableEscape(char, charSource) {
234
+ if (!charSource.startsWith("\\")) {
235
+ return false;
236
+ }
237
+ const match = /(?<=^\\+).$/su.exec(charSource);
238
+
239
+ return match?.[0] !== String.fromCodePoint(char.value);
240
+ }
241
+
242
+ /**
243
+ * Checks whether a specified regexpp character is represented as an acceptable escape sequence.
244
+ * This function works with characters that are produced by a string or template literal.
245
+ * It requires the source text and the CodeUnit list of the literal to be known.
246
+ * @param {Character} char Character to check.
247
+ * @param {string} nodeSource Source text of the string or template literal that produces the character.
248
+ * @param {CodeUnit[]} codeUnits List of CodeUnit objects of the literal that produces the character.
249
+ * @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
250
+ */
251
+ function checkForAcceptableEscapeInString(char, nodeSource, codeUnits) {
252
+ const firstIndex = char.start;
253
+ const lastIndex = char.end - 1;
254
+ const start = codeUnits[firstIndex].start;
255
+ const end = codeUnits[lastIndex].end;
256
+ const charSource = nodeSource.slice(start, end);
257
+
258
+ return checkForAcceptableEscape(char, charSource);
259
+ }
260
+
230
261
  //------------------------------------------------------------------------------
231
262
  // Rule Definition
232
263
  //------------------------------------------------------------------------------
@@ -244,7 +275,18 @@ module.exports = {
244
275
 
245
276
  hasSuggestions: true,
246
277
 
247
- schema: [],
278
+ schema: [
279
+ {
280
+ type: "object",
281
+ properties: {
282
+ allowEscape: {
283
+ type: "boolean",
284
+ default: false
285
+ }
286
+ },
287
+ additionalProperties: false
288
+ }
289
+ ],
248
290
 
249
291
  messages: {
250
292
  surrogatePairWithoutUFlag: "Unexpected surrogate pair in character class. Use 'u' flag.",
@@ -257,6 +299,7 @@ module.exports = {
257
299
  }
258
300
  },
259
301
  create(context) {
302
+ const allowEscape = context.options[0]?.allowEscape;
260
303
  const sourceCode = context.sourceCode;
261
304
  const parser = new RegExpParser();
262
305
  const checkedPatternNodes = new Set();
@@ -288,24 +331,62 @@ module.exports = {
288
331
  return;
289
332
  }
290
333
 
334
+ let codeUnits = null;
335
+
336
+ /**
337
+ * Checks whether a specified regexpp character is represented as an acceptable escape sequence.
338
+ * For the purposes of this rule, an escape sequence is considered acceptable if it consists of one or more backslashes followed by the character being escaped.
339
+ * @param {Character} char Character to check.
340
+ * @returns {boolean} Whether the specified regexpp character is represented as an acceptable escape sequence.
341
+ */
342
+ function isAcceptableEscapeSequence(char) {
343
+ if (node.type === "Literal" && node.regex) {
344
+ return checkForAcceptableEscape(char, char.raw);
345
+ }
346
+ if (node.type === "Literal" && typeof node.value === "string") {
347
+ const nodeSource = node.raw;
348
+
349
+ codeUnits ??= parseStringLiteral(nodeSource);
350
+
351
+ return checkForAcceptableEscapeInString(char, nodeSource, codeUnits);
352
+ }
353
+ if (astUtils.isStaticTemplateLiteral(node)) {
354
+ const nodeSource = sourceCode.getText(node);
355
+
356
+ codeUnits ??= parseTemplateToken(nodeSource);
357
+
358
+ return checkForAcceptableEscapeInString(char, nodeSource, codeUnits);
359
+ }
360
+ return false;
361
+ }
362
+
291
363
  const foundKindMatches = new Map();
292
364
 
293
365
  visitRegExpAST(patternNode, {
294
366
  onCharacterClassEnter(ccNode) {
295
- for (const chars of iterateCharacterSequence(ccNode.elements)) {
367
+ for (const unfilteredChars of iterateCharacterSequence(ccNode.elements)) {
368
+ let chars;
369
+
370
+ if (allowEscape) {
371
+
372
+ // Replace escape sequences with null to avoid having them flagged.
373
+ chars = unfilteredChars.map(char => (isAcceptableEscapeSequence(char) ? null : char));
374
+ } else {
375
+ chars = unfilteredChars;
376
+ }
296
377
  for (const kind of kinds) {
378
+ const matches = findCharacterSequences[kind](chars, unfilteredChars);
379
+
297
380
  if (foundKindMatches.has(kind)) {
298
- foundKindMatches.get(kind).push(...findCharacterSequences[kind](chars));
381
+ foundKindMatches.get(kind).push(...matches);
299
382
  } else {
300
- foundKindMatches.set(kind, [...findCharacterSequences[kind](chars)]);
383
+ foundKindMatches.set(kind, [...matches]);
301
384
  }
302
385
  }
303
386
  }
304
387
  }
305
388
  });
306
389
 
307
- let codeUnits = null;
308
-
309
390
  /**
310
391
  * Finds the report loc(s) for a range of matches.
311
392
  * Only literals and expression-less templates generate granular errors.
@@ -37,7 +37,8 @@ module.exports = {
37
37
  type: "string"
38
38
  },
39
39
  uniqueItems: true
40
- }
40
+ },
41
+ restrictedNamedExportsPattern: { type: "string" }
41
42
  },
42
43
  additionalProperties: false
43
44
  },
@@ -52,6 +53,7 @@ module.exports = {
52
53
  },
53
54
  uniqueItems: true
54
55
  },
56
+ restrictedNamedExportsPattern: { type: "string" },
55
57
  restrictDefaultExports: {
56
58
  type: "object",
57
59
  properties: {
@@ -98,6 +100,7 @@ module.exports = {
98
100
  create(context) {
99
101
 
100
102
  const restrictedNames = new Set(context.options[0] && context.options[0].restrictedNamedExports);
103
+ const restrictedNamePattern = context.options[0] && context.options[0].restrictedNamedExportsPattern;
101
104
  const restrictDefaultExports = context.options[0] && context.options[0].restrictDefaultExports;
102
105
  const sourceCode = context.sourceCode;
103
106
 
@@ -109,7 +112,15 @@ module.exports = {
109
112
  function checkExportedName(node) {
110
113
  const name = astUtils.getModuleExportName(node);
111
114
 
112
- if (restrictedNames.has(name)) {
115
+ let matchesRestrictedNamePattern = false;
116
+
117
+ if (restrictedNamePattern && name !== "default") {
118
+ const patternRegex = new RegExp(restrictedNamePattern, "u");
119
+
120
+ matchesRestrictedNamePattern = patternRegex.test(name);
121
+ }
122
+
123
+ if (matchesRestrictedNamePattern || restrictedNames.has(name)) {
113
124
  context.report({
114
125
  node,
115
126
  messageId: "restrictedNamed",
@@ -284,35 +284,22 @@ module.exports = {
284
284
  const arrowToken = sourceCode.getTokenBefore(node.value.body, astUtils.isArrowToken);
285
285
  const fnBody = sourceCode.text.slice(arrowToken.range[1], node.value.range[1]);
286
286
 
287
- let shouldAddParensAroundParameters = false;
288
- let tokenBeforeParams;
289
-
290
- if (node.value.params.length === 0) {
291
- tokenBeforeParams = sourceCode.getFirstToken(node.value, astUtils.isOpeningParenToken);
292
- } else {
293
- tokenBeforeParams = sourceCode.getTokenBefore(node.value.params[0]);
294
- }
295
-
296
- if (node.value.params.length === 1) {
297
- const hasParen = astUtils.isOpeningParenToken(tokenBeforeParams);
298
- const isTokenOutsideNode = tokenBeforeParams.range[0] < node.range[0];
299
-
300
- shouldAddParensAroundParameters = !hasParen || isTokenOutsideNode;
301
- }
287
+ // First token should not be `async`
288
+ const firstValueToken = sourceCode.getFirstToken(node.value, {
289
+ skip: node.value.async ? 1 : 0
290
+ });
302
291
 
303
- const sliceStart = shouldAddParensAroundParameters
304
- ? node.value.params[0].range[0]
305
- : tokenBeforeParams.range[0];
292
+ const sliceStart = firstValueToken.range[0];
306
293
  const sliceEnd = sourceCode.getTokenBefore(arrowToken).range[1];
294
+ const shouldAddParens = node.value.params.length === 1 && node.value.params[0].range[0] === sliceStart;
307
295
 
308
296
  const oldParamText = sourceCode.text.slice(sliceStart, sliceEnd);
309
- const newParamText = shouldAddParensAroundParameters ? `(${oldParamText})` : oldParamText;
297
+ const newParamText = shouldAddParens ? `(${oldParamText})` : oldParamText;
310
298
 
311
299
  return fixer.replaceTextRange(
312
300
  fixRange,
313
301
  methodPrefix + newParamText + fnBody
314
302
  );
315
-
316
303
  }
317
304
 
318
305
  /**
@@ -497,6 +484,13 @@ module.exports = {
497
484
  node,
498
485
  messageId: "expectedPropertyShorthand",
499
486
  fix(fixer) {
487
+
488
+ // x: /* */ x
489
+ // x: (/* */ x)
490
+ if (sourceCode.getCommentsInside(node).length > 0) {
491
+ return null;
492
+ }
493
+
500
494
  return fixer.replaceText(node, node.value.name);
501
495
  }
502
496
  });
@@ -510,6 +504,13 @@ module.exports = {
510
504
  node,
511
505
  messageId: "expectedPropertyShorthand",
512
506
  fix(fixer) {
507
+
508
+ // "x": /* */ x
509
+ // "x": (/* */ x)
510
+ if (sourceCode.getCommentsInside(node).length > 0) {
511
+ return null;
512
+ }
513
+
513
514
  return fixer.replaceText(node, node.value.name);
514
515
  }
515
516
  });
@@ -9,9 +9,9 @@
9
9
  // Requirements
10
10
  //------------------------------------------------------------------------------
11
11
 
12
- const path = require("path");
12
+ const path = require("node:path");
13
13
  const spawn = require("cross-spawn");
14
- const os = require("os");
14
+ const os = require("node:os");
15
15
  const log = require("../shared/logging");
16
16
  const packageJson = require("../../package.json");
17
17