oxlint-plugin-react-doctor 0.7.7-dev.79abd71 → 0.7.7-dev.89dbf08

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.
Files changed (2) hide show
  1. package/dist/index.js +370 -978
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7,13 +7,6 @@ import { analyze } from "eslint-scope";
7
7
  //#region src/plugin/utils/is-node-of-type.ts
8
8
  const isNodeOfType = (node, type) => node !== null && typeof node === "object" && "type" in node && node.type === type;
9
9
  //#endregion
10
- //#region src/plugin/utils/is-type-only-import.ts
11
- const isEverySpecifierInlineType = (specifiers, specifierType, kindField) => {
12
- if (!specifiers || specifiers.length === 0) return false;
13
- return specifiers.every((specifier) => isNodeOfType(specifier, specifierType) && specifier[kindField] === "type");
14
- };
15
- const isTypeOnlyImport = (node) => node.importKind === "type" || isEverySpecifierInlineType(node.specifiers, "ImportSpecifier", "importKind");
16
- //#endregion
17
10
  //#region src/plugin/utils/non-react-jsx-dialect.ts
18
11
  const NON_REACT_JSX_DIALECT_PACKAGES = new Set([
19
12
  "solid-js",
@@ -28,33 +21,17 @@ const NON_REACT_JSX_DIALECT_PACKAGES = new Set([
28
21
  "vidode"
29
22
  ]);
30
23
  const NON_REACT_JSX_DIALECT_PACKAGE_PREFIXES = ["solid-js", "@builder.io/qwik"];
31
- const REACT_JSX_DIALECT_PACKAGE_PREFIXES = [
32
- "react",
33
- "react-dom",
34
- "preact"
35
- ];
36
24
  const startsWithAny = (source, prefixes) => prefixes.some((prefix) => source === prefix || source.startsWith(`${prefix}/`));
37
- const collectJsxRuntimeImports = (program) => {
38
- let hasNonReactRuntime = false;
39
- let hasReactRuntime = false;
25
+ const fileImportsNonReactJsxDialect = (program) => {
40
26
  for (const statement of program.body) {
41
27
  if (!isNodeOfType(statement, "ImportDeclaration")) continue;
42
- const importDeclaration = statement;
43
- if (isTypeOnlyImport(importDeclaration)) continue;
44
- const source = importDeclaration.source;
28
+ const source = statement.source;
45
29
  const value = source && typeof source.value === "string" ? source.value : null;
46
30
  if (!value) continue;
47
- if (NON_REACT_JSX_DIALECT_PACKAGES.has(value) || startsWithAny(value, NON_REACT_JSX_DIALECT_PACKAGE_PREFIXES)) hasNonReactRuntime = true;
48
- if (startsWithAny(value, REACT_JSX_DIALECT_PACKAGE_PREFIXES)) hasReactRuntime = true;
31
+ if (NON_REACT_JSX_DIALECT_PACKAGES.has(value)) return true;
32
+ if (startsWithAny(value, NON_REACT_JSX_DIALECT_PACKAGE_PREFIXES)) return true;
49
33
  }
50
- return {
51
- hasNonReactRuntime,
52
- hasReactRuntime
53
- };
54
- };
55
- const fileImportsNonReactJsxDialect = (program) => {
56
- const runtimeImports = collectJsxRuntimeImports(program);
57
- return runtimeImports.hasNonReactRuntime && !runtimeImports.hasReactRuntime;
34
+ return false;
58
35
  };
59
36
  const jsxAttributeIsNonReactDialectMarker = (openingNode) => {
60
37
  for (const attribute of openingNode.attributes) {
@@ -267,7 +244,6 @@ const VISITOR_NODE_NAME_PATTERN = /^[A-Z]/;
267
244
  const wrapCreateForReactJsxOnly = (create) => ((context) => {
268
245
  const innerVisitors = create(context);
269
246
  let fileIsNonReactJsx = false;
270
- let fileImportsReactRuntime = false;
271
247
  const wrappedVisitors = {};
272
248
  for (const [key, visitor] of Object.entries(innerVisitors)) {
273
249
  if (typeof visitor !== "function") {
@@ -280,16 +256,14 @@ const wrapCreateForReactJsxOnly = (create) => ((context) => {
280
256
  }
281
257
  if (key === "Program") {
282
258
  wrappedVisitors.Program = (node) => {
283
- const runtimeImports = collectJsxRuntimeImports(node);
284
- fileImportsReactRuntime = runtimeImports.hasReactRuntime;
285
- fileIsNonReactJsx = runtimeImports.hasNonReactRuntime && !runtimeImports.hasReactRuntime;
259
+ fileIsNonReactJsx = fileImportsNonReactJsxDialect(node);
286
260
  visitor(node);
287
261
  };
288
262
  continue;
289
263
  }
290
264
  if (key === "JSXOpeningElement") {
291
265
  wrappedVisitors.JSXOpeningElement = (node) => {
292
- if (!fileImportsReactRuntime && !fileIsNonReactJsx && jsxAttributeIsNonReactDialectMarker(node)) fileIsNonReactJsx = true;
266
+ if (!fileIsNonReactJsx && jsxAttributeIsNonReactDialectMarker(node)) fileIsNonReactJsx = true;
293
267
  if (fileIsNonReactJsx) return;
294
268
  visitor(node);
295
269
  };
@@ -301,9 +275,7 @@ const wrapCreateForReactJsxOnly = (create) => ((context) => {
301
275
  };
302
276
  }
303
277
  if (!("Program" in wrappedVisitors)) wrappedVisitors.Program = (node) => {
304
- const runtimeImports = collectJsxRuntimeImports(node);
305
- fileImportsReactRuntime = runtimeImports.hasReactRuntime;
306
- fileIsNonReactJsx = runtimeImports.hasNonReactRuntime && !runtimeImports.hasReactRuntime;
278
+ fileIsNonReactJsx = fileImportsNonReactJsxDialect(node);
307
279
  };
308
280
  return wrappedVisitors;
309
281
  });
@@ -4342,397 +4314,6 @@ const findTransparentExpressionRoot = (node) => {
4342
4314
  return current;
4343
4315
  };
4344
4316
  //#endregion
4345
- //#region src/plugin/utils/get-static-property-key-name.ts
4346
- const getStaticPropertyKeyName = (node, options = {}) => {
4347
- if (!isNodeOfType(node, "Property") && !isNodeOfType(node, "MethodDefinition") && !isNodeOfType(node, "MemberExpression")) return null;
4348
- const key = isNodeOfType(node, "MemberExpression") ? node.property : node.key;
4349
- if (node.computed) {
4350
- if (options.allowComputedString && isNodeOfType(key, "Literal") && typeof key.value === "string") return key.value;
4351
- if (options.allowComputedString && isNodeOfType(key, "TemplateLiteral") && key.expressions.length === 0) return key.quasis[0]?.value.cooked ?? key.quasis[0]?.value.raw ?? null;
4352
- return null;
4353
- }
4354
- if (isNodeOfType(key, "Identifier")) return key.name;
4355
- if (isNodeOfType(key, "Literal")) {
4356
- if (typeof key.value === "string") return key.value;
4357
- if (options.stringifyNonStringLiterals) return String(key.value);
4358
- }
4359
- return null;
4360
- };
4361
- //#endregion
4362
- //#region src/plugin/utils/get-destructured-binding-property-name.ts
4363
- const getDestructuredBindingPropertyName = (bindingIdentifier) => {
4364
- let bindingNode = bindingIdentifier;
4365
- if (isNodeOfType(bindingNode.parent, "AssignmentPattern") && bindingNode.parent.left === bindingNode) bindingNode = bindingNode.parent;
4366
- const property = bindingNode.parent;
4367
- if (!property || !isNodeOfType(property, "Property") || property.value !== bindingNode || !property.parent || !isNodeOfType(property.parent, "ObjectPattern")) return null;
4368
- return getStaticPropertyKeyName(property, { allowComputedString: true });
4369
- };
4370
- //#endregion
4371
- //#region src/plugin/utils/get-static-property-name.ts
4372
- const getStaticPropertyName = (memberExpression) => {
4373
- const property = memberExpression.property;
4374
- if (!memberExpression.computed && isNodeOfType(property, "Identifier")) return property.name;
4375
- if (memberExpression.computed && isNodeOfType(property, "Literal")) return typeof property.value === "string" ? property.value : null;
4376
- if (memberExpression.computed && isNodeOfType(property, "TemplateLiteral") && property.expressions.length === 0) return property.quasis[0]?.value.cooked ?? property.quasis[0]?.value.raw ?? null;
4377
- return null;
4378
- };
4379
- //#endregion
4380
- //#region src/plugin/utils/has-static-property-write-before.ts
4381
- const equivalentSymbolsByAnalysis = /* @__PURE__ */ new WeakMap();
4382
- const potentiallyAliasedSymbolsByAnalysis = /* @__PURE__ */ new WeakMap();
4383
- const CONDITIONAL_EXECUTION_NODE_TYPES = new Set([
4384
- "CatchClause",
4385
- "ConditionalExpression",
4386
- "DoWhileStatement",
4387
- "ForInStatement",
4388
- "ForOfStatement",
4389
- "ForStatement",
4390
- "IfStatement",
4391
- "LogicalExpression",
4392
- "SwitchCase",
4393
- "SwitchStatement",
4394
- "TryStatement",
4395
- "WhileStatement"
4396
- ]);
4397
- const getResolvedStaticPropertyName = (memberExpression, scopes) => {
4398
- if (!isNodeOfType(memberExpression, "MemberExpression")) return null;
4399
- const directPropertyName = getStaticPropertyName(memberExpression);
4400
- if (directPropertyName || !memberExpression.computed) return directPropertyName;
4401
- const property = stripParenExpression(memberExpression.property);
4402
- if (!isNodeOfType(property, "Identifier")) return null;
4403
- const propertySymbol = resolveConstIdentifierAlias(property, scopes);
4404
- const initializer = propertySymbol?.initializer ? stripParenExpression(propertySymbol.initializer) : null;
4405
- return initializer && isNodeOfType(initializer, "Literal") && typeof initializer.value === "string" ? initializer.value : null;
4406
- };
4407
- const collectScopeSymbols = (scope, symbols) => {
4408
- symbols.push(...scope.symbols);
4409
- for (const childScope of scope.children) collectScopeSymbols(childScope, symbols);
4410
- };
4411
- const getEquivalentSymbols = (identifier, scopes) => {
4412
- const rootSymbol = resolveConstIdentifierAlias(identifier, scopes);
4413
- if (!rootSymbol) return [];
4414
- let symbolsByRootId = equivalentSymbolsByAnalysis.get(scopes);
4415
- if (!symbolsByRootId) {
4416
- symbolsByRootId = /* @__PURE__ */ new Map();
4417
- equivalentSymbolsByAnalysis.set(scopes, symbolsByRootId);
4418
- }
4419
- const cachedSymbols = symbolsByRootId.get(rootSymbol.id);
4420
- if (cachedSymbols) return cachedSymbols;
4421
- const allSymbols = [];
4422
- collectScopeSymbols(scopes.rootScope, allSymbols);
4423
- const equivalentSymbols = allSymbols.filter((symbol) => resolveConstIdentifierAlias(symbol.bindingIdentifier, scopes)?.id === rootSymbol.id);
4424
- symbolsByRootId.set(rootSymbol.id, equivalentSymbols);
4425
- return equivalentSymbols;
4426
- };
4427
- const getDirectAliasSourceSymbol = (expression, scopes) => {
4428
- const unwrappedExpression = stripParenExpression(expression);
4429
- return isNodeOfType(unwrappedExpression, "Identifier") ? scopes.symbolFor(unwrappedExpression) : null;
4430
- };
4431
- const getDirectAssignmentSourceSymbol = (identifier, scopes) => {
4432
- const assignmentTarget = findTransparentExpressionRoot(identifier);
4433
- const parent = assignmentTarget.parent;
4434
- if (!parent || !isNodeOfType(parent, "AssignmentExpression") || parent.operator !== "=" || parent.left !== assignmentTarget) return null;
4435
- return getDirectAliasSourceSymbol(parent.right, scopes);
4436
- };
4437
- const isDirectAliasSourceReference = (identifier) => {
4438
- const aliasSource = findTransparentExpressionRoot(identifier);
4439
- const parent = aliasSource.parent;
4440
- if (parent && isNodeOfType(parent, "VariableDeclarator") && parent.init === aliasSource && (isNodeOfType(parent.id, "Identifier") || isNodeOfType(parent.id, "ObjectPattern"))) return true;
4441
- return Boolean(parent && isNodeOfType(parent, "AssignmentExpression") && parent.operator === "=" && parent.right === aliasSource && isNodeOfType(stripParenExpression(parent.left), "Identifier"));
4442
- };
4443
- const isDirectAliasOfKnownSymbol = (symbol, knownSymbolIds, scopes) => {
4444
- if (symbol.initializer && isNodeOfType(symbol.declarationNode, "VariableDeclarator") && symbol.declarationNode.id === symbol.bindingIdentifier) {
4445
- const initializerSymbol = getDirectAliasSourceSymbol(symbol.initializer, scopes);
4446
- if (initializerSymbol && knownSymbolIds.has(initializerSymbol.id)) return true;
4447
- }
4448
- return symbol.references.some((reference) => {
4449
- const assignmentSourceSymbol = getDirectAssignmentSourceSymbol(reference.identifier, scopes);
4450
- return Boolean(assignmentSourceSymbol && knownSymbolIds.has(assignmentSourceSymbol.id));
4451
- });
4452
- };
4453
- const getPotentiallyAliasedSymbols = (identifier, scopes) => {
4454
- const rootSymbol = resolveConstIdentifierAlias(identifier, scopes);
4455
- if (!rootSymbol) return [];
4456
- let symbolsByRootId = potentiallyAliasedSymbolsByAnalysis.get(scopes);
4457
- if (!symbolsByRootId) {
4458
- symbolsByRootId = /* @__PURE__ */ new Map();
4459
- potentiallyAliasedSymbolsByAnalysis.set(scopes, symbolsByRootId);
4460
- }
4461
- const cachedSymbols = symbolsByRootId.get(rootSymbol.id);
4462
- if (cachedSymbols) return cachedSymbols;
4463
- const allSymbols = [];
4464
- collectScopeSymbols(scopes.rootScope, allSymbols);
4465
- const aliasedSymbolIds = new Set([rootSymbol.id]);
4466
- let didAddAlias = true;
4467
- while (didAddAlias) {
4468
- didAddAlias = false;
4469
- for (const symbol of allSymbols) {
4470
- if (aliasedSymbolIds.has(symbol.id)) continue;
4471
- if (!isDirectAliasOfKnownSymbol(symbol, aliasedSymbolIds, scopes)) continue;
4472
- aliasedSymbolIds.add(symbol.id);
4473
- didAddAlias = true;
4474
- }
4475
- }
4476
- const aliasedSymbols = allSymbols.filter((symbol) => aliasedSymbolIds.has(symbol.id));
4477
- symbolsByRootId.set(rootSymbol.id, aliasedSymbols);
4478
- return aliasedSymbols;
4479
- };
4480
- const findExecutionBoundary = (node) => {
4481
- let current = node;
4482
- while (current) {
4483
- if (isFunctionLike$2(current) || isNodeOfType(current, "Program")) return current;
4484
- current = current.parent ?? null;
4485
- }
4486
- return null;
4487
- };
4488
- const isOnUnconditionalPath = (node, boundary) => {
4489
- let current = node.parent ?? null;
4490
- while (current && current !== boundary) {
4491
- if (CONDITIONAL_EXECUTION_NODE_TYPES.has(current.type)) return false;
4492
- current = current.parent ?? null;
4493
- }
4494
- return current === boundary;
4495
- };
4496
- const findFunctionBindingIdentifier = (functionNode) => {
4497
- if (isNodeOfType(functionNode, "FunctionDeclaration")) return functionNode.id ?? null;
4498
- const parent = functionNode.parent;
4499
- if (parent && isNodeOfType(parent, "VariableDeclarator") && parent.init === functionNode && isNodeOfType(parent.id, "Identifier")) return parent.id;
4500
- return null;
4501
- };
4502
- const findDirectCall = (identifier) => {
4503
- let callee = identifier;
4504
- let parent = callee.parent;
4505
- while (parent && stripParenExpression(parent) === identifier) {
4506
- callee = parent;
4507
- parent = callee.parent;
4508
- }
4509
- return parent && isNodeOfType(parent, "CallExpression") && parent.callee === callee ? parent : null;
4510
- };
4511
- const isFunctionSynchronouslyInvokedBefore = (functionNode, referenceNode, scopes, visitedFunctionNodes = /* @__PURE__ */ new Set()) => {
4512
- if (visitedFunctionNodes.has(functionNode) || !isFunctionLike$2(functionNode) || functionNode.generator) return false;
4513
- visitedFunctionNodes.add(functionNode);
4514
- const referenceBoundary = findExecutionBoundary(referenceNode);
4515
- if (!referenceBoundary) return false;
4516
- const invocationCalls = [];
4517
- const bindingIdentifier = findFunctionBindingIdentifier(functionNode);
4518
- if (bindingIdentifier) for (const symbol of getEquivalentSymbols(bindingIdentifier, scopes)) for (const reference of symbol.references) {
4519
- const call = findDirectCall(reference.identifier);
4520
- if (call) invocationCalls.push(call);
4521
- }
4522
- else {
4523
- const call = findDirectCall(functionNode);
4524
- if (call) invocationCalls.push(call);
4525
- }
4526
- return invocationCalls.some((call) => {
4527
- if (call.range[0] >= referenceNode.range[0]) return false;
4528
- const callBoundary = findExecutionBoundary(call);
4529
- if (!callBoundary) return false;
4530
- if (callBoundary === referenceBoundary) return true;
4531
- if (!isFunctionLike$2(callBoundary)) return false;
4532
- return isFunctionSynchronouslyInvokedBefore(callBoundary, referenceNode, scopes, new Set(visitedFunctionNodes));
4533
- });
4534
- };
4535
- const isMemberWriteTarget = (memberExpression) => {
4536
- const parent = memberExpression.parent;
4537
- if (!parent) return false;
4538
- if (isNodeOfType(parent, "AssignmentExpression")) return parent.left === memberExpression;
4539
- if (isNodeOfType(parent, "UpdateExpression")) return parent.argument === memberExpression;
4540
- return isNodeOfType(parent, "UnaryExpression") && parent.operator === "delete" && parent.argument === memberExpression;
4541
- };
4542
- const getMemberWriteTarget = (identifier) => {
4543
- let parent = identifier.parent;
4544
- while (parent && stripParenExpression(parent) === identifier) parent = parent.parent;
4545
- if (!parent || !isNodeOfType(parent, "MemberExpression") || stripParenExpression(parent.object) !== identifier || !isMemberWriteTarget(parent)) return null;
4546
- return parent;
4547
- };
4548
- const getStaticPropertyWriteTarget = (identifier, propertyName, scopes) => {
4549
- const writeTarget = getMemberWriteTarget(identifier);
4550
- return writeTarget && getResolvedStaticPropertyName(writeTarget, scopes) === propertyName ? writeTarget : null;
4551
- };
4552
- const symbolHasStaticPropertyWriteBefore = (symbol, propertyName, referenceNode, scopes) => symbol.references.some((reference) => {
4553
- const writeTarget = getStaticPropertyWriteTarget(reference.identifier, propertyName, scopes);
4554
- if (!writeTarget) return false;
4555
- const writeBoundary = findExecutionBoundary(writeTarget);
4556
- const referenceBoundary = findExecutionBoundary(referenceNode);
4557
- if (!writeBoundary || !referenceBoundary || !isOnUnconditionalPath(writeTarget, writeBoundary)) return false;
4558
- if (writeBoundary === referenceBoundary) return writeTarget.range[0] < referenceNode.range[0];
4559
- return isFunctionLike$2(writeBoundary) && isFunctionSynchronouslyInvokedBefore(writeBoundary, referenceNode, scopes);
4560
- });
4561
- const isStableStaticPropertyReference = (identifier) => {
4562
- if (isDirectAliasSourceReference(identifier)) return true;
4563
- const identifierRoot = findTransparentExpressionRoot(identifier);
4564
- const memberExpression = identifierRoot.parent;
4565
- return Boolean(memberExpression && isNodeOfType(memberExpression, "MemberExpression") && stripParenExpression(memberExpression.object) === identifierRoot);
4566
- };
4567
- const hasPossibleStaticPropertyWrite = (identifier, propertyName, scopes) => {
4568
- if (!isNodeOfType(identifier, "Identifier")) return false;
4569
- return getPotentiallyAliasedSymbols(identifier, scopes).some((symbol) => symbol.references.some((reference) => {
4570
- const writeTarget = getMemberWriteTarget(reference.identifier);
4571
- if (!writeTarget) return false;
4572
- const writtenPropertyName = getResolvedStaticPropertyName(writeTarget, scopes);
4573
- return writtenPropertyName === null || writtenPropertyName === propertyName;
4574
- }));
4575
- };
4576
- const hasPossibleStaticPropertyMutationOrEscape = (identifier, propertyName, scopes) => {
4577
- if (!isNodeOfType(identifier, "Identifier")) return false;
4578
- if (hasPossibleStaticPropertyWrite(identifier, propertyName, scopes)) return true;
4579
- return getPotentiallyAliasedSymbols(identifier, scopes).some((symbol) => symbol.references.some((reference) => !isStableStaticPropertyReference(reference.identifier)));
4580
- };
4581
- const hasPossibleStaticMemberCallWrite = (callExpression, scopes) => {
4582
- const unwrappedCallExpression = stripParenExpression(callExpression);
4583
- if (!isNodeOfType(unwrappedCallExpression, "CallExpression")) return false;
4584
- const callee = stripParenExpression(unwrappedCallExpression.callee);
4585
- if (!isNodeOfType(callee, "MemberExpression")) return false;
4586
- const propertyName = getStaticPropertyName(callee);
4587
- if (propertyName === null) return false;
4588
- const receiver = stripParenExpression(callee.object);
4589
- return isNodeOfType(receiver, "Identifier") && hasPossibleStaticPropertyWrite(receiver, propertyName, scopes);
4590
- };
4591
- const hasStaticPropertyWriteBefore = (identifier, propertyName, referenceNode, scopes) => {
4592
- if (!isNodeOfType(identifier, "Identifier")) return false;
4593
- return getEquivalentSymbols(identifier, scopes).some((symbol) => symbolHasStaticPropertyWriteBefore(symbol, propertyName, referenceNode, scopes));
4594
- };
4595
- //#endregion
4596
- //#region src/plugin/utils/find-enclosing-function.ts
4597
- const findEnclosingFunction$1 = (node) => {
4598
- let cursor = node.parent;
4599
- while (cursor) {
4600
- if (isFunctionLike$2(cursor)) return cursor;
4601
- cursor = cursor.parent ?? null;
4602
- }
4603
- return null;
4604
- };
4605
- //#endregion
4606
- //#region src/plugin/utils/has-symbol-write-before.ts
4607
- const hasSymbolWriteBefore = (symbol, referenceNode, scopes) => symbol.references.some((reference) => {
4608
- if (reference.flag === "read") return false;
4609
- const writeFunction = findEnclosingFunction$1(reference.identifier);
4610
- if (writeFunction === findEnclosingFunction$1(referenceNode)) return reference.identifier.range[0] < referenceNode.range[0];
4611
- if (!writeFunction) return true;
4612
- return isFunctionSynchronouslyInvokedBefore(writeFunction, referenceNode, scopes);
4613
- });
4614
- //#endregion
4615
- //#region src/plugin/utils/get-order-independent-local-function.ts
4616
- const COMMUTATIVE_COMPOUND_ASSIGNMENT_OPERATORS = new Set([
4617
- "+=",
4618
- "-=",
4619
- "*=",
4620
- "/=",
4621
- "%=",
4622
- "&=",
4623
- "^=",
4624
- "|="
4625
- ]);
4626
- const isPureParameterExpression = (expression, parameterNames) => {
4627
- const unwrappedExpression = stripParenExpression(expression);
4628
- if (isNodeOfType(unwrappedExpression, "Literal")) return true;
4629
- if (isNodeOfType(unwrappedExpression, "Identifier")) return parameterNames.has(unwrappedExpression.name);
4630
- if (isNodeOfType(unwrappedExpression, "BinaryExpression") || isNodeOfType(unwrappedExpression, "LogicalExpression")) return isPureParameterExpression(unwrappedExpression.left, parameterNames) && isPureParameterExpression(unwrappedExpression.right, parameterNames);
4631
- if (isNodeOfType(unwrappedExpression, "UnaryExpression")) return unwrappedExpression.operator !== "delete" && isPureParameterExpression(unwrappedExpression.argument, parameterNames);
4632
- if (isNodeOfType(unwrappedExpression, "ConditionalExpression")) return isPureParameterExpression(unwrappedExpression.test, parameterNames) && isPureParameterExpression(unwrappedExpression.consequent, parameterNames) && isPureParameterExpression(unwrappedExpression.alternate, parameterNames);
4633
- if (isNodeOfType(unwrappedExpression, "TemplateLiteral")) return unwrappedExpression.expressions.every((nestedExpression) => isPureParameterExpression(nestedExpression, parameterNames));
4634
- return false;
4635
- };
4636
- const isOrderIndependentPromiseResolveCall = (expression, parameterNames, scopes) => {
4637
- const unwrappedExpression = stripParenExpression(expression);
4638
- if (!isNodeOfType(unwrappedExpression, "CallExpression")) return false;
4639
- if (!unwrappedExpression.arguments.every((argument) => !isNodeOfType(argument, "SpreadElement") && isPureParameterExpression(argument, parameterNames))) return false;
4640
- const callee = stripParenExpression(unwrappedExpression.callee);
4641
- if (!isNodeOfType(callee, "MemberExpression")) return false;
4642
- if (getStaticPropertyName(callee) !== "resolve") return false;
4643
- const receiver = stripParenExpression(callee.object);
4644
- return isNodeOfType(receiver, "Identifier") && receiver.name === "Promise" && scopes.isGlobalReference(receiver);
4645
- };
4646
- const isHarmlessPromiseResolveAwait = (statement, parameterNames, scopes) => {
4647
- if (!isNodeOfType(statement, "ExpressionStatement") || !isNodeOfType(statement.expression, "AwaitExpression")) return false;
4648
- return isOrderIndependentPromiseResolveCall(statement.expression.argument, parameterNames, scopes);
4649
- };
4650
- const isCommutativeParameterMutation = (statement, parameterNames) => {
4651
- if (!isNodeOfType(statement, "ExpressionStatement") || !isNodeOfType(statement.expression, "AssignmentExpression") || !COMMUTATIVE_COMPOUND_ASSIGNMENT_OPERATORS.has(statement.expression.operator)) return false;
4652
- const mutationTarget = stripParenExpression(statement.expression.left);
4653
- if (!isNodeOfType(mutationTarget, "MemberExpression")) return false;
4654
- if (getStaticPropertyName(mutationTarget) === null) return false;
4655
- const receiver = stripParenExpression(mutationTarget.object);
4656
- return isNodeOfType(receiver, "Identifier") && parameterNames.has(receiver.name) && isNodeOfType(stripParenExpression(statement.expression.right), "Literal");
4657
- };
4658
- const isOrderIndependentFunction = (functionNode, scopes) => {
4659
- if (!isFunctionLike$2(functionNode)) return false;
4660
- const parameterNames = /* @__PURE__ */ new Set();
4661
- for (const parameter of functionNode.params) {
4662
- if (!isNodeOfType(parameter, "Identifier")) return false;
4663
- parameterNames.add(parameter.name);
4664
- }
4665
- if (!functionNode.async) {
4666
- if (!isNodeOfType(functionNode.body, "BlockStatement")) return isOrderIndependentPromiseResolveCall(functionNode.body, parameterNames, scopes);
4667
- if (functionNode.body.body.length !== 1) return false;
4668
- const [returnStatement] = functionNode.body.body;
4669
- return Boolean(isNodeOfType(returnStatement, "ReturnStatement") && returnStatement.argument && isOrderIndependentPromiseResolveCall(returnStatement.argument, parameterNames, scopes));
4670
- }
4671
- if (!isNodeOfType(functionNode.body, "BlockStatement")) return isPureParameterExpression(functionNode.body, parameterNames);
4672
- const statements = functionNode.body.body;
4673
- for (let statementIndex = 0; statementIndex < statements.length; statementIndex++) {
4674
- const statement = statements[statementIndex];
4675
- const isTerminalStatement = statementIndex === statements.length - 1;
4676
- if (isHarmlessPromiseResolveAwait(statement, parameterNames, scopes)) continue;
4677
- if (isNodeOfType(statement, "ExpressionStatement") && isPureParameterExpression(statement.expression, parameterNames)) continue;
4678
- if (isCommutativeParameterMutation(statement, parameterNames)) return isTerminalStatement;
4679
- if (!isNodeOfType(statement, "ReturnStatement") || !isTerminalStatement) return false;
4680
- return !statement.argument || isPureParameterExpression(statement.argument, parameterNames) || isOrderIndependentPromiseResolveCall(statement.argument, parameterNames, scopes);
4681
- }
4682
- return true;
4683
- };
4684
- const getObjectPropertyName = (property) => {
4685
- if (!isNodeOfType(property, "Property")) return null;
4686
- return getStaticPropertyKeyName(property, { allowComputedString: true });
4687
- };
4688
- const resolveOrderIndependentObjectPropertyFunction = (objectExpression, propertyName, callExpression, scopes, visitedSymbolIds) => {
4689
- const unwrappedObject = stripParenExpression(objectExpression);
4690
- if (isNodeOfType(unwrappedObject, "Identifier")) {
4691
- const symbol = scopes.symbolFor(unwrappedObject);
4692
- if (!symbol || symbol.kind !== "const" || !symbol.initializer || visitedSymbolIds.has(symbol.id) || hasSymbolWriteBefore(symbol, callExpression, scopes) || hasPossibleStaticPropertyMutationOrEscape(unwrappedObject, propertyName, scopes)) return null;
4693
- visitedSymbolIds.add(symbol.id);
4694
- return resolveOrderIndependentObjectPropertyFunction(symbol.initializer, propertyName, callExpression, scopes, visitedSymbolIds);
4695
- }
4696
- if (!isNodeOfType(unwrappedObject, "ObjectExpression")) return null;
4697
- let matchingProperty = null;
4698
- for (const property of unwrappedObject.properties) {
4699
- if (!isNodeOfType(property, "Property")) return null;
4700
- if (property.kind !== "init") return null;
4701
- const candidatePropertyName = getObjectPropertyName(property);
4702
- if (candidatePropertyName === null) return null;
4703
- if (candidatePropertyName === propertyName) matchingProperty = property;
4704
- }
4705
- if (!matchingProperty || !isNodeOfType(matchingProperty, "Property")) return null;
4706
- const propertyValue = stripParenExpression(matchingProperty.value);
4707
- if (isFunctionLike$2(propertyValue)) return isOrderIndependentFunction(propertyValue, scopes) ? propertyValue : null;
4708
- return resolveOrderIndependentLocalFunction(propertyValue, callExpression, scopes, visitedSymbolIds);
4709
- };
4710
- const resolveOrderIndependentLocalFunction = (callee, callExpression, scopes, visitedSymbolIds) => {
4711
- const unwrappedCallee = stripParenExpression(callee);
4712
- if (isNodeOfType(unwrappedCallee, "MemberExpression")) {
4713
- const propertyName = getStaticPropertyName(unwrappedCallee);
4714
- if (propertyName === null) return null;
4715
- return resolveOrderIndependentObjectPropertyFunction(stripParenExpression(unwrappedCallee.object), propertyName, callExpression, scopes, visitedSymbolIds);
4716
- }
4717
- if (!isNodeOfType(unwrappedCallee, "Identifier")) return null;
4718
- const symbol = scopes.symbolFor(unwrappedCallee);
4719
- if (!symbol || visitedSymbolIds.has(symbol.id) || hasSymbolWriteBefore(symbol, callExpression, scopes)) return null;
4720
- visitedSymbolIds.add(symbol.id);
4721
- if (!symbol.initializer) return null;
4722
- const initializer = stripParenExpression(symbol.initializer);
4723
- const destructuredPropertyName = getDestructuredBindingPropertyName(symbol.bindingIdentifier);
4724
- if (destructuredPropertyName !== null) return resolveOrderIndependentObjectPropertyFunction(initializer, destructuredPropertyName, callExpression, scopes, visitedSymbolIds);
4725
- if (isFunctionLike$2(initializer)) return isOrderIndependentFunction(initializer, scopes) ? initializer : null;
4726
- if (symbol.kind !== "const") return null;
4727
- return resolveOrderIndependentLocalFunction(initializer, callExpression, scopes, visitedSymbolIds);
4728
- };
4729
- const getOrderIndependentLocalFunction = (callExpression, scopes) => {
4730
- const unwrappedCall = stripParenExpression(callExpression);
4731
- if (!isNodeOfType(unwrappedCall, "CallExpression")) return null;
4732
- if (hasPossibleStaticMemberCallWrite(unwrappedCall, scopes)) return null;
4733
- return resolveOrderIndependentLocalFunction(unwrappedCall.callee, unwrappedCall, scopes, /* @__PURE__ */ new Set());
4734
- };
4735
- //#endregion
4736
4317
  //#region src/plugin/utils/is-inline-function-expression.ts
4737
4318
  /**
4738
4319
  * Type-guard for the two "inline function expression" ESTree forms:
@@ -4766,15 +4347,13 @@ const isIntentionalSequencingCallee = (callee) => {
4766
4347
  if (isNodeOfType(callee, "MemberExpression") && isNodeOfType(callee.property, "Identifier")) return INTENTIONAL_SEQUENCING_CALLEE_NAMES.has(callee.property.name);
4767
4348
  return false;
4768
4349
  };
4769
- const isAwaitingSleepLikeCall = (awaitNode, context) => {
4350
+ const isAwaitingSleepLikeCall = (awaitNode) => {
4770
4351
  if (!isNodeOfType(awaitNode, "AwaitExpression")) return false;
4771
4352
  const argument = awaitNode.argument;
4772
4353
  if (!argument) return false;
4773
4354
  if (!isNodeOfType(argument, "CallExpression")) return false;
4774
- if (getOrderIndependentLocalFunction(argument, context.scopes) !== null) return false;
4775
4355
  return isIntentionalSequencingCallee(argument.callee);
4776
4356
  };
4777
- const isAwaitingPossiblyMutatedMemberCall = (awaitNode, context) => isNodeOfType(awaitNode, "AwaitExpression") && Boolean(awaitNode.argument) && hasPossibleStaticMemberCallWrite(awaitNode.argument, context.scopes);
4778
4357
  const PROMISE_CONCURRENCY_METHODS = new Set([
4779
4358
  "all",
4780
4359
  "allSettled",
@@ -4817,7 +4396,7 @@ const isAwaitingManualPromiseWait = (awaitNode) => {
4817
4396
  });
4818
4397
  return isWaitLike;
4819
4398
  };
4820
- const isIntentionallySequentialAwait = (awaitNode, context) => isAwaitingPossiblyMutatedMemberCall(awaitNode, context) || isAwaitingSleepLikeCall(awaitNode, context) || isAwaitingPromiseConcurrencyCall(awaitNode) || isAwaitingManualPromiseWait(awaitNode);
4399
+ const isIntentionallySequentialAwait = (awaitNode) => isAwaitingSleepLikeCall(awaitNode) || isAwaitingPromiseConcurrencyCall(awaitNode) || isAwaitingManualPromiseWait(awaitNode);
4821
4400
  const collectPatternIdentifiers = (pattern, target) => {
4822
4401
  if (isNodeOfType(pattern, "Identifier")) target.add(pattern.name);
4823
4402
  else if (isNodeOfType(pattern, "ObjectPattern")) {
@@ -5008,12 +4587,12 @@ const getLoopLabelName = (loopNode) => {
5008
4587
  if (isNodeOfType(parent, "LabeledStatement") && isNodeOfType(parent.label, "Identifier")) return parent.label.name;
5009
4588
  return null;
5010
4589
  };
5011
- const loopBodyHasIntentionallySequentialAwait = (block, context) => {
4590
+ const loopBodyHasIntentionallySequentialAwait = (block) => {
5012
4591
  let foundIntentional = false;
5013
4592
  walkAst(block, (child) => {
5014
4593
  if (foundIntentional) return false;
5015
4594
  if (isInlineFunctionExpression(child) || isNodeOfType(child, "FunctionDeclaration")) return false;
5016
- if (isNodeOfType(child, "AwaitExpression") && isIntentionallySequentialAwait(child, context)) {
4595
+ if (isNodeOfType(child, "AwaitExpression") && isIntentionallySequentialAwait(child)) {
5017
4596
  foundIntentional = true;
5018
4597
  return false;
5019
4598
  }
@@ -5118,7 +4697,7 @@ const asyncAwaitInLoop = defineRule({
5118
4697
  const inspectLoop = (loopNode, label) => {
5119
4698
  const loopBody = loopNode.body;
5120
4699
  if (!loopBody) return;
5121
- if (loopBodyHasIntentionallySequentialAwait(loopBody, context)) return;
4700
+ if (loopBodyHasIntentionallySequentialAwait(loopBody)) return;
5122
4701
  if ((isNodeOfType(loopNode, "WhileStatement") || isNodeOfType(loopNode, "DoWhileStatement")) && isLoopTestDependentOnBodyState(loopNode.test, loopBody)) return;
5123
4702
  if (hasLoopCarriedDependency(loopBody)) return;
5124
4703
  if (loopBodyHasAwaitDependentEarlyExit(loopBody, getLoopLabelName(loopNode))) return;
@@ -5378,7 +4957,7 @@ const guardConsequentPerformsSideEffects = (consequent) => {
5378
4957
  });
5379
4958
  return performsSideEffects;
5380
4959
  };
5381
- const findEnclosingFunction = (node) => {
4960
+ const findEnclosingFunction$1 = (node) => {
5382
4961
  let ancestor = node.parent;
5383
4962
  while (ancestor) {
5384
4963
  if (isFunctionLike$2(ancestor)) return ancestor;
@@ -5391,7 +4970,7 @@ const guardTestReadsReassignedLocal = (test, guardStatement) => {
5391
4970
  const testIdentifierNames = /* @__PURE__ */ new Set();
5392
4971
  collectReferenceIdentifierNames(test, testIdentifierNames);
5393
4972
  if (testIdentifierNames.size === 0) return false;
5394
- const enclosingFunction = findEnclosingFunction(guardStatement);
4973
+ const enclosingFunction = findEnclosingFunction$1(guardStatement);
5395
4974
  if (!enclosingFunction || !isFunctionLike$2(enclosingFunction) || !enclosingFunction.body) return false;
5396
4975
  let readsReassignedLocal = false;
5397
4976
  walkAst(enclosingFunction.body, (child) => {
@@ -5562,36 +5141,19 @@ const isIntentionalSequencingAwait = (awaitedCall) => {
5562
5141
  return getCalleeIdentifierTrail(awaitedCall).some((name) => INTENTIONAL_SEQUENCING_CALLEE_NAMES.has(name));
5563
5142
  };
5564
5143
  const isBareExpressionAwait = (statement) => isNodeOfType(statement, "ExpressionStatement") && isNodeOfType(statement.expression, "AwaitExpression");
5565
- const hasOrderIndependentBareAwaitArguments = (callExpression) => {
5566
- const unwrappedCallExpression = stripParenExpression(callExpression);
5567
- if (!isNodeOfType(unwrappedCallExpression, "CallExpression")) return false;
5568
- return unwrappedCallExpression.arguments.every((argument) => {
5569
- if (isNodeOfType(argument, "SpreadElement")) return false;
5570
- const unwrappedArgument = stripParenExpression(argument);
5571
- return isNodeOfType(unwrappedArgument, "Identifier") || isNodeOfType(unwrappedArgument, "Literal");
5572
- });
5573
- };
5574
5144
  const isNonCallAwait = (statement) => {
5575
5145
  const awaitedExpression = getAwaitedCall(statement);
5576
5146
  if (!awaitedExpression) return false;
5577
5147
  const stripped = stripParenExpression(awaitedExpression);
5578
5148
  return !isNodeOfType(stripped, "CallExpression") && !isNodeOfType(stripped, "NewExpression") && !isNodeOfType(stripped, "ImportExpression");
5579
5149
  };
5580
- const sequenceContainsSerializationSignal = (statements, context) => {
5581
- let bareAwaitFunction = null;
5150
+ const sequenceContainsSerializationSignal = (statements) => {
5582
5151
  for (const statement of statements) {
5152
+ if (isBareExpressionAwait(statement)) return true;
5583
5153
  if (isNonCallAwait(statement)) return true;
5584
5154
  const awaitedCall = getAwaitedCall(statement);
5585
- if (awaitedCall && hasPossibleStaticMemberCallWrite(awaitedCall, context.scopes)) return true;
5586
- const orderIndependentFunction = awaitedCall ? getOrderIndependentLocalFunction(awaitedCall, context.scopes) : null;
5587
- if (isBareExpressionAwait(statement)) {
5588
- if (orderIndependentFunction === null) return true;
5589
- if (!awaitedCall || !hasOrderIndependentBareAwaitArguments(awaitedCall)) return true;
5590
- if (bareAwaitFunction !== null && bareAwaitFunction !== orderIndependentFunction) return true;
5591
- bareAwaitFunction = orderIndependentFunction;
5592
- }
5593
5155
  if (isOrderedUiFlowAwait(awaitedCall)) return true;
5594
- if (isIntentionalSequencingAwait(awaitedCall) && orderIndependentFunction === null) return true;
5156
+ if (isIntentionalSequencingAwait(awaitedCall)) return true;
5595
5157
  }
5596
5158
  return false;
5597
5159
  };
@@ -5649,7 +5211,7 @@ const asyncParallel = defineRule({
5649
5211
  const consecutiveAwaitStatements = [];
5650
5212
  const flushConsecutiveAwaits = () => {
5651
5213
  if (consecutiveAwaitStatements.length >= 3) {
5652
- if (!sequenceContainsSerializationSignal(consecutiveAwaitStatements, context)) reportIfIndependent(consecutiveAwaitStatements, context);
5214
+ if (!sequenceContainsSerializationSignal(consecutiveAwaitStatements)) reportIfIndependent(consecutiveAwaitStatements, context);
5653
5215
  }
5654
5216
  consecutiveAwaitStatements.length = 0;
5655
5217
  };
@@ -6427,6 +5989,23 @@ const checkedRequiresOnchangeOrReadonly = defineRule({
6427
5989
  }
6428
5990
  });
6429
5991
  //#endregion
5992
+ //#region src/plugin/utils/get-static-property-key-name.ts
5993
+ const getStaticPropertyKeyName = (node, options = {}) => {
5994
+ if (!isNodeOfType(node, "Property") && !isNodeOfType(node, "MethodDefinition") && !isNodeOfType(node, "MemberExpression")) return null;
5995
+ const key = isNodeOfType(node, "MemberExpression") ? node.property : node.key;
5996
+ if (node.computed) {
5997
+ if (options.allowComputedString && isNodeOfType(key, "Literal") && typeof key.value === "string") return key.value;
5998
+ if (options.allowComputedString && isNodeOfType(key, "TemplateLiteral") && key.expressions.length === 0) return key.quasis[0]?.value.cooked ?? key.quasis[0]?.value.raw ?? null;
5999
+ return null;
6000
+ }
6001
+ if (isNodeOfType(key, "Identifier")) return key.name;
6002
+ if (isNodeOfType(key, "Literal")) {
6003
+ if (typeof key.value === "string") return key.value;
6004
+ if (options.stringifyNonStringLiterals) return String(key.value);
6005
+ }
6006
+ return null;
6007
+ };
6008
+ //#endregion
6430
6009
  //#region src/plugin/utils/are-expressions-structurally-equal.ts
6431
6010
  const areExpressionsStructurallyEqual = (a, b) => {
6432
6011
  if (!a || !b) return a === b;
@@ -7110,6 +6689,15 @@ const getDirectConstInitializer = (symbol) => {
7110
6689
  return symbol.initializer;
7111
6690
  };
7112
6691
  //#endregion
6692
+ //#region src/plugin/utils/get-static-property-name.ts
6693
+ const getStaticPropertyName = (memberExpression) => {
6694
+ const property = memberExpression.property;
6695
+ if (!memberExpression.computed && isNodeOfType(property, "Identifier")) return property.name;
6696
+ if (memberExpression.computed && isNodeOfType(property, "Literal")) return typeof property.value === "string" ? property.value : null;
6697
+ if (memberExpression.computed && isNodeOfType(property, "TemplateLiteral") && property.expressions.length === 0) return property.quasis[0]?.value.cooked ?? property.quasis[0]?.value.raw ?? null;
6698
+ return null;
6699
+ };
6700
+ //#endregion
7113
6701
  //#region src/plugin/utils/get-range-start.ts
7114
6702
  const getRangeStart = (node) => {
7115
6703
  const rangeStart = node.range?.[0];
@@ -7505,6 +7093,16 @@ const collectFunctionReturnStatements = (functionNode) => {
7505
7093
  return returnStatements;
7506
7094
  };
7507
7095
  //#endregion
7096
+ //#region src/plugin/utils/find-enclosing-function.ts
7097
+ const findEnclosingFunction = (node) => {
7098
+ let cursor = node.parent;
7099
+ while (cursor) {
7100
+ if (isFunctionLike$2(cursor)) return cursor;
7101
+ cursor = cursor.parent ?? null;
7102
+ }
7103
+ return null;
7104
+ };
7105
+ //#endregion
7508
7106
  //#region src/plugin/utils/statement-always-exits.ts
7509
7107
  const statementAlwaysExits = (statement) => {
7510
7108
  if (isNodeOfType(statement, "ReturnStatement") || isNodeOfType(statement, "ThrowStatement")) return true;
@@ -7550,8 +7148,8 @@ const applyDefinitions = (incomingDefinitions, definitions) => {
7550
7148
  const collectPossibleAssignedExpressions = (symbol, referenceNode, controlFlow) => {
7551
7149
  if (!REASSIGNABLE_BINDING_KINDS.has(symbol.kind)) return symbol.initializer ? [symbol.initializer] : [];
7552
7150
  if (!controlFlow) return [];
7553
- const referenceFunction = findEnclosingFunction$1(referenceNode);
7554
- if (findEnclosingFunction$1(symbol.bindingIdentifier) !== referenceFunction) return [];
7151
+ const referenceFunction = findEnclosingFunction(referenceNode);
7152
+ if (findEnclosingFunction(symbol.bindingIdentifier) !== referenceFunction) return [];
7555
7153
  if (!referenceFunction) return [];
7556
7154
  const functionControlFlow = controlFlow.cfgFor(referenceFunction);
7557
7155
  if (!functionControlFlow) return [];
@@ -7575,7 +7173,7 @@ const collectPossibleAssignedExpressions = (symbol, referenceNode, controlFlow)
7575
7173
  if (symbol.initializer) addDefinition(symbol.initializer, symbol.bindingIdentifier, bindingPosition);
7576
7174
  for (const reference of symbol.references) {
7577
7175
  const writePosition = getRangeStart(reference.identifier);
7578
- if (reference.flag === "read" || findEnclosingFunction$1(reference.identifier) !== referenceFunction || writePosition === null || writePosition >= referencePosition) continue;
7176
+ if (reference.flag === "read" || findEnclosingFunction(reference.identifier) !== referenceFunction || writePosition === null || writePosition >= referencePosition) continue;
7579
7177
  const assignedExpression = getAssignedExpressionForWrite(reference.identifier);
7580
7178
  if (!assignedExpression) continue;
7581
7179
  addDefinition(assignedExpression, reference.identifier, writePosition);
@@ -9247,7 +8845,6 @@ const HTML_FOR_ATTRIBUTE = "htmlFor";
9247
8845
  const LABEL_ELEMENT = "label";
9248
8846
  const LABEL_COMPONENT_NAME = "Label";
9249
8847
  const POLYMORPHIC_COMPONENT_PROP = "component";
9250
- const TITLE_ATTRIBUTE = "title";
9251
8848
  const WRAPPER_LABEL_PROP = "label";
9252
8849
  const SELECT_ELEMENT = "select";
9253
8850
  const DEFAULT_DEPTH = 5;
@@ -9293,96 +8890,6 @@ const hasNonEmptyPropValue = (attribute) => {
9293
8890
  }
9294
8891
  return true;
9295
8892
  };
9296
- const getLastJsxPropIgnoreCase = (attributes, targetProp) => {
9297
- const targetPropLower = targetProp.toLowerCase();
9298
- for (let attributeIndex = attributes.length - 1; attributeIndex >= 0; attributeIndex -= 1) {
9299
- const attribute = attributes[attributeIndex];
9300
- if (!attribute || !isNodeOfType(attribute, "JSXAttribute")) continue;
9301
- if (getJsxAttributeName(attribute.name)?.toLowerCase() === targetPropLower) return attribute;
9302
- }
9303
- };
9304
- const getStaticNativeTitleArrayValue = (expression, scopes) => {
9305
- const elementValues = [];
9306
- for (const rawElement of expression.elements) {
9307
- if (rawElement === null) {
9308
- elementValues.push("");
9309
- continue;
9310
- }
9311
- if (isNodeOfType(rawElement, "SpreadElement")) return null;
9312
- const element = stripParenExpression(rawElement);
9313
- if (isNodeOfType(element, "Literal")) {
9314
- elementValues.push(element.value === null ? "" : String(element.value));
9315
- continue;
9316
- }
9317
- if (isNodeOfType(element, "TemplateLiteral")) {
9318
- const staticValue = getStaticTemplateLiteralValue(element);
9319
- if (staticValue === null) return null;
9320
- elementValues.push(staticValue);
9321
- continue;
9322
- }
9323
- if (isNodeOfType(element, "Identifier") && element.name === "undefined" && scopes.isGlobalReference(element) || isNodeOfType(element, "UnaryExpression") && element.operator === "void") {
9324
- elementValues.push("");
9325
- continue;
9326
- }
9327
- if (isNodeOfType(element, "ArrayExpression")) {
9328
- const nestedValue = getStaticNativeTitleArrayValue(element, scopes);
9329
- if (nestedValue === null) return null;
9330
- elementValues.push(nestedValue);
9331
- continue;
9332
- }
9333
- return null;
9334
- }
9335
- return elementValues.join(",");
9336
- };
9337
- const isGlobalSymbolExpression = (expression, scopes) => {
9338
- if (isNodeOfType(expression, "Identifier")) return expression.name === "Symbol" && scopes.isGlobalReference(expression);
9339
- if (!isNodeOfType(expression, "MemberExpression")) return false;
9340
- const object = stripParenExpression(expression.object);
9341
- return isNodeOfType(object, "Identifier") && object.name === "Symbol" && scopes.isGlobalReference(object);
9342
- };
9343
- const hasNonEmptyNativeTitleExpression = (rawExpression, scopes) => {
9344
- const expression = stripParenExpression(rawExpression);
9345
- if (isNodeOfType(expression, "Literal")) {
9346
- if (typeof expression.value === "string") return expression.value.trim().length > 0;
9347
- return expression.value !== null && typeof expression.value !== "boolean";
9348
- }
9349
- if (isNodeOfType(expression, "TemplateLiteral")) {
9350
- const staticValue = getStaticTemplateLiteralValue(expression);
9351
- return staticValue === null || staticValue.trim().length > 0;
9352
- }
9353
- if (isNodeOfType(expression, "Identifier")) return expression.name !== "undefined" || !scopes.isGlobalReference(expression);
9354
- if (isNodeOfType(expression, "UnaryExpression") && expression.operator === "void") return false;
9355
- if (isNodeOfType(expression, "UnaryExpression") && expression.operator === "!") return false;
9356
- if (isNodeOfType(expression, "ArrowFunctionExpression")) return false;
9357
- if (isNodeOfType(expression, "FunctionExpression")) return false;
9358
- if (isNodeOfType(expression, "ClassExpression")) return false;
9359
- if (isNodeOfType(expression, "ArrayExpression")) {
9360
- const staticValue = getStaticNativeTitleArrayValue(expression, scopes);
9361
- return staticValue === null || staticValue.trim().length > 0;
9362
- }
9363
- if (isGlobalSymbolExpression(expression, scopes)) return false;
9364
- if (isNodeOfType(expression, "CallExpression") && isGlobalSymbolExpression(expression.callee, scopes)) return false;
9365
- if (isNodeOfType(expression, "ConditionalExpression")) return hasNonEmptyNativeTitleExpression(expression.consequent, scopes) && hasNonEmptyNativeTitleExpression(expression.alternate, scopes);
9366
- if (isNodeOfType(expression, "SequenceExpression")) {
9367
- const finalExpression = expression.expressions.at(-1);
9368
- return finalExpression ? hasNonEmptyNativeTitleExpression(finalExpression, scopes) : false;
9369
- }
9370
- if (isNodeOfType(expression, "LogicalExpression")) {
9371
- const leftExpression = stripParenExpression(expression.left);
9372
- if (!isNodeOfType(leftExpression, "Literal")) return expression.operator !== "&&";
9373
- if (expression.operator === "??") return hasNonEmptyNativeTitleExpression(leftExpression.value === null ? expression.right : leftExpression, scopes);
9374
- const leftValueIsTruthy = Boolean(leftExpression.value);
9375
- if (expression.operator === "&&") return hasNonEmptyNativeTitleExpression(leftValueIsTruthy ? expression.right : leftExpression, scopes);
9376
- return hasNonEmptyNativeTitleExpression(leftValueIsTruthy ? leftExpression : expression.right, scopes);
9377
- }
9378
- return true;
9379
- };
9380
- const hasNonEmptyNativeTitle = (attribute, scopes) => {
9381
- if (!attribute?.value) return false;
9382
- if (isNodeOfType(attribute.value, "Literal")) return typeof attribute.value.value === "string" && attribute.value.value.trim().length > 0;
9383
- if (isNodeOfType(attribute.value, "JSXExpressionContainer")) return hasNonEmptyNativeTitleExpression(attribute.value.expression, scopes);
9384
- return true;
9385
- };
9386
8893
  const toAttributeMatchKey = (kind, value) => {
9387
8894
  const trimmedValue = value.trim();
9388
8895
  return trimmedValue.length > 0 ? `${kind}:${trimmedValue}` : null;
@@ -9639,7 +9146,6 @@ const controlHasAssociatedLabel = defineRule({
9639
9146
  if (typeValue === "submit" || typeValue === "reset") return;
9640
9147
  if (typeValue === "button" && hasNonEmptyPropValue(hasJsxPropIgnoreCase(opening.attributes, "value"))) return;
9641
9148
  }
9642
- if (isDomElement && hasNonEmptyNativeTitle(getLastJsxPropIgnoreCase(opening.attributes, TITLE_ATTRIBUTE), context.scopes)) return;
9643
9149
  if (supportsPlaceholderNameFallback(tagName, opening) && hasNonEmptyPropValue(hasJsxPropIgnoreCase(opening.attributes, "placeholder"))) return;
9644
9150
  if (hasLabellingProp(opening.attributes, settings.labelAttributes)) return;
9645
9151
  if (isInsideJsxAttribute(node)) return;
@@ -11589,7 +11095,7 @@ const componentOrHookDisplayNameForFunction = (functionNode) => {
11589
11095
  //#endregion
11590
11096
  //#region src/plugin/utils/enclosing-component-or-hook-name.ts
11591
11097
  const enclosingComponentOrHookName = (node) => {
11592
- const functionNode = findEnclosingFunction$1(node);
11098
+ const functionNode = findEnclosingFunction(node);
11593
11099
  return functionNode ? componentOrHookDisplayNameForFunction(functionNode) : null;
11594
11100
  };
11595
11101
  //#endregion
@@ -11646,11 +11152,11 @@ const executesDuringRender = (functionNode, scopes) => {
11646
11152
  //#endregion
11647
11153
  //#region src/plugin/utils/find-render-phase-component-or-hook.ts
11648
11154
  const findRenderPhaseComponentOrHook = (node, scopes) => {
11649
- let functionNode = findEnclosingFunction$1(node);
11155
+ let functionNode = findEnclosingFunction(node);
11650
11156
  while (functionNode) {
11651
11157
  if (componentOrHookDisplayNameForFunction(functionNode)) return functionNode;
11652
11158
  if (!executesDuringRender(functionNode, scopes)) return null;
11653
- functionNode = findEnclosingFunction$1(functionNode);
11159
+ functionNode = findEnclosingFunction(functionNode);
11654
11160
  }
11655
11161
  return null;
11656
11162
  };
@@ -11899,13 +11405,13 @@ const findSubscribeLikeUsages = (callback, context) => {
11899
11405
  };
11900
11406
  const doMatchingNodesCoverEveryPathAfterUsage = (usageNode, matchingNodes, context) => {
11901
11407
  let pathAnchor = usageNode;
11902
- let pathOwner = findEnclosingFunction$1(pathAnchor);
11408
+ let pathOwner = findEnclosingFunction(pathAnchor);
11903
11409
  while (pathOwner && isSynchronousIteratorCallback(pathOwner)) {
11904
11410
  if (matchingNodes.length > 0 && matchingNodes.every((matchingNode) => context.cfg.enclosingFunction(matchingNode) === pathOwner)) break;
11905
11411
  const iteratorCall = pathOwner.parent;
11906
11412
  if (!isNodeOfType(iteratorCall, "CallExpression")) break;
11907
11413
  pathAnchor = iteratorCall;
11908
- pathOwner = findEnclosingFunction$1(pathAnchor);
11414
+ pathOwner = findEnclosingFunction(pathAnchor);
11909
11415
  }
11910
11416
  const owner = context.cfg.enclosingFunction(pathAnchor);
11911
11417
  if (!owner) return false;
@@ -12134,7 +11640,7 @@ const findCollectionMappingCall = (callbackNode) => {
12134
11640
  return callee.property.name === "map" && callNode.arguments?.[0] === callbackNode ? callNode : null;
12135
11641
  };
12136
11642
  const findMappedResourceCollectionKey = (resourceNode, context) => {
12137
- const callbackNode = findEnclosingFunction$1(resourceNode);
11643
+ const callbackNode = findEnclosingFunction(resourceNode);
12138
11644
  if (!callbackNode || !isNodeOfType(callbackNode, "ArrowFunctionExpression") && !isNodeOfType(callbackNode, "FunctionExpression")) return null;
12139
11645
  const mappingCall = findCollectionMappingCall(callbackNode);
12140
11646
  if (!mappingCall) return null;
@@ -12245,10 +11751,10 @@ const findSingleDirectInvocation = (functionNode, caller, context) => {
12245
11751
  });
12246
11752
  if (invocationCalls.length !== 1) return null;
12247
11753
  const invocationCall = invocationCalls[0];
12248
- return findEnclosingFunction$1(invocationCall) === caller && isNodeReachableWithinFunction(invocationCall, context) ? invocationCall : null;
11754
+ return findEnclosingFunction(invocationCall) === caller && isNodeReachableWithinFunction(invocationCall, context) ? invocationCall : null;
12249
11755
  };
12250
11756
  const resolveCleanupPathAnchor = (usageNode, effectCallback, context) => {
12251
- const usageFunction = findEnclosingFunction$1(usageNode);
11757
+ const usageFunction = findEnclosingFunction(usageNode);
12252
11758
  if (!usageFunction || usageFunction === effectCallback) return usageNode;
12253
11759
  return findSingleDirectInvocation(usageFunction, effectCallback, context) ?? usageNode;
12254
11760
  };
@@ -12263,7 +11769,7 @@ const resolveSingleAssignedCleanupFunction = (expression, usage, context) => {
12263
11769
  const assignmentReference = assignmentReferences[0];
12264
11770
  const assignmentTarget = findTransparentExpressionRoot(assignmentReference.identifier);
12265
11771
  const assignmentNode = assignmentTarget.parent;
12266
- if (!isNodeOfType(assignmentNode, "AssignmentExpression") || assignmentNode.operator !== "=" || assignmentNode.left !== assignmentTarget || findEnclosingFunction$1(assignmentNode) !== findEnclosingFunction$1(usage.node) || !doMatchingNodesCoverEveryPathAfterUsage(usage.node, [assignmentNode], context)) return null;
11772
+ if (!isNodeOfType(assignmentNode, "AssignmentExpression") || assignmentNode.operator !== "=" || assignmentNode.left !== assignmentTarget || findEnclosingFunction(assignmentNode) !== findEnclosingFunction(usage.node) || !doMatchingNodesCoverEveryPathAfterUsage(usage.node, [assignmentNode], context)) return null;
12267
11773
  const assignedValue = stripParenExpression(assignmentNode.right);
12268
11774
  return isFunctionLike$2(assignedValue) ? assignedValue : null;
12269
11775
  };
@@ -12352,12 +11858,12 @@ const hasRerunReleaseBeforeUsage = (callback, usage, context) => {
12352
11858
  return doMatchingNodesCoverEveryPathFromFunctionEntry(callback, matchingReleaseAnchors, context);
12353
11859
  };
12354
11860
  const hasStableUnmountCleanupForUsage = (callback, usage, context) => {
12355
- const componentFunction = findEnclosingFunction$1(callback);
11861
+ const componentFunction = findEnclosingFunction(callback);
12356
11862
  if (!componentFunction || !isNodeOfType(componentFunction, "ArrowFunctionExpression") && !isNodeOfType(componentFunction, "FunctionExpression") && !isNodeOfType(componentFunction, "FunctionDeclaration")) return false;
12357
11863
  let didFindUnmountCleanup = false;
12358
11864
  walkAst(componentFunction.body, (child) => {
12359
11865
  if (didFindUnmountCleanup) return false;
12360
- if (!isNodeOfType(child, "CallExpression") || findEnclosingFunction$1(child) !== componentFunction) return;
11866
+ if (!isNodeOfType(child, "CallExpression") || findEnclosingFunction(child) !== componentFunction) return;
12361
11867
  if (!isHookCall$2(child, CLEANUP_EFFECT_HOOK_NAMES)) return;
12362
11868
  const dependencyList = child.arguments?.[1];
12363
11869
  if (!isNodeOfType(dependencyList, "ArrayExpression") || dependencyList.elements.length > 0) return;
@@ -12453,7 +11959,7 @@ const deferredUsageWritesGuardBeforeUsage = (callback, usageNode, guardState, co
12453
11959
  return didWriteGuard;
12454
11960
  };
12455
11961
  const hasGuardedDeferredCleanup = (callback, usage, cleanupReturns, context) => {
12456
- const usageFunction = findEnclosingFunction$1(usage.node);
11962
+ const usageFunction = findEnclosingFunction(usage.node);
12457
11963
  const promiseChainCall = usageFunction ? getPromiseChainCallForCallback(usageFunction) : null;
12458
11964
  if (usage.handleKey === null || !usageFunction || usageFunction === callback || !promiseChainCall || !collectEffectInvokedFunctions(callback).has(usageFunction) || !doMatchingNodesCoverEveryPathAfterUsage(promiseChainCall, cleanupReturns, context)) return false;
12459
11965
  return collectDeferredUsageGuardStates(usageFunction, usage.node, context).some((guardState) => !deferredUsageWritesGuardBeforeUsage(usageFunction, usage.node, guardState, context) && cleanupReturns.every((cleanupReturn) => cleanupReturnInvalidatesGuard(cleanupReturn, guardState, context)));
@@ -12461,7 +11967,7 @@ const hasGuardedDeferredCleanup = (callback, usage, cleanupReturns, context) =>
12461
11967
  const effectHasCleanupForUsage = (callback, usage, context) => {
12462
11968
  if (!isNodeOfType(callback, "ArrowFunctionExpression") && !isNodeOfType(callback, "FunctionExpression")) return false;
12463
11969
  if (callback.async) return false;
12464
- if (usage.kind === "subscribe" && findEnclosingFunction$1(usage.node) === callback && doesResourceResultEscape(usage.node, true) && isCleanupReturningSubscribeLikeCallExpression(usage.node)) return true;
11970
+ if (usage.kind === "subscribe" && findEnclosingFunction(usage.node) === callback && doesResourceResultEscape(usage.node, true) && isCleanupReturningSubscribeLikeCallExpression(usage.node)) return true;
12465
11971
  if (!isNodeOfType(callback.body, "BlockStatement")) return callback.body === usage.node && isCleanupReturningSubscribeLikeCallExpression(callback.body);
12466
11972
  const matchingCleanupReturns = [];
12467
11973
  walkInsideStatementBlocks(callback.body, (child) => {
@@ -12630,7 +12136,7 @@ const isReturnedEffectCleanupFunction = (functionNode) => {
12630
12136
  parentNode = currentNode.parent;
12631
12137
  }
12632
12138
  if (!isNodeOfType(parentNode, "ReturnStatement") || parentNode.argument !== currentNode) return false;
12633
- const effectCallback = findEnclosingFunction$1(parentNode);
12139
+ const effectCallback = findEnclosingFunction(parentNode);
12634
12140
  const effectCall = effectCallback?.parent;
12635
12141
  return Boolean(effectCallback && isNodeOfType(effectCall, "CallExpression") && isHookCall$2(effectCall, CLEANUP_EFFECT_HOOK_NAMES));
12636
12142
  };
@@ -12640,13 +12146,13 @@ const isPotentiallyReachableFunction = (functionNode, context) => {
12640
12146
  if (!bindingIdentifier) return false;
12641
12147
  const symbol = context.scopes.symbolFor(bindingIdentifier);
12642
12148
  if (!symbol) return false;
12643
- return symbol.references.some((reference) => findEnclosingFunction$1(reference.identifier) !== functionNode);
12149
+ return symbol.references.some((reference) => findEnclosingFunction(reference.identifier) !== functionNode);
12644
12150
  };
12645
12151
  const isReleaseReachableForUsage = (releaseNode, usage, context) => {
12646
12152
  if (!isNodeReachableWithinFunction(releaseNode, context)) return false;
12647
- const releaseFunction = findEnclosingFunction$1(releaseNode);
12153
+ const releaseFunction = findEnclosingFunction(releaseNode);
12648
12154
  if (!releaseFunction) return true;
12649
- if (releaseFunction === findEnclosingFunction$1(usage.node)) return true;
12155
+ if (releaseFunction === findEnclosingFunction(usage.node)) return true;
12650
12156
  return isPotentiallyReachableFunction(releaseFunction, context);
12651
12157
  };
12652
12158
  const fileContainsReleaseForUsage = (usage, context) => {
@@ -12829,10 +12335,10 @@ const cleanupFunctionReleasesRefOwnedUsage = (cleanupFunction, componentFunction
12829
12335
  }
12830
12336
  if (assignedKey !== storage.refCurrentKey) return;
12831
12337
  const assignedValue = stripParenExpression(child.right);
12832
- if (isNodeOfType(assignedValue, "Literal") && assignedValue.value === null && findEnclosingFunction$1(child) === cleanupFunction) return;
12338
+ if (isNodeOfType(assignedValue, "Literal") && assignedValue.value === null && findEnclosingFunction(child) === cleanupFunction) return;
12833
12339
  const assignedSessionProperties = (isNodeOfType(assignedValue, "ObjectExpression") ? assignedValue : null)?.properties ?? [];
12834
12340
  const storesMatchingHandler = assignedSessionProperties.every((property) => isNodeOfType(property, "Property")) && assignedSessionProperties.some((property) => isNodeOfType(property, "Property") && `${storage.refCurrentKey}.${getStaticPropertyKeyName(property) ?? ""}` === storage.handlerKey && resolveExpressionKey(property.value, context) === usage.handlerKey);
12835
- if (findEnclosingFunction$1(child) !== retainedFunction || !storesMatchingHandler) {
12341
+ if (findEnclosingFunction(child) !== retainedFunction || !storesMatchingHandler) {
12836
12342
  hasUnsafeRefWrite = true;
12837
12343
  return false;
12838
12344
  }
@@ -12853,12 +12359,12 @@ const effectReturnsRefOwnedCleanup = (effectCallback, componentFunction, retaine
12853
12359
  return doMatchingNodesCoverEveryPathFromFunctionEntry(effectCallback, matchingReturns, context);
12854
12360
  };
12855
12361
  const hasGuaranteedRefOwnedUnmountCleanup = (retainedFunction, usage, context) => {
12856
- const componentFunction = findEnclosingFunction$1(retainedFunction);
12362
+ const componentFunction = findEnclosingFunction(retainedFunction);
12857
12363
  if (!componentFunction || !isFunctionLike$2(componentFunction)) return false;
12858
12364
  let didFindCleanupEffect = false;
12859
12365
  walkAst(componentFunction.body, (child) => {
12860
12366
  if (didFindCleanupEffect) return false;
12861
- if (!isNodeOfType(child, "CallExpression") || findEnclosingFunction$1(child) !== componentFunction || !isReactApiCall(child, "useEffect", context.scopes)) return;
12367
+ if (!isNodeOfType(child, "CallExpression") || findEnclosingFunction(child) !== componentFunction || !isReactApiCall(child, "useEffect", context.scopes)) return;
12862
12368
  const effectStatement = findTransparentExpressionRoot(child).parent;
12863
12369
  if (!isNodeOfType(effectStatement, "ExpressionStatement") || effectStatement.parent !== componentFunction.body) return;
12864
12370
  const effectCallback = getEffectCallback(child);
@@ -13712,202 +13218,6 @@ const resolveExhaustiveDepsSettings = (settings) => {
13712
13218
  };
13713
13219
  };
13714
13220
  //#endregion
13715
- //#region src/plugin/utils/is-ast-descendant.ts
13716
- /**
13717
- * True when `inner` is `outer` itself or any descendant in the AST
13718
- * `parent` chain. Walks `inner.parent` upward and stops at either a
13719
- * match (`true`) or the chain's root (`false`).
13720
- *
13721
- * Was duplicated byte-identical in:
13722
- * - exhaustive-deps-symbol-stability.ts
13723
- * - semantic/closure-captures.ts
13724
- */
13725
- const isAstDescendant = (inner, outer) => {
13726
- let current = inner;
13727
- while (current) {
13728
- if (current === outer) return true;
13729
- current = current.parent ?? null;
13730
- }
13731
- return false;
13732
- };
13733
- //#endregion
13734
- //#region src/plugin/rules/react-builtins/exhaustive-deps-sole-writer-guard.ts
13735
- const EQUALITY_BINARY_OPERATORS = new Set(["===", "!=="]);
13736
- const getUseStateSetterSymbol = (stateSymbol, scopes) => {
13737
- const declaration = stateSymbol.declarationNode;
13738
- if (!isNodeOfType(declaration, "VariableDeclarator")) return null;
13739
- if (!isNodeOfType(declaration.id, "ArrayPattern")) return null;
13740
- const stateBinding = declaration.id.elements[0];
13741
- const setterBinding = declaration.id.elements[1];
13742
- if (stateBinding !== stateSymbol.bindingIdentifier || !isNodeOfType(setterBinding, "Identifier")) return null;
13743
- const initializer = declaration.init ? stripParenExpression(declaration.init) : null;
13744
- if (!initializer || !isReactApiCall(initializer, "useState", scopes, {
13745
- allowGlobalReactNamespace: true,
13746
- allowUnboundBareCalls: true,
13747
- resolveNamedAliases: true
13748
- })) return null;
13749
- return scopes.symbolFor(setterBinding);
13750
- };
13751
- const getDirectSetterCall = (setterSymbol, callback) => {
13752
- if (setterSymbol.references.length !== 1) return null;
13753
- const setterReference = setterSymbol.references[0];
13754
- if (setterReference.flag !== "read") return null;
13755
- const referenceRoot = findTransparentExpressionRoot(setterReference.identifier);
13756
- const callExpression = referenceRoot.parent;
13757
- if (!isNodeOfType(callExpression, "CallExpression") || callExpression.callee !== referenceRoot || callExpression.arguments.length !== 1 || findEnclosingFunction$1(callExpression) !== callback) return null;
13758
- const writtenValue = stripParenExpression(callExpression.arguments[0]);
13759
- if (isNodeOfType(writtenValue, "ArrowFunctionExpression") || isNodeOfType(writtenValue, "FunctionExpression") || isNodeOfType(writtenValue, "SpreadElement")) return null;
13760
- return {
13761
- callExpression,
13762
- writtenValue
13763
- };
13764
- };
13765
- const isGlobalObjectIsCall = (callExpression, scopes) => {
13766
- if (!isNodeOfType(callExpression, "CallExpression")) return false;
13767
- const callee = stripParenExpression(callExpression.callee);
13768
- if (!isNodeOfType(callee, "MemberExpression")) return false;
13769
- const propertyName = getStaticPropertyName(callee);
13770
- const receiver = stripParenExpression(callee.object);
13771
- return Boolean(propertyName === "is" && isNodeOfType(receiver, "Identifier") && receiver.name === "Object" && scopes.isGlobalReference(receiver));
13772
- };
13773
- const isGlobalNaNReference = (expression, scopes) => {
13774
- const unwrappedExpression = stripParenExpression(expression);
13775
- return isNodeOfType(unwrappedExpression, "Identifier") && unwrappedExpression.name === "NaN" && scopes.isGlobalReference(unwrappedExpression);
13776
- };
13777
- const getEqualityComparison = (stateReference, candidate, scopes) => {
13778
- const unwrappedStateReference = stripParenExpression(stateReference);
13779
- if (isNodeOfType(candidate, "BinaryExpression") && EQUALITY_BINARY_OPERATORS.has(candidate.operator)) {
13780
- if (stripParenExpression(candidate.left) === unwrappedStateReference) return isGlobalNaNReference(candidate.right, scopes) ? null : {
13781
- comparison: candidate,
13782
- counterpart: candidate.right,
13783
- areValuesEqualWhenTruthy: candidate.operator === "==="
13784
- };
13785
- if (stripParenExpression(candidate.right) === unwrappedStateReference) return isGlobalNaNReference(candidate.left, scopes) ? null : {
13786
- comparison: candidate,
13787
- counterpart: candidate.left,
13788
- areValuesEqualWhenTruthy: candidate.operator === "==="
13789
- };
13790
- return null;
13791
- }
13792
- if (!isNodeOfType(candidate, "CallExpression") || !isGlobalObjectIsCall(candidate, scopes) || candidate.arguments.length !== 2) return null;
13793
- const firstArgument = candidate.arguments[0];
13794
- const secondArgument = candidate.arguments[1];
13795
- if (isNodeOfType(firstArgument, "SpreadElement") || isNodeOfType(secondArgument, "SpreadElement")) return null;
13796
- if (stripParenExpression(firstArgument) === unwrappedStateReference) return {
13797
- comparison: candidate,
13798
- counterpart: secondArgument,
13799
- areValuesEqualWhenTruthy: true
13800
- };
13801
- if (stripParenExpression(secondArgument) === unwrappedStateReference) return {
13802
- comparison: candidate,
13803
- counterpart: firstArgument,
13804
- areValuesEqualWhenTruthy: true
13805
- };
13806
- return null;
13807
- };
13808
- const findEqualityComparison = (stateReference, test, scopes) => {
13809
- let current = stateReference.parent;
13810
- while (current && isAstDescendant(current, test)) {
13811
- const comparison = getEqualityComparison(stateReference, current, scopes);
13812
- if (comparison) return comparison;
13813
- if (current === test) break;
13814
- current = current.parent;
13815
- }
13816
- return null;
13817
- };
13818
- const doesTestOutcomeRequireComparisonOutcome = (comparison, test, testOutcome, comparisonOutcome) => {
13819
- let requiredChildOutcome = testOutcome;
13820
- let current = comparison;
13821
- while (current !== test) {
13822
- const parent = current.parent;
13823
- if (!parent || !isAstDescendant(parent, test)) return false;
13824
- if (isNodeOfType(parent, "UnaryExpression") && parent.operator === "!") requiredChildOutcome = !requiredChildOutcome;
13825
- else if (isNodeOfType(parent, "LogicalExpression")) {
13826
- if (parent.operator === "&&" && !requiredChildOutcome) return false;
13827
- if (parent.operator === "||" && requiredChildOutcome) return false;
13828
- if (parent.operator !== "&&" && parent.operator !== "||") return false;
13829
- } else if (!TRANSPARENT_EXPRESSION_WRAPPER_TYPES.has(parent.type)) return false;
13830
- current = parent;
13831
- }
13832
- return requiredChildOutcome === comparisonOutcome;
13833
- };
13834
- const resolveImmutableAliasExpression = (expression, scopes) => {
13835
- const visitedSymbolIds = /* @__PURE__ */ new Set();
13836
- let current = stripParenExpression(expression);
13837
- while (isNodeOfType(current, "Identifier")) {
13838
- const symbol = scopes.symbolFor(current);
13839
- if (!symbol || visitedSymbolIds.has(symbol.id)) break;
13840
- const initializer = getDirectConstInitializer(symbol);
13841
- if (!initializer || !isNodeOfType(stripParenExpression(initializer), "Identifier")) break;
13842
- visitedSymbolIds.add(symbol.id);
13843
- current = stripParenExpression(initializer);
13844
- }
13845
- return current;
13846
- };
13847
- const referencesSameValue = (leftExpression, rightExpression, scopes) => {
13848
- const left = resolveImmutableAliasExpression(leftExpression, scopes);
13849
- const right = resolveImmutableAliasExpression(rightExpression, scopes);
13850
- if (left === right) return true;
13851
- if (isNodeOfType(left, "Identifier") && isNodeOfType(right, "Identifier")) {
13852
- const leftSymbol = scopes.symbolFor(left);
13853
- const rightSymbol = scopes.symbolFor(right);
13854
- if (leftSymbol || rightSymbol) return leftSymbol?.id === rightSymbol?.id;
13855
- return left.name === right.name;
13856
- }
13857
- if (isNodeOfType(left, "Literal") && isNodeOfType(right, "Literal")) return Object.is(left.value, right.value);
13858
- return false;
13859
- };
13860
- const hasDeclaredTriggerDependency = (callback) => {
13861
- const hookCall = findTransparentExpressionRoot(callback).parent;
13862
- if (!isNodeOfType(hookCall, "CallExpression")) return false;
13863
- const dependencyArray = hookCall.arguments[1];
13864
- return Boolean(isNodeOfType(dependencyArray, "ArrayExpression") && dependencyArray.elements.length);
13865
- };
13866
- const doesBranchExitEffect = (branch) => {
13867
- if (isNodeOfType(branch, "ReturnStatement") || isNodeOfType(branch, "ThrowStatement")) return true;
13868
- if (!isNodeOfType(branch, "BlockStatement")) return false;
13869
- const terminalStatement = branch.body.at(-1);
13870
- return Boolean(terminalStatement && doesBranchExitEffect(terminalStatement));
13871
- };
13872
- const doesGuardDominateLaterSetter = (guard, setterCall) => {
13873
- if (!isNodeOfType(guard, "IfStatement") || guard.alternate) return false;
13874
- if (!doesBranchExitEffect(guard.consequent)) return false;
13875
- const block = guard.parent;
13876
- if (!isNodeOfType(block, "BlockStatement")) return false;
13877
- const guardIndex = block.body.findIndex((statement) => statement === guard);
13878
- return block.body.some((statement, statementIndex) => statementIndex > guardIndex && isAstDescendant(setterCall, statement));
13879
- };
13880
- const findDominatingGuardCounterpart = (stateReference, setterCall, callback, scopes) => {
13881
- let current = stateReference.parent;
13882
- while (current && current !== callback) {
13883
- if (isNodeOfType(current, "IfStatement") && isAstDescendant(stateReference, current.test) && (isAstDescendant(setterCall, current.consequent) || Boolean(current.alternate && isAstDescendant(setterCall, current.alternate)) || doesGuardDominateLaterSetter(current, setterCall))) {
13884
- const setterRunsWhenTestTruthy = isAstDescendant(setterCall, current.consequent);
13885
- if (setterRunsWhenTestTruthy === (Boolean(current.alternate && isAstDescendant(setterCall, current.alternate)) || doesGuardDominateLaterSetter(current, setterCall))) return null;
13886
- const equalityComparison = findEqualityComparison(stateReference, current.test, scopes);
13887
- if (!equalityComparison) return null;
13888
- const comparisonOutcomeForDifferentValues = !equalityComparison.areValuesEqualWhenTruthy;
13889
- if (!doesTestOutcomeRequireComparisonOutcome(equalityComparison.comparison, current.test, setterRunsWhenTestTruthy, comparisonOutcomeForDifferentValues)) return null;
13890
- return equalityComparison.counterpart;
13891
- }
13892
- current = current.parent;
13893
- }
13894
- return null;
13895
- };
13896
- const isSoleWriterEffectGuardCapture = (stateSymbol, callback, scopes) => {
13897
- if (!hasDeclaredTriggerDependency(callback)) return false;
13898
- if (stateSymbol.references.some((reference) => reference.flag !== "read")) return false;
13899
- const setterSymbol = getUseStateSetterSymbol(stateSymbol, scopes);
13900
- if (!setterSymbol) return false;
13901
- const setterWrite = getDirectSetterCall(setterSymbol, callback);
13902
- if (!setterWrite) return false;
13903
- const callbackStateReferences = stateSymbol.references.filter((reference) => isAstDescendant(reference.identifier, callback));
13904
- if (callbackStateReferences.length !== 1) return false;
13905
- const stateReferenceRoot = findTransparentExpressionRoot(callbackStateReferences[0].identifier);
13906
- if (isNodeOfType(stateReferenceRoot.parent, "MemberExpression") && stateReferenceRoot.parent.object === stateReferenceRoot) return false;
13907
- const counterpart = findDominatingGuardCounterpart(callbackStateReferences[0].identifier, setterWrite.callExpression, callback, scopes);
13908
- return Boolean(counterpart && referencesSameValue(counterpart, setterWrite.writtenValue, scopes));
13909
- };
13910
- //#endregion
13911
13221
  //#region src/plugin/rules/react-builtins/exhaustive-deps-suppression.ts
13912
13222
  const DISABLE_COMMENT_RULE_NAME_PATTERN$1 = /(?:^|[\s,/])exhaustive-deps(?:$|[\s,:])/;
13913
13223
  const DISABLE_NEXT_LINE_PATTERN$1 = /\b(?:eslint|oxlint)-disable-next-line\b([^\n]*)/;
@@ -13979,6 +13289,25 @@ const isExhaustiveDepsSuppressedAt = (filename, nodeStartOffset) => {
13979
13289
  return index.suppressedLines.has(lineForOffset$1(nodeStartOffset, index.utf16NewlineOffsets)) || index.suppressedLines.has(lineForOffset$1(nodeStartOffset, index.utf8NewlineOffsets));
13980
13290
  };
13981
13291
  //#endregion
13292
+ //#region src/plugin/utils/is-ast-descendant.ts
13293
+ /**
13294
+ * True when `inner` is `outer` itself or any descendant in the AST
13295
+ * `parent` chain. Walks `inner.parent` upward and stops at either a
13296
+ * match (`true`) or the chain's root (`false`).
13297
+ *
13298
+ * Was duplicated byte-identical in:
13299
+ * - exhaustive-deps-symbol-stability.ts
13300
+ * - semantic/closure-captures.ts
13301
+ */
13302
+ const isAstDescendant = (inner, outer) => {
13303
+ let current = inner;
13304
+ while (current) {
13305
+ if (current === outer) return true;
13306
+ current = current.parent ?? null;
13307
+ }
13308
+ return false;
13309
+ };
13310
+ //#endregion
13982
13311
  //#region src/plugin/rules/react-builtins/exhaustive-deps-symbol-stability.ts
13983
13312
  /**
13984
13313
  * Symbol-stability helpers consumed by the `exhaustive-deps` rule.
@@ -14159,7 +13488,6 @@ const EFFECT_HOOKS_ALLOWING_EXTRA_REACTIVE_DEPS = new Set([
14159
13488
  "useLayoutEffect",
14160
13489
  "useInsertionEffect"
14161
13490
  ]);
14162
- const SOLE_WRITER_GUARD_HOOKS = new Set(["useEffect", "useLayoutEffect"]);
14163
13491
  const buildAdditionalHooksRegex = (additional) => {
14164
13492
  if (!additional) return null;
14165
13493
  try {
@@ -14296,7 +13624,7 @@ const stringifyMemberChain = (node) => {
14296
13624
  }
14297
13625
  return null;
14298
13626
  };
14299
- const collectCaptureDepKeys = (callback, scopes, declaredExactBindingKeys, allowSoleWriterEffectGuards = false) => {
13627
+ const collectCaptureDepKeys = (callback, scopes, declaredExactBindingKeys) => {
14300
13628
  const keys = /* @__PURE__ */ new Set();
14301
13629
  const stableCapturedNames = /* @__PURE__ */ new Set();
14302
13630
  const moduleScopeCapturedNames = /* @__PURE__ */ new Set();
@@ -14307,10 +13635,6 @@ const collectCaptureDepKeys = (callback, scopes, declaredExactBindingKeys, allow
14307
13635
  const symbol = reference.resolvedSymbol;
14308
13636
  if (!symbol) continue;
14309
13637
  if (isRecursiveInitializerCapture(symbol, callback)) continue;
14310
- if (allowSoleWriterEffectGuards && isSoleWriterEffectGuardCapture(symbol, callback, scopes)) {
14311
- stableCapturedNames.add(symbol.name);
14312
- continue;
14313
- }
14314
13638
  if (symbolHasStableValue(symbol, scopes)) {
14315
13639
  stableCapturedNames.add(symbol.name);
14316
13640
  continue;
@@ -14983,7 +14307,7 @@ If the missing value is recreated every render, move it inside the hook or stabi
14983
14307
  if (isNodeOfType(stripped, "Identifier")) declaredExactBindingKeys.add(key);
14984
14308
  declaredKeyToReportNode.set(key, elementNode);
14985
14309
  }
14986
- const { keys: captureKeys, stableCapturedNames, moduleScopeCapturedNames, outerFunctionCapturedNames } = collectCaptureDepKeys(callbackToAnalyze ?? callbackArgument, context.scopes, declaredExactBindingKeys, SOLE_WRITER_GUARD_HOOKS.has(hookName));
14310
+ const { keys: captureKeys, stableCapturedNames, moduleScopeCapturedNames, outerFunctionCapturedNames } = collectCaptureDepKeys(callbackToAnalyze ?? callbackArgument, context.scopes, declaredExactBindingKeys);
14987
14311
  for (const forcedCaptureKey of forcedCaptureKeys) captureKeys.add(forcedCaptureKey);
14988
14312
  addAggregatePropsDependency(captureKeys, declaredKeys, callbackToAnalyze ?? callbackArgument, context.scopes);
14989
14313
  const missingCaptureKeys = [];
@@ -16797,14 +16121,14 @@ const isBindingInvokedOnRenderPath = (root, bindingName) => {
16797
16121
  if (didFindRenderPathInvocation) return false;
16798
16122
  if (!isNodeOfType(node, "CallExpression")) return;
16799
16123
  if (!isNodeOfType(node.callee, "Identifier") || node.callee.name !== bindingName) return;
16800
- let enclosingFunction = findEnclosingFunction$1(node);
16124
+ let enclosingFunction = findEnclosingFunction(node);
16801
16125
  while (enclosingFunction) {
16802
16126
  if (isDeferredCallbackPosition$1(enclosingFunction) || getHandlerNamedBindingName(enclosingFunction)) return;
16803
16127
  if (containingFunctionIsComponentOrHook(enclosingFunction)) {
16804
16128
  didFindRenderPathInvocation = true;
16805
16129
  return;
16806
16130
  }
16807
- enclosingFunction = findEnclosingFunction$1(enclosingFunction);
16131
+ enclosingFunction = findEnclosingFunction(enclosingFunction);
16808
16132
  }
16809
16133
  });
16810
16134
  return didFindRenderPathInvocation;
@@ -16839,7 +16163,7 @@ const jotaiSelectAtomInRenderBody = defineRule({
16839
16163
  };
16840
16164
  return { CallExpression(node) {
16841
16165
  if (!isImportedSelectAtom(node)) return;
16842
- const nearestFunctionLike = findEnclosingFunction$1(node);
16166
+ const nearestFunctionLike = findEnclosingFunction(node);
16843
16167
  if (!nearestFunctionLike) return;
16844
16168
  if (isDeferredCallback(nearestFunctionLike)) return;
16845
16169
  if (isBindingUsedAsHandler(nearestFunctionLike)) return;
@@ -17836,7 +17160,7 @@ const isPersistentCacheSetWrite = (callExpression, newExpression, enclosingFunct
17836
17160
  return !isAstDescendant(receiverBinding.scopeOwner, enclosingFunction);
17837
17161
  };
17838
17162
  const isInsideCacheMemo = (node) => {
17839
- const enclosingFunction = findEnclosingFunction$1(node);
17163
+ const enclosingFunction = findEnclosingFunction(node);
17840
17164
  let child = node;
17841
17165
  let cursor = node.parent ?? null;
17842
17166
  while (cursor) {
@@ -17874,7 +17198,7 @@ const getFunctionName = (functionNode) => {
17874
17198
  return null;
17875
17199
  };
17876
17200
  const isUncacheableOptionsMergeUtility = (node) => {
17877
- const enclosingFunction = findEnclosingFunction$1(node);
17201
+ const enclosingFunction = findEnclosingFunction(node);
17878
17202
  if (!enclosingFunction || !isFunctionLike$2(enclosingFunction)) return false;
17879
17203
  const functionName = getFunctionName(enclosingFunction);
17880
17204
  if (!functionName || isComponentOrHookName(functionName)) return false;
@@ -18065,6 +17389,13 @@ const isSafeStatefulReplaceAllSearch = (node, flags, context) => {
18065
17389
  const callee = stripParenExpression(replaceAllCall.callee);
18066
17390
  return isNodeOfType(callee, "MemberExpression") && !callee.computed && !callee.optional && !replaceAllCall.optional && isNodeOfType(callee.property, "Identifier") && callee.property.name === "replaceAll" && isProvenNativeStringReceiver(callee.object, context);
18067
17391
  };
17392
+ const getDestructuredBindingPropertyName = (bindingIdentifier) => {
17393
+ let bindingNode = bindingIdentifier;
17394
+ if (isNodeOfType(bindingNode.parent, "AssignmentPattern") && bindingNode.parent.left === bindingNode) bindingNode = bindingNode.parent;
17395
+ const property = bindingNode.parent;
17396
+ if (!isNodeOfType(property, "Property") || property.value !== bindingNode || !isNodeOfType(property.parent, "ObjectPattern")) return null;
17397
+ return getStaticPropertyKeyName(property, { allowComputedString: true });
17398
+ };
18068
17399
  const extendGlobalPath = (basePath, propertyName) => {
18069
17400
  if (basePath === "global") {
18070
17401
  if (propertyName === null || GLOBAL_OBJECT_NAMES.has(propertyName)) return "global";
@@ -18354,89 +17685,7 @@ const collectEarlierAndGuardOperands = (node) => {
18354
17685
  return earlierOperands;
18355
17686
  };
18356
17687
  //#endregion
18357
- //#region src/plugin/utils/unwrap-object-integrity-expression.ts
18358
- const OBJECT_INTEGRITY_METHOD_NAMES = new Set([
18359
- "freeze",
18360
- "seal",
18361
- "preventExtensions"
18362
- ]);
18363
- const OBJECT_FREEZE_OR_SEAL_METHOD_NAMES = new Set(["freeze", "seal"]);
18364
- const getObjectIntegrityMethodName = (node, scopes, methodNames = OBJECT_INTEGRITY_METHOD_NAMES) => {
18365
- const expression = stripParenExpression(node);
18366
- if (!isNodeOfType(expression, "CallExpression")) return null;
18367
- const callee = stripParenExpression(expression.callee);
18368
- const receiver = isNodeOfType(callee, "MemberExpression") ? stripParenExpression(callee.object) : callee;
18369
- if (!isNodeOfType(callee, "MemberExpression") || callee.computed || !isNodeOfType(receiver, "Identifier") || receiver.name !== "Object" || !scopes.isGlobalReference(receiver) || !isNodeOfType(callee.property, "Identifier") || !methodNames.has(callee.property.name)) return null;
18370
- return callee.property.name;
18371
- };
18372
- const unwrapObjectIntegrityExpression = (node, scopes, methodNames = OBJECT_INTEGRITY_METHOD_NAMES) => {
18373
- let expression = stripParenExpression(node);
18374
- while (isNodeOfType(expression, "CallExpression")) {
18375
- if (!getObjectIntegrityMethodName(expression, scopes, methodNames)) break;
18376
- const wrappedExpression = expression.arguments[0];
18377
- if (!wrappedExpression || isNodeOfType(wrappedExpression, "SpreadElement")) break;
18378
- expression = stripParenExpression(wrappedExpression);
18379
- }
18380
- return expression;
18381
- };
18382
- //#endregion
18383
17688
  //#region src/plugin/rules/js-performance/js-length-check-first.ts
18384
- const OBJECT_CARDINALITY_PROJECTION_METHOD_NAMES = new Set(["keys", "values"]);
18385
- const getGlobalObjectProjection = (expression, context) => {
18386
- const callExpression = stripParenExpression(expression);
18387
- if (!isNodeOfType(callExpression, "CallExpression")) return null;
18388
- const callee = stripParenExpression(callExpression.callee);
18389
- if (!isNodeOfType(callee, "MemberExpression")) return null;
18390
- const receiver = stripParenExpression(callee.object);
18391
- if (!isNodeOfType(receiver, "Identifier") || receiver.name !== "Object" || !context.scopes.isGlobalReference(receiver)) return null;
18392
- const methodName = getStaticPropertyName(callee);
18393
- if (!methodName || !OBJECT_CARDINALITY_PROJECTION_METHOD_NAMES.has(methodName)) return null;
18394
- const callArguments = callExpression.arguments ?? [];
18395
- if (callArguments.length !== 1 || isNodeOfType(callArguments[0], "SpreadElement")) return null;
18396
- return {
18397
- methodName,
18398
- source: callArguments[0]
18399
- };
18400
- };
18401
- const isPlainDataObjectLiteral = (expression) => {
18402
- const objectExpression = stripParenExpression(expression);
18403
- if (!isNodeOfType(objectExpression, "ObjectExpression")) return false;
18404
- return (objectExpression.properties ?? []).every((property) => {
18405
- if (!isNodeOfType(property, "Property") || property.kind !== "init" || property.method === true) return false;
18406
- const propertyValue = stripParenExpression(property.value);
18407
- return isNodeOfType(propertyValue, "Literal") || isNodeOfType(propertyValue, "TemplateLiteral") && propertyValue.expressions.length === 0;
18408
- });
18409
- };
18410
- const getGlobalObjectFreezeArgument = (expression, context) => {
18411
- const callExpression = stripParenExpression(expression);
18412
- if (!isNodeOfType(callExpression, "CallExpression")) return null;
18413
- if (getObjectIntegrityMethodName(callExpression, context.scopes) !== "freeze") return null;
18414
- const callArguments = callExpression.arguments ?? [];
18415
- if (callArguments.length !== 1 || isNodeOfType(callArguments[0], "SpreadElement")) return null;
18416
- return callArguments[0];
18417
- };
18418
- const resolveStablePlainObjectRootId = (expression, context, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
18419
- const source = stripParenExpression(expression);
18420
- if (!isNodeOfType(source, "Identifier")) return null;
18421
- const symbol = context.scopes.symbolFor(source);
18422
- if (!symbol || visitedSymbolIds.has(symbol.id)) return null;
18423
- const directConstInitializer = getDirectConstInitializer(symbol);
18424
- if (!directConstInitializer) return null;
18425
- visitedSymbolIds.add(symbol.id);
18426
- const initializer = stripParenExpression(directConstInitializer);
18427
- const frozenValue = getGlobalObjectFreezeArgument(initializer, context);
18428
- if (frozenValue) return isPlainDataObjectLiteral(frozenValue) ? symbol.id : null;
18429
- return resolveStablePlainObjectRootId(initializer, context, visitedSymbolIds);
18430
- };
18431
- const areEqualCardinalityObjectProjections = (receiverArray, indexedArray, context) => {
18432
- const receiverProjection = getGlobalObjectProjection(receiverArray, context);
18433
- const indexedProjection = getGlobalObjectProjection(indexedArray, context);
18434
- if (!receiverProjection || !indexedProjection) return false;
18435
- if (receiverProjection.methodName === indexedProjection.methodName) return false;
18436
- const receiverRootId = resolveStablePlainObjectRootId(receiverProjection.source, context);
18437
- const indexedRootId = resolveStablePlainObjectRootId(indexedProjection.source, context);
18438
- return receiverRootId !== null && receiverRootId === indexedRootId;
18439
- };
18440
17689
  const findIndexedArrayObject = (callbackBody, indexParameterName) => {
18441
17690
  let indexedArrayObject = null;
18442
17691
  walkAst(callbackBody, (child) => {
@@ -18651,7 +17900,6 @@ const jsLengthCheckFirst = defineRule({
18651
17900
  const resolvedReceiverSource = resolveComparedArraySource(receiverArrayObject, node);
18652
17901
  const resolvedIndexedSource = resolveComparedArraySource(indexedArrayObject, node);
18653
17902
  if (areExpressionsStructurallyEqual(resolvedReceiverSource, resolvedIndexedSource)) return;
18654
- if (areEqualCardinalityObjectProjections(receiverArrayObject, indexedArrayObject, context) || areEqualCardinalityObjectProjections(resolvedReceiverSource, resolvedIndexedSource, context)) return;
18655
17903
  const comparedArrayPairs = [[receiverArrayObject, indexedArrayObject], [resolvedReceiverSource, resolvedIndexedSource]];
18656
17904
  if (collectEarlierAndGuardOperands(node).some((guardOperand) => comparedArrayPairs.some(([receiverSide, indexedSide]) => isLengthComparison(guardOperand, receiverSide, indexedSide, LENGTH_ANY_COMPARISON_OPERATORS)))) return;
18657
17905
  if (collectEarlierOrOperands(node).some((guardOperand) => comparedArrayPairs.some(([receiverSide, indexedSide]) => isLengthComparison(guardOperand, receiverSide, indexedSide, LENGTH_MISMATCH_OPERATORS)))) return;
@@ -24529,6 +23777,32 @@ const hasDirective = (programNode, directive) => {
24529
23777
  return Boolean(programNode.body?.some((statement) => isNodeOfType(statement, "ExpressionStatement") && isNodeOfType(statement.expression, "Literal") && statement.expression.value === directive));
24530
23778
  };
24531
23779
  //#endregion
23780
+ //#region src/plugin/utils/unwrap-object-integrity-expression.ts
23781
+ const OBJECT_INTEGRITY_METHOD_NAMES = new Set([
23782
+ "freeze",
23783
+ "seal",
23784
+ "preventExtensions"
23785
+ ]);
23786
+ const OBJECT_FREEZE_OR_SEAL_METHOD_NAMES = new Set(["freeze", "seal"]);
23787
+ const getObjectIntegrityMethodName = (node, scopes, methodNames = OBJECT_INTEGRITY_METHOD_NAMES) => {
23788
+ const expression = stripParenExpression(node);
23789
+ if (!isNodeOfType(expression, "CallExpression")) return null;
23790
+ const callee = stripParenExpression(expression.callee);
23791
+ const receiver = isNodeOfType(callee, "MemberExpression") ? stripParenExpression(callee.object) : callee;
23792
+ if (!isNodeOfType(callee, "MemberExpression") || callee.computed || !isNodeOfType(receiver, "Identifier") || receiver.name !== "Object" || !scopes.isGlobalReference(receiver) || !isNodeOfType(callee.property, "Identifier") || !methodNames.has(callee.property.name)) return null;
23793
+ return callee.property.name;
23794
+ };
23795
+ const unwrapObjectIntegrityExpression = (node, scopes, methodNames = OBJECT_INTEGRITY_METHOD_NAMES) => {
23796
+ let expression = stripParenExpression(node);
23797
+ while (isNodeOfType(expression, "CallExpression")) {
23798
+ if (!getObjectIntegrityMethodName(expression, scopes, methodNames)) break;
23799
+ const wrappedExpression = expression.arguments[0];
23800
+ if (!wrappedExpression || isNodeOfType(wrappedExpression, "SpreadElement")) break;
23801
+ expression = stripParenExpression(wrappedExpression);
23802
+ }
23803
+ return expression;
23804
+ };
23805
+ //#endregion
24532
23806
  //#region src/plugin/rules/nextjs/nextjs-async-client-component.ts
24533
23807
  const nextjsAsyncClientComponent = defineRule({
24534
23808
  id: "nextjs-async-client-component",
@@ -26868,7 +26142,7 @@ const isIndependentWriterIdentifier = (componentFunction, identifier, includeDef
26868
26142
  };
26869
26143
  const hasUserInputSetterWriter = (setterRef, effectNode, includeDeferredWriters = false) => {
26870
26144
  if (!setterRef.resolved) return false;
26871
- const componentFunction = findEnclosingFunction$1(effectNode);
26145
+ const componentFunction = findEnclosingFunction(effectNode);
26872
26146
  if (!componentFunction) return false;
26873
26147
  for (const reference of setterRef.resolved.references) {
26874
26148
  if (reference.init) continue;
@@ -29641,6 +28915,138 @@ const noBarrelImport = defineRule({
29641
28915
  }
29642
28916
  });
29643
28917
  //#endregion
28918
+ //#region src/plugin/utils/has-static-property-write-before.ts
28919
+ const equivalentSymbolsByAnalysis = /* @__PURE__ */ new WeakMap();
28920
+ const CONDITIONAL_EXECUTION_NODE_TYPES = new Set([
28921
+ "CatchClause",
28922
+ "ConditionalExpression",
28923
+ "DoWhileStatement",
28924
+ "ForInStatement",
28925
+ "ForOfStatement",
28926
+ "ForStatement",
28927
+ "IfStatement",
28928
+ "LogicalExpression",
28929
+ "SwitchCase",
28930
+ "SwitchStatement",
28931
+ "TryStatement",
28932
+ "WhileStatement"
28933
+ ]);
28934
+ const getResolvedStaticPropertyName = (memberExpression, scopes) => {
28935
+ if (!isNodeOfType(memberExpression, "MemberExpression")) return null;
28936
+ const directPropertyName = getStaticPropertyName(memberExpression);
28937
+ if (directPropertyName || !memberExpression.computed) return directPropertyName;
28938
+ const property = stripParenExpression(memberExpression.property);
28939
+ if (!isNodeOfType(property, "Identifier")) return null;
28940
+ const propertySymbol = resolveConstIdentifierAlias(property, scopes);
28941
+ const initializer = propertySymbol?.initializer ? stripParenExpression(propertySymbol.initializer) : null;
28942
+ return initializer && isNodeOfType(initializer, "Literal") && typeof initializer.value === "string" ? initializer.value : null;
28943
+ };
28944
+ const collectScopeSymbols = (scope, symbols) => {
28945
+ symbols.push(...scope.symbols);
28946
+ for (const childScope of scope.children) collectScopeSymbols(childScope, symbols);
28947
+ };
28948
+ const getEquivalentSymbols = (identifier, scopes) => {
28949
+ const rootSymbol = resolveConstIdentifierAlias(identifier, scopes);
28950
+ if (!rootSymbol) return [];
28951
+ let symbolsByRootId = equivalentSymbolsByAnalysis.get(scopes);
28952
+ if (!symbolsByRootId) {
28953
+ symbolsByRootId = /* @__PURE__ */ new Map();
28954
+ equivalentSymbolsByAnalysis.set(scopes, symbolsByRootId);
28955
+ }
28956
+ const cachedSymbols = symbolsByRootId.get(rootSymbol.id);
28957
+ if (cachedSymbols) return cachedSymbols;
28958
+ const allSymbols = [];
28959
+ collectScopeSymbols(scopes.rootScope, allSymbols);
28960
+ const equivalentSymbols = allSymbols.filter((symbol) => resolveConstIdentifierAlias(symbol.bindingIdentifier, scopes)?.id === rootSymbol.id);
28961
+ symbolsByRootId.set(rootSymbol.id, equivalentSymbols);
28962
+ return equivalentSymbols;
28963
+ };
28964
+ const findExecutionBoundary = (node) => {
28965
+ let current = node;
28966
+ while (current) {
28967
+ if (isFunctionLike$2(current) || isNodeOfType(current, "Program")) return current;
28968
+ current = current.parent ?? null;
28969
+ }
28970
+ return null;
28971
+ };
28972
+ const isOnUnconditionalPath = (node, boundary) => {
28973
+ let current = node.parent ?? null;
28974
+ while (current && current !== boundary) {
28975
+ if (CONDITIONAL_EXECUTION_NODE_TYPES.has(current.type)) return false;
28976
+ current = current.parent ?? null;
28977
+ }
28978
+ return current === boundary;
28979
+ };
28980
+ const findFunctionBindingIdentifier = (functionNode) => {
28981
+ if (isNodeOfType(functionNode, "FunctionDeclaration")) return functionNode.id ?? null;
28982
+ const parent = functionNode.parent;
28983
+ if (parent && isNodeOfType(parent, "VariableDeclarator") && parent.init === functionNode && isNodeOfType(parent.id, "Identifier")) return parent.id;
28984
+ return null;
28985
+ };
28986
+ const findDirectCall = (identifier) => {
28987
+ let callee = identifier;
28988
+ let parent = callee.parent;
28989
+ while (parent && stripParenExpression(parent) === identifier) {
28990
+ callee = parent;
28991
+ parent = callee.parent;
28992
+ }
28993
+ return parent && isNodeOfType(parent, "CallExpression") && parent.callee === callee ? parent : null;
28994
+ };
28995
+ const isFunctionSynchronouslyInvokedBefore = (functionNode, referenceNode, scopes, visitedFunctionNodes = /* @__PURE__ */ new Set()) => {
28996
+ if (visitedFunctionNodes.has(functionNode) || !isFunctionLike$2(functionNode) || functionNode.generator) return false;
28997
+ visitedFunctionNodes.add(functionNode);
28998
+ const referenceBoundary = findExecutionBoundary(referenceNode);
28999
+ if (!referenceBoundary) return false;
29000
+ const invocationCalls = [];
29001
+ const bindingIdentifier = findFunctionBindingIdentifier(functionNode);
29002
+ if (bindingIdentifier) for (const symbol of getEquivalentSymbols(bindingIdentifier, scopes)) for (const reference of symbol.references) {
29003
+ const call = findDirectCall(reference.identifier);
29004
+ if (call) invocationCalls.push(call);
29005
+ }
29006
+ else {
29007
+ const call = findDirectCall(functionNode);
29008
+ if (call) invocationCalls.push(call);
29009
+ }
29010
+ return invocationCalls.some((call) => {
29011
+ if (call.range[0] >= referenceNode.range[0]) return false;
29012
+ const callBoundary = findExecutionBoundary(call);
29013
+ if (!callBoundary) return false;
29014
+ if (callBoundary === referenceBoundary) return true;
29015
+ if (!isFunctionLike$2(callBoundary)) return false;
29016
+ return isFunctionSynchronouslyInvokedBefore(callBoundary, referenceNode, scopes, new Set(visitedFunctionNodes));
29017
+ });
29018
+ };
29019
+ const isMemberWriteTarget = (memberExpression) => {
29020
+ const parent = memberExpression.parent;
29021
+ if (!parent) return false;
29022
+ if (isNodeOfType(parent, "AssignmentExpression")) return parent.left === memberExpression;
29023
+ if (isNodeOfType(parent, "UpdateExpression")) return parent.argument === memberExpression;
29024
+ return isNodeOfType(parent, "UnaryExpression") && parent.operator === "delete" && parent.argument === memberExpression;
29025
+ };
29026
+ const symbolHasStaticPropertyWriteBefore = (symbol, propertyName, referenceNode, scopes) => symbol.references.some((reference) => {
29027
+ let parent = reference.identifier.parent;
29028
+ while (parent && stripParenExpression(parent) === reference.identifier) parent = parent.parent;
29029
+ if (!parent || !isNodeOfType(parent, "MemberExpression") || stripParenExpression(parent.object) !== reference.identifier || getResolvedStaticPropertyName(parent, scopes) !== propertyName || !isMemberWriteTarget(parent)) return false;
29030
+ const writeBoundary = findExecutionBoundary(parent);
29031
+ const referenceBoundary = findExecutionBoundary(referenceNode);
29032
+ if (!writeBoundary || !referenceBoundary || !isOnUnconditionalPath(parent, writeBoundary)) return false;
29033
+ if (writeBoundary === referenceBoundary) return parent.range[0] < referenceNode.range[0];
29034
+ return isFunctionLike$2(writeBoundary) && isFunctionSynchronouslyInvokedBefore(writeBoundary, referenceNode, scopes);
29035
+ });
29036
+ const hasStaticPropertyWriteBefore = (identifier, propertyName, referenceNode, scopes) => {
29037
+ if (!isNodeOfType(identifier, "Identifier")) return false;
29038
+ return getEquivalentSymbols(identifier, scopes).some((symbol) => symbolHasStaticPropertyWriteBefore(symbol, propertyName, referenceNode, scopes));
29039
+ };
29040
+ //#endregion
29041
+ //#region src/plugin/utils/has-symbol-write-before.ts
29042
+ const hasSymbolWriteBefore = (symbol, referenceNode, scopes) => symbol.references.some((reference) => {
29043
+ if (reference.flag === "read") return false;
29044
+ const writeFunction = findEnclosingFunction(reference.identifier);
29045
+ if (writeFunction === findEnclosingFunction(referenceNode)) return reference.identifier.range[0] < referenceNode.range[0];
29046
+ if (!writeFunction) return true;
29047
+ return isFunctionSynchronouslyInvokedBefore(writeFunction, referenceNode, scopes);
29048
+ });
29049
+ //#endregion
29644
29050
  //#region src/plugin/utils/has-stable-call-target.ts
29645
29051
  const hasStableCallTarget = (callExpression, scopes) => {
29646
29052
  if (!isNodeOfType(callExpression, "CallExpression")) return false;
@@ -30109,8 +29515,8 @@ const isUseMemoCallbackArgument = (functionNode) => {
30109
29515
  return isReactFunctionCall(parent, "useMemo");
30110
29516
  };
30111
29517
  const findEnclosingRenderFunction = (node) => {
30112
- let enclosingFunction = findEnclosingFunction$1(node);
30113
- while (enclosingFunction && isUseMemoCallbackArgument(enclosingFunction)) enclosingFunction = findEnclosingFunction$1(enclosingFunction);
29518
+ let enclosingFunction = findEnclosingFunction(node);
29519
+ while (enclosingFunction && isUseMemoCallbackArgument(enclosingFunction)) enclosingFunction = findEnclosingFunction(enclosingFunction);
30114
29520
  return enclosingFunction;
30115
29521
  };
30116
29522
  const noCreateRefInFunctionComponent = defineRule({
@@ -31161,7 +30567,7 @@ const getEnclosingEffectHookCallback = (node, componentFunction) => {
31161
30567
  const isEffectDrivenResync = (useStateCall) => {
31162
30568
  const setterName = getStateSetterName(useStateCall);
31163
30569
  if (!setterName) return false;
31164
- const componentFunction = findEnclosingFunction$1(useStateCall);
30570
+ const componentFunction = findEnclosingFunction(useStateCall);
31165
30571
  if (!componentFunction) return false;
31166
30572
  let isExempt = false;
31167
30573
  walkAst(componentFunction, (child) => {
@@ -31265,7 +30671,7 @@ const isDraftReseedOrRenderAdjusted = (useStateCall, isPropName) => {
31265
30671
  const setterName = getStateSetterName(useStateCall);
31266
30672
  if (!setterName) return false;
31267
30673
  const stateValueName = getStateValueName(useStateCall);
31268
- const componentFunction = findEnclosingFunction$1(useStateCall);
30674
+ const componentFunction = findEnclosingFunction(useStateCall);
31269
30675
  if (!componentFunction) return false;
31270
30676
  let isExempt = false;
31271
30677
  walkAst(componentFunction, (child) => {
@@ -31311,7 +30717,7 @@ const noDerivedUseState = defineRule({
31311
30717
  if (isDraftReseedOrRenderAdjusted(node, propStackTracker.isPropName)) return;
31312
30718
  if (isEffectDrivenResync(node)) return;
31313
30719
  if (isNextjsDataFetchingPage(node)) return;
31314
- const componentFunction = findEnclosingFunction$1(node);
30720
+ const componentFunction = findEnclosingFunction(node);
31315
30721
  if (componentFunction) {
31316
30722
  if (isDefaultedDestructuredProp(componentFunction, propName)) return;
31317
30723
  if (isDraftCommittedToParent(componentFunction, getStateValueName(node), propStackTracker.isPropName)) return;
@@ -33149,7 +32555,7 @@ const isFunctionUsedOutsideHandlers = (analysis, functionNode, componentFunction
33149
32555
  if (isInsideInlineEventHandler(identifier, componentFunction)) return false;
33150
32556
  const parent = identifier.parent;
33151
32557
  if (parent && isNodeOfType(parent, "CallExpression") && parent.callee === identifier) {
33152
- if (findEnclosingFunction$1(parent) === functionNode) return false;
32558
+ if (findEnclosingFunction(parent) === functionNode) return false;
33153
32559
  if (isInsideProvenEventHandler(analysis, parent, componentFunction, false)) return false;
33154
32560
  }
33155
32561
  return true;
@@ -33195,7 +32601,7 @@ const isStateWrittenOnlyFromEventHandlers = (analysis, stateReference) => {
33195
32601
  if (!setterVariable) return false;
33196
32602
  const stateDeclarator = getUseStateDecl(analysis, stateReference);
33197
32603
  if (!stateDeclarator) return false;
33198
- const componentFunction = findEnclosingFunction$1(stateDeclarator);
32604
+ const componentFunction = findEnclosingFunction(stateDeclarator);
33199
32605
  if (!componentFunction) return false;
33200
32606
  let hasWriter = false;
33201
32607
  for (const reference of setterVariable.references) {
@@ -34257,8 +33663,8 @@ const isAwaitedInFunction = (request, functionNode) => {
34257
33663
  return false;
34258
33664
  };
34259
33665
  const isCompletionSinkForRequest = (completionSink, request) => {
34260
- const requestFunction = findEnclosingFunction$1(request);
34261
- const completionSinkFunction = findEnclosingFunction$1(completionSink);
33666
+ const requestFunction = findEnclosingFunction(request);
33667
+ const completionSinkFunction = findEnclosingFunction(completionSink);
34262
33668
  if (!requestFunction || !completionSinkFunction) return false;
34263
33669
  if (requestFunction === completionSinkFunction) {
34264
33670
  if (!isAwaitedInFunction(request, requestFunction)) return false;
@@ -34545,6 +33951,13 @@ const isPublishedLibraryPackage = (filename) => {
34545
33951
  return manifest.private !== true && typeof manifest.peerDependencies === "object" && manifest.peerDependencies !== null && "react" in manifest.peerDependencies;
34546
33952
  };
34547
33953
  //#endregion
33954
+ //#region src/plugin/utils/is-type-only-import.ts
33955
+ const isEverySpecifierInlineType = (specifiers, specifierType, kindField) => {
33956
+ if (!specifiers || specifiers.length === 0) return false;
33957
+ return specifiers.every((specifier) => isNodeOfType(specifier, specifierType) && specifier[kindField] === "type");
33958
+ };
33959
+ const isTypeOnlyImport = (node) => node.importKind === "type" || isEverySpecifierInlineType(node.specifiers, "ImportSpecifier", "importKind");
33960
+ //#endregion
34548
33961
  //#region src/plugin/rules/bundle-size/no-full-lodash-import.ts
34549
33962
  const isLibraryDevPage = (filename) => {
34550
33963
  if (!filename) return false;
@@ -35108,7 +34521,7 @@ const isInRenderedOutput = (node, componentOrHookNode, scopes) => {
35108
34521
  return attribute ? !isEventHandlerAttribute(attribute) : true;
35109
34522
  }
35110
34523
  if (isNodeOfType(parentNode, "ReturnStatement")) {
35111
- if (findEnclosingFunction$1(parentNode) === componentOrHookNode) return true;
34524
+ if (findEnclosingFunction(parentNode) === componentOrHookNode) return true;
35112
34525
  }
35113
34526
  if (parentNode === componentOrHookNode) return isFunctionLike$2(componentOrHookNode) && !isNodeOfType(componentOrHookNode.body, "BlockStatement") && componentOrHookNode.body === currentNode;
35114
34527
  if (isFunctionLike$2(parentNode) && !executesDuringRender(parentNode, scopes)) return false;
@@ -35231,7 +34644,7 @@ const noHydrationBranchOnBrowserGlobal = defineRule({
35231
34644
  if (consequentValues.length === 0 || alternateValues.length === 0) return;
35232
34645
  const componentOrHookNode = findRenderPhaseComponentOrHook(node.test, context.scopes);
35233
34646
  if (!componentOrHookNode) return;
35234
- const enclosingFunction = findEnclosingFunction$1(node);
34647
+ const enclosingFunction = findEnclosingFunction(node);
35235
34648
  if (enclosingFunction !== componentOrHookNode && (!enclosingFunction || !isInRenderedOutput(enclosingFunction, componentOrHookNode, context.scopes))) return;
35236
34649
  for (const consequentValue of consequentValues) for (const alternateValue of alternateValues) {
35237
34650
  if (!isRenderedValue(consequentValue) && !isRenderedValue(alternateValue)) continue;
@@ -35679,10 +35092,10 @@ const isInsideInstanceField = (node) => {
35679
35092
  return false;
35680
35093
  };
35681
35094
  const isOneShotModuleInitialization = (node, context) => {
35682
- let functionNode = findEnclosingFunction$1(node);
35095
+ let functionNode = findEnclosingFunction(node);
35683
35096
  while (functionNode) {
35684
35097
  if (!executesDuringRender(functionNode, context.scopes)) return false;
35685
- functionNode = findEnclosingFunction$1(functionNode);
35098
+ functionNode = findEnclosingFunction(functionNode);
35686
35099
  }
35687
35100
  return !isInsideInstanceField(node);
35688
35101
  };
@@ -36666,10 +36079,10 @@ const getMethodCalls = (functionNode, scopes) => {
36666
36079
  const isFunctionInvokedBeforeUsage = (functionNode, usageNode, usageBoundary, scopes, visitedSymbolIds, visitedFunctionNodes = /* @__PURE__ */ new Set()) => {
36667
36080
  if (visitedFunctionNodes.has(functionNode)) return false;
36668
36081
  visitedFunctionNodes.add(functionNode);
36669
- const usageFunction = findEnclosingFunction$1(usageNode);
36082
+ const usageFunction = findEnclosingFunction(usageNode);
36670
36083
  const immediateCall = getDirectCallForExpression(functionNode);
36671
36084
  if (immediateCall) {
36672
- const immediateCallFunction = findEnclosingFunction$1(immediateCall);
36085
+ const immediateCallFunction = findEnclosingFunction(immediateCall);
36673
36086
  if (immediateCallFunction === usageFunction) {
36674
36087
  const immediateCallStart = getRangeStart(immediateCall);
36675
36088
  return immediateCallStart === null || immediateCallStart < usageBoundary;
@@ -36678,7 +36091,7 @@ const isFunctionInvokedBeforeUsage = (functionNode, usageNode, usageBoundary, sc
36678
36091
  return isFunctionInvokedBeforeUsage(immediateCallFunction, usageNode, usageBoundary, scopes, visitedSymbolIds, new Set(visitedFunctionNodes));
36679
36092
  }
36680
36093
  for (const methodCall of getMethodCalls(functionNode, scopes)) {
36681
- const methodCallFunction = findEnclosingFunction$1(methodCall);
36094
+ const methodCallFunction = findEnclosingFunction(methodCall);
36682
36095
  if (methodCallFunction === usageFunction) {
36683
36096
  const methodCallStart = getRangeStart(methodCall);
36684
36097
  if (methodCallStart === null || methodCallStart < usageBoundary) return true;
@@ -36701,7 +36114,7 @@ const isFunctionInvokedBeforeUsage = (functionNode, usageNode, usageBoundary, sc
36701
36114
  if (scopes.symbolFor(child)?.declarationNode !== symbol.declarationNode) return;
36702
36115
  const call = getDirectCallForExpression(child);
36703
36116
  if (!call) return false;
36704
- const callFunction = findEnclosingFunction$1(call);
36117
+ const callFunction = findEnclosingFunction(call);
36705
36118
  if (callFunction === usageFunction) {
36706
36119
  const callStart = getRangeStart(call);
36707
36120
  wasInvokedBeforeUsage = callStart === null || callStart < usageBoundary;
@@ -36732,14 +36145,14 @@ const wasMutatedBeforeUsage = (symbol, usageNode, readNode, scopes, visitedMutat
36732
36145
  visitedMutationSymbolIds.add(symbol.id);
36733
36146
  const usageBoundary = inheritedUsageBoundary === void 0 ? getMutationUsageBoundary(usageNode, readNode) : inheritedUsageBoundary;
36734
36147
  if (typeof usageBoundary !== "number") return true;
36735
- const usageFunction = findEnclosingFunction$1(usageNode);
36148
+ const usageFunction = findEnclosingFunction(usageNode);
36736
36149
  return symbol.references.some((reference) => {
36737
36150
  const referenceStart = getRangeStart(reference.identifier);
36738
36151
  const simpleAlias = getSimpleAlias(reference.identifier, scopes);
36739
36152
  if (simpleAlias) return wasMutatedBeforeUsage(simpleAlias.symbol, usageNode, readNodesBySymbolId.get(simpleAlias.symbol.id) ?? simpleAlias.readNode, scopes, new Set(visitedMutationSymbolIds), usageBoundary, readNodesBySymbolId);
36740
36153
  if (!isPotentialMutationReference(reference.identifier, readNode)) return false;
36741
36154
  if (referenceStart === null) return true;
36742
- const mutationFunction = findEnclosingFunction$1(reference.identifier);
36155
+ const mutationFunction = findEnclosingFunction(reference.identifier);
36743
36156
  if (mutationFunction === usageFunction) return referenceStart < usageBoundary;
36744
36157
  if (!mutationFunction) return usageFunction !== null;
36745
36158
  if (usageFunction && isAstDescendant(usageFunction, mutationFunction)) return true;
@@ -37321,6 +36734,13 @@ const isReactNamespaceExpression = (node, scopes) => {
37321
36734
  return isReactNamespaceImport(node, scopes);
37322
36735
  };
37323
36736
  const isReactHocMemberReference = (node, scopes) => Boolean(isNodeOfType(node, "MemberExpression") && !node.computed && isNodeOfType(node.property, "Identifier") && REACT_HOC_NAMES.has(node.property.name) && isReactNamespaceExpression(node.object, scopes));
36737
+ const getDestructuredPropertyName$1 = (symbol) => {
36738
+ const property = symbol.bindingIdentifier.parent;
36739
+ if (!property || !isNodeOfType(property, "Property") || !property.parent || !isNodeOfType(property.parent, "ObjectPattern")) return null;
36740
+ if (isNodeOfType(property.key, "Identifier") && !property.computed) return property.key.name;
36741
+ if (isNodeOfType(property.key, "Literal") && typeof property.key.value === "string") return property.key.value;
36742
+ return null;
36743
+ };
37324
36744
  const symbolMapsToHoc = (symbol, scopes, visitedSymbolIds) => {
37325
36745
  if (visitedSymbolIds.has(symbol.id)) return false;
37326
36746
  visitedSymbolIds.add(symbol.id);
@@ -37330,7 +36750,7 @@ const symbolMapsToHoc = (symbol, scopes, visitedSymbolIds) => {
37330
36750
  }
37331
36751
  const init = symbol.initializer;
37332
36752
  if (!init) return false;
37333
- const destructuredPropertyName = getDestructuredBindingPropertyName(symbol.bindingIdentifier);
36753
+ const destructuredPropertyName = getDestructuredPropertyName$1(symbol);
37334
36754
  if (destructuredPropertyName && REACT_HOC_NAMES.has(destructuredPropertyName) && isReactNamespaceExpression(init, scopes)) return true;
37335
36755
  if (isReactHocMemberReference(init, scopes)) return true;
37336
36756
  if (isNodeOfType(init, "Identifier")) {
@@ -39084,6 +38504,12 @@ const getDeclarationKind = (declarator) => {
39084
38504
  return declaration && isNodeOfType(declaration, "VariableDeclaration") ? declaration.kind : null;
39085
38505
  };
39086
38506
  const hasMutableBindingWrite = (reference) => Boolean(reference.resolved?.references.some((candidateReference) => candidateReference.isWrite() && !candidateReference.init));
38507
+ const getDestructuredPropertyName = (bindingIdentifier) => {
38508
+ const property = bindingIdentifier.parent;
38509
+ if (!property || !isNodeOfType(property, "Property")) return null;
38510
+ if (property.computed) return isNodeOfType(property.key, "Literal") && typeof property.key.value === "string" ? String(property.key.value) : null;
38511
+ return isNodeOfType(property.key, "Identifier") ? property.key.name : null;
38512
+ };
39087
38513
  const getParentCallbackPropName = (analysis, expression, visitedVariables = /* @__PURE__ */ new Set()) => {
39088
38514
  const unwrappedExpression = stripParenExpression(expression);
39089
38515
  if (isNodeOfType(unwrappedExpression, "Identifier")) {
@@ -39093,7 +38519,7 @@ const getParentCallbackPropName = (analysis, expression, visitedVariables = /* @
39093
38519
  if (isProp(analysis, callbackReference)) {
39094
38520
  if (isWholePropsObjectReference(analysis, callbackReference)) return null;
39095
38521
  const bindingIdentifier = callbackVariable.defs.find((definition) => definition.type === "Parameter")?.name;
39096
- return (bindingIdentifier && getDestructuredBindingPropertyName(bindingIdentifier)) ?? unwrappedExpression.name;
38522
+ return (bindingIdentifier && getDestructuredPropertyName(bindingIdentifier)) ?? unwrappedExpression.name;
39097
38523
  }
39098
38524
  if (hasMutableBindingWrite(callbackReference)) return null;
39099
38525
  const definitions = callbackVariable.defs.map((definition) => definition.node).filter((definitionNode) => isNodeOfType(definitionNode, "VariableDeclarator"));
@@ -39103,7 +38529,7 @@ const getParentCallbackPropName = (analysis, expression, visitedVariables = /* @
39103
38529
  visitedVariables.add(callbackVariable);
39104
38530
  if (isNodeOfType(declarator.id, "ObjectPattern")) {
39105
38531
  const bindingIdentifier = callbackVariable.defs[0]?.name;
39106
- const propertyName = bindingIdentifier ? getDestructuredBindingPropertyName(bindingIdentifier) : null;
38532
+ const propertyName = bindingIdentifier ? getDestructuredPropertyName(bindingIdentifier) : null;
39107
38533
  const propsReference = getDownstreamRefs(analysis, declarator.init).find((candidateReference) => isWholePropsObjectReference(analysis, candidateReference));
39108
38534
  return propertyName && propsReference ? propertyName : null;
39109
38535
  }
@@ -39206,7 +38632,7 @@ const getCallbackRefProvenance = (analysis, effectCall, callExpression, isReactU
39206
38632
  const bindingProvenance = getRefBindingProvenance(analysis, stripParenExpression(callee.object), isReactUseRefCall);
39207
38633
  if (!bindingProvenance) return null;
39208
38634
  const { refCall, variables } = bindingProvenance;
39209
- const componentFunction = findEnclosingFunction$1(effectCall);
38635
+ const componentFunction = findEnclosingFunction(effectCall);
39210
38636
  if (!componentFunction || !isFunctionLike$2(componentFunction) || !isComponentFunction$1(componentFunction) || !isNodeOfType(componentFunction.body, "BlockStatement")) return null;
39211
38637
  if (!getDirectComponentBodyStatement(effectCall, componentFunction.body)) return null;
39212
38638
  const callbackPropNames = /* @__PURE__ */ new Set();
@@ -40194,7 +39620,7 @@ const isModuleScopedBinding = (identifier) => {
40194
39620
  const binding = findVariableInitializer(identifier, identifier.name);
40195
39621
  if (!binding) return false;
40196
39622
  if (isNodeOfType(binding.scopeOwner, "Program")) return true;
40197
- if (isNodeOfType(binding.scopeOwner, "BlockStatement")) return findEnclosingFunction$1(binding.scopeOwner) === null;
39623
+ if (isNodeOfType(binding.scopeOwner, "BlockStatement")) return findEnclosingFunction(binding.scopeOwner) === null;
40198
39624
  return false;
40199
39625
  };
40200
39626
  const looksLikeFreshUpdateExpression = (expression) => {
@@ -42111,9 +41537,9 @@ const isReturnedFromAnyEffectInScope = (functionNode, ownerScope) => {
42111
41537
  return isReturnedFromEffect;
42112
41538
  };
42113
41539
  const isInsideEffectCleanupReturn = (node, ownerScope) => {
42114
- let functionNode = findEnclosingFunction$1(node);
41540
+ let functionNode = findEnclosingFunction(node);
42115
41541
  while (functionNode) {
42116
- const outerFunction = findEnclosingFunction$1(functionNode);
41542
+ const outerFunction = findEnclosingFunction(functionNode);
42117
41543
  if (outerFunction && isEffectCallbackFunction(outerFunction) && isFunctionReturnedFromEffectCallback(functionNode, outerFunction)) return true;
42118
41544
  if (isReturnedFromAnyEffectInScope(functionNode, ownerScope)) return true;
42119
41545
  functionNode = outerFunction;
@@ -42121,7 +41547,7 @@ const isInsideEffectCleanupReturn = (node, ownerScope) => {
42121
41547
  return false;
42122
41548
  };
42123
41549
  const hasRefCurrentReassignmentAfterClear = (clearCall, refName) => {
42124
- const enclosingFunction = findEnclosingFunction$1(clearCall);
41550
+ const enclosingFunction = findEnclosingFunction(clearCall);
42125
41551
  if (!isFunctionLike$2(enclosingFunction)) return false;
42126
41552
  if (!isNodeOfType(enclosingFunction.body, "BlockStatement")) return false;
42127
41553
  const clearStart = getRangeStart(clearCall);
@@ -42951,7 +42377,7 @@ const isInsideAvailabilityGuard = (node, browserGlobalName, context) => {
42951
42377
  return false;
42952
42378
  };
42953
42379
  const isAfterAvailabilityEarlyExit = (node, componentOrHookNode, browserGlobalName, context) => {
42954
- const enclosingFunction = findEnclosingFunction$1(node);
42380
+ const enclosingFunction = findEnclosingFunction(node);
42955
42381
  if (!enclosingFunction || enclosingFunction !== componentOrHookNode && !executesDuringRender(enclosingFunction, context.scopes) || !isFunctionLike$2(enclosingFunction) || !isNodeOfType(enclosingFunction.body, "BlockStatement")) return false;
42956
42382
  let currentNode = node;
42957
42383
  while (currentNode !== enclosingFunction) {
@@ -44218,11 +43644,7 @@ const resolveSettings$8 = (settings) => {
44218
43644
  propNamePattern: ruleSettings.propNamePattern ?? "render*"
44219
43645
  };
44220
43646
  };
44221
- const isReactCreateElementCall = (node, scopes) => isReactApiCall(node, "createElement", scopes, {
44222
- allowGlobalReactNamespace: true,
44223
- resolveNamedAliases: true
44224
- });
44225
- const expressionContainsJsxOrCreateElement = (root, scopes) => {
43647
+ const expressionContainsJsxOrCreateElement = (root) => {
44226
43648
  let found = false;
44227
43649
  walkAst(root, (node) => {
44228
43650
  if (found) return false;
@@ -44231,17 +43653,17 @@ const expressionContainsJsxOrCreateElement = (root, scopes) => {
44231
43653
  found = true;
44232
43654
  return false;
44233
43655
  }
44234
- if (isNodeOfType(node, "CallExpression") && isReactCreateElementCall(node, scopes)) {
43656
+ if (isNodeOfType(node, "CallExpression") && isCreateElementCall(node)) {
44235
43657
  found = true;
44236
43658
  return false;
44237
43659
  }
44238
43660
  });
44239
43661
  return found;
44240
43662
  };
44241
- const functionContainsJsxOrCreateElement = (functionNode, scopes, controlFlow) => expressionContainsJsxOrCreateElement(functionNode, scopes) || functionReturnsMatchingExpression(functionNode, scopes, (expression) => expressionContainsJsxOrCreateElement(expression, scopes), controlFlow);
44242
- const isReactClassComponent = (classNode, scopes) => {
43663
+ const functionContainsJsxOrCreateElement = (functionNode, scopes, controlFlow) => expressionContainsJsxOrCreateElement(functionNode) || functionReturnsMatchingExpression(functionNode, scopes, expressionContainsJsxOrCreateElement, controlFlow);
43664
+ const isReactClassComponent = (classNode) => {
44243
43665
  if (isEs6Component(classNode)) return true;
44244
- return expressionContainsJsxOrCreateElement(classNode, scopes);
43666
+ return expressionContainsJsxOrCreateElement(classNode);
44245
43667
  };
44246
43668
  const findEnclosingComponent = (node, scopes, controlFlow) => {
44247
43669
  let walker = node.parent;
@@ -44258,7 +43680,7 @@ const findEnclosingComponent = (node, scopes, controlFlow) => {
44258
43680
  };
44259
43681
  }
44260
43682
  if (isNodeOfType(walker, "ClassDeclaration") || isNodeOfType(walker, "ClassExpression")) {
44261
- if (walker.id && isReactComponentName(walker.id.name) && isReactClassComponent(walker, scopes)) return {
43683
+ if (walker.id && isReactComponentName(walker.id.name) && isReactClassComponent(walker)) return {
44262
43684
  component: walker,
44263
43685
  name: walker.id.name
44264
43686
  };
@@ -44347,12 +43769,12 @@ const isObjectCallbackCandidate = (node) => {
44347
43769
  }
44348
43770
  return false;
44349
43771
  };
44350
- const hocCallContainsComponent = (call, scopes) => {
43772
+ const hocCallContainsComponent = (call) => {
44351
43773
  const firstArgument = call.arguments[0];
44352
43774
  if (!firstArgument) return false;
44353
- if (isNodeOfType(firstArgument, "FunctionExpression") || isNodeOfType(firstArgument, "ArrowFunctionExpression") || isNodeOfType(firstArgument, "ClassExpression")) return expressionContainsJsxOrCreateElement(firstArgument, scopes);
44354
- if (isNodeOfType(firstArgument, "CallExpression") && isHocCallee$1(firstArgument)) return hocCallContainsComponent(firstArgument, scopes);
44355
- return expressionContainsJsxOrCreateElement(firstArgument, scopes);
43775
+ if (isNodeOfType(firstArgument, "FunctionExpression") || isNodeOfType(firstArgument, "ArrowFunctionExpression") || isNodeOfType(firstArgument, "ClassExpression")) return expressionContainsJsxOrCreateElement(firstArgument);
43776
+ if (isNodeOfType(firstArgument, "CallExpression") && isHocCallee$1(firstArgument)) return hocCallContainsComponent(firstArgument);
43777
+ return expressionContainsJsxOrCreateElement(firstArgument);
44356
43778
  };
44357
43779
  const isFirstArgumentOfHocCall = (node) => {
44358
43780
  const parent = node.parent;
@@ -44385,35 +43807,19 @@ const isReturnOfMapCallback = (node) => {
44385
43807
  }
44386
43808
  return false;
44387
43809
  };
43810
+ const isCloneElementCall = (node) => {
43811
+ if (!isNodeOfType(node, "CallExpression")) return false;
43812
+ const callee = node.callee;
43813
+ if (isNodeOfType(callee, "Identifier")) return callee.name === "cloneElement";
43814
+ return isNodeOfType(callee, "MemberExpression") && isNodeOfType(callee.property, "Identifier") && callee.property.name === "cloneElement";
43815
+ };
44388
43816
  const TS_VALUE_PASSTHROUGH_TYPES = new Set([
44389
43817
  "TSAsExpression",
44390
43818
  "TSNonNullExpression",
44391
43819
  "TSSatisfiesExpression",
44392
43820
  "TSTypeAssertion"
44393
43821
  ]);
44394
- const ELEMENT_TYPE_PROP_NAMES = new Set([
44395
- "as",
44396
- "body",
44397
- "calendarcontainer",
44398
- "component",
44399
- "fallback",
44400
- "tooltip"
44401
- ]);
44402
- const isElementTypeJsxAttribute = (node) => {
44403
- if (!isNodeOfType(node, "JSXAttribute")) return false;
44404
- if (!isNodeOfType(node.name, "JSXIdentifier")) return false;
44405
- const attributeName = node.name.name;
44406
- return ELEMENT_TYPE_PROP_NAMES.has(attributeName.toLowerCase()) || attributeName.endsWith("Component");
44407
- };
44408
- const isReactUseMemoCallback = (call, valueNode, scopes) => call.arguments[0] === valueNode && isReactApiCall(call, "useMemo", scopes, {
44409
- allowGlobalReactNamespace: true,
44410
- resolveNamedAliases: true
44411
- });
44412
- const isReactLazyCall = (call, scopes) => isReactApiCall(call, "lazy", scopes, {
44413
- allowGlobalReactNamespace: true,
44414
- resolveNamedAliases: true
44415
- });
44416
- const isRenderFlowingReadReference = (identifier, scopes, visitedSymbols = /* @__PURE__ */ new Set()) => {
43822
+ const isRenderFlowingReadReference = (identifier) => {
44417
43823
  let valueNode = identifier;
44418
43824
  let parent = valueNode.parent;
44419
43825
  while (parent) {
@@ -44423,26 +43829,20 @@ const isRenderFlowingReadReference = (identifier, scopes, visitedSymbols = /* @_
44423
43829
  continue;
44424
43830
  }
44425
43831
  switch (parent.type) {
44426
- case "JSXOpeningElement": return parent.name === valueNode;
44427
- case "JSXExpressionContainer": return Boolean(parent.parent && isElementTypeJsxAttribute(parent.parent));
44428
- case "ReturnStatement": return false;
44429
- case "ArrowFunctionExpression": return false;
43832
+ case "JSXExpressionContainer":
43833
+ case "ReturnStatement": return true;
43834
+ case "ArrowFunctionExpression": return parent.body === valueNode;
44430
43835
  case "CallExpression":
44431
43836
  if (parent.callee === valueNode) return false;
44432
- if (isReactUseMemoCallback(parent, valueNode, scopes)) return false;
44433
- if (isReactCreateElementCall(parent, scopes)) return true;
43837
+ if (isCreateElementCall(parent) || isCloneElementCall(parent)) return true;
44434
43838
  valueNode = parent;
44435
43839
  parent = parent.parent;
44436
43840
  continue;
44437
- case "VariableDeclarator": {
44438
- if (parent.init !== valueNode || !isNodeOfType(parent.id, "Identifier")) return false;
44439
- const aliasSymbol = scopes.symbolFor(parent.id);
44440
- if (!aliasSymbol || aliasSymbol.kind !== "const" || visitedSymbols.has(aliasSymbol.id)) return false;
44441
- const nextVisitedSymbols = new Set(visitedSymbols);
44442
- nextVisitedSymbols.add(aliasSymbol.id);
44443
- return aliasSymbol.references.some((reference) => reference.flag === "read" && isRenderFlowingReadReference(reference.identifier, scopes, nextVisitedSymbols));
43841
+ case "VariableDeclarator": return parent.init === valueNode && isNodeOfType(parent.id, "Identifier") && isReactComponentName(parent.id.name);
43842
+ case "AssignmentExpression": {
43843
+ const assignmentTarget = parent.left;
43844
+ return parent.right === valueNode && isNodeOfType(assignmentTarget, "Identifier") && isReactComponentName(assignmentTarget.name);
44444
43845
  }
44445
- case "AssignmentExpression": return false;
44446
43846
  case "Property":
44447
43847
  if (parent.value !== valueNode) return false;
44448
43848
  valueNode = parent;
@@ -44480,7 +43880,6 @@ const noUnstableNestedComponents = defineRule({
44480
43880
  severity: "warn",
44481
43881
  recommendation: "Move nested components to module scope so React does not remount them and lose state on every render.",
44482
43882
  category: "Performance",
44483
- tags: ["react-jsx-only"],
44484
43883
  create: (context) => {
44485
43884
  const settings = resolveSettings$8(context.settings);
44486
43885
  const renderPropRegex = compileGlob(settings.propNamePattern);
@@ -44543,7 +43942,7 @@ const noUnstableNestedComponents = defineRule({
44543
43942
  },
44544
43943
  Identifier(node) {
44545
43944
  if (!isReactComponentName(node.name)) return;
44546
- if (!isRenderFlowingReadReference(node, context.scopes)) return;
43945
+ if (!isRenderFlowingReadReference(node)) return;
44547
43946
  recordInstantiation(node, node.name);
44548
43947
  },
44549
43948
  FunctionDeclaration: checkFunctionLike,
@@ -44552,33 +43951,28 @@ const noUnstableNestedComponents = defineRule({
44552
43951
  ClassDeclaration(node) {
44553
43952
  if (!node.id) return;
44554
43953
  if (!isReactComponentName(node.id.name)) return;
44555
- if (!isReactClassComponent(node, context.scopes)) return;
43954
+ if (!isReactClassComponent(node)) return;
44556
43955
  enqueueCandidate(node, null);
44557
43956
  },
44558
43957
  ClassExpression(node) {
44559
43958
  const inferredName = node.id?.name ?? inferFunctionLikeName(node);
44560
43959
  if (!inferredName || !isReactComponentName(inferredName)) return;
44561
- if (!isReactClassComponent(node, context.scopes)) return;
43960
+ if (!isReactClassComponent(node)) return;
44562
43961
  enqueueCandidate(node, null);
44563
43962
  },
44564
43963
  CallExpression(node) {
44565
- if (isReactCreateElementCall(node, context.scopes)) {
43964
+ if (isCreateElementCall(node)) {
44566
43965
  const firstArgument = node.arguments[0];
44567
43966
  if (firstArgument && isNodeOfType(firstArgument, "Identifier")) recordInstantiation(firstArgument, firstArgument.name);
44568
43967
  else if (firstArgument && isNodeOfType(firstArgument, "MemberExpression")) recordMemberChainInstantiation(firstArgument);
44569
43968
  }
44570
- const isReactLazy = isReactLazyCall(node, context.scopes);
44571
- if (!isReactLazy && !isHocCallee$1(node)) return;
44572
- if (!isReactLazy && !hocCallContainsComponent(node, context.scopes)) return;
44573
- const inferredName = inferFunctionLikeName(node);
44574
- const propInfo = isComponentDeclaredInProp(node);
44575
- if (propInfo === null && (!inferredName || !isReactComponentName(inferredName))) return;
44576
- enqueueCandidate(node, propInfo === null ? inferredName : null);
43969
+ if (!isHocCallee$1(node)) return;
43970
+ if (!hocCallContainsComponent(node)) return;
43971
+ enqueueCandidate(node, null);
44577
43972
  },
44578
43973
  "Program:exit"() {
44579
43974
  for (const report of queuedReports) {
44580
43975
  if (report.requiredInstantiationName !== null) {
44581
- if ((report.requiredInstantiationBinding ? context.scopes.symbolFor(report.requiredInstantiationBinding) : null)?.references.some((reference) => reference.flag === "write" || reference.flag === "read-write")) continue;
44582
43976
  if (!(report.requiredInstantiationBinding !== null ? instantiatedBindingIdentifiers.has(report.requiredInstantiationBinding) : instantiatedComponentNames.has(report.requiredInstantiationName))) continue;
44583
43977
  }
44584
43978
  context.report({
@@ -45611,7 +45005,7 @@ const findChildrenDestructuringFunction = (identifier, scopes) => {
45611
45005
  const symbol = scopes.symbolFor(identifier);
45612
45006
  if (symbol) {
45613
45007
  if (symbol.kind !== "parameter") return null;
45614
- const declaringFunction = findEnclosingFunction$1(symbol.bindingIdentifier);
45008
+ const declaringFunction = findEnclosingFunction(symbol.bindingIdentifier);
45615
45009
  if (declaringFunction && destructuresChildrenAsFirstParam(declaringFunction)) return declaringFunction;
45616
45010
  return null;
45617
45011
  }
@@ -45657,7 +45051,7 @@ const isChildrenMemberExpression = (node, scopes) => {
45657
45051
  const symbol = scopes.symbolFor(propsObject);
45658
45052
  if (symbol) {
45659
45053
  if (symbol.kind !== "parameter") return false;
45660
- const declaringFunction = findEnclosingFunction$1(symbol.bindingIdentifier);
45054
+ const declaringFunction = findEnclosingFunction(symbol.bindingIdentifier);
45661
45055
  return declaringFunction ? isDeclaringFunctionComponentLike(declaringFunction) : false;
45662
45056
  }
45663
45057
  return hasComponentLikeAncestorFunction(node);
@@ -46309,7 +45703,7 @@ const doesFunctionReturnsObjectLiteral = (functionNode) => {
46309
45703
  //#endregion
46310
45704
  //#region src/plugin/utils/enclosing-component-or-hook-scope.ts
46311
45705
  const enclosingComponentOrHookScope = (startNode, ownScopeFor) => {
46312
- const functionNode = findEnclosingFunction$1(startNode);
45706
+ const functionNode = findEnclosingFunction(startNode);
46313
45707
  if (!functionNode) return null;
46314
45708
  const displayName = componentOrHookDisplayNameForFunction(functionNode);
46315
45709
  if (!displayName) return null;
@@ -47371,7 +46765,7 @@ const isTanstackQuerySource = (source) => TANSTACK_QUERY_PACKAGE_PATTERN.test(so
47371
46765
  //#region src/plugin/rules/tanstack-query/query-destructure-result.ts
47372
46766
  const isHookReturnForwardingSpread = (objectExpression) => {
47373
46767
  const objectParent = objectExpression.parent;
47374
- const enclosingFunction = findEnclosingFunction$1(objectExpression);
46768
+ const enclosingFunction = findEnclosingFunction(objectExpression);
47375
46769
  if (!enclosingFunction) return false;
47376
46770
  if (!(isNodeOfType(objectParent, "ReturnStatement") || isNodeOfType(enclosingFunction, "ArrowFunctionExpression") && enclosingFunction.body === objectExpression)) return false;
47377
46771
  const enclosingName = componentOrHookDisplayNameForFunction(enclosingFunction);
@@ -47749,10 +47143,10 @@ const hasSuspensionBefore = (functionNode, boundary, context) => {
47749
47143
  return hasSuspension;
47750
47144
  };
47751
47145
  const isFunctionAncestor = (ancestor, functionNode) => {
47752
- let enclosingFunction = findEnclosingFunction$1(functionNode);
47146
+ let enclosingFunction = findEnclosingFunction(functionNode);
47753
47147
  while (enclosingFunction) {
47754
47148
  if (enclosingFunction === ancestor) return true;
47755
- enclosingFunction = findEnclosingFunction$1(enclosingFunction);
47149
+ enclosingFunction = findEnclosingFunction(enclosingFunction);
47756
47150
  }
47757
47151
  return false;
47758
47152
  };
@@ -47774,7 +47168,7 @@ const functionInvokesTarget = (callerFunction, targetFunction, context, visitedF
47774
47168
  return invokesTarget;
47775
47169
  };
47776
47170
  const isFunctionInvokedBefore = (invokedFunction, boundary, context) => {
47777
- const boundaryFunction = findEnclosingFunction$1(boundary);
47171
+ const boundaryFunction = findEnclosingFunction(boundary);
47778
47172
  const boundaryStart = getRangeStart(boundary);
47779
47173
  if (!boundaryFunction || boundaryStart === null) return false;
47780
47174
  let isInvokedBefore = false;
@@ -47811,11 +47205,11 @@ const isFunctionInvokedAfter = (invokedFunction, boundary, callerFunction, conte
47811
47205
  const isWriteExecutedBefore = (writeNode, boundary, context, deferredExecutionFunction) => {
47812
47206
  const writeStart = getRangeStart(writeNode);
47813
47207
  const boundaryStart = getRangeStart(boundary);
47814
- const writeFunction = findEnclosingFunction$1(writeNode);
47208
+ const writeFunction = findEnclosingFunction(writeNode);
47815
47209
  const writeExecutionBoundary = writeFunction ?? findProgramRoot(writeNode);
47816
47210
  if (writeStart === null || boundaryStart === null || !writeExecutionBoundary || !isNodeReachableWithinFunction(writeNode, context) || !isUnconditionallyExecuted(writeNode, writeExecutionBoundary, context)) return false;
47817
- const boundaryFunction = findEnclosingFunction$1(boundary);
47818
- const renderFunction = deferredExecutionFunction ? findEnclosingFunction$1(deferredExecutionFunction) : null;
47211
+ const boundaryFunction = findEnclosingFunction(boundary);
47212
+ const renderFunction = deferredExecutionFunction ? findEnclosingFunction(deferredExecutionFunction) : null;
47819
47213
  if (writeFunction === boundaryFunction) return writeStart < boundaryStart;
47820
47214
  if (!writeFunction) return writeStart < boundaryStart;
47821
47215
  if (boundaryFunction && isFunctionAncestor(writeFunction, boundaryFunction)) {
@@ -48087,8 +47481,8 @@ const queryStableQueryClient = defineRule({
48087
47481
  create: (context) => ({ NewExpression(node) {
48088
47482
  if (!isNodeOfType(node.callee, "Identifier") || node.callee.name !== "QueryClient") return;
48089
47483
  if (isStableHookWrapperArgument(node)) return;
48090
- let enclosingFunction = findEnclosingFunction$1(node);
48091
- while (enclosingFunction && isImmediatelyInvokedFunction(enclosingFunction)) enclosingFunction = findEnclosingFunction$1(enclosingFunction);
47484
+ let enclosingFunction = findEnclosingFunction(node);
47485
+ while (enclosingFunction && isImmediatelyInvokedFunction(enclosingFunction)) enclosingFunction = findEnclosingFunction(enclosingFunction);
48092
47486
  if (!enclosingFunction) return;
48093
47487
  if (!isComponentFunction(enclosingFunction)) return;
48094
47488
  context.report({
@@ -48183,7 +47577,7 @@ const reactCompilerNoManualMemoization = defineRule({
48183
47577
  const comparatorArgument = node.arguments?.[1];
48184
47578
  if (comparatorArgument && !isNullishComparatorArgument(comparatorArgument)) return;
48185
47579
  } else {
48186
- const enclosingFunction = findEnclosingFunction$1(node);
47580
+ const enclosingFunction = findEnclosingFunction(node);
48187
47581
  if (!enclosingFunction || !isCompilerInferableFunction(enclosingFunction)) return;
48188
47582
  }
48189
47583
  const removalMessage = REMOVAL_MESSAGE_BY_REACT_API_NAME.get(apiName);
@@ -51288,7 +50682,7 @@ const isReactNativeDimensionsCallee = (node, callee) => {
51288
50682
  };
51289
50683
  const STYLE_FACTORY_CALLEE_PATTERN$1 = /(?:^|\.)(?:make|create)(?:Use)?Styles$/;
51290
50684
  const isInsideStyleFactoryCallback = (node) => {
51291
- const enclosingFunction = findEnclosingFunction$1(node);
50685
+ const enclosingFunction = findEnclosingFunction(node);
51292
50686
  if (!enclosingFunction) return false;
51293
50687
  const callExpression = enclosingFunction.parent;
51294
50688
  if (!callExpression || !isNodeOfType(callExpression, "CallExpression")) return false;
@@ -58144,14 +57538,12 @@ const declarationAwaitsRequestScopedCall = (declaration) => {
58144
57538
  }
58145
57539
  return false;
58146
57540
  };
58147
- const declarationAwaitsGate = (declaration, context) => {
57541
+ const declarationAwaitsGate = (declaration) => {
58148
57542
  if (!isNodeOfType(declaration, "VariableDeclaration")) return false;
58149
57543
  for (const declarator of declaration.declarations ?? []) {
58150
57544
  if (!isNodeOfType(declarator.init, "AwaitExpression")) continue;
58151
57545
  const argument = declarator.init.argument;
58152
57546
  if (!isNodeOfType(argument, "CallExpression")) continue;
58153
- if (hasPossibleStaticMemberCallWrite(argument, context.scopes)) return true;
58154
- if (getOrderIndependentLocalFunction(argument, context.scopes) !== null) continue;
58155
57547
  const calleeName = getCalleeName$2(argument);
58156
57548
  if (!calleeName) continue;
58157
57549
  if (isAuthGuardName(calleeName)) return true;
@@ -58179,7 +57571,7 @@ const serverSequentialIndependentAwait = defineRule({
58179
57571
  if (declarationReadsAnyName(nextStatement, declaredNames)) continue;
58180
57572
  if (declarationAwaitsExistingPromise(nextStatement)) continue;
58181
57573
  if (declarationAwaitsRequestScopedCall(currentStatement) || declarationAwaitsRequestScopedCall(nextStatement)) continue;
58182
- if (declarationAwaitsGate(currentStatement, context)) continue;
57574
+ if (declarationAwaitsGate(currentStatement)) continue;
58183
57575
  context.report({
58184
57576
  node: nextStatement,
58185
57577
  message: "This await doesn't use the previous result, so your users wait twice as long for nothing."
@@ -59165,7 +58557,7 @@ const tanstackStartNoNavigateInRender = defineRule({
59165
58557
  const isReturnedFromCustomHook = (functionNode) => {
59166
58558
  const parent = functionNode.parent;
59167
58559
  if (isNodeOfType(parent, "ReturnStatement")) {
59168
- const outerFunction = findEnclosingFunction$1(parent);
58560
+ const outerFunction = findEnclosingFunction(parent);
59169
58561
  const hookName = outerFunction ? getFunctionBindingName$1(outerFunction) : null;
59170
58562
  return Boolean(hookName && HOOK_NAME_PATTERN$3.test(hookName));
59171
58563
  }
@@ -59182,13 +58574,13 @@ const tanstackStartNoNavigateInRender = defineRule({
59182
58574
  return parent.callee === functionNode || (parent.arguments ?? []).some((callArgument) => callArgument === functionNode);
59183
58575
  };
59184
58576
  const isDeferredNavigateCall = (callNode) => {
59185
- let enclosingFunction = findEnclosingFunction$1(callNode);
58577
+ let enclosingFunction = findEnclosingFunction(callNode);
59186
58578
  while (enclosingFunction) {
59187
58579
  if (isDeferredCallbackPosition(enclosingFunction)) return true;
59188
58580
  if (isWiredAsEventHandler(enclosingFunction)) return true;
59189
58581
  if (isReturnedFromCustomHook(enclosingFunction)) return true;
59190
58582
  if (!isSynchronouslyInvokedAnonymousWrapper(enclosingFunction)) return false;
59191
- enclosingFunction = findEnclosingFunction$1(enclosingFunction);
58583
+ enclosingFunction = findEnclosingFunction(enclosingFunction);
59192
58584
  }
59193
58585
  return false;
59194
58586
  };