@sarj/eslint-plugin 16.26.0 → 16.26.1
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 +144 -54
- package/dist/index.js +1877 -1787
- 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.1",
|
|
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) => {
|
|
@@ -20789,6 +20797,7 @@ var PREFER_NODE_CRYPTO_HASH_DOCUMENTATION = {
|
|
|
20789
20797
|
"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
20798
|
"Only a literal algorithm with exactly one update call is reported; streaming and incremental hashes remain valid.",
|
|
20791
20799
|
"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.",
|
|
20800
|
+
"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
20801
|
"Runtime support and output encoding require manual review; no autofix or guaranteed speedup is promised."
|
|
20793
20802
|
],
|
|
20794
20803
|
references: ["https://nodejs.org/api/crypto.html#cryptohashalgorithm-data-options"],
|
|
@@ -20803,39 +20812,57 @@ var UNSAFE_NAMESPACE_METHODS = /* @__PURE__ */ new Set(["__defineGetter__", "__d
|
|
|
20803
20812
|
function stableNamespace(variable) {
|
|
20804
20813
|
if (variable.defs.some((definition) => definition.type === "Variable" && definition.parent.parent.type === import_utils118.AST_NODE_TYPES.ExportNamedDeclaration)) return false;
|
|
20805
20814
|
return stableValueBinding(variable, (reference) => {
|
|
20806
|
-
if (reference
|
|
20815
|
+
if (typeOnlyReference2(reference)) return true;
|
|
20816
|
+
const receiver = outerExpression(reference.identifier);
|
|
20817
|
+
return readonlyNamespaceUse(receiver);
|
|
20818
|
+
});
|
|
20819
|
+
}
|
|
20820
|
+
function readonlyNamespaceUse(receiver) {
|
|
20821
|
+
const member = receiver.parent;
|
|
20822
|
+
if (member?.type !== import_utils118.AST_NODE_TYPES.MemberExpression || member.object !== receiver) {
|
|
20823
|
+
return member?.type === import_utils118.AST_NODE_TYPES.UnaryExpression && member.operator === "typeof";
|
|
20824
|
+
}
|
|
20825
|
+
const use = outerExpression(member);
|
|
20826
|
+
const name = import_utils118.ASTUtils.getPropertyName(member);
|
|
20827
|
+
return name !== null && !UNSAFE_NAMESPACE_METHODS.has(name) && use.parent?.type === import_utils118.AST_NODE_TYPES.CallExpression && use.parent.callee === use;
|
|
20828
|
+
}
|
|
20829
|
+
function readonlyLoaderUse(node, resolve2, stable) {
|
|
20830
|
+
const receiver = outerExpression(node);
|
|
20831
|
+
const parent = receiver.parent;
|
|
20832
|
+
if (parent?.type === import_utils118.AST_NODE_TYPES.VariableDeclarator && parent.init === receiver) {
|
|
20833
|
+
if (parent.id.type === import_utils118.AST_NODE_TYPES.ObjectPattern) return true;
|
|
20834
|
+
if (parent.id.type !== import_utils118.AST_NODE_TYPES.Identifier) return false;
|
|
20835
|
+
const variable = resolve2(parent.id);
|
|
20836
|
+
return variable !== null && stable(variable);
|
|
20837
|
+
}
|
|
20838
|
+
return parent?.type === import_utils118.AST_NODE_TYPES.ExpressionStatement || readonlyNamespaceUse(receiver);
|
|
20839
|
+
}
|
|
20840
|
+
function namespaceDefaultMayEscape(variable) {
|
|
20841
|
+
return variable.references.some((reference) => {
|
|
20842
|
+
if (typeOnlyReference2(reference)) return false;
|
|
20807
20843
|
const receiver = outerExpression(reference.identifier);
|
|
20808
|
-
if (typeQueryReference(receiver)) return true;
|
|
20809
20844
|
const member = receiver.parent;
|
|
20810
20845
|
if (member?.type !== import_utils118.AST_NODE_TYPES.MemberExpression || member.object !== receiver) {
|
|
20811
|
-
return member?.type
|
|
20846
|
+
return member?.type !== import_utils118.AST_NODE_TYPES.UnaryExpression || member.operator !== "typeof";
|
|
20812
20847
|
}
|
|
20813
|
-
const use = outerExpression(member);
|
|
20814
20848
|
const name = import_utils118.ASTUtils.getPropertyName(member);
|
|
20815
|
-
return name
|
|
20849
|
+
return (name === null || name === "default") && !readonlyNamespaceUse(outerExpression(member));
|
|
20816
20850
|
});
|
|
20817
20851
|
}
|
|
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;
|
|
20852
|
+
function isBuiltinLoader(node, resolve2, builtin = "crypto") {
|
|
20827
20853
|
if (node.type !== import_utils118.AST_NODE_TYPES.CallExpression || node.arguments.length !== 1) return false;
|
|
20828
20854
|
const [argument] = node.arguments;
|
|
20829
|
-
if (argument === void 0 || argument.type === import_utils118.AST_NODE_TYPES.SpreadElement || !
|
|
20855
|
+
if (argument === void 0 || argument.type === import_utils118.AST_NODE_TYPES.SpreadElement || !isBuiltinSpecifier(argument, builtin)) {
|
|
20830
20856
|
return false;
|
|
20831
20857
|
}
|
|
20858
|
+
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
20832
20859
|
if (unwrappedNodeCallee?.type === import_utils118.AST_NODE_TYPES.Identifier) {
|
|
20833
20860
|
return unwrappedNodeCallee.name === "require" && isUnshadowedBuiltinIdentifier(unwrappedNodeCallee, resolve2);
|
|
20834
20861
|
}
|
|
20835
20862
|
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
20863
|
}
|
|
20837
|
-
function
|
|
20838
|
-
return node.type === import_utils118.AST_NODE_TYPES.Literal && (node.value ===
|
|
20864
|
+
function isBuiltinSpecifier(node, builtin) {
|
|
20865
|
+
return node.type === import_utils118.AST_NODE_TYPES.Literal && (node.value === builtin || node.value === `node:${builtin}`);
|
|
20839
20866
|
}
|
|
20840
20867
|
function isUnshadowedBuiltinIdentifier(identifier, resolve2) {
|
|
20841
20868
|
const variable = resolve2(identifier);
|
|
@@ -20854,46 +20881,84 @@ var prefer_node_crypto_hash_default = createRule({
|
|
|
20854
20881
|
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
20882
|
defaultOptions: [],
|
|
20856
20883
|
create(context) {
|
|
20884
|
+
if (!context.sourceCode.text.includes("crypto") && !context.sourceCode.text.includes("\\")) return {};
|
|
20857
20885
|
const directBindings = /* @__PURE__ */ new Set();
|
|
20858
20886
|
const namespaceBindings = /* @__PURE__ */ new Set();
|
|
20887
|
+
const sharedBindings = /* @__PURE__ */ new Set();
|
|
20888
|
+
const syncBindings = /* @__PURE__ */ new Set();
|
|
20889
|
+
const moduleBindings = /* @__PURE__ */ new Set();
|
|
20890
|
+
const namespaceStability = /* @__PURE__ */ new WeakMap();
|
|
20891
|
+
const candidates = [];
|
|
20892
|
+
const possibleSynchronizations = [];
|
|
20893
|
+
let sharedNamespaceUnsafe = false;
|
|
20894
|
+
function namespaceStable(variable) {
|
|
20895
|
+
const cached = namespaceStability.get(variable);
|
|
20896
|
+
if (cached !== void 0) return cached;
|
|
20897
|
+
const stable = stableNamespace(variable);
|
|
20898
|
+
namespaceStability.set(variable, stable);
|
|
20899
|
+
return stable;
|
|
20900
|
+
}
|
|
20859
20901
|
function resolve2(identifier) {
|
|
20860
20902
|
return import_utils118.ASTUtils.findVariable(
|
|
20861
20903
|
context.sourceCode.getScope(identifier),
|
|
20862
20904
|
identifier.name
|
|
20863
20905
|
);
|
|
20864
20906
|
}
|
|
20865
|
-
function record(identifier, destination) {
|
|
20907
|
+
function record(identifier, destination, shared = false) {
|
|
20866
20908
|
const variable = resolve2(identifier);
|
|
20867
|
-
if (variable
|
|
20909
|
+
if (variable === null) return;
|
|
20910
|
+
const stable = destination === namespaceBindings ? namespaceStable(variable) : stableValueBinding(variable);
|
|
20911
|
+
if (shared && destination === namespaceBindings && !stable) sharedNamespaceUnsafe = true;
|
|
20912
|
+
if (!stable) return;
|
|
20913
|
+
destination.add(variable);
|
|
20914
|
+
if (shared) sharedBindings.add(variable);
|
|
20915
|
+
}
|
|
20916
|
+
function recordModuleImports(specifiers) {
|
|
20917
|
+
for (const specifier of specifiers) {
|
|
20918
|
+
if (specifier.type === import_utils118.AST_NODE_TYPES.ImportSpecifier) {
|
|
20919
|
+
if (importedName5(specifier.imported) === "syncBuiltinESMExports") record(specifier.local, syncBindings);
|
|
20920
|
+
else if (importedName5(specifier.imported) === "default") record(specifier.local, moduleBindings);
|
|
20921
|
+
} else record(specifier.local, moduleBindings);
|
|
20922
|
+
}
|
|
20868
20923
|
}
|
|
20869
20924
|
return {
|
|
20870
20925
|
ImportDeclaration(node) {
|
|
20926
|
+
if (node.source.value === "module" || node.source.value === "node:module") {
|
|
20927
|
+
recordModuleImports(node.specifiers);
|
|
20928
|
+
return;
|
|
20929
|
+
}
|
|
20871
20930
|
if (node.source.value !== "crypto" && node.source.value !== "node:crypto") return;
|
|
20872
20931
|
for (const specifier of node.specifiers) {
|
|
20873
|
-
|
|
20874
|
-
|
|
20932
|
+
const shared = specifier.type === import_utils118.AST_NODE_TYPES.ImportDefaultSpecifier || specifier.type === import_utils118.AST_NODE_TYPES.ImportSpecifier && importedName5(specifier.imported) === "default";
|
|
20933
|
+
if (specifier.type === import_utils118.AST_NODE_TYPES.ImportNamespaceSpecifier || shared) {
|
|
20934
|
+
record(specifier.local, namespaceBindings, shared);
|
|
20935
|
+
const variable = resolve2(specifier.local);
|
|
20936
|
+
if (!shared && variable !== null && namespaceDefaultMayEscape(variable)) sharedNamespaceUnsafe = true;
|
|
20875
20937
|
} else if (specifier.type === import_utils118.AST_NODE_TYPES.ImportSpecifier && importedName5(specifier.imported) === "createHash") {
|
|
20876
20938
|
record(specifier.local, directBindings);
|
|
20877
20939
|
}
|
|
20878
20940
|
}
|
|
20879
20941
|
},
|
|
20880
20942
|
VariableDeclarator(node) {
|
|
20881
|
-
if (node.parent.kind !== "const" || node.init === null || !
|
|
20943
|
+
if (node.parent.kind !== "const" || node.init === null || !isBuiltinLoader(node.init, resolve2) && !isBuiltinLoader(node.init, resolve2, "module")) {
|
|
20882
20944
|
return;
|
|
20883
20945
|
}
|
|
20946
|
+
const crypto = isBuiltinLoader(node.init, resolve2);
|
|
20884
20947
|
if (node.id.type === import_utils118.AST_NODE_TYPES.Identifier) {
|
|
20885
|
-
record(node.id, namespaceBindings);
|
|
20948
|
+
record(node.id, crypto ? namespaceBindings : moduleBindings, crypto);
|
|
20886
20949
|
return;
|
|
20887
20950
|
}
|
|
20888
20951
|
if (node.id.type !== import_utils118.AST_NODE_TYPES.ObjectPattern) return;
|
|
20889
20952
|
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);
|
|
20953
|
+
if (property.type === import_utils118.AST_NODE_TYPES.Property && propertyName3(property) === (crypto ? "createHash" : "syncBuiltinESMExports") && property.value.type === import_utils118.AST_NODE_TYPES.Identifier) {
|
|
20954
|
+
record(property.value, crypto ? directBindings : syncBindings, crypto);
|
|
20892
20955
|
}
|
|
20893
20956
|
}
|
|
20894
20957
|
},
|
|
20895
20958
|
CallExpression(node) {
|
|
20959
|
+
if (isBuiltinLoader(node, resolve2) && !readonlyLoaderUse(node, resolve2, namespaceStable)) sharedNamespaceUnsafe = true;
|
|
20896
20960
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
20961
|
+
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
20962
|
if (unwrappedNodeCallee.type !== import_utils118.AST_NODE_TYPES.MemberExpression || !isMemberCall(node, "digest")) return;
|
|
20898
20963
|
const update = unwrapExpression(unwrappedNodeCallee.object);
|
|
20899
20964
|
if (update.type !== import_utils118.AST_NODE_TYPES.CallExpression || update.arguments.length !== 1 || !isMemberCall(update, "update"))
|
|
@@ -20902,14 +20967,16 @@ var prefer_node_crypto_hash_default = createRule({
|
|
|
20902
20967
|
if (updateCallee.type !== import_utils118.AST_NODE_TYPES.MemberExpression) return;
|
|
20903
20968
|
const create = unwrapExpression(updateCallee.object);
|
|
20904
20969
|
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
|
-
))
|
|
20970
|
+
if (create.type !== import_utils118.AST_NODE_TYPES.CallExpression || create.arguments.length !== 1 || staticString(algorithm ?? void 0) === null)
|
|
20911
20971
|
return;
|
|
20912
|
-
|
|
20972
|
+
const provider = builtinCallProvider(create, directBindings, namespaceBindings, sharedBindings, resolve2);
|
|
20973
|
+
if (provider !== null) candidates.push({ node, shared: provider === "shared" });
|
|
20974
|
+
},
|
|
20975
|
+
"Program:exit"() {
|
|
20976
|
+
const exportsMaySynchronize = sharedNamespaceUnsafe && possibleSynchronizations.some((node) => builtinCallProvider(node, syncBindings, moduleBindings, sharedBindings, resolve2, "module") !== null);
|
|
20977
|
+
for (const candidate2 of candidates) {
|
|
20978
|
+
if (!sharedNamespaceUnsafe || !candidate2.shared && !exportsMaySynchronize) context.report({ node: candidate2.node, messageId: "preferNodeCryptoHash" });
|
|
20979
|
+
}
|
|
20913
20980
|
}
|
|
20914
20981
|
};
|
|
20915
20982
|
}
|
|
@@ -20921,19 +20988,21 @@ function isMemberCall(node, name) {
|
|
|
20921
20988
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
20922
20989
|
return unwrappedNodeCallee.type === import_utils118.AST_NODE_TYPES.MemberExpression && import_utils118.ASTUtils.getPropertyName(unwrappedNodeCallee) === name;
|
|
20923
20990
|
}
|
|
20924
|
-
function
|
|
20991
|
+
function builtinCallProvider(node, directBindings, namespaceBindings, sharedBindings, resolve2, builtin = "crypto") {
|
|
20925
20992
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
20926
20993
|
if (unwrappedNodeCallee.type === import_utils118.AST_NODE_TYPES.Identifier) {
|
|
20927
20994
|
const variable2 = resolve2(unwrappedNodeCallee);
|
|
20928
|
-
|
|
20995
|
+
if (variable2 === null || !directBindings.has(variable2)) return null;
|
|
20996
|
+
return sharedBindings.has(variable2) ? "shared" : "snapshot";
|
|
20929
20997
|
}
|
|
20930
|
-
if (unwrappedNodeCallee.type !== import_utils118.AST_NODE_TYPES.MemberExpression || import_utils118.ASTUtils.getPropertyName(unwrappedNodeCallee) !== "createHash") {
|
|
20931
|
-
return
|
|
20998
|
+
if (unwrappedNodeCallee.type !== import_utils118.AST_NODE_TYPES.MemberExpression || import_utils118.ASTUtils.getPropertyName(unwrappedNodeCallee) !== (builtin === "crypto" ? "createHash" : "syncBuiltinESMExports")) {
|
|
20999
|
+
return null;
|
|
20932
21000
|
}
|
|
20933
|
-
if (
|
|
20934
|
-
if (unwrappedNodeCallee.object.type !== import_utils118.AST_NODE_TYPES.Identifier) return
|
|
21001
|
+
if (isBuiltinLoader(unwrappedNodeCallee.object, resolve2, builtin)) return "shared";
|
|
21002
|
+
if (unwrappedNodeCallee.object.type !== import_utils118.AST_NODE_TYPES.Identifier) return null;
|
|
20935
21003
|
const variable = resolve2(unwrappedNodeCallee.object);
|
|
20936
|
-
|
|
21004
|
+
if (variable === null || !namespaceBindings.has(variable)) return null;
|
|
21005
|
+
return sharedBindings.has(variable) ? "shared" : "snapshot";
|
|
20937
21006
|
}
|
|
20938
21007
|
|
|
20939
21008
|
// src/rules/prefer-node-fs-promises.ts
|
|
@@ -26103,6 +26172,7 @@ var require_static_next_matcher_default = createRule({
|
|
|
26103
26172
|
|
|
26104
26173
|
// src/rules/require-use-form-default-values.ts
|
|
26105
26174
|
var import_utils139 = require("@typescript-eslint/utils");
|
|
26175
|
+
var UNSAFE_FORM_MEMBERS = /* @__PURE__ */ new Set(["__defineGetter__", "__defineSetter__", "__proto__", "valueOf"]);
|
|
26106
26176
|
var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
|
|
26107
26177
|
summary: "Require explicit form-level initialization or a field default for directly bound Controller fields.",
|
|
26108
26178
|
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 +26180,8 @@ var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
|
|
|
26110
26180
|
category: "correctness",
|
|
26111
26181
|
limitations: [
|
|
26112
26182
|
"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."
|
|
26183
|
+
"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.",
|
|
26184
|
+
"Form bindings must have one initializer and remain local and read-only; aliases, exports, property writes, and other escaping uses are left unreported."
|
|
26114
26185
|
],
|
|
26115
26186
|
examples: [
|
|
26116
26187
|
{
|
|
@@ -26139,6 +26210,29 @@ function staticPropertyName2(property) {
|
|
|
26139
26210
|
if (property.key.type === import_utils139.AST_NODE_TYPES.Literal && typeof property.key.value === "string") return property.key.value;
|
|
26140
26211
|
return null;
|
|
26141
26212
|
}
|
|
26213
|
+
function readonlyFormReference(reference) {
|
|
26214
|
+
if (typeOnlyReference2(reference)) return true;
|
|
26215
|
+
const receiver = outerExpression(reference.identifier);
|
|
26216
|
+
const parent = receiver.parent;
|
|
26217
|
+
if (parent?.type === import_utils139.AST_NODE_TYPES.VariableDeclarator && parent.init === receiver) return parent.id.type === import_utils139.AST_NODE_TYPES.ObjectPattern;
|
|
26218
|
+
if (parent?.type !== import_utils139.AST_NODE_TYPES.MemberExpression || parent.object !== receiver) {
|
|
26219
|
+
return parent?.type === import_utils139.AST_NODE_TYPES.UnaryExpression && parent.operator === "typeof";
|
|
26220
|
+
}
|
|
26221
|
+
const name = import_utils139.ASTUtils.getPropertyName(parent);
|
|
26222
|
+
return name !== null && !UNSAFE_FORM_MEMBERS.has(name) && !memberWrite(parent);
|
|
26223
|
+
}
|
|
26224
|
+
function memberWrite(node) {
|
|
26225
|
+
let current = outerExpression(node);
|
|
26226
|
+
let parent = current.parent;
|
|
26227
|
+
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) {
|
|
26228
|
+
current = parent;
|
|
26229
|
+
parent = current.parent;
|
|
26230
|
+
}
|
|
26231
|
+
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;
|
|
26232
|
+
}
|
|
26233
|
+
function stableForm(variable) {
|
|
26234
|
+
return !variable.defs.some((definition) => definition.type === "Variable" && definition.parent.parent.type === import_utils139.AST_NODE_TYPES.ExportNamedDeclaration) && stableValueBinding(variable, readonlyFormReference);
|
|
26235
|
+
}
|
|
26142
26236
|
var require_use_form_default_values_default = createRule({
|
|
26143
26237
|
name: "require-use-form-default-values",
|
|
26144
26238
|
documentation: REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION,
|
|
@@ -26150,19 +26244,15 @@ var require_use_form_default_values_default = createRule({
|
|
|
26150
26244
|
},
|
|
26151
26245
|
defaultOptions: [],
|
|
26152
26246
|
create(context) {
|
|
26247
|
+
if (!context.sourceCode.ast.body.some((statement) => statement.type === import_utils139.AST_NODE_TYPES.ImportDeclaration && statement.source.value === "react-hook-form")) return {};
|
|
26153
26248
|
const imported = /* @__PURE__ */ new Map();
|
|
26154
26249
|
const uninitializedForms = /* @__PURE__ */ new Set();
|
|
26155
26250
|
const uninitializedControls = /* @__PURE__ */ new Set();
|
|
26156
26251
|
const bindingNamed = (node, name) => import_utils139.ASTUtils.findVariable(context.sourceCode.getScope(node), name);
|
|
26157
26252
|
const bindingOf = (node) => bindingNamed(node, node.name);
|
|
26158
|
-
const stable = (variable) => !variable.references.some((reference) => reference.isWrite() && reference.init !== true);
|
|
26159
26253
|
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
26254
|
const variable = bindingNamed(node, node.name);
|
|
26165
|
-
return variable
|
|
26255
|
+
return variable === null ? null : imported.get(variable) ?? null;
|
|
26166
26256
|
};
|
|
26167
26257
|
const isDefinitelyUndefined = (node) => {
|
|
26168
26258
|
const value = unwrapExpression(node);
|
|
@@ -26191,13 +26281,13 @@ var require_use_form_default_values_default = createRule({
|
|
|
26191
26281
|
node = unwrapExpression(node);
|
|
26192
26282
|
if (node.type !== import_utils139.AST_NODE_TYPES.Identifier) return false;
|
|
26193
26283
|
const variable = bindingOf(node);
|
|
26194
|
-
return variable !== null &&
|
|
26284
|
+
return variable !== null && uninitializedForms.has(variable);
|
|
26195
26285
|
};
|
|
26196
26286
|
const isUninitializedControl = (node) => {
|
|
26197
26287
|
node = unwrapExpression(node);
|
|
26198
26288
|
if (node.type === import_utils139.AST_NODE_TYPES.Identifier) {
|
|
26199
26289
|
const variable = bindingOf(node);
|
|
26200
|
-
return variable !== null &&
|
|
26290
|
+
return variable !== null && uninitializedControls.has(variable);
|
|
26201
26291
|
}
|
|
26202
26292
|
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
26293
|
};
|
|
@@ -26226,7 +26316,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
26226
26316
|
for (const property of pattern.properties) {
|
|
26227
26317
|
if (property.type !== import_utils139.AST_NODE_TYPES.Property || staticPropertyName2(property) !== "control" || property.value.type !== import_utils139.AST_NODE_TYPES.Identifier) continue;
|
|
26228
26318
|
const variable = bindingOf(property.value);
|
|
26229
|
-
if (variable !== null) uninitializedControls.add(variable);
|
|
26319
|
+
if (variable !== null && stableValueBinding(variable)) uninitializedControls.add(variable);
|
|
26230
26320
|
}
|
|
26231
26321
|
};
|
|
26232
26322
|
return {
|
|
@@ -26237,7 +26327,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
26237
26327
|
const name = specifier.imported.type === import_utils139.AST_NODE_TYPES.Identifier ? specifier.imported.name : String(specifier.imported.value);
|
|
26238
26328
|
if (name !== "Controller" && name !== "useController" && name !== "useForm") continue;
|
|
26239
26329
|
const variable = bindingOf(specifier.local);
|
|
26240
|
-
if (variable !== null) imported.set(variable, name);
|
|
26330
|
+
if (variable !== null && stableValueBinding(variable)) imported.set(variable, name);
|
|
26241
26331
|
}
|
|
26242
26332
|
},
|
|
26243
26333
|
VariableDeclarator(node) {
|
|
@@ -26245,7 +26335,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
26245
26335
|
if (uninitializedUseFormCall(node.init)) {
|
|
26246
26336
|
if (node.id.type === import_utils139.AST_NODE_TYPES.Identifier) {
|
|
26247
26337
|
const variable = bindingOf(node.id);
|
|
26248
|
-
if (variable !== null) uninitializedForms.add(variable);
|
|
26338
|
+
if (variable !== null && stableForm(variable)) uninitializedForms.add(variable);
|
|
26249
26339
|
} else if (node.id.type === import_utils139.AST_NODE_TYPES.ObjectPattern) {
|
|
26250
26340
|
trackDestructuredControl(node.id);
|
|
26251
26341
|
}
|
|
@@ -26257,7 +26347,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
26257
26347
|
}
|
|
26258
26348
|
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
26349
|
const variable = bindingOf(node.id);
|
|
26260
|
-
if (variable !== null) uninitializedControls.add(variable);
|
|
26350
|
+
if (variable !== null && stableValueBinding(variable)) uninitializedControls.add(variable);
|
|
26261
26351
|
}
|
|
26262
26352
|
},
|
|
26263
26353
|
CallExpression(node) {
|
|
@@ -26266,7 +26356,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
26266
26356
|
context.report({ node, messageId: "requireUseFormDefaultValues" });
|
|
26267
26357
|
},
|
|
26268
26358
|
JSXOpeningElement(node) {
|
|
26269
|
-
if (node.name.type !== import_utils139.AST_NODE_TYPES.JSXIdentifier ||
|
|
26359
|
+
if (node.name.type !== import_utils139.AST_NODE_TYPES.JSXIdentifier || importedKind(node.name) !== "Controller") return;
|
|
26270
26360
|
if (node.attributes.some((attribute) => attribute.type === import_utils139.AST_NODE_TYPES.JSXSpreadAttribute)) return;
|
|
26271
26361
|
const control = jsxAttribute(node, "control");
|
|
26272
26362
|
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;
|