eslint-plugin-react-x 5.24.0 → 5.24.2

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 +45 -1476
  2. package/package.json +8 -8
package/dist/index.js CHANGED
@@ -145,7 +145,7 @@ const rules$6 = {
145
145
  //#endregion
146
146
  //#region package.json
147
147
  var name$6 = "eslint-plugin-react-x";
148
- var version = "5.24.0";
148
+ var version = "5.24.2";
149
149
 
150
150
  //#endregion
151
151
  //#region src/utils/create-rule.ts
@@ -257,17 +257,11 @@ const rule$1 = {
257
257
  }
258
258
  context.report(problem);
259
259
  }
260
- /**
261
- * SourceCode that also works down to ESLint 3.0.0
262
- */
263
260
  const getSourceCode = typeof context.getSourceCode === "function" ? () => {
264
261
  return context.getSourceCode();
265
262
  } : () => {
266
263
  return context.sourceCode;
267
264
  };
268
- /**
269
- * SourceCode#getScope that also works down to ESLint 3.0.0
270
- */
271
265
  const getScope = typeof context.getScope === "function" ? () => {
272
266
  return context.getScope();
273
267
  } : (node) => {
@@ -287,9 +281,6 @@ const rule$1 = {
287
281
  return result;
288
282
  };
289
283
  }
290
- /**
291
- * Visitor for both function expressions and arrow function expressions.
292
- */
293
284
  function visitFunctionWithDependencies(node, declaredDependenciesNode, reactiveHook, reactiveHookName, isEffect, isAutoDepsHook) {
294
285
  if (isEffect && node.async) reportProblem({
295
286
  node,
@@ -989,24 +980,11 @@ function scanForConstructions({ declaredDependencies, declaredDependenciesNode,
989
980
  isUsedOutsideOfHook: isUsedOutsideOfHook(ref)
990
981
  }));
991
982
  }
992
- /**
993
- * Assuming () means the passed/returned node:
994
- * (props) => (props)
995
- * props.(foo) => (props.foo)
996
- * props.foo.(bar) => (props).foo.bar
997
- * props.foo.bar.(baz) => (props).foo.bar.baz
998
- */
999
983
  function getDependency(node) {
1000
984
  if (node.parent && (node.parent.type === "MemberExpression" || node.parent.type === "OptionalMemberExpression") && node.parent.object === node && "name" in node.parent.property && node.parent.property.name !== "current" && !node.parent.computed && !(node.parent.parent != null && (node.parent.parent.type === "CallExpression" || node.parent.parent.type === "OptionalCallExpression") && node.parent.parent.callee === node.parent)) return getDependency(node.parent);
1001
985
  else if (node.type === "MemberExpression" && node.parent && node.parent.type === "AssignmentExpression" && node.parent.left === node) return node.object;
1002
986
  else return node;
1003
987
  }
1004
- /**
1005
- * Mark a node as either optional or required.
1006
- * Note: If the node argument is an OptionalMemberExpression, it doesn't necessarily mean it is optional.
1007
- * It just means there is an optional member somewhere inside.
1008
- * This particular node might still represent a required member, so check .optional field.
1009
- */
1010
988
  function markNode(node, optionalChains, result) {
1011
989
  if (optionalChains) {
1012
990
  if ("optional" in node && node.optional) {
@@ -1014,13 +992,6 @@ function markNode(node, optionalChains, result) {
1014
992
  } else optionalChains.set(result, false);
1015
993
  }
1016
994
  }
1017
- /**
1018
- * Assuming () means the passed node.
1019
- * (foo) -> 'foo'
1020
- * foo(.)bar -> 'foo.bar'
1021
- * foo.bar(.)baz -> 'foo.bar.baz'
1022
- * Otherwise throw.
1023
- */
1024
995
  function analyzePropertyChain(node, optionalChains) {
1025
996
  if (node.type === "Identifier" || node.type === "JSXIdentifier") {
1026
997
  const result = node.name;
@@ -1067,16 +1038,6 @@ function getReactiveHookCallbackIndex(calleeNode, options) {
1067
1038
  } else return -1;
1068
1039
  }
1069
1040
  }
1070
- /**
1071
- * ESLint won't assign node.parent to references from context.getScope()
1072
- *
1073
- * So instead we search for the node from an ancestor assigning node.parent
1074
- * as we go. This mutates the AST.
1075
- *
1076
- * This traversal is:
1077
- * - optimized by only searching nodes with a range surrounding our target node
1078
- * - agnostic to AST node types, it looks for `{ type: string, ... }`
1079
- */
1080
1041
  function fastFindReferenceWithParent(start, target) {
1081
1042
  const queue = [start];
1082
1043
  let item;
@@ -1127,10 +1088,6 @@ function getUnknownDependenciesMessage(reactiveHookName) {
1127
1088
 
1128
1089
  //#endregion
1129
1090
  //#region src/rules/globals/helpers.ts
1130
- /**
1131
- * Array methods that mutate the array in place.
1132
- * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
1133
- */
1134
1091
  const MUTATING_ARRAY_METHODS = /* @__PURE__ */ new Set([
1135
1092
  "copyWithin",
1136
1093
  "fill",
@@ -1142,7 +1099,6 @@ const MUTATING_ARRAY_METHODS = /* @__PURE__ */ new Set([
1142
1099
  "splice",
1143
1100
  "unshift"
1144
1101
  ]);
1145
- /** Resolve a direct call target, following simple function aliases. */
1146
1102
  function resolveToFunction(context, node, seen = /* @__PURE__ */ new Set()) {
1147
1103
  const expression = Extract.unwrap(node);
1148
1104
  if (Check.isFunction(expression)) return expression;
@@ -1222,22 +1178,11 @@ function createFactCollector$6() {
1222
1178
 
1223
1179
  //#endregion
1224
1180
  //#region src/rules/globals/origins.ts
1225
- /**
1226
- * Return whether an identifier is an unresolved global or is declared in the
1227
- * global/module scope.
1228
- */
1229
1181
  function isGlobalVariable(context, node) {
1230
1182
  const variable = findVariable(context.sourceCode.getScope(node), node);
1231
1183
  if (variable == null || variable.defs.length === 0) return true;
1232
1184
  return variable.scope.type === ScopeType.global || variable.scope.type === ScopeType.module;
1233
1185
  }
1234
- /**
1235
- * Resolve an object expression to the global/module binding it aliases.
1236
- *
1237
- * This intentionally follows only stable `const alias = value` declarations.
1238
- * It gives the rule useful Alias effects without pretending to perform full
1239
- * control-flow analysis for reassigned locals.
1240
- */
1241
1186
  function resolveGlobalOrigin(context, node, seen = /* @__PURE__ */ new Set()) {
1242
1187
  const expression = Extract.unwrap(node);
1243
1188
  if (seen.has(expression)) return null;
@@ -1257,11 +1202,6 @@ function resolveGlobalOrigin(context, node, seen = /* @__PURE__ */ new Set()) {
1257
1202
 
1258
1203
  //#endregion
1259
1204
  //#region src/rules/globals/effects.ts
1260
- /**
1261
- * Classify the collected writes and mutating method calls, keeping only the
1262
- * ones that reach a global/module binding, grouped by the function that
1263
- * performs them.
1264
- */
1265
1205
  function inferGlobalMutations(context, facts) {
1266
1206
  const directEffects = /* @__PURE__ */ new Map();
1267
1207
  function pushEffect(enclosingFunction, effect) {
@@ -1300,7 +1240,6 @@ function inferGlobalMutations(context, facts) {
1300
1240
  }
1301
1241
  return directEffects;
1302
1242
  }
1303
- /** Resolve the collected call edges into a function-to-function call graph. */
1304
1243
  function inferCallGraph$1(context, callEdges) {
1305
1244
  const callGraph = /* @__PURE__ */ new Map();
1306
1245
  for (const edge of callEdges) {
@@ -1312,11 +1251,6 @@ function inferCallGraph$1(context, callEdges) {
1312
1251
  }
1313
1252
  return callGraph;
1314
1253
  }
1315
- /**
1316
- * Like the SPEC's function signatures, these summaries keep creation of an
1317
- * effect separate from applying it in a component or hook render: walk the
1318
- * call graph from each render function and gather every reachable effect once.
1319
- */
1320
1254
  function collectReachableEffects(renderFunctions, directEffects, callGraph) {
1321
1255
  const visited = /* @__PURE__ */ new Set();
1322
1256
  const reported = /* @__PURE__ */ new Set();
@@ -1377,12 +1311,6 @@ function create$49(context) {
1377
1311
 
1378
1312
  //#endregion
1379
1313
  //#region src/rules/immutability/helpers.ts
1380
- /**
1381
- * Methods that mutate their receiver in place.
1382
- * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
1383
- * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
1384
- * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
1385
- */
1386
1314
  const KNOWN_MUTATING_METHODS = /* @__PURE__ */ new Set([
1387
1315
  "add",
1388
1316
  "clear",
@@ -1398,9 +1326,6 @@ const KNOWN_MUTATING_METHODS = /* @__PURE__ */ new Set([
1398
1326
  "splice",
1399
1327
  "unshift"
1400
1328
  ]);
1401
- /**
1402
- * Known mutating hooks.
1403
- */
1404
1329
  const KNOWN_MUTATING_HOOKS = /* @__PURE__ */ new Set([
1405
1330
  "useHistory",
1406
1331
  "useNavigate",
@@ -1571,17 +1496,6 @@ function createFactCollector$5() {
1571
1496
 
1572
1497
  //#endregion
1573
1498
  //#region src/rules/immutability/origins.ts
1574
- /**
1575
- * Classify whether a variable ultimately holds a value that must be treated as
1576
- * immutable: a component's props, a state value returned from `useState`-like or
1577
- * `useReducer` calls, a shallow copy (spread literal) of either, or a `for...of`
1578
- * iterator variable whose iterated collection resolves to one of those.
1579
- * @param context The rule context.
1580
- * @param variable The variable to classify.
1581
- * @param components The confirmed function component nodes in the file.
1582
- * @param seen Variables already visited during spread/iterator recursion.
1583
- * @returns The frozen origin, or `null` when the variable is not derived from one.
1584
- */
1585
1499
  function classifyFrozenOrigin(context, variable, components, seen = /* @__PURE__ */ new Set()) {
1586
1500
  if (seen.has(variable)) return null;
1587
1501
  seen.add(variable);
@@ -1835,12 +1749,6 @@ function create$47(context) {
1835
1749
 
1836
1750
  //#endregion
1837
1751
  //#region src/rules/no-array-index-key/lib.ts
1838
- /**
1839
- * Iterator-like methods that pass the item's index to their callback,
1840
- * mapped to the position of the index parameter in the callback's parameter list.
1841
- * `map` and `forEach` also cover `Children.map` and `Children.forEach`,
1842
- * whose callback is the second argument instead of the first.
1843
- */
1844
1752
  const INDEX_PARAM_POSITIONS$1 = /* @__PURE__ */ new Map([
1845
1753
  ["every", 1],
1846
1754
  ["filter", 1],
@@ -1855,13 +1763,6 @@ const INDEX_PARAM_POSITIONS$1 = /* @__PURE__ */ new Map([
1855
1763
  ["reduceRight", 2],
1856
1764
  ["some", 1]
1857
1765
  ]);
1858
- /**
1859
- * Checks whether an identifier is a reference to the index parameter of an
1860
- * iterator-like method's callback (e.g. `i` in `items.map((item, i) => ...)`).
1861
- * @param context The ESLint rule context.
1862
- * @param node The identifier to check.
1863
- * @returns `true` if the identifier resolves to an array index parameter.
1864
- */
1865
1766
  function isArrayIndexReference(context, node) {
1866
1767
  const def = findVariable(context.sourceCode.getScope(node), node)?.defs.at(0);
1867
1768
  if (def == null || def.type !== DefinitionType.Parameter) return false;
@@ -1882,12 +1783,6 @@ function isArrayIndexReference(context, node) {
1882
1783
  if (param == null) return false;
1883
1784
  return param === def.name || param.type === AST_NODE_TYPES.AssignmentPattern && param.left === def.name;
1884
1785
  }
1885
- /**
1886
- * Recursively collects all identifiers from a binary expression.
1887
- * e.g., for `a + b + c`, it returns identifiers for a, b, and c.
1888
- * @param side The binary expression (or one of its sides) to collect from.
1889
- * @returns The identifiers found in the expression.
1890
- */
1891
1786
  function getIdentifiersFromBinaryExpression(side) {
1892
1787
  if (Check.isIdentifier(side)) return [side];
1893
1788
  if (side.type === AST_NODE_TYPES.BinaryExpression) return [...getIdentifiersFromBinaryExpression(side.left), ...getIdentifiersFromBinaryExpression(side.right)];
@@ -1897,7 +1792,6 @@ function getIdentifiersFromBinaryExpression(side) {
1897
1792
  //#endregion
1898
1793
  //#region src/rules/no-array-index-key/no-array-index-key.ts
1899
1794
  const RULE_NAME$46 = "no-array-index-key";
1900
- /** Global functions that convert their first argument while preserving its identity as a key. */
1901
1795
  const COERCION_FUNCTIONS = /* @__PURE__ */ new Set(["Number", "String"]);
1902
1796
  var no_array_index_key_default = createRule({
1903
1797
  meta: {
@@ -1920,12 +1814,6 @@ function create$46(context) {
1920
1814
  if (!core.isCloneElementCall(context, node)) return null;
1921
1815
  return props?.type === AST_NODE_TYPES.ObjectExpression ? props : null;
1922
1816
  }
1923
- /**
1924
- * Checks an expression used as a 'key' value, recursing into the branches
1925
- * it may evaluate to and reporting every array index it is derived from.
1926
- * @param node The key value expression to check.
1927
- * @returns The report descriptors for the violations found.
1928
- */
1929
1817
  function visitKeyExpression(node) {
1930
1818
  switch (node.type) {
1931
1819
  case AST_NODE_TYPES.Identifier: return isArrayIndex(node) ? [{
@@ -2094,60 +1982,6 @@ function create$41(context) {
2094
1982
 
2095
1983
  //#endregion
2096
1984
  //#region ../../.pkgs/eff/dist/index.js
2097
- function not(predicate) {
2098
- return (data) => !predicate(data);
2099
- }
2100
- function or(a, b) {
2101
- return (data) => a(data) || b(data);
2102
- }
2103
- /**
2104
- * A function that checks if the passed parameter is a string and narrows its type accordingly.
2105
- *
2106
- * @param data - The variable to check.
2107
- * @returns True if the passed input is a string, false otherwise.
2108
- * @category guards
2109
- */
2110
- function isString(data) {
2111
- return typeof data === "string";
2112
- }
2113
- /**
2114
- * Applies a `pipe` method's variadic arguments to an initial value from left
2115
- * to right.
2116
- *
2117
- * **When to use**
2118
- *
2119
- * Use to implement a custom `.pipe(...)` method from JavaScript's `arguments`
2120
- * object.
2121
- *
2122
- * **Details**
2123
- *
2124
- * This helper is intended for implementing `Pipeable.pipe` methods that
2125
- * receive JavaScript's `arguments` object. With no functions it returns the
2126
- * original value; otherwise it feeds each result into the next function.
2127
- *
2128
- * **Example** (Implementing a pipe method)
2129
- *
2130
- * ```ts
2131
- * import { Pipeable } from "effect"
2132
- *
2133
- * class NumberBox {
2134
- * constructor(readonly value: number) {}
2135
- *
2136
- * pipe(..._fns: ReadonlyArray<(value: number) => number>): number {
2137
- * return Pipeable.pipeArguments(this.value, arguments) as number
2138
- * }
2139
- * }
2140
- *
2141
- * const result = new NumberBox(5).pipe(
2142
- * (n) => n + 2,
2143
- * (n) => n * 3
2144
- * )
2145
- * console.log(result) // 21
2146
- * ```
2147
- *
2148
- * @category combinators
2149
- * @since 2.0.0
2150
- */
2151
1985
  const pipeArguments = (self, args) => {
2152
1986
  switch (args.length) {
2153
1987
  case 0: return self;
@@ -2167,110 +2001,14 @@ const pipeArguments = (self, args) => {
2167
2001
  }
2168
2002
  }
2169
2003
  };
2170
- /**
2171
- * Reusable prototype that implements `Pipeable.pipe`.
2172
- *
2173
- * **When to use**
2174
- *
2175
- * Use when classes or object prototypes can reuse this value when they need the
2176
- * standard pipe implementation backed by `pipeArguments`.
2177
- *
2178
- * @category prototypes
2179
- * @since 3.15.0
2180
- */
2181
2004
  const Prototype = { pipe() {
2182
2005
  return pipeArguments(this, arguments);
2183
2006
  } };
2184
- /**
2185
- * Provides a base constructor whose instances implement the standard `Pipeable.pipe`
2186
- * method.
2187
- *
2188
- * **When to use**
2189
- *
2190
- * Use when you need to define a class that supports Effect-style method
2191
- * chaining through `.pipe(...)`.
2192
- *
2193
- * @category constructors
2194
- * @since 3.15.0
2195
- */
2196
2007
  const Class = (function() {
2197
2008
  function PipeableBase() {}
2198
2009
  PipeableBase.prototype = Prototype;
2199
2010
  return PipeableBase;
2200
2011
  })();
2201
- /**
2202
- * Provides small helpers for defining and reusing TypeScript functions.
2203
- *
2204
- * The main helpers are `pipe` and `flow` for left-to-right composition and
2205
- * `dual` for APIs that support both direct and pipe-friendly call styles. The
2206
- * module also contains small identity, constant, tuple, type-level, and
2207
- * memoization helpers used across the library.
2208
- *
2209
- * @since 2.0.0
2210
- */
2211
- /**
2212
- * Creates a function that can be called in data-first style or data-last
2213
- * (`pipe`-friendly) style.
2214
- *
2215
- * **When to use**
2216
- *
2217
- * Use to expose one implementation through both direct and `pipe`-friendly
2218
- * call styles.
2219
- *
2220
- * **Details**
2221
- *
2222
- * Pass either the arity of the uncurried function or a predicate that decides
2223
- * whether the current call is data-first. Arity is the common case. Use a
2224
- * predicate when optional arguments make arity ambiguous.
2225
- *
2226
- * **Example** (Selecting data-first or data-last style by arity)
2227
- *
2228
- * ```ts
2229
- * import { Function, pipe } from "effect"
2230
- *
2231
- * const sum = Function.dual<
2232
- * (that: number) => (self: number) => number,
2233
- * (self: number, that: number) => number
2234
- * >(2, (self, that) => self + that)
2235
- *
2236
- * console.log(sum(2, 3)) // 5
2237
- * console.log(pipe(2, sum(3))) // 5
2238
- * ```
2239
- *
2240
- * **Example** (Defining overloads with call signatures)
2241
- *
2242
- * ```ts
2243
- * import { Function, pipe } from "effect"
2244
- *
2245
- * const sum: {
2246
- * (that: number): (self: number) => number
2247
- * (self: number, that: number): number
2248
- * } = Function.dual(2, (self: number, that: number): number => self + that)
2249
- *
2250
- * console.log(sum(2, 3)) // 5
2251
- * console.log(pipe(2, sum(3))) // 5
2252
- * ```
2253
- *
2254
- * **Example** (Selecting data-first or data-last style with a predicate)
2255
- *
2256
- * ```ts
2257
- * import { Function, pipe } from "effect"
2258
- *
2259
- * const sum = Function.dual<
2260
- * (that: number) => (self: number) => number,
2261
- * (self: number, that: number) => number
2262
- * >(
2263
- * (args) => args.length === 2,
2264
- * (self, that) => self + that
2265
- * )
2266
- *
2267
- * console.log(sum(2, 3)) // 5
2268
- * console.log(pipe(2, sum(3))) // 5
2269
- * ```
2270
- *
2271
- * @category combinators
2272
- * @since 2.0.0
2273
- */
2274
2012
  const dual = function(arity, body) {
2275
2013
  if (typeof arity === "function") return function() {
2276
2014
  return arity(arguments) ? body.apply(this, arguments) : ((self) => body(self, ...arguments));
@@ -2299,203 +2037,14 @@ const dual = function(arity, body) {
2299
2037
  };
2300
2038
  }
2301
2039
  };
2302
- /**
2303
- * Returns its input argument unchanged.
2304
- *
2305
- * **When to use**
2306
- *
2307
- * Use to return a value unchanged where a function is required.
2308
- *
2309
- * **Example** (Returning the same value)
2310
- *
2311
- * ```ts
2312
- * import { identity } from "effect"
2313
- * import * as assert from "node:assert"
2314
- *
2315
- * assert.deepStrictEqual(identity(5), 5)
2316
- * ```
2317
- *
2318
- * @category combinators
2319
- * @since 2.0.0
2320
- */
2321
2040
  const identity = (a) => a;
2322
- /**
2323
- * Returns the input value with a different static type.
2324
- *
2325
- * **When to use**
2326
- *
2327
- * Use when you need an explicit type-level cast and accept that the value is
2328
- * returned unchanged at runtime.
2329
- *
2330
- * **Gotchas**
2331
- *
2332
- * This is a type-level cast only; it performs no runtime validation or
2333
- * conversion.
2334
- *
2335
- * @see {@link satisfies} for checking assignability without changing the resulting type
2336
- *
2337
- * @category utility types
2338
- * @since 4.0.0
2339
- */
2340
2041
  const cast = identity;
2341
- /**
2342
- * Creates a zero-argument function that always returns the provided value.
2343
- *
2344
- * **When to use**
2345
- *
2346
- * Use when you need a thunk or callback that returns the same value on every
2347
- * invocation.
2348
- *
2349
- * **Example** (Creating a constant thunk)
2350
- *
2351
- * ```ts
2352
- * import { Function } from "effect"
2353
- * import * as assert from "node:assert"
2354
- *
2355
- * const constNull = Function.constant(null)
2356
- *
2357
- * assert.deepStrictEqual(constNull(), null)
2358
- * assert.deepStrictEqual(constNull(), null)
2359
- * ```
2360
- *
2361
- * @category constructors
2362
- * @since 2.0.0
2363
- */
2364
2042
  const constant = (value) => () => value;
2365
- /**
2366
- * Returns `true` when called.
2367
- *
2368
- * **When to use**
2369
- *
2370
- * Use when you need a thunk that returns `true` on every invocation.
2371
- *
2372
- * **Example** (Returning true from a thunk)
2373
- *
2374
- * ```ts
2375
- * import { Function } from "effect"
2376
- * import * as assert from "node:assert"
2377
- *
2378
- * assert.deepStrictEqual(Function.constTrue(), true)
2379
- * ```
2380
- *
2381
- * @category constants
2382
- * @since 2.0.0
2383
- */
2384
2043
  const constTrue = constant(true);
2385
- /**
2386
- * Returns `false` when called.
2387
- *
2388
- * **When to use**
2389
- *
2390
- * Use when you need a thunk that returns `false` on every invocation.
2391
- *
2392
- * **Example** (Returning false from a thunk)
2393
- *
2394
- * ```ts
2395
- * import { Function } from "effect"
2396
- * import * as assert from "node:assert"
2397
- *
2398
- * assert.deepStrictEqual(Function.constFalse(), false)
2399
- * ```
2400
- *
2401
- * @category constants
2402
- * @since 2.0.0
2403
- */
2404
2044
  const constFalse = constant(false);
2405
- /**
2406
- * Returns `null` when called.
2407
- *
2408
- * **When to use**
2409
- *
2410
- * Use when you need a thunk that returns `null` on every invocation.
2411
- *
2412
- * **Example** (Returning null from a thunk)
2413
- *
2414
- * ```ts
2415
- * import { Function } from "effect"
2416
- * import * as assert from "node:assert"
2417
- *
2418
- * assert.deepStrictEqual(Function.constNull(), null)
2419
- * ```
2420
- *
2421
- * @category constants
2422
- * @since 2.0.0
2423
- */
2424
2045
  const constNull = constant(null);
2425
- /**
2426
- * Returns `undefined` when called.
2427
- *
2428
- * **When to use**
2429
- *
2430
- * Use when you need a thunk that returns `undefined` on every invocation.
2431
- *
2432
- * **Example** (Returning undefined from a thunk)
2433
- *
2434
- * ```ts
2435
- * import { Function } from "effect"
2436
- * import * as assert from "node:assert"
2437
- *
2438
- * assert.deepStrictEqual(Function.constUndefined(), undefined)
2439
- * ```
2440
- *
2441
- * @category constants
2442
- * @since 2.0.0
2443
- */
2444
2046
  const constUndefined = constant(void 0);
2445
- /**
2446
- * Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
2447
- * The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
2448
- *
2449
- * **When to use**
2450
- *
2451
- * Use to compose exactly two unary functions into a reusable unary function.
2452
- *
2453
- * **Example** (Composing two functions)
2454
- *
2455
- * ```ts
2456
- * import { Function } from "effect"
2457
- * import * as assert from "node:assert"
2458
- *
2459
- * const increment = (n: number) => n + 1
2460
- * const square = (n: number) => n * n
2461
- *
2462
- * assert.strictEqual(Function.compose(increment, square)(2), 9)
2463
- * ```
2464
- *
2465
- * @see {@link flow} for composing a left-to-right sequence of functions
2466
- * @see {@link pipe} for applying a value through a left-to-right sequence immediately
2467
- *
2468
- * @category combinators
2469
- * @since 2.0.0
2470
- */
2471
2047
  const compose = dual(2, (ab, bc) => (a) => bc(ab(a)));
2472
- /**
2473
- * Marks an impossible branch by accepting a `never` value and returning any
2474
- * type.
2475
- *
2476
- * **When to use**
2477
- *
2478
- * Use when you need a return value in a branch that exhaustive checks prove
2479
- * cannot be reached.
2480
- *
2481
- * **Gotchas**
2482
- *
2483
- * Calling `absurd` throws, because a value of type `never` should be
2484
- * impossible at runtime.
2485
- *
2486
- * **Example** (Handling impossible values)
2487
- *
2488
- * ```ts
2489
- * import { absurd } from "effect"
2490
- *
2491
- * const handleNever = (value: never) => {
2492
- * return absurd(value) // This will throw an error if called
2493
- * }
2494
- * ```
2495
- *
2496
- * @category utility types
2497
- * @since 2.0.0
2498
- */
2499
2048
  const absurd = (_) => {
2500
2049
  throw new Error("Called `absurd` function which should be uncallable");
2501
2050
  };
@@ -2528,93 +2077,46 @@ function flow(ab, bc, cd, de, ef, fg, gh, hi, ij) {
2528
2077
  };
2529
2078
  }
2530
2079
  }
2531
- /**
2532
- * Creates a compile-time placeholder for a value of any type.
2533
- *
2534
- * **When to use**
2535
- *
2536
- * Use as a temporary typed placeholder while developing incomplete code.
2537
- *
2538
- * **Gotchas**
2539
- *
2540
- * `hole` is intended for temporary development use. If the placeholder is
2541
- * evaluated at runtime, it throws.
2542
- *
2543
- * **Example** (Creating a development placeholder)
2544
- *
2545
- * ```ts
2546
- * import { hole } from "effect"
2547
- *
2548
- * // Intentionally not called: `hole` throws if the placeholder is evaluated.
2549
- * const buildUser = (id: number): { readonly id: number; readonly name: string } => ({
2550
- * id,
2551
- * name: hole<string>()
2552
- * })
2553
- *
2554
- * console.log(typeof buildUser) // "function"
2555
- * ```
2556
- *
2557
- * @category utility types
2558
- * @since 2.0.0
2559
- */
2560
2080
  const hole = cast(absurd);
2081
+ function not(predicate) {
2082
+ return (data) => !predicate(data);
2083
+ }
2084
+ const and = dual(2, (a, b) => (data) => a(data) && b(data));
2085
+ const or = dual(2, (a, b) => (data) => a(data) || b(data));
2086
+ const xor = dual(2, (a, b) => (data) => a(data) !== b(data));
2087
+ const eqv = dual(2, (a, b) => (data) => a(data) === b(data));
2088
+ const implies = dual(2, (antecedent, consequent) => (data) => !antecedent(data) || consequent(data));
2089
+ const nor = dual(2, (a, b) => (data) => !a(data) && !b(data));
2090
+ const nand = dual(2, (a, b) => (data) => !a(data) || !b(data));
2091
+ function isString(input) {
2092
+ return typeof input === "string";
2093
+ }
2094
+ function isFunction(input) {
2095
+ return typeof input === "function";
2096
+ }
2097
+ function isObjectKeyword(input) {
2098
+ return typeof input === "object" && input !== null || isFunction(input);
2099
+ }
2100
+ const hasProperty = dual(2, (data, property) => isObjectKeyword(data) && property in data);
2561
2101
  function getOrInsertComputed(map, key, callback) {
2562
2102
  if (map.has(key)) return map.get(key);
2563
2103
  const value = callback(key);
2564
2104
  map.set(key, value);
2565
2105
  return value;
2566
2106
  }
2567
- /**
2568
- * Drops the longest prefix of elements from an array that satisfy the given predicate.
2569
- *
2570
- * Supports both data-first and data-last (`pipe`-friendly) call styles.
2571
- *
2572
- * @param pred - The predicate to test each element with.
2573
- * @returns A new array without the matching prefix.
2574
- * @example
2575
- * ```ts
2576
- * import * as assert from "node:assert"
2577
- * import { dropWhile, pipe } from "@local/eff"
2578
- *
2579
- * // data-first
2580
- * assert.deepStrictEqual(dropWhile([1, 2, 3, 2, 1], (n: number) => n < 3), [3, 2, 1])
2581
- *
2582
- * // data-last
2583
- * assert.deepStrictEqual(pipe([1, 2, 3, 2, 1], dropWhile((n: number) => n < 3)), [3, 2, 1])
2584
- * ```
2585
- * @category array
2586
- */
2587
- const dropWhile = dual(2, (xs, pred) => {
2588
- const len = xs.length;
2107
+ const dropWhile = dual(2, (self, predicate) => {
2108
+ const input = Array.isArray(self) ? self : Array.from(self);
2109
+ const len = input.length;
2589
2110
  let idx = 0;
2590
- while (idx < len && pred(xs[idx])) idx++;
2591
- return xs.slice(idx);
2111
+ while (idx < len && predicate(input[idx], idx)) idx++;
2112
+ return input.slice(idx);
2592
2113
  });
2593
- /**
2594
- * Takes the longest prefix of elements from an array that satisfy the given predicate.
2595
- *
2596
- * Supports both data-first and data-last (`pipe`-friendly) call styles.
2597
- *
2598
- * @param pred - The predicate to test each element with.
2599
- * @returns A new array containing only the matching prefix.
2600
- * @example
2601
- * ```ts
2602
- * import * as assert from "node:assert"
2603
- * import { pipe, takeWhile } from "@local/eff"
2604
- *
2605
- * // data-first
2606
- * assert.deepStrictEqual(takeWhile([1, 2, 3, 2, 1], (n: number) => n < 3), [1, 2])
2607
- *
2608
- * // data-last
2609
- * assert.deepStrictEqual(pipe([1, 2, 3, 2, 1], takeWhile((n: number) => n < 3)), [1, 2])
2610
- * ```
2611
- * @category array
2612
- */
2613
- const takeWhile = dual(2, (xs, pred) => {
2614
- const len = xs.length;
2114
+ const takeWhile = dual(2, (self, predicate) => {
2115
+ const input = Array.isArray(self) ? self : Array.from(self);
2116
+ const len = input.length;
2615
2117
  let idx = 0;
2616
- while (idx < len && pred(xs[idx])) idx++;
2617
- return xs.slice(0, idx);
2118
+ while (idx < len && predicate(input[idx], idx)) idx++;
2119
+ return input.slice(0, idx);
2618
2120
  });
2619
2121
 
2620
2122
  //#endregion
@@ -2694,7 +2196,7 @@ function create$38(context) {
2694
2196
  const { body } = component.body;
2695
2197
  for (const member of body) if (core.isComponentWillMount(member)) context.report({
2696
2198
  fix(fixer) {
2697
- if (!("key" in member)) return null;
2199
+ if (!hasProperty(member, "key")) return null;
2698
2200
  return fixer.replaceText(member.key, "UNSAFE_componentWillMount");
2699
2201
  },
2700
2202
  messageId: "default",
@@ -2727,7 +2229,7 @@ function create$37(context) {
2727
2229
  const { body } = component.body;
2728
2230
  for (const member of body) if (core.isComponentWillReceiveProps(member)) context.report({
2729
2231
  fix(fixer) {
2730
- if (!("key" in member)) return null;
2232
+ if (!hasProperty(member, "key")) return null;
2731
2233
  return fixer.replaceText(member.key, "UNSAFE_componentWillReceiveProps");
2732
2234
  },
2733
2235
  messageId: "default",
@@ -2760,7 +2262,7 @@ function create$36(context) {
2760
2262
  const { body } = component.body;
2761
2263
  for (const member of body) if (core.isComponentWillUpdate(member)) context.report({
2762
2264
  fix(fixer) {
2763
- if (!("key" in member)) return null;
2265
+ if (!hasProperty(member, "key")) return null;
2764
2266
  return fixer.replaceText(member.key, "UNSAFE_componentWillUpdate");
2765
2267
  },
2766
2268
  messageId: "default",
@@ -3005,14 +2507,6 @@ function create$31(context) {
3005
2507
  });
3006
2508
  } };
3007
2509
  }
3008
- /**
3009
- * Determine whether the given CallExpression can be safely auto-fixed by replacing
3010
- * the usage of `forwardRef` with passing `ref` as a prop
3011
- *
3012
- * @param context The rule context object
3013
- * @param node The CallExpression node to check
3014
- * @returns True if the call can be auto-fixed, false otherwise
3015
- */
3016
2510
  function couldFix(context, node) {
3017
2511
  const { importSource } = getSettingsFromContext(context);
3018
2512
  const initialScope = context.sourceCode.getScope(node);
@@ -3023,12 +2517,6 @@ function couldFix(context, node) {
3023
2517
  default: return false;
3024
2518
  }
3025
2519
  }
3026
- /**
3027
- * Generates the fix for the `forwardRef` call
3028
- * @param context The rule context
3029
- * @param node The `forwardRef` call expression
3030
- * @returns A fixer function that applies the changes
3031
- */
3032
2520
  function buildFix(context, node) {
3033
2521
  return (fixer) => {
3034
2522
  const [componentNode] = node.arguments;
@@ -3040,14 +2528,6 @@ function buildFix(context, node) {
3040
2528
  ];
3041
2529
  };
3042
2530
  }
3043
- /**
3044
- * Generates fixes for the component's props and ref arguments
3045
- * @param context The rule context
3046
- * @param fixer The rule fixer
3047
- * @param node The function component node
3048
- * @param typeArguments The type arguments from the `forwardRef` call
3049
- * @returns An array of fixes for the component's signature
3050
- */
3051
2531
  function buildFixForComponentProps(context, fixer, node, typeArguments) {
3052
2532
  const getText = (node) => context.sourceCode.getText(node);
3053
2533
  const [arg0, arg1] = node.params;
@@ -3093,22 +2573,6 @@ function buildFixForComponentProps(context, fixer, node, typeArguments) {
3093
2573
 
3094
2574
  //#endregion
3095
2575
  //#region src/utils/create-implicit-prop-listener.ts
3096
- /**
3097
- * Creates a listener that detects JSX spread attributes implicitly passing a given prop
3098
- * (ex: 'children', 'key', 'ref') to a component.
3099
- *
3100
- * For each union constituent of the spread argument's type, the prop is reported unless:
3101
- * 1. The prop symbol's fully qualified name is allowed (pass-through of React internally defined props)
3102
- * 2. The fully qualified name of the prop's type symbol (or its alias) is allowed (React type aliases)
3103
- *
3104
- * @param context The ESLint rule context
3105
- * @param options The prop name, the allow-list predicates (receive lowercased fully qualified names), and the report callback
3106
- * @param options.name The name of the prop to detect
3107
- * @param options.isAllowedProp A predicate that receives the prop symbol's lowercased fully qualified name and returns `true` if it is allowed
3108
- * @param options.isAllowedType A predicate that receives the prop's type symbol's lowercased fully qualified name and returns `true` if it is allowed
3109
- * @param options.onImplicitProp A callback invoked with the spread attribute node when an implicit prop is detected
3110
- * @returns A rule listener reporting on JSX spread attributes
3111
- */
3112
2576
  function createImplicitPropListener(context, options) {
3113
2577
  const { name, isAllowedProp, isAllowedType, onImplicitProp } = options;
3114
2578
  const services = ESLintUtils.getParserServices(context, false);
@@ -3244,12 +2708,6 @@ function create$27(context) {
3244
2708
  ...compare(version, "18.0.0", "<") ? [] : ["string", "falsy string"]
3245
2709
  ];
3246
2710
  const services = ESLintUtils.getParserServices(context, false);
3247
- /**
3248
- * Recursively inspects a node to find potential leaked conditional rendering
3249
- * @param node The AST node to inspect
3250
- * @param seen A set of visited identifier names to prevent infinite recursion.
3251
- * @returns A report descriptor if a problem is found, otherwise `null`
3252
- */
3253
2711
  function visit(node, seen = /* @__PURE__ */ new Set()) {
3254
2712
  if (node == null) return null;
3255
2713
  if (Check.isJSXExpressionContainer(node)) return visit(node.expression, seen);
@@ -3387,21 +2845,11 @@ function create$25(context) {
3387
2845
 
3388
2846
  //#endregion
3389
2847
  //#region src/rules/no-missing-key/lib.ts
3390
- /**
3391
- * Iterator-like methods whose callback's return value becomes an item in a rendered list,
3392
- * mapped to the position of the callback in the call's argument list.
3393
- * `from` covers `Array.from(iterable, mapFn)`.
3394
- */
3395
2848
  const INDEX_PARAM_POSITIONS = /* @__PURE__ */ new Map([
3396
2849
  ["flatMap", 0],
3397
2850
  ["from", 1],
3398
2851
  ["map", 0]
3399
2852
  ]);
3400
- /**
3401
- * Gets the nested return statements in the node that are within the same function
3402
- * @param node The AST node
3403
- * @returns The nested return statements in the node
3404
- */
3405
2853
  function getNestedReturnStatements$1(node) {
3406
2854
  const statements = [];
3407
2855
  const boundary = Check.isFunction(node) ? node : Traverse.findParent(node, Check.isFunction);
@@ -3430,11 +2878,6 @@ var no_missing_key_default = createRule({
3430
2878
  create: create$24,
3431
2879
  defaultOptions: []
3432
2880
  });
3433
- /**
3434
- * Gets the mapping callback of an iterator-like call expression (e.g. `.map(cb)`, `.flatMap(cb)`, `Array.from(it, cb)`).
3435
- * @param node The call expression to inspect.
3436
- * @returns The callback function node, or `null` if the call is not an iterator-like call with a function callback.
3437
- */
3438
2881
  function getIteratorCallback(node) {
3439
2882
  const callee = Extract.unwrap(node.callee);
3440
2883
  if (callee.type !== AST_NODE_TYPES.MemberExpression) return null;
@@ -3447,12 +2890,6 @@ function getIteratorCallback(node) {
3447
2890
  }
3448
2891
  function create$24(context) {
3449
2892
  let childrenToArrayDepth = 0;
3450
- /**
3451
- * Checks an expression that is rendered as an item of a list,
3452
- * recursing into the branches it may evaluate to.
3453
- * @param node The expression to check.
3454
- * @returns The report descriptors for the violations found.
3455
- */
3456
2893
  function visitItemExpression(node) {
3457
2894
  switch (node.type) {
3458
2895
  case AST_NODE_TYPES.ChainExpression:
@@ -3474,12 +2911,6 @@ function create$24(context) {
3474
2911
  default: return [];
3475
2912
  }
3476
2913
  }
3477
- /**
3478
- * Checks every value an iterator callback may produce as a list item,
3479
- * whether from an expression body or from return statements in a block body.
3480
- * @param node The callback function to check.
3481
- * @returns The report descriptors for the violations found.
3482
- */
3483
2914
  function visitIteratorCallback(node) {
3484
2915
  if (node.body.type !== AST_NODE_TYPES.BlockStatement) return visitItemExpression(node.body);
3485
2916
  return getNestedReturnStatements$1(node.body).flatMap((stmt) => stmt.argument == null ? [] : visitItemExpression(stmt.argument));
@@ -3510,23 +2941,9 @@ function create$24(context) {
3510
2941
 
3511
2942
  //#endregion
3512
2943
  //#region src/rules/no-misused-capture-owner-stack/lib.ts
3513
- /**
3514
- * Check if the given node is a member expression that accesses `process.env.NODE_ENV`
3515
- * @param context The rule context
3516
- * @param node The AST node
3517
- * @returns True if the node is a member expression that accesses `process.env.NODE_ENV`, false otherwise
3518
- */
3519
2944
  function isProcessEnvNodeEnv(context, node) {
3520
2945
  return node != null && core.isAPI("process.env.NODE_ENV")(context, node);
3521
2946
  }
3522
- /**
3523
- * Check if the given node is a binary expression that compares `process.env.NODE_ENV` with a string literal.
3524
- * @param context The rule context
3525
- * @param node The AST node
3526
- * @param operator The operator used in the comparison
3527
- * @param value The string literal value to compare against
3528
- * @returns True if the node is a binary expression that compares `process.env.NODE_ENV` with the specified value, false otherwise
3529
- */
3530
2947
  function isProcessEnvNodeEnvCompare(context, node, operator, value) {
3531
2948
  if (node == null) return false;
3532
2949
  if (node.type !== AST_NODE_TYPES.BinaryExpression) return false;
@@ -3588,44 +3005,21 @@ function create$23(context) {
3588
3005
 
3589
3006
  //#endregion
3590
3007
  //#region src/rules/no-nested-component-definitions/lib.ts
3591
- /** Check if the node is a call expression to react-redux's `connect`. */
3592
3008
  const isConnectCall = core.isAPICall("connect");
3593
- /** Check if the node is a call expression to Relay's `createFragmentContainer`. */
3594
3009
  const isCreateFragmentContainerCall = core.isAPICall("createFragmentContainer");
3595
- /** Check if the node is a call expression to Relay's `createPaginationContainer`. */
3596
3010
  const isCreatePaginationContainerCall = core.isAPICall("createPaginationContainer");
3597
- /** Check if the node is a call expression to Relay's `createRefetchContainer`. */
3598
3011
  const isCreateRefetchContainerCall = core.isAPICall("createRefetchContainer");
3599
- /** Check if the node is a call expression to React's `forwardRef`. */
3600
3012
  const isForwardRefCall = core.isAPICall("forwardRef");
3601
- /** Check if the node is a call expression to a `graphql` tag function (e.g. from Relay or Apollo). */
3602
3013
  const isGraphqlCall = core.isAPICall("graphql");
3603
- /** Check if the node is a call expression to React's `memo`. */
3604
3014
  const isMemoCall = core.isAPICall("memo");
3605
- /** Check if the node is a call expression to MobX's `observer`. */
3606
3015
  const isObserverCall = core.isAPICall("observer");
3607
- /** Check if the node is a call expression to React's `useCallback`. */
3608
3016
  const isUseCallbackCall = core.isAPICall("useCallback");
3609
- /** Check if the node is a call expression to Formik's `withFormik`. */
3610
3017
  const isWithFormikCall = core.isAPICall("withFormik");
3611
- /** Check if the node is a call expression to recompose's `withHandlers`. */
3612
3018
  const isWithHandlersCall = core.isAPICall("withHandlers");
3613
- /** Check if the node is a call expression to recompose's `withLifecycle`. */
3614
3019
  const isWithLifecycleCall = core.isAPICall("withLifecycle");
3615
- /** Check if the node is a call expression to recompose's `withProps`. */
3616
3020
  const isWithPropsCall = core.isAPICall("withProps");
3617
- /** Check if the node is a call expression to react-router v5's `withRouter`. */
3618
3021
  const isWithRouterCall = core.isAPICall("withRouter");
3619
- /** Check if the node is a call expression to recompose's `withState`. */
3620
3022
  const isWithStateCall = core.isAPICall("withState");
3621
- /**
3622
- * Check if a call is a well-known component wrapper call (e.g. `memo`, `connect`, `withFormik`).
3623
- * Curried forms like `connect(...)(Component)` are matched via the innermost callee call.
3624
- * @param context The rule context
3625
- * @param call The call expression to check
3626
- * @param arg The function node passed to the call
3627
- * @returns `true` if the call is a component wrapper call
3628
- */
3629
3023
  function isComponentWrapperCall(context, call, arg) {
3630
3024
  if (Extract.unwrap(call.callee) === arg) return false;
3631
3025
  call = getInnermostCall(call);
@@ -3646,12 +3040,6 @@ function isComponentWrapperCall(context, call, arg) {
3646
3040
  if (isWithStateCall(context, call)) return true;
3647
3041
  return false;
3648
3042
  }
3649
- /**
3650
- * Unwrap curried call wrappers like `connect(...)(Component)` to get the innermost call expression.
3651
- * Type expressions and chain expressions around each callee are unwrapped along the way.
3652
- * @param node The outermost call expression to inspect.
3653
- * @returns The innermost call expression, whose callee is not itself a call expression.
3654
- */
3655
3043
  function getInnermostCall(node) {
3656
3044
  let call = node;
3657
3045
  let callee = Extract.unwrap(call.callee);
@@ -3661,12 +3049,6 @@ function getInnermostCall(node) {
3661
3049
  }
3662
3050
  return call;
3663
3051
  }
3664
- /**
3665
- * Resolve the name a function is bound to through wrapping calls (e.g. `const C = useCallback(...)` → `C`).
3666
- * @param context The rule context
3667
- * @param node The function node to resolve the bound name for
3668
- * @returns The bound name, or `null` if the call chain does not end at an identifier declarator
3669
- */
3670
3052
  function getWrapperCallBoundName(context, node) {
3671
3053
  let current = node;
3672
3054
  let parent = current.parent;
@@ -3685,20 +3067,9 @@ function getWrapperCallBoundName(context, node) {
3685
3067
  if (parent.type !== AST_NODE_TYPES.VariableDeclarator || !Check.isIdentifier(parent.id)) return null;
3686
3068
  return parent.id.name;
3687
3069
  }
3688
- /**
3689
- * Check if the node is inside a JSX attribute value
3690
- * @param node The AST node to check
3691
- * @returns `true` if the node is inside a JSX attribute value
3692
- */
3693
3070
  function isInsideJSXAttributeValue(node) {
3694
3071
  return node.parent.type === AST_NODE_TYPES.JSXAttribute || findParentAttribute(node, (n) => n.value?.type === AST_NODE_TYPES.JSXExpressionContainer) != null;
3695
3072
  }
3696
- /**
3697
- * Check if the node is declared inside a class component's render block
3698
- * Ex: class C extends React.Component { render() { const Nested = () => <div />; } }
3699
- * @param node The AST node to check
3700
- * @returns `true` if the node is inside a class component's render block
3701
- */
3702
3073
  function isInsideRenderMethod(node) {
3703
3074
  return Traverse.findParent(node, (n) => core.isRenderMethodLike(n) && core.isClassComponent(n.parent.parent)) != null;
3704
3075
  }
@@ -4066,7 +3437,7 @@ function isContextName(name, isReact18OrBelow) {
4066
3437
  }
4067
3438
  function getHumanReadableKind$1(node) {
4068
3439
  if (node.type === AST_NODE_TYPES.Literal) {
4069
- if ("regex" in node) return "regexp literal";
3440
+ if (hasProperty(node, "regex")) return "regexp literal";
4070
3441
  if (node.value === null) return "null literal";
4071
3442
  return `${typeof node.value} literal`;
4072
3443
  }
@@ -4103,7 +3474,7 @@ function create$13(context) {
4103
3474
  if (enclosingFunction == null) return;
4104
3475
  if (compilationMode === "annotation" && core.isFunctionHasDirective(enclosingFunction, "use memo")) return;
4105
3476
  const attribute = node.attributes.find((attribute) => attribute.type === AST_NODE_TYPES.JSXAttribute && attribute.name.name === "value");
4106
- if (attribute == null || !("value" in attribute)) return;
3477
+ if (attribute == null || !hasProperty(attribute, "value")) return;
4107
3478
  const value = attribute.value;
4108
3479
  if (value?.type !== AST_NODE_TYPES.JSXExpressionContainer) return;
4109
3480
  const valueExpression = value.expression;
@@ -4141,7 +3512,7 @@ const SEL_OBJECT_DESTRUCTURING_VARIABLE_DECLARATOR = [
4141
3512
  ].join("");
4142
3513
  function getHumanReadableKind(node) {
4143
3514
  if (node.type === AST_NODE_TYPES.Literal) {
4144
- if ("regex" in node) return "regexp literal";
3515
+ if (hasProperty(node, "regex")) return "regexp literal";
4145
3516
  if (node.value === null) return "null literal";
4146
3517
  return `${typeof node.value} literal`;
4147
3518
  }
@@ -4528,9 +3899,6 @@ function create$8(context) {
4528
3899
 
4529
3900
  //#endregion
4530
3901
  //#region src/rules/purity/lib.ts
4531
- /**
4532
- * Known impure functions
4533
- */
4534
3902
  const IMPURE_FUNCS = /* @__PURE__ */ new Map([
4535
3903
  ["Atomics", /* @__PURE__ */ new Set([
4536
3904
  "add",
@@ -4781,9 +4149,6 @@ const IMPURE_FUNCS = /* @__PURE__ */ new Map([
4781
4149
  "structuredClone"
4782
4150
  ])]
4783
4151
  ]);
4784
- /**
4785
- * Known impure global constructors used with `new`
4786
- */
4787
4152
  const IMPURE_CTORS = /* @__PURE__ */ new Set([
4788
4153
  "Audio",
4789
4154
  "AudioContext",
@@ -4809,9 +4174,6 @@ const IMPURE_CTORS = /* @__PURE__ */ new Set([
4809
4174
  "Worker",
4810
4175
  "XMLHttpRequest"
4811
4176
  ]);
4812
- /**
4813
- * Known pure functions
4814
- */
4815
4177
  const PURE_FUNCS = /* @__PURE__ */ new Map([
4816
4178
  ["Array", /* @__PURE__ */ new Set([
4817
4179
  "from",
@@ -4919,18 +4281,9 @@ const PURE_FUNCS = /* @__PURE__ */ new Map([
4919
4281
  function isCatalogObject(name) {
4920
4282
  return IMPURE_FUNCS.has(name) || PURE_FUNCS.has(name);
4921
4283
  }
4922
- /**
4923
- * Check if the program has a top-level `use client` directive, marking the
4924
- * module as a client module in React Server Components conventions.
4925
- */
4926
4284
  function hasUseClientDirective(program) {
4927
4285
  return program.body.some((stmt) => stmt.type === AST_NODE_TYPES.ExpressionStatement && stmt.directive === "use client");
4928
4286
  }
4929
- /**
4930
- * Find the property key under which `name` is bound in an object destructuring
4931
- * pattern, e.g. `"random"` for `random` in `const { random } = Math` or for
4932
- * `r` in `const { random: r } = Math`.
4933
- */
4934
4287
  function getDestructuredPropertyName(pattern, name) {
4935
4288
  for (const property of pattern.properties) {
4936
4289
  if (property.type !== AST_NODE_TYPES.Property) continue;
@@ -4939,13 +4292,6 @@ function getDestructuredPropertyName(pattern, name) {
4939
4292
  }
4940
4293
  return null;
4941
4294
  }
4942
- /**
4943
- * Resolve a member expression to a builtin object name and property, e.g.
4944
- * `window.Math.random` resolves to `{ object: "Math", property: "random" }`.
4945
- * Intermediate segments are followed only while they name known catalog
4946
- * objects (`window`, `Math`, ...), so unknown-global chains like
4947
- * `foo.Math.random` do not resolve.
4948
- */
4949
4295
  function resolveBuiltinMember(context, node, seen = /* @__PURE__ */ new Set()) {
4950
4296
  const chain = Extract.getMemberChain(node);
4951
4297
  const rootId = chain.at(0);
@@ -4965,17 +4311,6 @@ function resolveBuiltinMember(context, node, seen = /* @__PURE__ */ new Set()) {
4965
4311
  property: names.at(-1) ?? null
4966
4312
  };
4967
4313
  }
4968
- /**
4969
- * Recursively resolve an identifier to a builtin global object name and
4970
- * optional property. Follows simple assignment chains like `const M = Math`,
4971
- * member-function aliases like `const random = Math.random`, and destructured
4972
- * aliases like `const { random } = Math`.
4973
- * Returns `null` if the identifier is locally defined (parameter, import, function declaration, etc.)
4974
- * or resolves to a non-builtin source.
4975
- * @param context - The rule context.
4976
- * @param node - The identifier node to resolve.
4977
- * @param seen - A set of already visited identifier names to prevent infinite loops.
4978
- */
4979
4314
  function resolveBuiltinObjectName(context, node, seen = /* @__PURE__ */ new Set()) {
4980
4315
  if (seen.has(node.name)) return null;
4981
4316
  seen.add(node.name);
@@ -5147,13 +4482,6 @@ function getRefAccess(node) {
5147
4482
  node
5148
4483
  };
5149
4484
  }
5150
- /**
5151
- * Check whether `node` (a `ref.current` MemberExpression) is assigned through a
5152
- * destructuring pattern or a for-in/of loop target, e.g.
5153
- * `({ a: ref.current } = value)`, `[ref.current] = value`,
5154
- * `({ a: ref.current.x } = value)`, or `for (ref.current of items)`. Defaults
5155
- * and computed keys inside patterns are reads, not writes.
5156
- */
5157
4485
  function isPatternWriteTarget(node) {
5158
4486
  let child = node;
5159
4487
  let current = node.parent;
@@ -5180,10 +4508,6 @@ function isPatternWriteTarget(node) {
5180
4508
  current = current.parent;
5181
4509
  }
5182
4510
  }
5183
- /**
5184
- * Check whether `node` (a `ref.current` MemberExpression) is being written to indirectly through
5185
- * a nested property write, e.g. `ref.current.inner = value` or `ref.current.inner++`.
5186
- */
5187
4511
  function isNestedRefCurrentWrite(node) {
5188
4512
  let outer = node;
5189
4513
  let sawNesting = false;
@@ -5202,11 +4526,6 @@ function isNestedRefCurrentWrite(node) {
5202
4526
  return false;
5203
4527
  }
5204
4528
  }
5205
- /**
5206
- * Parse an exact nullish check and return the branch where the checked value is null/undefined.
5207
- * Truthiness checks such as `!ref.current` are deliberately excluded: falsy ref values are not
5208
- * necessarily uninitialized.
5209
- */
5210
4529
  function getNullCheckBranch(test, isCheckedValue, isNullishValue) {
5211
4530
  const unwrapped = Extract.unwrap(test);
5212
4531
  if (unwrapped.type === AST_NODE_TYPES.UnaryExpression && unwrapped.operator === "!") {
@@ -5245,7 +4564,6 @@ function getGuardDisposition(node, getNullBranch) {
5245
4564
  }
5246
4565
  return null;
5247
4566
  }
5248
- /** Return whether every path through a statement exits the current function. */
5249
4567
  function isUnconditionallyTerminating(statement) {
5250
4568
  switch (statement.type) {
5251
4569
  case AST_NODE_TYPES.ReturnStatement:
@@ -5279,14 +4597,6 @@ function isAfterTerminatingNonNullGuard(node, getNullBranch) {
5279
4597
 
5280
4598
  //#endregion
5281
4599
  //#region src/rules/refs/collect.ts
5282
- /**
5283
- * Collect the raw facts the refs rule reasons about: identifier/member/function
5284
- * bindings with their source positions, JSX `ref` attribute targets, call
5285
- * expressions, ref pass sites (calls, constructor calls, tagged templates), and
5286
- * every `.current` member access. Facts outside any function are never
5287
- * reachable during render and are not collected. All inference is deferred to
5288
- * `Program:exit`.
5289
- */
5290
4600
  function createFactCollector$4() {
5291
4601
  const facts = {
5292
4602
  bindings: [],
@@ -5386,11 +4696,9 @@ function createFactCollector$4() {
5386
4696
 
5387
4697
  //#endregion
5388
4698
  //#region src/rules/refs/effects.ts
5389
- /** The nearest strict ancestor of `node` that is a component or hook. */
5390
4699
  function findBoundary(node, boundaries) {
5391
4700
  return Traverse.findParent(node, (candidate) => Check.isFunction(candidate) && boundaries.has(candidate));
5392
4701
  }
5393
- /** The boundary containing `node`, where `node` is the nearest enclosing function of the fact. */
5394
4702
  function getBoundaryOf(node, boundaries) {
5395
4703
  return boundaries.has(node) ? node : findBoundary(node, boundaries);
5396
4704
  }
@@ -5398,12 +4706,6 @@ function isReachedDuringRender(node, boundary, reachability) {
5398
4706
  const reached = reachability.get(boundary);
5399
4707
  return reached != null && isReachedThroughFunctions(node, boundary, reached);
5400
4708
  }
5401
- /**
5402
- * Resolve the collected call edges into a per-boundary render call graph.
5403
- * Direct calls, IIFEs, known synchronous callbacks, function declarations,
5404
- * aliases, and simple object-property bindings all share the same
5405
- * identity-based resolver. Each call target is resolved exactly once.
5406
- */
5407
4709
  function inferCallGraph(boundaries, callEdges, resolveCallable) {
5408
4710
  const callGraph = /* @__PURE__ */ new Map();
5409
4711
  for (const edge of callEdges) {
@@ -5426,10 +4728,6 @@ function inferCallGraph(boundaries, callEdges, resolveCallable) {
5426
4728
  }
5427
4729
  return callGraph;
5428
4730
  }
5429
- /**
5430
- * Walk the call graph from each render boundary and gather every function
5431
- * reached during that boundary's render.
5432
- */
5433
4731
  function collectReachableFunctions(boundaries, callGraph) {
5434
4732
  const reachedByBoundary = /* @__PURE__ */ new Map();
5435
4733
  for (const boundary of boundaries) {
@@ -5446,10 +4744,6 @@ function collectReachableFunctions(boundaries, callGraph) {
5446
4744
  }
5447
4745
  return reachedByBoundary;
5448
4746
  }
5449
- /**
5450
- * Validate the reached `.current` accesses and track the one permitted lazy
5451
- * initialization per ref.
5452
- */
5453
4747
  function inferRefViolations(accesses, boundaries, reachability, resolver) {
5454
4748
  const violations = [];
5455
4749
  const initializedRefs = /* @__PURE__ */ new Map();
@@ -5486,31 +4780,18 @@ function inferRefViolations(accesses, boundaries, reachability, resolver) {
5486
4780
  }
5487
4781
  return violations;
5488
4782
  }
5489
- /**
5490
- * Get the statically known name of a pass-site callee, whether it is a plain
5491
- * call, a constructor call, or a tagged template.
5492
- */
5493
4783
  function getPassSiteCalleeName(node) {
5494
4784
  const callee = Extract.unwrap(node.type === AST_NODE_TYPES.TaggedTemplateExpression ? node.tag : node.callee);
5495
4785
  if (Check.isIdentifier(callee)) return callee.name;
5496
4786
  if (callee.type === AST_NODE_TYPES.MemberExpression && !callee.computed && Check.isIdentifier(callee.property)) return callee.property.name;
5497
4787
  return null;
5498
4788
  }
5499
- /**
5500
- * The `mergeRefs` exemption is name-based but alias-aware: a simple variable
5501
- * alias of a `mergeRefs` binding keeps the exemption.
5502
- */
5503
4789
  function isMergeRefsCallee(callee, calleeName, position, resolver) {
5504
4790
  if (calleeName === "mergeRefs") return true;
5505
4791
  if (callee.type !== AST_NODE_TYPES.Identifier) return false;
5506
4792
  const variable = resolver.getVariable(callee);
5507
4793
  return variable != null && resolver.resolveAliasTarget(variable, position).name === "mergeRefs";
5508
4794
  }
5509
- /**
5510
- * Passing a ref to an unknown function can expose its value during render.
5511
- * Hook callbacks, mergeRefs, and the existing render-prop compatibility case
5512
- * remain exempt.
5513
- */
5514
4795
  function inferRefPassViolations(passSites, boundaries, reachability, resolver) {
5515
4796
  const violations = [];
5516
4797
  for (const site of passSites) {
@@ -5540,11 +4821,6 @@ function inferRefPassViolations(passSites, boundaries, reachability, resolver) {
5540
4821
 
5541
4822
  //#endregion
5542
4823
  //#region src/rules/refs/origins.ts
5543
- /**
5544
- * Resolve which variables hold refs and which resolve to callable functions.
5545
- * Maps are keyed by ESLint variables, not source names, so shadowed
5546
- * identifiers and separate components cannot contaminate each other.
5547
- */
5548
4824
  function createBindingResolver(context, facts) {
5549
4825
  const { additionalRefHooks } = getSettingsFromContext(context);
5550
4826
  const bindings = /* @__PURE__ */ new Map();
@@ -5637,11 +4913,6 @@ function createBindingResolver(context, facts) {
5637
4913
  case "unknown": return null;
5638
4914
  }
5639
4915
  }
5640
- /**
5641
- * Follow simple variable-to-variable aliases to the terminal variable, e.g.
5642
- * `const combine = mergeRefs` resolves to the `mergeRefs` variable itself.
5643
- * Position-aware, so a reassigned alias resolves to its latest source.
5644
- */
5645
4916
  function resolveAliasTarget(variable, position, seen = /* @__PURE__ */ new Set()) {
5646
4917
  if (seen.has(variable)) return variable;
5647
4918
  seen.add(variable);
@@ -5753,38 +5024,17 @@ function create$6(context) {
5753
5024
  function assert(cond, message) {
5754
5025
  if (!cond) throw new Error(message ?? "Assertion violated.");
5755
5026
  }
5756
- /**
5757
- * Checks whether or not a given segment is reachable.
5758
- */
5759
5027
  function isReachable$1(segment) {
5760
5028
  return segment.reachable;
5761
5029
  }
5762
- /**
5763
- * A code path segment.
5764
- */
5765
5030
  var CodePathSegment = class CodePathSegment {
5766
- /**
5767
- * The identifier of this code path.
5768
- * Rules use it to store additional information of each rule.
5769
- */
5770
5031
  id;
5771
- /** An array of the next reachable segments. */
5772
5032
  nextSegments;
5773
- /** An array of the previous reachable segments. */
5774
5033
  prevSegments;
5775
- /** An array of all next segments (including unreachable). */
5776
5034
  allNextSegments;
5777
- /** An array of all previous segments (including unreachable). */
5778
5035
  allPrevSegments;
5779
- /** Whether this segment is reachable. */
5780
5036
  reachable;
5781
- /** Internal bookkeeping data. */
5782
5037
  internal;
5783
- /**
5784
- * @param id An identifier.
5785
- * @param allPrevSegments An array of the previous segments (including unreachable).
5786
- * @param reachable Whether this segment is reachable.
5787
- */
5788
5038
  constructor(id, allPrevSegments, reachable) {
5789
5039
  this.id = id;
5790
5040
  this.nextSegments = [];
@@ -5797,44 +5047,23 @@ var CodePathSegment = class CodePathSegment {
5797
5047
  loopedPrevSegments: []
5798
5048
  };
5799
5049
  }
5800
- /**
5801
- * Checks if a given previous segment is coming from the end of a loop.
5802
- */
5803
5050
  isLoopedPrevSegment(segment) {
5804
5051
  return this.internal.loopedPrevSegments.includes(segment);
5805
5052
  }
5806
- /**
5807
- * Creates the root segment.
5808
- */
5809
5053
  static newRoot(id) {
5810
5054
  return new CodePathSegment(id, [], true);
5811
5055
  }
5812
- /**
5813
- * Creates a segment that follows given segments.
5814
- */
5815
5056
  static newNext(id, allPrevSegments) {
5816
5057
  return new CodePathSegment(id, CodePathSegment.flattenUnusedSegments(allPrevSegments), allPrevSegments.some(isReachable$1));
5817
5058
  }
5818
- /**
5819
- * Creates an unreachable segment that follows given segments.
5820
- */
5821
5059
  static newUnreachable(id, allPrevSegments) {
5822
5060
  const segment = new CodePathSegment(id, CodePathSegment.flattenUnusedSegments(allPrevSegments), false);
5823
5061
  CodePathSegment.markUsed(segment);
5824
5062
  return segment;
5825
5063
  }
5826
- /**
5827
- * Creates a segment that follows given segments.
5828
- * This factory method does not connect with `allPrevSegments`.
5829
- * But this inherits `reachable` flag.
5830
- */
5831
5064
  static newDisconnected(id, allPrevSegments) {
5832
5065
  return new CodePathSegment(id, [], allPrevSegments.some(isReachable$1));
5833
5066
  }
5834
- /**
5835
- * Makes a given segment being used.
5836
- * Also registers the segment into the previous segments as a next.
5837
- */
5838
5067
  static markUsed(segment) {
5839
5068
  if (segment.internal.used) return;
5840
5069
  segment.internal.used = true;
@@ -5846,15 +5075,9 @@ var CodePathSegment = class CodePathSegment {
5846
5075
  }
5847
5076
  else for (i = 0; i < segment.allPrevSegments.length; ++i) segment.allPrevSegments[i].allNextSegments.push(segment);
5848
5077
  }
5849
- /**
5850
- * Marks a previous segment as looped.
5851
- */
5852
5078
  static markPrevSegmentAsLooped(segment, prevSegment) {
5853
5079
  segment.internal.loopedPrevSegments.push(prevSegment);
5854
5080
  }
5855
- /**
5856
- * Replaces unused segments with the previous segments of each unused segment.
5857
- */
5858
5081
  static flattenUnusedSegments(segments) {
5859
5082
  const done = Object.create(null);
5860
5083
  const retv = [];
@@ -5876,19 +5099,9 @@ var CodePathSegment = class CodePathSegment {
5876
5099
  return retv;
5877
5100
  }
5878
5101
  };
5879
- /**
5880
- * Gets whether or not a given segment is reachable.
5881
- */
5882
5102
  function isReachable(segment) {
5883
5103
  return segment.reachable;
5884
5104
  }
5885
- /**
5886
- * Creates new segments from the specific range of `context.segmentsList`.
5887
- *
5888
- * When `context.segmentsList` is `[[a, b], [c, d], [e, f]]`, `begin` is `0`, and
5889
- * `end` is `-1`, this creates `[g, h]`. This `g` is from `a`, `c`, and `e`.
5890
- * This `h` is from `b`, `d`, and `f`.
5891
- */
5892
5105
  function makeSegments(context, begin, end, create) {
5893
5106
  const list = context.segmentsList;
5894
5107
  const normalizedBegin = begin >= 0 ? begin : list.length + begin;
@@ -5901,12 +5114,6 @@ function makeSegments(context, begin, end, create) {
5901
5114
  }
5902
5115
  return segments;
5903
5116
  }
5904
- /**
5905
- * `segments` becomes doubly in a `finally` block. Then if a code path exits by a
5906
- * control statement (such as `break`, `continue`) from the `finally` block, the
5907
- * destination's segments may be half of the source segments. In that case, this
5908
- * merges segments.
5909
- */
5910
5117
  function mergeExtraSegments(context, segments) {
5911
5118
  let currentSegments = segments;
5912
5119
  while (currentSegments.length > context.count) {
@@ -5916,9 +5123,6 @@ function mergeExtraSegments(context, segments) {
5916
5123
  }
5917
5124
  return currentSegments;
5918
5125
  }
5919
- /**
5920
- * A class to manage forking.
5921
- */
5922
5126
  var ForkContext = class ForkContext {
5923
5127
  idGenerator;
5924
5128
  upper;
@@ -5930,91 +5134,51 @@ var ForkContext = class ForkContext {
5930
5134
  this.count = count;
5931
5135
  this.segmentsList = [];
5932
5136
  }
5933
- /** The head segments. */
5934
5137
  get head() {
5935
5138
  const list = this.segmentsList;
5936
5139
  return list.length === 0 ? [] : list[list.length - 1];
5937
5140
  }
5938
- /** Whether the segments list is empty. */
5939
5141
  get empty() {
5940
5142
  return this.segmentsList.length === 0;
5941
5143
  }
5942
- /** Whether any head segment is reachable. */
5943
5144
  get reachable() {
5944
5145
  const segments = this.head;
5945
5146
  return segments.length > 0 && segments.some(isReachable);
5946
5147
  }
5947
- /**
5948
- * Creates new segments from this context.
5949
- */
5950
5148
  makeNext(begin, end) {
5951
5149
  return makeSegments(this, begin, end, CodePathSegment.newNext);
5952
5150
  }
5953
- /**
5954
- * Creates new unreachable segments from this context.
5955
- */
5956
5151
  makeUnreachable(begin, end) {
5957
5152
  return makeSegments(this, begin, end, CodePathSegment.newUnreachable);
5958
5153
  }
5959
- /**
5960
- * Creates new disconnected segments from this context.
5961
- * The new segments don't have connections for previous segments,
5962
- * but inherit the reachable flag.
5963
- */
5964
5154
  makeDisconnected(begin, end) {
5965
5155
  return makeSegments(this, begin, end, CodePathSegment.newDisconnected);
5966
5156
  }
5967
- /**
5968
- * Adds segments into this context. The added segments become the head.
5969
- */
5970
5157
  add(segments) {
5971
5158
  assert(segments.length >= this.count, `${segments.length} >= ${this.count}`);
5972
5159
  this.segmentsList.push(mergeExtraSegments(this, segments));
5973
5160
  }
5974
- /**
5975
- * Replaces the head segments with given segments.
5976
- * The current head segments are removed.
5977
- */
5978
5161
  replaceHead(segments) {
5979
5162
  assert(segments.length >= this.count, `${segments.length} >= ${this.count}`);
5980
5163
  this.segmentsList.splice(-1, 1, mergeExtraSegments(this, segments));
5981
5164
  }
5982
- /**
5983
- * Adds all segments of a given fork context into this context.
5984
- */
5985
5165
  addAll(context) {
5986
5166
  assert(context.count === this.count);
5987
5167
  const source = context.segmentsList;
5988
5168
  for (let i = 0; i < source.length; ++i) this.segmentsList.push(source[i]);
5989
5169
  }
5990
- /**
5991
- * Clears all segments in this context.
5992
- */
5993
5170
  clear() {
5994
5171
  this.segmentsList = [];
5995
5172
  }
5996
- /**
5997
- * Creates the root fork context.
5998
- */
5999
5173
  static newRoot(idGenerator) {
6000
5174
  const context = new ForkContext(idGenerator, null, 1);
6001
5175
  context.add([CodePathSegment.newRoot(idGenerator.next())]);
6002
5176
  return context;
6003
5177
  }
6004
- /**
6005
- * Creates an empty fork context preceded by a given context.
6006
- */
6007
5178
  static newEmpty(parentContext, forkLeavingPath) {
6008
5179
  return new ForkContext(parentContext.idGenerator, parentContext, (forkLeavingPath ? 2 : 1) * parentContext.count);
6009
5180
  }
6010
5181
  };
6011
- /**
6012
- * Adds given segments into the `dest` array.
6013
- * If the `others` array does not include the given segments, adds to the `all`
6014
- * array as well.
6015
- *
6016
- * This adds only reachable and used segments.
6017
- */
6018
5182
  function addToReturnedOrThrown(dest, others, all, segments) {
6019
5183
  for (let i = 0; i < segments.length; ++i) {
6020
5184
  const segment = segments[i];
@@ -6022,9 +5186,6 @@ function addToReturnedOrThrown(dest, others, all, segments) {
6022
5186
  if (!others.includes(segment)) all.push(segment);
6023
5187
  }
6024
5188
  }
6025
- /**
6026
- * Gets a loop-context for a `continue` statement.
6027
- */
6028
5189
  function getContinueContext(state, label) {
6029
5190
  if (!label) return state.loopContext;
6030
5191
  let context = state.loopContext;
@@ -6035,9 +5196,6 @@ function getContinueContext(state, label) {
6035
5196
  /* c8 ignore next */
6036
5197
  return null;
6037
5198
  }
6038
- /**
6039
- * Gets a context for a `break` statement.
6040
- */
6041
5199
  function getBreakContext(state, label) {
6042
5200
  let context = state.breakContext;
6043
5201
  while (context) {
@@ -6047,9 +5205,6 @@ function getBreakContext(state, label) {
6047
5205
  /* c8 ignore next */
6048
5206
  return null;
6049
5207
  }
6050
- /**
6051
- * Gets a context for a `return` statement.
6052
- */
6053
5208
  function getReturnContext(state) {
6054
5209
  let context = state.tryContext;
6055
5210
  while (context) {
@@ -6058,9 +5213,6 @@ function getReturnContext(state) {
6058
5213
  }
6059
5214
  return state;
6060
5215
  }
6061
- /**
6062
- * Gets a context for a `throw` statement.
6063
- */
6064
5216
  function getThrowContext(state) {
6065
5217
  let context = state.tryContext;
6066
5218
  while (context) {
@@ -6069,19 +5221,9 @@ function getThrowContext(state) {
6069
5221
  }
6070
5222
  return state;
6071
5223
  }
6072
- /**
6073
- * Removes a given element from a given array.
6074
- */
6075
5224
  function remove(xs, x) {
6076
5225
  xs.splice(xs.indexOf(x), 1);
6077
5226
  }
6078
- /**
6079
- * Disconnect given segments.
6080
- *
6081
- * This is used in a process for switch statements.
6082
- * If there is the "default" chunk before other cases, the order is different
6083
- * between node's and running's.
6084
- */
6085
5227
  function removeConnection(prevSegments, nextSegments) {
6086
5228
  for (let i = 0; i < prevSegments.length; ++i) {
6087
5229
  const prevSegment = prevSegments[i];
@@ -6092,9 +5234,6 @@ function removeConnection(prevSegments, nextSegments) {
6092
5234
  remove(nextSegment.allPrevSegments, prevSegment);
6093
5235
  }
6094
5236
  }
6095
- /**
6096
- * Creates looping path.
6097
- */
6098
5237
  function makeLooped(state, unflattenedFromSegments, unflattenedToSegments) {
6099
5238
  const fromSegments = CodePathSegment.flattenUnusedSegments(unflattenedFromSegments);
6100
5239
  const toSegments = CodePathSegment.flattenUnusedSegments(unflattenedToSegments);
@@ -6110,12 +5249,6 @@ function makeLooped(state, unflattenedFromSegments, unflattenedToSegments) {
6110
5249
  state.notifyLooped(fromSegment, toSegment);
6111
5250
  }
6112
5251
  }
6113
- /**
6114
- * Finalizes segments of `test` chunk of a ForStatement.
6115
- *
6116
- * - Adds `false` paths to paths which are leaving from the loop.
6117
- * - Sets `true` paths to paths which go to the body.
6118
- */
6119
5252
  function finalizeTestSegmentsOfFor(context, choiceContext, head) {
6120
5253
  if (!choiceContext.processed) {
6121
5254
  choiceContext.trueForkContext.add(head);
@@ -6125,9 +5258,6 @@ function finalizeTestSegmentsOfFor(context, choiceContext, head) {
6125
5258
  if (context.test !== true) context.brokenForkContext.addAll(choiceContext.falseForkContext);
6126
5259
  context.endOfTestSegments = choiceContext.trueForkContext.makeNext(0, -1);
6127
5260
  }
6128
- /**
6129
- * A class which manages state to analyze code paths.
6130
- */
6131
5261
  var CodePathState = class {
6132
5262
  idGenerator;
6133
5263
  notifyLooped;
@@ -6164,60 +5294,29 @@ var CodePathState = class {
6164
5294
  returned.add = addToReturnedOrThrown.bind(null, returned, thrown, final);
6165
5295
  thrown.add = addToReturnedOrThrown.bind(null, thrown, returned, final);
6166
5296
  }
6167
- /** The head segments. */
6168
5297
  get headSegments() {
6169
5298
  return this.forkContext.head;
6170
5299
  }
6171
- /**
6172
- * The parent forking context.
6173
- * This is used for the root of new forks.
6174
- */
6175
5300
  get parentForkContext() {
6176
5301
  const current = this.forkContext;
6177
5302
  return current && current.upper;
6178
5303
  }
6179
- /**
6180
- * Creates and stacks new forking context.
6181
- */
6182
5304
  pushForkContext(forkLeavingPath) {
6183
5305
  this.forkContext = ForkContext.newEmpty(this.forkContext, forkLeavingPath);
6184
5306
  return this.forkContext;
6185
5307
  }
6186
- /**
6187
- * Pops and merges the last forking context.
6188
- */
6189
5308
  popForkContext() {
6190
5309
  const lastContext = this.forkContext;
6191
5310
  this.forkContext = lastContext.upper;
6192
5311
  this.forkContext.replaceHead(lastContext.makeNext(0, -1));
6193
5312
  return lastContext;
6194
5313
  }
6195
- /**
6196
- * Creates a new path.
6197
- */
6198
5314
  forkPath() {
6199
5315
  this.forkContext.add(this.parentForkContext.makeNext(-1, -1));
6200
5316
  }
6201
- /**
6202
- * Creates a bypass path.
6203
- * This is used for such as IfStatement which does not have "else" chunk.
6204
- */
6205
5317
  forkBypassPath() {
6206
5318
  this.forkContext.add(this.parentForkContext.head);
6207
5319
  }
6208
- /**
6209
- * Creates a context for ConditionalExpression, LogicalExpression,
6210
- * AssignmentExpression (logical assignments only), IfStatement,
6211
- * WhileStatement, DoWhileStatement, or ForStatement.
6212
- *
6213
- * @param kind A kind string.
6214
- * If the new context is LogicalExpression's or AssignmentExpression's,
6215
- * this is `"&&"` or `"||"` or `"??"`.
6216
- * If it's IfStatement's or ConditionalExpression's, this is `"test"`.
6217
- * Otherwise, this is `"loop"`.
6218
- * @param isForkingAsResult A flag that shows that goes different
6219
- * paths between `true` and `false`.
6220
- */
6221
5320
  pushChoiceContext(kind, isForkingAsResult) {
6222
5321
  this.choiceContext = {
6223
5322
  upper: this.choiceContext,
@@ -6229,9 +5328,6 @@ var CodePathState = class {
6229
5328
  processed: false
6230
5329
  };
6231
5330
  }
6232
- /**
6233
- * Pops the last choice context and finalizes it.
6234
- */
6235
5331
  popChoiceContext() {
6236
5332
  const context = this.choiceContext;
6237
5333
  this.choiceContext = context.upper;
@@ -6272,10 +5368,6 @@ var CodePathState = class {
6272
5368
  forkContext.replaceHead(prevForkContext.makeNext(0, -1));
6273
5369
  return context;
6274
5370
  }
6275
- /**
6276
- * Makes a code path segment of the right-hand operand of a logical
6277
- * expression.
6278
- */
6279
5371
  makeLogicalRight() {
6280
5372
  const context = this.choiceContext;
6281
5373
  const forkContext = this.forkContext;
@@ -6313,9 +5405,6 @@ var CodePathState = class {
6313
5405
  forkContext.replaceHead(forkContext.makeNext(-1, -1));
6314
5406
  }
6315
5407
  }
6316
- /**
6317
- * Makes a code path segment of the `if` block.
6318
- */
6319
5408
  makeIfConsequent() {
6320
5409
  const context = this.choiceContext;
6321
5410
  const forkContext = this.forkContext;
@@ -6327,9 +5416,6 @@ var CodePathState = class {
6327
5416
  context.processed = false;
6328
5417
  forkContext.replaceHead(context.trueForkContext.makeNext(0, -1));
6329
5418
  }
6330
- /**
6331
- * Makes a code path segment of the `else` block.
6332
- */
6333
5419
  makeIfAlternate() {
6334
5420
  const context = this.choiceContext;
6335
5421
  const forkContext = this.forkContext;
@@ -6338,50 +5424,26 @@ var CodePathState = class {
6338
5424
  context.processed = true;
6339
5425
  forkContext.replaceHead(context.falseForkContext.makeNext(0, -1));
6340
5426
  }
6341
- /**
6342
- * Push a new `ChainExpression` context to the stack.
6343
- * This method is called on entering to each `ChainExpression` node.
6344
- * This context is used to count forking in the optional chain then merge
6345
- * them on exiting from the `ChainExpression` node.
6346
- */
6347
5427
  pushChainContext() {
6348
5428
  this.chainContext = {
6349
5429
  upper: this.chainContext,
6350
5430
  countChoiceContexts: 0
6351
5431
  };
6352
5432
  }
6353
- /**
6354
- * Pop a `ChainExpression` context from the stack.
6355
- * This method is called on exiting from each `ChainExpression` node.
6356
- * This merges all forks of the last optional chaining.
6357
- */
6358
5433
  popChainContext() {
6359
5434
  const context = this.chainContext;
6360
5435
  this.chainContext = context.upper;
6361
5436
  for (let i = context.countChoiceContexts; i > 0; --i) this.popChoiceContext();
6362
5437
  }
6363
- /**
6364
- * Create a choice context for optional access.
6365
- * This method is called on entering to each `(Call|Member)Expression[optional=true]` node.
6366
- * This creates a choice context as similar to `LogicalExpression[operator="??"]` node.
6367
- */
6368
5438
  makeOptionalNode() {
6369
5439
  if (this.chainContext) {
6370
5440
  this.chainContext.countChoiceContexts += 1;
6371
5441
  this.pushChoiceContext("??", false);
6372
5442
  }
6373
5443
  }
6374
- /**
6375
- * Create a fork.
6376
- * This method is called on entering to the `arguments|property` property
6377
- * of each `(Call|Member)Expression` node.
6378
- */
6379
5444
  makeOptionalRight() {
6380
5445
  if (this.chainContext) this.makeLogicalRight();
6381
5446
  }
6382
- /**
6383
- * Creates a context object of SwitchStatement and stacks it.
6384
- */
6385
5447
  pushSwitchContext(hasCase, label) {
6386
5448
  this.switchContext = {
6387
5449
  upper: this.switchContext,
@@ -6394,14 +5456,6 @@ var CodePathState = class {
6394
5456
  };
6395
5457
  this.pushBreakContext(true, label);
6396
5458
  }
6397
- /**
6398
- * Pops the last context of SwitchStatement and finalizes it.
6399
- *
6400
- * - Disposes all forking stack for `case` and `default`.
6401
- * - Creates the next code path segment from `context.brokenForkContext`.
6402
- * - If the last `SwitchCase` node is not a `default` part, creates a path
6403
- * to the `default` body.
6404
- */
6405
5459
  popSwitchContext() {
6406
5460
  const context = this.switchContext;
6407
5461
  this.switchContext = context.upper;
@@ -6427,9 +5481,6 @@ var CodePathState = class {
6427
5481
  for (let i = 0; i < context.countForks; ++i) this.forkContext = this.forkContext.upper;
6428
5482
  this.forkContext.replaceHead(brokenForkContext.makeNext(0, -1));
6429
5483
  }
6430
- /**
6431
- * Makes a code path segment for a `SwitchCase` node.
6432
- */
6433
5484
  makeSwitchCaseBody(isEmpty, isDefault) {
6434
5485
  const context = this.switchContext;
6435
5486
  if (!context.hasCase) return;
@@ -6447,9 +5498,6 @@ var CodePathState = class {
6447
5498
  context.lastIsDefault = isDefault;
6448
5499
  context.countForks += 1;
6449
5500
  }
6450
- /**
6451
- * Creates a context object of TryStatement and stacks it.
6452
- */
6453
5501
  pushTryContext(hasFinalizer) {
6454
5502
  this.tryContext = {
6455
5503
  upper: this.tryContext,
@@ -6461,9 +5509,6 @@ var CodePathState = class {
6461
5509
  lastOfCatchIsReachable: false
6462
5510
  };
6463
5511
  }
6464
- /**
6465
- * Pops the last context of TryStatement and finalizes it.
6466
- */
6467
5512
  popTryContext() {
6468
5513
  const context = this.tryContext;
6469
5514
  this.tryContext = context.upper;
@@ -6483,9 +5528,6 @@ var CodePathState = class {
6483
5528
  this.forkContext.replaceHead(normalSegments);
6484
5529
  if (!context.lastOfTryIsReachable && !context.lastOfCatchIsReachable) this.forkContext.makeUnreachable(-1, -1);
6485
5530
  }
6486
- /**
6487
- * Makes a code path segment for a `catch` block.
6488
- */
6489
5531
  makeCatchBlock() {
6490
5532
  const context = this.tryContext;
6491
5533
  const forkContext = this.forkContext;
@@ -6499,13 +5541,6 @@ var CodePathState = class {
6499
5541
  this.forkBypassPath();
6500
5542
  this.forkContext.add(thrownSegments);
6501
5543
  }
6502
- /**
6503
- * Makes a code path segment for a `finally` block.
6504
- *
6505
- * In the `finally` block, parallel paths are created. The parallel paths
6506
- * are used as leaving-paths. The leaving-paths are paths from `return`
6507
- * statements and `throw` statements in a `try` block or a `catch` block.
6508
- */
6509
5544
  makeFinallyBlock() {
6510
5545
  const context = this.tryContext;
6511
5546
  let forkContext = this.forkContext;
@@ -6529,10 +5564,6 @@ var CodePathState = class {
6529
5564
  this.pushForkContext(true);
6530
5565
  this.forkContext.add(segments);
6531
5566
  }
6532
- /**
6533
- * Makes a code path segment from the first throwable node to the `catch`
6534
- * block or the `finally` block.
6535
- */
6536
5567
  makeFirstThrowablePathInTryBlock() {
6537
5568
  const forkContext = this.forkContext;
6538
5569
  if (!forkContext.reachable) return;
@@ -6541,9 +5572,6 @@ var CodePathState = class {
6541
5572
  context.thrownForkContext.add(forkContext.head);
6542
5573
  forkContext.replaceHead(forkContext.makeNext(-1, -1));
6543
5574
  }
6544
- /**
6545
- * Creates a context object of a loop statement and stacks it.
6546
- */
6547
5575
  pushLoopContext(type, label) {
6548
5576
  const forkContext = this.forkContext;
6549
5577
  const breakContext = this.pushBreakContext(true, label);
@@ -6603,9 +5631,6 @@ var CodePathState = class {
6603
5631
  default: throw new Error(`unknown type: "${type}"`);
6604
5632
  }
6605
5633
  }
6606
- /**
6607
- * Pops the last context of a loop statement and finalizes it.
6608
- */
6609
5634
  popLoopContext() {
6610
5635
  const context = this.loopContext;
6611
5636
  this.loopContext = context.upper;
@@ -6638,9 +5663,6 @@ var CodePathState = class {
6638
5663
  if (brokenForkContext.empty) forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
6639
5664
  else forkContext.replaceHead(brokenForkContext.makeNext(0, -1));
6640
5665
  }
6641
- /**
6642
- * Makes a code path segment for the test part of a WhileStatement.
6643
- */
6644
5666
  makeWhileTest(test) {
6645
5667
  const context = this.loopContext;
6646
5668
  const forkContext = this.forkContext;
@@ -6649,9 +5671,6 @@ var CodePathState = class {
6649
5671
  context.continueDestSegments = testSegments;
6650
5672
  forkContext.replaceHead(testSegments);
6651
5673
  }
6652
- /**
6653
- * Makes a code path segment for the body part of a WhileStatement.
6654
- */
6655
5674
  makeWhileBody() {
6656
5675
  const context = this.loopContext;
6657
5676
  const choiceContext = this.choiceContext;
@@ -6663,9 +5682,6 @@ var CodePathState = class {
6663
5682
  if (context.test !== true) context.brokenForkContext.addAll(choiceContext.falseForkContext);
6664
5683
  forkContext.replaceHead(choiceContext.trueForkContext.makeNext(0, -1));
6665
5684
  }
6666
- /**
6667
- * Makes a code path segment for the body part of a DoWhileStatement.
6668
- */
6669
5685
  makeDoWhileBody() {
6670
5686
  const context = this.loopContext;
6671
5687
  const forkContext = this.forkContext;
@@ -6673,9 +5689,6 @@ var CodePathState = class {
6673
5689
  context.entrySegments = bodySegments;
6674
5690
  forkContext.replaceHead(bodySegments);
6675
5691
  }
6676
- /**
6677
- * Makes a code path segment for the test part of a DoWhileStatement.
6678
- */
6679
5692
  makeDoWhileTest(test) {
6680
5693
  const context = this.loopContext;
6681
5694
  const forkContext = this.forkContext;
@@ -6686,9 +5699,6 @@ var CodePathState = class {
6686
5699
  forkContext.replaceHead(testSegments);
6687
5700
  }
6688
5701
  }
6689
- /**
6690
- * Makes a code path segment for the test part of a ForStatement.
6691
- */
6692
5702
  makeForTest(test) {
6693
5703
  const context = this.loopContext;
6694
5704
  const forkContext = this.forkContext;
@@ -6699,9 +5709,6 @@ var CodePathState = class {
6699
5709
  context.continueDestSegments = context.testSegments = testSegments;
6700
5710
  forkContext.replaceHead(testSegments);
6701
5711
  }
6702
- /**
6703
- * Makes a code path segment for the update part of a ForStatement.
6704
- */
6705
5712
  makeForUpdate() {
6706
5713
  const context = this.loopContext;
6707
5714
  const choiceContext = this.choiceContext;
@@ -6712,9 +5719,6 @@ var CodePathState = class {
6712
5719
  context.continueDestSegments = context.updateSegments = updateSegments;
6713
5720
  forkContext.replaceHead(updateSegments);
6714
5721
  }
6715
- /**
6716
- * Makes a code path segment for the body part of a ForStatement.
6717
- */
6718
5722
  makeForBody() {
6719
5723
  const context = this.loopContext;
6720
5724
  const choiceContext = this.choiceContext;
@@ -6734,10 +5738,6 @@ var CodePathState = class {
6734
5738
  context.continueDestSegments = context.continueDestSegments || bodySegments;
6735
5739
  forkContext.replaceHead(bodySegments);
6736
5740
  }
6737
- /**
6738
- * Makes a code path segment for the left part of a ForInStatement and a
6739
- * ForOfStatement.
6740
- */
6741
5741
  makeForInOfLeft() {
6742
5742
  const context = this.loopContext;
6743
5743
  const forkContext = this.forkContext;
@@ -6746,10 +5746,6 @@ var CodePathState = class {
6746
5746
  context.leftSegments = context.continueDestSegments = leftSegments;
6747
5747
  forkContext.replaceHead(leftSegments);
6748
5748
  }
6749
- /**
6750
- * Makes a code path segment for the right part of a ForInStatement and a
6751
- * ForOfStatement.
6752
- */
6753
5749
  makeForInOfRight() {
6754
5750
  const context = this.loopContext;
6755
5751
  const forkContext = this.forkContext;
@@ -6759,10 +5755,6 @@ var CodePathState = class {
6759
5755
  context.endOfLeftSegments = forkContext.head;
6760
5756
  forkContext.replaceHead(rightSegments);
6761
5757
  }
6762
- /**
6763
- * Makes a code path segment for the body part of a ForInStatement and a
6764
- * ForOfStatement.
6765
- */
6766
5758
  makeForInOfBody() {
6767
5759
  const context = this.loopContext;
6768
5760
  const forkContext = this.forkContext;
@@ -6773,9 +5765,6 @@ var CodePathState = class {
6773
5765
  context.brokenForkContext.add(forkContext.head);
6774
5766
  forkContext.replaceHead(bodySegments);
6775
5767
  }
6776
- /**
6777
- * Creates new context for BreakStatement.
6778
- */
6779
5768
  pushBreakContext(breakable, label) {
6780
5769
  this.breakContext = {
6781
5770
  upper: this.breakContext,
@@ -6785,9 +5774,6 @@ var CodePathState = class {
6785
5774
  };
6786
5775
  return this.breakContext;
6787
5776
  }
6788
- /**
6789
- * Removes the top item of the break context stack.
6790
- */
6791
5777
  popBreakContext() {
6792
5778
  const context = this.breakContext;
6793
5779
  const forkContext = this.forkContext;
@@ -6801,12 +5787,6 @@ var CodePathState = class {
6801
5787
  }
6802
5788
  return context;
6803
5789
  }
6804
- /**
6805
- * Makes a path for a `break` statement.
6806
- *
6807
- * It registers the head segment to a context of `break`.
6808
- * It makes new unreachable segment, then it set the head with the segment.
6809
- */
6810
5790
  makeBreak(label) {
6811
5791
  const forkContext = this.forkContext;
6812
5792
  if (!forkContext.reachable) return;
@@ -6815,12 +5795,6 @@ var CodePathState = class {
6815
5795
  /* c8 ignore next */
6816
5796
  forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
6817
5797
  }
6818
- /**
6819
- * Makes a path for a `continue` statement.
6820
- *
6821
- * It makes a looping path.
6822
- * It makes new unreachable segment, then it set the head with the segment.
6823
- */
6824
5798
  makeContinue(label) {
6825
5799
  const forkContext = this.forkContext;
6826
5800
  if (!forkContext.reachable) return;
@@ -6833,12 +5807,6 @@ var CodePathState = class {
6833
5807
  }
6834
5808
  forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
6835
5809
  }
6836
- /**
6837
- * Makes a path for a `return` statement.
6838
- *
6839
- * It registers the head segment to a context of `return`.
6840
- * It makes new unreachable segment, then it set the head with the segment.
6841
- */
6842
5810
  makeReturn() {
6843
5811
  const forkContext = this.forkContext;
6844
5812
  if (forkContext.reachable) {
@@ -6846,12 +5814,6 @@ var CodePathState = class {
6846
5814
  forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
6847
5815
  }
6848
5816
  }
6849
- /**
6850
- * Makes a path for a `throw` statement.
6851
- *
6852
- * It registers the head segment to a context of `throw`.
6853
- * It makes new unreachable segment, then it set the head with the segment.
6854
- */
6855
5817
  makeThrow() {
6856
5818
  const forkContext = this.forkContext;
6857
5819
  if (forkContext.reachable) {
@@ -6859,17 +5821,11 @@ var CodePathState = class {
6859
5821
  forkContext.replaceHead(forkContext.makeUnreachable(-1, -1));
6860
5822
  }
6861
5823
  }
6862
- /**
6863
- * Makes the final path.
6864
- */
6865
5824
  makeFinal() {
6866
5825
  const segments = this.currentSegments;
6867
5826
  if (segments.length > 0 && segments[0].reachable) this.returnedForkContext.add(segments);
6868
5827
  }
6869
5828
  };
6870
- /**
6871
- * A generator for unique ids.
6872
- */
6873
5829
  var IdGenerator = class {
6874
5830
  prefix;
6875
5831
  n;
@@ -6877,9 +5833,6 @@ var IdGenerator = class {
6877
5833
  this.prefix = String(prefix);
6878
5834
  this.n = 0;
6879
5835
  }
6880
- /**
6881
- * Generates id.
6882
- */
6883
5836
  next() {
6884
5837
  this.n = 1 + this.n | 0;
6885
5838
  /* c8 ignore start */
@@ -6887,22 +5840,11 @@ var IdGenerator = class {
6887
5840
  return this.prefix + this.n;
6888
5841
  }
6889
5842
  };
6890
- /**
6891
- * A code path.
6892
- */
6893
5843
  var CodePath = class {
6894
- /** The identifier of this code path. */
6895
5844
  id;
6896
- /**
6897
- * The reason that this code path was started. May be "program",
6898
- * "function", "class-field-initializer", or "class-static-block".
6899
- */
6900
5845
  origin;
6901
- /** The code path of the upper function scope. */
6902
5846
  upper;
6903
- /** The code paths of nested function scopes. */
6904
5847
  childCodePaths;
6905
- /** Internal state for the code path. */
6906
5848
  internal;
6907
5849
  constructor({ id, origin, upper, onLooped }) {
6908
5850
  this.id = id;
@@ -6912,48 +5854,24 @@ var CodePath = class {
6912
5854
  this.internal = new CodePathState(new IdGenerator(`${id}_`), onLooped);
6913
5855
  if (upper) upper.childCodePaths.push(this);
6914
5856
  }
6915
- /**
6916
- * Gets the state of a given code path.
6917
- */
6918
5857
  static getState(codePath) {
6919
5858
  return codePath.internal;
6920
5859
  }
6921
- /** The initial code path segment. */
6922
5860
  get initialSegment() {
6923
5861
  return this.internal.initialSegment;
6924
5862
  }
6925
- /**
6926
- * Final code path segments.
6927
- * This array is a mix of `returnedSegments` and `thrownSegments`.
6928
- */
6929
5863
  get finalSegments() {
6930
5864
  return this.internal.finalSegments;
6931
5865
  }
6932
- /**
6933
- * Final code path segments which is with `return` statements.
6934
- * This array contains the last path segment if it's reachable.
6935
- * Since the reachable last path returns `undefined`.
6936
- */
6937
5866
  get returnedSegments() {
6938
5867
  return this.internal.returnedForkContext;
6939
5868
  }
6940
- /** Final code path segments which is with `throw` statements. */
6941
5869
  get thrownSegments() {
6942
5870
  return this.internal.thrownForkContext;
6943
5871
  }
6944
- /** Current code path segments. */
6945
5872
  get currentSegments() {
6946
5873
  return this.internal.currentSegments;
6947
5874
  }
6948
- /**
6949
- * Traverses all segments in this code path.
6950
- *
6951
- * This method enumerates segments in order from the head.
6952
- *
6953
- * The `controller` object has two methods:
6954
- * - `controller.skip()` - Skip the following segments in this branch.
6955
- * - `controller.break()` - Skip all following segments.
6956
- */
6957
5875
  traverseSegments(options, callback) {
6958
5876
  let resolvedOptions;
6959
5877
  let resolvedCallback;
@@ -7019,45 +5937,23 @@ var CodePath = class {
7019
5937
  }
7020
5938
  };
7021
5939
  const breakableTypePattern = /^(?:(?:Do)?While|For(?:In|Of)?|Switch)Statement$/u;
7022
- /**
7023
- * Checks whether or not a given node is a `case` node (not `default` node).
7024
- */
7025
5940
  function isCaseNode(node) {
7026
5941
  return Boolean(node.test);
7027
5942
  }
7028
- /**
7029
- * Checks if a given node appears as the value of a PropertyDefinition node.
7030
- */
7031
5943
  function isPropertyDefinitionValue(node) {
7032
5944
  const parent = node.parent;
7033
5945
  return parent && parent.type === "PropertyDefinition" && parent.value === node;
7034
5946
  }
7035
- /**
7036
- * Checks whether the given logical operator is taken into account for the code
7037
- * path analysis.
7038
- */
7039
5947
  function isHandledLogicalOperator(operator) {
7040
5948
  return operator === "&&" || operator === "||" || operator === "??";
7041
5949
  }
7042
- /**
7043
- * Checks whether the given assignment operator is a logical assignment operator.
7044
- * Logical assignments are taken into account for the code path analysis
7045
- * because of their short-circuiting semantics.
7046
- */
7047
5950
  function isLogicalAssignmentOperator(operator) {
7048
5951
  return operator === "&&=" || operator === "||=" || operator === "??=";
7049
5952
  }
7050
- /**
7051
- * Gets the label if the parent node of a given node is a LabeledStatement.
7052
- */
7053
5953
  function getLabel(node) {
7054
5954
  if (node.parent.type === "LabeledStatement") return node.parent.label.name;
7055
5955
  return null;
7056
5956
  }
7057
- /**
7058
- * Checks whether or not a given logical expression node goes different path
7059
- * between the `true` case and the `false` case.
7060
- */
7061
5957
  function isForkingByTrueOrFalse(node) {
7062
5958
  const parent = node.parent;
7063
5959
  switch (parent.type) {
@@ -7071,21 +5967,9 @@ function isForkingByTrueOrFalse(node) {
7071
5967
  default: return false;
7072
5968
  }
7073
5969
  }
7074
- /**
7075
- * Gets the boolean value of a given literal node.
7076
- *
7077
- * This is used to detect infinity loops (ex: `while (true) {}`).
7078
- * Statements preceded by an infinity loop are unreachable if the loop didn't
7079
- * have any `break` statement.
7080
- */
7081
5970
  function getBooleanValueIfSimpleConstant(node) {
7082
5971
  if (node.type === "Literal") return Boolean(node.value);
7083
5972
  }
7084
- /**
7085
- * Checks that a given identifier node is a reference or not.
7086
- *
7087
- * This is used to detect the first throwable node in a `try` block.
7088
- */
7089
5973
  function isIdentifierReference(node) {
7090
5974
  const parent = node.parent;
7091
5975
  switch (parent.type) {
@@ -7113,15 +5997,6 @@ function isIdentifierReference(node) {
7113
5997
  default: return true;
7114
5998
  }
7115
5999
  }
7116
- /**
7117
- * Updates the current segment with the head segment.
7118
- * This is similar to local branches and tracking branches of git.
7119
- *
7120
- * To separate the current and the head is in order to not make useless segments.
7121
- *
7122
- * In this process, both "onCodePathSegmentStart" and "onCodePathSegmentEnd"
7123
- * events are fired.
7124
- */
7125
6000
  function forwardCurrentToHead(analyzer, node) {
7126
6001
  const codePath = analyzer.codePath;
7127
6002
  const state = CodePath.getState(codePath);
@@ -7148,10 +6023,6 @@ function forwardCurrentToHead(analyzer, node) {
7148
6023
  }
7149
6024
  }
7150
6025
  }
7151
- /**
7152
- * Updates the current segment with empty.
7153
- * This is called at the last of functions or the program.
7154
- */
7155
6026
  function leaveFromCurrentSegment(analyzer, node) {
7156
6027
  const state = CodePath.getState(analyzer.codePath);
7157
6028
  const currentSegments = state.currentSegments;
@@ -7161,13 +6032,6 @@ function leaveFromCurrentSegment(analyzer, node) {
7161
6032
  }
7162
6033
  state.currentSegments = [];
7163
6034
  }
7164
- /**
7165
- * Updates the code path due to the position of a given node in the parent node
7166
- * thereof.
7167
- *
7168
- * For example, if the node is `parent.consequent`, this creates a fork from the
7169
- * current path.
7170
- */
7171
6035
  function preprocess(analyzer, node) {
7172
6036
  const codePath = analyzer.codePath;
7173
6037
  const state = CodePath.getState(codePath);
@@ -7232,17 +6096,10 @@ function preprocess(analyzer, node) {
7232
6096
  }
7233
6097
  }
7234
6098
  }
7235
- /**
7236
- * Updates the code path due to the type of a given node in entering.
7237
- */
7238
6099
  function processCodePathToEnter(analyzer, node) {
7239
6100
  let codePath = analyzer.codePath;
7240
6101
  let state = codePath && CodePath.getState(codePath);
7241
6102
  const parent = node.parent;
7242
- /**
7243
- * Creates a new code path and trigger the onCodePathStart event
7244
- * based on the currently selected node.
7245
- */
7246
6103
  function startCodePath(origin) {
7247
6104
  if (codePath) forwardCurrentToHead(analyzer, node);
7248
6105
  codePath = analyzer.codePath = new CodePath({
@@ -7308,9 +6165,6 @@ function processCodePathToEnter(analyzer, node) {
7308
6165
  }
7309
6166
  forwardCurrentToHead(analyzer, node);
7310
6167
  }
7311
- /**
7312
- * Updates the code path due to the type of a given node in leaving.
7313
- */
7314
6168
  function processCodePathToExit(analyzer, node) {
7315
6169
  const codePath = analyzer.codePath;
7316
6170
  const state = CodePath.getState(codePath);
@@ -7386,9 +6240,6 @@ function processCodePathToExit(analyzer, node) {
7386
6240
  }
7387
6241
  if (!dontForward) forwardCurrentToHead(analyzer, node);
7388
6242
  }
7389
- /**
7390
- * Updates the code path to finalize the current code path.
7391
- */
7392
6243
  function postprocess(analyzer, node) {
7393
6244
  function endCodePath() {
7394
6245
  const codePath = analyzer.codePath;
@@ -7411,10 +6262,6 @@ function postprocess(analyzer, node) {
7411
6262
  }
7412
6263
  if (isPropertyDefinitionValue(node)) endCodePath();
7413
6264
  }
7414
- /**
7415
- * The class to analyze code paths.
7416
- * This class implements the EventGenerator interface.
7417
- */
7418
6265
  var CodePathAnalyzer = class {
7419
6266
  emitter;
7420
6267
  codePath;
@@ -7430,30 +6277,18 @@ var CodePathAnalyzer = class {
7430
6277
  this.currentNode = null;
7431
6278
  this.onLooped = this._onLooped.bind(this);
7432
6279
  }
7433
- /**
7434
- * Does the process to enter a given AST node.
7435
- * This updates state of analysis and calls `enterNode` of the wrapped.
7436
- */
7437
6280
  enterNode(node) {
7438
6281
  this.currentNode = node;
7439
6282
  if (node.parent) preprocess(this, node);
7440
6283
  processCodePathToEnter(this, node);
7441
6284
  this.currentNode = null;
7442
6285
  }
7443
- /**
7444
- * Does the process to leave a given AST node.
7445
- * This updates state of analysis and calls `leaveNode` of the wrapped.
7446
- */
7447
6286
  leaveNode(node) {
7448
6287
  this.currentNode = node;
7449
6288
  processCodePathToExit(this, node);
7450
6289
  postprocess(this, node);
7451
6290
  this.currentNode = null;
7452
6291
  }
7453
- /**
7454
- * This is called on a code path looped.
7455
- * Then this raises a looped event.
7456
- */
7457
6292
  _onLooped(fromSegment, toSegment) {
7458
6293
  if (fromSegment.reachable && toSegment.reachable) this.emitter.emit("onCodePathSegmentLoop", fromSegment, toSegment, this.currentNode);
7459
6294
  }
@@ -7461,17 +6296,9 @@ var CodePathAnalyzer = class {
7461
6296
 
7462
6297
  //#endregion
7463
6298
  //#region src/rules/rules-of-hooks/rules-of-hooks.ts
7464
- /**
7465
- * Catch all identifiers that begin with "use" followed by an uppercase Latin
7466
- * character to exclude identifiers like "user".
7467
- */
7468
6299
  function isHookName(s) {
7469
6300
  return s === "use" || /^use[A-Z0-9]/.test(s);
7470
6301
  }
7471
- /**
7472
- * We consider hooks to be a hook name identifier or a member expression
7473
- * containing a hook name.
7474
- */
7475
6302
  function isHook(node) {
7476
6303
  const expr = Extract.unwrap(node);
7477
6304
  if (expr.type === "Identifier") return isHookName(expr.name);
@@ -7480,27 +6307,15 @@ function isHook(node) {
7480
6307
  return obj.type === "Identifier" && /^[A-Z].*/.test(obj.name);
7481
6308
  } else return false;
7482
6309
  }
7483
- /**
7484
- * Checks if the node is a React component name. React component names must
7485
- * always start with an uppercase letter.
7486
- */
7487
6310
  function isComponentName(node) {
7488
6311
  return node.type === "Identifier" && /^[A-Z]/.test(node.name);
7489
6312
  }
7490
6313
  function isReactFunction(node, functionName) {
7491
6314
  return "name" in node && node.name === functionName || node.type === "MemberExpression" && "name" in node.object && node.object.name === "React" && "name" in node.property && node.property.name === functionName;
7492
6315
  }
7493
- /**
7494
- * Checks if the node is a callback argument of forwardRef. This render function
7495
- * should follow the rules of hooks.
7496
- */
7497
6316
  function isForwardRefCallback(node) {
7498
6317
  return !!(node.parent && "callee" in node.parent && node.parent.callee && isReactFunction(node.parent.callee, "forwardRef"));
7499
6318
  }
7500
- /**
7501
- * Checks if the node is a callback argument of React.memo. This anonymous
7502
- * functional component should follow the rules of hooks.
7503
- */
7504
6319
  function isMemoCallback(node) {
7505
6320
  return !!(node.parent && "callee" in node.parent && node.parent.callee && isReactFunction(node.parent.callee, "memo"));
7506
6321
  }
@@ -7579,17 +6394,11 @@ const rule = {
7579
6394
  }
7580
6395
  }
7581
6396
  }
7582
- /**
7583
- * SourceCode that also works down to ESLint 3.0.0
7584
- */
7585
6397
  const getSourceCode = typeof context.getSourceCode === "function" ? () => {
7586
6398
  return context.getSourceCode();
7587
6399
  } : () => {
7588
6400
  return context.sourceCode;
7589
6401
  };
7590
- /**
7591
- * SourceCode#getScope that also works down to ESLint 3.0.0
7592
- */
7593
6402
  const getScope = typeof context.getScope === "function" ? () => {
7594
6403
  return context.getScope();
7595
6404
  } : (node) => {
@@ -7609,27 +6418,6 @@ const rule = {
7609
6418
  if (reactHooksMap?.size === 0) return;
7610
6419
  else if (typeof reactHooksMap === "undefined") throw new Error("Unexpected undefined reactHooksMap");
7611
6420
  const cyclic = /* @__PURE__ */ new Set();
7612
- /**
7613
- * Count the number of code paths from the start of the function to this
7614
- * segment. For example:
7615
- *
7616
- * ```js
7617
- * function MyComponent() {
7618
- * if (condition) {
7619
- * // Segment 1
7620
- * } else {
7621
- * // Segment 2
7622
- * }
7623
- * // Segment 3
7624
- * }
7625
- * ```
7626
- *
7627
- * Segments 1 and 2 have one path to the beginning of `MyComponent` and
7628
- * segment 3 has two paths to the beginning of `MyComponent` since we
7629
- * could have either taken the path of segment 1 or segment 2.
7630
- *
7631
- * Populates `cyclic` with cyclic segments.
7632
- */
7633
6421
  function countPathsFromStart(segment, pathHistory) {
7634
6422
  const { cache } = countPathsFromStart;
7635
6423
  let paths = cache.get(segment.id);
@@ -7652,27 +6440,6 @@ const rule = {
7652
6440
  else cache.set(segment.id, paths);
7653
6441
  return paths;
7654
6442
  }
7655
- /**
7656
- * Count the number of code paths from this segment to the end of the
7657
- * function. For example:
7658
- *
7659
- * ```js
7660
- * function MyComponent() {
7661
- * // Segment 1
7662
- * if (condition) {
7663
- * // Segment 2
7664
- * } else {
7665
- * // Segment 3
7666
- * }
7667
- * }
7668
- * ```
7669
- *
7670
- * Segments 2 and 3 have one path to the end of `MyComponent` and
7671
- * segment 1 has two paths to the end of `MyComponent` since we could
7672
- * either take the path of segment 1 or segment 2.
7673
- *
7674
- * Populates `cyclic` with cyclic segments.
7675
- */
7676
6443
  function countPathsToEnd(segment, pathHistory) {
7677
6444
  const { cache } = countPathsToEnd;
7678
6445
  let paths = cache.get(segment.id);
@@ -7694,27 +6461,6 @@ const rule = {
7694
6461
  cache.set(segment.id, paths);
7695
6462
  return paths;
7696
6463
  }
7697
- /**
7698
- * Gets the shortest path length to the start of a code path.
7699
- * For example:
7700
- *
7701
- * ```js
7702
- * function MyComponent() {
7703
- * if (condition) {
7704
- * // Segment 1
7705
- * }
7706
- * // Segment 2
7707
- * }
7708
- * ```
7709
- *
7710
- * There is only one path from segment 1 to the code path start. Its
7711
- * length is one so that is the shortest path.
7712
- *
7713
- * There are two paths from segment 2 to the code path start. One
7714
- * through segment 1 with a length of two and another directly to the
7715
- * start with a length of one. The shortest path has a length of one
7716
- * so we would return that.
7717
- */
7718
6464
  function shortestPathLengthToStart(segment) {
7719
6465
  const { cache } = shortestPathLengthToStart;
7720
6466
  let length = cache.get(segment.id);
@@ -7858,13 +6604,6 @@ const rule = {
7858
6604
  };
7859
6605
  }
7860
6606
  };
7861
- /**
7862
- * Gets the static name of a function AST node. For function declarations it is
7863
- * easy. For anonymous function expressions it is much harder. If you search for
7864
- * `IsAnonymousFunctionDefinition()` in the ECMAScript spec you'll find places
7865
- * where JS gives anonymous function expressions names. We roughly detect the
7866
- * same AST nodes with some exceptions to better fit our use case.
7867
- */
7868
6607
  function getFunctionName(node) {
7869
6608
  if (node.type === "ComponentDeclaration" || node.type === "HookDeclaration" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression" && node.id) return node.id;
7870
6609
  else if (node.type === "FunctionExpression" || node.type === "ArrowFunctionExpression") {
@@ -7875,9 +6614,6 @@ function getFunctionName(node) {
7875
6614
  else return;
7876
6615
  } else return;
7877
6616
  }
7878
- /**
7879
- * Convenience function for peeking the last item in a stack.
7880
- */
7881
6617
  function last(array) {
7882
6618
  return array[array.length - 1];
7883
6619
  }
@@ -7920,11 +6656,6 @@ const IDENTIFIER_VISITOR_KEYS = {
7920
6656
  [AST_NODE_TYPES.UpdateExpression]: ["argument"],
7921
6657
  [AST_NODE_TYPES.YieldExpression]: ["argument"]
7922
6658
  };
7923
- /**
7924
- * Get all nested identifiers in a expression like node
7925
- * @param node The node to get the nested identifiers from
7926
- * @returns All nested identifiers
7927
- */
7928
6659
  function getNestedIdentifiers(node) {
7929
6660
  const identifiers = [];
7930
6661
  simpleTraverse(node, {
@@ -7953,23 +6684,10 @@ function isTerminatingStatement(node) {
7953
6684
  if (node.type === AST_NODE_TYPES.BlockStatement) return node.body.some(isTerminatingStatement);
7954
6685
  return false;
7955
6686
  }
7956
- /**
7957
- * Get the display name of a setState call reference for reporting.
7958
- * @param node The setState call node (CallExpression or Identifier)
7959
- * @param getText The source text getter
7960
- * @returns The fully qualified name of the call
7961
- */
7962
6687
  function getCallName(node, getText) {
7963
6688
  if (node.type === AST_NODE_TYPES.CallExpression) return Extract.getFullyQualifiedName(node.callee, getText);
7964
6689
  return Extract.getFullyQualifiedName(node, getText);
7965
6690
  }
7966
- /**
7967
- * Get the actual CallExpression node from a setState call reference.
7968
- * When the node is an Identifier that is the callee of a CallExpression,
7969
- * returns the parent CallExpression; otherwise returns the node itself.
7970
- * @param node The setState call node (CallExpression or Identifier)
7971
- * @returns The actual CallExpression node
7972
- */
7973
6691
  function getSetStateCallExpression(node) {
7974
6692
  return Check.isIdentifier(node) && node.parent.type === AST_NODE_TYPES.CallExpression && node.parent.callee === node ? node.parent : node;
7975
6693
  }
@@ -8057,13 +6775,6 @@ function createFactCollector$3(additionalStateHooks, additionalEffectHooks) {
8057
6775
 
8058
6776
  //#endregion
8059
6777
  //#region src/rules/set-state-in-effect/origins.ts
8060
- /**
8061
- * Create a resolver that answers whether an identifier or call originates from
8062
- * a `useState`-like hook's setter function (the element at index 1 of the
8063
- * returned tuple).
8064
- * @param context The rule context
8065
- * @returns The setState provenance resolver
8066
- */
8067
6778
  function createSetStateResolver$1(context) {
8068
6779
  const { additionalStateHooks } = getSettingsFromContext(context);
8069
6780
  function isUseStateCall(node) {
@@ -8075,7 +6786,7 @@ function createSetStateResolver$1(context) {
8075
6786
  if (initNode.type !== AST_NODE_TYPES.CallExpression) return false;
8076
6787
  if (!isUseStateCall(initNode)) return false;
8077
6788
  const variableNodeParent = initNode.parent;
8078
- if (!("id" in variableNodeParent) || variableNodeParent.id?.type !== AST_NODE_TYPES.ArrayPattern) return true;
6789
+ if (!hasProperty(variableNodeParent, "id") || variableNodeParent.id?.type !== AST_NODE_TYPES.ArrayPattern) return true;
8079
6790
  return variableNodeParent.id.elements.findIndex((e) => e != null && Check.isIdentifier(e, id.name)) === at;
8080
6791
  }
8081
6792
  function isSetStateCall(node) {
@@ -8084,7 +6795,7 @@ function createSetStateResolver$1(context) {
8084
6795
  case AST_NODE_TYPES.CallExpression: {
8085
6796
  const innerCallee = Extract.unwrap(callee.callee);
8086
6797
  if (innerCallee.type !== AST_NODE_TYPES.MemberExpression) return false;
8087
- if (!("name" in innerCallee.object)) return false;
6798
+ if (!hasProperty(innerCallee.object, "name")) return false;
8088
6799
  const isAt = Extract.getCalleeName(callee) === "at";
8089
6800
  const [index] = callee.arguments;
8090
6801
  if (!isAt || index == null) return false;
@@ -8093,7 +6804,7 @@ function createSetStateResolver$1(context) {
8093
6804
  }
8094
6805
  case AST_NODE_TYPES.Identifier: return isSetStateId(callee, 1);
8095
6806
  case AST_NODE_TYPES.MemberExpression: {
8096
- if (!("name" in callee.object)) return false;
6807
+ if (!hasProperty(callee.object, "name")) return false;
8097
6808
  const property = callee.property;
8098
6809
  const propertyScope = context.sourceCode.getScope(node);
8099
6810
  return getStaticValue(property, propertyScope)?.value === 1 && isSetStateId(callee.object, 1);
@@ -8141,12 +6852,6 @@ function isInitializedFromRef(context, name, initialScope, seen = /* @__PURE__ *
8141
6852
  }
8142
6853
  return false;
8143
6854
  }
8144
- /**
8145
- * Check if the setState call is using a ref value, which is safe to use in an effect (ex: `setState(ref.current.scrollTop)`)
8146
- * @param context The rule context
8147
- * @param node The setState call argument to check
8148
- * @returns `true` if the argument value is derived from a ref
8149
- */
8150
6855
  function isArgumentUsingRefValue(context, node) {
8151
6856
  const isUsingRefValue = (n) => {
8152
6857
  switch (n.type) {
@@ -8172,13 +6877,6 @@ function isArgumentUsingRefValue(context, node) {
8172
6877
  if (isUsingRefValue(node)) return true;
8173
6878
  return Check.isFunction(node) && context.sourceCode.getScope(node.body).references.some((r) => isUsingRefValue(r.identifier));
8174
6879
  }
8175
- /**
8176
- * Check if a setState call is inside a conditional block whose test expression
8177
- * is derived from a ref value (e.g. `if (prevRef.current !== value) setState(...)`).
8178
- * @param context The ESLint rule context
8179
- * @param node The AST node to check
8180
- * @returns `true` if the node is inside a ref-gated conditional block
8181
- */
8182
6880
  function isRefGatedContext(context, node) {
8183
6881
  let child = node;
8184
6882
  let current = node.parent;
@@ -8206,11 +6904,6 @@ function isRefGatedContext(context, node) {
8206
6904
  function isRefInExpression(context, node) {
8207
6905
  return getNestedIdentifiers(node).some((id) => isInitializedFromRef(context, id.name, context.sourceCode.getScope(id)));
8208
6906
  }
8209
- /**
8210
- * Get the name that identifies the source of a `.current` member access.
8211
- * @param node The object of the member expression
8212
- * @returns The identifier name, the last property name of a member chain, or null
8213
- */
8214
6907
  function getRefSourceName(node) {
8215
6908
  switch (node.type) {
8216
6909
  case AST_NODE_TYPES.Identifier: return node.name;
@@ -8224,15 +6917,6 @@ function getRefSourceName(node) {
8224
6917
 
8225
6918
  //#endregion
8226
6919
  //#region src/rules/set-state-in-effect/effects.ts
8227
- /**
8228
- * Infer the setState calls that run synchronously during an effect setup from
8229
- * the collected facts: calls made directly in the setup body (or an IIFE within
8230
- * it), and calls reached indirectly through local functions, hook callbacks, or
8231
- * setup identifiers passed to the effect.
8232
- * @param context The rule context
8233
- * @param facts The collected facts
8234
- * @returns The violations to report, in report order
8235
- */
8236
6920
  function inferViolations$2(context, facts) {
8237
6921
  const { additionalEffectHooks } = getSettingsFromContext(context);
8238
6922
  const resolver = createSetStateResolver$1(context);
@@ -8453,13 +7137,6 @@ function createFactCollector$2(additionalStateHooks) {
8453
7137
 
8454
7138
  //#endregion
8455
7139
  //#region src/rules/set-state-in-render/origins.ts
8456
- /**
8457
- * Create a resolver that answers whether an identifier or call originates from
8458
- * a `useState`-like hook's setter function (the element at index 1 of the
8459
- * returned tuple).
8460
- * @param context The rule context
8461
- * @returns The setState provenance resolver
8462
- */
8463
7140
  function createSetStateResolver(context) {
8464
7141
  const { additionalStateHooks } = getSettingsFromContext(context);
8465
7142
  function isUseStateCall(node) {
@@ -8471,7 +7148,7 @@ function createSetStateResolver(context) {
8471
7148
  if (initNode.type !== AST_NODE_TYPES.CallExpression) return false;
8472
7149
  if (!isUseStateCall(initNode)) return false;
8473
7150
  const variableNodeParent = initNode.parent;
8474
- if (!("id" in variableNodeParent) || variableNodeParent.id?.type !== AST_NODE_TYPES.ArrayPattern) return true;
7151
+ if (!hasProperty(variableNodeParent, "id") || variableNodeParent.id?.type !== AST_NODE_TYPES.ArrayPattern) return true;
8475
7152
  return variableNodeParent.id.elements.findIndex((e) => e != null && Check.isIdentifier(e, id.name)) === at;
8476
7153
  }
8477
7154
  function isSetStateCall(node) {
@@ -8480,7 +7157,7 @@ function createSetStateResolver(context) {
8480
7157
  case AST_NODE_TYPES.CallExpression: {
8481
7158
  const innerCallee = Extract.unwrap(callee.callee);
8482
7159
  if (innerCallee.type !== AST_NODE_TYPES.MemberExpression) return false;
8483
- if (!("name" in innerCallee.object)) return false;
7160
+ if (!hasProperty(innerCallee.object, "name")) return false;
8484
7161
  const isAt = Extract.getCalleeName(callee) === "at";
8485
7162
  const [index] = callee.arguments;
8486
7163
  if (!isAt || index == null) return false;
@@ -8489,7 +7166,7 @@ function createSetStateResolver(context) {
8489
7166
  }
8490
7167
  case AST_NODE_TYPES.Identifier: return isSetStateId(callee, 1);
8491
7168
  case AST_NODE_TYPES.MemberExpression: {
8492
- if (!("name" in callee.object)) return false;
7169
+ if (!hasProperty(callee.object, "name")) return false;
8493
7170
  const property = callee.property;
8494
7171
  const propertyScope = context.sourceCode.getScope(node);
8495
7172
  return getStaticValue(property, propertyScope)?.value === 1 && isSetStateId(callee.object, 1);
@@ -8506,14 +7183,6 @@ function createSetStateResolver(context) {
8506
7183
 
8507
7184
  //#endregion
8508
7185
  //#region src/rules/set-state-in-render/effects.ts
8509
- /**
8510
- * Infer the setState calls that run unconditionally during render from the
8511
- * collected facts: calls made directly in a component function body that are
8512
- * neither guarded by a conditional nor positioned after an early return.
8513
- * @param context The rule context
8514
- * @param facts The collected facts
8515
- * @returns The violations to report, in report order
8516
- */
8517
7186
  function inferViolations$1(context, facts) {
8518
7187
  const resolver = createSetStateResolver(context);
8519
7188
  const getText = (n) => context.sourceCode.getText(n);
@@ -8580,10 +7249,6 @@ function createFactCollector$1() {
8580
7249
 
8581
7250
  //#endregion
8582
7251
  //#region src/rules/static-components/helpers.ts
8583
- /**
8584
- * Expression kinds that always produce a brand-new value on every evaluation, and are
8585
- * therefore considered "dynamically created" when used as a component's value.
8586
- */
8587
7252
  const KNOWN_DYNAMIC_EXPRESSION_TYPES = /* @__PURE__ */ new Set([
8588
7253
  AST_NODE_TYPES.ArrowFunctionExpression,
8589
7254
  AST_NODE_TYPES.CallExpression,
@@ -8591,10 +7256,6 @@ const KNOWN_DYNAMIC_EXPRESSION_TYPES = /* @__PURE__ */ new Set([
8591
7256
  AST_NODE_TYPES.FunctionExpression,
8592
7257
  AST_NODE_TYPES.NewExpression
8593
7258
  ]);
8594
- /**
8595
- * Builds a predicate that tells whether a given node lies within the body of one of the
8596
- * collected function or class components, i.e. whether it is "created during render".
8597
- */
8598
7259
  function createRenderBoundaryChecker(componentNodes) {
8599
7260
  const components = new Set(componentNodes);
8600
7261
  return (node) => Traverse.findParent(node, (n) => (Check.isFunction(n) || Check.isClass(n)) && components.has(n)) != null;
@@ -8602,11 +7263,6 @@ function createRenderBoundaryChecker(componentNodes) {
8602
7263
 
8603
7264
  //#endregion
8604
7265
  //#region src/rules/static-components/origins.ts
8605
- /**
8606
- * Resolves an expression down to the node that dynamically created its value, if any.
8607
- * Recurses through identifier references, both branches of ternaries and logical
8608
- * expressions, and the final element of sequence expressions.
8609
- */
8610
7266
  function findDynamicCreationSite(context, node, isInsideRender, seen) {
8611
7267
  const expr = Extract.unwrap(node);
8612
7268
  if (KNOWN_DYNAMIC_EXPRESSION_TYPES.has(expr.type)) return expr;
@@ -8626,10 +7282,6 @@ function findDynamicCreationSite(context, node, isInsideRender, seen) {
8626
7282
  default: return null;
8627
7283
  }
8628
7284
  }
8629
- /**
8630
- * Looks for a reassignment of `variable` (e.g. `Component = createComponent();`) whose
8631
- * right-hand side is dynamically created.
8632
- */
8633
7285
  function findReassignmentCreationSite(context, variable, isInsideRender, seen) {
8634
7286
  for (const ref of variable.references) {
8635
7287
  if (!ref.isWrite()) continue;
@@ -8640,10 +7292,6 @@ function findReassignmentCreationSite(context, variable, isInsideRender, seen) {
8640
7292
  }
8641
7293
  return null;
8642
7294
  }
8643
- /**
8644
- * Resolves a component binding to the node that dynamically created its value, if the
8645
- * value is created during render (a fresh function/class/call result on every render).
8646
- */
8647
7295
  function resolveDynamicComponentOrigin(context, variable, isInsideRender, seen = /* @__PURE__ */ new Set()) {
8648
7296
  if (seen.has(variable)) return {
8649
7297
  creationNode: null,
@@ -8677,11 +7325,6 @@ function resolveDynamicComponentOrigin(context, variable, isInsideRender, seen =
8677
7325
 
8678
7326
  //#endregion
8679
7327
  //#region src/rules/static-components/effects.ts
8680
- /**
8681
- * Turn collected JSX component usages into effects: a usage is an effect when the
8682
- * binding it refers to is declared inside a component's render body and its value is
8683
- * dynamically created, i.e. the component is recreated on every render.
8684
- */
8685
7328
  function inferCreatedComponents(context, componentUsages, isInsideRender) {
8686
7329
  const effects = [];
8687
7330
  for (const usage of componentUsages) {
@@ -8822,22 +7465,11 @@ function create$2(context) {
8822
7465
 
8823
7466
  //#endregion
8824
7467
  //#region src/rules/use-memo/helpers.ts
8825
- /**
8826
- * Check whether the result of a `useMemo` call is used (assigned, returned,
8827
- * passed as an argument, etc.) rather than discarded as a bare statement.
8828
- * @param node The `useMemo` call expression
8829
- * @returns `true` when the call result flows into a surrounding expression
8830
- */
8831
7468
  function isResultUsed(node) {
8832
7469
  let parent = node.parent;
8833
7470
  while (Check.isTypeExpression(parent)) parent = parent.parent;
8834
7471
  return parent.type === AST_NODE_TYPES.VariableDeclarator || parent.type === AST_NODE_TYPES.AssignmentExpression || parent.type === AST_NODE_TYPES.AssignmentPattern || parent.type === AST_NODE_TYPES.Property || parent.type === AST_NODE_TYPES.ReturnStatement || parent.type === AST_NODE_TYPES.JSXExpressionContainer || parent.type === AST_NODE_TYPES.CallExpression || parent.type === AST_NODE_TYPES.NewExpression || parent.type === AST_NODE_TYPES.ArrayExpression || parent.type === AST_NODE_TYPES.ConditionalExpression || parent.type === AST_NODE_TYPES.LogicalExpression || parent.type === AST_NODE_TYPES.SequenceExpression || parent.type === AST_NODE_TYPES.SpreadElement || parent.type === AST_NODE_TYPES.TemplateLiteral || parent.type === AST_NODE_TYPES.BinaryExpression || parent.type === AST_NODE_TYPES.UnaryExpression || parent.type === AST_NODE_TYPES.MemberExpression || parent.type === AST_NODE_TYPES.TaggedTemplateExpression || parent.type === AST_NODE_TYPES.ChainExpression || parent.type === AST_NODE_TYPES.ArrowFunctionExpression || parent.type === AST_NODE_TYPES.ForOfStatement || parent.type === AST_NODE_TYPES.ForInStatement;
8835
7472
  }
8836
- /**
8837
- * Gets the nested return statements in the node that are within the same function
8838
- * @param node The AST node
8839
- * @returns The nested return statements in the node
8840
- */
8841
7473
  function getNestedReturnStatements(node) {
8842
7474
  const statements = [];
8843
7475
  const boundary = Check.isFunction(node) ? node : Traverse.findParent(node, Check.isFunction);
@@ -8906,15 +7538,6 @@ function isDeclaredInsideCallback(variable, callback) {
8906
7538
  }
8907
7539
  return false;
8908
7540
  }
8909
- /**
8910
- * Resolve whether an identifier written inside a `useMemo` callback refers to a
8911
- * variable declared outside the callback. Unresolved identifiers and variables
8912
- * without definitions are treated as outer variables.
8913
- * @param context The rule context
8914
- * @param target The written identifier
8915
- * @param callback The `useMemo` callback the write occurs in
8916
- * @returns `true` when the write reassigns an outer variable
8917
- */
8918
7541
  function isOuterVariable(context, target, callback) {
8919
7542
  const scope = context.sourceCode.getScope(target);
8920
7543
  const variable = findVariable(scope, target);
@@ -8924,14 +7547,6 @@ function isOuterVariable(context, target, callback) {
8924
7547
 
8925
7548
  //#endregion
8926
7549
  //#region src/rules/use-memo/effects.ts
8927
- /**
8928
- * Infer the `useMemo` usage violations from the collected facts: unused
8929
- * results, callbacks with parameters, async or generator callbacks, outer
8930
- * variable reassignments, and callbacks that never return a value.
8931
- * @param context The rule context
8932
- * @param facts The collected facts
8933
- * @returns The violations to report, in report order
8934
- */
8935
7550
  function inferViolations(context, facts) {
8936
7551
  const violations = [];
8937
7552
  for (const fact of facts.calls) {
@@ -9064,12 +7679,6 @@ const EXPRESSION_VISITOR_KEYS = {
9064
7679
  [AST_NODE_TYPES.WhileStatement]: ["test"],
9065
7680
  [AST_NODE_TYPES.YieldExpression]: ["argument"]
9066
7681
  };
9067
- /**
9068
- * Get all nested expressions of type T in an expression like node
9069
- * @param type The type of the expression to retrieve within the node
9070
- * @returns A partially applied function bound to a predicate of type AST. The returned function can be called passing a
9071
- * node, and it will return an array of all nested expressions of type AST.
9072
- */
9073
7682
  function getNestedExpressionsOfType(type) {
9074
7683
  const isNodeOfType = Check.is(type);
9075
7684
  const recurse = (node) => {
@@ -9085,17 +7694,7 @@ function getNestedExpressionsOfType(type) {
9085
7694
  };
9086
7695
  return recurse;
9087
7696
  }
9088
- /**
9089
- * Get all nested new expressions in an expression like node
9090
- * @param node The node to get the nested new expressions from
9091
- * @returns All nested new expressions
9092
- */
9093
7697
  const getNestedNewExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.NewExpression);
9094
- /**
9095
- * Get all nested call expressions in a expression like node
9096
- * @param node The node to get the nested call expressions from
9097
- * @returns All nested call expressions
9098
- */
9099
7698
  const getNestedCallExpressions = getNestedExpressionsOfType(AST_NODE_TYPES.CallExpression);
9100
7699
 
9101
7700
  //#endregion
@@ -9148,7 +7747,7 @@ function create(context) {
9148
7747
  const [useStateInput] = node.arguments;
9149
7748
  if (useStateInput != null) {
9150
7749
  for (const expr of getNestedNewExpressions(useStateInput)) {
9151
- if (!("name" in expr.callee)) continue;
7750
+ if (!hasProperty(expr.callee, "name")) continue;
9152
7751
  if (LAZY_INIT_ALLOW_LIST.includes(expr.callee.name)) continue;
9153
7752
  if (Traverse.findParent(expr, (n) => core.isUseCall(context, n)) != null) continue;
9154
7753
  context.report({
@@ -9157,7 +7756,7 @@ function create(context) {
9157
7756
  });
9158
7757
  }
9159
7758
  for (const expr of getNestedCallExpressions(useStateInput)) {
9160
- if (!("name" in expr.callee)) continue;
7759
+ if (!hasProperty(expr.callee, "name")) continue;
9161
7760
  if (core.isHookName(expr.callee.name)) continue;
9162
7761
  if (LAZY_INIT_ALLOW_LIST.includes(expr.callee.name)) continue;
9163
7762
  if (Traverse.findParent(expr, (n) => core.isUseCall(context, n)) != null) continue;
@@ -9429,45 +8028,15 @@ function createConfig(base) {
9429
8028
  const finalPlugin = {
9430
8029
  ...plugin,
9431
8030
  configs: {
9432
- /**
9433
- * Disable rules in `eslint-plugin-react` that conflict with rules in this plugin
9434
- */
9435
8031
  ["disable-conflict-eslint-plugin-react"]: createConfig(disable_conflict_eslint_plugin_react_exports),
9436
- /**
9437
- * Disable rules in `eslint-plugin-react-hooks` that conflict with rules in this plugin
9438
- */
9439
8032
  ["disable-conflict-eslint-plugin-react-hooks"]: createConfig(disable_conflict_eslint_plugin_react_hooks_exports),
9440
- /**
9441
- * Disable experimental rules that might be subject to change in the future
9442
- */
9443
8033
  ["disable-experimental"]: createConfig(disable_experimental_exports),
9444
- /**
9445
- * Disable rules that can be enforced by TypeScript
9446
- */
9447
8034
  ["disable-type-checked"]: createConfig(disable_type_checked_exports),
9448
- /**
9449
- * Enforce rules that are recommended by ESLint React for general purpose React + React DOM projects
9450
- */
9451
8035
  ["recommended"]: createConfig(recommended_exports),
9452
- /**
9453
- * Same as the `recommended-typescript` preset but enables additional rules that require type information
9454
- */
9455
8036
  ["recommended-type-checked"]: createConfig(recommended_type_checked_exports),
9456
- /**
9457
- * Same as the `recommended` preset but disables rules that can be enforced by TypeScript
9458
- */
9459
8037
  ["recommended-typescript"]: createConfig(recommended_typescript_exports),
9460
- /**
9461
- * More strict version of the `recommended` preset
9462
- */
9463
8038
  ["strict"]: createConfig(strict_exports),
9464
- /**
9465
- * Same as the `strict-typescript` preset but enables additional rules that require type information
9466
- */
9467
8039
  ["strict-type-checked"]: createConfig(strict_type_checked_exports),
9468
- /**
9469
- * Same as the `strict` preset but disables rules that can be enforced by TypeScript
9470
- */
9471
8040
  ["strict-typescript"]: createConfig(strict_typescript_exports)
9472
8041
  }
9473
8042
  };