@sarj/eslint-plugin 16.26.0 → 16.26.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.
- package/dist/index.cjs +168 -60
- package/dist/index.js +1900 -1792
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -883,7 +883,7 @@ function isSearchParamReceiver(call, services) {
|
|
|
883
883
|
// package.json
|
|
884
884
|
var package_default = {
|
|
885
885
|
name: "@sarj/eslint-plugin",
|
|
886
|
-
version: "16.26.
|
|
886
|
+
version: "16.26.2",
|
|
887
887
|
packageManager: "npm@12.2.0",
|
|
888
888
|
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
889
889
|
type: "module",
|
|
@@ -8845,6 +8845,14 @@ var import_utils53 = require("@typescript-eslint/utils");
|
|
|
8845
8845
|
|
|
8846
8846
|
// src/rules/_stable-value-binding.ts
|
|
8847
8847
|
var import_utils52 = require("@typescript-eslint/utils");
|
|
8848
|
+
function typeOnlyReference2(reference) {
|
|
8849
|
+
if (reference.isTypeReference && !reference.isValueReference) return true;
|
|
8850
|
+
let current = outerExpression(reference.identifier);
|
|
8851
|
+
while (current.parent?.type === import_utils52.AST_NODE_TYPES.TSQualifiedName && current.parent.left === current) {
|
|
8852
|
+
current = current.parent;
|
|
8853
|
+
}
|
|
8854
|
+
return current.parent?.type === import_utils52.AST_NODE_TYPES.TSTypeQuery && current.parent.exprName === current;
|
|
8855
|
+
}
|
|
8848
8856
|
function stableValueBinding(variable, acceptRead) {
|
|
8849
8857
|
let initializer;
|
|
8850
8858
|
return variable.references.every((reference) => {
|
|
@@ -11076,6 +11084,7 @@ var no_bare_return_from_test_catch_default = createRule({
|
|
|
11076
11084
|
const returnBlock = node.parent;
|
|
11077
11085
|
if (parameter?.type === import_utils64.AST_NODE_TYPES.Identifier && returnBlock?.type === import_utils64.AST_NODE_TYPES.BlockStatement) {
|
|
11078
11086
|
const errorBinding = import_utils64.ASTUtils.findVariable(context.sourceCode.getScope(parameter), parameter.name);
|
|
11087
|
+
const errorReferences = errorBinding !== null && errorBinding.references.length > 32 ? new Set(errorBinding.references.map((reference) => reference.identifier)) : void 0;
|
|
11079
11088
|
const assertedError = returnBlock.body.some((statement) => {
|
|
11080
11089
|
if (statement.range[1] > node.range[0] || statement.type !== import_utils64.AST_NODE_TYPES.ExpressionStatement) return false;
|
|
11081
11090
|
const expression = statement.expression;
|
|
@@ -11086,7 +11095,7 @@ var no_bare_return_from_test_catch_default = createRule({
|
|
|
11086
11095
|
let operand = expression.callee.type === import_utils64.AST_NODE_TYPES.MemberExpression ? expression.callee.object : null;
|
|
11087
11096
|
if (operand?.type === import_utils64.AST_NODE_TYPES.MemberExpression && staticMemberName3(operand) === "not") operand = operand.object;
|
|
11088
11097
|
if (assertionName !== "assert" && (assertionName !== "expect" || operand?.type !== import_utils64.AST_NODE_TYPES.CallExpression || operand.callee !== root)) return false;
|
|
11089
|
-
return walkOwnScope(expression, (current) => current.type === import_utils64.AST_NODE_TYPES.Identifier && errorBinding?.references.some((reference) => reference.identifier === current) === true);
|
|
11098
|
+
return walkOwnScope(expression, (current) => current.type === import_utils64.AST_NODE_TYPES.Identifier && (errorReferences?.has(current) ?? errorBinding?.references.some((reference) => reference.identifier === current)) === true);
|
|
11090
11099
|
});
|
|
11091
11100
|
if (assertedError) return;
|
|
11092
11101
|
}
|
|
@@ -17317,6 +17326,15 @@ var test_loops_over_literal_cases_default = createRule({
|
|
|
17317
17326
|
if (!isTestFile(context)) {
|
|
17318
17327
|
return {};
|
|
17319
17328
|
}
|
|
17329
|
+
const referenceIdentifiers = /* @__PURE__ */ new WeakMap();
|
|
17330
|
+
const isReference = (variable, identifier) => {
|
|
17331
|
+
let identifiers = referenceIdentifiers.get(variable);
|
|
17332
|
+
if (identifiers === void 0) {
|
|
17333
|
+
identifiers = new Set(variable.references.map((reference) => reference.identifier));
|
|
17334
|
+
referenceIdentifiers.set(variable, identifiers);
|
|
17335
|
+
}
|
|
17336
|
+
return identifiers.has(identifier);
|
|
17337
|
+
};
|
|
17320
17338
|
const isFrameworkTest = (identifier) => TEST_CALLERS3.has(runtimeTestFrameworkName(context.sourceCode, identifier, "test") ?? "");
|
|
17321
17339
|
const isFrameworkAssertion = (identifier) => ASSERTION_ROOTS.has(runtimeTestFrameworkName(context.sourceCode, identifier, "assertion") ?? "");
|
|
17322
17340
|
return {
|
|
@@ -17340,7 +17358,7 @@ var test_loops_over_literal_cases_default = createRule({
|
|
|
17340
17358
|
const capturesSetup = walkOwnScope2(node.body, (current) => {
|
|
17341
17359
|
if (current.type !== import_utils99.AST_NODE_TYPES.Identifier) return false;
|
|
17342
17360
|
const variable = import_utils99.ASTUtils.findVariable(context.sourceCode.getScope(current), current.name);
|
|
17343
|
-
if (variable === null || !variable
|
|
17361
|
+
if (variable === null || !isReference(variable, current)) return false;
|
|
17344
17362
|
return variable.defs.some((definition) => {
|
|
17345
17363
|
const declaration = definition.name;
|
|
17346
17364
|
return declaration.range[0] >= enclosing.range[0] && declaration.range[1] <= enclosing.range[1] && (declaration.range[0] < node.range[0] || declaration.range[1] > node.range[1]);
|
|
@@ -20789,6 +20807,7 @@ var PREFER_NODE_CRYPTO_HASH_DOCUMENTATION = {
|
|
|
20789
20807
|
"Only direct imports, const bindings, and inline calls with statically proven provenance from crypto or node:crypto are analyzed; arbitrary assignments and dynamic module specifiers are excluded.",
|
|
20790
20808
|
"Only a literal algorithm with exactly one update call is reported; streaming and incremental hashes remain valid.",
|
|
20791
20809
|
"Namespace bindings must remain read-only: visible writes, aliases, exports, inherited mutation or alias methods, unknown computed members, and other escaping uses are excluded; type-only references and direct member calls remain eligible.",
|
|
20810
|
+
"CommonJS loads and default imports share one mutable native module object. A visible unsafe use of that object excludes its other loads; ESM named exports remain separate unless visible native export synchronization can update them.",
|
|
20792
20811
|
"Runtime support and output encoding require manual review; no autofix or guaranteed speedup is promised."
|
|
20793
20812
|
],
|
|
20794
20813
|
references: ["https://nodejs.org/api/crypto.html#cryptohashalgorithm-data-options"],
|
|
@@ -20803,39 +20822,57 @@ var UNSAFE_NAMESPACE_METHODS = /* @__PURE__ */ new Set(["__defineGetter__", "__d
|
|
|
20803
20822
|
function stableNamespace(variable) {
|
|
20804
20823
|
if (variable.defs.some((definition) => definition.type === "Variable" && definition.parent.parent.type === import_utils118.AST_NODE_TYPES.ExportNamedDeclaration)) return false;
|
|
20805
20824
|
return stableValueBinding(variable, (reference) => {
|
|
20806
|
-
if (reference
|
|
20825
|
+
if (typeOnlyReference2(reference)) return true;
|
|
20826
|
+
const receiver = outerExpression(reference.identifier);
|
|
20827
|
+
return readonlyNamespaceUse(receiver);
|
|
20828
|
+
});
|
|
20829
|
+
}
|
|
20830
|
+
function readonlyNamespaceUse(receiver) {
|
|
20831
|
+
const member = receiver.parent;
|
|
20832
|
+
if (member?.type !== import_utils118.AST_NODE_TYPES.MemberExpression || member.object !== receiver) {
|
|
20833
|
+
return member?.type === import_utils118.AST_NODE_TYPES.UnaryExpression && member.operator === "typeof";
|
|
20834
|
+
}
|
|
20835
|
+
const use = outerExpression(member);
|
|
20836
|
+
const name = import_utils118.ASTUtils.getPropertyName(member);
|
|
20837
|
+
return name !== null && !UNSAFE_NAMESPACE_METHODS.has(name) && use.parent?.type === import_utils118.AST_NODE_TYPES.CallExpression && use.parent.callee === use;
|
|
20838
|
+
}
|
|
20839
|
+
function readonlyLoaderUse(node, resolve2, stable) {
|
|
20840
|
+
const receiver = outerExpression(node);
|
|
20841
|
+
const parent = receiver.parent;
|
|
20842
|
+
if (parent?.type === import_utils118.AST_NODE_TYPES.VariableDeclarator && parent.init === receiver) {
|
|
20843
|
+
if (parent.id.type === import_utils118.AST_NODE_TYPES.ObjectPattern) return true;
|
|
20844
|
+
if (parent.id.type !== import_utils118.AST_NODE_TYPES.Identifier) return false;
|
|
20845
|
+
const variable = resolve2(parent.id);
|
|
20846
|
+
return variable !== null && stable(variable);
|
|
20847
|
+
}
|
|
20848
|
+
return parent?.type === import_utils118.AST_NODE_TYPES.ExpressionStatement || readonlyNamespaceUse(receiver);
|
|
20849
|
+
}
|
|
20850
|
+
function namespaceDefaultMayEscape(variable) {
|
|
20851
|
+
return variable.references.some((reference) => {
|
|
20852
|
+
if (typeOnlyReference2(reference)) return false;
|
|
20807
20853
|
const receiver = outerExpression(reference.identifier);
|
|
20808
|
-
if (typeQueryReference(receiver)) return true;
|
|
20809
20854
|
const member = receiver.parent;
|
|
20810
20855
|
if (member?.type !== import_utils118.AST_NODE_TYPES.MemberExpression || member.object !== receiver) {
|
|
20811
|
-
return member?.type
|
|
20856
|
+
return member?.type !== import_utils118.AST_NODE_TYPES.UnaryExpression || member.operator !== "typeof";
|
|
20812
20857
|
}
|
|
20813
|
-
const use = outerExpression(member);
|
|
20814
20858
|
const name = import_utils118.ASTUtils.getPropertyName(member);
|
|
20815
|
-
return name
|
|
20859
|
+
return (name === null || name === "default") && !readonlyNamespaceUse(outerExpression(member));
|
|
20816
20860
|
});
|
|
20817
20861
|
}
|
|
20818
|
-
function
|
|
20819
|
-
let current = node;
|
|
20820
|
-
while (current.parent?.type === import_utils118.AST_NODE_TYPES.TSQualifiedName && current.parent.left === current) {
|
|
20821
|
-
current = current.parent;
|
|
20822
|
-
}
|
|
20823
|
-
return current.parent?.type === import_utils118.AST_NODE_TYPES.TSTypeQuery && current.parent.exprName === current;
|
|
20824
|
-
}
|
|
20825
|
-
function isCryptoLoader(node, resolve2) {
|
|
20826
|
-
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
20862
|
+
function isBuiltinLoader(node, resolve2, builtin = "crypto") {
|
|
20827
20863
|
if (node.type !== import_utils118.AST_NODE_TYPES.CallExpression || node.arguments.length !== 1) return false;
|
|
20828
20864
|
const [argument] = node.arguments;
|
|
20829
|
-
if (argument === void 0 || argument.type === import_utils118.AST_NODE_TYPES.SpreadElement || !
|
|
20865
|
+
if (argument === void 0 || argument.type === import_utils118.AST_NODE_TYPES.SpreadElement || !isBuiltinSpecifier(argument, builtin)) {
|
|
20830
20866
|
return false;
|
|
20831
20867
|
}
|
|
20868
|
+
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
20832
20869
|
if (unwrappedNodeCallee?.type === import_utils118.AST_NODE_TYPES.Identifier) {
|
|
20833
20870
|
return unwrappedNodeCallee.name === "require" && isUnshadowedBuiltinIdentifier(unwrappedNodeCallee, resolve2);
|
|
20834
20871
|
}
|
|
20835
20872
|
return unwrappedNodeCallee?.type === import_utils118.AST_NODE_TYPES.MemberExpression && unwrappedNodeCallee.object.type === import_utils118.AST_NODE_TYPES.Identifier && unwrappedNodeCallee.object.name === "process" && isUnshadowedBuiltinIdentifier(unwrappedNodeCallee.object, resolve2) && import_utils118.ASTUtils.getPropertyName(unwrappedNodeCallee) === "getBuiltinModule";
|
|
20836
20873
|
}
|
|
20837
|
-
function
|
|
20838
|
-
return node.type === import_utils118.AST_NODE_TYPES.Literal && (node.value ===
|
|
20874
|
+
function isBuiltinSpecifier(node, builtin) {
|
|
20875
|
+
return node.type === import_utils118.AST_NODE_TYPES.Literal && (node.value === builtin || node.value === `node:${builtin}`);
|
|
20839
20876
|
}
|
|
20840
20877
|
function isUnshadowedBuiltinIdentifier(identifier, resolve2) {
|
|
20841
20878
|
const variable = resolve2(identifier);
|
|
@@ -20854,46 +20891,84 @@ var prefer_node_crypto_hash_default = createRule({
|
|
|
20854
20891
|
meta: { type: "problem", docs: { description: PREFER_NODE_CRYPTO_HASH_DOCUMENTATION.summary }, schema: [], messages: { preferNodeCryptoHash: "Prefer the modern one-shot node:crypto hash API when streaming state is unnecessary." } },
|
|
20855
20892
|
defaultOptions: [],
|
|
20856
20893
|
create(context) {
|
|
20894
|
+
if (!context.sourceCode.text.includes("crypto") && !context.sourceCode.text.includes("\\")) return {};
|
|
20857
20895
|
const directBindings = /* @__PURE__ */ new Set();
|
|
20858
20896
|
const namespaceBindings = /* @__PURE__ */ new Set();
|
|
20897
|
+
const sharedBindings = /* @__PURE__ */ new Set();
|
|
20898
|
+
const syncBindings = /* @__PURE__ */ new Set();
|
|
20899
|
+
const moduleBindings = /* @__PURE__ */ new Set();
|
|
20900
|
+
const namespaceStability = /* @__PURE__ */ new WeakMap();
|
|
20901
|
+
const candidates = [];
|
|
20902
|
+
const possibleSynchronizations = [];
|
|
20903
|
+
let sharedNamespaceUnsafe = false;
|
|
20904
|
+
function namespaceStable(variable) {
|
|
20905
|
+
const cached = namespaceStability.get(variable);
|
|
20906
|
+
if (cached !== void 0) return cached;
|
|
20907
|
+
const stable = stableNamespace(variable);
|
|
20908
|
+
namespaceStability.set(variable, stable);
|
|
20909
|
+
return stable;
|
|
20910
|
+
}
|
|
20859
20911
|
function resolve2(identifier) {
|
|
20860
20912
|
return import_utils118.ASTUtils.findVariable(
|
|
20861
20913
|
context.sourceCode.getScope(identifier),
|
|
20862
20914
|
identifier.name
|
|
20863
20915
|
);
|
|
20864
20916
|
}
|
|
20865
|
-
function record(identifier, destination) {
|
|
20917
|
+
function record(identifier, destination, shared = false) {
|
|
20866
20918
|
const variable = resolve2(identifier);
|
|
20867
|
-
if (variable
|
|
20919
|
+
if (variable === null) return;
|
|
20920
|
+
const stable = destination === namespaceBindings ? namespaceStable(variable) : stableValueBinding(variable);
|
|
20921
|
+
if (shared && destination === namespaceBindings && !stable) sharedNamespaceUnsafe = true;
|
|
20922
|
+
if (!stable) return;
|
|
20923
|
+
destination.add(variable);
|
|
20924
|
+
if (shared) sharedBindings.add(variable);
|
|
20925
|
+
}
|
|
20926
|
+
function recordModuleImports(specifiers) {
|
|
20927
|
+
for (const specifier of specifiers) {
|
|
20928
|
+
if (specifier.type === import_utils118.AST_NODE_TYPES.ImportSpecifier) {
|
|
20929
|
+
if (importedName5(specifier.imported) === "syncBuiltinESMExports") record(specifier.local, syncBindings);
|
|
20930
|
+
else if (importedName5(specifier.imported) === "default") record(specifier.local, moduleBindings);
|
|
20931
|
+
} else record(specifier.local, moduleBindings);
|
|
20932
|
+
}
|
|
20868
20933
|
}
|
|
20869
20934
|
return {
|
|
20870
20935
|
ImportDeclaration(node) {
|
|
20936
|
+
if (node.source.value === "module" || node.source.value === "node:module") {
|
|
20937
|
+
recordModuleImports(node.specifiers);
|
|
20938
|
+
return;
|
|
20939
|
+
}
|
|
20871
20940
|
if (node.source.value !== "crypto" && node.source.value !== "node:crypto") return;
|
|
20872
20941
|
for (const specifier of node.specifiers) {
|
|
20873
|
-
|
|
20874
|
-
|
|
20942
|
+
const shared = specifier.type === import_utils118.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils118.AST_NODE_TYPES.ImportSpecifier && importedName5(specifier.imported) === "default";
|
|
20943
|
+
if (specifier.type === import_utils118.AST_NODE_TYPES.ImportNamespaceSpecifier || shared) {
|
|
20944
|
+
record(specifier.local, namespaceBindings, shared);
|
|
20945
|
+
const variable = resolve2(specifier.local);
|
|
20946
|
+
if (!shared && variable !== null && namespaceDefaultMayEscape(variable)) sharedNamespaceUnsafe = true;
|
|
20875
20947
|
} else if (specifier.type === import_utils118.AST_NODE_TYPES.ImportSpecifier && importedName5(specifier.imported) === "createHash") {
|
|
20876
20948
|
record(specifier.local, directBindings);
|
|
20877
20949
|
}
|
|
20878
20950
|
}
|
|
20879
20951
|
},
|
|
20880
20952
|
VariableDeclarator(node) {
|
|
20881
|
-
if (node.parent.kind !== "const" || node.init === null || !
|
|
20953
|
+
if (node.parent.kind !== "const" || node.init === null || !isBuiltinLoader(node.init, resolve2) && !isBuiltinLoader(node.init, resolve2, "module")) {
|
|
20882
20954
|
return;
|
|
20883
20955
|
}
|
|
20956
|
+
const crypto = isBuiltinLoader(node.init, resolve2);
|
|
20884
20957
|
if (node.id.type === import_utils118.AST_NODE_TYPES.Identifier) {
|
|
20885
|
-
record(node.id, namespaceBindings);
|
|
20958
|
+
record(node.id, crypto ? namespaceBindings : moduleBindings, crypto);
|
|
20886
20959
|
return;
|
|
20887
20960
|
}
|
|
20888
20961
|
if (node.id.type !== import_utils118.AST_NODE_TYPES.ObjectPattern) return;
|
|
20889
20962
|
for (const property of node.id.properties) {
|
|
20890
|
-
if (property.type === import_utils118.AST_NODE_TYPES.Property && propertyName3(property) === "createHash" && property.value.type === import_utils118.AST_NODE_TYPES.Identifier) {
|
|
20891
|
-
record(property.value, directBindings);
|
|
20963
|
+
if (property.type === import_utils118.AST_NODE_TYPES.Property && propertyName3(property) === (crypto ? "createHash" : "syncBuiltinESMExports") && property.value.type === import_utils118.AST_NODE_TYPES.Identifier) {
|
|
20964
|
+
record(property.value, crypto ? directBindings : syncBindings, crypto);
|
|
20892
20965
|
}
|
|
20893
20966
|
}
|
|
20894
20967
|
},
|
|
20895
20968
|
CallExpression(node) {
|
|
20969
|
+
if (isBuiltinLoader(node, resolve2) && !readonlyLoaderUse(node, resolve2, namespaceStable)) sharedNamespaceUnsafe = true;
|
|
20896
20970
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
20971
|
+
if (unwrappedNodeCallee.type === import_utils118.AST_NODE_TYPES.Identifier || unwrappedNodeCallee.type === import_utils118.AST_NODE_TYPES.MemberExpression && import_utils118.ASTUtils.getPropertyName(unwrappedNodeCallee) === "syncBuiltinESMExports") possibleSynchronizations.push(node);
|
|
20897
20972
|
if (unwrappedNodeCallee.type !== import_utils118.AST_NODE_TYPES.MemberExpression || !isMemberCall(node, "digest")) return;
|
|
20898
20973
|
const update = unwrapExpression(unwrappedNodeCallee.object);
|
|
20899
20974
|
if (update.type !== import_utils118.AST_NODE_TYPES.CallExpression || update.arguments.length !== 1 || !isMemberCall(update, "update"))
|
|
@@ -20902,14 +20977,16 @@ var prefer_node_crypto_hash_default = createRule({
|
|
|
20902
20977
|
if (updateCallee.type !== import_utils118.AST_NODE_TYPES.MemberExpression) return;
|
|
20903
20978
|
const create = unwrapExpression(updateCallee.object);
|
|
20904
20979
|
const algorithm = create.type === import_utils118.AST_NODE_TYPES.CallExpression && create.arguments[0] !== void 0 ? unwrapExpression(create.arguments[0]) : null;
|
|
20905
|
-
if (create.type !== import_utils118.AST_NODE_TYPES.CallExpression || create.arguments.length !== 1 || staticString(algorithm ?? void 0) === null
|
|
20906
|
-
create,
|
|
20907
|
-
directBindings,
|
|
20908
|
-
namespaceBindings,
|
|
20909
|
-
resolve2
|
|
20910
|
-
))
|
|
20980
|
+
if (create.type !== import_utils118.AST_NODE_TYPES.CallExpression || create.arguments.length !== 1 || staticString(algorithm ?? void 0) === null)
|
|
20911
20981
|
return;
|
|
20912
|
-
|
|
20982
|
+
const provider = builtinCallProvider(create, directBindings, namespaceBindings, sharedBindings, resolve2);
|
|
20983
|
+
if (provider !== null) candidates.push({ node, shared: provider === "shared" });
|
|
20984
|
+
},
|
|
20985
|
+
"Program:exit"() {
|
|
20986
|
+
const exportsMaySynchronize = sharedNamespaceUnsafe && possibleSynchronizations.some((node) => builtinCallProvider(node, syncBindings, moduleBindings, sharedBindings, resolve2, "module") !== null);
|
|
20987
|
+
for (const candidate2 of candidates) {
|
|
20988
|
+
if (!sharedNamespaceUnsafe || !candidate2.shared && !exportsMaySynchronize) context.report({ node: candidate2.node, messageId: "preferNodeCryptoHash" });
|
|
20989
|
+
}
|
|
20913
20990
|
}
|
|
20914
20991
|
};
|
|
20915
20992
|
}
|
|
@@ -20921,19 +20998,21 @@ function isMemberCall(node, name) {
|
|
|
20921
20998
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
20922
20999
|
return unwrappedNodeCallee.type === import_utils118.AST_NODE_TYPES.MemberExpression && import_utils118.ASTUtils.getPropertyName(unwrappedNodeCallee) === name;
|
|
20923
21000
|
}
|
|
20924
|
-
function
|
|
21001
|
+
function builtinCallProvider(node, directBindings, namespaceBindings, sharedBindings, resolve2, builtin = "crypto") {
|
|
20925
21002
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
20926
21003
|
if (unwrappedNodeCallee.type === import_utils118.AST_NODE_TYPES.Identifier) {
|
|
20927
21004
|
const variable2 = resolve2(unwrappedNodeCallee);
|
|
20928
|
-
|
|
21005
|
+
if (variable2 === null || !directBindings.has(variable2)) return null;
|
|
21006
|
+
return sharedBindings.has(variable2) ? "shared" : "snapshot";
|
|
20929
21007
|
}
|
|
20930
|
-
if (unwrappedNodeCallee.type !== import_utils118.AST_NODE_TYPES.MemberExpression || import_utils118.ASTUtils.getPropertyName(unwrappedNodeCallee) !== "createHash") {
|
|
20931
|
-
return
|
|
21008
|
+
if (unwrappedNodeCallee.type !== import_utils118.AST_NODE_TYPES.MemberExpression || import_utils118.ASTUtils.getPropertyName(unwrappedNodeCallee) !== (builtin === "crypto" ? "createHash" : "syncBuiltinESMExports")) {
|
|
21009
|
+
return null;
|
|
20932
21010
|
}
|
|
20933
|
-
if (
|
|
20934
|
-
if (unwrappedNodeCallee.object.type !== import_utils118.AST_NODE_TYPES.Identifier) return
|
|
21011
|
+
if (isBuiltinLoader(unwrappedNodeCallee.object, resolve2, builtin)) return "shared";
|
|
21012
|
+
if (unwrappedNodeCallee.object.type !== import_utils118.AST_NODE_TYPES.Identifier) return null;
|
|
20935
21013
|
const variable = resolve2(unwrappedNodeCallee.object);
|
|
20936
|
-
|
|
21014
|
+
if (variable === null || !namespaceBindings.has(variable)) return null;
|
|
21015
|
+
return sharedBindings.has(variable) ? "shared" : "snapshot";
|
|
20937
21016
|
}
|
|
20938
21017
|
|
|
20939
21018
|
// src/rules/prefer-node-fs-promises.ts
|
|
@@ -26103,6 +26182,7 @@ var require_static_next_matcher_default = createRule({
|
|
|
26103
26182
|
|
|
26104
26183
|
// src/rules/require-use-form-default-values.ts
|
|
26105
26184
|
var import_utils139 = require("@typescript-eslint/utils");
|
|
26185
|
+
var UNSAFE_FORM_MEMBERS = /* @__PURE__ */ new Set(["__defineGetter__", "__defineSetter__", "__proto__", "valueOf"]);
|
|
26106
26186
|
var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
|
|
26107
26187
|
summary: "Require explicit form-level initialization or a field default for directly bound Controller fields.",
|
|
26108
26188
|
rationale: "React Hook Form exposes form-level defaultValues/values and field-level defaultValue as its explicit initialization mechanisms. A directly bound controlled field should not omit both mechanisms.",
|
|
@@ -26110,7 +26190,8 @@ var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
|
|
|
26110
26190
|
category: "correctness",
|
|
26111
26191
|
limitations: [
|
|
26112
26192
|
"The rule proves only that an explicit form-level initialization option or field default is present; it does not prove that a particular field path occurs inside a defaultValues/values object.",
|
|
26113
|
-
"The rule reports only scope-resolved Controller/useController fields explicitly bound to a directly created useForm control. FormProvider context, wrapper hooks, dynamic options, spreads, computed properties, and interprocedural flows are intentionally left unreported."
|
|
26193
|
+
"The rule reports only scope-resolved Controller/useController fields explicitly bound to a directly created useForm control. FormProvider context, wrapper hooks, dynamic options, spreads, computed properties, and interprocedural flows are intentionally left unreported.",
|
|
26194
|
+
"Form bindings must have one initializer and remain local and read-only; aliases, exports, property writes, and other escaping uses are left unreported."
|
|
26114
26195
|
],
|
|
26115
26196
|
examples: [
|
|
26116
26197
|
{
|
|
@@ -26139,6 +26220,29 @@ function staticPropertyName2(property) {
|
|
|
26139
26220
|
if (property.key.type === import_utils139.AST_NODE_TYPES.Literal && typeof property.key.value === "string") return property.key.value;
|
|
26140
26221
|
return null;
|
|
26141
26222
|
}
|
|
26223
|
+
function readonlyFormReference(reference) {
|
|
26224
|
+
if (typeOnlyReference2(reference)) return true;
|
|
26225
|
+
const receiver = outerExpression(reference.identifier);
|
|
26226
|
+
const parent = receiver.parent;
|
|
26227
|
+
if (parent?.type === import_utils139.AST_NODE_TYPES.VariableDeclarator && parent.init === receiver) return parent.id.type === import_utils139.AST_NODE_TYPES.ObjectPattern;
|
|
26228
|
+
if (parent?.type !== import_utils139.AST_NODE_TYPES.MemberExpression || parent.object !== receiver) {
|
|
26229
|
+
return parent?.type === import_utils139.AST_NODE_TYPES.UnaryExpression && parent.operator === "typeof";
|
|
26230
|
+
}
|
|
26231
|
+
const name = import_utils139.ASTUtils.getPropertyName(parent);
|
|
26232
|
+
return name !== null && !UNSAFE_FORM_MEMBERS.has(name) && !memberWrite(parent);
|
|
26233
|
+
}
|
|
26234
|
+
function memberWrite(node) {
|
|
26235
|
+
let current = outerExpression(node);
|
|
26236
|
+
let parent = current.parent;
|
|
26237
|
+
while (parent?.type === import_utils139.AST_NODE_TYPES.Property && parent.value === current || parent?.type === import_utils139.AST_NODE_TYPES.ObjectPattern || parent?.type === import_utils139.AST_NODE_TYPES.ArrayPattern || parent?.type === import_utils139.AST_NODE_TYPES.RestElement || parent?.type === import_utils139.AST_NODE_TYPES.AssignmentPattern && parent.left === current) {
|
|
26238
|
+
current = parent;
|
|
26239
|
+
parent = current.parent;
|
|
26240
|
+
}
|
|
26241
|
+
return parent?.type === import_utils139.AST_NODE_TYPES.AssignmentExpression && parent.left === current || parent?.type === import_utils139.AST_NODE_TYPES.UpdateExpression && parent.argument === current || parent?.type === import_utils139.AST_NODE_TYPES.UnaryExpression && parent.operator === "delete" || (parent?.type === import_utils139.AST_NODE_TYPES.ForOfStatement || parent?.type === import_utils139.AST_NODE_TYPES.ForInStatement) && parent.left === current;
|
|
26242
|
+
}
|
|
26243
|
+
function stableForm(variable) {
|
|
26244
|
+
return !variable.defs.some((definition) => definition.type === "Variable" && definition.parent.parent.type === import_utils139.AST_NODE_TYPES.ExportNamedDeclaration) && stableValueBinding(variable, readonlyFormReference);
|
|
26245
|
+
}
|
|
26142
26246
|
var require_use_form_default_values_default = createRule({
|
|
26143
26247
|
name: "require-use-form-default-values",
|
|
26144
26248
|
documentation: REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION,
|
|
@@ -26150,19 +26254,15 @@ var require_use_form_default_values_default = createRule({
|
|
|
26150
26254
|
},
|
|
26151
26255
|
defaultOptions: [],
|
|
26152
26256
|
create(context) {
|
|
26257
|
+
if (!context.sourceCode.ast.body.some((statement) => statement.type === import_utils139.AST_NODE_TYPES.ImportDeclaration && statement.source.value === "react-hook-form")) return {};
|
|
26153
26258
|
const imported = /* @__PURE__ */ new Map();
|
|
26154
26259
|
const uninitializedForms = /* @__PURE__ */ new Set();
|
|
26155
26260
|
const uninitializedControls = /* @__PURE__ */ new Set();
|
|
26156
26261
|
const bindingNamed = (node, name) => import_utils139.ASTUtils.findVariable(context.sourceCode.getScope(node), name);
|
|
26157
26262
|
const bindingOf = (node) => bindingNamed(node, node.name);
|
|
26158
|
-
const stable = (variable) => !variable.references.some((reference) => reference.isWrite() && reference.init !== true);
|
|
26159
26263
|
const importedKind = (node) => {
|
|
26160
|
-
const variable = bindingOf(node);
|
|
26161
|
-
return variable !== null && stable(variable) ? imported.get(variable) ?? null : null;
|
|
26162
|
-
};
|
|
26163
|
-
const importedJsxKind = (node) => {
|
|
26164
26264
|
const variable = bindingNamed(node, node.name);
|
|
26165
|
-
return variable
|
|
26265
|
+
return variable === null ? null : imported.get(variable) ?? null;
|
|
26166
26266
|
};
|
|
26167
26267
|
const isDefinitelyUndefined = (node) => {
|
|
26168
26268
|
const value = unwrapExpression(node);
|
|
@@ -26191,13 +26291,13 @@ var require_use_form_default_values_default = createRule({
|
|
|
26191
26291
|
node = unwrapExpression(node);
|
|
26192
26292
|
if (node.type !== import_utils139.AST_NODE_TYPES.Identifier) return false;
|
|
26193
26293
|
const variable = bindingOf(node);
|
|
26194
|
-
return variable !== null &&
|
|
26294
|
+
return variable !== null && uninitializedForms.has(variable);
|
|
26195
26295
|
};
|
|
26196
26296
|
const isUninitializedControl = (node) => {
|
|
26197
26297
|
node = unwrapExpression(node);
|
|
26198
26298
|
if (node.type === import_utils139.AST_NODE_TYPES.Identifier) {
|
|
26199
26299
|
const variable = bindingOf(node);
|
|
26200
|
-
return variable !== null &&
|
|
26300
|
+
return variable !== null && uninitializedControls.has(variable);
|
|
26201
26301
|
}
|
|
26202
26302
|
return node.type === import_utils139.AST_NODE_TYPES.MemberExpression && import_utils139.ASTUtils.getPropertyName(node) !== null && (import_utils139.ASTUtils.getPropertyName(node) ?? "") === "control" && isUninitializedForm(node.object);
|
|
26203
26303
|
};
|
|
@@ -26226,7 +26326,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
26226
26326
|
for (const property of pattern.properties) {
|
|
26227
26327
|
if (property.type !== import_utils139.AST_NODE_TYPES.Property || staticPropertyName2(property) !== "control" || property.value.type !== import_utils139.AST_NODE_TYPES.Identifier) continue;
|
|
26228
26328
|
const variable = bindingOf(property.value);
|
|
26229
|
-
if (variable !== null) uninitializedControls.add(variable);
|
|
26329
|
+
if (variable !== null && stableValueBinding(variable)) uninitializedControls.add(variable);
|
|
26230
26330
|
}
|
|
26231
26331
|
};
|
|
26232
26332
|
return {
|
|
@@ -26237,7 +26337,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
26237
26337
|
const name = specifier.imported.type === import_utils139.AST_NODE_TYPES.Identifier ? specifier.imported.name : String(specifier.imported.value);
|
|
26238
26338
|
if (name !== "Controller" && name !== "useController" && name !== "useForm") continue;
|
|
26239
26339
|
const variable = bindingOf(specifier.local);
|
|
26240
|
-
if (variable !== null) imported.set(variable, name);
|
|
26340
|
+
if (variable !== null && stableValueBinding(variable)) imported.set(variable, name);
|
|
26241
26341
|
}
|
|
26242
26342
|
},
|
|
26243
26343
|
VariableDeclarator(node) {
|
|
@@ -26245,7 +26345,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
26245
26345
|
if (uninitializedUseFormCall(node.init)) {
|
|
26246
26346
|
if (node.id.type === import_utils139.AST_NODE_TYPES.Identifier) {
|
|
26247
26347
|
const variable = bindingOf(node.id);
|
|
26248
|
-
if (variable !== null) uninitializedForms.add(variable);
|
|
26348
|
+
if (variable !== null && stableForm(variable)) uninitializedForms.add(variable);
|
|
26249
26349
|
} else if (node.id.type === import_utils139.AST_NODE_TYPES.ObjectPattern) {
|
|
26250
26350
|
trackDestructuredControl(node.id);
|
|
26251
26351
|
}
|
|
@@ -26257,7 +26357,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
26257
26357
|
}
|
|
26258
26358
|
if (node.id.type === import_utils139.AST_NODE_TYPES.Identifier && node.init.type === import_utils139.AST_NODE_TYPES.MemberExpression && import_utils139.ASTUtils.getPropertyName(node.init) !== null && (import_utils139.ASTUtils.getPropertyName(node.init) ?? "") === "control" && isUninitializedForm(node.init.object)) {
|
|
26259
26359
|
const variable = bindingOf(node.id);
|
|
26260
|
-
if (variable !== null) uninitializedControls.add(variable);
|
|
26360
|
+
if (variable !== null && stableValueBinding(variable)) uninitializedControls.add(variable);
|
|
26261
26361
|
}
|
|
26262
26362
|
},
|
|
26263
26363
|
CallExpression(node) {
|
|
@@ -26266,7 +26366,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
26266
26366
|
context.report({ node, messageId: "requireUseFormDefaultValues" });
|
|
26267
26367
|
},
|
|
26268
26368
|
JSXOpeningElement(node) {
|
|
26269
|
-
if (node.name.type !== import_utils139.AST_NODE_TYPES.JSXIdentifier ||
|
|
26369
|
+
if (node.name.type !== import_utils139.AST_NODE_TYPES.JSXIdentifier || importedKind(node.name) !== "Controller") return;
|
|
26270
26370
|
if (node.attributes.some((attribute) => attribute.type === import_utils139.AST_NODE_TYPES.JSXSpreadAttribute)) return;
|
|
26271
26371
|
const control = jsxAttribute(node, "control");
|
|
26272
26372
|
if (control?.value?.type !== import_utils139.AST_NODE_TYPES.JSXExpressionContainer || control.value.expression.type === import_utils139.AST_NODE_TYPES.JSXEmptyExpression || !isUninitializedControl(control.value.expression)) return;
|
|
@@ -27442,6 +27542,14 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
27442
27542
|
defaultOptions: [],
|
|
27443
27543
|
create(context) {
|
|
27444
27544
|
if (!isTestFile(context) || isGeneratedFile(context, context.sourceCode.text)) return {};
|
|
27545
|
+
const referenceStability = /* @__PURE__ */ new WeakMap();
|
|
27546
|
+
const referenceStable = (variable) => {
|
|
27547
|
+
const cached = referenceStability.get(variable);
|
|
27548
|
+
if (cached !== void 0) return cached;
|
|
27549
|
+
const stable = !variable.references.some((reference) => reference.isWrite() && reference.init !== true);
|
|
27550
|
+
referenceStability.set(variable, stable);
|
|
27551
|
+
return stable;
|
|
27552
|
+
};
|
|
27445
27553
|
const scopes = [newScope()];
|
|
27446
27554
|
const reportedOrigins = /* @__PURE__ */ new Set();
|
|
27447
27555
|
const currentScope = () => scopes.at(-1) ?? scopes[0];
|
|
@@ -27459,7 +27567,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
27459
27567
|
};
|
|
27460
27568
|
const visible = (kind, node) => {
|
|
27461
27569
|
const name2 = bindingOf(node);
|
|
27462
|
-
if (name2 === null || name2
|
|
27570
|
+
if (name2 === null || !referenceStable(name2)) return false;
|
|
27463
27571
|
for (let index = scopes.length - 1; index >= 0; index--) {
|
|
27464
27572
|
const scope = scopes[index];
|
|
27465
27573
|
if (scope.declared.has(name2)) return scope[kind].has(name2);
|
|
@@ -27468,7 +27576,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
27468
27576
|
};
|
|
27469
27577
|
const visibleRawOrigins = (node) => {
|
|
27470
27578
|
const name2 = bindingOf(node);
|
|
27471
|
-
if (name2 === null || name2
|
|
27579
|
+
if (name2 === null || !referenceStable(name2)) return /* @__PURE__ */ new Set();
|
|
27472
27580
|
for (let index = scopes.length - 1; index >= 0; index--) {
|
|
27473
27581
|
const scope = scopes[index];
|
|
27474
27582
|
if (scope.declared.has(name2)) return scope.rawOrigins.get(name2) ?? /* @__PURE__ */ new Set();
|
|
@@ -27500,7 +27608,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
27500
27608
|
};
|
|
27501
27609
|
const nativeImportedName = (node, modules) => {
|
|
27502
27610
|
const binding = bindingOf(node);
|
|
27503
|
-
if (binding === null || binding
|
|
27611
|
+
if (binding === null || !referenceStable(binding)) return null;
|
|
27504
27612
|
for (const definition of binding.defs) {
|
|
27505
27613
|
const imported = definition.node;
|
|
27506
27614
|
if (imported.type === import_utils144.AST_NODE_TYPES.ImportSpecifier && imported.imported.type === import_utils144.AST_NODE_TYPES.Identifier && imported.parent.type === import_utils144.AST_NODE_TYPES.ImportDeclaration && modules.has(String(imported.parent.source.value))) {
|
|
@@ -27511,7 +27619,7 @@ function createSourceCoupledRule(name, documentation, sourceSuffixRe) {
|
|
|
27511
27619
|
};
|
|
27512
27620
|
const stableInitializer = (node) => {
|
|
27513
27621
|
const binding = bindingOf(node);
|
|
27514
|
-
if (binding === null || binding
|
|
27622
|
+
if (binding === null || !referenceStable(binding) || binding.defs.length !== 1) return null;
|
|
27515
27623
|
const definition = binding.defs[0]?.node;
|
|
27516
27624
|
return definition?.type === import_utils144.AST_NODE_TYPES.VariableDeclarator ? definition.init : null;
|
|
27517
27625
|
};
|