oxlint-plugin-react-doctor 0.7.7-dev.a468589 → 0.7.7-dev.af58965

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 +1707 -796
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1194,7 +1194,7 @@ const findVariableInitializer = (referenceNode, bindingName) => {
1194
1194
  * (`FUNCTION_LIKE_TYPES.has(node.type)`) and as a type-guard. The
1195
1195
  * type-guard form covers both shapes without callers paying a cast.
1196
1196
  */
1197
- const isFunctionLike$2 = (node) => Boolean(node && (isNodeOfType(node, "ArrowFunctionExpression") || isNodeOfType(node, "FunctionExpression") || isNodeOfType(node, "FunctionDeclaration")));
1197
+ const isFunctionLike$1 = (node) => Boolean(node && (isNodeOfType(node, "ArrowFunctionExpression") || isNodeOfType(node, "FunctionExpression") || isNodeOfType(node, "FunctionDeclaration")));
1198
1198
  //#endregion
1199
1199
  //#region src/plugin/utils/strip-paren-expression.ts
1200
1200
  const TRANSPARENT_EXPRESSION_WRAPPER_TYPES = new Set([
@@ -1230,13 +1230,13 @@ const resolveConstIdentifierAlias = (identifier, scopes) => {
1230
1230
  //#region src/plugin/utils/resolve-exact-local-function.ts
1231
1231
  const resolveExactLocalFunction = (expression, scopes) => {
1232
1232
  const unwrappedExpression = stripParenExpression(expression);
1233
- if (isFunctionLike$2(unwrappedExpression)) return unwrappedExpression;
1233
+ if (isFunctionLike$1(unwrappedExpression)) return unwrappedExpression;
1234
1234
  if (!isNodeOfType(unwrappedExpression, "Identifier")) return null;
1235
1235
  const symbol = resolveConstIdentifierAlias(unwrappedExpression, scopes);
1236
- if (symbol?.kind === "function") return !symbol.references.some((reference) => reference.flag !== "read") && isFunctionLike$2(symbol.declarationNode) ? symbol.declarationNode : null;
1236
+ if (symbol?.kind === "function") return !symbol.references.some((reference) => reference.flag !== "read") && isFunctionLike$1(symbol.declarationNode) ? symbol.declarationNode : null;
1237
1237
  if (symbol?.kind !== "const" || !symbol.initializer) return null;
1238
1238
  const unwrappedInitializer = stripParenExpression(symbol.initializer);
1239
- return isFunctionLike$2(unwrappedInitializer) ? unwrappedInitializer : null;
1239
+ return isFunctionLike$1(unwrappedInitializer) ? unwrappedInitializer : null;
1240
1240
  };
1241
1241
  //#endregion
1242
1242
  //#region src/plugin/utils/get-effect-callback.ts
@@ -1921,9 +1921,9 @@ const isComponentIdentifierName = (name) => {
1921
1921
  const firstCharacter = name[0];
1922
1922
  return Boolean(firstCharacter && firstCharacter === firstCharacter.toUpperCase());
1923
1923
  };
1924
- const isFunctionLike$1 = (node) => Boolean(node && (isNodeOfType(node, "FunctionDeclaration") || isNodeOfType(node, "FunctionExpression") || isNodeOfType(node, "ArrowFunctionExpression")));
1924
+ const isFunctionLike = (node) => Boolean(node && (isNodeOfType(node, "FunctionDeclaration") || isNodeOfType(node, "FunctionExpression") || isNodeOfType(node, "ArrowFunctionExpression")));
1925
1925
  const markFunctionReturnJsx = (functionNode, programRoot, generatedImageJsxNodes, visitedComponentNames) => {
1926
- if (!isFunctionLike$1(functionNode)) return;
1926
+ if (!isFunctionLike(functionNode)) return;
1927
1927
  if (isNodeOfType(functionNode, "ArrowFunctionExpression")) {
1928
1928
  const body = stripParenExpression(functionNode.body);
1929
1929
  if (!isNodeOfType(body, "BlockStatement")) {
@@ -1934,7 +1934,7 @@ const markFunctionReturnJsx = (functionNode, programRoot, generatedImageJsxNodes
1934
1934
  const body = functionNode.body;
1935
1935
  if (!isNodeOfType(body, "BlockStatement")) return;
1936
1936
  walkAst(body, (descendantNode) => {
1937
- if (descendantNode !== body && isFunctionLike$1(descendantNode)) return false;
1937
+ if (descendantNode !== body && isFunctionLike(descendantNode)) return false;
1938
1938
  if (!isNodeOfType(descendantNode, "ReturnStatement")) return;
1939
1939
  if (!descendantNode.argument) return;
1940
1940
  markGeneratedImageExpression(stripParenExpression(descendantNode.argument), programRoot, generatedImageJsxNodes, visitedComponentNames);
@@ -1996,7 +1996,7 @@ const markGeneratedImageExpression = (expression, programRoot, generatedImageJsx
1996
1996
  markJsxSubtree(unwrappedExpression, programRoot, generatedImageJsxNodes, visitedComponentNames);
1997
1997
  return;
1998
1998
  }
1999
- if (isFunctionLike$1(unwrappedExpression)) {
1999
+ if (isFunctionLike(unwrappedExpression)) {
2000
2000
  markFunctionReturnJsx(unwrappedExpression, programRoot, generatedImageJsxNodes, visitedComponentNames);
2001
2001
  return;
2002
2002
  }
@@ -2012,7 +2012,7 @@ const markGeneratedImageExpression = (expression, programRoot, generatedImageJsx
2012
2012
  }
2013
2013
  if (isNodeOfType(unwrappedExpression, "CallExpression")) {
2014
2014
  const callee = unwrappedExpression.callee;
2015
- if (isFunctionLike$1(callee)) {
2015
+ if (isFunctionLike(callee)) {
2016
2016
  markFunctionReturnJsx(callee, programRoot, generatedImageJsxNodes, visitedComponentNames);
2017
2017
  return;
2018
2018
  }
@@ -2021,7 +2021,7 @@ const markGeneratedImageExpression = (expression, programRoot, generatedImageJsx
2021
2021
  if (hasNormalJsxUsage(programRoot, callee.name, generatedImageJsxNodes)) return;
2022
2022
  if (hasNormalFunctionCallUsage(programRoot, callee.name)) return;
2023
2023
  const binding = findVariableInitializer(callee, callee.name);
2024
- if (!binding?.initializer || !isFunctionLike$1(stripParenExpression(binding.initializer))) return;
2024
+ if (!binding?.initializer || !isFunctionLike(stripParenExpression(binding.initializer))) return;
2025
2025
  visitedComponentNames.add(callee.name);
2026
2026
  markFunctionReturnJsx(stripParenExpression(binding.initializer), programRoot, generatedImageJsxNodes, visitedComponentNames);
2027
2027
  return;
@@ -4480,7 +4480,7 @@ const getPotentiallyAliasedSymbols = (identifier, scopes) => {
4480
4480
  const findExecutionBoundary = (node) => {
4481
4481
  let current = node;
4482
4482
  while (current) {
4483
- if (isFunctionLike$2(current) || isNodeOfType(current, "Program")) return current;
4483
+ if (isFunctionLike$1(current) || isNodeOfType(current, "Program")) return current;
4484
4484
  current = current.parent ?? null;
4485
4485
  }
4486
4486
  return null;
@@ -4509,7 +4509,7 @@ const findDirectCall = (identifier) => {
4509
4509
  return parent && isNodeOfType(parent, "CallExpression") && parent.callee === callee ? parent : null;
4510
4510
  };
4511
4511
  const isFunctionSynchronouslyInvokedBefore = (functionNode, referenceNode, scopes, visitedFunctionNodes = /* @__PURE__ */ new Set()) => {
4512
- if (visitedFunctionNodes.has(functionNode) || !isFunctionLike$2(functionNode) || functionNode.generator) return false;
4512
+ if (visitedFunctionNodes.has(functionNode) || !isFunctionLike$1(functionNode) || functionNode.generator) return false;
4513
4513
  visitedFunctionNodes.add(functionNode);
4514
4514
  const referenceBoundary = findExecutionBoundary(referenceNode);
4515
4515
  if (!referenceBoundary) return false;
@@ -4528,7 +4528,7 @@ const isFunctionSynchronouslyInvokedBefore = (functionNode, referenceNode, scope
4528
4528
  const callBoundary = findExecutionBoundary(call);
4529
4529
  if (!callBoundary) return false;
4530
4530
  if (callBoundary === referenceBoundary) return true;
4531
- if (!isFunctionLike$2(callBoundary)) return false;
4531
+ if (!isFunctionLike$1(callBoundary)) return false;
4532
4532
  return isFunctionSynchronouslyInvokedBefore(callBoundary, referenceNode, scopes, new Set(visitedFunctionNodes));
4533
4533
  });
4534
4534
  };
@@ -4556,7 +4556,7 @@ const symbolHasStaticPropertyWriteBefore = (symbol, propertyName, referenceNode,
4556
4556
  const referenceBoundary = findExecutionBoundary(referenceNode);
4557
4557
  if (!writeBoundary || !referenceBoundary || !isOnUnconditionalPath(writeTarget, writeBoundary)) return false;
4558
4558
  if (writeBoundary === referenceBoundary) return writeTarget.range[0] < referenceNode.range[0];
4559
- return isFunctionLike$2(writeBoundary) && isFunctionSynchronouslyInvokedBefore(writeBoundary, referenceNode, scopes);
4559
+ return isFunctionLike$1(writeBoundary) && isFunctionSynchronouslyInvokedBefore(writeBoundary, referenceNode, scopes);
4560
4560
  });
4561
4561
  const isStableStaticPropertyReference = (identifier) => {
4562
4562
  if (isDirectAliasSourceReference(identifier)) return true;
@@ -4597,7 +4597,7 @@ const hasStaticPropertyWriteBefore = (identifier, propertyName, referenceNode, s
4597
4597
  const findEnclosingFunction$1 = (node) => {
4598
4598
  let cursor = node.parent;
4599
4599
  while (cursor) {
4600
- if (isFunctionLike$2(cursor)) return cursor;
4600
+ if (isFunctionLike$1(cursor)) return cursor;
4601
4601
  cursor = cursor.parent ?? null;
4602
4602
  }
4603
4603
  return null;
@@ -4656,7 +4656,7 @@ const isCommutativeParameterMutation = (statement, parameterNames) => {
4656
4656
  return isNodeOfType(receiver, "Identifier") && parameterNames.has(receiver.name) && isNodeOfType(stripParenExpression(statement.expression.right), "Literal");
4657
4657
  };
4658
4658
  const isOrderIndependentFunction = (functionNode, scopes) => {
4659
- if (!isFunctionLike$2(functionNode)) return false;
4659
+ if (!isFunctionLike$1(functionNode)) return false;
4660
4660
  const parameterNames = /* @__PURE__ */ new Set();
4661
4661
  for (const parameter of functionNode.params) {
4662
4662
  if (!isNodeOfType(parameter, "Identifier")) return false;
@@ -4704,7 +4704,7 @@ const resolveOrderIndependentObjectPropertyFunction = (objectExpression, propert
4704
4704
  }
4705
4705
  if (!matchingProperty || !isNodeOfType(matchingProperty, "Property")) return null;
4706
4706
  const propertyValue = stripParenExpression(matchingProperty.value);
4707
- if (isFunctionLike$2(propertyValue)) return isOrderIndependentFunction(propertyValue, scopes) ? propertyValue : null;
4707
+ if (isFunctionLike$1(propertyValue)) return isOrderIndependentFunction(propertyValue, scopes) ? propertyValue : null;
4708
4708
  return resolveOrderIndependentLocalFunction(propertyValue, callExpression, scopes, visitedSymbolIds);
4709
4709
  };
4710
4710
  const resolveOrderIndependentLocalFunction = (callee, callExpression, scopes, visitedSymbolIds) => {
@@ -4722,7 +4722,7 @@ const resolveOrderIndependentLocalFunction = (callee, callExpression, scopes, vi
4722
4722
  const initializer = stripParenExpression(symbol.initializer);
4723
4723
  const destructuredPropertyName = getDestructuredBindingPropertyName(symbol.bindingIdentifier);
4724
4724
  if (destructuredPropertyName !== null) return resolveOrderIndependentObjectPropertyFunction(initializer, destructuredPropertyName, callExpression, scopes, visitedSymbolIds);
4725
- if (isFunctionLike$2(initializer)) return isOrderIndependentFunction(initializer, scopes) ? initializer : null;
4725
+ if (isFunctionLike$1(initializer)) return isOrderIndependentFunction(initializer, scopes) ? initializer : null;
4726
4726
  if (symbol.kind !== "const") return null;
4727
4727
  return resolveOrderIndependentLocalFunction(initializer, callExpression, scopes, visitedSymbolIds);
4728
4728
  };
@@ -4755,7 +4755,7 @@ const findFirstAwaitOutsideNestedFunctions = (block, skipNestedLoops = false) =>
4755
4755
  let firstAwait = null;
4756
4756
  walkAst(block, (child) => {
4757
4757
  if (firstAwait) return false;
4758
- if (child !== block && isFunctionLike$2(child)) return false;
4758
+ if (child !== block && isFunctionLike$1(child)) return false;
4759
4759
  if (skipNestedLoops && child !== block && LOOP_STATEMENT_TYPES.has(child.type)) return false;
4760
4760
  if (isNodeOfType(child, "AwaitExpression")) firstAwait = child;
4761
4761
  });
@@ -4835,7 +4835,7 @@ const ARRAY_MUTATION_METHOD_NAMES = new Set([
4835
4835
  const addDerivedBindings = (block, names) => {
4836
4836
  const declaratorBindings = [];
4837
4837
  walkAst(block, (child) => {
4838
- if (child !== block && isFunctionLike$2(child)) return false;
4838
+ if (child !== block && isFunctionLike$1(child)) return false;
4839
4839
  if (!isNodeOfType(child, "VariableDeclarator") || !child.init) return;
4840
4840
  if (!isNodeOfType(child.id, "Identifier")) return;
4841
4841
  const referencedNames = /* @__PURE__ */ new Set();
@@ -4862,7 +4862,7 @@ const hasLoopCarriedDependency = (block) => {
4862
4862
  const carried = /* @__PURE__ */ new Set();
4863
4863
  const awaitedReferences = /* @__PURE__ */ new Set();
4864
4864
  walkAst(block, (child) => {
4865
- if (child !== block && isFunctionLike$2(child)) return false;
4865
+ if (child !== block && isFunctionLike$1(child)) return false;
4866
4866
  if (isNodeOfType(child, "AssignmentExpression") && child.left) {
4867
4867
  collectPatternIdentifiers(child.left, carried);
4868
4868
  return;
@@ -4884,7 +4884,7 @@ const NESTED_LOOP_OR_SWITCH_TYPES = new Set([...LOOP_TYPES, "SwitchStatement"]);
4884
4884
  const collectAwaitAssignedBindingNames = (block) => {
4885
4885
  const awaitAssignedNames = /* @__PURE__ */ new Set();
4886
4886
  walkAst(block, (child) => {
4887
- if (child !== block && isFunctionLike$2(child)) return false;
4887
+ if (child !== block && isFunctionLike$1(child)) return false;
4888
4888
  if (isNodeOfType(child, "VariableDeclarator") && child.id && containsDirectAwait(child.init)) collectPatternIdentifiers(child.id, awaitAssignedNames);
4889
4889
  if (isNodeOfType(child, "AssignmentExpression") && child.left && containsDirectAwait(child.right)) collectPatternIdentifiers(child.left, awaitAssignedNames);
4890
4890
  });
@@ -4954,7 +4954,7 @@ const loopBodyHasAwaitDependentEarlyExit = (block, loopLabelName) => {
4954
4954
  let hasAwaitDependentExit = false;
4955
4955
  walkAst(block, (child) => {
4956
4956
  if (hasAwaitDependentExit) return false;
4957
- if (child !== block && isFunctionLike$2(child)) return false;
4957
+ if (child !== block && isFunctionLike$1(child)) return false;
4958
4958
  if (!(isNodeOfType(child, "ReturnStatement") || isNodeOfType(child, "BreakStatement") && doesBreakExitInspectedLoop(child, block, loopLabelName))) return;
4959
4959
  if (isExitAwaitDependent(child, block, awaitAssignedNames)) {
4960
4960
  hasAwaitDependentExit = true;
@@ -4976,7 +4976,7 @@ const MUTATING_ARRAY_METHOD_NAMES$1 = new Set([
4976
4976
  const collectBodyWrittenBindingNames = (block) => {
4977
4977
  const writtenNames = /* @__PURE__ */ new Set();
4978
4978
  walkAst(block, (child) => {
4979
- if (child !== block && isFunctionLike$2(child)) return false;
4979
+ if (child !== block && isFunctionLike$1(child)) return false;
4980
4980
  if (isNodeOfType(child, "AssignmentExpression") && child.left) {
4981
4981
  collectPatternIdentifiers(child.left, writtenNames);
4982
4982
  const assignedRootName = getRootObjectIdentifierName(child.left);
@@ -5072,7 +5072,7 @@ const resolvePromiseFlowNode = (mapCall) => {
5072
5072
  };
5073
5073
  const findEnclosingFunctionOrProgram = (node) => {
5074
5074
  let current = node;
5075
- while (current.parent && !isFunctionLike$2(current)) current = current.parent;
5075
+ while (current.parent && !isFunctionLike$1(current)) current = current.parent;
5076
5076
  return current;
5077
5077
  };
5078
5078
  const isBindingCombinedWithPromiseConcurrency = (bindingName, scope) => {
@@ -5101,7 +5101,7 @@ const isWrappedInPromiseConcurrency = (mapCall) => {
5101
5101
  };
5102
5102
  const isLoopInsideWorkerPoolFunction = (loopNode) => {
5103
5103
  const enclosingFunction = findEnclosingFunctionOrProgram(loopNode);
5104
- if (!isFunctionLike$2(enclosingFunction)) return false;
5104
+ if (!isFunctionLike$1(enclosingFunction)) return false;
5105
5105
  let functionBindingName = null;
5106
5106
  if (isNodeOfType(enclosingFunction, "FunctionDeclaration") && isNodeOfType(enclosingFunction.id, "Identifier")) functionBindingName = enclosingFunction.id.name;
5107
5107
  else if (isNodeOfType(enclosingFunction.parent, "VariableDeclarator") && isNodeOfType(enclosingFunction.parent.id, "Identifier")) functionBindingName = enclosingFunction.parent.id.name;
@@ -5369,7 +5369,7 @@ const guardConsequentPerformsSideEffects = (consequent) => {
5369
5369
  let performsSideEffects = false;
5370
5370
  walkAst(consequent, (child) => {
5371
5371
  if (performsSideEffects) return false;
5372
- if (isFunctionLike$2(child)) return false;
5372
+ if (isFunctionLike$1(child)) return false;
5373
5373
  if (isNodeOfType(child, "ThrowStatement")) return false;
5374
5374
  if (isNodeOfType(child, "CallExpression") || isNodeOfType(child, "NewExpression") || isNodeOfType(child, "AssignmentExpression") || isNodeOfType(child, "UpdateExpression")) {
5375
5375
  performsSideEffects = true;
@@ -5381,7 +5381,7 @@ const guardConsequentPerformsSideEffects = (consequent) => {
5381
5381
  const findEnclosingFunction = (node) => {
5382
5382
  let ancestor = node.parent;
5383
5383
  while (ancestor) {
5384
- if (isFunctionLike$2(ancestor)) return ancestor;
5384
+ if (isFunctionLike$1(ancestor)) return ancestor;
5385
5385
  ancestor = ancestor.parent;
5386
5386
  }
5387
5387
  return null;
@@ -5392,7 +5392,7 @@ const guardTestReadsReassignedLocal = (test, guardStatement) => {
5392
5392
  collectReferenceIdentifierNames(test, testIdentifierNames);
5393
5393
  if (testIdentifierNames.size === 0) return false;
5394
5394
  const enclosingFunction = findEnclosingFunction(guardStatement);
5395
- if (!enclosingFunction || !isFunctionLike$2(enclosingFunction) || !enclosingFunction.body) return false;
5395
+ if (!enclosingFunction || !isFunctionLike$1(enclosingFunction) || !enclosingFunction.body) return false;
5396
5396
  let readsReassignedLocal = false;
5397
5397
  walkAst(enclosingFunction.body, (child) => {
5398
5398
  if (readsReassignedLocal) return false;
@@ -5487,13 +5487,13 @@ const asyncDeferAwait = defineRule({
5487
5487
  const inspectAllStatementBlocks = (functionBody) => {
5488
5488
  if (!functionBody) return;
5489
5489
  walkAst(functionBody, (descendant) => {
5490
- if (isFunctionLike$2(descendant)) return false;
5490
+ if (isFunctionLike$1(descendant)) return false;
5491
5491
  if (isNodeOfType(descendant, "BlockStatement")) inspectStatements(descendant.body ?? []);
5492
5492
  else if (isNodeOfType(descendant, "SwitchCase")) inspectStatements(descendant.consequent ?? []);
5493
5493
  });
5494
5494
  };
5495
5495
  const enterFunction = (node) => {
5496
- if (!isFunctionLike$2(node)) return;
5496
+ if (!isFunctionLike$1(node)) return;
5497
5497
  if (!node.async) return;
5498
5498
  if (!isNodeOfType(node.body, "BlockStatement")) return;
5499
5499
  inspectAllStatementBlocks(node.body);
@@ -5598,7 +5598,7 @@ const sequenceContainsSerializationSignal = (statements, context) => {
5598
5598
  const isInsideTransactionCallback = (node) => {
5599
5599
  let current = node.parent;
5600
5600
  while (current) {
5601
- if (isFunctionLike$2(current)) {
5601
+ if (isFunctionLike$1(current)) {
5602
5602
  const callParent = current.parent;
5603
5603
  if (callParent && isNodeOfType(callParent, "CallExpression")) {
5604
5604
  const callee = callParent.callee;
@@ -6937,7 +6937,7 @@ const catchReturnsFallback = (tryStatement) => {
6937
6937
  let hasReturn = false;
6938
6938
  let hasThrow = false;
6939
6939
  walkAst(handler.body, (child) => {
6940
- if (isFunctionLike$2(child)) return false;
6940
+ if (isFunctionLike$1(child)) return false;
6941
6941
  if (isNodeOfType(child, "ReturnStatement")) hasReturn = true;
6942
6942
  if (isNodeOfType(child, "ThrowStatement")) hasThrow = true;
6943
6943
  });
@@ -6949,10 +6949,10 @@ const resolveValidatorFunction = (callee, scopes) => {
6949
6949
  const symbol = scopes.symbolFor(unwrappedCallee);
6950
6950
  if (!symbol) return null;
6951
6951
  const candidate = symbol.kind === "function" ? symbol.declarationNode : symbol.initializer;
6952
- return isFunctionLike$2(candidate) ? candidate : null;
6952
+ return isFunctionLike$1(candidate) ? candidate : null;
6953
6953
  };
6954
6954
  const validatorChecksPayloadProperties = (validatorFunction, scopes) => {
6955
- if (!isFunctionLike$2(validatorFunction)) return false;
6955
+ if (!isFunctionLike$1(validatorFunction)) return false;
6956
6956
  const firstParameter = validatorFunction.params?.[0];
6957
6957
  if (!firstParameter || !isNodeOfType(firstParameter, "Identifier")) return false;
6958
6958
  const parameterSymbol = scopes.symbolFor(firstParameter);
@@ -6960,7 +6960,7 @@ const validatorChecksPayloadProperties = (validatorFunction, scopes) => {
6960
6960
  const payloadSymbolIds = new Set([parameterSymbol.id]);
6961
6961
  let hasPropertyTypeCheck = false;
6962
6962
  walkAst(validatorFunction.body, (child) => {
6963
- if (isFunctionLike$2(child)) return false;
6963
+ if (isFunctionLike$1(child)) return false;
6964
6964
  if (isNodeOfType(child, "VariableDeclarator") && isNodeOfType(child.id, "Identifier") && child.init) {
6965
6965
  const initializer = stripParenExpression(child.init);
6966
6966
  if (isNodeOfType(initializer, "Identifier")) {
@@ -7004,7 +7004,7 @@ const collectSafelyValidatedLocalStorageKeys = ({ programNode, scopes, resolveKe
7004
7004
  const rawValueKeys = /* @__PURE__ */ new Map();
7005
7005
  const parsedValueSources = /* @__PURE__ */ new Map();
7006
7006
  walkAst(child.block, (tryChild) => {
7007
- if (isFunctionLike$2(tryChild)) return false;
7007
+ if (isFunctionLike$1(tryChild)) return false;
7008
7008
  if (isNodeOfType(tryChild, "VariableDeclarator") && isNodeOfType(tryChild.id, "Identifier") && tryChild.init) {
7009
7009
  const initializer = stripParenExpression(tryChild.init);
7010
7010
  if (isNodeOfType(initializer, "CallExpression") && isLocalStorageCall(initializer, "getItem")) {
@@ -7144,7 +7144,7 @@ const resolveExpressionKey$1 = (expression, context, visitedSymbolIds = /* @__PU
7144
7144
  }
7145
7145
  if (isNodeOfType(unwrappedExpression, "ThisExpression")) return "this";
7146
7146
  if (isNodeOfType(unwrappedExpression, "Literal") && (typeof unwrappedExpression.value === "string" || typeof unwrappedExpression.value === "number")) return `literal:${String(unwrappedExpression.value)}`;
7147
- if (isFunctionLike$2(unwrappedExpression)) {
7147
+ if (isFunctionLike$1(unwrappedExpression)) {
7148
7148
  const rangeStart = getRangeStart(unwrappedExpression);
7149
7149
  return rangeStart === null ? null : `function:${rangeStart}`;
7150
7150
  }
@@ -7306,15 +7306,15 @@ const getLocalCalledFunction = (callExpression, context) => {
7306
7306
  if (!isNodeOfType(callee, "Identifier")) return null;
7307
7307
  const symbol = context.scopes.symbolFor(callee);
7308
7308
  const candidate = symbol?.initializer ?? symbol?.declarationNode;
7309
- return candidate && isFunctionLike$2(stripParenExpression(candidate)) ? stripParenExpression(candidate) : null;
7309
+ return candidate && isFunctionLike$1(stripParenExpression(candidate)) ? stripParenExpression(candidate) : null;
7310
7310
  };
7311
7311
  const hasDominatingEscapeMutation = (symbol, callNode, context, mutationIndex) => getSymbolEscapeCalls(symbol, context).some((escape) => escape.callExpression !== callNode && mutationDominatesCall(escape.callExpression, callNode, context) && callMayMutateArgument(escape.callExpression, escape.argumentIndex, context, mutationIndex, /* @__PURE__ */ new Map()));
7312
7312
  const factoryReturnsMutatedReceiver = (receiver, methodName, context, mutationIndex) => {
7313
7313
  const factory = getLocalCalledFunction(stripParenExpression(receiver), context);
7314
- if (!factory || !isFunctionLike$2(factory)) return false;
7314
+ if (!factory || !isFunctionLike$1(factory)) return false;
7315
7315
  const returnStatements = [];
7316
7316
  walkAst(factory.body, (node) => {
7317
- if (node !== factory.body && isFunctionLike$2(node)) return false;
7317
+ if (node !== factory.body && isFunctionLike$1(node)) return false;
7318
7318
  if (isNodeOfType(node, "ReturnStatement") && node.argument) returnStatements.push(node);
7319
7319
  });
7320
7320
  return returnStatements.length > 0 && returnStatements.every((returnStatement) => {
@@ -7395,11 +7395,11 @@ const getSymbolEscapeCalls = (symbol, context, visitedSymbols = /* @__PURE__ */
7395
7395
  return result;
7396
7396
  };
7397
7397
  const functionReturnsParameter = (functionNode, parameterIdentity, context) => {
7398
- if (!isFunctionLike$2(functionNode)) return false;
7398
+ if (!isFunctionLike$1(functionNode)) return false;
7399
7399
  if (isNodeOfType(functionNode, "ArrowFunctionExpression") && !isNodeOfType(functionNode.body, "BlockStatement")) return resolveExpressionKey$1(functionNode.body, context) === parameterIdentity;
7400
7400
  const returnStatements = [];
7401
7401
  walkAst(functionNode.body, (node) => {
7402
- if (node !== functionNode.body && isFunctionLike$2(node)) return false;
7402
+ if (node !== functionNode.body && isFunctionLike$1(node)) return false;
7403
7403
  if (isNodeOfType(node, "ReturnStatement")) returnStatements.push(node);
7404
7404
  });
7405
7405
  return returnStatements.length > 0 && returnStatements.every((returnStatement) => isNodeOfType(returnStatement, "ReturnStatement") && returnStatement.argument && resolveExpressionKey$1(returnStatement.argument, context) === parameterIdentity);
@@ -7419,7 +7419,7 @@ const getCallResultSymbol = (callExpression, context) => {
7419
7419
  };
7420
7420
  const callMayMutateArgument = (callExpression, argumentIndex, context, mutationIndex, visitedParameterIndexesByFunction) => {
7421
7421
  const calledFunction = getLocalCalledFunction(callExpression, context);
7422
- if (!calledFunction || !isFunctionLike$2(calledFunction)) return true;
7422
+ if (!calledFunction || !isFunctionLike$1(calledFunction)) return true;
7423
7423
  if (calledFunction.generator) return false;
7424
7424
  const visitedParameterIndexes = visitedParameterIndexesByFunction.get(calledFunction) ?? /* @__PURE__ */ new Set();
7425
7425
  if (visitedParameterIndexes.has(argumentIndex)) return false;
@@ -7496,10 +7496,10 @@ const createMethodMutationAnalysis = (context) => {
7496
7496
  //#endregion
7497
7497
  //#region src/plugin/utils/collect-function-return-statements.ts
7498
7498
  const collectFunctionReturnStatements = (functionNode) => {
7499
- if (!isFunctionLike$2(functionNode) || !isNodeOfType(functionNode.body, "BlockStatement")) return [];
7499
+ if (!isFunctionLike$1(functionNode) || !isNodeOfType(functionNode.body, "BlockStatement")) return [];
7500
7500
  const returnStatements = [];
7501
7501
  walkAst(functionNode.body, (node) => {
7502
- if (node !== functionNode.body && (isFunctionLike$2(node) || isNodeOfType(node, "ClassDeclaration") || isNodeOfType(node, "ClassExpression"))) return false;
7502
+ if (node !== functionNode.body && (isFunctionLike$1(node) || isNodeOfType(node, "ClassDeclaration") || isNodeOfType(node, "ClassExpression"))) return false;
7503
7503
  if (isNodeOfType(node, "ReturnStatement")) returnStatements.push(node);
7504
7504
  });
7505
7505
  return returnStatements;
@@ -7517,7 +7517,7 @@ const statementAlwaysExits = (statement) => {
7517
7517
  const REASSIGNABLE_BINDING_KINDS = new Set(["let", "var"]);
7518
7518
  const CONDITIONAL_EXPRESSION_TYPES = new Set(["ConditionalExpression", "LogicalExpression"]);
7519
7519
  const collectReturnedExpressions = (functionNode) => {
7520
- if (!isFunctionLike$2(functionNode) || !functionNode.body) return [];
7520
+ if (!isFunctionLike$1(functionNode) || !functionNode.body) return [];
7521
7521
  if (!isNodeOfType(functionNode.body, "BlockStatement")) return [functionNode.body];
7522
7522
  return collectFunctionReturnStatements(functionNode).flatMap((returnStatement) => returnStatement.argument ? [returnStatement.argument] : []);
7523
7523
  };
@@ -7619,11 +7619,11 @@ const collectPossibleAssignedExpressions = (symbol, referenceNode, controlFlow)
7619
7619
  return [...applyDefinitions(incomingDefinitionsByBlock.get(referenceBlock) ?? /* @__PURE__ */ new Set(), definitionsBeforeReference)].map((definition) => definition.expression);
7620
7620
  };
7621
7621
  const functionHasBareReturn = (functionNode) => {
7622
- if (!isFunctionLike$2(functionNode) || !isNodeOfType(functionNode.body, "BlockStatement")) return false;
7622
+ if (!isFunctionLike$1(functionNode) || !isNodeOfType(functionNode.body, "BlockStatement")) return false;
7623
7623
  let didFindBareReturn = false;
7624
7624
  walkAst(functionNode.body, (node) => {
7625
7625
  if (didFindBareReturn) return false;
7626
- if (node !== functionNode.body && isFunctionLike$2(node)) return false;
7626
+ if (node !== functionNode.body && isFunctionLike$1(node)) return false;
7627
7627
  if (isNodeOfType(node, "ReturnStatement") && !node.argument) didFindBareReturn = true;
7628
7628
  });
7629
7629
  return didFindBareReturn;
@@ -7635,7 +7635,7 @@ const functionReturnsMatchingExpression = (functionNode, scopes, matchesExpressi
7635
7635
  if (visitedFunctions.has(candidateFunction)) return false;
7636
7636
  visitedFunctions.add(candidateFunction);
7637
7637
  const returnedExpressions = collectReturnedExpressions(candidateFunction);
7638
- if (matchMode === "every" && isFunctionLike$2(candidateFunction) && isNodeOfType(candidateFunction.body, "BlockStatement") && (!statementAlwaysExits(candidateFunction.body) || functionHasBareReturn(candidateFunction))) return false;
7638
+ if (matchMode === "every" && isFunctionLike$1(candidateFunction) && isNodeOfType(candidateFunction.body, "BlockStatement") && (!statementAlwaysExits(candidateFunction.body) || functionHasBareReturn(candidateFunction))) return false;
7639
7639
  return returnedExpressions.length > 0 && (matchMode === "every" ? returnedExpressions.every(expressionMatches) : returnedExpressions.some(expressionMatches));
7640
7640
  };
7641
7641
  const expressionMatches = (expression) => {
@@ -7648,7 +7648,7 @@ const functionReturnsMatchingExpression = (functionNode, scopes, matchesExpressi
7648
7648
  if (!symbol || symbol.kind !== "const" && !REASSIGNABLE_BINDING_KINDS.has(symbol.kind)) return false;
7649
7649
  return collectPossibleAssignedExpressions(symbol, unwrappedExpression, controlFlow).some((assignedExpression) => {
7650
7650
  const assignedValue = stripParenExpression(assignedExpression);
7651
- return !isFunctionLike$2(assignedValue) && expressionMatches(assignedValue);
7651
+ return !isFunctionLike$1(assignedValue) && expressionMatches(assignedValue);
7652
7652
  });
7653
7653
  }
7654
7654
  if (isNodeOfType(unwrappedExpression, "CallExpression")) {
@@ -7657,7 +7657,7 @@ const functionReturnsMatchingExpression = (functionNode, scopes, matchesExpressi
7657
7657
  const symbol = scopes.symbolFor(unwrappedExpression.callee);
7658
7658
  if (!symbol || symbol.kind !== "const" && symbol.kind !== "function") return false;
7659
7659
  const initializer = symbol.initializer ? stripParenExpression(symbol.initializer) : null;
7660
- const candidateFunction = isFunctionLike$2(initializer) ? initializer : isFunctionLike$2(symbol.declarationNode) ? symbol.declarationNode : null;
7660
+ const candidateFunction = isFunctionLike$1(initializer) ? initializer : isFunctionLike$1(symbol.declarationNode) ? symbol.declarationNode : null;
7661
7661
  if (!candidateFunction || candidateFunction.async || candidateFunction.generator || candidateFunction.params.length !== 0) return false;
7662
7662
  return functionMatches(candidateFunction);
7663
7663
  }
@@ -7988,7 +7988,7 @@ const getSameFileCalledFunction = (callExpression, scopes, visitedSymbolIds) =>
7988
7988
  if (!symbol || visitedSymbolIds.has(symbol.id)) return null;
7989
7989
  if (symbol.kind !== "const" && !(symbol.kind === "function" && symbol.references.every((reference) => reference.flag === "read"))) return null;
7990
7990
  const candidate = symbol.initializer ?? symbol.declarationNode;
7991
- if (!isFunctionLike$2(candidate) || candidate.async || candidate.generator) return null;
7991
+ if (!isFunctionLike$1(candidate) || candidate.async || candidate.generator) return null;
7992
7992
  visitedSymbolIds.add(symbol.id);
7993
7993
  return candidate;
7994
7994
  };
@@ -8071,12 +8071,8 @@ const isProvenBrowserApiReceiver = (receiver, receiverKind, scopes, visitedSymbo
8071
8071
  const GENERATED_DOCS_ARCHIVE_PATH_PATTERN = /(?:^|\/)(?:docs?|documentation)\/archive\/[^/]+\/static\/(?:[^/]+\/)*docs\.js$/i;
8072
8072
  const isGeneratedDocsArchiveFilename = (filename) => GENERATED_DOCS_ARCHIVE_PATH_PATTERN.test(normalizeFilename(filename ?? ""));
8073
8073
  //#endregion
8074
- //#region src/plugin/utils/find-exported-function-body.ts
8075
- const isFunctionLike = (node) => {
8076
- if (!node) return false;
8077
- return isNodeOfType(node, "FunctionDeclaration") || isNodeOfType(node, "FunctionExpression") || isNodeOfType(node, "ArrowFunctionExpression");
8078
- };
8079
- const findExportedFunctionBody = (programRoot, exportedName) => {
8074
+ //#region src/plugin/utils/find-exported-value.ts
8075
+ const findExportedValue = (programRoot, exportedName) => {
8080
8076
  if (!isNodeOfType(programRoot, "Program")) return null;
8081
8077
  const localBindings = /* @__PURE__ */ new Map();
8082
8078
  const namedExports = /* @__PURE__ */ new Map();
@@ -8085,9 +8081,8 @@ const findExportedFunctionBody = (programRoot, exportedName) => {
8085
8081
  const recordVariableDeclaration = (declaration) => {
8086
8082
  for (const declarator of declaration.declarations ?? []) {
8087
8083
  if (!isNodeOfType(declarator, "VariableDeclarator")) continue;
8088
- if (!isNodeOfType(declarator.id, "Identifier")) continue;
8089
- const initializer = declarator.init ? stripParenExpression(declarator.init) : null;
8090
- if (initializer && isFunctionLike(initializer)) localBindings.set(declarator.id.name, initializer);
8084
+ if (!isNodeOfType(declarator.id, "Identifier") || !declarator.init) continue;
8085
+ localBindings.set(declarator.id.name, stripParenExpression(declarator.init));
8091
8086
  }
8092
8087
  };
8093
8088
  for (const statement of programRoot.body ?? []) {
@@ -8114,33 +8109,22 @@ const findExportedFunctionBody = (programRoot, exportedName) => {
8114
8109
  namedExports.set(declaration.id.name, declaration.id.name);
8115
8110
  }
8116
8111
  for (const specifier of statement.specifiers ?? []) {
8117
- if (!isNodeOfType(specifier, "ExportSpecifier")) continue;
8118
- if (specifier.exportKind === "type") continue;
8119
- const local = specifier.local;
8120
- const exported = specifier.exported;
8121
- if (!isNodeOfType(local, "Identifier")) continue;
8122
- const exportedNameSpec = isNodeOfType(exported, "Identifier") ? exported.name : isNodeOfType(exported, "Literal") && typeof exported.value === "string" ? exported.value : null;
8123
- if (!exportedNameSpec) continue;
8124
- namedExports.set(exportedNameSpec, local.name);
8112
+ if (!isNodeOfType(specifier, "ExportSpecifier") || specifier.exportKind === "type") continue;
8113
+ const localName = isNodeOfType(specifier.local, "Identifier") ? specifier.local.name : null;
8114
+ let exportedSpecifierName = null;
8115
+ if (isNodeOfType(specifier.exported, "Identifier")) exportedSpecifierName = specifier.exported.name;
8116
+ else if (isNodeOfType(specifier.exported, "Literal") && typeof specifier.exported.value === "string") exportedSpecifierName = specifier.exported.value;
8117
+ if (localName && exportedSpecifierName) namedExports.set(exportedSpecifierName, localName);
8125
8118
  }
8126
8119
  continue;
8127
8120
  }
8128
- if (isNodeOfType(statement, "ExportDefaultDeclaration")) {
8129
- const declaration = statement.declaration;
8130
- if (!declaration) continue;
8131
- if (isNodeOfType(declaration, "FunctionDeclaration") && declaration.id) {
8132
- localBindings.set(declaration.id.name, declaration);
8133
- defaultExport = declaration;
8134
- continue;
8135
- }
8136
- if (isFunctionLike(declaration)) {
8137
- defaultExport = declaration;
8138
- continue;
8139
- }
8140
- if (isNodeOfType(declaration, "Identifier")) {
8141
- defaultExportIdentifierName = declaration.name;
8142
- continue;
8143
- }
8121
+ if (!isNodeOfType(statement, "ExportDefaultDeclaration")) continue;
8122
+ const declaration = statement.declaration;
8123
+ if (!declaration) continue;
8124
+ if (isNodeOfType(declaration, "Identifier")) defaultExportIdentifierName = declaration.name;
8125
+ else {
8126
+ if ((isNodeOfType(declaration, "FunctionDeclaration") || isNodeOfType(declaration, "ClassDeclaration")) && declaration.id) localBindings.set(declaration.id.name, declaration);
8127
+ defaultExport = stripParenExpression(declaration);
8144
8128
  }
8145
8129
  }
8146
8130
  if (exportedName === "default") {
@@ -8151,9 +8135,10 @@ const findExportedFunctionBody = (programRoot, exportedName) => {
8151
8135
  }
8152
8136
  }
8153
8137
  const localName = namedExports.get(exportedName);
8154
- if (!localName) return null;
8155
- return localBindings.get(localName) ?? null;
8138
+ return localName ? localBindings.get(localName) ?? null : null;
8156
8139
  };
8140
+ //#endregion
8141
+ //#region src/plugin/utils/find-exported-function-body.ts
8157
8142
  const resolveImportedExportName = (importSpecifier) => {
8158
8143
  if (isNodeOfType(importSpecifier, "ImportSpecifier")) {
8159
8144
  const imported = importSpecifier.imported;
@@ -8610,28 +8595,44 @@ const resolveModulePath = (fromFilename, source) => {
8610
8595
  };
8611
8596
  //#endregion
8612
8597
  //#region src/plugin/utils/resolve-cross-file-function-export.ts
8613
- const resolveFunctionExportInFile = (filePath, exportedName, visitedFilePaths) => {
8598
+ const resolveValueExportInFile = (filePath, exportedName, visitedFilePaths) => {
8614
8599
  if (visitedFilePaths.size >= 4) return null;
8615
8600
  if (visitedFilePaths.has(filePath)) return null;
8616
8601
  visitedFilePaths.add(filePath);
8617
8602
  const programRoot = parseSourceFile(filePath);
8618
8603
  if (!programRoot) return null;
8619
- const exported = findExportedFunctionBody(programRoot, exportedName);
8620
- if (exported) return exported;
8621
- const resolvedCandidates = /* @__PURE__ */ new Set();
8604
+ const exported = findExportedValue(programRoot, exportedName);
8605
+ if (exported) return {
8606
+ filePath,
8607
+ exportedNode: exported,
8608
+ programNode: programRoot
8609
+ };
8610
+ const resolvedCandidates = /* @__PURE__ */ new Map();
8622
8611
  for (const target of findReExportTargetsForName(programRoot, exportedName)) {
8623
8612
  const nextFilePath = resolveModulePath(filePath, target.source);
8624
8613
  if (!nextFilePath) continue;
8625
- const resolved = resolveFunctionExportInFile(nextFilePath, target.importedName, new Set(visitedFilePaths));
8626
- if (resolved) resolvedCandidates.add(resolved);
8614
+ const resolved = resolveValueExportInFile(nextFilePath, target.importedName, new Set(visitedFilePaths));
8615
+ if (resolved) resolvedCandidates.set(resolved.exportedNode, resolved);
8627
8616
  }
8628
8617
  if (resolvedCandidates.size !== 1) return null;
8629
8618
  return resolvedCandidates.values().next().value ?? null;
8630
8619
  };
8631
8620
  const resolveCrossFileFunctionExport = (fromFilename, source, exportedName) => {
8621
+ return resolveCrossFileFunctionExportWithFilePath(fromFilename, source, exportedName)?.functionNode ?? null;
8622
+ };
8623
+ const resolveCrossFileFunctionExportWithFilePath = (fromFilename, source, exportedName) => {
8624
+ const resolved = resolveCrossFileValueExportWithFilePath(fromFilename, source, exportedName);
8625
+ if (!resolved || !isFunctionLike$1(resolved.exportedNode)) return null;
8626
+ return {
8627
+ filePath: resolved.filePath,
8628
+ functionNode: resolved.exportedNode,
8629
+ programNode: resolved.programNode
8630
+ };
8631
+ };
8632
+ const resolveCrossFileValueExportWithFilePath = (fromFilename, source, exportedName) => {
8632
8633
  const resolvedFilePath = resolveModulePath(fromFilename, source);
8633
8634
  if (!resolvedFilePath) return null;
8634
- return resolveFunctionExportInFile(resolvedFilePath, exportedName, /* @__PURE__ */ new Set());
8635
+ return resolveValueExportInFile(resolvedFilePath, exportedName, /* @__PURE__ */ new Set());
8635
8636
  };
8636
8637
  //#endregion
8637
8638
  //#region src/plugin/utils/is-proven-pure-imported-predicate-call.ts
@@ -8682,7 +8683,7 @@ const isProvenPureImportedPredicateCall = (callExpression, eventArgumentIndex, c
8682
8683
  const exportedName = resolveImportedExportName(importSpecifier);
8683
8684
  if (!exportedName || !isNodeOfType(importDeclaration, "ImportDeclaration") || typeof importDeclaration.source.value !== "string") return false;
8684
8685
  const importedFunction = resolveCrossFileFunctionExport(context.filename, importDeclaration.source.value, exportedName);
8685
- if (!importedFunction || !isFunctionLike$2(importedFunction)) return false;
8686
+ if (!importedFunction || !isFunctionLike$1(importedFunction)) return false;
8686
8687
  const parameter = importedFunction.params[eventArgumentIndex];
8687
8688
  if (!isNodeOfType(parameter, "Identifier")) return false;
8688
8689
  const aliasNames = new Set([parameter.name]);
@@ -8736,11 +8737,11 @@ const PROMISE_DEFERRED_METHOD_NAMES = new Set([
8736
8737
  ]);
8737
8738
  const EMPTY_VISITORS$7 = {};
8738
8739
  const handlerCallsPreventDefault = (handler) => {
8739
- if (!isFunctionLike$2(handler)) return false;
8740
+ if (!isFunctionLike$1(handler)) return false;
8740
8741
  let didFindPreventDefault = false;
8741
8742
  walkAst(handler, (child) => {
8742
8743
  if (didFindPreventDefault) return false;
8743
- if (child !== handler && isFunctionLike$2(child)) return false;
8744
+ if (child !== handler && isFunctionLike$1(child)) return false;
8744
8745
  if (isNodeOfType(child, "CallExpression") && isNodeOfType(child.callee, "MemberExpression") && getStaticPropertyName(child.callee) === "preventDefault") didFindPreventDefault = true;
8745
8746
  });
8746
8747
  return didFindPreventDefault;
@@ -8771,18 +8772,18 @@ const handlerArgumentCallsPreventDefault = (handler) => {
8771
8772
  const resolveHandlerFunction = (handler, context) => {
8772
8773
  if (!handler) return void 0;
8773
8774
  const unwrappedHandler = stripParenExpression(handler);
8774
- if (isFunctionLike$2(unwrappedHandler)) return unwrappedHandler;
8775
+ if (isFunctionLike$1(unwrappedHandler)) return unwrappedHandler;
8775
8776
  if (isNodeOfType(unwrappedHandler, "Identifier")) {
8776
8777
  const symbol = context.scopes.symbolFor(unwrappedHandler);
8777
8778
  const candidate = symbol?.initializer ?? symbol?.declarationNode;
8778
- if (candidate && isFunctionLike$2(candidate)) return candidate;
8779
+ if (candidate && isFunctionLike$1(candidate)) return candidate;
8779
8780
  const binding = findVariableInitializer(unwrappedHandler, unwrappedHandler.name);
8780
8781
  let assignedFunction;
8781
8782
  if (symbol && binding) walkAst(binding.scopeOwner, (child) => {
8782
8783
  if (child.range[0] >= unwrappedHandler.range[0]) return false;
8783
8784
  if (isNodeOfType(child, "AssignmentExpression") && child.operator === "=" && isNodeOfType(child.left, "Identifier") && context.scopes.symbolFor(child.left) === symbol) {
8784
8785
  const assignedValue = stripParenExpression(child.right);
8785
- assignedFunction = isFunctionLike$2(assignedValue) ? assignedValue : void 0;
8786
+ assignedFunction = isFunctionLike$1(assignedValue) ? assignedValue : void 0;
8786
8787
  }
8787
8788
  });
8788
8789
  return assignedFunction;
@@ -8813,7 +8814,7 @@ const handlerMayExposeEvent = (handler, context) => {
8813
8814
  const visitedParameterIndexesByFunction = /* @__PURE__ */ new Map();
8814
8815
  const isAsyncFunctionReference = (rawExpression, visitedSymbolIds) => {
8815
8816
  const expression = stripParenExpression(rawExpression);
8816
- if (isFunctionLike$2(expression)) return expression.async;
8817
+ if (isFunctionLike$1(expression)) return expression.async;
8817
8818
  if (!isNodeOfType(expression, "Identifier")) return false;
8818
8819
  const symbol = context.scopes.symbolFor(expression);
8819
8820
  if (!symbol || visitedSymbolIds.has(symbol.id)) return false;
@@ -8883,7 +8884,7 @@ const handlerMayExposeEvent = (handler, context) => {
8883
8884
  return true;
8884
8885
  };
8885
8886
  const functionMayExposeParameter = (functionNode, parameterIndex, isRootHandler = false) => {
8886
- if (!isFunctionLike$2(functionNode)) return false;
8887
+ if (!isFunctionLike$1(functionNode)) return false;
8887
8888
  const visitedParameterIndexes = visitedParameterIndexesByFunction.get(functionNode) ?? /* @__PURE__ */ new Set();
8888
8889
  if (visitedParameterIndexes.has(parameterIndex)) return false;
8889
8890
  visitedParameterIndexes.add(parameterIndex);
@@ -8970,7 +8971,7 @@ const handlerMayExposeEvent = (handler, context) => {
8970
8971
  let didExposeEvent = false;
8971
8972
  walkAst(functionNode.body, (child) => {
8972
8973
  if (didExposeEvent) return false;
8973
- if (child !== functionNode.body && isFunctionLike$2(child) && !shouldVisitNestedFunction(child)) return false;
8974
+ if (child !== functionNode.body && isFunctionLike$1(child) && !shouldVisitNestedFunction(child)) return false;
8974
8975
  if (isNodeOfType(child, "VariableDeclarator") && child.init) {
8975
8976
  addAliasesFromPattern(child.id, child.init);
8976
8977
  return;
@@ -10988,7 +10989,7 @@ const resolveAliasedSymbol = (identifier, context, visitedSymbolIds) => {
10988
10989
  const resolveCallbackIdentity = (callbackNode, context) => {
10989
10990
  if (!callbackNode) return null;
10990
10991
  const unwrappedCallback = stripParenExpression(callbackNode);
10991
- if (isFunctionLike$2(unwrappedCallback)) return {
10992
+ if (isFunctionLike$1(unwrappedCallback)) return {
10992
10993
  node: unwrappedCallback,
10993
10994
  isConcreteFunction: true
10994
10995
  };
@@ -10996,7 +10997,7 @@ const resolveCallbackIdentity = (callbackNode, context) => {
10996
10997
  const symbol = resolveAliasedSymbol(unwrappedCallback, context, /* @__PURE__ */ new Set());
10997
10998
  if (!symbol) return null;
10998
10999
  const initializer = symbol.initializer ? stripParenExpression(symbol.initializer) : null;
10999
- if (initializer && isFunctionLike$2(initializer)) return {
11000
+ if (initializer && isFunctionLike$1(initializer)) return {
11000
11001
  node: initializer,
11001
11002
  isConcreteFunction: true
11002
11003
  };
@@ -11226,12 +11227,12 @@ const readDestructuredRemovalCandidate = (node, context) => {
11226
11227
  const resolveReturnedCleanupBody = (returnedValue, context) => {
11227
11228
  if (!returnedValue) return null;
11228
11229
  const unwrappedValue = stripParenExpression(returnedValue);
11229
- if (isFunctionLike$2(unwrappedValue)) return unwrappedValue.body;
11230
+ if (isFunctionLike$1(unwrappedValue)) return unwrappedValue.body;
11230
11231
  if (!isNodeOfType(unwrappedValue, "Identifier")) return null;
11231
11232
  const symbol = resolveAliasedSymbol(unwrappedValue, context, /* @__PURE__ */ new Set());
11232
11233
  if (!symbol || !symbol.initializer) return null;
11233
11234
  const initializer = stripParenExpression(symbol.initializer);
11234
- return isFunctionLike$2(initializer) ? initializer.body : null;
11235
+ return isFunctionLike$1(initializer) ? initializer.body : null;
11235
11236
  };
11236
11237
  const collectEffectListenerInputs = (effectBody, context) => {
11237
11238
  const registrations = [];
@@ -11247,7 +11248,7 @@ const collectEffectListenerInputs = (effectBody, context) => {
11247
11248
  const finalEffectStatement = effectBody.body[effectBody.body.length - 1];
11248
11249
  const hasCanonicalCleanupReturn = isNodeOfType(finalEffectStatement, "ReturnStatement");
11249
11250
  walkAst(effectBody, (child) => {
11250
- if (child !== effectBody && isFunctionLike$2(child)) return false;
11251
+ if (child !== effectBody && isFunctionLike$1(child)) return false;
11251
11252
  if (isNodeOfType(child, "ClassDeclaration") || isNodeOfType(child, "ClassExpression")) return false;
11252
11253
  if (isNodeOfType(child, "CallExpression")) {
11253
11254
  if (isListenerPathAmbiguous(child, effectBody)) return;
@@ -11295,7 +11296,7 @@ const resolveCalledCleanup = (callNode, context) => {
11295
11296
  const cleanupSymbol = resolveAliasedSymbol(callee, context, /* @__PURE__ */ new Set());
11296
11297
  if (!cleanupSymbol?.initializer || cleanupSymbol.kind !== "const" && cleanupSymbol.kind !== "function") return null;
11297
11298
  const initializer = stripParenExpression(cleanupSymbol.initializer);
11298
- if (!isFunctionLike$2(initializer) || initializer.async || initializer.generator) return null;
11299
+ if (!isFunctionLike$1(initializer) || initializer.async || initializer.generator) return null;
11299
11300
  return {
11300
11301
  body: initializer.body,
11301
11302
  symbolId: cleanupSymbol.id
@@ -11342,7 +11343,7 @@ const analyzeCleanupBody = (cleanupBody, context, visitedCleanupSymbolIds = /* @
11342
11343
  return false;
11343
11344
  };
11344
11345
  walkAst(cleanupBody, (child) => {
11345
- if (child !== cleanupBody && isFunctionLike$2(child)) return false;
11346
+ if (child !== cleanupBody && isFunctionLike$1(child)) return false;
11346
11347
  if (isNodeOfType(child, "ClassDeclaration") || isNodeOfType(child, "ClassExpression")) return false;
11347
11348
  if (isNodeOfType(child, "ReturnStatement") && child === finalCleanupStatement) return;
11348
11349
  if (isNodeOfType(child, "ReturnStatement") || isNodeOfType(child, "ThrowStatement") || isLoopBody && (isNodeOfType(child, "BreakStatement") || isNodeOfType(child, "ContinueStatement"))) {
@@ -11452,7 +11453,7 @@ const effectListenerCleanupMismatch = defineRule({
11452
11453
  create: (context) => ({ CallExpression(node) {
11453
11454
  if (!isReactApiCall(node, LISTENER_EFFECT_HOOK_NAMES, context.scopes)) return;
11454
11455
  const effectCallback = getEffectCallback(node);
11455
- if (!isFunctionLike$2(effectCallback)) return;
11456
+ if (!isFunctionLike$1(effectCallback)) return;
11456
11457
  const listenerAnalysis = analyzeEffectListeners(effectCallback.body, context);
11457
11458
  if (!listenerAnalysis) return;
11458
11459
  for (const registration of listenerAnalysis.registrations) {
@@ -11514,7 +11515,7 @@ const collectEffectInvokedFunctions = (effectCallback) => {
11514
11515
  const pendingFunctions = [effectCallback];
11515
11516
  const enqueue = (candidate) => {
11516
11517
  const strippedCandidate = candidate ? stripParenExpression(candidate) : candidate;
11517
- if (!isFunctionLike$2(strippedCandidate) || invokedFunctions.has(strippedCandidate)) return;
11518
+ if (!isFunctionLike$1(strippedCandidate) || invokedFunctions.has(strippedCandidate)) return;
11518
11519
  invokedFunctions.add(strippedCandidate);
11519
11520
  pendingFunctions.push(strippedCandidate);
11520
11521
  };
@@ -11522,18 +11523,18 @@ const collectEffectInvokedFunctions = (effectCallback) => {
11522
11523
  const currentFunction = pendingFunctions.pop();
11523
11524
  if (!currentFunction) break;
11524
11525
  walkAst(currentFunction, (child) => {
11525
- if (child !== currentFunction && isFunctionLike$2(child)) {
11526
+ if (child !== currentFunction && isFunctionLike$1(child)) {
11526
11527
  if (isNodeOfType(child, "FunctionDeclaration") && isNodeOfType(child.id, "Identifier")) localFunctionBindings.set(child.id.name, child);
11527
11528
  return false;
11528
11529
  }
11529
11530
  if (isNodeOfType(child, "VariableDeclarator") && isNodeOfType(child.id, "Identifier")) {
11530
11531
  const initializer = child.init ? stripParenExpression(child.init) : null;
11531
- if (isFunctionLike$2(initializer)) localFunctionBindings.set(child.id.name, initializer);
11532
+ if (isFunctionLike$1(initializer)) localFunctionBindings.set(child.id.name, initializer);
11532
11533
  return;
11533
11534
  }
11534
11535
  if (!isNodeOfType(child, "CallExpression")) return;
11535
11536
  const callee = stripParenExpression(child.callee);
11536
- if (isFunctionLike$2(callee)) {
11537
+ if (isFunctionLike$1(callee)) {
11537
11538
  enqueue(callee);
11538
11539
  return;
11539
11540
  }
@@ -11695,7 +11696,7 @@ const hasReactRefCurrentOrigin = (node, scopes, visitedSymbolIds = /* @__PURE__
11695
11696
  //#region src/plugin/utils/walk-inside-statement-blocks.ts
11696
11697
  const walkInsideStatementBlocks = (node, visitor) => {
11697
11698
  if (!node || typeof node !== "object") return;
11698
- if (isFunctionLike$2(node)) return;
11699
+ if (isFunctionLike$1(node)) return;
11699
11700
  visitor(node);
11700
11701
  const nodeRecord = node;
11701
11702
  for (const key of Object.keys(nodeRecord)) {
@@ -11810,7 +11811,7 @@ const resolveExpressionKey = (expression, context, visitedSymbolIds = /* @__PURE
11810
11811
  }
11811
11812
  if (isNodeOfType(unwrappedExpression, "ThisExpression")) return "this";
11812
11813
  if (isNodeOfType(unwrappedExpression, "Literal") && (typeof unwrappedExpression.value === "string" || typeof unwrappedExpression.value === "number")) return `literal:${String(unwrappedExpression.value)}`;
11813
- if (isFunctionLike$2(unwrappedExpression)) {
11814
+ if (isFunctionLike$1(unwrappedExpression)) {
11814
11815
  const rangeStart = getRangeStart(unwrappedExpression);
11815
11816
  return rangeStart === null ? null : `function:${rangeStart}`;
11816
11817
  }
@@ -11853,7 +11854,7 @@ const findSubscribeLikeUsages = (callback, context) => {
11853
11854
  }
11854
11855
  const effectInvokedFunctions = collectEffectInvokedFunctions(callback);
11855
11856
  walkAst(callback, (child) => {
11856
- if (child !== callback && isFunctionLike$2(child)) {
11857
+ if (child !== callback && isFunctionLike$1(child)) {
11857
11858
  if (child === cleanupArgument) return false;
11858
11859
  if (!effectInvokedFunctions.has(child) && !isSynchronousIteratorCallback(child)) return false;
11859
11860
  }
@@ -12016,7 +12017,7 @@ const isAssignmentFormForOfIteratorReference = (expression, context) => {
12016
12017
  return didAssignReferencedSymbol;
12017
12018
  };
12018
12019
  let currentNode = unwrappedExpression.parent;
12019
- while (currentNode && !isFunctionLike$2(currentNode)) {
12020
+ while (currentNode && !isFunctionLike$1(currentNode)) {
12020
12021
  if (isNodeOfType(currentNode, "ForOfStatement")) {
12021
12022
  const loopTarget = stripParenExpression(currentNode.left);
12022
12023
  if (!isNodeOfType(loopTarget, "VariableDeclaration") && (assignsReferencedSymbol(loopTarget, false) || assignsReferencedSymbol(currentNode.body, true))) return true;
@@ -12085,8 +12086,8 @@ const resolveIteratorCollectionKey = (expression, context) => {
12085
12086
  const symbol = context.scopes.symbolFor(unwrappedExpression);
12086
12087
  if (!symbol || symbol.kind !== "parameter") return null;
12087
12088
  let callbackNode = symbol.bindingIdentifier.parent;
12088
- while (callbackNode && !isFunctionLike$2(callbackNode)) callbackNode = callbackNode.parent;
12089
- if (!callbackNode || !isFunctionLike$2(callbackNode)) return null;
12089
+ while (callbackNode && !isFunctionLike$1(callbackNode)) callbackNode = callbackNode.parent;
12090
+ if (!callbackNode || !isFunctionLike$1(callbackNode)) return null;
12090
12091
  const callNode = callbackNode.parent;
12091
12092
  if (!isNodeOfType(callNode, "CallExpression")) return null;
12092
12093
  const callee = stripParenExpression(callNode.callee);
@@ -12116,7 +12117,7 @@ const isDirectExhaustiveForOfRelease = (releaseNode, forOfStatement) => {
12116
12117
  let hasAbruptLoopExit = false;
12117
12118
  walkAst(forOfStatement.body, (child) => {
12118
12119
  if (hasAbruptLoopExit) return false;
12119
- if (child !== forOfStatement.body && isFunctionLike$2(child)) return false;
12120
+ if (child !== forOfStatement.body && isFunctionLike$1(child)) return false;
12120
12121
  if (isNodeOfType(child, "BreakStatement") || isNodeOfType(child, "ContinueStatement") || isNodeOfType(child, "ReturnStatement") || isNodeOfType(child, "ThrowStatement")) {
12121
12122
  hasAbruptLoopExit = true;
12122
12123
  return false;
@@ -12145,7 +12146,7 @@ const findMappedResourceCollectionKey = (resourceNode, context) => {
12145
12146
  if (!isNodeOfType(resourceDeclarator, "VariableDeclarator") || resourceDeclarator.init !== resourceRoot || !isNodeOfType(resourceDeclarator.id, "Identifier") || !isNodeOfType(resourceDeclaration, "VariableDeclaration") || resourceDeclaration.kind !== "const" || resourceDeclaration.parent !== callbackNode.body) return null;
12146
12147
  const returnStatements = [];
12147
12148
  walkAst(callbackNode.body, (child) => {
12148
- if (child !== callbackNode.body && isFunctionLike$2(child)) return false;
12149
+ if (child !== callbackNode.body && isFunctionLike$1(child)) return false;
12149
12150
  if (isNodeOfType(child, "ReturnStatement")) returnStatements.push(child);
12150
12151
  });
12151
12152
  const returnStatement = returnStatements[0];
@@ -12164,7 +12165,7 @@ const findContainingCollectionKey = (resourceNode, context) => {
12164
12165
  let currentNode = resourceNode;
12165
12166
  let parentNode = currentNode.parent;
12166
12167
  while (parentNode) {
12167
- if (isFunctionLike$2(parentNode)) return null;
12168
+ if (isFunctionLike$1(parentNode)) return null;
12168
12169
  if (isNodeOfType(parentNode, "VariableDeclarator") && parentNode.init === currentNode) return resolveExpressionKey(parentNode.id, context);
12169
12170
  currentNode = parentNode;
12170
12171
  parentNode = currentNode.parent;
@@ -12189,7 +12190,7 @@ const resolveStableValue = (expression, context, visitedSymbolIds = /* @__PURE__
12189
12190
  if (!isNodeOfType(unwrappedExpression, "Identifier")) return unwrappedExpression;
12190
12191
  const symbol = context.scopes.symbolFor(unwrappedExpression);
12191
12192
  const isUnreassignedMutableBinding = (symbol?.kind === "let" || symbol?.kind === "var") && isNodeOfType(symbol.declarationNode, "VariableDeclarator") && symbol.declarationNode.id === symbol.bindingIdentifier && symbol.references.every((reference) => reference.flag === "read" && !isWithinAssignmentTarget(reference.identifier)) && symbol.scope.symbols.filter((candidate) => candidate.name === symbol.name).length === 1;
12192
- const recursiveFunctionSymbol = symbol?.kind === "function" && isFunctionLike$2(symbol.declarationNode) ? context.scopes.ownScopeFor(symbol.declarationNode)?.symbols.find((candidate) => candidate.name === symbol.name && candidate.declarationNode === symbol.declarationNode) : null;
12193
+ const recursiveFunctionSymbol = symbol?.kind === "function" && isFunctionLike$1(symbol.declarationNode) ? context.scopes.ownScopeFor(symbol.declarationNode)?.symbols.find((candidate) => candidate.name === symbol.name && candidate.declarationNode === symbol.declarationNode) : null;
12193
12194
  const isUnreassignedFunctionBinding = symbol?.kind === "function" && symbol.references.every((reference) => reference.flag === "read" && !isWithinAssignmentTarget(reference.identifier)) && (!recursiveFunctionSymbol || recursiveFunctionSymbol.references.every((reference) => reference.flag === "read" && !isWithinAssignmentTarget(reference.identifier))) && symbol.scope.symbols.filter((candidate) => candidate.name === symbol.name).length === 1;
12194
12195
  if (!symbol || symbol.kind !== "const" && !isUnreassignedMutableBinding && !isUnreassignedFunctionBinding || !symbol.initializer || visitedSymbolIds.has(symbol.id)) return unwrappedExpression;
12195
12196
  visitedSymbolIds.add(symbol.id);
@@ -12265,16 +12266,16 @@ const resolveSingleAssignedCleanupFunction = (expression, usage, context) => {
12265
12266
  const assignmentNode = assignmentTarget.parent;
12266
12267
  if (!isNodeOfType(assignmentNode, "AssignmentExpression") || assignmentNode.operator !== "=" || assignmentNode.left !== assignmentTarget || findEnclosingFunction$1(assignmentNode) !== findEnclosingFunction$1(usage.node) || !doMatchingNodesCoverEveryPathAfterUsage(usage.node, [assignmentNode], context)) return null;
12267
12268
  const assignedValue = stripParenExpression(assignmentNode.right);
12268
- return isFunctionLike$2(assignedValue) ? assignedValue : null;
12269
+ return isFunctionLike$1(assignedValue) ? assignedValue : null;
12269
12270
  };
12270
12271
  const doesCleanupFunctionReleaseUsage = (cleanupFunction, usage, context, visitedFunctions = /* @__PURE__ */ new Set()) => {
12271
- if (!isFunctionLike$2(cleanupFunction) || visitedFunctions.has(cleanupFunction)) return false;
12272
+ if (!isFunctionLike$1(cleanupFunction) || visitedFunctions.has(cleanupFunction)) return false;
12272
12273
  visitedFunctions.add(cleanupFunction);
12273
12274
  let didCleanupFunctionMatch = false;
12274
12275
  const matchingLoopOrHelperAnchors = [];
12275
12276
  walkAst(cleanupFunction.body, (cleanupChild) => {
12276
12277
  if (didCleanupFunctionMatch) return false;
12277
- if (cleanupChild !== cleanupFunction.body && isFunctionLike$2(cleanupChild) && !isSynchronousIteratorCallback(cleanupChild)) return false;
12278
+ if (cleanupChild !== cleanupFunction.body && isFunctionLike$1(cleanupChild) && !isSynchronousIteratorCallback(cleanupChild)) return false;
12278
12279
  const cleanupCall = isNodeOfType(cleanupChild, "ChainExpression") ? cleanupChild.expression : cleanupChild;
12279
12280
  if (doesReleaseCallMatchUsage(cleanupChild, usage, context)) {
12280
12281
  const cleanupForOfStatement = findForOfStatementForIteratorExpression(isNodeOfType(cleanupCall, "CallExpression") ? cleanupCall.arguments?.[0] : null, context);
@@ -12288,7 +12289,7 @@ const doesCleanupFunctionReleaseUsage = (cleanupFunction, usage, context, visite
12288
12289
  if (!isNodeOfType(cleanupCall, "CallExpression")) return;
12289
12290
  const stableHelperFunction = resolveStableValue(cleanupCall.callee, context);
12290
12291
  const helperFunction = isNodeOfType(stableHelperFunction, "Identifier") ? resolveSingleAssignedCleanupFunction(stableHelperFunction, usage, context) : stableHelperFunction;
12291
- if (helperFunction && isFunctionLike$2(helperFunction) && !helperFunction.async && !helperFunction.generator && doesCleanupFunctionReleaseUsage(helperFunction, usage, context, new Set(visitedFunctions))) matchingLoopOrHelperAnchors.push(cleanupCall);
12292
+ if (helperFunction && isFunctionLike$1(helperFunction) && !helperFunction.async && !helperFunction.generator && doesCleanupFunctionReleaseUsage(helperFunction, usage, context, new Set(visitedFunctions))) matchingLoopOrHelperAnchors.push(cleanupCall);
12292
12293
  });
12293
12294
  return didCleanupFunctionMatch || doMatchingNodesCoverEveryPathFromFunctionEntry(cleanupFunction, matchingLoopOrHelperAnchors, context);
12294
12295
  };
@@ -12312,7 +12313,7 @@ const callbackReturnsCleanupForUsage = (callback, usage, context) => {
12312
12313
  if (doesBoundCleanupReleaseUsage(returnedValue, usage, context)) return true;
12313
12314
  const cleanupFunction = resolveStableValue(returnedValue, context);
12314
12315
  if (cleanupFunction && doesBoundCleanupReleaseUsage(cleanupFunction, usage, context)) return true;
12315
- return Boolean(cleanupFunction && isFunctionLike$2(cleanupFunction) && doesCleanupFunctionReleaseUsage(cleanupFunction, usage, context));
12316
+ return Boolean(cleanupFunction && isFunctionLike$1(cleanupFunction) && doesCleanupFunctionReleaseUsage(cleanupFunction, usage, context));
12316
12317
  };
12317
12318
  if (!isNodeOfType(callback.body, "BlockStatement")) return doesReturnedValueReleaseUsage(stripParenExpression(callback.body));
12318
12319
  const matchingCleanupReturns = [];
@@ -12347,7 +12348,7 @@ const hasRerunReleaseBeforeUsage = (callback, usage, context) => {
12347
12348
  return;
12348
12349
  }
12349
12350
  const helperFunction = resolveStableValue(child.callee, context);
12350
- if (helperFunction && isFunctionLike$2(helperFunction) && doesCleanupFunctionReleaseUsage(helperFunction, usage, context)) matchingReleaseAnchors.push(handleGuard ?? child);
12351
+ if (helperFunction && isFunctionLike$1(helperFunction) && doesCleanupFunctionReleaseUsage(helperFunction, usage, context)) matchingReleaseAnchors.push(handleGuard ?? child);
12351
12352
  });
12352
12353
  return doMatchingNodesCoverEveryPathFromFunctionEntry(callback, matchingReleaseAnchors, context);
12353
12354
  };
@@ -12405,10 +12406,10 @@ const isDirectEarlyReturnConsequent = (ifStatement) => {
12405
12406
  return isNodeOfType(ifStatement.consequent, "BlockStatement") && ifStatement.consequent.body.length === 1 && isNodeOfType(ifStatement.consequent.body[0], "ReturnStatement");
12406
12407
  };
12407
12408
  const collectDeferredUsageGuardStates = (callback, usageNode, context) => {
12408
- if (!isFunctionLike$2(callback) || callback.async) return [];
12409
+ if (!isFunctionLike$1(callback) || callback.async) return [];
12409
12410
  const guardStates = [];
12410
12411
  walkAst(callback.body, (child) => {
12411
- if (child !== callback.body && isFunctionLike$2(child)) return false;
12412
+ if (child !== callback.body && isFunctionLike$1(child)) return false;
12412
12413
  if (isNodeOfType(child, "IfStatement") && isDirectEarlyReturnConsequent(child) && doMatchingNodesCoverEveryPathBeforeUsage(usageNode, [child], callback, context)) guardStates.push(...collectBlockingBooleanStates(child.test, true, context));
12413
12414
  });
12414
12415
  let descendant = usageNode;
@@ -12423,11 +12424,11 @@ const collectDeferredUsageGuardStates = (callback, usageNode, context) => {
12423
12424
  const cleanupReturnInvalidatesGuard = (cleanupReturn, guardState, context) => {
12424
12425
  if (!isNodeOfType(cleanupReturn, "ReturnStatement") || !cleanupReturn.argument) return false;
12425
12426
  const cleanupFunction = resolveStableValue(cleanupReturn.argument, context);
12426
- if (!cleanupFunction || !isFunctionLike$2(cleanupFunction) || cleanupFunction.async) return false;
12427
+ if (!cleanupFunction || !isFunctionLike$1(cleanupFunction) || cleanupFunction.async) return false;
12427
12428
  let didInvalidateGuard = false;
12428
12429
  walkAst(cleanupFunction.body, (child) => {
12429
12430
  if (didInvalidateGuard) return false;
12430
- if (child !== cleanupFunction.body && isFunctionLike$2(child)) return false;
12431
+ if (child !== cleanupFunction.body && isFunctionLike$1(child)) return false;
12431
12432
  if (isNodeOfType(child, "AssignmentExpression") && child.operator === "=" && resolveExpressionKey(child.left, context) === guardState.key && readStaticBoolean(child.right) === guardState.value && context.cfg.isUnconditionalFromEntry(child)) {
12432
12433
  didInvalidateGuard = true;
12433
12434
  return false;
@@ -12437,11 +12438,11 @@ const cleanupReturnInvalidatesGuard = (cleanupReturn, guardState, context) => {
12437
12438
  };
12438
12439
  const deferredUsageWritesGuardBeforeUsage = (callback, usageNode, guardState, context) => {
12439
12440
  const usageStart = getRangeStart(usageNode);
12440
- if (!isFunctionLike$2(callback) || usageStart === null) return true;
12441
+ if (!isFunctionLike$1(callback) || usageStart === null) return true;
12441
12442
  let didWriteGuard = false;
12442
12443
  walkAst(callback.body, (child) => {
12443
12444
  if (didWriteGuard) return false;
12444
- if (child !== callback.body && isFunctionLike$2(child)) return false;
12445
+ if (child !== callback.body && isFunctionLike$1(child)) return false;
12445
12446
  const childStart = getRangeStart(child);
12446
12447
  if (childStart === null || childStart >= usageStart) return;
12447
12448
  const writtenExpression = isNodeOfType(child, "AssignmentExpression") ? child.left : isNodeOfType(child, "UpdateExpression") ? child.argument : null;
@@ -12494,7 +12495,7 @@ const effectHasCleanupForUsage = (callback, usage, context) => {
12494
12495
  matchingCleanupReturns.push(child);
12495
12496
  return;
12496
12497
  }
12497
- if (!cleanupFunction || !isFunctionLike$2(cleanupFunction)) return;
12498
+ if (!cleanupFunction || !isFunctionLike$1(cleanupFunction)) return;
12498
12499
  if (doesCleanupFunctionReleaseUsage(cleanupFunction, usage, context)) matchingCleanupReturns.push(child);
12499
12500
  });
12500
12501
  if (hasGuardedDeferredCleanup(callback, usage, matchingCleanupReturns, context)) return true;
@@ -12664,19 +12665,19 @@ const fileContainsReleaseForUsage = (usage, context) => {
12664
12665
  };
12665
12666
  const resolveRefOwnedCleanupFunction = (expression, context) => {
12666
12667
  const resolvedExpression = resolveStableValue(expression, context);
12667
- if (isFunctionLike$2(resolvedExpression)) return resolvedExpression;
12668
+ if (isFunctionLike$1(resolvedExpression)) return resolvedExpression;
12668
12669
  if (!isNodeOfType(resolvedExpression, "CallExpression") || !isReactApiCall(resolvedExpression, "useCallback", context.scopes)) return null;
12669
12670
  return getEffectCallback(resolvedExpression);
12670
12671
  };
12671
12672
  const findRefOwnedHandlerStorage = (retainedFunction, usage, context) => {
12672
- if (!isFunctionLike$2(retainedFunction) || usage.kind !== "subscribe" || usage.registrationVerbName !== "addEventListener" || usage.handlerKey === null || !usage.receiverKey?.startsWith("global:") || !usage.eventKey?.startsWith("literal:")) return null;
12673
+ if (!isFunctionLike$1(retainedFunction) || usage.kind !== "subscribe" || usage.registrationVerbName !== "addEventListener" || usage.handlerKey === null || !usage.receiverKey?.startsWith("global:") || !usage.eventKey?.startsWith("literal:")) return null;
12673
12674
  const usageStart = getRangeStart(usage.node);
12674
12675
  const functionCfg = context.cfg.cfgFor(retainedFunction);
12675
12676
  const usageBlock = functionCfg?.blockOf(usage.node);
12676
12677
  if (usageStart === null || !functionCfg || !usageBlock) return null;
12677
12678
  const matchingStorage = [];
12678
12679
  walkAst(retainedFunction.body, (child) => {
12679
- if (child !== retainedFunction.body && isFunctionLike$2(child)) return false;
12680
+ if (child !== retainedFunction.body && isFunctionLike$1(child)) return false;
12680
12681
  if (!isNodeOfType(child, "AssignmentExpression") || child.operator !== "=") return;
12681
12682
  const assignmentStart = getRangeStart(child);
12682
12683
  const refCurrentExpression = stripParenExpression(child.left);
@@ -12733,17 +12734,17 @@ const doMatchingNodesCoverEveryPathBeforeUsage = (usageNode, matchingNodes, owne
12733
12734
  return true;
12734
12735
  };
12735
12736
  const retainedFunctionReleasesPreviousRefOwnedUsage = (retainedFunction, cleanupFunction, storageNode, context) => {
12736
- if (!isFunctionLike$2(retainedFunction)) return false;
12737
+ if (!isFunctionLike$1(retainedFunction)) return false;
12737
12738
  const retainedFunctionBody = retainedFunction.body;
12738
12739
  const cleanupCalls = [];
12739
12740
  walkAst(retainedFunctionBody, (child) => {
12740
- if (child !== retainedFunctionBody && isFunctionLike$2(child)) return false;
12741
+ if (child !== retainedFunctionBody && isFunctionLike$1(child)) return false;
12741
12742
  if (isNodeOfType(child, "CallExpression") && resolveRefOwnedCleanupFunction(child.callee, context) === cleanupFunction) cleanupCalls.push(child);
12742
12743
  });
12743
12744
  return doMatchingNodesCoverEveryPathBeforeUsage(storageNode, cleanupCalls, retainedFunction, context);
12744
12745
  };
12745
12746
  const isDirectRefOwnedRelease = (releaseNode, cleanupFunction, usage, storedHandlerKey, refCurrentKey, context) => {
12746
- if (!isFunctionLike$2(cleanupFunction)) return false;
12747
+ if (!isFunctionLike$1(cleanupFunction)) return false;
12747
12748
  const releaseCall = isNodeOfType(releaseNode, "ChainExpression") ? releaseNode.expression : releaseNode;
12748
12749
  if (!isNodeOfType(releaseCall, "CallExpression") || !isNodeOfType(releaseCall.callee, "MemberExpression") || releaseCall.callee.computed || !isNodeOfType(releaseCall.callee.property, "Identifier") || releaseCall.callee.property.name !== "removeEventListener" || !isNodeOfType(usage.node, "CallExpression") || usage.node.arguments?.[2] !== void 0 || releaseCall.arguments?.[2] !== void 0) return false;
12749
12750
  const releaseStatement = findTransparentExpressionRoot(releaseNode).parent;
@@ -12763,13 +12764,13 @@ const isRefPresenceGuardedEarlyReturn = (returnStatement, refCurrentKey, context
12763
12764
  return isNodeOfType(guardTest, "UnaryExpression") && guardTest.operator === "!" && resolveExpressionKey(guardTest.argument, context) === refCurrentKey;
12764
12765
  };
12765
12766
  const hasUnprovenReturnBeforeRefOwnedRelease = (cleanupFunction, releaseNode, refCurrentKey, context) => {
12766
- if (!isFunctionLike$2(cleanupFunction)) return true;
12767
+ if (!isFunctionLike$1(cleanupFunction)) return true;
12767
12768
  const releaseStart = getRangeStart(releaseNode);
12768
12769
  if (releaseStart === null) return true;
12769
12770
  let hasUnprovenEarlyReturn = false;
12770
12771
  walkAst(cleanupFunction.body, (child) => {
12771
12772
  if (hasUnprovenEarlyReturn) return false;
12772
- if (child !== cleanupFunction.body && isFunctionLike$2(child)) return false;
12773
+ if (child !== cleanupFunction.body && isFunctionLike$1(child)) return false;
12773
12774
  if (!isNodeOfType(child, "ReturnStatement")) return;
12774
12775
  const returnStart = getRangeStart(child);
12775
12776
  if ((returnStart === null || returnStart < releaseStart) && !isRefPresenceGuardedEarlyReturn(child, refCurrentKey, context)) {
@@ -12780,14 +12781,14 @@ const hasUnprovenReturnBeforeRefOwnedRelease = (cleanupFunction, releaseNode, re
12780
12781
  return hasUnprovenEarlyReturn;
12781
12782
  };
12782
12783
  const cleanupFunctionReleasesRefOwnedUsage = (cleanupFunction, componentFunction, retainedFunction, usage, context) => {
12783
- if (!isFunctionLike$2(cleanupFunction) || !isFunctionLike$2(componentFunction) || cleanupFunction.async || cleanupFunction.generator) return false;
12784
+ if (!isFunctionLike$1(cleanupFunction) || !isFunctionLike$1(componentFunction) || cleanupFunction.async || cleanupFunction.generator) return false;
12784
12785
  const storage = findRefOwnedHandlerStorage(retainedFunction, usage, context);
12785
12786
  if (!storage) return false;
12786
12787
  if (!retainedFunctionReleasesPreviousRefOwnedUsage(retainedFunction, cleanupFunction, storage.assignmentNode, context)) return false;
12787
12788
  let releaseNode = null;
12788
12789
  walkAst(cleanupFunction.body, (child) => {
12789
12790
  if (releaseNode) return false;
12790
- if (child !== cleanupFunction.body && isFunctionLike$2(child)) return false;
12791
+ if (child !== cleanupFunction.body && isFunctionLike$1(child)) return false;
12791
12792
  if (isDirectRefOwnedRelease(child, cleanupFunction, usage, storage.handlerKey, storage.refCurrentKey, context)) {
12792
12793
  releaseNode = child;
12793
12794
  return false;
@@ -12844,7 +12845,7 @@ const effectReturnsRefOwnedCleanup = (effectCallback, componentFunction, retaine
12844
12845
  const cleanupFunction = resolveRefOwnedCleanupFunction(returnedValue, context);
12845
12846
  return Boolean(cleanupFunction && cleanupFunctionReleasesRefOwnedUsage(cleanupFunction, componentFunction, retainedFunction, usage, context));
12846
12847
  };
12847
- if (!isFunctionLike$2(effectCallback)) return false;
12848
+ if (!isFunctionLike$1(effectCallback)) return false;
12848
12849
  if (!isNodeOfType(effectCallback.body, "BlockStatement")) return matchesReturnedCleanup(stripParenExpression(effectCallback.body));
12849
12850
  const matchingReturns = [];
12850
12851
  walkInsideStatementBlocks(effectCallback.body, (child) => {
@@ -12854,7 +12855,7 @@ const effectReturnsRefOwnedCleanup = (effectCallback, componentFunction, retaine
12854
12855
  };
12855
12856
  const hasGuaranteedRefOwnedUnmountCleanup = (retainedFunction, usage, context) => {
12856
12857
  const componentFunction = findEnclosingFunction$1(retainedFunction);
12857
- if (!componentFunction || !isFunctionLike$2(componentFunction)) return false;
12858
+ if (!componentFunction || !isFunctionLike$1(componentFunction)) return false;
12858
12859
  let didFindCleanupEffect = false;
12859
12860
  walkAst(componentFunction.body, (child) => {
12860
12861
  if (didFindCleanupEffect) return false;
@@ -12903,7 +12904,7 @@ const doesResourceResultEscape = (resourceNode, allowConciseReturnEscape) => {
12903
12904
  return false;
12904
12905
  };
12905
12906
  const findRetainedFunctionLeak = (retainedFunction, context) => {
12906
- if (!isFunctionLike$2(retainedFunction)) return null;
12907
+ if (!isFunctionLike$1(retainedFunction)) return null;
12907
12908
  const body = retainedFunction.body;
12908
12909
  if (!body) return null;
12909
12910
  let leak = null;
@@ -12912,7 +12913,7 @@ const findRetainedFunctionLeak = (retainedFunction, context) => {
12912
12913
  const hasReleaseForUsage = (usage) => isExternalStoreSubscribeFunction ? effectHasCleanupForUsage(retainedFunction, usage, context) : fileContainsReleaseForUsage(usage, context) || hasGuaranteedRefOwnedUnmountCleanup(retainedFunction, usage, context);
12913
12914
  walkAst(body, (child) => {
12914
12915
  if (leak !== null) return false;
12915
- if (isFunctionLike$2(child)) return false;
12916
+ if (isFunctionLike$1(child)) return false;
12916
12917
  if (isSocketConstruction(child) && !doesResourceResultEscape(child, false)) {
12917
12918
  const socketUsage = {
12918
12919
  kind: "socket",
@@ -12973,7 +12974,7 @@ const isDirectJsxEventHandlerValue = (expression) => {
12973
12974
  return isNodeOfType(expressionContainer, "JSXExpressionContainer") && expressionContainer.expression === expressionRoot && isEventHandlerAttribute(expressionContainer.parent);
12974
12975
  };
12975
12976
  const isInlineRetainedHandlerFunction = (functionNode, context) => {
12976
- if (!isFunctionLike$2(functionNode)) return false;
12977
+ if (!isFunctionLike$1(functionNode)) return false;
12977
12978
  const functionRoot = findTransparentExpressionRoot(functionNode);
12978
12979
  const callbackCall = functionRoot.parent;
12979
12980
  if (isNodeOfType(callbackCall, "CallExpression") && callbackCall.arguments?.[0] === functionRoot && isHookCall$2(callbackCall, "useCallback") && isDirectJsxEventHandlerValue(callbackCall)) return true;
@@ -13166,7 +13167,7 @@ const recordReference = (state, identifier, flag) => {
13166
13167
  };
13167
13168
  const isFunctionBodyBlock = (block) => {
13168
13169
  if (!block.parent) return false;
13169
- return isFunctionLike$2(block.parent);
13170
+ return isFunctionLike$1(block.parent);
13170
13171
  };
13171
13172
  const isCatchClauseBlock = (block) => block.parent !== null && block.parent !== void 0 && block.parent.type === "CatchClause";
13172
13173
  const handleVariableDeclaration = (declaration, state) => {
@@ -13321,7 +13322,7 @@ const walkParameterReferences = (pattern, state) => {
13321
13322
  if (isNodeOfType(pattern, "RestElement")) walkParameterReferences(pattern.argument, state);
13322
13323
  };
13323
13324
  const walk = (node, state) => {
13324
- if (isFunctionLike$2(node)) {
13325
+ if (isFunctionLike$1(node)) {
13325
13326
  if (isNodeOfType(node, "FunctionDeclaration") && node.id) handleFunctionDeclaration(node, state);
13326
13327
  const functionParams = node.params ?? [];
13327
13328
  for (const param of functionParams) {
@@ -13555,7 +13556,7 @@ const computeClosureCaptures = (functionNode, scopes) => {
13555
13556
  const out = [];
13556
13557
  const seen = /* @__PURE__ */ new Set();
13557
13558
  walkAst(functionNode, (node) => {
13558
- if (node !== functionNode && isFunctionLike$2(node)) {
13559
+ if (node !== functionNode && isFunctionLike$1(node)) {
13559
13560
  const innerCaptures = closureCaptures(node, scopes);
13560
13561
  for (const reference of innerCaptures) if (reference.resolvedSymbol && !isDescendantScope(reference.resolvedSymbol.scope, functionScope)) {
13561
13562
  if (!seen.has(reference.id)) {
@@ -13591,6 +13592,768 @@ const closureCaptures = (functionNode, scopes) => {
13591
13592
  return computedCaptures;
13592
13593
  };
13593
13594
  //#endregion
13595
+ //#region src/plugin/semantic/control-flow-graph.ts
13596
+ let nextBlockId = 0;
13597
+ const createBlock = (builder) => {
13598
+ const block = {
13599
+ id: nextBlockId++,
13600
+ nodes: [],
13601
+ successors: [],
13602
+ predecessors: []
13603
+ };
13604
+ builder.blocks.push(block);
13605
+ return block;
13606
+ };
13607
+ const addEdge = (from, to, kind) => {
13608
+ const edge = {
13609
+ from,
13610
+ to,
13611
+ kind
13612
+ };
13613
+ from.successors.push(edge);
13614
+ to.predecessors.push(edge);
13615
+ };
13616
+ const appendNode = (builder, block, node) => {
13617
+ block.nodes.push(node);
13618
+ if (!builder.nodeBlock.has(node)) builder.nodeBlock.set(node, block);
13619
+ };
13620
+ const mapDescendantsToBlock = (builder, node, block) => {
13621
+ builder.nodeBlock.set(node, block);
13622
+ if (isFunctionLike$1(node)) {
13623
+ builder.nestedFunctions.push(node);
13624
+ return;
13625
+ }
13626
+ const record = node;
13627
+ for (const key of Object.keys(record)) {
13628
+ if (key === "parent") continue;
13629
+ const child = record[key];
13630
+ if (Array.isArray(child)) {
13631
+ for (const item of child) if (isAstNode(item)) mapDescendantsToBlock(builder, item, block);
13632
+ } else if (isAstNode(child)) mapDescendantsToBlock(builder, child, block);
13633
+ }
13634
+ };
13635
+ const hasInternalControlFlow = (node) => {
13636
+ switch (node.type) {
13637
+ case "IfStatement":
13638
+ case "WhileStatement":
13639
+ case "DoWhileStatement":
13640
+ case "ForStatement":
13641
+ case "ForInStatement":
13642
+ case "ForOfStatement":
13643
+ case "SwitchStatement":
13644
+ case "TryStatement":
13645
+ case "ReturnStatement":
13646
+ case "ThrowStatement":
13647
+ case "BreakStatement":
13648
+ case "ContinueStatement":
13649
+ case "BlockStatement":
13650
+ case "LabeledStatement": return true;
13651
+ default: return false;
13652
+ }
13653
+ };
13654
+ const findLabel = (builder, name) => {
13655
+ if (name === null) {
13656
+ if (builder.loopStack.length > 0) {
13657
+ const top = builder.loopStack[builder.loopStack.length - 1];
13658
+ return {
13659
+ merge: top.merge,
13660
+ header: top.header
13661
+ };
13662
+ }
13663
+ if (builder.switchStack.length > 0) return {
13664
+ merge: builder.switchStack[builder.switchStack.length - 1].merge,
13665
+ header: null
13666
+ };
13667
+ return null;
13668
+ }
13669
+ for (let i = builder.labelStack.length - 1; i >= 0; i--) {
13670
+ const entry = builder.labelStack[i];
13671
+ if (entry.label === name) return {
13672
+ merge: entry.merge,
13673
+ header: entry.header
13674
+ };
13675
+ }
13676
+ return null;
13677
+ };
13678
+ const buildStatements = (builder, statements, current) => {
13679
+ let cursor = current;
13680
+ for (const statement of statements) cursor = buildStatement(builder, statement, cursor);
13681
+ return cursor;
13682
+ };
13683
+ const buildStatement = (builder, statement, current) => {
13684
+ builder.nodeBlock.set(statement, current);
13685
+ if (!hasInternalControlFlow(statement)) {
13686
+ appendNode(builder, current, statement);
13687
+ mapDescendantsToBlock(builder, statement, current);
13688
+ return current;
13689
+ }
13690
+ if (isNodeOfType(statement, "BlockStatement")) return buildStatements(builder, statement.body, current);
13691
+ if (isNodeOfType(statement, "LabeledStatement")) {
13692
+ const merge = createBlock(builder);
13693
+ const labelEntry = {
13694
+ label: statement.label.name,
13695
+ merge,
13696
+ header: null
13697
+ };
13698
+ builder.labelStack.push(labelEntry);
13699
+ const body = statement.body;
13700
+ const end = buildStatement(builder, body, current);
13701
+ builder.labelStack.pop();
13702
+ addEdge(end, merge, "uncond");
13703
+ return merge;
13704
+ }
13705
+ if (isNodeOfType(statement, "ReturnStatement")) {
13706
+ if (statement.argument) mapDescendantsToBlock(builder, statement.argument, current);
13707
+ addEdge(current, builder.exit, "uncond");
13708
+ return createBlock(builder);
13709
+ }
13710
+ if (isNodeOfType(statement, "ThrowStatement")) {
13711
+ if (statement.argument) mapDescendantsToBlock(builder, statement.argument, current);
13712
+ const top = builder.tryStack[builder.tryStack.length - 1];
13713
+ if (top?.catch) addEdge(current, top.catch, "uncond");
13714
+ else if (top?.finally) addEdge(current, top.finally, "uncond");
13715
+ else addEdge(current, builder.exit, "throw");
13716
+ return createBlock(builder);
13717
+ }
13718
+ if (isNodeOfType(statement, "BreakStatement")) {
13719
+ const target = findLabel(builder, statement.label ? statement.label.name : null);
13720
+ if (target) addEdge(current, target.merge, "uncond");
13721
+ else addEdge(current, builder.exit, "uncond");
13722
+ return createBlock(builder);
13723
+ }
13724
+ if (isNodeOfType(statement, "ContinueStatement")) {
13725
+ const target = findLabel(builder, statement.label ? statement.label.name : null);
13726
+ if (target?.header) addEdge(current, target.header, "uncond");
13727
+ return createBlock(builder);
13728
+ }
13729
+ if (isNodeOfType(statement, "IfStatement")) {
13730
+ mapDescendantsToBlock(builder, statement.test, current);
13731
+ const thenBlock = createBlock(builder);
13732
+ const merge = createBlock(builder);
13733
+ addEdge(current, thenBlock, "cond");
13734
+ addEdge(buildStatement(builder, statement.consequent, thenBlock), merge, "uncond");
13735
+ if (statement.alternate) {
13736
+ const elseBlock = createBlock(builder);
13737
+ addEdge(current, elseBlock, "cond");
13738
+ addEdge(buildStatement(builder, statement.alternate, elseBlock), merge, "uncond");
13739
+ } else addEdge(current, merge, "cond");
13740
+ return merge;
13741
+ }
13742
+ if (isNodeOfType(statement, "WhileStatement") || isNodeOfType(statement, "DoWhileStatement")) {
13743
+ const isDoWhile = isNodeOfType(statement, "DoWhileStatement");
13744
+ mapDescendantsToBlock(builder, statement.test, current);
13745
+ const header = createBlock(builder);
13746
+ const body = createBlock(builder);
13747
+ const merge = createBlock(builder);
13748
+ if (isDoWhile) addEdge(current, body, "uncond");
13749
+ else {
13750
+ addEdge(current, header, "uncond");
13751
+ addEdge(header, body, "cond");
13752
+ addEdge(header, merge, "cond");
13753
+ }
13754
+ builder.loopStack.push({
13755
+ header,
13756
+ merge,
13757
+ label: null
13758
+ });
13759
+ const bodyEnd = buildStatement(builder, statement.body, body);
13760
+ builder.loopStack.pop();
13761
+ if (isDoWhile) {
13762
+ addEdge(bodyEnd, header, "uncond");
13763
+ addEdge(header, body, "cond");
13764
+ addEdge(header, merge, "cond");
13765
+ } else addEdge(bodyEnd, header, "uncond");
13766
+ return merge;
13767
+ }
13768
+ if (isNodeOfType(statement, "ForStatement")) {
13769
+ if (statement.init) mapDescendantsToBlock(builder, statement.init, current);
13770
+ if (statement.test) mapDescendantsToBlock(builder, statement.test, current);
13771
+ const header = createBlock(builder);
13772
+ const body = createBlock(builder);
13773
+ const merge = createBlock(builder);
13774
+ addEdge(current, header, "uncond");
13775
+ addEdge(header, body, "cond");
13776
+ addEdge(header, merge, "cond");
13777
+ builder.loopStack.push({
13778
+ header,
13779
+ merge,
13780
+ label: null
13781
+ });
13782
+ const bodyEnd = buildStatement(builder, statement.body, body);
13783
+ builder.loopStack.pop();
13784
+ if (statement.update) mapDescendantsToBlock(builder, statement.update, header);
13785
+ addEdge(bodyEnd, header, "uncond");
13786
+ return merge;
13787
+ }
13788
+ if (isNodeOfType(statement, "ForInStatement") || isNodeOfType(statement, "ForOfStatement")) {
13789
+ mapDescendantsToBlock(builder, statement.right, current);
13790
+ mapDescendantsToBlock(builder, statement.left, current);
13791
+ const header = createBlock(builder);
13792
+ const body = createBlock(builder);
13793
+ const merge = createBlock(builder);
13794
+ addEdge(current, header, "uncond");
13795
+ addEdge(header, body, "cond");
13796
+ addEdge(header, merge, "cond");
13797
+ builder.loopStack.push({
13798
+ header,
13799
+ merge,
13800
+ label: null
13801
+ });
13802
+ const bodyEnd = buildStatement(builder, statement.body, body);
13803
+ builder.loopStack.pop();
13804
+ addEdge(bodyEnd, header, "uncond");
13805
+ return merge;
13806
+ }
13807
+ if (isNodeOfType(statement, "SwitchStatement")) {
13808
+ mapDescendantsToBlock(builder, statement.discriminant, current);
13809
+ const merge = createBlock(builder);
13810
+ builder.switchStack.push({
13811
+ merge,
13812
+ label: null
13813
+ });
13814
+ let previousCaseEnd = null;
13815
+ let hasDefault = false;
13816
+ for (const switchCase of statement.cases) {
13817
+ const caseBlock = createBlock(builder);
13818
+ addEdge(current, caseBlock, "cond");
13819
+ if (previousCaseEnd) addEdge(previousCaseEnd, caseBlock, "uncond");
13820
+ previousCaseEnd = buildStatements(builder, switchCase.consequent, caseBlock);
13821
+ if (switchCase.test === null) hasDefault = true;
13822
+ }
13823
+ builder.switchStack.pop();
13824
+ if (previousCaseEnd) addEdge(previousCaseEnd, merge, "uncond");
13825
+ if (!hasDefault) addEdge(current, merge, "cond");
13826
+ return merge;
13827
+ }
13828
+ if (isNodeOfType(statement, "TryStatement")) {
13829
+ const tryBlock = createBlock(builder);
13830
+ const merge = createBlock(builder);
13831
+ let catchBlock = null;
13832
+ let finallyBlock = null;
13833
+ if (statement.handler) catchBlock = createBlock(builder);
13834
+ if (statement.finalizer) finallyBlock = createBlock(builder);
13835
+ addEdge(current, tryBlock, "uncond");
13836
+ builder.tryStack.push({
13837
+ catch: catchBlock,
13838
+ finally: finallyBlock
13839
+ });
13840
+ const tryEnd = buildStatements(builder, statement.block.body, tryBlock);
13841
+ builder.tryStack.pop();
13842
+ if (catchBlock) addEdge(tryBlock, catchBlock, "cond");
13843
+ if (statement.handler && catchBlock) {
13844
+ const handlerBody = statement.handler.body;
13845
+ const catchEnd = buildStatement(builder, handlerBody, catchBlock);
13846
+ if (finallyBlock) addEdge(catchEnd, finallyBlock, "uncond");
13847
+ else addEdge(catchEnd, merge, "uncond");
13848
+ }
13849
+ if (finallyBlock && statement.finalizer) {
13850
+ addEdge(tryEnd, finallyBlock, "uncond");
13851
+ addEdge(buildStatements(builder, statement.finalizer.body, finallyBlock), merge, "uncond");
13852
+ } else addEdge(tryEnd, merge, "uncond");
13853
+ return merge;
13854
+ }
13855
+ appendNode(builder, current, statement);
13856
+ mapDescendantsToBlock(builder, statement, current);
13857
+ return current;
13858
+ };
13859
+ const buildFunctionCfg = (functionNode, body, nestedFunctionSink) => {
13860
+ const builder = {
13861
+ blocks: [],
13862
+ entry: null,
13863
+ exit: null,
13864
+ nestedFunctions: nestedFunctionSink,
13865
+ nodeBlock: /* @__PURE__ */ new Map(),
13866
+ loopStack: [],
13867
+ switchStack: [],
13868
+ tryStack: [],
13869
+ labelStack: []
13870
+ };
13871
+ const entry = createBlock(builder);
13872
+ const exit = createBlock(builder);
13873
+ builder.entry = entry;
13874
+ builder.exit = exit;
13875
+ let bodyEnd;
13876
+ if (isNodeOfType(body, "BlockStatement")) bodyEnd = buildStatements(builder, body.body, entry);
13877
+ else {
13878
+ mapDescendantsToBlock(builder, body, entry);
13879
+ bodyEnd = entry;
13880
+ }
13881
+ addEdge(bodyEnd, exit, "uncond");
13882
+ return {
13883
+ owner: functionNode,
13884
+ entry,
13885
+ exit,
13886
+ blocks: builder.blocks,
13887
+ blockOf: (node) => builder.nodeBlock.get(node) ?? null
13888
+ };
13889
+ };
13890
+ const computeUnconditionalSet = (cfg) => {
13891
+ const reachableFromEntry = (excluded) => {
13892
+ const visited = /* @__PURE__ */ new Set();
13893
+ const queue = [];
13894
+ if (cfg.entry !== excluded) queue.push(cfg.entry);
13895
+ while (queue.length > 0) {
13896
+ const block = queue.shift();
13897
+ if (visited.has(block)) continue;
13898
+ visited.add(block);
13899
+ for (const edge of block.successors) {
13900
+ if (edge.kind === "throw") continue;
13901
+ if (edge.to === excluded) continue;
13902
+ queue.push(edge.to);
13903
+ }
13904
+ }
13905
+ return visited;
13906
+ };
13907
+ const reachableFromEntryFull = reachableFromEntry(null);
13908
+ const unconditional = /* @__PURE__ */ new Set();
13909
+ unconditional.add(cfg.entry);
13910
+ unconditional.add(cfg.exit);
13911
+ for (const block of cfg.blocks) {
13912
+ if (unconditional.has(block)) continue;
13913
+ if (!reachableFromEntryFull.has(block)) {
13914
+ unconditional.add(block);
13915
+ continue;
13916
+ }
13917
+ if (!reachableFromEntry(block).has(cfg.exit)) unconditional.add(block);
13918
+ }
13919
+ return unconditional;
13920
+ };
13921
+ const analyzeControlFlow = (program) => {
13922
+ nextBlockId = 0;
13923
+ const functionCfgs = /* @__PURE__ */ new Map();
13924
+ const pendingFunctions = [];
13925
+ const buildFor = (functionNode, body) => {
13926
+ const cfg = buildFunctionCfg(functionNode, body, pendingFunctions);
13927
+ functionCfgs.set(functionNode, {
13928
+ cfg,
13929
+ unconditionalSet: computeUnconditionalSet(cfg)
13930
+ });
13931
+ };
13932
+ if (isNodeOfType(program, "Program")) buildFor(program, {
13933
+ type: "BlockStatement",
13934
+ body: program.body
13935
+ });
13936
+ for (let functionIndex = 0; functionIndex < pendingFunctions.length; functionIndex += 1) {
13937
+ const functionNode = pendingFunctions[functionIndex];
13938
+ if (!isFunctionLike$1(functionNode) || !functionNode.body || functionCfgs.has(functionNode)) continue;
13939
+ buildFor(functionNode, functionNode.body);
13940
+ }
13941
+ const getFunctionEntry = (functionNode) => {
13942
+ const existingEntry = functionCfgs.get(functionNode);
13943
+ if (existingEntry) return existingEntry;
13944
+ if (!isFunctionLike$1(functionNode) || !functionNode.body) return null;
13945
+ buildFor(functionNode, functionNode.body);
13946
+ return functionCfgs.get(functionNode) ?? null;
13947
+ };
13948
+ const enclosingFunction = (node) => {
13949
+ let current = node;
13950
+ while (current) {
13951
+ if (isFunctionLike$1(current)) return current;
13952
+ if (isNodeOfType(current, "Program")) return current;
13953
+ current = current.parent ?? null;
13954
+ }
13955
+ return null;
13956
+ };
13957
+ const cfgFor = (functionLike) => {
13958
+ return getFunctionEntry(functionLike)?.cfg ?? null;
13959
+ };
13960
+ const isUnconditionalFromEntry = (node) => {
13961
+ const owner = enclosingFunction(node);
13962
+ if (!owner) return true;
13963
+ const entry = getFunctionEntry(owner);
13964
+ if (!entry) return true;
13965
+ const block = entry.cfg.blockOf(node);
13966
+ if (!block) return true;
13967
+ return entry.unconditionalSet.has(block);
13968
+ };
13969
+ return {
13970
+ cfgFor,
13971
+ enclosingFunction,
13972
+ isUnconditionalFromEntry
13973
+ };
13974
+ };
13975
+ //#endregion
13976
+ //#region src/plugin/utils/resolve-fresh-render-value.ts
13977
+ const classifyFreshRenderValue = (expression) => {
13978
+ const candidate = stripParenExpression(expression);
13979
+ if (isNodeOfType(candidate, "ObjectExpression")) return "object";
13980
+ if (isNodeOfType(candidate, "ArrayExpression")) return "array";
13981
+ if (isNodeOfType(candidate, "ArrowFunctionExpression") || isNodeOfType(candidate, "FunctionExpression")) return "function";
13982
+ if (isNodeOfType(candidate, "JSXElement") || isNodeOfType(candidate, "JSXFragment")) return "JSX";
13983
+ if (isNodeOfType(candidate, "NewExpression")) return "instance";
13984
+ return null;
13985
+ };
13986
+ const resolveFreshRenderValue = (expression, scopes, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
13987
+ const directKind = classifyFreshRenderValue(expression);
13988
+ if (directKind) return {
13989
+ bindingName: null,
13990
+ kind: directKind
13991
+ };
13992
+ const candidate = stripParenExpression(expression);
13993
+ if (!isNodeOfType(candidate, "Identifier")) return null;
13994
+ const symbol = scopes.symbolFor(candidate);
13995
+ if (!symbol || symbol.scope.kind === "module" || symbol.kind !== "const" || !symbol.initializer || visitedSymbolIds.has(symbol.id) || symbol.references.some((reference) => reference.flag !== "read") || !isNodeOfType(symbol.declarationNode, "VariableDeclarator") || symbol.declarationNode.id !== symbol.bindingIdentifier) return null;
13996
+ visitedSymbolIds.add(symbol.id);
13997
+ const resolved = resolveFreshRenderValue(symbol.initializer, scopes, visitedSymbolIds);
13998
+ return resolved ? {
13999
+ bindingName: candidate.name,
14000
+ kind: resolved.kind
14001
+ } : null;
14002
+ };
14003
+ //#endregion
14004
+ //#region src/plugin/utils/find-forwarded-fresh-hook-dependencies.ts
14005
+ const DEPENDENCY_HOOK_NAMES = new Set([
14006
+ ...HOOKS_WITH_DEPS,
14007
+ "useImperativeHandle",
14008
+ "useInsertionEffect"
14009
+ ]);
14010
+ const crossFileScopes = /* @__PURE__ */ new WeakMap();
14011
+ const crossFileControlFlow = /* @__PURE__ */ new WeakMap();
14012
+ const forwardedFreshDependencyCache = /* @__PURE__ */ new WeakMap();
14013
+ const getCrossFileScopes = (resolved) => {
14014
+ const cached = crossFileScopes.get(resolved.programNode);
14015
+ if (cached) return cached;
14016
+ const scopes = analyzeScopes(resolved.programNode);
14017
+ crossFileScopes.set(resolved.programNode, scopes);
14018
+ return scopes;
14019
+ };
14020
+ const getCrossFileControlFlow = (resolved) => {
14021
+ const cached = crossFileControlFlow.get(resolved.programNode);
14022
+ if (cached) return cached;
14023
+ const cfg = analyzeControlFlow(resolved.programNode);
14024
+ crossFileControlFlow.set(resolved.programNode, cfg);
14025
+ return cfg;
14026
+ };
14027
+ const isNodeReachable = (node, cfg) => {
14028
+ const owner = cfg.enclosingFunction(node);
14029
+ if (!owner) return true;
14030
+ const functionCfg = cfg.cfgFor(owner);
14031
+ if (!functionCfg) return true;
14032
+ const targetBlock = functionCfg.blockOf(node);
14033
+ if (!targetBlock) return true;
14034
+ const visitedBlocks = new Set([functionCfg.entry]);
14035
+ const pendingBlocks = [functionCfg.entry];
14036
+ while (pendingBlocks.length > 0) {
14037
+ const currentBlock = pendingBlocks.pop();
14038
+ if (!currentBlock) break;
14039
+ if (currentBlock === targetBlock) return true;
14040
+ for (const edge of currentBlock.successors) {
14041
+ if (visitedBlocks.has(edge.to)) continue;
14042
+ visitedBlocks.add(edge.to);
14043
+ pendingBlocks.push(edge.to);
14044
+ }
14045
+ }
14046
+ return false;
14047
+ };
14048
+ const isCustomHookFunction = (functionNode, fallbackName) => {
14049
+ const displayName = componentOrHookDisplayNameForFunction(functionNode) ?? fallbackName ?? "";
14050
+ return /^use[A-Z0-9]/.test(displayName);
14051
+ };
14052
+ const getImportedHookBinding = (callee, scopes) => {
14053
+ if (!isNodeOfType(callee, "Identifier")) return null;
14054
+ const importedSymbol = resolveConstIdentifierAlias(callee, scopes);
14055
+ if (importedSymbol?.kind !== "import" || !importedSymbol.initializer) return null;
14056
+ const importDeclaration = importedSymbol.initializer.parent;
14057
+ if (!importDeclaration || !isNodeOfType(importDeclaration, "ImportDeclaration")) return null;
14058
+ const source = importDeclaration.source?.value;
14059
+ if (typeof source !== "string") return null;
14060
+ const exportedName = resolveImportedExportName(importedSymbol.initializer);
14061
+ return exportedName ? {
14062
+ exportedName,
14063
+ source
14064
+ } : null;
14065
+ };
14066
+ const resolveImportedHookFunction = (callee, scopes, currentFilename) => {
14067
+ if (!currentFilename) return null;
14068
+ const importedBinding = getImportedHookBinding(callee, scopes);
14069
+ if (!importedBinding) return null;
14070
+ const resolved = resolveCrossFileFunctionExportWithFilePath(currentFilename, importedBinding.source, importedBinding.exportedName);
14071
+ if (!resolved || !isCustomHookFunction(resolved.functionNode, importedBinding.exportedName)) return null;
14072
+ return {
14073
+ cfg: getCrossFileControlFlow(resolved),
14074
+ filePath: resolved.filePath,
14075
+ functionNode: resolved.functionNode,
14076
+ programNode: resolved.programNode,
14077
+ scopes: getCrossFileScopes(resolved)
14078
+ };
14079
+ };
14080
+ const dependencyIndexForReactHookReference = (expression, scopes, dependencyHookNames, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
14081
+ const candidate = stripParenExpression(expression);
14082
+ if (isNodeOfType(candidate, "Identifier")) {
14083
+ const symbol = resolveConstIdentifierAlias(candidate, scopes);
14084
+ if (!symbol || visitedSymbolIds.has(symbol.id)) return null;
14085
+ if (isImportedFromReact(symbol)) {
14086
+ const importedName = getImportedName(symbol.declarationNode);
14087
+ if (!importedName || !dependencyHookNames.has(importedName)) return null;
14088
+ return importedName === "useImperativeHandle" ? 2 : 1;
14089
+ }
14090
+ if (symbol.kind !== "const" || !symbol.initializer || isSymbolMutated(symbol)) return null;
14091
+ visitedSymbolIds.add(symbol.id);
14092
+ return dependencyIndexForReactHookReference(symbol.initializer, scopes, dependencyHookNames, visitedSymbolIds);
14093
+ }
14094
+ if (isNodeOfType(candidate, "MemberExpression")) {
14095
+ const hookName = getStaticPropertyName(candidate);
14096
+ if (!hookName || !dependencyHookNames.has(hookName)) return null;
14097
+ const receiver = stripParenExpression(candidate.object);
14098
+ if (!isNodeOfType(receiver, "Identifier") || !isReactNamespaceImport(receiver, scopes)) return null;
14099
+ return hookName === "useImperativeHandle" ? 2 : 1;
14100
+ }
14101
+ if (!isNodeOfType(candidate, "ConditionalExpression")) return null;
14102
+ const consequentIndex = dependencyIndexForReactHookReference(candidate.consequent, scopes, dependencyHookNames, new Set(visitedSymbolIds));
14103
+ const alternateIndex = dependencyIndexForReactHookReference(candidate.alternate, scopes, dependencyHookNames, new Set(visitedSymbolIds));
14104
+ return consequentIndex !== null && consequentIndex === alternateIndex ? consequentIndex : null;
14105
+ };
14106
+ const getImportedReactDependencyIndex = (callExpression, scopes, currentFilename, dependencyHookNames) => {
14107
+ if (!currentFilename) return null;
14108
+ const importedBinding = getImportedHookBinding(stripParenExpression(callExpression.callee), scopes);
14109
+ if (!importedBinding) return null;
14110
+ const resolved = resolveCrossFileValueExportWithFilePath(currentFilename, importedBinding.source, importedBinding.exportedName);
14111
+ if (!resolved) return null;
14112
+ return dependencyIndexForReactHookReference(resolved.exportedNode, getCrossFileScopes(resolved), dependencyHookNames);
14113
+ };
14114
+ const resolveHookFunction = (callExpression, scopes, cfg, currentFilename) => {
14115
+ const callee = stripParenExpression(callExpression.callee);
14116
+ const localFunction = resolveExactLocalFunction(callee, scopes);
14117
+ if (localFunction && isCustomHookFunction(localFunction)) {
14118
+ const programNode = findProgramRoot(localFunction);
14119
+ if (!programNode) return null;
14120
+ return {
14121
+ cfg,
14122
+ filePath: currentFilename,
14123
+ functionNode: localFunction,
14124
+ programNode,
14125
+ scopes
14126
+ };
14127
+ }
14128
+ return resolveImportedHookFunction(callee, scopes, currentFilename);
14129
+ };
14130
+ const collectParameterBindings = (functionNode) => {
14131
+ if (!isFunctionLike$1(functionNode)) return [];
14132
+ const bindings = [];
14133
+ for (const [parameterIndex, rawParameter] of (functionNode.params ?? []).entries()) {
14134
+ const parameter = stripParenExpression(rawParameter);
14135
+ if (isNodeOfType(parameter, "Identifier")) {
14136
+ bindings.push({
14137
+ bindingIdentifier: parameter,
14138
+ defaultExpression: null,
14139
+ parameterIndex,
14140
+ propertyName: null
14141
+ });
14142
+ continue;
14143
+ }
14144
+ if (isNodeOfType(parameter, "AssignmentPattern") && isNodeOfType(parameter.left, "Identifier")) {
14145
+ bindings.push({
14146
+ bindingIdentifier: parameter.left,
14147
+ defaultExpression: parameter.right,
14148
+ parameterIndex,
14149
+ propertyName: null
14150
+ });
14151
+ continue;
14152
+ }
14153
+ if (!isNodeOfType(parameter, "ObjectPattern")) continue;
14154
+ for (const property of parameter.properties ?? []) {
14155
+ if (!isNodeOfType(property, "Property")) continue;
14156
+ const propertyName = getStaticPropertyKeyName(property, { allowComputedString: true });
14157
+ if (!propertyName) continue;
14158
+ const value = stripParenExpression(property.value);
14159
+ if (isNodeOfType(value, "Identifier")) bindings.push({
14160
+ bindingIdentifier: value,
14161
+ defaultExpression: null,
14162
+ parameterIndex,
14163
+ propertyName
14164
+ });
14165
+ else if (isNodeOfType(value, "AssignmentPattern") && isNodeOfType(value.left, "Identifier")) bindings.push({
14166
+ bindingIdentifier: value.left,
14167
+ defaultExpression: value.right,
14168
+ parameterIndex,
14169
+ propertyName
14170
+ });
14171
+ }
14172
+ }
14173
+ return bindings;
14174
+ };
14175
+ const resolveConstObjectExpression = (expression, scopes, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
14176
+ const candidate = stripParenExpression(expression);
14177
+ if (isNodeOfType(candidate, "ObjectExpression")) return candidate;
14178
+ if (!isNodeOfType(candidate, "Identifier")) return null;
14179
+ const symbol = scopes.symbolFor(candidate);
14180
+ if (!symbol || symbol.kind !== "const" || !symbol.initializer || visitedSymbolIds.has(symbol.id) || isSymbolMutated(symbol)) return null;
14181
+ visitedSymbolIds.add(symbol.id);
14182
+ return resolveConstObjectExpression(symbol.initializer, scopes, visitedSymbolIds);
14183
+ };
14184
+ const findObjectPropertyValue = (objectExpression, propertyName) => {
14185
+ for (let propertyIndex = objectExpression.properties.length - 1; propertyIndex >= 0; propertyIndex--) {
14186
+ const property = objectExpression.properties[propertyIndex];
14187
+ if (isNodeOfType(property, "SpreadElement")) return {
14188
+ expression: null,
14189
+ isProvenOmitted: false
14190
+ };
14191
+ if (isNodeOfType(property, "Property") && getStaticPropertyKeyName(property, { allowComputedString: true }) === propertyName) return {
14192
+ expression: property.value,
14193
+ isProvenOmitted: false
14194
+ };
14195
+ }
14196
+ return {
14197
+ expression: null,
14198
+ isProvenOmitted: true
14199
+ };
14200
+ };
14201
+ const resolveArgumentValue = (callExpression, parameter, callerScopes) => {
14202
+ if ((callExpression.arguments ?? []).slice(0, parameter.parameterIndex + 1).some((argument) => isNodeOfType(argument, "SpreadElement"))) return {
14203
+ expression: null,
14204
+ isProvenOmitted: false
14205
+ };
14206
+ const argument = callExpression.arguments?.[parameter.parameterIndex];
14207
+ if (!argument) return {
14208
+ expression: null,
14209
+ isProvenOmitted: true
14210
+ };
14211
+ if (parameter.propertyName === null) return {
14212
+ expression: argument,
14213
+ isProvenOmitted: false
14214
+ };
14215
+ const objectExpression = resolveConstObjectExpression(argument, callerScopes);
14216
+ if (!objectExpression) return {
14217
+ expression: null,
14218
+ isProvenOmitted: false
14219
+ };
14220
+ return findObjectPropertyValue(objectExpression, parameter.propertyName);
14221
+ };
14222
+ const isSymbolMutated = (symbol) => {
14223
+ if (symbol.references.some((reference) => reference.flag !== "read")) return true;
14224
+ for (const reference of symbol.references) {
14225
+ let expression = reference.identifier;
14226
+ while (expression.parent && isNodeOfType(expression.parent, "MemberExpression") && expression.parent.object === expression) expression = expression.parent;
14227
+ const parent = expression.parent;
14228
+ if (isNodeOfType(parent, "AssignmentExpression") && parent.left === expression || isNodeOfType(parent, "UpdateExpression") && parent.argument === expression || isNodeOfType(parent, "UnaryExpression") && parent.operator === "delete" && parent.argument === expression) return true;
14229
+ if (isNodeOfType(parent, "CallExpression") && parent.callee === expression && isNodeOfType(expression, "MemberExpression")) {
14230
+ const methodName = getStaticPropertyName(expression);
14231
+ if (methodName && (MUTATING_ARRAY_METHODS.has(methodName) || MUTATING_COLLECTION_METHODS.has(methodName))) return true;
14232
+ }
14233
+ }
14234
+ return false;
14235
+ };
14236
+ const expressionHasTaint = (expression, mode, scopes, taint, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
14237
+ const candidate = stripParenExpression(expression);
14238
+ if (!isNodeOfType(candidate, "Identifier")) return false;
14239
+ const symbol = scopes.symbolFor(candidate);
14240
+ if (!symbol || visitedSymbolIds.has(symbol.id) || isSymbolMutated(symbol)) return false;
14241
+ if ((mode === "value" ? taint.valueSymbolIds : taint.listSymbolIds).has(symbol.id)) return true;
14242
+ if (symbol.kind !== "const" || !symbol.initializer || !isNodeOfType(symbol.declarationNode, "VariableDeclarator") || symbol.declarationNode.id !== symbol.bindingIdentifier) return false;
14243
+ visitedSymbolIds.add(symbol.id);
14244
+ return expressionHasTaint(symbol.initializer, mode, scopes, taint, visitedSymbolIds);
14245
+ };
14246
+ const dependencyListContainsTaint = (expression, scopes, taint, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
14247
+ if (expressionHasTaint(expression, "list", scopes, taint)) return true;
14248
+ const candidate = stripParenExpression(expression);
14249
+ if (isNodeOfType(candidate, "Identifier")) {
14250
+ const symbol = scopes.symbolFor(candidate);
14251
+ if (!symbol || visitedSymbolIds.has(symbol.id) || symbol.kind !== "const" || !symbol.initializer || isSymbolMutated(symbol)) return false;
14252
+ visitedSymbolIds.add(symbol.id);
14253
+ return dependencyListContainsTaint(symbol.initializer, scopes, taint, visitedSymbolIds);
14254
+ }
14255
+ if (!isNodeOfType(candidate, "ArrayExpression")) return false;
14256
+ return (candidate.elements ?? []).some((element) => {
14257
+ if (!element) return false;
14258
+ if (isNodeOfType(element, "SpreadElement")) return expressionHasTaint(element.argument, "list", scopes, taint);
14259
+ return expressionHasTaint(element, "value", scopes, taint);
14260
+ });
14261
+ };
14262
+ const buildForwardedTaint = (callExpression, target, callerScopes, callerTaint) => {
14263
+ const forwardedTaint = {
14264
+ listSymbolIds: /* @__PURE__ */ new Set(),
14265
+ valueSymbolIds: /* @__PURE__ */ new Set()
14266
+ };
14267
+ for (const parameter of collectParameterBindings(target.functionNode)) {
14268
+ const argument = resolveArgumentValue(callExpression, parameter, callerScopes);
14269
+ if (!argument.expression) continue;
14270
+ const targetSymbol = target.scopes.symbolFor(parameter.bindingIdentifier);
14271
+ if (!targetSymbol || isSymbolMutated(targetSymbol)) continue;
14272
+ if (expressionHasTaint(argument.expression, "value", callerScopes, callerTaint)) forwardedTaint.valueSymbolIds.add(targetSymbol.id);
14273
+ if (expressionHasTaint(argument.expression, "list", callerScopes, callerTaint) || dependencyListContainsTaint(argument.expression, callerScopes, callerTaint)) forwardedTaint.listSymbolIds.add(targetSymbol.id);
14274
+ }
14275
+ return forwardedTaint;
14276
+ };
14277
+ const taintReachesBuiltInDependency = (target, taint, remainingDepth, visitedFunctions, dependencyHookNames) => {
14278
+ if (!isFunctionLike$1(target.functionNode)) return false;
14279
+ const functionNode = target.functionNode;
14280
+ if (remainingDepth < 0 || visitedFunctions.has(functionNode) || [...taint.valueSymbolIds, ...taint.listSymbolIds].some((symbolId) => {
14281
+ const symbol = target.scopes.ownScopeFor(target.functionNode)?.symbols.find((candidate) => candidate.id === symbolId);
14282
+ return symbol ? isSymbolMutated(symbol) : false;
14283
+ })) return false;
14284
+ const nextVisitedFunctions = new Set(visitedFunctions);
14285
+ nextVisitedFunctions.add(functionNode);
14286
+ let didReachDependency = false;
14287
+ walkAst(functionNode.body, (node) => {
14288
+ if (didReachDependency) return false;
14289
+ if (node !== functionNode.body && isFunctionLike$1(node)) return false;
14290
+ if (!isNodeOfType(node, "CallExpression")) return;
14291
+ if (!isNodeReachable(node, target.cfg)) return;
14292
+ if (isReactApiCall(node, dependencyHookNames, target.scopes, { allowGlobalReactNamespace: true })) {
14293
+ const callee = stripParenExpression(node.callee);
14294
+ const dependencyIndex = (isNodeOfType(callee, "Identifier") ? callee.name : isNodeOfType(callee, "MemberExpression") ? getStaticPropertyName(callee) : null) === "useImperativeHandle" ? 2 : 1;
14295
+ const dependencies = node.arguments?.[dependencyIndex];
14296
+ if (dependencies && !isNodeOfType(dependencies, "SpreadElement") && dependencyListContainsTaint(dependencies, target.scopes, taint)) {
14297
+ didReachDependency = true;
14298
+ return false;
14299
+ }
14300
+ return;
14301
+ }
14302
+ const importedDependencyIndex = getImportedReactDependencyIndex(node, target.scopes, target.filePath, dependencyHookNames);
14303
+ if (importedDependencyIndex !== null) {
14304
+ const dependencies = node.arguments?.[importedDependencyIndex];
14305
+ if (dependencies && !isNodeOfType(dependencies, "SpreadElement") && dependencyListContainsTaint(dependencies, target.scopes, taint)) {
14306
+ didReachDependency = true;
14307
+ return false;
14308
+ }
14309
+ return;
14310
+ }
14311
+ if (remainingDepth === 0) return;
14312
+ const nestedTarget = resolveHookFunction(node, target.scopes, target.cfg, target.filePath);
14313
+ if (!nestedTarget) return;
14314
+ const forwardedTaint = buildForwardedTaint(node, nestedTarget, target.scopes, taint);
14315
+ if (forwardedTaint.valueSymbolIds.size === 0 && forwardedTaint.listSymbolIds.size === 0) return;
14316
+ if (taintReachesBuiltInDependency(nestedTarget, forwardedTaint, remainingDepth - 1, nextVisitedFunctions, dependencyHookNames)) {
14317
+ didReachDependency = true;
14318
+ return false;
14319
+ }
14320
+ });
14321
+ return didReachDependency;
14322
+ };
14323
+ const findForwardedFreshHookDependencies = (callExpression, context, dependencyHookNames = DEPENDENCY_HOOK_NAMES) => {
14324
+ const cacheKey = [...dependencyHookNames].sort().join("\0");
14325
+ const cacheForCall = forwardedFreshDependencyCache.get(callExpression);
14326
+ const cached = cacheForCall?.get(cacheKey);
14327
+ if (cached) return cached;
14328
+ const findings = [];
14329
+ if (cacheForCall) cacheForCall.set(cacheKey, findings);
14330
+ else forwardedFreshDependencyCache.set(callExpression, new Map([[cacheKey, findings]]));
14331
+ if (!findRenderPhaseComponentOrHook(callExpression, context.scopes)) return findings;
14332
+ if (!isNodeReachable(callExpression, context.cfg)) return findings;
14333
+ const target = resolveHookFunction(callExpression, context.scopes, context.cfg, context.filename);
14334
+ if (!target) return findings;
14335
+ for (const parameter of collectParameterBindings(target.functionNode)) {
14336
+ const targetSymbol = target.scopes.symbolFor(parameter.bindingIdentifier);
14337
+ if (!targetSymbol || isSymbolMutated(targetSymbol)) continue;
14338
+ const argument = resolveArgumentValue(callExpression, parameter, context.scopes);
14339
+ const sourceExpression = argument.expression ?? (argument.isProvenOmitted ? parameter.defaultExpression : null);
14340
+ if (!sourceExpression) continue;
14341
+ const freshness = resolveFreshRenderValue(sourceExpression, argument.expression ? context.scopes : target.scopes);
14342
+ if (!freshness) continue;
14343
+ if (!taintReachesBuiltInDependency(target, {
14344
+ listSymbolIds: /* @__PURE__ */ new Set(),
14345
+ valueSymbolIds: new Set([targetSymbol.id])
14346
+ }, 4, /* @__PURE__ */ new Set(), dependencyHookNames)) continue;
14347
+ findings.push({
14348
+ bindingName: freshness.bindingName ?? (isNodeOfType(parameter.bindingIdentifier, "Identifier") ? parameter.bindingIdentifier.name : "dependency"),
14349
+ kind: freshness.kind,
14350
+ origin: argument.expression ? "argument" : "default",
14351
+ reportNode: argument.expression ?? callExpression
14352
+ });
14353
+ }
14354
+ return findings;
14355
+ };
14356
+ //#endregion
13594
14357
  //#region src/plugin/utils/is-react-hoc-callback-argument.ts
13595
14358
  const reactHocCalleeName = (callee) => {
13596
14359
  if (isNodeOfType(callee, "Identifier")) return callee.name;
@@ -13605,6 +14368,22 @@ const isReactHocCallbackArgument = (functionNode) => {
13605
14368
  return calleeName !== null && REACT_HOC_NAMES.has(calleeName);
13606
14369
  };
13607
14370
  //#endregion
14371
+ //#region src/plugin/utils/is-outside-all-functions.ts
14372
+ const FUNCTION_SCOPE_KINDS = new Set([
14373
+ "function",
14374
+ "arrow-function",
14375
+ "method"
14376
+ ]);
14377
+ const isOutsideAllFunctions = (symbol) => {
14378
+ let scope = symbol.scope;
14379
+ while (scope) {
14380
+ if (FUNCTION_SCOPE_KINDS.has(scope.kind)) return false;
14381
+ if (scope.kind === "module") return true;
14382
+ scope = scope.parent;
14383
+ }
14384
+ return true;
14385
+ };
14386
+ //#endregion
13608
14387
  //#region src/plugin/rules/react-builtins/exhaustive-deps-low-level.ts
13609
14388
  /**
13610
14389
  * Lowest-level helpers consumed by both the main `exhaustive-deps`
@@ -13657,25 +14436,6 @@ const getHookName = (callee, scopes) => {
13657
14436
  if (isNodeOfType(strippedCallee, "MemberExpression") && !strippedCallee.computed && isNodeOfType(strippedCallee.property, "Identifier")) return strippedCallee.property.name;
13658
14437
  return null;
13659
14438
  };
13660
- const FUNCTION_SCOPE_KINDS = new Set([
13661
- "function",
13662
- "arrow-function",
13663
- "method"
13664
- ]);
13665
- /**
13666
- * True for symbols declared at module scope (outside any function
13667
- * scope). Module-scope bindings don't change between renders so they
13668
- * don't need to live in dependency arrays.
13669
- */
13670
- const isOutsideAllFunctions = (symbol) => {
13671
- let scope = symbol.scope;
13672
- while (scope) {
13673
- if (FUNCTION_SCOPE_KINDS.has(scope.kind)) return false;
13674
- if (scope.kind === "module") return true;
13675
- scope = scope.parent ?? null;
13676
- }
13677
- return true;
13678
- };
13679
14439
  //#endregion
13680
14440
  //#region src/plugin/rules/react-builtins/exhaustive-deps-messages.ts
13681
14441
  const buildMissingDepMessage = (hookName, depName) => `\`${hookName}\` can run with a stale \`${depName}\` & show your users old data.`;
@@ -13693,6 +14453,7 @@ const buildComplexDepMessage = (hookName) => `A complex expression in \`${hookNa
13693
14453
  const buildAsyncEffectMessage = (hookName) => `\`${hookName}\` was given an async function, so its cleanup breaks.`;
13694
14454
  const buildUnknownCallbackMessage = (hookName) => `\`${hookName}\`'s callback is defined elsewhere, so dependencies can't be checked and stale values can slip through.`;
13695
14455
  const buildUnstableDepMessage = (hookName, depName) => `\`${depName}\` is rebuilt every render, so \`${hookName}\` runs every time.`;
14456
+ const buildForwardedUnstableDepMessage = (depName) => `\`${depName}\` is rebuilt every render and reaches a Hook dependency inside this custom Hook.`;
13696
14457
  const buildSetStateWithoutDepsMessage = (hookName, setterName) => `\`${hookName}\` calls \`${setterName}\` with no dependency array, so it can loop forever & freeze the component.`;
13697
14458
  const buildRefCleanupMessage = (depName) => `Your cleanup may read the wrong node since the ref \`${depName}\` can change before it runs.`;
13698
14459
  const buildAssignmentMessage = (name) => `Assigning to \`${name}\` inside a hook is thrown away after each render, so the next render reads the old value.`;
@@ -14784,6 +15545,10 @@ If the missing value is recreated every render, move it inside the hook or stabi
14784
15545
  };
14785
15546
  const isAutoDependenciesHook = (hookName) => settings.experimental_autoDependenciesHooks.includes(hookName);
14786
15547
  return { CallExpression(node) {
15548
+ for (const finding of findForwardedFreshHookDependencies(node, context, EFFECT_HOOK_NAMES$1)) context.report({
15549
+ node: finding.reportNode,
15550
+ message: buildForwardedUnstableDepMessage(finding.bindingName)
15551
+ });
14787
15552
  const hookName = getHookName(node.callee, context.scopes);
14788
15553
  if (!hookName || !isHookOfInterest(hookName, node.callee)) return;
14789
15554
  if (HOOKS_REQUIRING_DEPS_MATCH.has(hookName) && !isReactApiCall(node, HOOKS_REQUIRING_DEPS_MATCH, context.scopes, {
@@ -16659,7 +17424,7 @@ const classifyReturnedExpression = (expression) => {
16659
17424
  const collectTopLevelReturnExpressions$1 = (block) => {
16660
17425
  const returns = [];
16661
17426
  walkAst(block, (child) => {
16662
- if (isFunctionLike$2(child)) return false;
17427
+ if (isFunctionLike$1(child)) return false;
16663
17428
  if (isNodeOfType(child, "ReturnStatement")) returns.push(child.argument);
16664
17429
  });
16665
17430
  return returns;
@@ -16684,7 +17449,7 @@ const functionBodyReferencesGetParameter = (fn, getParameterName) => {
16684
17449
  let found = false;
16685
17450
  walkAst(body, (child) => {
16686
17451
  if (found) return false;
16687
- if (isFunctionLike$2(child) && child !== fn) return false;
17452
+ if (isFunctionLike$1(child) && child !== fn) return false;
16688
17453
  if (!isNodeOfType(child, "CallExpression")) return;
16689
17454
  if (!isNodeOfType(child.callee, "Identifier")) return;
16690
17455
  if (child.callee.name === getParameterName) {
@@ -16845,7 +17610,7 @@ const jotaiSelectAtomInRenderBody = defineRule({
16845
17610
  if (isBindingUsedAsHandler(nearestFunctionLike)) return;
16846
17611
  let outerCursor = nearestFunctionLike;
16847
17612
  while (outerCursor) {
16848
- if (isFunctionLike$2(outerCursor) && containingFunctionIsComponentOrHook(outerCursor)) {
17613
+ if (isFunctionLike$1(outerCursor) && containingFunctionIsComponentOrHook(outerCursor)) {
16849
17614
  context.report({
16850
17615
  node,
16851
17616
  message: "`selectAtom(...)` runs in a component or hook without `useMemo`, so every render makes a new atom & re-subscribes forever, freezing the page for your users. Lift it to module scope, or wrap it in `useMemo(() => selectAtom(...), [deps])`."
@@ -17181,7 +17946,7 @@ const findEnclosingPerIterationBody = (node) => {
17181
17946
  let current = node.parent;
17182
17947
  while (current) {
17183
17948
  if (isNodeOfType(current, "ForStatement") || isNodeOfType(current, "ForInStatement") || isNodeOfType(current, "ForOfStatement") || isNodeOfType(current, "WhileStatement") || isNodeOfType(current, "DoWhileStatement")) return current.body ?? null;
17184
- if (isFunctionLike$2(current)) {
17949
+ if (isFunctionLike$1(current)) {
17185
17950
  if (isIteratorCallback$1(current)) return current.body ?? null;
17186
17951
  return null;
17187
17952
  }
@@ -17222,7 +17987,7 @@ const scanPerIterationLayoutReads = (body) => {
17222
17987
  let hasUsedLayoutRead = false;
17223
17988
  let hasDeliberateForcedReflow = false;
17224
17989
  walkAst(body, (child) => {
17225
- const isNestedFunction = child !== body && isFunctionLike$2(child);
17990
+ const isNestedFunction = child !== body && isFunctionLike$1(child);
17226
17991
  const valueNode = getLayoutReadValueNode(child);
17227
17992
  if (valueNode) {
17228
17993
  if (isDiscardedValue(valueNode)) hasDeliberateForcedReflow = true;
@@ -17347,7 +18112,7 @@ const buildMemberAccessKey = (node) => {
17347
18112
  const isNameShadowedByEnclosingFunctionParameter = (node, name, boundary) => {
17348
18113
  let ancestor = node.parent;
17349
18114
  while (ancestor && ancestor !== boundary) {
17350
- if (isFunctionLike$2(ancestor)) {
18115
+ if (isFunctionLike$1(ancestor)) {
17351
18116
  const parameterNames = /* @__PURE__ */ new Set();
17352
18117
  for (const parameter of ancestor.params ?? []) collectPatternNames(parameter, parameterNames);
17353
18118
  if (parameterNames.has(name)) return true;
@@ -17840,7 +18605,7 @@ const isInsideCacheMemo = (node) => {
17840
18605
  let child = node;
17841
18606
  let cursor = node.parent ?? null;
17842
18607
  while (cursor) {
17843
- if (isFunctionLike$2(cursor)) return false;
18608
+ if (isFunctionLike$1(cursor)) return false;
17844
18609
  if (isNodeOfType(cursor, "AssignmentExpression") && cursor.right === child) {
17845
18610
  if (MEMO_ASSIGNMENT_OPERATORS.has(cursor.operator)) return true;
17846
18611
  if (cursor.operator === "=" && isNodeOfType(cursor.left, "Identifier") && isIdentifierInitializedFromCacheLookup(cursor.left)) return true;
@@ -17859,7 +18624,7 @@ const isDiscardedProbeInsideTry = (node) => {
17859
18624
  if (!isNodeOfType(statement, "ExpressionStatement")) return false;
17860
18625
  let child = statement;
17861
18626
  let cursor = statement.parent ?? null;
17862
- while (cursor && !isFunctionLike$2(cursor)) {
18627
+ while (cursor && !isFunctionLike$1(cursor)) {
17863
18628
  if (isNodeOfType(cursor, "TryStatement") && cursor.block === child) return true;
17864
18629
  child = cursor;
17865
18630
  cursor = cursor.parent ?? null;
@@ -17875,7 +18640,7 @@ const getFunctionName = (functionNode) => {
17875
18640
  };
17876
18641
  const isUncacheableOptionsMergeUtility = (node) => {
17877
18642
  const enclosingFunction = findEnclosingFunction$1(node);
17878
- if (!enclosingFunction || !isFunctionLike$2(enclosingFunction)) return false;
18643
+ if (!enclosingFunction || !isFunctionLike$1(enclosingFunction)) return false;
17879
18644
  const functionName = getFunctionName(enclosingFunction);
17880
18645
  if (!functionName || isComponentOrHookName(functionName)) return false;
17881
18646
  const parameterNames = /* @__PURE__ */ new Set();
@@ -17903,7 +18668,7 @@ const jsHoistIntl = defineRule({
17903
18668
  let cursor = node.parent ?? null;
17904
18669
  let inFunctionBody = false;
17905
18670
  while (cursor) {
17906
- if (isFunctionLike$2(cursor)) {
18671
+ if (isFunctionLike$1(cursor)) {
17907
18672
  inFunctionBody = true;
17908
18673
  const fnParent = cursor.parent;
17909
18674
  if (fnParent && isNodeOfType(fnParent, "CallExpression") && fnParent.arguments?.[0] === cursor) {
@@ -18250,7 +19015,7 @@ const getLoopBoundNames = (loop) => {
18250
19015
  if (isNodeOfType(child, "Identifier")) names.add(child.name);
18251
19016
  });
18252
19017
  walkAst(loop, (child) => {
18253
- if (child !== loop && isFunctionLike$2(child)) return false;
19018
+ if (child !== loop && isFunctionLike$1(child)) return false;
18254
19019
  if (isNodeOfType(child, "VariableDeclarator") && child.id) {
18255
19020
  walkAst(child.id, (idNode) => {
18256
19021
  if (isNodeOfType(idNode, "Identifier")) names.add(idNode.name);
@@ -18500,7 +19265,7 @@ const hasDominatingLengthGuard = (callNode, receiverArray, indexedArray) => {
18500
19265
  let child = callNode;
18501
19266
  let ancestor = callNode.parent;
18502
19267
  while (ancestor) {
18503
- if (isFunctionLike$2(ancestor)) {
19268
+ if (isFunctionLike$1(ancestor)) {
18504
19269
  const parameterNames = /* @__PURE__ */ new Set();
18505
19270
  for (const parameter of ancestor.params ?? []) collectPatternNames(parameter, parameterNames);
18506
19271
  if (comparedRootNames.some((rootName) => parameterNames.has(rootName))) return false;
@@ -18583,7 +19348,7 @@ const findConstInitializer = (identifierName, fromNode) => {
18583
19348
  let child = fromNode;
18584
19349
  let ancestor = fromNode.parent;
18585
19350
  while (ancestor) {
18586
- if (isFunctionLike$2(ancestor)) {
19351
+ if (isFunctionLike$1(ancestor)) {
18587
19352
  const parameterNames = /* @__PURE__ */ new Set();
18588
19353
  for (const parameter of ancestor.params ?? []) collectPatternNames(parameter, parameterNames);
18589
19354
  if (parameterNames.has(identifierName)) return null;
@@ -18619,7 +19384,7 @@ const PREFIX_INTENT_NAME_PATTERN = /prefix|startswith/i;
18619
19384
  const isInsidePrefixNamedFunction = (node) => {
18620
19385
  let ancestor = node.parent;
18621
19386
  while (ancestor) {
18622
- if (isFunctionLike$2(ancestor)) {
19387
+ if (isFunctionLike$1(ancestor)) {
18623
19388
  if (isNodeOfType(ancestor, "FunctionDeclaration") && isNodeOfType(ancestor.id, "Identifier") && PREFIX_INTENT_NAME_PATTERN.test(ancestor.id.name)) return true;
18624
19389
  const holder = ancestor.parent;
18625
19390
  if (holder && isNodeOfType(holder, "VariableDeclarator") && isNodeOfType(holder.id, "Identifier") && PREFIX_INTENT_NAME_PATTERN.test(holder.id.name)) return true;
@@ -19348,7 +20113,7 @@ const hasWriteBeforeQuery = (body, identifier) => {
19348
20113
  if (hasEarlierWrite) return false;
19349
20114
  const childStart = getRangeStart(child);
19350
20115
  if (childStart !== null && childStart >= queryStart) return false;
19351
- if (child !== body && isFunctionLike$2(child)) return false;
20116
+ if (child !== body && isFunctionLike$1(child)) return false;
19352
20117
  const writeTarget = isNodeOfType(child, "AssignmentExpression") ? child.left : isNodeOfType(child, "UpdateExpression") ? child.argument : isNodeOfType(child, "ForInStatement") || isNodeOfType(child, "ForOfStatement") ? child.left : null;
19353
20118
  if (writeTarget && writeTargetContainsIdentifierBinding(writeTarget, identifier)) {
19354
20119
  hasEarlierWrite = true;
@@ -19361,7 +20126,7 @@ const isProtectedByRelationalLoopGuard = (identifier) => {
19361
20126
  let descendant = identifier;
19362
20127
  let ancestor = identifier.parent;
19363
20128
  while (ancestor) {
19364
- if (isFunctionLike$2(ancestor)) return false;
20129
+ if (isFunctionLike$1(ancestor)) return false;
19365
20130
  if ((isNodeOfType(ancestor, "ForStatement") || isNodeOfType(ancestor, "WhileStatement")) && ancestor.body === descendant && testProvesIdentifierIsNotNaN(ancestor.test, identifier)) return !hasWriteBeforeQuery(ancestor.body, identifier);
19366
20131
  descendant = ancestor;
19367
20132
  ancestor = ancestor.parent;
@@ -19405,7 +20170,7 @@ const isKnownUserlandMembershipReceiver = (receiver, methodName) => {
19405
20170
  const findTypeParameter = (reference, typeName) => {
19406
20171
  let ancestor = reference.parent;
19407
20172
  while (ancestor) {
19408
- if (isFunctionLike$2(ancestor) || isNodeOfType(ancestor, "ClassDeclaration") || isNodeOfType(ancestor, "ClassExpression")) {
20173
+ if (isFunctionLike$1(ancestor) || isNodeOfType(ancestor, "ClassDeclaration") || isNodeOfType(ancestor, "ClassExpression")) {
19409
20174
  const matchingTypeParameter = ancestor.typeParameters?.params?.find((typeParameter) => isNodeOfType(typeParameter, "TSTypeParameter") && isNodeOfType(typeParameter.name, "Identifier") && typeParameter.name.name === typeName);
19410
20175
  if (matchingTypeParameter && isNodeOfType(matchingTypeParameter, "TSTypeParameter")) return matchingTypeParameter;
19411
20176
  }
@@ -19756,7 +20521,7 @@ const hasSizeReadOnSameExpression = (spreadArgument) => {
19756
20521
  let ancestor = spreadArgument.parent;
19757
20522
  while (ancestor) {
19758
20523
  scopeOwner = ancestor;
19759
- if (isFunctionLike$2(ancestor)) break;
20524
+ if (isFunctionLike$1(ancestor)) break;
19760
20525
  ancestor = ancestor.parent ?? null;
19761
20526
  }
19762
20527
  let didFindSizeRead = false;
@@ -21208,7 +21973,7 @@ const unwrapReactHocFunction = (node, scopes) => resolveReactHocFunction(node, s
21208
21973
  //#endregion
21209
21974
  //#region src/plugin/utils/build-same-file-jsx-slot-prop-registry.ts
21210
21975
  const REACT_SLOT_TYPE_NAMES = new Set(["ReactNode", "ReactElement"]);
21211
- const unwrapTopLevelDeclaration = (statement) => {
21976
+ const unwrapTopLevelDeclaration$1 = (statement) => {
21212
21977
  if (isNodeOfType(statement, "ExportNamedDeclaration")) return statement.declaration;
21213
21978
  if (isNodeOfType(statement, "ExportDefaultDeclaration")) return statement.declaration;
21214
21979
  return statement;
@@ -21245,7 +22010,7 @@ const buildReactSlotTypeEnvironment = (program) => {
21245
22010
  }
21246
22011
  continue;
21247
22012
  }
21248
- const declaration = unwrapTopLevelDeclaration(statement);
22013
+ const declaration = unwrapTopLevelDeclaration$1(statement);
21249
22014
  if (!declaration) continue;
21250
22015
  if ((isNodeOfType(declaration, "TSInterfaceDeclaration") || isNodeOfType(declaration, "TSTypeAliasDeclaration")) && isNodeOfType(declaration.id, "Identifier")) sameFileTypeDeclarations.set(declaration.id.name, declaration);
21251
22016
  if (isNodeOfType(declaration, "TSModuleDeclaration") && isNodeOfType(declaration.id, "Identifier") && declaration.id.name === "JSX") hasLocalJsxNamespace = true;
@@ -21337,7 +22102,7 @@ const buildSameFileJsxSlotPropRegistry = (program, memoRegistry, scopes) => {
21337
22102
  if (!isNodeOfType(program, "Program")) return registry;
21338
22103
  const environment = buildReactSlotTypeEnvironment(program);
21339
22104
  for (const statement of program.body) {
21340
- const declaration = unwrapTopLevelDeclaration(statement);
22105
+ const declaration = unwrapTopLevelDeclaration$1(statement);
21341
22106
  if (!declaration || !isNodeOfType(declaration, "VariableDeclaration")) continue;
21342
22107
  for (const declarator of declaration.declarations) {
21343
22108
  if (!isNodeOfType(declarator.id, "Identifier") || memoRegistry.get(declarator.id.name) !== "memoised" || !declarator.init) continue;
@@ -24864,7 +25629,7 @@ const containsFetchCall = (node, options) => {
24864
25629
  let didFindFetchCall = false;
24865
25630
  walkAst(node, (child) => {
24866
25631
  if (didFindFetchCall) return false;
24867
- if (effectInvokedFunctions && child !== node && isFunctionLike$2(child) && !effectInvokedFunctions.has(child)) return false;
25632
+ if (effectInvokedFunctions && child !== node && isFunctionLike$1(child) && !effectInvokedFunctions.has(child)) return false;
24868
25633
  if (isFetchCall$1(child)) {
24869
25634
  didFindFetchCall = true;
24870
25635
  return false;
@@ -24962,7 +25727,7 @@ const isInsidePollingLoop = (navigationNode, effectCallback, timerScheduledNames
24962
25727
  if (timerScheduledNames.size === 0) return false;
24963
25728
  let cursor = navigationNode.parent;
24964
25729
  while (cursor && cursor !== effectCallback) {
24965
- if (isFunctionLike$2(cursor)) {
25730
+ if (isFunctionLike$1(cursor)) {
24966
25731
  const bindingName = getFunctionBindingName(cursor);
24967
25732
  if (bindingName && timerScheduledNames.has(bindingName)) return true;
24968
25733
  }
@@ -25002,7 +25767,7 @@ const nextjsNoClientSideRedirect = defineRule({
25002
25767
  const effectInvokedFunctions = collectEffectInvokedFunctions(callback);
25003
25768
  const timerScheduledNames = collectTimerScheduledFunctionNames(callback);
25004
25769
  walkAst(callback, (child) => {
25005
- if (child !== callback && isFunctionLike$2(child) && !effectInvokedFunctions.has(child)) return false;
25770
+ if (child !== callback && isFunctionLike$1(child) && !effectInvokedFunctions.has(child)) return false;
25006
25771
  const navigationDescription = describeClientSideNavigation(child);
25007
25772
  if (navigationDescription) {
25008
25773
  if (isNodeOfType(child, "CallExpression")) {
@@ -25392,7 +26157,7 @@ const catchClauseRethrowsCaught = (handler) => {
25392
26157
  let didRethrow = false;
25393
26158
  walkAst(handler.body, (child) => {
25394
26159
  if (didRethrow) return false;
25395
- if (child !== handler.body && isFunctionLike$2(child)) return false;
26160
+ if (child !== handler.body && isFunctionLike$1(child)) return false;
25396
26161
  if (isNodeOfType(child, "ThrowStatement") && isNodeOfType(child.argument, "Identifier") && child.argument.name === caughtBindingName && doesThrowEscapeCatchClause(child, handler)) {
25397
26162
  didRethrow = true;
25398
26163
  return false;
@@ -25417,7 +26182,7 @@ const findGuardingTryStatement = (node) => {
25417
26182
  let child = node;
25418
26183
  let ancestor = node.parent;
25419
26184
  while (ancestor) {
25420
- if (isFunctionLike$2(ancestor) && !isImmediatelyInvokedFunction(ancestor)) return null;
26185
+ if (isFunctionLike$1(ancestor) && !isImmediatelyInvokedFunction(ancestor)) return null;
25421
26186
  if (isNodeOfType(ancestor, "TryStatement") && ancestor.block === child && ancestor.handler && !catchClauseRethrowsCaught(ancestor.handler)) return ancestor;
25422
26187
  child = ancestor;
25423
26188
  ancestor = ancestor.parent ?? null;
@@ -25716,7 +26481,7 @@ const collectChainedGetHandlerBodies = (initNode) => {
25716
26481
  };
25717
26482
  const resolveBodiesFromExpression = (expression, resolveBinding, remainingDepth) => {
25718
26483
  if (remainingDepth <= 0) return [];
25719
- if (isFunctionLike$2(expression)) return expression.body ? [expression.body] : [];
26484
+ if (isFunctionLike$1(expression)) return expression.body ? [expression.body] : [];
25720
26485
  if (isNodeOfType(expression, "CallExpression")) {
25721
26486
  for (const callArgument of expression.arguments ?? []) {
25722
26487
  if (isNodeOfType(callArgument, "ArrowFunctionExpression") || isNodeOfType(callArgument, "FunctionExpression")) {
@@ -25762,7 +26527,7 @@ const collectCalledSameFileHelperBodies = (handlerBody, resolveBinding) => {
25762
26527
  if (visitedHelperNames.has(helperName)) return;
25763
26528
  visitedHelperNames.add(helperName);
25764
26529
  const helperBinding = resolveBinding(helperName);
25765
- if (!isFunctionLike$2(helperBinding) || !helperBinding.body) return;
26530
+ if (!isFunctionLike$1(helperBinding) || !helperBinding.body) return;
25766
26531
  if (helperBinding.body === handlerBody) return;
25767
26532
  helperBodies.push(helperBinding.body);
25768
26533
  });
@@ -26166,7 +26931,7 @@ const HOOK_NAME_PATTERN$2 = /^use[A-Z0-9]/;
26166
26931
  const isInsideCallbackArgumentOf = (identifier, initializer) => {
26167
26932
  if (!isNodeOfType(initializer, "CallExpression") && !isNodeOfType(initializer, "NewExpression")) return false;
26168
26933
  if (isNodeOfType(initializer, "CallExpression") && isNodeOfType(initializer.callee, "Identifier") && HOOK_NAME_PATTERN$2.test(initializer.callee.name)) return false;
26169
- const callbackArguments = (initializer.arguments ?? []).filter((argument) => isFunctionLike$2(argument));
26934
+ const callbackArguments = (initializer.arguments ?? []).filter((argument) => isFunctionLike$1(argument));
26170
26935
  if (callbackArguments.length === 0) return false;
26171
26936
  let node = identifier;
26172
26937
  while (node && node !== initializer) {
@@ -26302,10 +27067,10 @@ const resolveToFunction = (ref) => {
26302
27067
  if (!definition || hasParameterDefinition(ref)) return null;
26303
27068
  const definitionNode = definition.node;
26304
27069
  if (!definitionNode) return null;
26305
- if (isFunctionLike$2(definitionNode)) return definitionNode;
27070
+ if (isFunctionLike$1(definitionNode)) return definitionNode;
26306
27071
  if (isNodeOfType(definitionNode, "VariableDeclarator")) {
26307
27072
  const initializer = unwrapUseCallback(definitionNode.init);
26308
- if (isFunctionLike$2(initializer)) return initializer;
27073
+ if (isFunctionLike$1(initializer)) return initializer;
26309
27074
  }
26310
27075
  return null;
26311
27076
  };
@@ -26397,7 +27162,7 @@ const isDeferredCallbackFunction = (analysis, fn) => {
26397
27162
  const isInsideDeferredCallback$1 = (analysis, node, boundary) => {
26398
27163
  let current = parentOf(node);
26399
27164
  while (current && current !== boundary) {
26400
- if (isFunctionLike$2(current) && isDeferredCallbackFunction(analysis, current)) return true;
27165
+ if (isFunctionLike$1(current) && isDeferredCallbackFunction(analysis, current)) return true;
26401
27166
  current = parentOf(current);
26402
27167
  }
26403
27168
  return false;
@@ -26637,9 +27402,9 @@ const isProp = (analysis, ref) => Boolean(ref.resolved?.defs.some((def) => {
26637
27402
  return isReactFunctionalComponent(declaringNode) && !isReactFunctionalHOC(analysis, declaringNode) || isCustomHook(declaringNode);
26638
27403
  }));
26639
27404
  const isWholePropsParameterBinding = (bindingNode) => {
26640
- if (isFunctionLike$2(bindingNode.parent)) return true;
27405
+ if (isFunctionLike$1(bindingNode.parent)) return true;
26641
27406
  let declaringFunction = bindingNode.parent;
26642
- while (declaringFunction && !isFunctionLike$2(declaringFunction)) declaringFunction = declaringFunction.parent;
27407
+ while (declaringFunction && !isFunctionLike$1(declaringFunction)) declaringFunction = declaringFunction.parent;
26643
27408
  return Boolean(declaringFunction && resolveFirstArgumentBinding(declaringFunction.params?.[0]) === bindingNode);
26644
27409
  };
26645
27410
  const isWholePropsObjectReference = (analysis, ref) => isProp(analysis, ref) && Boolean(ref.resolved?.defs.some((def) => {
@@ -26706,7 +27471,7 @@ const getUseStateDecl = (analysis, ref) => {
26706
27471
  return node ?? null;
26707
27472
  };
26708
27473
  const isCleanupReturnArgument = (analysis, node) => {
26709
- if (isFunctionLike$2(node)) return true;
27474
+ if (isFunctionLike$1(node)) return true;
26710
27475
  if (isNodeOfType(node, "MemberExpression")) return true;
26711
27476
  if (isNodeOfType(node, "Identifier")) {
26712
27477
  const ref = getRef(analysis, node);
@@ -26719,7 +27484,7 @@ const hasCleanupReturn = (analysis, node, visited = /* @__PURE__ */ new WeakSet(
26719
27484
  if (visited.has(node)) return false;
26720
27485
  visited.add(node);
26721
27486
  if (isNodeOfType(node, "ReturnStatement") && node.argument != null) return isCleanupReturnArgument(analysis, node.argument);
26722
- if (!isNodeOfType(node, "BlockStatement") && isFunctionLike$2(node)) return false;
27487
+ if (!isNodeOfType(node, "BlockStatement") && isFunctionLike$1(node)) return false;
26723
27488
  const record = node;
26724
27489
  const childKeys = getAstChildKeys(node);
26725
27490
  for (let keyIndex = 0; keyIndex < childKeys.length; keyIndex += 1) {
@@ -26734,7 +27499,7 @@ const hasCleanupReturn = (analysis, node, visited = /* @__PURE__ */ new WeakSet(
26734
27499
  };
26735
27500
  const hasCleanup = (analysis, node) => {
26736
27501
  const fn = getEffectFn(analysis, node);
26737
- if (!isFunctionLike$2(fn)) return false;
27502
+ if (!isFunctionLike$1(fn)) return false;
26738
27503
  if (!isNodeOfType(fn.body, "BlockStatement")) return isCleanupReturnArgument(analysis, fn.body);
26739
27504
  return hasCleanupReturn(analysis, fn.body);
26740
27505
  };
@@ -26774,9 +27539,9 @@ const getOwnScopeBoundNames = (functionNode) => {
26774
27539
  const cached = ownScopeBoundNamesCache.get(functionNode);
26775
27540
  if (cached) return cached;
26776
27541
  const boundNames = /* @__PURE__ */ new Set();
26777
- if (isFunctionLike$2(functionNode)) for (const param of functionNode.params ?? []) collectPatternNames(param, boundNames);
27542
+ if (isFunctionLike$1(functionNode)) for (const param of functionNode.params ?? []) collectPatternNames(param, boundNames);
26778
27543
  walkAst(functionNode, (child) => {
26779
- if (child !== functionNode && isFunctionLike$2(child)) return false;
27544
+ if (child !== functionNode && isFunctionLike$1(child)) return false;
26780
27545
  if (isNodeOfType(child, "VariableDeclarator")) collectPatternNames(child.id, boundNames);
26781
27546
  });
26782
27547
  ownScopeBoundNamesCache.set(functionNode, boundNames);
@@ -26794,7 +27559,7 @@ const referencesIdentifierNamed = (root, identifierName) => {
26794
27559
  let isReferenced = false;
26795
27560
  walkAst(root, (child) => {
26796
27561
  if (isReferenced) return false;
26797
- if (child !== root && isFunctionLike$2(child) && declaresBindingNamed(child, identifierName)) return false;
27562
+ if (child !== root && isFunctionLike$1(child) && declaresBindingNamed(child, identifierName)) return false;
26798
27563
  if (isNodeOfType(child, "Identifier") && child.name === identifierName && !isPropertyNamePosition(child)) {
26799
27564
  isReferenced = true;
26800
27565
  return false;
@@ -26806,7 +27571,7 @@ const isSetterWiredToJsxHandler = (componentFunction, setterName) => {
26806
27571
  let isWired = false;
26807
27572
  walkAst(componentFunction, (child) => {
26808
27573
  if (isWired) return false;
26809
- if (child !== componentFunction && isFunctionLike$2(child) && declaresBindingNamed(child, setterName)) return false;
27574
+ if (child !== componentFunction && isFunctionLike$1(child) && declaresBindingNamed(child, setterName)) return false;
26810
27575
  if (!isNodeOfType(child, "JSXAttribute") || !child.value) return;
26811
27576
  const attributeName = getJsxAttributeName(child.name);
26812
27577
  if (!attributeName || !isEventHandlerName(attributeName)) return;
@@ -26853,7 +27618,7 @@ const isIndependentWriterIdentifier = (componentFunction, identifier, includeDef
26853
27618
  }
26854
27619
  if (isEventHandlerPropertyKey(cursor)) return true;
26855
27620
  if (includeDeferredWriters && isDeferredCallbackArgumentOf(cursor, previous)) return true;
26856
- if (isFunctionLike$2(cursor)) {
27621
+ if (isFunctionLike$1(cursor)) {
26857
27622
  outermostFunctionBelowComponent = cursor;
26858
27623
  if (includeDeferredWriters && cursor.async === true) return true;
26859
27624
  }
@@ -27048,7 +27813,7 @@ const getCallCalleeName$1 = (callExpression) => {
27048
27813
  if (isNodeOfType(callee, "Identifier")) return callee.name;
27049
27814
  return getStaticMemberName$1(callee);
27050
27815
  };
27051
- const getFunctionParameters = (functionNode) => isFunctionLike$2(functionNode) ? functionNode.params ?? [] : [];
27816
+ const getFunctionParameters = (functionNode) => isFunctionLike$1(functionNode) ? functionNode.params ?? [] : [];
27052
27817
  const getIdentifierBindingIdentity = (analysis, identifier) => {
27053
27818
  if (!isNodeOfType(identifier, "Identifier")) return null;
27054
27819
  return getRef(analysis, identifier)?.resolved ?? null;
@@ -27065,7 +27830,7 @@ const isAsyncOrGeneratorFunction = (functionNode) => Boolean(functionNode.async
27065
27830
  const isModuleFunction = (functionNode) => {
27066
27831
  let ancestor = functionNode.parent;
27067
27832
  while (ancestor) {
27068
- if (isFunctionLike$2(ancestor)) return false;
27833
+ if (isFunctionLike$1(ancestor)) return false;
27069
27834
  if (isNodeOfType(ancestor, "Program")) return true;
27070
27835
  ancestor = ancestor.parent;
27071
27836
  }
@@ -27138,7 +27903,7 @@ const localUseEventPreservesCallback = (analysis, callee) => {
27138
27903
  const callbackBinding = getParameterBindingIdentity(analysis, implementation, callbackParameter);
27139
27904
  const callbackRefDeclarators = [];
27140
27905
  walkAst(implementation, (child) => {
27141
- if (child !== implementation && isFunctionLike$2(child)) return false;
27906
+ if (child !== implementation && isFunctionLike$1(child)) return false;
27142
27907
  if (!isNodeOfType(child, "VariableDeclarator")) return;
27143
27908
  if (!isNodeOfType(child.id, "Identifier")) return;
27144
27909
  if (!isNodeOfType(child.init, "CallExpression")) return;
@@ -27154,11 +27919,11 @@ const localUseEventPreservesCallback = (analysis, callee) => {
27154
27919
  const returnedCalleeName = getCallCalleeName$1(returnedCall);
27155
27920
  if (returnedCalleeName !== "useCallback" && returnedCalleeName !== "useEffectEvent") return false;
27156
27921
  const stableCallback = returnedCall.arguments?.[0];
27157
- if (!stableCallback || !isFunctionLike$2(stableCallback)) return false;
27922
+ if (!stableCallback || !isFunctionLike$1(stableCallback)) return false;
27158
27923
  let forwardsCallback = false;
27159
27924
  walkAst(stableCallback, (child) => {
27160
27925
  if (forwardsCallback) return false;
27161
- if (child !== stableCallback && isFunctionLike$2(child)) return false;
27926
+ if (child !== stableCallback && isFunctionLike$1(child)) return false;
27162
27927
  if (!isNodeOfType(child, "CallExpression")) return;
27163
27928
  const forwardedCallee = stripParenExpression(child.callee);
27164
27929
  if (!isNodeOfType(forwardedCallee, "MemberExpression")) return;
@@ -27178,7 +27943,7 @@ const localUseEventPreservesCallback = (analysis, callee) => {
27178
27943
  };
27179
27944
  const resolveWrappedCallable = (analysis, node) => {
27180
27945
  const candidate = stripParenExpression(node);
27181
- if (isFunctionLike$2(candidate)) return candidate;
27946
+ if (isFunctionLike$1(candidate)) return candidate;
27182
27947
  if (isNodeOfType(candidate, "Identifier")) {
27183
27948
  const reference = getRef(analysis, candidate);
27184
27949
  if (!reference) return null;
@@ -27191,7 +27956,7 @@ const resolveWrappedCallable = (analysis, node) => {
27191
27956
  if (!initializer || !isNodeOfType(initializer, "CallExpression")) return null;
27192
27957
  if (!isReactUseEffectEventCallee(analysis, initializer.callee) && !localUseEventPreservesCallback(analysis, initializer.callee)) return null;
27193
27958
  const callback = initializer.arguments?.[0];
27194
- return callback && isFunctionLike$2(callback) ? callback : null;
27959
+ return callback && isFunctionLike$1(callback) ? callback : null;
27195
27960
  }
27196
27961
  if (!isNodeOfType(candidate, "MemberExpression")) return null;
27197
27962
  if (getStaticMemberName$1(candidate) !== "current") return null;
@@ -27202,7 +27967,7 @@ const resolveWrappedCallable = (analysis, node) => {
27202
27967
  if (!isNodeOfType(declarator.init, "CallExpression")) return null;
27203
27968
  if (getCallCalleeName$1(declarator.init) !== "useRef") return null;
27204
27969
  const initializer = declarator.init.arguments?.[0];
27205
- if (!initializer || !isFunctionLike$2(initializer)) return null;
27970
+ if (!initializer || !isFunctionLike$1(initializer)) return null;
27206
27971
  return Boolean(reference?.resolved?.references.some((candidateReference) => {
27207
27972
  const member = candidateReference.identifier.parent;
27208
27973
  const assignment = member?.parent;
@@ -27213,7 +27978,7 @@ const functionInvokesItself = (analysis, functionNode) => {
27213
27978
  let invokesItself = false;
27214
27979
  walkAst(functionNode, (child) => {
27215
27980
  if (invokesItself) return false;
27216
- if (child !== functionNode && isFunctionLike$2(child)) return false;
27981
+ if (child !== functionNode && isFunctionLike$1(child)) return false;
27217
27982
  if (!isNodeOfType(child, "CallExpression")) return;
27218
27983
  if (resolveWrappedCallable(analysis, child.callee) === functionNode) {
27219
27984
  invokesItself = true;
@@ -27229,7 +27994,7 @@ const collectIntroducedBindings = (analysis, functionNode) => {
27229
27994
  };
27230
27995
  const collectBoundedEffectExecutionFrames = (analysis, effectNode, currentFilename) => {
27231
27996
  const effectFunction = getEffectFn(analysis, effectNode);
27232
- if (!effectFunction || !isFunctionLike$2(effectFunction) || effectFunction.async === true) return [];
27997
+ if (!effectFunction || !isFunctionLike$1(effectFunction) || effectFunction.async === true) return [];
27233
27998
  const invokedFunctionEvidence = collectEffectInvokedFunctions(effectFunction);
27234
27999
  const rootFrame = {
27235
28000
  functionNode: effectFunction,
@@ -27241,7 +28006,7 @@ const collectBoundedEffectExecutionFrames = (analysis, effectNode, currentFilena
27241
28006
  };
27242
28007
  const frames = [rootFrame];
27243
28008
  walkAst(effectFunction, (child) => {
27244
- if (child !== effectFunction && isFunctionLike$2(child)) return false;
28009
+ if (child !== effectFunction && isFunctionLike$1(child)) return false;
27245
28010
  if (!isNodeOfType(child, "CallExpression")) return;
27246
28011
  const callee = stripParenExpression(child.callee);
27247
28012
  const calleeName = getCallCalleeName$1(child);
@@ -27262,7 +28027,7 @@ const collectBoundedEffectExecutionFrames = (analysis, effectNode, currentFilena
27262
28027
  currentFilename
27263
28028
  });
27264
28029
  };
27265
- if (isFunctionLike$2(callee)) {
28030
+ if (isFunctionLike$1(callee)) {
27266
28031
  enqueueFrame(callee, child.arguments ?? [], false, /* @__PURE__ */ new Set());
27267
28032
  return;
27268
28033
  }
@@ -27299,11 +28064,11 @@ const mergeEvidence = (target, source) => {
27299
28064
  target.readsExternalValue ||= source.readsExternalValue;
27300
28065
  };
27301
28066
  const getReturnedExpressions = (functionNode) => {
27302
- if (!isFunctionLike$2(functionNode)) return [];
28067
+ if (!isFunctionLike$1(functionNode)) return [];
27303
28068
  if (!isNodeOfType(functionNode.body, "BlockStatement")) return [functionNode.body];
27304
28069
  const returnedExpressions = [];
27305
28070
  walkAst(functionNode.body, (child) => {
27306
- if (child !== functionNode.body && isFunctionLike$2(child)) return false;
28071
+ if (child !== functionNode.body && isFunctionLike$1(child)) return false;
27307
28072
  if (isNodeOfType(child, "ReturnStatement") && child.argument) returnedExpressions.push(child.argument);
27308
28073
  });
27309
28074
  return returnedExpressions;
@@ -27388,7 +28153,7 @@ const analyzeHelperExpression = (expression, environment, usedParameterIndices)
27388
28153
  if (!analyzeHelperExpression(node.object, environment, usedParameterIndices)) return false;
27389
28154
  return !node.computed || analyzeHelperExpression(node.property, environment, usedParameterIndices);
27390
28155
  }
27391
- if (isFunctionLike$2(node)) {
28156
+ if (isFunctionLike$1(node)) {
27392
28157
  if (isAsyncOrGeneratorFunction(node)) return false;
27393
28158
  const callbackParameterIndices = new Map(environment.parameterIndices);
27394
28159
  for (const parameter of getFunctionParameters(node)) {
@@ -27426,7 +28191,7 @@ const analyzeHelperExpression = (expression, environment, usedParameterIndices)
27426
28191
  };
27427
28192
  const helperSummaryCache = /* @__PURE__ */ new WeakMap();
27428
28193
  const summarizeHelperReturn = (functionNode) => {
27429
- if (!isFunctionLike$2(functionNode) || !isModuleFunction(functionNode)) return null;
28194
+ if (!isFunctionLike$1(functionNode) || !isModuleFunction(functionNode)) return null;
27430
28195
  if (helperSummaryCache.has(functionNode)) return helperSummaryCache.get(functionNode) ?? null;
27431
28196
  if (isAsyncOrGeneratorFunction(functionNode)) {
27432
28197
  helperSummaryCache.set(functionNode, null);
@@ -27616,7 +28381,7 @@ const collectValueEvidence = (analysis, expression, frame, remainingCallFrames,
27616
28381
  if (isPureGlobalCall || isPureMemberTransform) {
27617
28382
  if (isPureMemberTransform && isNodeOfType(callee, "MemberExpression")) mergeEvidence(evidence, collectValueEvidence(analysis, callee.object, frame, remainingCallFrames, new Set(visitedBindings)));
27618
28383
  for (const argument of node.arguments ?? []) {
27619
- if (isFunctionLike$2(argument)) continue;
28384
+ if (isFunctionLike$1(argument)) continue;
27620
28385
  mergeEvidence(evidence, collectValueEvidence(analysis, argument, frame, remainingCallFrames, new Set(visitedBindings)));
27621
28386
  }
27622
28387
  return evidence;
@@ -27673,7 +28438,7 @@ const collectValueEvidence = (analysis, expression, frame, remainingCallFrames,
27673
28438
  for (const argument of node.arguments ?? []) mergeEvidence(evidence, collectValueEvidence(analysis, argument, frame, remainingCallFrames, new Set(visitedBindings)));
27674
28439
  return evidence;
27675
28440
  }
27676
- if (isFunctionLike$2(node) || isNodeOfType(node, "AwaitExpression")) {
28441
+ if (isFunctionLike$1(node) || isNodeOfType(node, "AwaitExpression")) {
27677
28442
  evidence.hasUnknownSource = true;
27678
28443
  return evidence;
27679
28444
  }
@@ -27740,7 +28505,7 @@ const matchesStateInitializer = (analysis, callExpression, stateDeclarator) => {
27740
28505
  const collectFrameSetterCalls = (analysis, frame) => {
27741
28506
  const calls = [];
27742
28507
  walkAst(frame.functionNode, (child) => {
27743
- if (child !== frame.functionNode && isFunctionLike$2(child)) return false;
28508
+ if (child !== frame.functionNode && isFunctionLike$1(child)) return false;
27744
28509
  if (!isNodeOfType(child, "CallExpression")) return;
27745
28510
  const setterReference = findStateSetterReference(analysis, child);
27746
28511
  if (setterReference) calls.push({
@@ -27779,7 +28544,7 @@ const collectEffectStateWriteFacts = (analysis, effectNode, currentFilename) =>
27779
28544
  if (!stateDeclarator) continue;
27780
28545
  const remainingValueCallFrames = frame === frames[0] ? 1 : 0;
27781
28546
  let valueEvidence;
27782
- if (isFunctionLike$2(writtenValue)) {
28547
+ if (isFunctionLike$1(writtenValue)) {
27783
28548
  const updaterFrame = {
27784
28549
  functionNode: writtenValue,
27785
28550
  invocation: callExpression,
@@ -28346,13 +29111,13 @@ const hasEmptyDependencyArray = (useMemoCall) => {
28346
29111
  const useMemoReturnsArrayLiteral = (useMemoCall) => {
28347
29112
  if (!isNodeOfType(useMemoCall, "CallExpression")) return false;
28348
29113
  const factory = useMemoCall.arguments?.[0];
28349
- if (!factory || !isFunctionLike$2(factory)) return false;
29114
+ if (!factory || !isFunctionLike$1(factory)) return false;
28350
29115
  const body = factory.body;
28351
29116
  if (!isNodeOfType(body, "BlockStatement")) return isSpreadFreeArrayLiteral(body);
28352
29117
  let didFindReturn = false;
28353
29118
  let allReturnsAreFixedArrays = true;
28354
29119
  walkAst(body, (child) => {
28355
- if (isFunctionLike$2(child)) return false;
29120
+ if (isFunctionLike$1(child)) return false;
28356
29121
  if (isNodeOfType(child, "ReturnStatement")) {
28357
29122
  didFindReturn = true;
28358
29123
  if (!child.argument || !isSpreadFreeArrayLiteral(child.argument)) allReturnsAreFixedArrays = false;
@@ -28495,7 +29260,7 @@ const findEnclosingParameter = (bindingIdentifier) => {
28495
29260
  let current = bindingIdentifier;
28496
29261
  while (current.parent) {
28497
29262
  const parent = current.parent;
28498
- if (isFunctionLike$2(parent)) {
29263
+ if (isFunctionLike$1(parent)) {
28499
29264
  const parameterPosition = (parent.params ?? []).indexOf(current);
28500
29265
  return parameterPosition >= 0 ? {
28501
29266
  functionNode: parent,
@@ -28731,7 +29496,7 @@ const isNumericForLoopCounter = (attributeNode, indexName) => {
28731
29496
  const EMPTY_NAME_SET = /* @__PURE__ */ new Set();
28732
29497
  const findIteratorItemNamesOfBinding = (binding) => {
28733
29498
  const names = /* @__PURE__ */ new Set();
28734
- if (!binding.bindingFunction || !isFunctionLike$2(binding.bindingFunction)) return names;
29499
+ if (!binding.bindingFunction || !isFunctionLike$1(binding.bindingFunction)) return names;
28735
29500
  if (binding.indexParameterPosition === null || binding.indexParameterPosition < 1) return names;
28736
29501
  const firstParameter = (binding.bindingFunction.params ?? [])[0];
28737
29502
  if (firstParameter) collectPatternNames(firstParameter, names);
@@ -28745,7 +29510,7 @@ const collectDerivedRowContentNames = (bindingFunction, itemNames) => {
28745
29510
  walkAst(bindingFunction, (child) => {
28746
29511
  if (budget <= 0) return false;
28747
29512
  budget -= 1;
28748
- if (isFunctionLike$2(child) && child !== bindingFunction) return false;
29513
+ if (isFunctionLike$1(child) && child !== bindingFunction) return false;
28749
29514
  if (isNodeOfType(child, "VariableDeclarator") && isNodeOfType(child.id, "Identifier") && child.init) {
28750
29515
  const rootName = getRootIdentifierName(child.init, { followCallChains: true });
28751
29516
  if (rootName !== null && itemNames.has(rootName)) names.add(child.id.name);
@@ -28777,7 +29542,7 @@ const callbackFiltersRows = (bindingFunction) => {
28777
29542
  let didFindNullReturn = false;
28778
29543
  walkAst(bindingFunction, (child) => {
28779
29544
  if (didFindNullReturn) return false;
28780
- if (isFunctionLike$2(child) && child !== bindingFunction) return false;
29545
+ if (isFunctionLike$1(child) && child !== bindingFunction) return false;
28781
29546
  if (isNodeOfType(child, "ReturnStatement") && child.argument && isNodeOfType(child.argument, "Literal") && child.argument.value === null) {
28782
29547
  didFindNullReturn = true;
28783
29548
  return false;
@@ -28800,7 +29565,7 @@ const hasAriaHiddenAncestor = (attributeNode) => {
28800
29565
  let current = attributeNode.parent;
28801
29566
  while (current) {
28802
29567
  if (isNodeOfType(current, "Program")) return false;
28803
- if (isFunctionLike$2(current)) {
29568
+ if (isFunctionLike$1(current)) {
28804
29569
  const parent = current.parent;
28805
29570
  if (!(isNodeOfType(parent, "CallExpression") && parent.arguments.includes(current))) return false;
28806
29571
  }
@@ -29766,7 +30531,7 @@ const symbolIsLocalComponent = (symbol, context) => {
29766
30531
  const isModuleScopeDeclaration = (declaration) => {
29767
30532
  let current = declaration?.parent;
29768
30533
  while (current) {
29769
- if (isFunctionLike$2(current)) return false;
30534
+ if (isFunctionLike$1(current)) return false;
29770
30535
  current = current.parent ?? null;
29771
30536
  }
29772
30537
  return true;
@@ -29788,12 +30553,12 @@ const declarationBodyContainsHookCall = (symbol) => {
29788
30553
  };
29789
30554
  const declarationTakesMultiplePositionalArguments = (symbol) => {
29790
30555
  const componentFunction = isComponentDeclaration(symbol.declarationNode) ? symbol.declarationNode : symbol.initializer;
29791
- if (!componentFunction || !isFunctionLike$2(componentFunction)) return false;
30556
+ if (!componentFunction || !isFunctionLike$1(componentFunction)) return false;
29792
30557
  return (componentFunction.params?.length ?? 0) >= 2;
29793
30558
  };
29794
30559
  const declarationIsAsyncFunction = (symbol) => {
29795
30560
  const componentFunction = isComponentDeclaration(symbol.declarationNode) ? symbol.declarationNode : symbol.initializer;
29796
- if (!componentFunction || !isFunctionLike$2(componentFunction)) return false;
30561
+ if (!componentFunction || !isFunctionLike$1(componentFunction)) return false;
29797
30562
  return componentFunction.async === true;
29798
30563
  };
29799
30564
  const isReturnedFromUseCallbackAdapter = (callNode) => {
@@ -29898,7 +30663,7 @@ const isSimpleExpression$1 = (analysis, expression, effectFn, visitedDeclarators
29898
30663
  let isSimple = true;
29899
30664
  walkAst(expression, (child) => {
29900
30665
  if (!isSimple) return false;
29901
- if (isFunctionLike$2(child) || isNodeOfType(child, "AwaitExpression") || isNodeOfType(child, "NewExpression")) {
30666
+ if (isFunctionLike$1(child) || isNodeOfType(child, "AwaitExpression") || isNodeOfType(child, "NewExpression")) {
29902
30667
  isSimple = false;
29903
30668
  return false;
29904
30669
  }
@@ -30683,7 +31448,7 @@ const isFunctionAssignedToComponent = (functionNode) => {
30683
31448
  return isNodeOfType(cursor, "ExportDefaultDeclaration");
30684
31449
  };
30685
31450
  const isComponentFunction$1 = (node) => {
30686
- if (!isFunctionLike$2(node)) return false;
31451
+ if (!isFunctionLike$1(node)) return false;
30687
31452
  if (isNodeOfType(node, "FunctionDeclaration")) return !node.id || node.id.name === "default" || isUppercaseName(node.id.name) || isNodeOfType(node.parent, "ExportDefaultDeclaration");
30688
31453
  return isFunctionAssignedToComponent(node);
30689
31454
  };
@@ -30696,7 +31461,7 @@ const extractDestructuredPropNames = (params) => {
30696
31461
  };
30697
31462
  const getInlineFunctionNode = (node) => {
30698
31463
  if (!node) return null;
30699
- if (isFunctionLike$2(node)) return node;
31464
+ if (isFunctionLike$1(node)) return node;
30700
31465
  if (!isNodeOfType(node, "CallExpression")) return null;
30701
31466
  for (const argument of node.arguments ?? []) {
30702
31467
  const inlineFunctionNode = getInlineFunctionNode(argument);
@@ -30707,7 +31472,7 @@ const getInlineFunctionNode = (node) => {
30707
31472
  const getNearestComponentFunction = (node) => {
30708
31473
  let cursor = node.parent ?? null;
30709
31474
  while (cursor) {
30710
- if (isFunctionLike$2(cursor)) return cursor;
31475
+ if (isFunctionLike$1(cursor)) return cursor;
30711
31476
  cursor = cursor.parent ?? null;
30712
31477
  }
30713
31478
  return null;
@@ -30949,7 +31714,7 @@ const getStateInitializer = (stateDeclarator) => {
30949
31714
  return initializer ? initializer : null;
30950
31715
  };
30951
31716
  const collectRenderStateWriteFacts = (analysis, componentBody, currentFilename) => {
30952
- if (!isNodeOfType(componentBody, "BlockStatement") || !componentBody.parent || !isFunctionLike$2(componentBody.parent)) return [];
31717
+ if (!isNodeOfType(componentBody, "BlockStatement") || !componentBody.parent || !isFunctionLike$1(componentBody.parent)) return [];
30953
31718
  const componentFunction = componentBody.parent;
30954
31719
  const facts = [];
30955
31720
  for (const statement of componentBody.body ?? []) {
@@ -30964,7 +31729,7 @@ const collectRenderStateWriteFacts = (analysis, componentBody, currentFilename)
30964
31729
  if (!stateDeclarator || !isGenuineReactHookDeclarator(analysis, stateDeclarator, "useState") || guard.tracker.kind === "state" && stateDeclarator === guard.tracker.declarator) continue;
30965
31730
  const writtenValue = callExpression.arguments?.[0];
30966
31731
  const initializer = getStateInitializer(stateDeclarator);
30967
- if (!writtenValue || !initializer || isFunctionLike$2(writtenValue) || !doesEvidenceMatchSource(collectRenderValueEvidence(analysis, writtenValue, componentFunction, currentFilename), guard.source) || !doesEvidenceMatchSource(collectRenderValueEvidence(analysis, initializer, componentFunction, currentFilename), guard.source)) continue;
31732
+ if (!writtenValue || !initializer || isFunctionLike$1(writtenValue) || !doesEvidenceMatchSource(collectRenderValueEvidence(analysis, writtenValue, componentFunction, currentFilename), guard.source) || !doesEvidenceMatchSource(collectRenderValueEvidence(analysis, initializer, componentFunction, currentFilename), guard.source)) continue;
30968
31733
  facts.push({
30969
31734
  callExpression,
30970
31735
  stateDeclarator
@@ -31104,7 +31869,7 @@ const isComponentScopeValueArgument = (setterCall, componentFunction, argument)
31104
31869
  if (rootName === null) return false;
31105
31870
  let cursor = setterCall.parent ?? null;
31106
31871
  while (cursor && cursor !== componentFunction) {
31107
- if (isFunctionLike$2(cursor)) {
31872
+ if (isFunctionLike$1(cursor)) {
31108
31873
  const nestedParamNames = /* @__PURE__ */ new Set();
31109
31874
  for (const param of cursor.params ?? []) collectPatternNames(param, nestedParamNames);
31110
31875
  if (nestedParamNames.has(rootName)) return false;
@@ -31147,7 +31912,7 @@ const hasSessionDismissProp = (propNames) => {
31147
31912
  const getEnclosingEffectHookCallback = (node, componentFunction) => {
31148
31913
  let cursor = node.parent ?? null;
31149
31914
  while (cursor && cursor !== componentFunction) {
31150
- if (isFunctionLike$2(cursor)) {
31915
+ if (isFunctionLike$1(cursor)) {
31151
31916
  const parent = cursor.parent ?? null;
31152
31917
  if (parent && isNodeOfType(parent, "CallExpression")) {
31153
31918
  const calleeName = getCalleeName$2(parent);
@@ -31228,7 +31993,7 @@ const isHandlerShapedReseed = (setterCall, componentFunction) => {
31228
31993
  let hasNestedFunction = false;
31229
31994
  let cursor = setterCall.parent ?? null;
31230
31995
  while (cursor && cursor !== componentFunction) {
31231
- if (isFunctionLike$2(cursor)) {
31996
+ if (isFunctionLike$1(cursor)) {
31232
31997
  hasNestedFunction = true;
31233
31998
  if (isNonHandlerHookCallback(cursor)) return false;
31234
31999
  }
@@ -31239,7 +32004,7 @@ const isHandlerShapedReseed = (setterCall, componentFunction) => {
31239
32004
  const isInRenderScope = (node, componentFunction) => {
31240
32005
  let cursor = node.parent ?? null;
31241
32006
  while (cursor && cursor !== componentFunction) {
31242
- if (isFunctionLike$2(cursor)) return false;
32007
+ if (isFunctionLike$1(cursor)) return false;
31243
32008
  cursor = cursor.parent ?? null;
31244
32009
  }
31245
32010
  return true;
@@ -31253,10 +32018,10 @@ const getStateValueName = (useStateCall) => {
31253
32018
  return valueElement.name;
31254
32019
  };
31255
32020
  const isHookDrivenFunctionalUpdate = (setterCall, componentFunction, argument) => {
31256
- if (!argument || !isFunctionLike$2(argument)) return false;
32021
+ if (!argument || !isFunctionLike$1(argument)) return false;
31257
32022
  let cursor = setterCall.parent ?? null;
31258
32023
  while (cursor && cursor !== componentFunction) {
31259
- if (isFunctionLike$2(cursor) && isNonHandlerHookCallback(cursor)) return true;
32024
+ if (isFunctionLike$1(cursor) && isNonHandlerHookCallback(cursor)) return true;
31260
32025
  cursor = cursor.parent ?? null;
31261
32026
  }
31262
32027
  return false;
@@ -31378,7 +32143,7 @@ const getNodeStart = (node) => "start" in node && typeof node.start === "number"
31378
32143
  const getEnclosingLifecycleFunction = (setStateCall) => {
31379
32144
  let ancestor = setStateCall.parent;
31380
32145
  while (ancestor) {
31381
- if (isFunctionLike$2(ancestor)) {
32146
+ if (isFunctionLike$1(ancestor)) {
31382
32147
  const parent = ancestor.parent;
31383
32148
  if ((isNodeOfType(parent, "MethodDefinition") || isNodeOfType(parent, "PropertyDefinition") || isNodeOfType(parent, "Property")) && isNodeOfType(parent.key, "Identifier") && LIFECYCLE_NAMES$2.has(parent.key.name)) return ancestor;
31384
32149
  }
@@ -31462,7 +32227,7 @@ const argumentDerivesFromPostMountSource = (setStateCall, lifecycleFunction) =>
31462
32227
  return false;
31463
32228
  };
31464
32229
  const isAfterAwaitInAsyncLifecycle = (setStateCall, lifecycleFunction) => {
31465
- if (!isFunctionLike$2(lifecycleFunction) || lifecycleFunction.async !== true) return false;
32230
+ if (!isFunctionLike$1(lifecycleFunction) || lifecycleFunction.async !== true) return false;
31466
32231
  const callStart = getNodeStart(setStateCall);
31467
32232
  if (callStart < 0) return false;
31468
32233
  let didFindPrecedingAwait = false;
@@ -31906,7 +32671,7 @@ const collectBlockScopedBindings = (node) => {
31906
32671
  const walkComponentRespectingShadows = (node, shadowedStateNames, visit, isComponentBodyRoot = false) => {
31907
32672
  if (!node || typeof node !== "object") return;
31908
32673
  let nextShadowedStateNames = shadowedStateNames;
31909
- const localBindings = isComponentBodyRoot ? null : isFunctionLike$2(node) ? collectFunctionLocalBindings(node) : collectBlockScopedBindings(node);
32674
+ const localBindings = isComponentBodyRoot ? null : isFunctionLike$1(node) ? collectFunctionLocalBindings(node) : collectBlockScopedBindings(node);
31910
32675
  if (localBindings && localBindings.size > 0) {
31911
32676
  const merged = new Set(shadowedStateNames);
31912
32677
  for (const localName of localBindings) merged.add(localName);
@@ -32443,7 +33208,7 @@ const containsReleaseLikeCall = (node, knownCleanupFunctionNames, knownBoundSubs
32443
33208
  let didFindRelease = false;
32444
33209
  walkAst(node, (child) => {
32445
33210
  if (didFindRelease) return false;
32446
- if (child !== node && isFunctionLike$2(child) && !isIteratorCallbackArgument(child)) return false;
33211
+ if (child !== node && isFunctionLike$1(child) && !isIteratorCallbackArgument(child)) return false;
32447
33212
  if (isReleaseLikeCall(child, knownCleanupFunctionNames, knownBoundSubscriptionNames)) {
32448
33213
  didFindRelease = true;
32449
33214
  return false;
@@ -32452,16 +33217,16 @@ const containsReleaseLikeCall = (node, knownCleanupFunctionNames, knownBoundSubs
32452
33217
  return didFindRelease;
32453
33218
  };
32454
33219
  const isCleanupFunctionLike = (node, knownCleanupFunctionNames, knownBoundSubscriptionNames) => {
32455
- if (!isFunctionLike$2(node)) return false;
33220
+ if (!isFunctionLike$1(node)) return false;
32456
33221
  return containsReleaseLikeCall(node.body, knownCleanupFunctionNames, knownBoundSubscriptionNames);
32457
33222
  };
32458
33223
  const isProvablyNoOpCleanupFunction = (node) => {
32459
- if (!isFunctionLike$2(node)) return false;
33224
+ if (!isFunctionLike$1(node)) return false;
32460
33225
  let sawNoOpRemoval = false;
32461
33226
  let sawOtherCall = false;
32462
33227
  walkAst(node.body, (child) => {
32463
33228
  if (sawOtherCall) return false;
32464
- if (isFunctionLike$2(child)) return false;
33229
+ if (isFunctionLike$1(child)) return false;
32465
33230
  const callNode = unwrapChainExpression$2(child);
32466
33231
  if (!isNodeOfType(callNode, "CallExpression")) return;
32467
33232
  const callee = unwrapChainExpression$2(callNode.callee);
@@ -32515,12 +33280,12 @@ const collectSynchronouslyInvokedFunctions = (effectCallback, scopes) => {
32515
33280
  const pendingFunctions = [effectCallback];
32516
33281
  while (pendingFunctions.length > 0) {
32517
33282
  const currentFunction = pendingFunctions.pop();
32518
- if (!currentFunction || !isFunctionLike$2(currentFunction)) continue;
33283
+ if (!currentFunction || !isFunctionLike$1(currentFunction)) continue;
32519
33284
  walkInsideStatementBlocks(currentFunction.body, (child) => {
32520
33285
  if (!isNodeOfType(child, "CallExpression")) return;
32521
33286
  const invokedFunction = resolveExactLocalFunction(child.callee, scopes);
32522
33287
  if (!invokedFunction || analysisFunctions.has(invokedFunction)) return;
32523
- if (isFunctionLike$2(invokedFunction) && invokedFunction.async) return;
33288
+ if (isFunctionLike$1(invokedFunction) && invokedFunction.async) return;
32524
33289
  analysisFunctions.add(invokedFunction);
32525
33290
  pendingFunctions.push(invokedFunction);
32526
33291
  });
@@ -32529,7 +33294,7 @@ const collectSynchronouslyInvokedFunctions = (effectCallback, scopes) => {
32529
33294
  };
32530
33295
  const visitSynchronousFunctionBodies = (analysisFunctions, visitor) => {
32531
33296
  for (const analysisFunction of analysisFunctions) {
32532
- if (!isFunctionLike$2(analysisFunction)) continue;
33297
+ if (!isFunctionLike$1(analysisFunction)) continue;
32533
33298
  walkInsideStatementBlocks(analysisFunction.body, visitor);
32534
33299
  }
32535
33300
  };
@@ -32608,7 +33373,7 @@ const isExternalSyncNode = (node) => {
32608
33373
  return receiverRootName !== null && EXTERNAL_SYNC_HTTP_CLIENT_RECEIVERS.has(receiverRootName);
32609
33374
  };
32610
33375
  const isExternalSyncEffect = (effectCallback, analysisFunctions, setterToStateName) => {
32611
- if (!isFunctionLike$2(effectCallback)) return false;
33376
+ if (!isFunctionLike$1(effectCallback)) return false;
32612
33377
  if (!isNodeOfType(effectCallback.body, "BlockStatement")) {
32613
33378
  if (isFunctionShapedReturn(effectCallback.body, setterToStateName, false)) return true;
32614
33379
  } else for (const statement of effectCallback.body.body ?? []) if (isNodeOfType(statement, "ReturnStatement") && statement.argument && isFunctionShapedReturn(statement.argument, setterToStateName, true)) return true;
@@ -32635,7 +33400,7 @@ const noEffectChain = defineRule({
32635
33400
  const effectInfos = [];
32636
33401
  for (const effectCall of findTopLevelEffectCalls(componentBody)) {
32637
33402
  const callback = getEffectCallback(effectCall, context.scopes);
32638
- if (!callback || !isFunctionLike$2(callback) || callback.async) continue;
33403
+ if (!callback || !isFunctionLike$1(callback) || callback.async) continue;
32639
33404
  const analysisFunctions = collectSynchronouslyInvokedFunctions(callback, context.scopes);
32640
33405
  const writtenStateNames = collectWrittenStateNamesInEffect(analysisFunctions, setterToStateName);
32641
33406
  effectInfos.push({
@@ -33111,6 +33876,10 @@ const noEffectWithFreshDeps = defineRule({
33111
33876
  category: "State & Effects",
33112
33877
  recommendation: "Move the value inside the hook body and depend on its simple inputs instead, or wrap it in useMemo / useCallback so it stays the same between renders.",
33113
33878
  create: (context) => ({ CallExpression(node) {
33879
+ for (const finding of findForwardedFreshHookDependencies(node, context, EFFECT_HOOK_NAMES$1)) context.report({
33880
+ node: finding.reportNode,
33881
+ message: `A dependency inside this custom Hook changes every render because \`${finding.bindingName}\` is a new ${finding.kind} built fresh each time.`
33882
+ });
33114
33883
  if (!isHookCall$2(node, HOOKS_WITH_DEPS)) return;
33115
33884
  const args = node.arguments ?? [];
33116
33885
  if (args.length < 2) return;
@@ -33199,7 +33968,7 @@ const findFunctionDefinitionNode = (functionNode) => {
33199
33968
  let current = functionNode;
33200
33969
  while (current) {
33201
33970
  if (isNodeOfType(current, "VariableDeclarator")) return current;
33202
- if (isNodeOfType(current, "Program") || isFunctionLike$2(current) && current !== functionNode) return null;
33971
+ if (isNodeOfType(current, "Program") || isFunctionLike$1(current) && current !== functionNode) return null;
33203
33972
  current = current.parent;
33204
33973
  }
33205
33974
  return null;
@@ -33219,7 +33988,7 @@ const isFunctionWiredToEventAttribute = (analysis, functionNode) => {
33219
33988
  if (!variable) return false;
33220
33989
  return variable.references.some((reference) => {
33221
33990
  let current = reference.identifier;
33222
- while (current && !isFunctionLike$2(current)) {
33991
+ while (current && !isFunctionLike$1(current)) {
33223
33992
  if (isEventAttribute(current) || isEventProperty(current)) return true;
33224
33993
  current = current.parent;
33225
33994
  }
@@ -33262,7 +34031,7 @@ const isInsideProvenEventHandler = (analysis, node, componentFunction, allowOneC
33262
34031
  if (isInsideInlineEventHandler(node, componentFunction)) return true;
33263
34032
  let current = node.parent;
33264
34033
  while (current && current !== componentFunction) {
33265
- if (isFunctionLike$2(current)) {
34034
+ if (isFunctionLike$1(current)) {
33266
34035
  if (isFunctionWiredToEventAttribute(analysis, current) && !isFunctionUsedOutsideHandlers(analysis, current, componentFunction)) return true;
33267
34036
  return allowOneCallFrame && isFunctionCalledOnlyFromHandlers(analysis, current, componentFunction);
33268
34037
  }
@@ -33275,7 +34044,7 @@ const isSetterWriterUsage = (identifier) => {
33275
34044
  if (!parent) return false;
33276
34045
  if (isNodeOfType(parent, "CallExpression")) return parent.callee === identifier || (parent.arguments ?? []).includes(identifier);
33277
34046
  let current = identifier;
33278
- while (current && !isFunctionLike$2(current)) {
34047
+ while (current && !isFunctionLike$1(current)) {
33279
34048
  if (isEventAttribute(current) || isEventProperty(current)) return true;
33280
34049
  current = current.parent;
33281
34050
  }
@@ -33329,7 +34098,7 @@ const consequentHasTransferableWork = (analysis, consequent) => {
33329
34098
  let hasTransferableWork = false;
33330
34099
  walkAst(consequent, (child) => {
33331
34100
  if (hasTransferableWork) return false;
33332
- if (child !== consequent && isFunctionLike$2(child)) return false;
34101
+ if (child !== consequent && isFunctionLike$1(child)) return false;
33333
34102
  if (!isNodeOfType(child, "CallExpression")) return;
33334
34103
  if (isNodeOfType(child.callee, "Identifier")) {
33335
34104
  const calleeReference = getRef(analysis, child.callee);
@@ -33356,7 +34125,7 @@ const consequentHasAdditionalReactiveGuard = (analysis, consequent, handlerState
33356
34125
  let hasAdditionalGuard = false;
33357
34126
  walkAst(consequent, (child) => {
33358
34127
  if (hasAdditionalGuard) return false;
33359
- if (child !== consequent && isFunctionLike$2(child)) return false;
34128
+ if (child !== consequent && isFunctionLike$1(child)) return false;
33360
34129
  if (!isNodeOfType(child, "IfStatement")) return;
33361
34130
  if (guardHasOtherReactiveSource(analysis, child.test, handlerStateDeclarator)) {
33362
34131
  hasAdditionalGuard = true;
@@ -33380,7 +34149,7 @@ const noEventHandler = defineRule({
33380
34149
  let reported = false;
33381
34150
  walkAst(frame.functionNode, (child) => {
33382
34151
  if (reported) return false;
33383
- if (child !== frame.functionNode && isFunctionLike$2(child)) return false;
34152
+ if (child !== frame.functionNode && isFunctionLike$1(child)) return false;
33384
34153
  if (!isNodeOfType(child, "IfStatement") || child.alternate) return;
33385
34154
  if (!consequentHasTransferableWork(analysis, child.consequent)) return;
33386
34155
  const stateReferences = collectGuardStateReferences(analysis, child.test);
@@ -33694,7 +34463,7 @@ const addIteratorMutationDependencies = (graph, expression, scope, eventHandlerR
33694
34463
  for (const argument of expression.arguments ?? []) {
33695
34464
  if (!isNodeOfType(argument, "ArrowFunctionExpression") && !isNodeOfType(argument, "FunctionExpression")) continue;
33696
34465
  walkAst(argument.body, (node) => {
33697
- if (node !== argument.body && isFunctionLike$2(node)) return false;
34466
+ if (node !== argument.body && isFunctionLike$1(node)) return false;
33698
34467
  if (!isNodeOfType(node, "CallExpression")) return;
33699
34468
  if (!isNodeOfType(node.callee, "MemberExpression")) return;
33700
34469
  const nestedMethodName = getStaticMemberPropertyName(node.callee);
@@ -34155,12 +34924,12 @@ const isNetworkRequest = (node) => isRealFetchCall(node) || isXmlHttpRequestCons
34155
34924
  const resolveLocalFunction = (expression, context) => {
34156
34925
  if (!expression) return null;
34157
34926
  const unwrappedExpression = stripParenExpression(expression);
34158
- if (isFunctionLike$2(unwrappedExpression)) return unwrappedExpression;
34927
+ if (isFunctionLike$1(unwrappedExpression)) return unwrappedExpression;
34159
34928
  if (!isNodeOfType(unwrappedExpression, "Identifier")) return null;
34160
34929
  const initializer = context.scopes.symbolFor(unwrappedExpression)?.initializer;
34161
34930
  if (!initializer) return null;
34162
34931
  const unwrappedInitializer = stripParenExpression(initializer);
34163
- return isFunctionLike$2(unwrappedInitializer) ? unwrappedInitializer : null;
34932
+ return isFunctionLike$1(unwrappedInitializer) ? unwrappedInitializer : null;
34164
34933
  };
34165
34934
  const collectEffectAnalysisFunctions = (effectCallback, context) => {
34166
34935
  const analysisFunctions = /* @__PURE__ */ new Set();
@@ -34177,7 +34946,7 @@ const collectEffectAnalysisFunctions = (effectCallback, context) => {
34177
34946
  const currentFunction = pendingFunctions.pop();
34178
34947
  if (!currentFunction) break;
34179
34948
  walkAst(currentFunction, (child) => {
34180
- if (child !== currentFunction && isFunctionLike$2(child)) return false;
34949
+ if (child !== currentFunction && isFunctionLike$1(child)) return false;
34181
34950
  if (!isNodeOfType(child, "CallExpression")) return;
34182
34951
  const calledFunction = resolveLocalFunction(child.callee, context);
34183
34952
  if (calledFunction) enqueueFunction(calledFunction);
@@ -34193,7 +34962,7 @@ const collectNodesFromAnalysisFunctions = (analysisFunctions, predicate) => {
34193
34962
  const nodes = [];
34194
34963
  const seenNodes = /* @__PURE__ */ new Set();
34195
34964
  for (const analysisFunction of analysisFunctions) walkAst(analysisFunction, (child) => {
34196
- if (child !== analysisFunction && isFunctionLike$2(child)) return false;
34965
+ if (child !== analysisFunction && isFunctionLike$1(child)) return false;
34197
34966
  if (!seenNodes.has(child) && predicate(child)) {
34198
34967
  seenNodes.add(child);
34199
34968
  nodes.push(child);
@@ -34202,19 +34971,19 @@ const collectNodesFromAnalysisFunctions = (analysisFunctions, predicate) => {
34202
34971
  return nodes;
34203
34972
  };
34204
34973
  const findEffectCleanupFunction = (callback) => {
34205
- if (!isFunctionLike$2(callback)) return null;
34974
+ if (!isFunctionLike$1(callback)) return null;
34206
34975
  const body = callback.body;
34207
- if (isFunctionLike$2(body)) return body;
34976
+ if (isFunctionLike$1(body)) return body;
34208
34977
  let cleanup = null;
34209
34978
  walkAst(body, (child) => {
34210
- if (child !== body && isFunctionLike$2(child)) return false;
34211
- if (isNodeOfType(child, "ReturnStatement") && child.argument && isFunctionLike$2(child.argument)) cleanup = child.argument;
34979
+ if (child !== body && isFunctionLike$1(child)) return false;
34980
+ if (isNodeOfType(child, "ReturnStatement") && child.argument && isFunctionLike$1(child.argument)) cleanup = child.argument;
34212
34981
  });
34213
34982
  return cleanup;
34214
34983
  };
34215
34984
  const collectEffectCancellationFlagKeys = (effectCallback, context) => {
34216
34985
  const flagKeys = /* @__PURE__ */ new Set();
34217
- if (!isFunctionLike$2(effectCallback)) return flagKeys;
34986
+ if (!isFunctionLike$1(effectCallback)) return flagKeys;
34218
34987
  const body = effectCallback.body;
34219
34988
  if (!isNodeOfType(body, "BlockStatement")) return flagKeys;
34220
34989
  for (const statement of body.body ?? []) {
@@ -34298,7 +35067,7 @@ const isCompletionSinkInsideCancellationGuard = (completionSink, cancellationFla
34298
35067
  let currentNode = completionSink;
34299
35068
  let parentNode = currentNode.parent;
34300
35069
  while (parentNode) {
34301
- if (isFunctionLike$2(parentNode)) return false;
35070
+ if (isFunctionLike$1(parentNode)) return false;
34302
35071
  if (isNodeOfType(parentNode, "IfStatement")) {
34303
35072
  const cancellationResult = readCancellationCondition(parentNode.test, cancellationFlagKey, context);
34304
35073
  if (currentNode === parentNode.consequent && cancellationResult === false) return true;
@@ -34323,7 +35092,7 @@ const isCompletionSinkAfterCancellationEarlyExit = (completionSink, cancellation
34323
35092
  let currentNode = completionSink;
34324
35093
  let parentNode = currentNode.parent;
34325
35094
  while (parentNode) {
34326
- if (isFunctionLike$2(parentNode)) return false;
35095
+ if (isFunctionLike$1(parentNode)) return false;
34327
35096
  if (isNodeOfType(parentNode, "BlockStatement")) {
34328
35097
  const statementIndex = parentNode.body.findIndex((statement) => statement === currentNode);
34329
35098
  if (statementIndex >= 0) for (const statement of parentNode.body.slice(0, statementIndex)) {
@@ -34494,7 +35263,7 @@ const collectMeasuringFunctionNames = (program) => {
34494
35263
  if (!isNodeOfType(child, "VariableDeclarator") || !isNodeOfType(child.id, "Identifier")) return;
34495
35264
  let functionValue = child.init;
34496
35265
  if (functionValue && isNodeOfType(functionValue, "CallExpression") && isNodeOfType(functionValue.callee, "Identifier") && /^use[A-Z]/.test(functionValue.callee.name)) functionValue = functionValue.arguments?.[0];
34497
- if (functionValue && isFunctionLike$2(functionValue) && subtreeReadsDomMeasurement(functionValue.body)) names.add(child.id.name);
35266
+ if (functionValue && isFunctionLike$1(functionValue) && subtreeReadsDomMeasurement(functionValue.body)) names.add(child.id.name);
34498
35267
  });
34499
35268
  return names;
34500
35269
  };
@@ -34521,7 +35290,7 @@ const isInsideStartViewTransition = (node) => {
34521
35290
  const enclosingFunctionChainReadsMeasurement = (node, measuringFunctionNames) => {
34522
35291
  let cursor = node.parent;
34523
35292
  while (cursor) {
34524
- if (isFunctionLike$2(cursor)) {
35293
+ if (isFunctionLike$1(cursor)) {
34525
35294
  const body = cursor.body;
34526
35295
  if (subtreeReadsDomMeasurement(body) || callsAnyName(body, measuringFunctionNames)) return true;
34527
35296
  }
@@ -34963,7 +35732,7 @@ const hasClientRenderEvidence = (componentOrHookNode, fileHasUseClientDirective)
34963
35732
  const displayName = componentOrHookDisplayNameForFunction(componentOrHookNode);
34964
35733
  if (displayName && isReactHookName(displayName)) return true;
34965
35734
  let callsHook = false;
34966
- walkAst((isFunctionLike$2(componentOrHookNode) ? componentOrHookNode.body : null) ?? componentOrHookNode, (child) => {
35735
+ walkAst((isFunctionLike$1(componentOrHookNode) ? componentOrHookNode.body : null) ?? componentOrHookNode, (child) => {
34967
35736
  if (callsHook) return false;
34968
35737
  if (isNodeOfType(child, "CallExpression") && isNodeOfType(child.callee, "Identifier") && isReactHookName(child.callee.name)) {
34969
35738
  callsHook = true;
@@ -35033,7 +35802,7 @@ const readInitialStateBoolean = (expression, scopes) => readInitialStateBooleanI
35033
35802
  //#endregion
35034
35803
  //#region src/plugin/utils/is-after-client-only-early-return.ts
35035
35804
  const isAfterClientOnlyEarlyReturn = (node, componentOrHookNode, scopes) => {
35036
- const body = isFunctionLike$2(componentOrHookNode) ? componentOrHookNode.body : null;
35805
+ const body = isFunctionLike$1(componentOrHookNode) ? componentOrHookNode.body : null;
35037
35806
  if (!isNodeOfType(body, "BlockStatement")) return false;
35038
35807
  const ancestors = /* @__PURE__ */ new Set();
35039
35808
  let currentNode = node;
@@ -35066,7 +35835,7 @@ const isGatedByFalsyInitialState = (node, scopes) => {
35066
35835
  };
35067
35836
  //#endregion
35068
35837
  //#region src/plugin/rules/performance/no-hydration-branch-on-browser-global.ts
35069
- const evaluateEquality = (operator, left, right) => {
35838
+ const evaluateEquality$1 = (operator, left, right) => {
35070
35839
  if (operator === "===" || operator === "==") return left === right;
35071
35840
  if (operator === "!==" || operator === "!=") return left !== right;
35072
35841
  return null;
@@ -35097,8 +35866,8 @@ const matchBrowserPredicate = (expression, context) => {
35097
35866
  const browserGlobalName = leftGlobalName && typeof rightString === "string" ? leftGlobalName : rightGlobalName && typeof leftString === "string" ? rightGlobalName : null;
35098
35867
  const comparedType = leftGlobalName && typeof rightString === "string" ? rightString : rightGlobalName && typeof leftString === "string" ? leftString : null;
35099
35868
  if (!browserGlobalName || !comparedType) return null;
35100
- const clientResult = evaluateEquality(unwrappedExpression.operator, "object", comparedType);
35101
- const serverResult = evaluateEquality(unwrappedExpression.operator, "undefined", comparedType);
35869
+ const clientResult = evaluateEquality$1(unwrappedExpression.operator, "object", comparedType);
35870
+ const serverResult = evaluateEquality$1(unwrappedExpression.operator, "undefined", comparedType);
35102
35871
  if (clientResult === null || serverResult === null || clientResult === serverResult) return null;
35103
35872
  return {
35104
35873
  browserGlobalName,
@@ -35197,7 +35966,7 @@ const findEnclosingJsxAttribute = (node) => {
35197
35966
  let currentNode = node.parent;
35198
35967
  while (currentNode) {
35199
35968
  if (isNodeOfType(currentNode, "JSXAttribute")) return currentNode;
35200
- if (isNodeOfType(currentNode, "JSXElement") || isNodeOfType(currentNode, "JSXFragment") || isFunctionLike$2(currentNode)) return null;
35969
+ if (isNodeOfType(currentNode, "JSXElement") || isNodeOfType(currentNode, "JSXFragment") || isFunctionLike$1(currentNode)) return null;
35201
35970
  currentNode = currentNode.parent;
35202
35971
  }
35203
35972
  return null;
@@ -35213,8 +35982,8 @@ const isInRenderedOutput = (node, componentOrHookNode, scopes) => {
35213
35982
  if (isNodeOfType(parentNode, "ReturnStatement")) {
35214
35983
  if (findEnclosingFunction$1(parentNode) === componentOrHookNode) return true;
35215
35984
  }
35216
- if (parentNode === componentOrHookNode) return isFunctionLike$2(componentOrHookNode) && !isNodeOfType(componentOrHookNode.body, "BlockStatement") && componentOrHookNode.body === currentNode;
35217
- if (isFunctionLike$2(parentNode) && !executesDuringRender(parentNode, scopes)) return false;
35985
+ if (parentNode === componentOrHookNode) return isFunctionLike$1(componentOrHookNode) && !isNodeOfType(componentOrHookNode.body, "BlockStatement") && componentOrHookNode.body === currentNode;
35986
+ if (isFunctionLike$1(parentNode) && !executesDuringRender(parentNode, scopes)) return false;
35218
35987
  currentNode = parentNode;
35219
35988
  parentNode = currentNode.parent;
35220
35989
  }
@@ -35492,7 +36261,7 @@ const findImpureUpdaterOperation = (updater, scopes) => {
35492
36261
  let operation = null;
35493
36262
  walkAst(updater, (child) => {
35494
36263
  if (operation) return false;
35495
- if (child !== updater && isFunctionLike$2(child) && !isDefinitelySynchronousCallback(child, scopes)) return false;
36264
+ if (child !== updater && isFunctionLike$1(child) && !isDefinitelySynchronousCallback(child, scopes)) return false;
35496
36265
  if (isNodeOfType(child, "CallExpression")) {
35497
36266
  if (isNodeOfType(child.callee, "Identifier") && analysis) {
35498
36267
  const calleeReference = getRef(analysis, child.callee);
@@ -35533,7 +36302,7 @@ const noImpureStateUpdater = defineRule({
35533
36302
  const stateDeclarator = getUseStateDecl(analysis, calleeReference);
35534
36303
  if (!isNodeOfType(stateDeclarator, "VariableDeclarator") || !isNodeOfType(stateDeclarator.init, "CallExpression") || !isReactApiCall(stateDeclarator.init, "useState", context.scopes, { allowGlobalReactNamespace: true })) return;
35535
36304
  let updater = null;
35536
- if (isFunctionLike$2(updaterArgument)) updater = updaterArgument;
36305
+ if (isFunctionLike$1(updaterArgument)) updater = updaterArgument;
35537
36306
  else if (isNodeOfType(updaterArgument, "Identifier")) {
35538
36307
  const updaterReference = getRef(analysis, updaterArgument);
35539
36308
  if (updaterReference) updater = resolveToFunction(updaterReference);
@@ -35966,7 +36735,7 @@ const isCatchParameterRoundTrip = (stringifyCall) => {
35966
36735
  if (!argument || !isNodeOfType(argument, "Identifier")) return false;
35967
36736
  let current = stringifyCall.parent;
35968
36737
  while (current) {
35969
- if (isFunctionLike$2(current) && (current.params ?? []).some((parameter) => isNodeOfType(parameter, "Identifier") && parameter.name === argument.name)) return false;
36738
+ if (isFunctionLike$1(current) && (current.params ?? []).some((parameter) => isNodeOfType(parameter, "Identifier") && parameter.name === argument.name)) return false;
35970
36739
  if (isNodeOfType(current, "CatchClause") && isNodeOfType(current.param, "Identifier") && current.param.name === argument.name) return true;
35971
36740
  current = current.parent ?? null;
35972
36741
  }
@@ -35980,7 +36749,7 @@ const getName = (candidate) => {
35980
36749
  const isInsideSnapshotHelper = (node) => {
35981
36750
  let current = node.parent;
35982
36751
  while (current) {
35983
- if (isFunctionLike$2(current)) {
36752
+ if (isFunctionLike$1(current)) {
35984
36753
  const directName = isNodeOfType(current, "ArrowFunctionExpression") ? null : getName(current.id);
35985
36754
  const parent = current.parent;
35986
36755
  let boundName = directName;
@@ -36003,9 +36772,9 @@ const noJsonParseStringifyClone = defineRule({
36003
36772
  const firstArgument = node.arguments?.[0];
36004
36773
  if (!firstArgument || !isJsonMethodCall(firstArgument, "stringify")) return;
36005
36774
  const replacer = firstArgument.arguments?.[1];
36006
- if (isFunctionLike$2(replacer) || isNodeOfType(replacer, "ArrayExpression")) return;
36775
+ if (isFunctionLike$1(replacer) || isNodeOfType(replacer, "ArrayExpression")) return;
36007
36776
  const reviver = node.arguments?.[1];
36008
- if (isFunctionLike$2(reviver)) return;
36777
+ if (isFunctionLike$1(reviver)) return;
36009
36778
  if (isInsideSnapshotHelper(node)) return;
36010
36779
  if (isAssignedToNormalizationBinding(node)) return;
36011
36780
  if (isCatchParameterRoundTrip(firstArgument)) return;
@@ -36332,11 +37101,11 @@ const isProvenReactClassComponent = (classNode, scopes, visitedClassNodes = /* @
36332
37101
  //#endregion
36333
37102
  //#region src/plugin/utils/function-contains-proven-react-hook-call.ts
36334
37103
  const functionContainsProvenReactHookCall = (functionNode, scopes) => {
36335
- if (!isFunctionLike$2(functionNode)) return false;
37104
+ if (!isFunctionLike$1(functionNode)) return false;
36336
37105
  let containsReactHookCall = false;
36337
37106
  walkAst(functionNode.body, (node) => {
36338
37107
  if (containsReactHookCall) return false;
36339
- if (node !== functionNode.body && (isFunctionLike$2(node) || isNodeOfType(node, "ClassDeclaration") || isNodeOfType(node, "ClassExpression"))) return false;
37108
+ if (node !== functionNode.body && (isFunctionLike$1(node) || isNodeOfType(node, "ClassDeclaration") || isNodeOfType(node, "ClassExpression"))) return false;
36340
37109
  if (isNodeOfType(node, "CallExpression") && isReactApiCall(node, BUILTIN_HOOK_NAMES, scopes, { resolveNamedAliases: true })) {
36341
37110
  containsReactHookCall = true;
36342
37111
  return false;
@@ -36347,7 +37116,7 @@ const functionContainsProvenReactHookCall = (functionNode, scopes) => {
36347
37116
  //#endregion
36348
37117
  //#region src/plugin/utils/function-returns-props-children.ts
36349
37118
  const functionReturnsPropsChildren = (functionNode, scopes, controlFlow) => {
36350
- if (!isFunctionLike$2(functionNode) || functionNode.params.length === 0) return false;
37119
+ if (!isFunctionLike$1(functionNode) || functionNode.params.length === 0) return false;
36351
37120
  const firstParameter = stripParenExpression(functionNode.params[0]);
36352
37121
  const firstParameterPattern = isNodeOfType(firstParameter, "AssignmentPattern") ? stripParenExpression(firstParameter.left) : firstParameter;
36353
37122
  const propsParameterSymbol = isNodeOfType(firstParameterPattern, "Identifier") ? scopes.symbolFor(firstParameterPattern) : null;
@@ -36383,7 +37152,7 @@ const isNullExpression = (expression) => {
36383
37152
  return isNodeOfType(candidate, "Literal") && candidate.value === null;
36384
37153
  };
36385
37154
  const functionReturnsOnlyNull = (functionNode) => {
36386
- if (!isFunctionLike$2(functionNode)) return false;
37155
+ if (!isFunctionLike$1(functionNode)) return false;
36387
37156
  if (!isNodeOfType(functionNode.body, "BlockStatement")) return isNullExpression(functionNode.body);
36388
37157
  const returnStatements = collectFunctionReturnStatements(functionNode);
36389
37158
  return returnStatements.length > 0 && returnStatements.every((returnStatement) => Boolean(returnStatement.argument && isNullExpression(returnStatement.argument)));
@@ -37024,10 +37793,10 @@ const noLocaleFormatInRender = defineRule({
37024
37793
  const componentOrHookNode = findRenderPhaseComponentOrHook(node, context.scopes);
37025
37794
  if (!componentOrHookNode) return;
37026
37795
  const helperNode = findVariableInitializer(expression.callee, helperName)?.initializer;
37027
- if (!helperNode || !isFunctionLike$2(helperNode)) return;
37796
+ if (!helperNode || !isFunctionLike$1(helperNode)) return;
37028
37797
  if (componentOrHookDisplayNameForFunction(helperNode)) return;
37029
37798
  walkAst(helperNode.body ?? helperNode, (child) => {
37030
- if (isFunctionLike$2(child)) return false;
37799
+ if (isFunctionLike$1(child)) return false;
37031
37800
  if (!isNodeOfType(child, "CallExpression")) return;
37032
37801
  const match = matchLocaleMethodCall(child, context.scopes) ?? matchIntlFormatCall(child, context.scopes);
37033
37802
  if (!match || reportedNodes.has(match.node)) return;
@@ -37250,7 +38019,7 @@ const findDirectMatchMediaCall = (root, context) => {
37250
38019
  let matchMediaCall = null;
37251
38020
  walkAst(root, (visitedNode) => {
37252
38021
  if (matchMediaCall) return false;
37253
- if (isFunctionLike$2(visitedNode)) return false;
38022
+ if (isFunctionLike$1(visitedNode)) return false;
37254
38023
  if (isGlobalMatchMediaCall(visitedNode, context.scopes)) {
37255
38024
  matchMediaCall = visitedNode;
37256
38025
  return false;
@@ -37260,7 +38029,7 @@ const findDirectMatchMediaCall = (root, context) => {
37260
38029
  };
37261
38030
  const findMatchMediaCallDuringInitialization = (initializer, context) => {
37262
38031
  const rootInitializer = stripParenExpression(initializer);
37263
- if (!isFunctionLike$2(rootInitializer)) return findDirectMatchMediaCall(rootInitializer, context);
38032
+ if (!isFunctionLike$1(rootInitializer)) return findDirectMatchMediaCall(rootInitializer, context);
37264
38033
  if (rootInitializer.async || rootInitializer.generator) return null;
37265
38034
  return findDirectMatchMediaCall(rootInitializer.body, context);
37266
38035
  };
@@ -37921,7 +38690,7 @@ const isLodashMutatorCall = (callExpression) => {
37921
38690
  const resolveReducerFunction = (node, currentFilename) => {
37922
38691
  if (!node) return null;
37923
38692
  const unwrappedNode = stripParenExpression(node);
37924
- if (isFunctionLike$2(unwrappedNode)) return {
38693
+ if (isFunctionLike$1(unwrappedNode)) return {
37925
38694
  functionNode: unwrappedNode,
37926
38695
  crossFileSourceDisplay: null
37927
38696
  };
@@ -37929,7 +38698,7 @@ const resolveReducerFunction = (node, currentFilename) => {
37929
38698
  const initializer = findVariableInitializer(unwrappedNode, unwrappedNode.name)?.initializer;
37930
38699
  if (!initializer) return null;
37931
38700
  const unwrappedInitializer = stripParenExpression(initializer);
37932
- if (isFunctionLike$2(unwrappedInitializer)) return {
38701
+ if (isFunctionLike$1(unwrappedInitializer)) return {
37933
38702
  functionNode: unwrappedInitializer,
37934
38703
  crossFileSourceDisplay: null
37935
38704
  };
@@ -38040,11 +38809,11 @@ const canExpressionReturnOriginalReducerStateReference = (node, state) => {
38040
38809
  return false;
38041
38810
  };
38042
38811
  const collectReducerStateMutationsInExpressionOrStatement = (node, state) => {
38043
- if (isFunctionLike$2(node)) return [];
38812
+ if (isFunctionLike$1(node)) return [];
38044
38813
  const mutations = [];
38045
38814
  walkAst(node, (child) => {
38046
38815
  const unwrappedChild = stripParenExpression(child);
38047
- if (child !== node && isFunctionLike$2(unwrappedChild)) return false;
38816
+ if (child !== node && isFunctionLike$1(unwrappedChild)) return false;
38048
38817
  if (isNodeOfType(unwrappedChild, "AssignmentExpression")) {
38049
38818
  if (isNodeOfType(stripParenExpression(unwrappedChild.left), "MemberExpression") && isExpressionRootedInMutableReducerStateSource(unwrappedChild.left, state)) mutations.push({ node: unwrappedChild });
38050
38819
  return;
@@ -38150,7 +38919,7 @@ const updateReducerStateIdentityForIdentifierAssignment = (assignment, state) =>
38150
38919
  if (isExpressionReachableFromOriginalReducerState(assignment.right, state)) state.mutableStateSourceNames.add(name);
38151
38920
  };
38152
38921
  const analyzeReactUseReducerFunctionForStateMutation = (context, functionNode, reportedNodes, options) => {
38153
- if (!isFunctionLike$2(functionNode) || !isNodeOfType(functionNode.body, "BlockStatement")) return;
38922
+ if (!isFunctionLike$1(functionNode) || !isNodeOfType(functionNode.body, "BlockStatement")) return;
38154
38923
  const firstParam = functionNode.params?.[0];
38155
38924
  const stateName = isNodeOfType(firstParam, "Identifier") ? firstParam.name : isNodeOfType(firstParam, "AssignmentPattern") && isNodeOfType(firstParam.left, "Identifier") ? firstParam.left.name : null;
38156
38925
  if (!stateName) return;
@@ -38819,7 +39588,7 @@ const rendersFocusManagerInSameFunction = (styleAttribute) => {
38819
39588
  let ancestor = styleAttribute.parent;
38820
39589
  while (ancestor) {
38821
39590
  scopeOwner = ancestor;
38822
- if (isFunctionLike$2(ancestor)) break;
39591
+ if (isFunctionLike$1(ancestor)) break;
38823
39592
  ancestor = ancestor.parent ?? null;
38824
39593
  }
38825
39594
  let didFindFocusManager = false;
@@ -39156,7 +39925,7 @@ const getWrapperHookWrappedFunction = (initializer) => {
39156
39925
  const calleeName = isNodeOfType(callee, "Identifier") ? callee.name : isNodeOfType(callee, "MemberExpression") && isNodeOfType(callee.property, "Identifier") ? callee.property.name : null;
39157
39926
  if (!calleeName || !FUNCTION_WRAPPER_HOOK_NAMES$1.has(calleeName)) return null;
39158
39927
  const wrapped = initializer.arguments?.[0];
39159
- if (!wrapped || !isFunctionLike$2(wrapped)) return null;
39928
+ if (!wrapped || !isFunctionLike$1(wrapped)) return null;
39160
39929
  return wrapped;
39161
39930
  };
39162
39931
  const HANDLER_NAMED_PROP_PATTERN = /^(on|handle)[A-Z]/;
@@ -39310,7 +40079,7 @@ const getCallbackRefProvenance = (analysis, effectCall, callExpression, isReactU
39310
40079
  if (!bindingProvenance) return null;
39311
40080
  const { refCall, variables } = bindingProvenance;
39312
40081
  const componentFunction = findEnclosingFunction$1(effectCall);
39313
- if (!componentFunction || !isFunctionLike$2(componentFunction) || !isComponentFunction$1(componentFunction) || !isNodeOfType(componentFunction.body, "BlockStatement")) return null;
40082
+ if (!componentFunction || !isFunctionLike$1(componentFunction) || !isComponentFunction$1(componentFunction) || !isNodeOfType(componentFunction.body, "BlockStatement")) return null;
39314
40083
  if (!getDirectComponentBodyStatement(effectCall, componentFunction.body)) return null;
39315
40084
  const callbackPropNames = /* @__PURE__ */ new Set();
39316
40085
  const initializer = refCall.arguments?.[0];
@@ -39348,7 +40117,7 @@ const isHandlerBagArgument = (analysis, argument) => {
39348
40117
  return properties.every((property) => {
39349
40118
  if (!isNodeOfType(property, "Property")) return false;
39350
40119
  const value = property.value;
39351
- if (isFunctionLike$2(value)) return true;
40120
+ if (isFunctionLike$1(value)) return true;
39352
40121
  if (isNodeOfType(value, "Identifier")) {
39353
40122
  const valueRef = getRef(analysis, value);
39354
40123
  return Boolean(valueRef && resolveToFunction(valueRef));
@@ -39451,7 +40220,7 @@ const noPassDataToParent = defineRule({
39451
40220
  const isSetterNamedCallee = callbackRefProvenance ? [...callbackRefProvenance.callbackPropNames].every((callbackPropName) => SETTER_NAMED_PROP_PATTERN.test(callbackPropName)) : Boolean((isNodeOfType(identifier, "Identifier") ? identifier.name : methodName) && SETTER_NAMED_PROP_PATTERN.test((isNodeOfType(identifier, "Identifier") ? identifier.name : methodName) ?? ""));
39452
40221
  const isLeafRef = (argRef) => getUpstreamRefs(analysis, argRef).length === 1;
39453
40222
  const argsUpstreamRefs = (callExpr.arguments ?? []).flatMap((argument) => {
39454
- if (isFunctionLike$2(argument)) {
40223
+ if (isFunctionLike$1(argument)) {
39455
40224
  if (!isSetterNamedCallee) return [];
39456
40225
  return getFunctionalUpdaterDataRefs(analysis, argument);
39457
40226
  }
@@ -39568,7 +40337,7 @@ const collectPropCallbackBoundStateRefs = (analysis, ref, isPropCallbackRef) =>
39568
40337
  if (!callExpr || !isNodeOfType(callExpr, "CallExpression")) continue;
39569
40338
  if (!(getEventualCallRefsTo(analysis, upRef, isPropCallbackRef).length > 0)) continue;
39570
40339
  for (const argument of callExpr.arguments ?? []) {
39571
- if (isFunctionLike$2(argument)) continue;
40340
+ if (isFunctionLike$1(argument)) continue;
39572
40341
  for (const argRef of getDownstreamRefs(analysis, argument)) {
39573
40342
  if (resolveToFunction(argRef)) continue;
39574
40343
  collectUpstreamStateRefs(analysis, argRef, stateRefs, /* @__PURE__ */ new Set());
@@ -39585,7 +40354,7 @@ const isSetterNamedCallbackReceivingData = (callbackRef) => {
39585
40354
  if (!isCustomHookParameter(callbackRef)) return false;
39586
40355
  const firstArgument = (callExpr.arguments ?? [])[0];
39587
40356
  if (!firstArgument) return false;
39588
- return !isNodeOfType(firstArgument, "Literal") && !isNodeOfType(firstArgument, "TemplateLiteral") && !isFunctionLike$2(firstArgument);
40357
+ return !isNodeOfType(firstArgument, "Literal") && !isNodeOfType(firstArgument, "TemplateLiteral") && !isFunctionLike$1(firstArgument);
39589
40358
  };
39590
40359
  const FUNCTION_WRAPPER_HOOK_NAMES = new Set([
39591
40360
  "useCallback",
@@ -39765,14 +40534,25 @@ const isPropsChildrenLength = (node, scopes) => {
39765
40534
  const unwrappedNode = stripParenExpression(node);
39766
40535
  return isNodeOfType(unwrappedNode, "MemberExpression") && !unwrappedNode.computed && isNodeOfType(unwrappedNode.property, "Identifier") && unwrappedNode.property.name === "length" && resolvesToPropsChildren(stripParenExpression(unwrappedNode.object), scopes);
39767
40536
  };
40537
+ const resolveStaticNumericValue = (node, scopes, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
40538
+ const unwrappedNode = stripParenExpression(node);
40539
+ if (isNodeOfType(unwrappedNode, "Literal") && typeof unwrappedNode.value === "number") return Number.isFinite(unwrappedNode.value) ? unwrappedNode.value : null;
40540
+ if (!isNodeOfType(unwrappedNode, "Identifier")) return null;
40541
+ const symbol = scopes.symbolFor(unwrappedNode);
40542
+ if (!symbol || visitedSymbolIds.has(symbol.id)) return null;
40543
+ const initializer = getDirectConstInitializer(symbol);
40544
+ if (!initializer) return null;
40545
+ return resolveStaticNumericValue(initializer, scopes, new Set(visitedSymbolIds).add(symbol.id));
40546
+ };
39768
40547
  const isLargeTextLengthComparison = (node, scopes) => {
39769
40548
  const unwrappedNode = stripParenExpression(node);
39770
40549
  if (!isNodeOfType(unwrappedNode, "BinaryExpression")) return false;
39771
40550
  const leftIsLength = isPropsChildrenLength(unwrappedNode.left, scopes);
39772
40551
  const rightIsLength = isPropsChildrenLength(unwrappedNode.right, scopes);
39773
40552
  const thresholdNode = leftIsLength ? unwrappedNode.right : unwrappedNode.left;
39774
- if (!leftIsLength && !rightIsLength || !isNodeOfType(thresholdNode, "Literal")) return false;
39775
- if (typeof thresholdNode.value !== "number" || thresholdNode.value < 1e3) return false;
40553
+ if (!leftIsLength && !rightIsLength) return false;
40554
+ const thresholdValue = resolveStaticNumericValue(thresholdNode, scopes);
40555
+ if (thresholdValue === null || thresholdValue < 1e3) return false;
39776
40556
  return leftIsLength ? unwrappedNode.operator === ">" || unwrappedNode.operator === ">=" : unwrappedNode.operator === "<" || unwrappedNode.operator === "<=";
39777
40557
  };
39778
40558
  const isLargeStringOptimizationGuard = (comparison, scopes) => {
@@ -39859,7 +40639,7 @@ const collectEnclosingParameterNames = (handlerExpression) => {
39859
40639
  const parameterNames = /* @__PURE__ */ new Set();
39860
40640
  let ancestor = handlerExpression;
39861
40641
  while (ancestor) {
39862
- if (isFunctionLike$2(ancestor)) for (const parameter of ancestor.params ?? []) collectPatternNames(parameter, parameterNames);
40642
+ if (isFunctionLike$1(ancestor)) for (const parameter of ancestor.params ?? []) collectPatternNames(parameter, parameterNames);
39863
40643
  ancestor = ancestor.parent ?? null;
39864
40644
  }
39865
40645
  return parameterNames;
@@ -39921,7 +40701,7 @@ const containsControlledInput = (formOpeningElement) => {
39921
40701
  return didFindControlledInput;
39922
40702
  };
39923
40703
  const containsAsynchronousWork = (handlerExpression) => {
39924
- if (isFunctionLike$2(handlerExpression) && handlerExpression.async === true) return true;
40704
+ if (isFunctionLike$1(handlerExpression) && handlerExpression.async === true) return true;
39925
40705
  let didFindAsynchronousWork = false;
39926
40706
  walkAst(handlerExpression, (child) => {
39927
40707
  if (didFindAsynchronousWork) return;
@@ -40136,7 +40916,7 @@ const noPropCallbackInRender = defineRule({
40136
40916
  const analysis = getProgramAnalysis(node);
40137
40917
  if (!analysis) return;
40138
40918
  const callee = stripParenExpression(node.callee);
40139
- if (isFunctionLike$2(callee)) return;
40919
+ if (isFunctionLike$1(callee)) return;
40140
40920
  if (!getDownstreamRefs(analysis, callee).some((reference) => isPropCallbackInvocationRef(analysis, reference))) return;
40141
40921
  context.report({
40142
40922
  node,
@@ -40319,7 +41099,7 @@ const findFreshCallInSubtree = (root) => {
40319
41099
  let foundDescription = null;
40320
41100
  walkAst(root, (child) => {
40321
41101
  if (foundDescription) return false;
40322
- if (child !== root && isFunctionLike$2(child)) return false;
41102
+ if (child !== root && isFunctionLike$1(child)) return false;
40323
41103
  const description = isAlwaysFreshExpression(child);
40324
41104
  if (description) {
40325
41105
  foundDescription = description;
@@ -40863,7 +41643,7 @@ const isEmptySentinel = (node, scopes) => isNodeOfType(node, "Literal") && node.
40863
41643
  const hasRepeatedExecutionAncestor = (node, stop) => {
40864
41644
  let ancestor = node.parent;
40865
41645
  while (ancestor && ancestor !== stop) {
40866
- if (isFunctionLike$2(ancestor) || REPEATED_ANCESTOR_TYPES.has(ancestor.type)) return true;
41646
+ if (isFunctionLike$1(ancestor) || REPEATED_ANCESTOR_TYPES.has(ancestor.type)) return true;
40867
41647
  ancestor = ancestor.parent;
40868
41648
  }
40869
41649
  return ancestor !== stop;
@@ -40958,15 +41738,15 @@ const noRefCurrentInRender = defineRule({
40958
41738
  const isInsideComponentContext = (node) => {
40959
41739
  let cursor = node.parent;
40960
41740
  while (cursor) {
40961
- if (isFunctionLike$2(cursor) && isComponentFunction$1(cursor)) return true;
41741
+ if (isFunctionLike$1(cursor) && isComponentFunction$1(cursor)) return true;
40962
41742
  if (isEs5Component(cursor) || isEs6Component(cursor)) return true;
40963
41743
  cursor = cursor.parent ?? null;
40964
41744
  }
40965
41745
  return false;
40966
41746
  };
40967
41747
  const functionBodyOf = (node) => {
40968
- if (isFunctionLike$2(node)) return node.body ?? null;
40969
- if (isNodeOfType(node, "VariableDeclarator") && node.init && isFunctionLike$2(node.init)) return node.init.body ?? null;
41748
+ if (isFunctionLike$1(node)) return node.body ?? null;
41749
+ if (isNodeOfType(node, "VariableDeclarator") && node.init && isFunctionLike$1(node.init)) return node.init.body ?? null;
40970
41750
  return null;
40971
41751
  };
40972
41752
  const isHookCallee = (callee) => {
@@ -40978,7 +41758,7 @@ const containsHookCall = (body) => {
40978
41758
  let found = false;
40979
41759
  walkAst(body, (child) => {
40980
41760
  if (found) return false;
40981
- if (child !== body && isFunctionLike$2(child) && isComponentFunction$1(child)) return false;
41761
+ if (child !== body && isFunctionLike$1(child) && isComponentFunction$1(child)) return false;
40982
41762
  if (!isNodeOfType(child, "CallExpression")) return;
40983
41763
  if (isHookCallee(child.callee)) found = true;
40984
41764
  });
@@ -41100,18 +41880,107 @@ const getNodeText$1 = (node) => {
41100
41880
  return value;
41101
41881
  });
41102
41882
  };
41103
- const isLiteralConstantIdentifier = (analysis, identifier) => {
41104
- const definitions = getRef(analysis, identifier)?.resolved?.defs;
41105
- if (!definitions || definitions.length !== 1) return false;
41106
- const definition = definitions[0];
41107
- if (definition.type !== "Variable") return false;
41108
- const declarator = definition.node;
41109
- if (!isNodeOfType(declarator, "VariableDeclarator")) return false;
41110
- const declaration = declarator.parent;
41111
- if (!isNodeOfType(declaration, "VariableDeclaration") || declaration.kind !== "const") return false;
41112
- return isNodeOfType(declarator.init, "Literal");
41883
+ const normalizeAsBoolean = (identity) => ({
41884
+ ...identity,
41885
+ booleanNormalization: identity.booleanNormalization === "identity" ? "normalized" : identity.booleanNormalization
41886
+ });
41887
+ const negateBoolean = (identity) => ({
41888
+ ...identity,
41889
+ booleanNormalization: identity.booleanNormalization === "negated" ? "normalized" : "negated"
41890
+ });
41891
+ const getLivePropExpressionIdentity = (analysis, context, node, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
41892
+ const expression = stripParenExpression(node);
41893
+ if (isNodeOfType(expression, "Identifier")) {
41894
+ const reference = getRef(analysis, expression);
41895
+ const symbol = context.scopes.symbolFor(expression);
41896
+ if (!reference || !symbol) return null;
41897
+ if (isProp(analysis, reference)) return {
41898
+ propSymbolId: symbol.id,
41899
+ memberPath: [],
41900
+ booleanNormalization: "identity"
41901
+ };
41902
+ if (visitedSymbolIds.has(symbol.id) || symbol.kind !== "const") return null;
41903
+ visitedSymbolIds.add(symbol.id);
41904
+ const initializer = getDirectConstInitializer(symbol);
41905
+ if (initializer) return getLivePropExpressionIdentity(analysis, context, initializer, visitedSymbolIds);
41906
+ return getUpstreamRefs(analysis, reference).some((upstreamReference) => isProp(analysis, upstreamReference)) ? {
41907
+ propSymbolId: symbol.id,
41908
+ memberPath: [],
41909
+ booleanNormalization: "identity"
41910
+ } : null;
41911
+ }
41912
+ if (isNodeOfType(expression, "MemberExpression")) {
41913
+ const propertyName = getStaticMemberPropertyName(expression);
41914
+ if (!propertyName) return null;
41915
+ const objectIdentity = getLivePropExpressionIdentity(analysis, context, expression.object, visitedSymbolIds);
41916
+ if (!objectIdentity) return null;
41917
+ return {
41918
+ ...objectIdentity,
41919
+ memberPath: [...objectIdentity.memberPath, propertyName]
41920
+ };
41921
+ }
41922
+ if (isNodeOfType(expression, "CallExpression") && isNodeOfType(expression.callee, "Identifier") && expression.callee.name === "Boolean" && context.scopes.isGlobalReference(expression.callee) && expression.arguments?.length === 1) {
41923
+ const argument = expression.arguments[0];
41924
+ const argumentIdentity = getLivePropExpressionIdentity(analysis, context, argument, visitedSymbolIds);
41925
+ return argumentIdentity ? normalizeAsBoolean(argumentIdentity) : null;
41926
+ }
41927
+ if (isNodeOfType(expression, "UnaryExpression") && expression.operator === "!") {
41928
+ const argumentIdentity = getLivePropExpressionIdentity(analysis, context, expression.argument, visitedSymbolIds);
41929
+ return argumentIdentity ? negateBoolean(argumentIdentity) : null;
41930
+ }
41931
+ return null;
41932
+ };
41933
+ const isMountSnapshotInitializer = (context, node) => {
41934
+ if (!isReactApiCall(node, "useMemo", context.scopes, { resolveNamedAliases: true }) || !isNodeOfType(node, "CallExpression")) return false;
41935
+ const dependencies = node.arguments?.[1];
41936
+ return isNodeOfType(dependencies, "ArrayExpression") && dependencies.elements.length === 0;
41113
41937
  };
41114
- const isSetStateToInitialValue = (analysis, setterRef) => {
41938
+ const isMountSnapshotBinding = (context, identifier, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
41939
+ const symbol = context.scopes.symbolFor(identifier);
41940
+ if (!symbol || visitedSymbolIds.has(symbol.id)) return false;
41941
+ visitedSymbolIds.add(symbol.id);
41942
+ const initializer = getDirectConstInitializer(symbol);
41943
+ if (!initializer) return false;
41944
+ if (isMountSnapshotInitializer(context, initializer)) return true;
41945
+ const expression = stripParenExpression(initializer);
41946
+ return isNodeOfType(expression, "Identifier") && isMountSnapshotBinding(context, expression, visitedSymbolIds);
41947
+ };
41948
+ const isConstantBooleanExpression = (context, node, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
41949
+ const expression = stripParenExpression(node);
41950
+ if (isNodeOfType(expression, "Literal")) return true;
41951
+ if (isNodeOfType(expression, "Identifier")) {
41952
+ const symbol = context.scopes.symbolFor(expression);
41953
+ if (!symbol || visitedSymbolIds.has(symbol.id)) return false;
41954
+ visitedSymbolIds.add(symbol.id);
41955
+ const initializer = getDirectConstInitializer(symbol);
41956
+ return Boolean(initializer && isConstantBooleanExpression(context, initializer, visitedSymbolIds));
41957
+ }
41958
+ if (isNodeOfType(expression, "UnaryExpression") && expression.operator === "!") return isConstantBooleanExpression(context, expression.argument, visitedSymbolIds);
41959
+ if (isNodeOfType(expression, "CallExpression") && isNodeOfType(expression.callee, "Identifier") && expression.callee.name === "Boolean" && context.scopes.isGlobalReference(expression.callee) && expression.arguments?.length === 1) return isConstantBooleanExpression(context, expression.arguments[0], visitedSymbolIds);
41960
+ return false;
41961
+ };
41962
+ const isProvenLiveBinding = (analysis, context, identifier) => {
41963
+ const reference = getRef(analysis, identifier);
41964
+ const symbol = context.scopes.symbolFor(identifier);
41965
+ if (!reference || !symbol || symbol.kind !== "const" || isOutsideAllFunctions(symbol)) return false;
41966
+ const initializer = symbol.initializer;
41967
+ if (!initializer || isMountSnapshotBinding(context, identifier)) return false;
41968
+ if (getDownstreamRefs(analysis, initializer).some((initializerReference) => isRefCurrent(initializerReference))) return false;
41969
+ return !isConstantBooleanExpression(context, initializer);
41970
+ };
41971
+ const areSameProvenLiveBinding = (analysis, context, left, right) => {
41972
+ const leftExpression = stripParenExpression(left);
41973
+ const rightExpression = stripParenExpression(right);
41974
+ if (!isNodeOfType(leftExpression, "Identifier") || !isNodeOfType(rightExpression, "Identifier")) return false;
41975
+ const leftSymbol = context.scopes.symbolFor(leftExpression);
41976
+ const rightSymbol = context.scopes.symbolFor(rightExpression);
41977
+ return Boolean(leftSymbol && leftSymbol === rightSymbol && isProvenLiveBinding(analysis, context, leftExpression));
41978
+ };
41979
+ const haveSameLivePropExpressionIdentity = (left, right) => {
41980
+ if (left.propSymbolId !== right.propSymbolId || left.booleanNormalization !== right.booleanNormalization || left.memberPath.length !== right.memberPath.length) return false;
41981
+ return left.memberPath.every((propertyName, index) => propertyName === right.memberPath[index]);
41982
+ };
41983
+ const isSetStateToInitialValue = (analysis, context, setterRef) => {
41115
41984
  const callExpr = getCallExpr(setterRef);
41116
41985
  if (!callExpr || !isNodeOfType(callExpr, "CallExpression")) return false;
41117
41986
  const setStateToValue = callExpr.arguments?.[0];
@@ -41122,7 +41991,12 @@ const isSetStateToInitialValue = (analysis, setterRef) => {
41122
41991
  if (isUndefinedNode(setStateToValue) && isUndefinedNode(stateInitialValue)) return true;
41123
41992
  if (setStateToValue == null && stateInitialValue == null) return true;
41124
41993
  if (setStateToValue && !stateInitialValue || !setStateToValue && stateInitialValue) return false;
41125
- if (stateInitialValue && isNodeOfType(stateInitialValue, "Identifier") && stateInitialValue.name !== "undefined" && !isLiteralConstantIdentifier(analysis, stateInitialValue)) return false;
41994
+ if (stateInitialValue && setStateToValue) {
41995
+ const initialLivePropIdentity = getLivePropExpressionIdentity(analysis, context, stateInitialValue);
41996
+ const nextLivePropIdentity = getLivePropExpressionIdentity(analysis, context, setStateToValue);
41997
+ if (initialLivePropIdentity && nextLivePropIdentity && haveSameLivePropExpressionIdentity(initialLivePropIdentity, nextLivePropIdentity)) return false;
41998
+ if (areSameProvenLiveBinding(analysis, context, stateInitialValue, setStateToValue)) return false;
41999
+ }
41126
42000
  return getNodeText$1(setStateToValue) === getNodeText$1(stateInitialValue);
41127
42001
  };
41128
42002
  const countUseStates = (analysis, componentNode) => {
@@ -41131,10 +42005,10 @@ const countUseStates = (analysis, componentNode) => {
41131
42005
  for (const ref of getDownstreamRefs(analysis, componentNode)) if (isState(analysis, ref)) stateVariables.add(ref.resolved);
41132
42006
  return stateVariables.size;
41133
42007
  };
41134
- const findPropUsedToResetAllState = (analysis, effectFnRefs, depsRefs, useEffectNode, effectFn) => {
42008
+ const findPropUsedToResetAllState = (analysis, context, effectFnRefs, depsRefs, useEffectNode, effectFn) => {
41135
42009
  const stateSetterRefs = effectFnRefs.filter((ref) => isSyncStateSetterCall(analysis, ref, effectFn));
41136
42010
  if (stateSetterRefs.length === 0) return null;
41137
- if (!stateSetterRefs.every((ref) => isSetStateToInitialValue(analysis, ref))) return null;
42011
+ if (!stateSetterRefs.every((ref) => isSetStateToInitialValue(analysis, context, ref))) return null;
41138
42012
  if (stateSetterRefs.every((setterRef) => effectFnRefs.some((otherRef) => otherRef !== setterRef && otherRef.resolved === setterRef.resolved && Boolean(getCallExpr(otherRef)) && !isSyncStateSetterCall(analysis, otherRef, effectFn)))) return null;
41139
42013
  const containing = findContainingNode(analysis, useEffectNode);
41140
42014
  if (new Set(stateSetterRefs.map((setterRef) => setterRef.resolved)).size !== countUseStates(analysis, containing)) return null;
@@ -41158,7 +42032,7 @@ const noResetAllStateOnPropChange = defineRule({
41158
42032
  if (containing && isCustomHook(containing)) return;
41159
42033
  const effectFn = getEffectFn(analysis, node);
41160
42034
  if (!effectFn) return;
41161
- if (!findPropUsedToResetAllState(analysis, effectFnRefs, depsRefs, node, effectFn)) return;
42035
+ if (!findPropUsedToResetAllState(analysis, context, effectFnRefs, depsRefs, node, effectFn)) return;
41162
42036
  context.report({
41163
42037
  node,
41164
42038
  message: `Your users briefly see stale state when a prop changes because this useEffect clears all state.`
@@ -41350,7 +42224,7 @@ const isTanStackServerFnHandler = (node) => {
41350
42224
  const isInsideServerOnlyScope = (node) => {
41351
42225
  let currentNode = node.parent ?? null;
41352
42226
  while (currentNode) {
41353
- if (isFunctionLike$2(currentNode)) {
42227
+ if (isFunctionLike$1(currentNode)) {
41354
42228
  if (hasUseServerDirective(currentNode) || isTanStackServerFnHandler(currentNode)) return true;
41355
42229
  }
41356
42230
  currentNode = currentNode.parent ?? null;
@@ -42185,7 +43059,7 @@ const isEffectCallbackFunction = (functionNode) => {
42185
43059
  return isHookCall$2(parent, EFFECT_HOOK_NAMES$1) && getEffectCallback(parent) === functionNode;
42186
43060
  };
42187
43061
  const doesEffectCallbackReturnName = (effectCallback, name) => {
42188
- if (!isFunctionLike$2(effectCallback)) return false;
43062
+ if (!isFunctionLike$1(effectCallback)) return false;
42189
43063
  let isReturnedByName = false;
42190
43064
  walkInsideStatementBlocks(effectCallback.body, (child) => {
42191
43065
  if (isReturnedByName || !isNodeOfType(child, "ReturnStatement") || !child.argument) return;
@@ -42195,7 +43069,7 @@ const doesEffectCallbackReturnName = (effectCallback, name) => {
42195
43069
  return isReturnedByName;
42196
43070
  };
42197
43071
  const isFunctionReturnedFromEffectCallback = (functionNode, effectCallback) => {
42198
- if (!isFunctionLike$2(effectCallback)) return false;
43072
+ if (!isFunctionLike$1(effectCallback)) return false;
42199
43073
  if (isNodeOfType(functionNode.parent, "ReturnStatement")) return true;
42200
43074
  if (effectCallback.body === functionNode) return true;
42201
43075
  const cleanupBindingName = getFunctionBindingName$1(functionNode);
@@ -42225,7 +43099,7 @@ const isInsideEffectCleanupReturn = (node, ownerScope) => {
42225
43099
  };
42226
43100
  const hasRefCurrentReassignmentAfterClear = (clearCall, refName) => {
42227
43101
  const enclosingFunction = findEnclosingFunction$1(clearCall);
42228
- if (!isFunctionLike$2(enclosingFunction)) return false;
43102
+ if (!isFunctionLike$1(enclosingFunction)) return false;
42229
43103
  if (!isNodeOfType(enclosingFunction.body, "BlockStatement")) return false;
42230
43104
  const clearStart = getRangeStart(clearCall);
42231
43105
  if (clearStart === null) return false;
@@ -43040,7 +43914,7 @@ const isInsideAvailabilityGuard = (node, browserGlobalName, context) => {
43040
43914
  let currentNode = node;
43041
43915
  let parentNode = currentNode.parent;
43042
43916
  while (parentNode) {
43043
- if (isFunctionLike$2(parentNode) && !executesDuringRender(parentNode, context.scopes)) break;
43917
+ if (isFunctionLike$1(parentNode) && !executesDuringRender(parentNode, context.scopes)) break;
43044
43918
  if (isNodeOfType(parentNode, "LogicalExpression") && (parentNode.operator === "&&" || parentNode.operator === "||") && parentNode.right === currentNode && readAvailabilityWhenPredicate(parentNode.left, browserGlobalName, context, parentNode.operator === "&&") === true) return true;
43045
43919
  if (isNodeOfType(parentNode, "ConditionalExpression")) {
43046
43920
  if (parentNode.consequent === currentNode && readAvailabilityWhenPredicate(parentNode.test, browserGlobalName, context, true) === true || parentNode.alternate === currentNode && readAvailabilityWhenPredicate(parentNode.test, browserGlobalName, context, false) === true) return true;
@@ -43055,7 +43929,7 @@ const isInsideAvailabilityGuard = (node, browserGlobalName, context) => {
43055
43929
  };
43056
43930
  const isAfterAvailabilityEarlyExit = (node, componentOrHookNode, browserGlobalName, context) => {
43057
43931
  const enclosingFunction = findEnclosingFunction$1(node);
43058
- if (!enclosingFunction || enclosingFunction !== componentOrHookNode && !executesDuringRender(enclosingFunction, context.scopes) || !isFunctionLike$2(enclosingFunction) || !isNodeOfType(enclosingFunction.body, "BlockStatement")) return false;
43932
+ if (!enclosingFunction || enclosingFunction !== componentOrHookNode && !executesDuringRender(enclosingFunction, context.scopes) || !isFunctionLike$1(enclosingFunction) || !isNodeOfType(enclosingFunction.body, "BlockStatement")) return false;
43059
43933
  let currentNode = node;
43060
43934
  while (currentNode !== enclosingFunction) {
43061
43935
  const parentNode = currentNode.parent;
@@ -44349,7 +45223,7 @@ const isReactClassComponent = (classNode, scopes) => {
44349
45223
  const findEnclosingComponent = (node, scopes, controlFlow) => {
44350
45224
  let walker = node.parent;
44351
45225
  while (walker) {
44352
- if (isFunctionLike$2(walker)) {
45226
+ if (isFunctionLike$1(walker)) {
44353
45227
  const componentName = inferFunctionLikeName(walker);
44354
45228
  if (componentName && isReactComponentName(componentName) && functionContainsJsxOrCreateElement(walker, scopes, controlFlow)) return {
44355
45229
  component: walker,
@@ -45694,7 +46568,7 @@ const isComponentLikeFunction = (functionNode) => {
45694
46568
  const hasComponentLikeAncestorFunction = (node) => {
45695
46569
  let cursor = node.parent;
45696
46570
  while (cursor) {
45697
- if (isFunctionLike$2(cursor) && isComponentLikeFunction(cursor)) return true;
46571
+ if (isFunctionLike$1(cursor) && isComponentLikeFunction(cursor)) return true;
45698
46572
  cursor = cursor.parent ?? null;
45699
46573
  }
45700
46574
  return false;
@@ -45705,7 +46579,7 @@ const isDeclaringFunctionComponentLike = (declaringFunction) => {
45705
46579
  return hasComponentLikeAncestorFunction(declaringFunction);
45706
46580
  };
45707
46581
  const destructuresChildrenAsFirstParam = (functionNode) => {
45708
- if (!isFunctionLike$2(functionNode)) return false;
46582
+ if (!isFunctionLike$1(functionNode)) return false;
45709
46583
  const firstParam = functionNode.params[0];
45710
46584
  if (!firstParam || !isNodeOfType(firstParam, "ObjectPattern")) return false;
45711
46585
  return firstParam.properties.some((property) => isNodeOfType(property, "Property") && isNodeOfType(property.key, "Identifier") && property.key.name === "children");
@@ -45720,7 +46594,7 @@ const findChildrenDestructuringFunction = (identifier, scopes) => {
45720
46594
  }
45721
46595
  let cursor = identifier.parent;
45722
46596
  while (cursor) {
45723
- if (isFunctionLike$2(cursor)) {
46597
+ if (isFunctionLike$1(cursor)) {
45724
46598
  if (destructuresChildrenAsFirstParam(cursor)) return cursor;
45725
46599
  return null;
45726
46600
  }
@@ -47120,7 +47994,7 @@ const isListenerCollectionInitializer = (init) => {
47120
47994
  return isNodeOfType(init, "NewExpression") && isNodeOfType(init.callee, "Identifier") && init.callee.name === "Set";
47121
47995
  };
47122
47996
  const functionRegistersParameterIntoCollection = (functionNode, listenerCollectionNames) => {
47123
- if (!isFunctionLike$2(functionNode)) return false;
47997
+ if (!isFunctionLike$1(functionNode)) return false;
47124
47998
  const firstParam = functionNode.params?.[0];
47125
47999
  if (!isNodeOfType(firstParam, "Identifier")) return false;
47126
48000
  const listenerParamName = firstParam.name;
@@ -47156,7 +48030,7 @@ const buildModuleScopeStoreIndex = (programRoot) => {
47156
48030
  for (const declarator of unwrapped.declarations ?? []) {
47157
48031
  if (!isNodeOfType(declarator.id, "Identifier")) continue;
47158
48032
  const init = declarator.init ?? null;
47159
- if ((unwrapped.kind === "let" || unwrapped.kind === "var") && init && !isFunctionLike$2(init)) {
48033
+ if ((unwrapped.kind === "let" || unwrapped.kind === "var") && init && !isFunctionLike$1(init)) {
47160
48034
  mutableBindingNames.add(declarator.id.name);
47161
48035
  continue;
47162
48036
  }
@@ -47164,7 +48038,7 @@ const buildModuleScopeStoreIndex = (programRoot) => {
47164
48038
  listenerCollectionNames.add(declarator.id.name);
47165
48039
  continue;
47166
48040
  }
47167
- if (init && isFunctionLike$2(init)) moduleFunctionsByName.set(declarator.id.name, init);
48041
+ if (init && isFunctionLike$1(init)) moduleFunctionsByName.set(declarator.id.name, init);
47168
48042
  }
47169
48043
  }
47170
48044
  const subscribeFunctionNames = /* @__PURE__ */ new Set();
@@ -47177,7 +48051,7 @@ const buildModuleScopeStoreIndex = (programRoot) => {
47177
48051
  const getModuleStoreSnapshotName = (useStateCall, storeIndex) => {
47178
48052
  if (!isNodeOfType(useStateCall, "CallExpression")) return null;
47179
48053
  let initialArgument = stripParenExpression(useStateCall.arguments?.[0]);
47180
- if (initialArgument && isFunctionLike$2(initialArgument) && !isNodeOfType(initialArgument.body, "BlockStatement")) initialArgument = stripParenExpression(initialArgument.body);
48054
+ if (initialArgument && isFunctionLike$1(initialArgument) && !isNodeOfType(initialArgument.body, "BlockStatement")) initialArgument = stripParenExpression(initialArgument.body);
47181
48055
  if (!isNodeOfType(initialArgument, "Identifier")) return null;
47182
48056
  if (!storeIndex.mutableBindingNames.has(initialArgument.name)) return null;
47183
48057
  const binding = findVariableInitializer(initialArgument, initialArgument.name);
@@ -47188,7 +48062,7 @@ const argumentForwardsSetter = (argument, setterName) => {
47188
48062
  if (!argument) return false;
47189
48063
  const unwrapped = stripParenExpression(argument);
47190
48064
  if (isNodeOfType(unwrapped, "Identifier")) return unwrapped.name === setterName;
47191
- if (!isFunctionLike$2(unwrapped)) return false;
48065
+ if (!isFunctionLike$1(unwrapped)) return false;
47192
48066
  let callsSetter = false;
47193
48067
  walkAst(unwrapped.body, (child) => {
47194
48068
  if (isNodeOfType(child, "CallExpression") && isNodeOfType(child.callee, "Identifier") && child.callee.name === setterName) {
@@ -47200,7 +48074,7 @@ const argumentForwardsSetter = (argument, setterName) => {
47200
48074
  };
47201
48075
  const findModuleSubscribeCallForwardingSetter = (effectCallback, setterName, storeIndex) => {
47202
48076
  let matchedCall = null;
47203
- walkAst((isFunctionLike$2(effectCallback) ? effectCallback.body : null) ?? effectCallback, (child) => {
48077
+ walkAst((isFunctionLike$1(effectCallback) ? effectCallback.body : null) ?? effectCallback, (child) => {
47204
48078
  if (matchedCall) return false;
47205
48079
  if (!isNodeOfType(child, "CallExpression")) return;
47206
48080
  if (!isNodeOfType(child.callee, "Identifier")) return;
@@ -47304,7 +48178,7 @@ const preferUseSyncExternalStore = defineRule({
47304
48178
  if (!isNodeOfType(depsNode, "ArrayExpression")) continue;
47305
48179
  if ((depsNode.elements?.length ?? 0) !== 0) continue;
47306
48180
  const callback = getEffectCallback(effectCall);
47307
- if (!callback || !isFunctionLike$2(callback)) continue;
48181
+ if (!callback || !isFunctionLike$1(callback)) continue;
47308
48182
  for (const { binding, storeName } of snapshotBindings) {
47309
48183
  if (reportedDeclarators.has(binding.declarator)) continue;
47310
48184
  if (!findModuleSubscribeCallForwardingSetter(callback, binding.setterName, storeIndex)) continue;
@@ -47372,7 +48246,7 @@ const findLargestCoUpdatedSetterGroup = (componentBody, setterNames, initializer
47372
48246
  }
47373
48247
  if (hasDataCarryingWrite) largestGroupSize = Math.max(largestGroupSize, groupSetterNames.size);
47374
48248
  }
47375
- const enteringNestedFunction = isInsideNestedFunction || isFunctionLike$2(node);
48249
+ const enteringNestedFunction = isInsideNestedFunction || isFunctionLike$1(node);
47376
48250
  const record = node;
47377
48251
  for (const key of Object.keys(record)) {
47378
48252
  if (key === "parent" || key === "type") continue;
@@ -47827,21 +48701,21 @@ const isTanstackQueryResult = (expression, context) => Boolean(resolveTanstackQu
47827
48701
  const isStaticRefetchMember = (memberExpression) => getStaticPropertyKeyName(memberExpression, { allowComputedString: true }) === "refetch";
47828
48702
  const resolveCalledFunction = (callee, context) => {
47829
48703
  const unwrappedCallee = stripParenExpression(callee);
47830
- if (isFunctionLike$2(unwrappedCallee)) return unwrappedCallee;
48704
+ if (isFunctionLike$1(unwrappedCallee)) return unwrappedCallee;
47831
48705
  if (!isNodeOfType(unwrappedCallee, "Identifier")) return null;
47832
48706
  const symbol = resolveConstIdentifierAlias(unwrappedCallee, context.scopes);
47833
48707
  if (!symbol) return null;
47834
48708
  const candidate = symbol.kind === "function" ? symbol.declarationNode : symbol.initializer;
47835
- return candidate && isFunctionLike$2(candidate) ? candidate : null;
48709
+ return candidate && isFunctionLike$1(candidate) ? candidate : null;
47836
48710
  };
47837
48711
  const hasSuspensionBefore = (functionNode, boundary, context) => {
47838
- if (!isFunctionLike$2(functionNode)) return true;
48712
+ if (!isFunctionLike$1(functionNode)) return true;
47839
48713
  if (functionNode.generator) return true;
47840
48714
  const boundaryStart = getRangeStart(boundary);
47841
48715
  if (boundaryStart === null) return true;
47842
48716
  let hasSuspension = false;
47843
48717
  walkAst(functionNode, (node) => {
47844
- if (node !== functionNode && isFunctionLike$2(node)) return false;
48718
+ if (node !== functionNode && isFunctionLike$1(node)) return false;
47845
48719
  if (!isNodeOfType(node, "AwaitExpression") || !isNodeReachableWithinFunction(node, context)) return;
47846
48720
  const suspensionStart = getRangeStart(node);
47847
48721
  if (suspensionStart !== null && suspensionStart < boundaryStart) {
@@ -47865,7 +48739,7 @@ const functionInvokesTarget = (callerFunction, targetFunction, context, visitedF
47865
48739
  visitedFunctions.add(callerFunction);
47866
48740
  let invokesTarget = false;
47867
48741
  walkAst(callerFunction, (node) => {
47868
- if (node !== callerFunction && isFunctionLike$2(node)) return false;
48742
+ if (node !== callerFunction && isFunctionLike$1(node)) return false;
47869
48743
  if (!isNodeOfType(node, "CallExpression")) return;
47870
48744
  if (!isNodeReachableWithinFunction(node, context) || !isUnconditionallyExecuted(node, callerFunction, context) || !canCrossSuspension && hasSuspensionBefore(callerFunction, node, context)) return;
47871
48745
  const calledFunction = resolveCalledFunction(node.callee, context);
@@ -47882,7 +48756,7 @@ const isFunctionInvokedBefore = (invokedFunction, boundary, context) => {
47882
48756
  if (!boundaryFunction || boundaryStart === null) return false;
47883
48757
  let isInvokedBefore = false;
47884
48758
  walkAst(boundaryFunction, (node) => {
47885
- if (node !== boundaryFunction && isFunctionLike$2(node)) return false;
48759
+ if (node !== boundaryFunction && isFunctionLike$1(node)) return false;
47886
48760
  if (!isNodeOfType(node, "CallExpression")) return;
47887
48761
  const callStart = getRangeStart(node);
47888
48762
  if (callStart === null || callStart >= boundaryStart || !isNodeReachableWithinFunction(node, context) || !isUnconditionallyExecuted(node, boundaryFunction, context) || hasSuspensionBefore(boundaryFunction, node, context)) return;
@@ -47899,7 +48773,7 @@ const isFunctionInvokedAfter = (invokedFunction, boundary, callerFunction, conte
47899
48773
  if (boundaryStart === null) return false;
47900
48774
  let isInvokedAfter = false;
47901
48775
  walkAst(callerFunction, (node) => {
47902
- if (node !== callerFunction && isFunctionLike$2(node)) return false;
48776
+ if (node !== callerFunction && isFunctionLike$1(node)) return false;
47903
48777
  if (!isNodeOfType(node, "CallExpression")) return;
47904
48778
  const callStart = getRangeStart(node);
47905
48779
  if (callStart === null || callStart <= boundaryStart || !isNodeReachableWithinFunction(node, context) || !isUnconditionallyExecuted(node, callerFunction, context)) return;
@@ -48033,7 +48907,7 @@ const queryNoQueryInEffect = defineRule({
48033
48907
  if (!callback) return;
48034
48908
  const effectInvokedFunctions = collectEffectInvokedFunctions(callback);
48035
48909
  walkAst(callback, (child) => {
48036
- if (child !== callback && isFunctionLike$2(child) && !effectInvokedFunctions.has(child)) return false;
48910
+ if (child !== callback && isFunctionLike$1(child) && !effectInvokedFunctions.has(child)) return false;
48037
48911
  if (!isNodeOfType(child, "CallExpression")) return;
48038
48912
  if (isTanstackRefetchCall(child, context, callback)) context.report({
48039
48913
  node: child,
@@ -48623,7 +49497,7 @@ const reduxUseselectorInlineDerivation = defineRule({
48623
49497
  if (!body) return;
48624
49498
  const returnedExpressions = [];
48625
49499
  if (isNodeOfType(body, "BlockStatement")) walkAst(body, (node) => {
48626
- if (node !== body && isFunctionLike$2(node)) return false;
49500
+ if (node !== body && isFunctionLike$1(node)) return false;
48627
49501
  if (isNodeOfType(node, "ReturnStatement")) {
48628
49502
  if (node.argument) returnedExpressions.push(node.argument);
48629
49503
  return false;
@@ -48915,7 +49789,7 @@ const renderingHydrationMismatchTime = defineRule({
48915
49789
  return;
48916
49790
  }
48917
49791
  walkAst(node.expression, (child) => {
48918
- if (isFunctionLike$2(child) && !executesDuringRender(child, context.scopes)) return false;
49792
+ if (isFunctionLike$1(child) && !executesDuringRender(child, context.scopes)) return false;
48919
49793
  for (const pattern of NONDETERMINISTIC_RENDER_PATTERNS) if (pattern.matches(child)) {
48920
49794
  if (hasSuppressHydrationWarningAttribute(findOpeningElementOfChild(node))) return;
48921
49795
  if (isGatedByFalsyInitialState(child, context.scopes)) return;
@@ -49186,7 +50060,7 @@ const hasOwnAwait = (functionBody) => {
49186
50060
  let found = false;
49187
50061
  walkAst(functionBody, (child) => {
49188
50062
  if (found) return;
49189
- if (child !== functionBody && isFunctionLike$2(child)) return false;
50063
+ if (child !== functionBody && isFunctionLike$1(child)) return false;
49190
50064
  if (isNodeOfType(child, "AwaitExpression")) found = true;
49191
50065
  });
49192
50066
  return found;
@@ -49236,7 +50110,7 @@ const hasAsyncLoadingWork = (fnBody, setterName) => {
49236
50110
  return false;
49237
50111
  }
49238
50112
  if (setterName !== null && PROMISE_CHAIN_METHOD_NAMES.has(callee.property.name)) for (const argument of child.arguments ?? []) {
49239
- if (!isFunctionLike$2(argument)) continue;
50113
+ if (!isFunctionLike$1(argument)) continue;
49240
50114
  if (callsIdentifier(argument.body, setterName)) {
49241
50115
  found = true;
49242
50116
  return false;
@@ -49245,7 +50119,7 @@ const hasAsyncLoadingWork = (fnBody, setterName) => {
49245
50119
  }
49246
50120
  return;
49247
50121
  }
49248
- if (setterName !== null && isFunctionLike$2(child)) {
50122
+ if (setterName !== null && isFunctionLike$1(child)) {
49249
50123
  const functionBody = child.body;
49250
50124
  if ((Boolean(child.async) || hasOwnAwait(functionBody)) && callsIdentifier(functionBody, setterName)) {
49251
50125
  found = true;
@@ -49310,7 +50184,7 @@ const collectAsyncSignalNames = (fnBody) => {
49310
50184
  if (!isNodeOfType(child, "VariableDeclarator") || !isNodeOfType(child.id, "Identifier")) return;
49311
50185
  const init = child.init;
49312
50186
  if (!init) return;
49313
- if (isFunctionLike$2(init) && Boolean(init.async)) {
50187
+ if (isFunctionLike$1(init) && Boolean(init.async)) {
49314
50188
  names.add(child.id.name);
49315
50189
  return;
49316
50190
  }
@@ -49333,7 +50207,7 @@ const setterCalledAlongsideAsyncSignal = (fnBody, setterName) => {
49333
50207
  let found = false;
49334
50208
  walkAst(fnBody, (child) => {
49335
50209
  if (found) return false;
49336
- if (!isFunctionLike$2(child)) return;
50210
+ if (!isFunctionLike$1(child)) return;
49337
50211
  const functionBody = child.body;
49338
50212
  if (callsIdentifier(functionBody, setterName) && callsAnyIdentifier(functionBody, asyncSignalNames)) {
49339
50213
  found = true;
@@ -49350,7 +50224,7 @@ const setterCalledInEventListenerHandler = (fnBody, setterName) => {
49350
50224
  if (!isNodeOfType(child, "CallExpression") || !isNodeOfType(child.callee, "MemberExpression") || !isNodeOfType(child.callee.property, "Identifier") || child.callee.property.name !== "addEventListener") return;
49351
50225
  const handler = child.arguments?.[1];
49352
50226
  if (!handler) return;
49353
- if (isFunctionLike$2(handler)) {
50227
+ if (isFunctionLike$1(handler)) {
49354
50228
  if (callsIdentifier(handler.body, setterName)) foundInline = true;
49355
50229
  return;
49356
50230
  }
@@ -49361,7 +50235,7 @@ const setterCalledInEventListenerHandler = (fnBody, setterName) => {
49361
50235
  let foundNamed = false;
49362
50236
  walkAst(fnBody, (child) => {
49363
50237
  if (foundNamed) return false;
49364
- if (isNodeOfType(child, "VariableDeclarator") && isNodeOfType(child.id, "Identifier") && handlerNames.has(child.id.name) && child.init && isFunctionLike$2(child.init) && callsIdentifier(child.init.body, setterName)) {
50238
+ if (isNodeOfType(child, "VariableDeclarator") && isNodeOfType(child.id, "Identifier") && handlerNames.has(child.id.name) && child.init && isFunctionLike$1(child.init) && callsIdentifier(child.init.body, setterName)) {
49365
50239
  foundNamed = true;
49366
50240
  return false;
49367
50241
  }
@@ -50183,6 +51057,357 @@ const rerenderMemoBeforeEarlyReturn = defineRule({
50183
51057
  }
50184
51058
  });
50185
51059
  //#endregion
51060
+ //#region src/plugin/utils/build-same-file-memo-comparator-registry.ts
51061
+ const unwrapTopLevelDeclaration = (statement) => {
51062
+ if (isNodeOfType(statement, "ExportNamedDeclaration")) return statement.declaration;
51063
+ return statement;
51064
+ };
51065
+ const buildSameFileMemoComparatorRegistry = (program) => {
51066
+ const registry = /* @__PURE__ */ new Map();
51067
+ if (!isNodeOfType(program, "Program")) return registry;
51068
+ const memoBindings = /* @__PURE__ */ new Set();
51069
+ const reactNamespaceBindings = /* @__PURE__ */ new Set();
51070
+ for (const statement of program.body) {
51071
+ if (!isNodeOfType(statement, "ImportDeclaration") || statement.source.value !== "react") continue;
51072
+ for (const specifier of statement.specifiers) if (isNodeOfType(specifier, "ImportDefaultSpecifier") || isNodeOfType(specifier, "ImportNamespaceSpecifier")) reactNamespaceBindings.add(specifier.local.name);
51073
+ else if (isNodeOfType(specifier, "ImportSpecifier") && getImportedName(specifier) === "memo") memoBindings.add(specifier.local.name);
51074
+ }
51075
+ for (const statement of program.body) {
51076
+ const declaration = unwrapTopLevelDeclaration(statement);
51077
+ if (!declaration || !isNodeOfType(declaration, "VariableDeclaration")) continue;
51078
+ for (const declarator of declaration.declarations ?? []) {
51079
+ if (!isNodeOfType(declarator, "VariableDeclarator") || !isNodeOfType(declarator.id, "Identifier") || !declarator.init) continue;
51080
+ const initializer = stripParenExpression(declarator.init);
51081
+ if (!isNodeOfType(initializer, "CallExpression")) continue;
51082
+ const callee = stripParenExpression(initializer.callee);
51083
+ const isNamedMemo = isNodeOfType(callee, "Identifier") && memoBindings.has(callee.name);
51084
+ const isNamespaceMemo = isNodeOfType(callee, "MemberExpression") && !callee.computed && isNodeOfType(callee.object, "Identifier") && reactNamespaceBindings.has(callee.object.name) && isNodeOfType(callee.property, "Identifier") && callee.property.name === "memo";
51085
+ if (!isNamedMemo && !isNamespaceMemo) continue;
51086
+ const comparator = initializer.arguments?.[1];
51087
+ if (!comparator || isNodeOfType(comparator, "SpreadElement")) continue;
51088
+ registry.set(declarator.id.name, {
51089
+ bindingIdentifier: declarator.id,
51090
+ comparator
51091
+ });
51092
+ }
51093
+ }
51094
+ return registry;
51095
+ };
51096
+ //#endregion
51097
+ //#region src/plugin/utils/comparator-proves-empty-prop-equality.ts
51098
+ const UNKNOWN_VALUE = { kind: "unknown" };
51099
+ const TRUE_VALUE = {
51100
+ kind: "boolean",
51101
+ value: true
51102
+ };
51103
+ const FALSE_VALUE = {
51104
+ kind: "boolean",
51105
+ value: false
51106
+ };
51107
+ const UNDEFINED_VALUE = { kind: "undefined" };
51108
+ const PREVIOUS_PROPS_VALUE = { kind: "previous-props" };
51109
+ const NEXT_PROPS_VALUE = { kind: "next-props" };
51110
+ const OBJECT_PROTOTYPE_PROPERTY_NAMES = new Set([
51111
+ "__defineGetter__",
51112
+ "__defineSetter__",
51113
+ "__lookupGetter__",
51114
+ "__lookupSetter__",
51115
+ "__proto__",
51116
+ "constructor",
51117
+ "hasOwnProperty",
51118
+ "isPrototypeOf",
51119
+ "propertyIsEnumerable",
51120
+ "toLocaleString",
51121
+ "toString",
51122
+ "valueOf"
51123
+ ]);
51124
+ const PROVABLY_CALLABLE_GLOBAL_NAMES = new Set([
51125
+ "Boolean",
51126
+ "Number",
51127
+ "String"
51128
+ ]);
51129
+ const booleanValue = (value) => value ? TRUE_VALUE : FALSE_VALUE;
51130
+ const constantBooleanFormula = (value) => ({
51131
+ kind: "constant",
51132
+ value
51133
+ });
51134
+ const getBooleanFormula = (value) => {
51135
+ if (value.kind === "boolean") return constantBooleanFormula(value.value === true);
51136
+ return value.kind === "boolean-formula" && value.formula ? value.formula : null;
51137
+ };
51138
+ const booleanFormulaValue = (formula) => formula.kind === "constant" ? booleanValue(formula.value === true) : {
51139
+ kind: "boolean-formula",
51140
+ formula
51141
+ };
51142
+ const negateBooleanFormula = (formula) => {
51143
+ if (formula.kind === "constant") return constantBooleanFormula(formula.value !== true);
51144
+ if (formula.kind === "not" && formula.operand) return formula.operand;
51145
+ return {
51146
+ kind: "not",
51147
+ operand: formula
51148
+ };
51149
+ };
51150
+ const combineBooleanFormulas = (operator, left, right) => {
51151
+ if (left.kind === "constant") {
51152
+ if (operator === "and") return left.value === true ? right : left;
51153
+ return left.value === true ? left : right;
51154
+ }
51155
+ if (right.kind === "constant") {
51156
+ if (operator === "and") return right.value === true ? left : right;
51157
+ return right.value === true ? right : left;
51158
+ }
51159
+ return {
51160
+ kind: operator,
51161
+ left,
51162
+ right
51163
+ };
51164
+ };
51165
+ const conditionalBooleanFormula = (test, consequent, alternate) => {
51166
+ if (test.kind === "constant") return test.value === true ? consequent : alternate;
51167
+ return {
51168
+ kind: "conditional",
51169
+ test,
51170
+ consequent,
51171
+ alternate
51172
+ };
51173
+ };
51174
+ const collectBooleanFormulaAtomKeys = (formula, atomKeys) => {
51175
+ if (formula.kind === "atom") {
51176
+ if (formula.atomKey) atomKeys.add(formula.atomKey);
51177
+ return;
51178
+ }
51179
+ if (formula.operand) collectBooleanFormulaAtomKeys(formula.operand, atomKeys);
51180
+ if (formula.left) collectBooleanFormulaAtomKeys(formula.left, atomKeys);
51181
+ if (formula.right) collectBooleanFormulaAtomKeys(formula.right, atomKeys);
51182
+ if (formula.test) collectBooleanFormulaAtomKeys(formula.test, atomKeys);
51183
+ if (formula.consequent) collectBooleanFormulaAtomKeys(formula.consequent, atomKeys);
51184
+ if (formula.alternate) collectBooleanFormulaAtomKeys(formula.alternate, atomKeys);
51185
+ };
51186
+ const evaluateBooleanFormula = (formula, atomValues) => {
51187
+ if (formula.kind === "constant") return formula.value ?? null;
51188
+ if (formula.kind === "atom") return formula.atomKey ? atomValues.get(formula.atomKey) ?? null : null;
51189
+ if (formula.kind === "not") {
51190
+ const operand = formula.operand ? evaluateBooleanFormula(formula.operand, atomValues) : null;
51191
+ return operand === null ? null : !operand;
51192
+ }
51193
+ if (formula.kind === "and" || formula.kind === "or") {
51194
+ const left = formula.left ? evaluateBooleanFormula(formula.left, atomValues) : null;
51195
+ const right = formula.right ? evaluateBooleanFormula(formula.right, atomValues) : null;
51196
+ if (left === null || right === null) return null;
51197
+ return formula.kind === "and" ? left && right : left || right;
51198
+ }
51199
+ const test = formula.test ? evaluateBooleanFormula(formula.test, atomValues) : null;
51200
+ if (test === null) return null;
51201
+ const branch = test ? formula.consequent : formula.alternate;
51202
+ return branch ? evaluateBooleanFormula(branch, atomValues) : null;
51203
+ };
51204
+ const couldStableTargetReferencePreventRender = (distinctReferenceFormula, sharedReferenceFormula) => {
51205
+ const atomKeys = /* @__PURE__ */ new Set();
51206
+ collectBooleanFormulaAtomKeys(distinctReferenceFormula, atomKeys);
51207
+ collectBooleanFormulaAtomKeys(sharedReferenceFormula, atomKeys);
51208
+ if (atomKeys.size > 8) return true;
51209
+ const orderedAtomKeys = [...atomKeys];
51210
+ const assignmentCount = 2 ** orderedAtomKeys.length;
51211
+ for (let assignmentIndex = 0; assignmentIndex < assignmentCount; assignmentIndex += 1) {
51212
+ const atomValues = /* @__PURE__ */ new Map();
51213
+ for (const [atomIndex, atomKey] of orderedAtomKeys.entries()) atomValues.set(atomKey, Boolean(assignmentIndex & 1 << atomIndex));
51214
+ const distinctReferenceResult = evaluateBooleanFormula(distinctReferenceFormula, atomValues);
51215
+ const sharedReferenceResult = evaluateBooleanFormula(sharedReferenceFormula, atomValues);
51216
+ if (distinctReferenceResult === null || sharedReferenceResult === null) return true;
51217
+ if (!distinctReferenceResult && sharedReferenceResult) return true;
51218
+ }
51219
+ return false;
51220
+ };
51221
+ const emptyReferenceValue = (kind, referenceOrigin) => ({
51222
+ kind,
51223
+ referenceOrigin
51224
+ });
51225
+ const evaluateEquality = (left, right, emptyReferencesAreEqual, equalityKind) => {
51226
+ if (left.kind === "unknown" || right.kind === "unknown") return UNKNOWN_VALUE;
51227
+ const leftBooleanFormula = getBooleanFormula(left);
51228
+ const rightBooleanFormula = getBooleanFormula(right);
51229
+ if (leftBooleanFormula || rightBooleanFormula) {
51230
+ if (!leftBooleanFormula || !rightBooleanFormula) return UNKNOWN_VALUE;
51231
+ return booleanFormulaValue(combineBooleanFormulas("or", combineBooleanFormulas("and", leftBooleanFormula, rightBooleanFormula), combineBooleanFormulas("and", negateBooleanFormula(leftBooleanFormula), negateBooleanFormula(rightBooleanFormula))));
51232
+ }
51233
+ if (left.kind === "prop-symbol" || right.kind === "prop-symbol") {
51234
+ if (left.kind !== "prop-symbol" || right.kind !== "prop-symbol") return UNKNOWN_VALUE;
51235
+ if (left.propOwner === right.propOwner && left.value === right.value) return TRUE_VALUE;
51236
+ if (left.propOwner === right.propOwner || left.value !== right.value) return UNKNOWN_VALUE;
51237
+ return booleanFormulaValue({
51238
+ kind: "atom",
51239
+ atomKey: `${equalityKind}:${String(left.value)}`
51240
+ });
51241
+ }
51242
+ if (left.kind === "empty-array" || left.kind === "empty-object") {
51243
+ if (left.kind !== right.kind) return FALSE_VALUE;
51244
+ if (left.referenceOrigin === right.referenceOrigin) return TRUE_VALUE;
51245
+ return booleanValue((left.referenceOrigin === "previous-target" && right.referenceOrigin === "next-target" || left.referenceOrigin === "next-target" && right.referenceOrigin === "previous-target") && emptyReferencesAreEqual);
51246
+ }
51247
+ if (right.kind === "empty-array" || right.kind === "empty-object") return FALSE_VALUE;
51248
+ if (left.kind !== right.kind) return FALSE_VALUE;
51249
+ if (left.kind === "previous-props" || left.kind === "next-props") return UNKNOWN_VALUE;
51250
+ if (left.kind === "symbol" && left.value !== right.value) return UNKNOWN_VALUE;
51251
+ return booleanValue(left.value === right.value);
51252
+ };
51253
+ const getReturnedExpression = (functionNode) => {
51254
+ if (!isFunctionLike$1(functionNode)) return null;
51255
+ if (isNodeOfType(functionNode, "ArrowFunctionExpression")) {
51256
+ const body = functionNode.body;
51257
+ if (!isNodeOfType(body, "BlockStatement")) return body;
51258
+ }
51259
+ const body = functionNode.body;
51260
+ if (!isNodeOfType(body, "BlockStatement") || body.body.length !== 1) return null;
51261
+ const returnStatement = body.body[0];
51262
+ return isNodeOfType(returnStatement, "ReturnStatement") && returnStatement.argument ? returnStatement.argument : null;
51263
+ };
51264
+ const isProvablyCallable = (expression, state) => {
51265
+ const node = stripParenExpression(expression);
51266
+ if (isFunctionLike$1(node)) return true;
51267
+ if (isNodeOfType(node, "Identifier") && PROVABLY_CALLABLE_GLOBAL_NAMES.has(node.name) && state.scopes.isGlobalReference(node)) return true;
51268
+ return isFunctionLike$1(resolveExactLocalFunction(node, state.scopes));
51269
+ };
51270
+ const evaluateExpression = (expression, state) => {
51271
+ const node = stripParenExpression(expression);
51272
+ if (isNodeOfType(node, "Literal")) {
51273
+ if (typeof node.value === "boolean") return booleanValue(node.value);
51274
+ if (typeof node.value === "number") return {
51275
+ kind: "number",
51276
+ value: node.value
51277
+ };
51278
+ if (typeof node.value === "string") return {
51279
+ kind: "string",
51280
+ value: node.value
51281
+ };
51282
+ return node.value === void 0 ? UNDEFINED_VALUE : UNKNOWN_VALUE;
51283
+ }
51284
+ if (isNodeOfType(node, "Identifier")) {
51285
+ if (node.name === "undefined" && state.scopes.isGlobalReference(node)) return UNDEFINED_VALUE;
51286
+ return state.bindings.get(node.name) ?? UNKNOWN_VALUE;
51287
+ }
51288
+ if (isNodeOfType(node, "MemberExpression")) {
51289
+ const objectValue = evaluateExpression(node.object, state);
51290
+ if ((objectValue.kind === "empty-array" || objectValue.kind === "empty-object") && node.computed && isNodeOfType(node.property, "Literal") && (typeof node.property.value === "number" || typeof node.property.value === "string" && /^\d+$/.test(node.property.value))) return UNDEFINED_VALUE;
51291
+ const propertyName = getStaticPropertyName(node);
51292
+ if (propertyName === null) return UNKNOWN_VALUE;
51293
+ if (objectValue.kind === "previous-props" || objectValue.kind === "next-props") {
51294
+ if (propertyName === state.propName) {
51295
+ const referenceOrigin = objectValue.kind === "previous-props" ? "previous-target" : "next-target";
51296
+ return emptyReferenceValue(state.emptyLiteralKind === "array" ? "empty-array" : "empty-object", referenceOrigin);
51297
+ }
51298
+ return {
51299
+ kind: "prop-symbol",
51300
+ propOwner: objectValue.kind === "previous-props" ? "previous" : "next",
51301
+ value: propertyName
51302
+ };
51303
+ }
51304
+ if (objectValue.kind === "empty-array" && propertyName === "length") return {
51305
+ kind: "number",
51306
+ value: 0
51307
+ };
51308
+ if (objectValue.kind === "empty-object" && !OBJECT_PROTOTYPE_PROPERTY_NAMES.has(propertyName)) return UNDEFINED_VALUE;
51309
+ return UNKNOWN_VALUE;
51310
+ }
51311
+ if (isNodeOfType(node, "UnaryExpression") && node.operator === "!") {
51312
+ const argumentFormula = getBooleanFormula(evaluateExpression(node.argument, state));
51313
+ return argumentFormula ? booleanFormulaValue(negateBooleanFormula(argumentFormula)) : UNKNOWN_VALUE;
51314
+ }
51315
+ if (isNodeOfType(node, "LogicalExpression")) {
51316
+ const leftFormula = getBooleanFormula(evaluateExpression(node.left, state));
51317
+ if (!leftFormula) return UNKNOWN_VALUE;
51318
+ if (node.operator === "&&") {
51319
+ if (leftFormula.kind === "constant" && leftFormula.value === false) return FALSE_VALUE;
51320
+ const rightFormula = getBooleanFormula(evaluateExpression(node.right, state));
51321
+ return rightFormula ? booleanFormulaValue(combineBooleanFormulas("and", leftFormula, rightFormula)) : UNKNOWN_VALUE;
51322
+ }
51323
+ if (node.operator === "||") {
51324
+ if (leftFormula.kind === "constant" && leftFormula.value === true) return TRUE_VALUE;
51325
+ const rightFormula = getBooleanFormula(evaluateExpression(node.right, state));
51326
+ return rightFormula ? booleanFormulaValue(combineBooleanFormulas("or", leftFormula, rightFormula)) : UNKNOWN_VALUE;
51327
+ }
51328
+ return UNKNOWN_VALUE;
51329
+ }
51330
+ if (isNodeOfType(node, "BinaryExpression")) {
51331
+ const left = evaluateExpression(node.left, state);
51332
+ const right = evaluateExpression(node.right, state);
51333
+ if ([
51334
+ "===",
51335
+ "==",
51336
+ "!==",
51337
+ "!="
51338
+ ].includes(node.operator)) {
51339
+ const equality = evaluateEquality(left, right, state.emptyReferencesAreEqual, node.operator === "===" || node.operator === "!==" ? "strict" : "loose");
51340
+ if (node.operator === "===" || node.operator === "==") return equality;
51341
+ const equalityFormula = getBooleanFormula(equality);
51342
+ return equalityFormula ? booleanFormulaValue(negateBooleanFormula(equalityFormula)) : UNKNOWN_VALUE;
51343
+ }
51344
+ if (left.kind !== "number" || right.kind !== "number") return UNKNOWN_VALUE;
51345
+ if (node.operator === "<") return booleanValue(Number(left.value) < Number(right.value));
51346
+ if (node.operator === "<=") return booleanValue(Number(left.value) <= Number(right.value));
51347
+ if (node.operator === ">") return booleanValue(Number(left.value) > Number(right.value));
51348
+ if (node.operator === ">=") return booleanValue(Number(left.value) >= Number(right.value));
51349
+ return UNKNOWN_VALUE;
51350
+ }
51351
+ if (isNodeOfType(node, "ConditionalExpression")) {
51352
+ const testFormula = getBooleanFormula(evaluateExpression(node.test, state));
51353
+ if (!testFormula) return UNKNOWN_VALUE;
51354
+ if (testFormula.kind === "constant") return evaluateExpression(testFormula.value === true ? node.consequent : node.alternate, state);
51355
+ const consequentFormula = getBooleanFormula(evaluateExpression(node.consequent, state));
51356
+ const alternateFormula = getBooleanFormula(evaluateExpression(node.alternate, state));
51357
+ return consequentFormula && alternateFormula ? booleanFormulaValue(conditionalBooleanFormula(testFormula, consequentFormula, alternateFormula)) : UNKNOWN_VALUE;
51358
+ }
51359
+ if (!isNodeOfType(node, "CallExpression")) return UNKNOWN_VALUE;
51360
+ const callee = stripParenExpression(node.callee);
51361
+ if (isNodeOfType(callee, "MemberExpression")) {
51362
+ const receiver = evaluateExpression(callee.object, state);
51363
+ const methodName = getStaticPropertyName(callee);
51364
+ const callback = node.arguments[0];
51365
+ if (receiver.kind === "empty-array" && (methodName === "every" || methodName === "some") && callback && !isNodeOfType(callback, "SpreadElement") && isProvablyCallable(callback, state)) return methodName === "every" ? TRUE_VALUE : FALSE_VALUE;
51366
+ if (isNodeOfType(callee.object, "Identifier") && callee.object.name === "Object" && state.scopes.isGlobalReference(callee.object) && (methodName === "keys" || methodName === "values") && node.arguments.length === 1 && !isNodeOfType(node.arguments[0], "SpreadElement")) {
51367
+ if (evaluateExpression(node.arguments[0], state).kind === "empty-object") return emptyReferenceValue("empty-array", node);
51368
+ }
51369
+ return UNKNOWN_VALUE;
51370
+ }
51371
+ if (!isNodeOfType(callee, "Identifier")) return UNKNOWN_VALUE;
51372
+ const localFunction = resolveExactLocalFunction(callee, state.scopes);
51373
+ if (!isFunctionLike$1(localFunction) || localFunction.async || localFunction.generator || state.activeFunctions.has(localFunction)) return UNKNOWN_VALUE;
51374
+ const returnedExpression = getReturnedExpression(localFunction);
51375
+ if (!returnedExpression) return UNKNOWN_VALUE;
51376
+ const parameters = localFunction.params ?? [];
51377
+ if (parameters.length !== node.arguments.length) return UNKNOWN_VALUE;
51378
+ const bindings = new Map(state.bindings);
51379
+ for (const [parameterIndex, parameter] of parameters.entries()) {
51380
+ const argument = node.arguments[parameterIndex];
51381
+ if (!isNodeOfType(parameter, "Identifier") || !argument || isNodeOfType(argument, "SpreadElement")) return UNKNOWN_VALUE;
51382
+ bindings.set(parameter.name, evaluateExpression(argument, state));
51383
+ }
51384
+ return evaluateExpression(returnedExpression, {
51385
+ ...state,
51386
+ activeFunctions: new Set([...state.activeFunctions, localFunction]),
51387
+ bindings
51388
+ });
51389
+ };
51390
+ const comparatorProvesEmptyPropDoesNotBreakMemo = (comparatorExpression, propName, emptyLiteralKind, scopes) => {
51391
+ const comparator = resolveExactLocalFunction(comparatorExpression, scopes);
51392
+ if (!isFunctionLike$1(comparator) || comparator.async || comparator.generator) return false;
51393
+ const returnedExpression = getReturnedExpression(comparator);
51394
+ if (!returnedExpression) return false;
51395
+ const parameters = comparator.params ?? [];
51396
+ if (parameters.length !== 2 || !isNodeOfType(parameters[0], "Identifier") || !isNodeOfType(parameters[1], "Identifier")) return false;
51397
+ const bindings = new Map([[parameters[0].name, PREVIOUS_PROPS_VALUE], [parameters[1].name, NEXT_PROPS_VALUE]]);
51398
+ const evaluateComparator = (emptyReferencesAreEqual) => evaluateExpression(returnedExpression, {
51399
+ activeFunctions: new Set([comparator]),
51400
+ bindings,
51401
+ emptyLiteralKind,
51402
+ emptyReferencesAreEqual,
51403
+ propName,
51404
+ scopes
51405
+ });
51406
+ const distinctReferenceFormula = getBooleanFormula(evaluateComparator(false));
51407
+ const sharedReferenceFormula = getBooleanFormula(evaluateComparator(true));
51408
+ return Boolean(distinctReferenceFormula && sharedReferenceFormula && !couldStableTargetReferencePreventRender(distinctReferenceFormula, sharedReferenceFormula));
51409
+ };
51410
+ //#endregion
50186
51411
  //#region src/plugin/rules/performance/rerender-memo-with-default-value.ts
50187
51412
  const DEP_TAKING_HOOK_NAMES = new Set([
50188
51413
  ...HOOKS_WITH_DEPS,
@@ -50260,7 +51485,7 @@ const markCandidateIdentifier = (expression, candidateNames, shadowedNames, use,
50260
51485
  if (!candidateNames.has(stripped.name)) return;
50261
51486
  if (!into.has(stripped.name)) into.set(stripped.name, use);
50262
51487
  };
50263
- const collectIdentitySensitiveUses = (node, candidateNames, shadowedNames, memoRegistry, into) => {
51488
+ const collectIdentitySensitiveUses = (node, candidateNames, shadowedNames, memoRegistry, memoComparatorRegistry, defaultedBindings, context, into) => {
50264
51489
  let innerShadowedNames = shadowedNames;
50265
51490
  if (isNodeOfType(node, "FunctionDeclaration") || isNodeOfType(node, "FunctionExpression") || isNodeOfType(node, "ArrowFunctionExpression")) {
50266
51491
  const parameterNames = /* @__PURE__ */ new Set();
@@ -50275,12 +51500,21 @@ const collectIdentitySensitiveUses = (node, candidateNames, shadowedNames, memoR
50275
51500
  if (isNodeOfType(node, "JSXOpeningElement")) {
50276
51501
  const openingName = node.name;
50277
51502
  const memoStatus = memoStatusForJsxOpeningName(memoRegistry, openingName);
50278
- if (!isIntrinsicJsxElementName(openingName) && memoStatus !== "not-memoised") for (const attribute of node.attributes ?? []) {
50279
- if (!isNodeOfType(attribute, "JSXAttribute")) continue;
50280
- if (!attribute.value || !isNodeOfType(attribute.value, "JSXExpressionContainer")) continue;
50281
- const attributeExpression = attribute.value.expression;
50282
- if (!attributeExpression || attributeExpression.type === "JSXEmptyExpression") continue;
50283
- markCandidateIdentifier(attributeExpression, candidateNames, innerShadowedNames, "memoized-prop", into);
51503
+ if (!isIntrinsicJsxElementName(openingName) && memoStatus !== "not-memoised") {
51504
+ const comparatorDescriptor = isNodeOfType(openingName, "JSXIdentifier") ? memoComparatorRegistry.get(openingName.name) : void 0;
51505
+ const comparator = comparatorDescriptor && context.scopes.symbolFor(openingName)?.bindingIdentifier === comparatorDescriptor.bindingIdentifier ? comparatorDescriptor.comparator : void 0;
51506
+ for (const attribute of node.attributes ?? []) {
51507
+ if (!isNodeOfType(attribute, "JSXAttribute")) continue;
51508
+ if (!attribute.value || !isNodeOfType(attribute.value, "JSXExpressionContainer")) continue;
51509
+ const attributeExpression = attribute.value.expression;
51510
+ if (!attributeExpression || attributeExpression.type === "JSXEmptyExpression") continue;
51511
+ const strippedAttributeExpression = stripParenExpression(attributeExpression);
51512
+ if (comparator && isNodeOfType(attribute.name, "JSXIdentifier") && isNodeOfType(strippedAttributeExpression, "Identifier") && !innerShadowedNames.has(strippedAttributeExpression.name)) {
51513
+ const binding = defaultedBindings.get(strippedAttributeExpression.name);
51514
+ if (binding && comparatorProvesEmptyPropDoesNotBreakMemo(comparator, attribute.name.name, binding.literalKind, context.scopes)) continue;
51515
+ }
51516
+ markCandidateIdentifier(attributeExpression, candidateNames, innerShadowedNames, "memoized-prop", into);
51517
+ }
50284
51518
  }
50285
51519
  }
50286
51520
  const nodeRecord = node;
@@ -50288,8 +51522,8 @@ const collectIdentitySensitiveUses = (node, candidateNames, shadowedNames, memoR
50288
51522
  if (key === "parent") continue;
50289
51523
  const child = nodeRecord[key];
50290
51524
  if (Array.isArray(child)) {
50291
- for (const item of child) if (isAstNode(item)) collectIdentitySensitiveUses(item, candidateNames, innerShadowedNames, memoRegistry, into);
50292
- } else if (isAstNode(child)) collectIdentitySensitiveUses(child, candidateNames, innerShadowedNames, memoRegistry, into);
51525
+ for (const item of child) if (isAstNode(item)) collectIdentitySensitiveUses(item, candidateNames, innerShadowedNames, memoRegistry, memoComparatorRegistry, defaultedBindings, context, into);
51526
+ } else if (isAstNode(child)) collectIdentitySensitiveUses(child, candidateNames, innerShadowedNames, memoRegistry, memoComparatorRegistry, defaultedBindings, context, into);
50293
51527
  }
50294
51528
  };
50295
51529
  const buildMessage$2 = (literalKind, use) => {
@@ -50306,13 +51540,14 @@ const rerenderMemoWithDefaultValue = defineRule({
50306
51540
  recommendation: "Move it to the top of the file: `const EMPTY_ITEMS: Item[] = []`, then use that as the default value",
50307
51541
  create: (context) => {
50308
51542
  let memoRegistry = /* @__PURE__ */ new Map();
51543
+ let memoComparatorRegistry = /* @__PURE__ */ new Map();
50309
51544
  const checkComponentFunction = (functionNode) => {
50310
51545
  if (!isNodeOfType(functionNode, "FunctionDeclaration") && !isNodeOfType(functionNode, "FunctionExpression") && !isNodeOfType(functionNode, "ArrowFunctionExpression")) return;
50311
51546
  const defaultedBindings = collectDefaultedEmptyBindings(functionNode);
50312
51547
  if (defaultedBindings.size === 0) return;
50313
51548
  if (!functionNode.body) return;
50314
51549
  const identitySensitiveUses = /* @__PURE__ */ new Map();
50315
- collectIdentitySensitiveUses(functionNode.body, new Set(defaultedBindings.keys()), /* @__PURE__ */ new Set(), memoRegistry, identitySensitiveUses);
51550
+ collectIdentitySensitiveUses(functionNode.body, new Set(defaultedBindings.keys()), /* @__PURE__ */ new Set(), memoRegistry, memoComparatorRegistry, defaultedBindings, context, identitySensitiveUses);
50316
51551
  for (const [bindingName, binding] of defaultedBindings) {
50317
51552
  const use = identitySensitiveUses.get(bindingName);
50318
51553
  if (!use) continue;
@@ -50325,6 +51560,17 @@ const rerenderMemoWithDefaultValue = defineRule({
50325
51560
  return {
50326
51561
  Program(node) {
50327
51562
  memoRegistry = buildSameFileMemoRegistry(node);
51563
+ memoComparatorRegistry = buildSameFileMemoComparatorRegistry(node);
51564
+ },
51565
+ CallExpression(node) {
51566
+ for (const finding of findForwardedFreshHookDependencies(node, context)) {
51567
+ if (finding.origin !== "default") continue;
51568
+ if (finding.kind !== "array" && finding.kind !== "object") continue;
51569
+ context.report({
51570
+ node: finding.reportNode,
51571
+ message: `This custom Hook default creates a new ${finding.kind} every render and forwards it to a Hook dependency.`
51572
+ });
51573
+ }
50328
51574
  },
50329
51575
  FunctionDeclaration(node) {
50330
51576
  if (!node.id?.name || !isUppercaseName(node.id.name)) return;
@@ -50414,7 +51660,7 @@ const isSetterCalledDuringRender = (root, setterName) => {
50414
51660
  let found = false;
50415
51661
  walkAst(root, (child) => {
50416
51662
  if (found) return false;
50417
- if (child !== root && isFunctionLike$2(child)) return false;
51663
+ if (child !== root && isFunctionLike$1(child)) return false;
50418
51664
  if (isNodeOfType(child, "CallExpression") && isNodeOfType(child.callee, "Identifier") && child.callee.name === setterName) {
50419
51665
  found = true;
50420
51666
  return false;
@@ -50454,7 +51700,7 @@ const collectEffectDependencyInfos = (componentBody, setterNames) => {
50454
51700
  const effectCallback = child.arguments?.[0];
50455
51701
  if (isNodeOfType(effectCallback, "ArrowFunctionExpression") || isNodeOfType(effectCallback, "FunctionExpression")) {
50456
51702
  walkAst(effectCallback.body, (bodyNode) => {
50457
- if (bodyNode !== effectCallback.body && isFunctionLike$2(bodyNode)) return false;
51703
+ if (bodyNode !== effectCallback.body && isFunctionLike$1(bodyNode)) return false;
50458
51704
  if (isNodeOfType(bodyNode, "CallExpression") && isNodeOfType(bodyNode.callee, "Identifier")) synchronouslyCalledFunctionNames.add(bodyNode.callee.name);
50459
51705
  });
50460
51706
  walkAst(effectCallback.body, (bodyNode) => {
@@ -50462,7 +51708,7 @@ const collectEffectDependencyInfos = (componentBody, setterNames) => {
50462
51708
  if (!isNodeOfType(bodyNode.callee, "Identifier")) return;
50463
51709
  let ancestor = bodyNode.parent;
50464
51710
  while (ancestor && ancestor !== effectCallback.body) {
50465
- if (isFunctionLike$2(ancestor)) {
51711
+ if (isFunctionLike$1(ancestor)) {
50466
51712
  nestedCallbackCalledFunctionNames.add(bodyNode.callee.name);
50467
51713
  return;
50468
51714
  }
@@ -50523,7 +51769,7 @@ const hasRenderPhaseNonHookCall = (componentBody) => {
50523
51769
  let didFindRenderPhaseCall = false;
50524
51770
  walkAst(componentBody, (child) => {
50525
51771
  if (didFindRenderPhaseCall) return false;
50526
- if (child !== componentBody && isFunctionLike$2(child)) return false;
51772
+ if (child !== componentBody && isFunctionLike$1(child)) return false;
50527
51773
  if (!isNodeOfType(child, "CallExpression")) return;
50528
51774
  const calleeName = isNodeOfType(child.callee, "Identifier") ? child.callee.name : isNodeOfType(child.callee, "MemberExpression") && isNodeOfType(child.callee.property, "Identifier") ? child.callee.property.name : null;
50529
51775
  if (calleeName !== null && isReactHookName(calleeName)) return;
@@ -52627,7 +53873,7 @@ const isReduceBuildingJsxRows = (node) => {
52627
53873
  if (!isNodeOfType(node.callee, "MemberExpression")) return false;
52628
53874
  if (!isNodeOfType(node.callee.property, "Identifier") || node.callee.property.name !== "reduce") return false;
52629
53875
  const rowBuilder = node.arguments?.[0];
52630
- if (!rowBuilder || !isFunctionLike$2(rowBuilder)) return false;
53876
+ if (!rowBuilder || !isFunctionLike$1(rowBuilder)) return false;
52631
53877
  let buildsJsx = false;
52632
53878
  walkAst(rowBuilder, (child) => {
52633
53879
  if (isNodeOfType(child, "JSXElement")) buildsJsx = true;
@@ -56852,7 +58098,7 @@ const countOwnScopeHookCalls = (functionNode, scopes, settings, countedFunctionN
56852
58098
  let count = 0;
56853
58099
  walkAst(functionNode, (child) => {
56854
58100
  if (child === functionNode) return;
56855
- if (isFunctionLike$2(child)) return false;
58101
+ if (isFunctionLike$1(child)) return false;
56856
58102
  if (!isHookCall$1(child, scopes, settings)) return;
56857
58103
  if (isNodeOfType(child, "CallExpression") && isLocalNonHookFunctionCallee(child, scopes, settings, countedFunctionNodes)) return;
56858
58104
  count += 1;
@@ -56866,7 +58112,7 @@ const isLocalNonHookFunctionCallee = (call, scopes, settings, countedFunctionNod
56866
58112
  if (!isNodeOfType(callee, "Identifier")) return false;
56867
58113
  const symbol = scopes.symbolFor(callee);
56868
58114
  if (!symbol) return false;
56869
- const localFunction = symbol.initializer && isFunctionLike$2(symbol.initializer) ? symbol.initializer : null;
58115
+ const localFunction = symbol.initializer && isFunctionLike$1(symbol.initializer) ? symbol.initializer : null;
56870
58116
  if (!localFunction) return false;
56871
58117
  return countOwnScopeHookCalls(localFunction, scopes, settings, countedFunctionNodes) === 0;
56872
58118
  };
@@ -56941,7 +58187,7 @@ const isInsideLoop = (descendant, ancestor) => {
56941
58187
  const findEnclosingComponentOrHookFunction = (node) => {
56942
58188
  let current = node.parent;
56943
58189
  while (current) {
56944
- if (isFunctionLike$2(current)) {
58190
+ if (isFunctionLike$1(current)) {
56945
58191
  if (isReactHocCallbackArgument(current)) return current;
56946
58192
  const resolvedName = inferFunctionName(current);
56947
58193
  if (resolvedName !== null && isComponentOrHookDisplayName(resolvedName, current)) return current;
@@ -56963,7 +58209,7 @@ const isCallbackArgumentForAllowedEffectEventHook = (functionNode, additionalEff
56963
58209
  const isInsideAllowedEffectEventCallback = (node, additionalEffectHooksRegex) => {
56964
58210
  let current = node.parent;
56965
58211
  while (current) {
56966
- if (isFunctionLike$2(current) && isCallbackArgumentForAllowedEffectEventHook(current, additionalEffectHooksRegex)) return true;
58212
+ if (isFunctionLike$1(current) && isCallbackArgumentForAllowedEffectEventHook(current, additionalEffectHooksRegex)) return true;
56967
58213
  current = current.parent ?? null;
56968
58214
  }
56969
58215
  return false;
@@ -57379,7 +58625,7 @@ const isNonPrivilegedServerAction = (functionNode) => {
57379
58625
  let hasPrivilegedEffect = false;
57380
58626
  walkAst(functionBody, (child) => {
57381
58627
  if (hasPrivilegedEffect) return false;
57382
- if (child !== functionBody && isFunctionLike$2(child)) return false;
58628
+ if (child !== functionBody && isFunctionLike$1(child)) return false;
57383
58629
  if (isCacheOrNavigationCall(child)) {
57384
58630
  hasNonDataEffectCall = true;
57385
58631
  return;
@@ -57451,7 +58697,7 @@ const containsAuthCheck = (rootNodes, allowedFunctionNames, genericMethodNames)
57451
58697
  let foundAuthCall = false;
57452
58698
  for (const rootNode of rootNodes) walkAst(rootNode, (child) => {
57453
58699
  if (foundAuthCall) return;
57454
- if (isFunctionLike$2(child)) return false;
58700
+ if (isFunctionLike$1(child)) return false;
57455
58701
  if (!isNodeOfType(child, "CallExpression")) return;
57456
58702
  if (getAuthCallName(child, allowedFunctionNames, genericMethodNames)) foundAuthCall = true;
57457
58703
  });
@@ -57902,7 +59148,7 @@ const serverHoistStaticIo = defineRule({
57902
59148
  ExportDefaultDeclaration(node) {
57903
59149
  if (!isInProjectDirectory(context, "pages/api")) return;
57904
59150
  const declaration = node.declaration;
57905
- if (!isFunctionLike$2(declaration)) return;
59151
+ if (!isFunctionLike$1(declaration)) return;
57906
59152
  if (!declaration.async) return;
57907
59153
  const body = declaration.body;
57908
59154
  if (!isNodeOfType(body, "BlockStatement")) return;
@@ -58085,7 +59331,7 @@ const isKnownPropertyObjectMutation = (callExpression, methodName, writablePrope
58085
59331
  const runsAfterModuleInitialization = (node, boundaryNode = null) => {
58086
59332
  let ancestor = node.parent;
58087
59333
  while (ancestor && ancestor !== boundaryNode) {
58088
- if (isFunctionLike$2(ancestor) && !isImmediatelyInvokedFunction(ancestor)) return true;
59334
+ if (isFunctionLike$1(ancestor) && !isImmediatelyInvokedFunction(ancestor)) return true;
58089
59335
  ancestor = ancestor.parent ?? null;
58090
59336
  }
58091
59337
  return false;
@@ -58105,7 +59351,7 @@ const isMutatedThroughCallArgument = (referenceIdentifier, scopes, mayFollowCall
58105
59351
  const calleeSymbol = scopes.symbolFor(callee);
58106
59352
  if (!calleeSymbol) return false;
58107
59353
  const calleeFunction = calleeSymbol.initializer;
58108
- if (!isFunctionLike$2(calleeFunction)) return false;
59354
+ if (!isFunctionLike$1(calleeFunction)) return false;
58109
59355
  const parameter = calleeFunction.params?.[referenceArgumentIndex];
58110
59356
  if (!parameter || !isNodeOfType(parameter, "Identifier")) return false;
58111
59357
  const parameterSymbol = scopes.symbolFor(parameter);
@@ -59287,8 +60533,8 @@ const tanstackStartNoNavigateInRender = defineRule({
59287
60533
  };
59288
60534
  const isEventHandlerAttribute = (node) => isNodeOfType(node, "JSXAttribute") && isNodeOfType(node.name, "JSXIdentifier") && REACT_HANDLER_PROP_PATTERN.test(node.name.name);
59289
60535
  const isEventHandlerNamedProperty = (node) => isNodeOfType(node, "Property") && (isNodeOfType(node.key, "Identifier") && typeof node.key.name === "string" && REACT_HANDLER_PROP_PATTERN.test(node.key.name) || isNodeOfType(node.key, "Literal") && typeof node.key.value === "string" && REACT_HANDLER_PROP_PATTERN.test(node.key.value));
59290
- const isEventHandlerProperty = (node) => isNodeOfType(node, "Property") && isFunctionLike$2(node.value) && isEventHandlerNamedProperty(node);
59291
- const isHandlerNamedVariableDeclarator = (node) => isNodeOfType(node, "VariableDeclarator") && isNodeOfType(node.id, "Identifier") && typeof node.id.name === "string" && HANDLER_FUNCTION_NAME_PATTERN.test(node.id.name) && isFunctionLike$2(node.init);
60536
+ const isEventHandlerProperty = (node) => isNodeOfType(node, "Property") && isFunctionLike$1(node.value) && isEventHandlerNamedProperty(node);
60537
+ const isHandlerNamedVariableDeclarator = (node) => isNodeOfType(node, "VariableDeclarator") && isNodeOfType(node.id, "Identifier") && typeof node.id.name === "string" && HANDLER_FUNCTION_NAME_PATTERN.test(node.id.name) && isFunctionLike$1(node.init);
59292
60538
  const isHandlerNamedFunctionDeclaration = (node) => isNodeOfType(node, "FunctionDeclaration") && isNodeOfType(node.id, "Identifier") && typeof node.id.name === "string" && HANDLER_FUNCTION_NAME_PATTERN.test(node.id.name);
59293
60539
  const isInsideEventHandlerValue = (identifier) => {
59294
60540
  let cursor = identifier.parent;
@@ -59466,7 +60712,7 @@ const tanstackStartNoUseEffectFetch = defineRule({
59466
60712
  const effectInvokedFunctions = collectEffectInvokedFunctions(callback);
59467
60713
  walkAst(callback, (child) => {
59468
60714
  if (hasFetchCall) return false;
59469
- if (child !== callback && isFunctionLike$2(child) && !effectInvokedFunctions.has(child)) return false;
60715
+ if (child !== callback && isFunctionLike$1(child) && !effectInvokedFunctions.has(child)) return false;
59470
60716
  if (isNodeOfType(child, "CallExpression") && isNodeOfType(child.callee, "Identifier") && child.callee.name === "fetch") hasFetchCall = true;
59471
60717
  });
59472
60718
  if (hasFetchCall) context.report({
@@ -65041,387 +66287,6 @@ const wrapReactNativeRule = (rule) => {
65041
66287
  };
65042
66288
  };
65043
66289
  //#endregion
65044
- //#region src/plugin/semantic/control-flow-graph.ts
65045
- let nextBlockId = 0;
65046
- const createBlock = (builder) => {
65047
- const block = {
65048
- id: nextBlockId++,
65049
- nodes: [],
65050
- successors: [],
65051
- predecessors: []
65052
- };
65053
- builder.blocks.push(block);
65054
- return block;
65055
- };
65056
- const addEdge = (from, to, kind) => {
65057
- const edge = {
65058
- from,
65059
- to,
65060
- kind
65061
- };
65062
- from.successors.push(edge);
65063
- to.predecessors.push(edge);
65064
- };
65065
- const appendNode = (builder, block, node) => {
65066
- block.nodes.push(node);
65067
- if (!builder.nodeBlock.has(node)) builder.nodeBlock.set(node, block);
65068
- };
65069
- const mapDescendantsToBlock = (builder, node, block) => {
65070
- builder.nodeBlock.set(node, block);
65071
- if (isFunctionLike$2(node)) {
65072
- builder.nestedFunctions.push(node);
65073
- return;
65074
- }
65075
- const record = node;
65076
- for (const key of Object.keys(record)) {
65077
- if (key === "parent") continue;
65078
- const child = record[key];
65079
- if (Array.isArray(child)) {
65080
- for (const item of child) if (isAstNode(item)) mapDescendantsToBlock(builder, item, block);
65081
- } else if (isAstNode(child)) mapDescendantsToBlock(builder, child, block);
65082
- }
65083
- };
65084
- const hasInternalControlFlow = (node) => {
65085
- switch (node.type) {
65086
- case "IfStatement":
65087
- case "WhileStatement":
65088
- case "DoWhileStatement":
65089
- case "ForStatement":
65090
- case "ForInStatement":
65091
- case "ForOfStatement":
65092
- case "SwitchStatement":
65093
- case "TryStatement":
65094
- case "ReturnStatement":
65095
- case "ThrowStatement":
65096
- case "BreakStatement":
65097
- case "ContinueStatement":
65098
- case "BlockStatement":
65099
- case "LabeledStatement": return true;
65100
- default: return false;
65101
- }
65102
- };
65103
- const findLabel = (builder, name) => {
65104
- if (name === null) {
65105
- if (builder.loopStack.length > 0) {
65106
- const top = builder.loopStack[builder.loopStack.length - 1];
65107
- return {
65108
- merge: top.merge,
65109
- header: top.header
65110
- };
65111
- }
65112
- if (builder.switchStack.length > 0) return {
65113
- merge: builder.switchStack[builder.switchStack.length - 1].merge,
65114
- header: null
65115
- };
65116
- return null;
65117
- }
65118
- for (let i = builder.labelStack.length - 1; i >= 0; i--) {
65119
- const entry = builder.labelStack[i];
65120
- if (entry.label === name) return {
65121
- merge: entry.merge,
65122
- header: entry.header
65123
- };
65124
- }
65125
- return null;
65126
- };
65127
- const buildStatements = (builder, statements, current) => {
65128
- let cursor = current;
65129
- for (const statement of statements) cursor = buildStatement(builder, statement, cursor);
65130
- return cursor;
65131
- };
65132
- const buildStatement = (builder, statement, current) => {
65133
- builder.nodeBlock.set(statement, current);
65134
- if (!hasInternalControlFlow(statement)) {
65135
- appendNode(builder, current, statement);
65136
- mapDescendantsToBlock(builder, statement, current);
65137
- return current;
65138
- }
65139
- if (isNodeOfType(statement, "BlockStatement")) return buildStatements(builder, statement.body, current);
65140
- if (isNodeOfType(statement, "LabeledStatement")) {
65141
- const merge = createBlock(builder);
65142
- const labelEntry = {
65143
- label: statement.label.name,
65144
- merge,
65145
- header: null
65146
- };
65147
- builder.labelStack.push(labelEntry);
65148
- const body = statement.body;
65149
- const end = buildStatement(builder, body, current);
65150
- builder.labelStack.pop();
65151
- addEdge(end, merge, "uncond");
65152
- return merge;
65153
- }
65154
- if (isNodeOfType(statement, "ReturnStatement")) {
65155
- if (statement.argument) mapDescendantsToBlock(builder, statement.argument, current);
65156
- addEdge(current, builder.exit, "uncond");
65157
- return createBlock(builder);
65158
- }
65159
- if (isNodeOfType(statement, "ThrowStatement")) {
65160
- if (statement.argument) mapDescendantsToBlock(builder, statement.argument, current);
65161
- const top = builder.tryStack[builder.tryStack.length - 1];
65162
- if (top?.catch) addEdge(current, top.catch, "uncond");
65163
- else if (top?.finally) addEdge(current, top.finally, "uncond");
65164
- else addEdge(current, builder.exit, "throw");
65165
- return createBlock(builder);
65166
- }
65167
- if (isNodeOfType(statement, "BreakStatement")) {
65168
- const target = findLabel(builder, statement.label ? statement.label.name : null);
65169
- if (target) addEdge(current, target.merge, "uncond");
65170
- else addEdge(current, builder.exit, "uncond");
65171
- return createBlock(builder);
65172
- }
65173
- if (isNodeOfType(statement, "ContinueStatement")) {
65174
- const target = findLabel(builder, statement.label ? statement.label.name : null);
65175
- if (target?.header) addEdge(current, target.header, "uncond");
65176
- return createBlock(builder);
65177
- }
65178
- if (isNodeOfType(statement, "IfStatement")) {
65179
- mapDescendantsToBlock(builder, statement.test, current);
65180
- const thenBlock = createBlock(builder);
65181
- const merge = createBlock(builder);
65182
- addEdge(current, thenBlock, "cond");
65183
- addEdge(buildStatement(builder, statement.consequent, thenBlock), merge, "uncond");
65184
- if (statement.alternate) {
65185
- const elseBlock = createBlock(builder);
65186
- addEdge(current, elseBlock, "cond");
65187
- addEdge(buildStatement(builder, statement.alternate, elseBlock), merge, "uncond");
65188
- } else addEdge(current, merge, "cond");
65189
- return merge;
65190
- }
65191
- if (isNodeOfType(statement, "WhileStatement") || isNodeOfType(statement, "DoWhileStatement")) {
65192
- const isDoWhile = isNodeOfType(statement, "DoWhileStatement");
65193
- mapDescendantsToBlock(builder, statement.test, current);
65194
- const header = createBlock(builder);
65195
- const body = createBlock(builder);
65196
- const merge = createBlock(builder);
65197
- if (isDoWhile) addEdge(current, body, "uncond");
65198
- else {
65199
- addEdge(current, header, "uncond");
65200
- addEdge(header, body, "cond");
65201
- addEdge(header, merge, "cond");
65202
- }
65203
- builder.loopStack.push({
65204
- header,
65205
- merge,
65206
- label: null
65207
- });
65208
- const bodyEnd = buildStatement(builder, statement.body, body);
65209
- builder.loopStack.pop();
65210
- if (isDoWhile) {
65211
- addEdge(bodyEnd, header, "uncond");
65212
- addEdge(header, body, "cond");
65213
- addEdge(header, merge, "cond");
65214
- } else addEdge(bodyEnd, header, "uncond");
65215
- return merge;
65216
- }
65217
- if (isNodeOfType(statement, "ForStatement")) {
65218
- if (statement.init) mapDescendantsToBlock(builder, statement.init, current);
65219
- if (statement.test) mapDescendantsToBlock(builder, statement.test, current);
65220
- const header = createBlock(builder);
65221
- const body = createBlock(builder);
65222
- const merge = createBlock(builder);
65223
- addEdge(current, header, "uncond");
65224
- addEdge(header, body, "cond");
65225
- addEdge(header, merge, "cond");
65226
- builder.loopStack.push({
65227
- header,
65228
- merge,
65229
- label: null
65230
- });
65231
- const bodyEnd = buildStatement(builder, statement.body, body);
65232
- builder.loopStack.pop();
65233
- if (statement.update) mapDescendantsToBlock(builder, statement.update, header);
65234
- addEdge(bodyEnd, header, "uncond");
65235
- return merge;
65236
- }
65237
- if (isNodeOfType(statement, "ForInStatement") || isNodeOfType(statement, "ForOfStatement")) {
65238
- mapDescendantsToBlock(builder, statement.right, current);
65239
- mapDescendantsToBlock(builder, statement.left, current);
65240
- const header = createBlock(builder);
65241
- const body = createBlock(builder);
65242
- const merge = createBlock(builder);
65243
- addEdge(current, header, "uncond");
65244
- addEdge(header, body, "cond");
65245
- addEdge(header, merge, "cond");
65246
- builder.loopStack.push({
65247
- header,
65248
- merge,
65249
- label: null
65250
- });
65251
- const bodyEnd = buildStatement(builder, statement.body, body);
65252
- builder.loopStack.pop();
65253
- addEdge(bodyEnd, header, "uncond");
65254
- return merge;
65255
- }
65256
- if (isNodeOfType(statement, "SwitchStatement")) {
65257
- mapDescendantsToBlock(builder, statement.discriminant, current);
65258
- const merge = createBlock(builder);
65259
- builder.switchStack.push({
65260
- merge,
65261
- label: null
65262
- });
65263
- let previousCaseEnd = null;
65264
- let hasDefault = false;
65265
- for (const switchCase of statement.cases) {
65266
- const caseBlock = createBlock(builder);
65267
- addEdge(current, caseBlock, "cond");
65268
- if (previousCaseEnd) addEdge(previousCaseEnd, caseBlock, "uncond");
65269
- previousCaseEnd = buildStatements(builder, switchCase.consequent, caseBlock);
65270
- if (switchCase.test === null) hasDefault = true;
65271
- }
65272
- builder.switchStack.pop();
65273
- if (previousCaseEnd) addEdge(previousCaseEnd, merge, "uncond");
65274
- if (!hasDefault) addEdge(current, merge, "cond");
65275
- return merge;
65276
- }
65277
- if (isNodeOfType(statement, "TryStatement")) {
65278
- const tryBlock = createBlock(builder);
65279
- const merge = createBlock(builder);
65280
- let catchBlock = null;
65281
- let finallyBlock = null;
65282
- if (statement.handler) catchBlock = createBlock(builder);
65283
- if (statement.finalizer) finallyBlock = createBlock(builder);
65284
- addEdge(current, tryBlock, "uncond");
65285
- builder.tryStack.push({
65286
- catch: catchBlock,
65287
- finally: finallyBlock
65288
- });
65289
- const tryEnd = buildStatements(builder, statement.block.body, tryBlock);
65290
- builder.tryStack.pop();
65291
- if (catchBlock) addEdge(tryBlock, catchBlock, "cond");
65292
- if (statement.handler && catchBlock) {
65293
- const handlerBody = statement.handler.body;
65294
- const catchEnd = buildStatement(builder, handlerBody, catchBlock);
65295
- if (finallyBlock) addEdge(catchEnd, finallyBlock, "uncond");
65296
- else addEdge(catchEnd, merge, "uncond");
65297
- }
65298
- if (finallyBlock && statement.finalizer) {
65299
- addEdge(tryEnd, finallyBlock, "uncond");
65300
- addEdge(buildStatements(builder, statement.finalizer.body, finallyBlock), merge, "uncond");
65301
- } else addEdge(tryEnd, merge, "uncond");
65302
- return merge;
65303
- }
65304
- appendNode(builder, current, statement);
65305
- mapDescendantsToBlock(builder, statement, current);
65306
- return current;
65307
- };
65308
- const buildFunctionCfg = (functionNode, body, nestedFunctionSink) => {
65309
- const builder = {
65310
- blocks: [],
65311
- entry: null,
65312
- exit: null,
65313
- nestedFunctions: nestedFunctionSink,
65314
- nodeBlock: /* @__PURE__ */ new Map(),
65315
- loopStack: [],
65316
- switchStack: [],
65317
- tryStack: [],
65318
- labelStack: []
65319
- };
65320
- const entry = createBlock(builder);
65321
- const exit = createBlock(builder);
65322
- builder.entry = entry;
65323
- builder.exit = exit;
65324
- let bodyEnd;
65325
- if (isNodeOfType(body, "BlockStatement")) bodyEnd = buildStatements(builder, body.body, entry);
65326
- else {
65327
- mapDescendantsToBlock(builder, body, entry);
65328
- bodyEnd = entry;
65329
- }
65330
- addEdge(bodyEnd, exit, "uncond");
65331
- return {
65332
- owner: functionNode,
65333
- entry,
65334
- exit,
65335
- blocks: builder.blocks,
65336
- blockOf: (node) => builder.nodeBlock.get(node) ?? null
65337
- };
65338
- };
65339
- const computeUnconditionalSet = (cfg) => {
65340
- const reachableFromEntry = (excluded) => {
65341
- const visited = /* @__PURE__ */ new Set();
65342
- const queue = [];
65343
- if (cfg.entry !== excluded) queue.push(cfg.entry);
65344
- while (queue.length > 0) {
65345
- const block = queue.shift();
65346
- if (visited.has(block)) continue;
65347
- visited.add(block);
65348
- for (const edge of block.successors) {
65349
- if (edge.kind === "throw") continue;
65350
- if (edge.to === excluded) continue;
65351
- queue.push(edge.to);
65352
- }
65353
- }
65354
- return visited;
65355
- };
65356
- const reachableFromEntryFull = reachableFromEntry(null);
65357
- const unconditional = /* @__PURE__ */ new Set();
65358
- unconditional.add(cfg.entry);
65359
- unconditional.add(cfg.exit);
65360
- for (const block of cfg.blocks) {
65361
- if (unconditional.has(block)) continue;
65362
- if (!reachableFromEntryFull.has(block)) {
65363
- unconditional.add(block);
65364
- continue;
65365
- }
65366
- if (!reachableFromEntry(block).has(cfg.exit)) unconditional.add(block);
65367
- }
65368
- return unconditional;
65369
- };
65370
- const analyzeControlFlow = (program) => {
65371
- nextBlockId = 0;
65372
- const functionCfgs = /* @__PURE__ */ new Map();
65373
- const pendingFunctions = [];
65374
- const buildFor = (functionNode, body) => {
65375
- const cfg = buildFunctionCfg(functionNode, body, pendingFunctions);
65376
- functionCfgs.set(functionNode, {
65377
- cfg,
65378
- unconditionalSet: computeUnconditionalSet(cfg)
65379
- });
65380
- };
65381
- if (isNodeOfType(program, "Program")) buildFor(program, {
65382
- type: "BlockStatement",
65383
- body: program.body
65384
- });
65385
- for (let functionIndex = 0; functionIndex < pendingFunctions.length; functionIndex += 1) {
65386
- const functionNode = pendingFunctions[functionIndex];
65387
- if (!isFunctionLike$2(functionNode) || !functionNode.body || functionCfgs.has(functionNode)) continue;
65388
- buildFor(functionNode, functionNode.body);
65389
- }
65390
- const getFunctionEntry = (functionNode) => {
65391
- const existingEntry = functionCfgs.get(functionNode);
65392
- if (existingEntry) return existingEntry;
65393
- if (!isFunctionLike$2(functionNode) || !functionNode.body) return null;
65394
- buildFor(functionNode, functionNode.body);
65395
- return functionCfgs.get(functionNode) ?? null;
65396
- };
65397
- const enclosingFunction = (node) => {
65398
- let current = node;
65399
- while (current) {
65400
- if (isFunctionLike$2(current)) return current;
65401
- if (isNodeOfType(current, "Program")) return current;
65402
- current = current.parent ?? null;
65403
- }
65404
- return null;
65405
- };
65406
- const cfgFor = (functionLike) => {
65407
- return getFunctionEntry(functionLike)?.cfg ?? null;
65408
- };
65409
- const isUnconditionalFromEntry = (node) => {
65410
- const owner = enclosingFunction(node);
65411
- if (!owner) return true;
65412
- const entry = getFunctionEntry(owner);
65413
- if (!entry) return true;
65414
- const block = entry.cfg.blockOf(node);
65415
- if (!block) return true;
65416
- return entry.unconditionalSet.has(block);
65417
- };
65418
- return {
65419
- cfgFor,
65420
- enclosingFunction,
65421
- isUnconditionalFromEntry
65422
- };
65423
- };
65424
- //#endregion
65425
66290
  //#region src/plugin/utils/wrap-with-semantic-context.ts
65426
66291
  const buildFallbackScopes = () => ({
65427
66292
  rootScope: {
@@ -65623,6 +66488,7 @@ const REACT_COMPILER_RULES = toRuleMap(collectExternalRulesBySource("react-compi
65623
66488
  //#region src/plugin/constants/cross-file-rule-ids.ts
65624
66489
  const CROSS_FILE_RULE_IDS = new Set([
65625
66490
  "client-passive-event-listeners",
66491
+ "exhaustive-deps",
65626
66492
  "no-barrel-import",
65627
66493
  "nextjs-missing-metadata",
65628
66494
  "nextjs-no-use-search-params-without-suspense",
@@ -65636,11 +66502,13 @@ const CROSS_FILE_RULE_IDS = new Set([
65636
66502
  "no-derived-state",
65637
66503
  "no-derived-state-effect",
65638
66504
  "no-event-handler",
66505
+ "no-effect-with-fresh-deps",
65639
66506
  "no-initialize-state",
65640
66507
  "no-mutating-reducer-state",
65641
66508
  "no-unguarded-browser-global-in-render-or-hook-init",
65642
66509
  "prefer-dynamic-import",
65643
66510
  "rendering-hydration-mismatch-time",
66511
+ "rerender-memo-with-default-value",
65644
66512
  "rn-no-legacy-shadow-styles",
65645
66513
  "rn-no-raw-text",
65646
66514
  "rn-prefer-expo-image",
@@ -65693,6 +66561,46 @@ const collectNextjsSearchParamsDependencies = ({ absoluteFilePath, staticImports
65693
66561
  const collectEffectValueHelperDependencies = ({ absoluteFilePath, staticImports }) => {
65694
66562
  for (const entry of flattenImportEntries(staticImports)) resolveCrossFileFunctionExport(absoluteFilePath, entry.source, entry.exportedName);
65695
66563
  };
66564
+ const flattenProgramImportEntries = (program) => {
66565
+ const entries = [];
66566
+ for (const statement of program.body ?? []) {
66567
+ if (statement.type !== "ImportDeclaration") continue;
66568
+ const source = statement.source?.value;
66569
+ if (typeof source !== "string") continue;
66570
+ for (const specifier of statement.specifiers ?? []) if (specifier.type === "ImportDefaultSpecifier") entries.push({
66571
+ source,
66572
+ exportedName: "default"
66573
+ });
66574
+ else if (specifier.type === "ImportSpecifier") {
66575
+ const imported = specifier.imported;
66576
+ let exportedName = null;
66577
+ if (typeof imported?.name === "string") exportedName = imported.name;
66578
+ else if (typeof imported?.value === "string") exportedName = imported.value;
66579
+ if (exportedName) entries.push({
66580
+ source,
66581
+ exportedName
66582
+ });
66583
+ }
66584
+ }
66585
+ return entries;
66586
+ };
66587
+ const collectForwardedHookDependencies = ({ absoluteFilePath, staticImports }) => {
66588
+ const greatestTraversedDepthByFilePath = /* @__PURE__ */ new Map();
66589
+ const collectProgramDependencies = (filePath, program, remainingDepth) => {
66590
+ if ((greatestTraversedDepthByFilePath.get(filePath) ?? -1) >= remainingDepth) return;
66591
+ greatestTraversedDepthByFilePath.set(filePath, remainingDepth);
66592
+ for (const entry of flattenProgramImportEntries(program)) {
66593
+ const resolved = resolveCrossFileValueExportWithFilePath(filePath, entry.source, entry.exportedName);
66594
+ if (!resolved || remainingDepth === 0) continue;
66595
+ collectProgramDependencies(resolved.filePath, resolved.programNode, remainingDepth - 1);
66596
+ }
66597
+ };
66598
+ for (const entry of flattenImportEntries(staticImports)) {
66599
+ const resolved = resolveCrossFileValueExportWithFilePath(absoluteFilePath, entry.source, entry.exportedName);
66600
+ if (!resolved) continue;
66601
+ collectProgramDependencies(resolved.filePath, resolved.programNode, 4);
66602
+ }
66603
+ };
65696
66604
  const collectMutatingReducerDependencies = ({ absoluteFilePath, sourceText, staticImports, program }) => {
65697
66605
  const namedUseReducerLocals = /* @__PURE__ */ new Set();
65698
66606
  const reactObjectLocals = /* @__PURE__ */ new Set();
@@ -65771,6 +66679,7 @@ const collectLegacyArchDependencies = ({ absoluteFilePath }) => {
65771
66679
  };
65772
66680
  const CROSS_FILE_DEPENDENCY_COLLECTORS = new Map([
65773
66681
  ["client-passive-event-listeners", collectEffectValueHelperDependencies],
66682
+ ["exhaustive-deps", collectForwardedHookDependencies],
65774
66683
  ["no-barrel-import", collectNoBarrelImportDependencies],
65775
66684
  ["nextjs-missing-metadata", collectNextjsMissingMetadataDependencies],
65776
66685
  ["nextjs-no-use-search-params-without-suspense", collectNextjsSearchParamsDependencies],
@@ -65784,11 +66693,13 @@ const CROSS_FILE_DEPENDENCY_COLLECTORS = new Map([
65784
66693
  ["no-derived-state", collectEffectValueHelperDependencies],
65785
66694
  ["no-derived-state-effect", collectEffectValueHelperDependencies],
65786
66695
  ["no-event-handler", collectEffectValueHelperDependencies],
66696
+ ["no-effect-with-fresh-deps", collectForwardedHookDependencies],
65787
66697
  ["no-initialize-state", collectEffectValueHelperDependencies],
65788
66698
  ["no-mutating-reducer-state", collectMutatingReducerDependencies],
65789
66699
  ["no-unguarded-browser-global-in-render-or-hook-init", collectNearestManifestDependencies],
65790
66700
  ["prefer-dynamic-import", collectNearestManifestDependencies],
65791
66701
  ["rendering-hydration-mismatch-time", collectNearestManifestDependencies],
66702
+ ["rerender-memo-with-default-value", collectForwardedHookDependencies],
65792
66703
  ["rn-no-legacy-shadow-styles", collectLegacyArchDependencies],
65793
66704
  ["rn-no-raw-text", collectRnNoRawTextDependencies],
65794
66705
  ["rn-prefer-expo-image", collectNearestManifestDependencies],