@sarj/eslint-plugin 16.4.7 → 16.4.8
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 +423 -71
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +702 -350
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -49,6 +49,125 @@ __export(src_exports, {
|
|
|
49
49
|
});
|
|
50
50
|
module.exports = __toCommonJS(src_exports);
|
|
51
51
|
|
|
52
|
+
// package.json
|
|
53
|
+
var package_default = {
|
|
54
|
+
name: "@sarj/eslint-plugin",
|
|
55
|
+
version: "16.4.8",
|
|
56
|
+
packageManager: "npm@12.1.0",
|
|
57
|
+
description: "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
58
|
+
type: "module",
|
|
59
|
+
main: "./dist/index.cjs",
|
|
60
|
+
module: "./dist/index.js",
|
|
61
|
+
types: "./dist/index.d.ts",
|
|
62
|
+
exports: {
|
|
63
|
+
".": {
|
|
64
|
+
types: "./dist/index.d.ts",
|
|
65
|
+
import: "./dist/index.js",
|
|
66
|
+
require: "./dist/index.cjs"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
files: [
|
|
70
|
+
"dist",
|
|
71
|
+
"README.md",
|
|
72
|
+
"LICENSE"
|
|
73
|
+
],
|
|
74
|
+
publishConfig: {
|
|
75
|
+
access: "public"
|
|
76
|
+
},
|
|
77
|
+
sideEffects: false,
|
|
78
|
+
repository: {
|
|
79
|
+
type: "git",
|
|
80
|
+
url: "git+https://github.com/sarj-ai/code-standards.git",
|
|
81
|
+
directory: "packages/typescript"
|
|
82
|
+
},
|
|
83
|
+
homepage: "https://code-standards.sarj.ai/rules/eslint/",
|
|
84
|
+
bugs: {
|
|
85
|
+
url: "https://github.com/sarj-ai/code-standards/issues"
|
|
86
|
+
},
|
|
87
|
+
scripts: {
|
|
88
|
+
build: "tsup",
|
|
89
|
+
dogfood: "npm run build && npm run dogfood:built",
|
|
90
|
+
lint: "eslint . ../../.github/scripts ../standards/src ../standards/eslint.config.mjs --max-warnings 0",
|
|
91
|
+
prepack: "npm run build && npm run verify-package",
|
|
92
|
+
test: "vitest run",
|
|
93
|
+
typecheck: "tsc --noEmit",
|
|
94
|
+
"verify-package": `node -e "const fs=require('node:fs'),p=require('./package.json'),walk=x=>typeof x==='string'?[x]:x&&typeof x==='object'?Object.values(x).flatMap(walk):[];for(const file of new Set([p.main,p.module,p.types,...walk(p.exports)].filter(Boolean).map(x=>x.startsWith('./')?x.slice(2):x))){if(!file.startsWith('dist/'))throw new Error('export must live under dist: '+file);const stat=fs.statSync(file);if(!stat.isFile()||stat.size===0)throw new Error('missing or empty export: '+file)}"`,
|
|
95
|
+
"dogfood:built": `eslint --config eslint.dogfood.config.mjs src tests eslint.config.mjs eslint.dogfood.config.mjs module-constant-naming-options.mjs tsup.config.ts vitest.config.ts --max-warnings 0 && node -e "import('./dist/index.js').then(({default:p}) => console.log('dogfood: '+Object.keys(p.rules).length+' TypeScript rules, 0 diagnostics'))"`
|
|
96
|
+
},
|
|
97
|
+
keywords: [
|
|
98
|
+
"eslint",
|
|
99
|
+
"eslintplugin",
|
|
100
|
+
"eslint-plugin",
|
|
101
|
+
"sarj",
|
|
102
|
+
"react",
|
|
103
|
+
"nextjs",
|
|
104
|
+
"zod"
|
|
105
|
+
],
|
|
106
|
+
author: "sarj-ai",
|
|
107
|
+
license: "MIT",
|
|
108
|
+
dependencies: {
|
|
109
|
+
"@typescript-eslint/typescript-estree": "^8.70.1",
|
|
110
|
+
"@typescript-eslint/utils": "^8.70.1",
|
|
111
|
+
"jsonc-parser": "^3.3.1"
|
|
112
|
+
},
|
|
113
|
+
devDependencies: {
|
|
114
|
+
"@eslint-community/eslint-plugin-eslint-comments": "^4.8.1",
|
|
115
|
+
"@eslint/compat": "^2.1.1",
|
|
116
|
+
"@eslint/js": "10.0.1",
|
|
117
|
+
"@shadcn/lint": "0.2.0",
|
|
118
|
+
"@types/node": "26.6.2",
|
|
119
|
+
"@typescript-eslint/parser": "8.70.1",
|
|
120
|
+
"@typescript-eslint/rule-tester": "8.70.1",
|
|
121
|
+
"@typescript-eslint/utils": "8.70.1",
|
|
122
|
+
"@typescript/native": "npm:typescript@7.0.2",
|
|
123
|
+
"@vitest/eslint-plugin": "1.6.27",
|
|
124
|
+
eslint: "10.11.0",
|
|
125
|
+
"eslint-node-test": "0.4.0",
|
|
126
|
+
"eslint-plugin-better-tailwindcss": "^4.7.0",
|
|
127
|
+
"eslint-plugin-jest": "29.16.6",
|
|
128
|
+
"eslint-plugin-jsdoc": "64.5.4",
|
|
129
|
+
"eslint-plugin-n": "^18.3.0",
|
|
130
|
+
"eslint-plugin-perfectionist": "5.12.1",
|
|
131
|
+
"eslint-plugin-playwright": "2.12.0",
|
|
132
|
+
"eslint-plugin-promise": "^7.3.0",
|
|
133
|
+
"eslint-plugin-react": "^7.37.5",
|
|
134
|
+
"eslint-plugin-react-hooks": "^7.1.1",
|
|
135
|
+
"eslint-plugin-simple-import-sort": "^14.0.0",
|
|
136
|
+
"eslint-plugin-testing-library": "7.16.2",
|
|
137
|
+
"eslint-plugin-unicorn": "^76.0.0",
|
|
138
|
+
"eslint-plugin-zod": "^4.14.2",
|
|
139
|
+
globals: "15.15.0",
|
|
140
|
+
tsup: "latest",
|
|
141
|
+
typescript: "npm:@typescript/typescript6@6.0.2",
|
|
142
|
+
"typescript-eslint": "^8.70.1",
|
|
143
|
+
vitest: "5.0.1"
|
|
144
|
+
},
|
|
145
|
+
peerDependencies: {
|
|
146
|
+
eslint: ">=9.39.4",
|
|
147
|
+
typescript: ">=5.0.0"
|
|
148
|
+
},
|
|
149
|
+
engines: {
|
|
150
|
+
node: ">=22.22.2"
|
|
151
|
+
},
|
|
152
|
+
allowScripts: {
|
|
153
|
+
"esbuild@0.28.2": true,
|
|
154
|
+
"fsevents@2.3.3": true
|
|
155
|
+
},
|
|
156
|
+
peerDependenciesMeta: {
|
|
157
|
+
typescript: {
|
|
158
|
+
optional: true
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
overrides: {
|
|
162
|
+
"brace-expansion@^5.0.0": "5.0.9",
|
|
163
|
+
esbuild: "0.28.2",
|
|
164
|
+
"nanoid@<3.3.18": "3.3.18",
|
|
165
|
+
"eslint-plugin-react": {
|
|
166
|
+
eslint: "$eslint"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
52
171
|
// src/rules/require-explicit-contract-implementation.ts
|
|
53
172
|
var import_utils2 = require("@typescript-eslint/utils");
|
|
54
173
|
var ts = __toESM(require("typescript"), 1);
|
|
@@ -4794,6 +4913,41 @@ function staticString(node) {
|
|
|
4794
4913
|
if (value.type === import_utils29.AST_NODE_TYPES.Literal && typeof value.value === "string") return value.value;
|
|
4795
4914
|
return value.type === import_utils29.AST_NODE_TYPES.TemplateLiteral && value.expressions.length === 0 ? value.quasis[0]?.value.cooked ?? null : null;
|
|
4796
4915
|
}
|
|
4916
|
+
var SCOPED_STRING_VALUES = /* @__PURE__ */ new WeakMap();
|
|
4917
|
+
function scopedStaticString(node, sourceCode) {
|
|
4918
|
+
let value = unwrapExpression(node);
|
|
4919
|
+
if (value.type !== import_utils29.AST_NODE_TYPES.Identifier) return staticString(value);
|
|
4920
|
+
let values = SCOPED_STRING_VALUES.get(sourceCode);
|
|
4921
|
+
if (values === void 0) {
|
|
4922
|
+
values = /* @__PURE__ */ new WeakMap();
|
|
4923
|
+
SCOPED_STRING_VALUES.set(sourceCode, values);
|
|
4924
|
+
}
|
|
4925
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4926
|
+
const pending = [];
|
|
4927
|
+
let result = null;
|
|
4928
|
+
while (value.type === import_utils29.AST_NODE_TYPES.Identifier) {
|
|
4929
|
+
const binding = import_utils29.ASTUtils.findVariable(sourceCode.getScope(value), value.name);
|
|
4930
|
+
if (binding === null || seen.has(binding)) break;
|
|
4931
|
+
if (values.has(binding)) {
|
|
4932
|
+
result = values.get(binding) ?? null;
|
|
4933
|
+
break;
|
|
4934
|
+
}
|
|
4935
|
+
seen.add(binding);
|
|
4936
|
+
pending.push(binding);
|
|
4937
|
+
const definition = binding.defs.length === 1 ? binding.defs[0] : void 0;
|
|
4938
|
+
if (definition?.type !== "Variable" || definition.node.id.type !== import_utils29.AST_NODE_TYPES.Identifier || definition.node.init === null || binding.references.some((reference) => reference.isWrite() && reference.init !== true)) break;
|
|
4939
|
+
value = unwrapExpression(definition.node.init);
|
|
4940
|
+
if (value.type !== import_utils29.AST_NODE_TYPES.Identifier) result = staticString(value);
|
|
4941
|
+
}
|
|
4942
|
+
for (const binding of pending) values.set(binding, result);
|
|
4943
|
+
return result;
|
|
4944
|
+
}
|
|
4945
|
+
function staticPropertyName(node, sourceCode) {
|
|
4946
|
+
const direct = import_utils29.ASTUtils.getPropertyName(node);
|
|
4947
|
+
if (direct !== null || !node.computed) return direct;
|
|
4948
|
+
const key = node.type === import_utils29.AST_NODE_TYPES.MemberExpression ? node.property : node.key;
|
|
4949
|
+
return key.type === import_utils29.AST_NODE_TYPES.Identifier ? scopedStaticString(key, sourceCode) : null;
|
|
4950
|
+
}
|
|
4797
4951
|
|
|
4798
4952
|
// src/rules/no-duplicate-lifecycle-refresh-listeners.ts
|
|
4799
4953
|
var NO_DUPLICATE_LIFECYCLE_REFRESH_LISTENERS_DOCUMENTATION = {
|
|
@@ -6833,31 +6987,26 @@ var NO_JSON_STRINGIFY_ERROR_DOCUMENTATION = {
|
|
|
6833
6987
|
rationale: "Native Error details are non-enumerable, so generic JSON serialization discards diagnostic information.",
|
|
6834
6988
|
remediation: "Serialize explicit error fields or use an error-aware serializer.",
|
|
6835
6989
|
category: "correctness",
|
|
6836
|
-
limitations: ["The rule uses stable local catch bindings and unshadowed built-in constructors, not runtime type information. Custom replacers are left to their serializer contract; a catch value is not guaranteed to be an Error."],
|
|
6990
|
+
limitations: ["The rule uses stable local catch bindings and unshadowed built-in constructors, not runtime type information. Custom replacers and explicit toJSON hooks are left to their serializer contract; a catch value is not guaranteed to be an Error. Member values, including cause, do not inherit the base Error's provenance; even an Error-valued member requires explicit value/dataflow proof outside this rule. Known literal __proto__ initializer chains preserve native hook inheritance and own toJSON precedence; computed __proto__ keys remain data. Unknown prototype expressions, hook values/spreads and deferred hook writes conservatively lose default serializer proof. Explicit writes invalidate constructor provenance except a later, separate top-level statement; deferred functions, loops, and unknown property keys conservatively lose constructor proof. Statically owned global/property writes and native Reflect.set/Reflect.defineProperty/Object.defineProperty/Object.defineProperties calls are tracked. Mutator aliases, replaced Reflect/Object methods, external calls, and runtime-only property names are not resolved; uncertain ordering conservatively loses proof."],
|
|
6837
6991
|
examples: [
|
|
6838
6992
|
{ id: "explicit-error-message", title: "Narrow an unknown catch value before selecting fields", outcome: "no-match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err instanceof Error ? err.message : String(err) }); }" }], focusPath: "src/report.ts", expectedCount: 0, public: true },
|
|
6839
6993
|
{ id: "stringified-error", title: "Do not stringify an Error object", outcome: "match", files: [{ path: "src/report.ts", source: "try { f(); } catch (err) { JSON.stringify({ error: err }); }" }], focusPath: "src/report.ts", expectedCount: 1, public: true },
|
|
6840
6994
|
{ id: "shadowed-error-binding", scenarioId: "binding-provenance", title: "Keep native binding provenance", outcome: "match", files: [{ path: "src/error.ts", source: 'function probe(){try{throw {id:1};}catch(err){if(err instanceof Error)return err.message;{const err=new Error("lost");return JSON.stringify(err);}}}\nconsole.log(probe());' }], focusPath: "src/error.ts", expectedCount: 1, public: true },
|
|
6841
|
-
{ id: "escaped-fallback-binding", scenarioId: "binding-provenance", title: "Keep native binding provenance", outcome: "no-match", files: [{ path: "src/error.ts", source: "function probe(){try{throw {id:1};}catch(err){if(err instanceof Error)return err.message;return JSON.stringify(\\u0065rr);}}\nconsole.log(probe());" }], focusPath: "src/error.ts", expectedCount: 0, public: true }
|
|
6995
|
+
{ id: "escaped-fallback-binding", scenarioId: "binding-provenance", title: "Keep native binding provenance", outcome: "no-match", files: [{ path: "src/error.ts", source: "function probe(){try{throw {id:1};}catch(err){if(err instanceof Error)return err.message;return JSON.stringify(\\u0065rr);}}\nconsole.log(probe());" }], focusPath: "src/error.ts", expectedCount: 0, public: true },
|
|
6996
|
+
{ id: "constructor-before-write", scenarioId: "explicit-constructor-write", title: "A later write does not change an already constructed native Error", outcome: "match", files: [{ path: "src/error.js", source: "const value=new Error('lost');Error=class Other{message='kept'};JSON.stringify(value);" }], focusPath: "src/error.js", expectedCount: 1, public: true },
|
|
6997
|
+
{ id: "constructor-after-write", scenarioId: "explicit-constructor-write", title: "A replaced constructor does not prove a native Error", outcome: "no-match", files: [{ path: "src/error.js", source: "Error=class Other{message='kept'};const value=new Error();JSON.stringify(value);" }], focusPath: "src/error.js", expectedCount: 0, public: true },
|
|
6998
|
+
{ "id": "native-serializer-before-write", "scenarioId": "explicit-serializer-write", "title": "A later write does not change an earlier native serialization", "outcome": "match", "files": [{ "path": "src/error.js", "source": "const result=JSON.stringify(new Error('lost'));JSON.stringify=value=>'kept:'+value.message;" }], "focusPath": "src/error.js", "expectedCount": 1, "public": true },
|
|
6999
|
+
{ "id": "native-serializer-after-write", "scenarioId": "explicit-serializer-write", "title": "A replaced serializer owns its error-field contract", "outcome": "no-match", "files": [{ "path": "src/error.js", "source": "JSON.stringify=value=>'kept:'+value.message;JSON.stringify(new Error('lost'));" }], "focusPath": "src/error.js", "expectedCount": 0, "public": true },
|
|
7000
|
+
{ "id": "static-serializer-key", "scenarioId": "static-property-provenance", "title": "A constant computed serializer still loses native Error details", "outcome": "match", "files": [{ "path": "src/error.js", "source": "const key='stringify';JSON[key](new Error('lost'));" }], "focusPath": "src/error.js", "expectedCount": 1, "public": true },
|
|
7001
|
+
{ "id": "static-error-field", "scenarioId": "static-property-provenance", "title": "A constant message field selects the explicit string escape hatch", "outcome": "no-match", "files": [{ "path": "src/error.js", "source": "const key='message';const error=new Error('lost');JSON.stringify(error[key]);" }], "focusPath": "src/error.js", "expectedCount": 0, "public": true },
|
|
7002
|
+
{ "id": "scalar-cause", "scenarioId": "member-value-provenance", "title": "Native Error cause can be a string value", "outcome": "no-match", "files": [{ "path": "src/error.js", "source": "const error=new Error('lost',{cause:'kept'});JSON.stringify(error.cause);" }], "focusPath": "src/error.js", "expectedCount": 0, "public": true },
|
|
7003
|
+
{ "id": "whole-error-with-cause", "scenarioId": "member-value-provenance", "title": "Serializing the whole Error still loses its native details", "outcome": "match", "files": [{ "path": "src/error.js", "source": "const error=new Error('lost',{cause:'kept'});JSON.stringify(error);" }], "focusPath": "src/error.js", "expectedCount": 1, "public": true },
|
|
7004
|
+
{ "id": "explicit-to-json-hook", "scenarioId": "custom-serializer-contract", "title": "An explicit callable toJSON owns its serialization contract", "outcome": "no-match", "files": [{ "path": "src/error.js", "source": "JSON.stringify({error:new Error('lost'),toJSON(){return {message:'kept'};}});" }], "focusPath": "src/error.js", "expectedCount": 0, "public": true },
|
|
7005
|
+
{ "id": "noncallable-to-json", "scenarioId": "custom-serializer-contract", "title": "A noncallable toJSON does not replace native serialization", "outcome": "match", "files": [{ "path": "src/error.js", "source": "JSON.stringify({error:new Error('lost'),toJSON:42});" }], "focusPath": "src/error.js", "expectedCount": 1, "public": true },
|
|
7006
|
+
{ "id": "literal-prototype-hook", "scenarioId": "native-prototype-serializer", "title": "A literal prototype hook owns the payload serializer contract", "outcome": "no-match", "files": [{ "path": "src/error.js", "source": "JSON.stringify({error:new Error('lost'),__proto__:{toJSON(){return {message:'kept'};}}});" }], "focusPath": "src/error.js", "expectedCount": 0, "public": true },
|
|
7007
|
+
{ "id": "computed-prototype-data", "scenarioId": "native-prototype-serializer", "title": "A computed prototype name remains ordinary serialized data", "outcome": "match", "files": [{ "path": "src/error.js", "source": "JSON.stringify({error:new Error('lost'),['__proto__']:{toJSON(){return {message:'kept'};}}});" }], "focusPath": "src/error.js", "expectedCount": 1, "public": true }
|
|
6842
7008
|
]
|
|
6843
7009
|
};
|
|
6844
|
-
var SAFE_STRING_PROPS = /* @__PURE__ */ new Set(["message", "stack", "name"]);
|
|
6845
|
-
var PAYLOAD_PROPS = /* @__PURE__ */ new Set([
|
|
6846
|
-
"data",
|
|
6847
|
-
"status",
|
|
6848
|
-
"statuscode",
|
|
6849
|
-
"statustext",
|
|
6850
|
-
"code",
|
|
6851
|
-
"issues",
|
|
6852
|
-
"details",
|
|
6853
|
-
"body",
|
|
6854
|
-
"payload",
|
|
6855
|
-
"response",
|
|
6856
|
-
"info",
|
|
6857
|
-
"meta",
|
|
6858
|
-
"metadata",
|
|
6859
|
-
"context"
|
|
6860
|
-
]);
|
|
6861
7010
|
var BUILTIN_ERROR_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
6862
7011
|
"AggregateError",
|
|
6863
7012
|
"Error",
|
|
@@ -6868,14 +7017,200 @@ var BUILTIN_ERROR_CONSTRUCTORS = /* @__PURE__ */ new Set([
|
|
|
6868
7017
|
"TypeError",
|
|
6869
7018
|
"URIError"
|
|
6870
7019
|
]);
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
const
|
|
6875
|
-
if (
|
|
6876
|
-
if (
|
|
6877
|
-
|
|
6878
|
-
|
|
7020
|
+
var TRACKED_BUILTINS = /* @__PURE__ */ new Set([...BUILTIN_ERROR_CONSTRUCTORS, "JSON", "JSON.stringify"]);
|
|
7021
|
+
function nativeObjectName(expression, sourceCode) {
|
|
7022
|
+
const value = unwrapExpression(expression);
|
|
7023
|
+
const scope = sourceCode.getScope(value);
|
|
7024
|
+
if (value.type === "Identifier" && (value.name === "globalThis" || value.name === "JSON") && isGlobalIdentifier(value.name, scope)) return value.name;
|
|
7025
|
+
if (value.type === "MemberExpression" && nativeObjectName(value.object, sourceCode) === "globalThis" && staticPropertyName(value, sourceCode) === "JSON") return "JSON";
|
|
7026
|
+
return null;
|
|
7027
|
+
}
|
|
7028
|
+
function globalBuiltinName(expression, sourceCode) {
|
|
7029
|
+
const value = unwrapExpression(expression);
|
|
7030
|
+
const scope = sourceCode.getScope(value);
|
|
7031
|
+
if (value.type === "Identifier") return TRACKED_BUILTINS.has(value.name) && isGlobalIdentifier(value.name, scope) ? value.name : null;
|
|
7032
|
+
if (value.type !== "MemberExpression") return null;
|
|
7033
|
+
const receiver = nativeObjectName(value.object, sourceCode);
|
|
7034
|
+
const name = staticPropertyName(value, sourceCode);
|
|
7035
|
+
if (receiver === "JSON") return name === "stringify" ? "JSON.stringify" : null;
|
|
7036
|
+
return receiver === "globalThis" && name !== null && name !== "JSON.stringify" && TRACKED_BUILTINS.has(name) ? name : null;
|
|
7037
|
+
}
|
|
7038
|
+
function writePreservesBuiltin(target, sourceCode) {
|
|
7039
|
+
const assignment = target.parent;
|
|
7040
|
+
if (assignment?.type !== "AssignmentExpression" || assignment.left !== target) return false;
|
|
7041
|
+
const name = globalBuiltinName(target, sourceCode);
|
|
7042
|
+
if (name === null) return false;
|
|
7043
|
+
if (assignment.operator === "||=" || assignment.operator === "??=") return true;
|
|
7044
|
+
return (assignment.operator === "=" || assignment.operator === "&&=") && globalBuiltinName(assignment.right, sourceCode) === name;
|
|
7045
|
+
}
|
|
7046
|
+
function mayBeCallable(value) {
|
|
7047
|
+
return !["Literal", "TemplateLiteral", "ObjectExpression", "ArrayExpression"].includes(value.type);
|
|
7048
|
+
}
|
|
7049
|
+
var BUILTIN_WRITES = /* @__PURE__ */ new WeakMap();
|
|
7050
|
+
function directProgramStatement(node) {
|
|
7051
|
+
let current = node;
|
|
7052
|
+
while (current.parent !== void 0) {
|
|
7053
|
+
if (current.parent.type === "Program") return current;
|
|
7054
|
+
if (["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression", "ClassBody", "StaticBlock", "ForStatement", "ForInStatement", "ForOfStatement", "WhileStatement", "DoWhileStatement"].includes(current.parent.type)) return null;
|
|
7055
|
+
current = current.parent;
|
|
7056
|
+
}
|
|
7057
|
+
return null;
|
|
7058
|
+
}
|
|
7059
|
+
function hasUnchangedBuiltin(name, read, sourceCode) {
|
|
7060
|
+
const summary = builtinWrites(sourceCode).get(name);
|
|
7061
|
+
if (summary === void 0) return true;
|
|
7062
|
+
const statement = directProgramStatement(read);
|
|
7063
|
+
return !summary.unknownOrder && statement !== null && statement.range[1] <= summary.earliestStatementStart;
|
|
7064
|
+
}
|
|
7065
|
+
function builtinWrites(sourceCode) {
|
|
7066
|
+
const cached = BUILTIN_WRITES.get(sourceCode);
|
|
7067
|
+
if (cached !== void 0) return cached;
|
|
7068
|
+
const writes = /* @__PURE__ */ new Map();
|
|
7069
|
+
const record = (name, node) => {
|
|
7070
|
+
const statement = directProgramStatement(node);
|
|
7071
|
+
const existing = writes.get(name);
|
|
7072
|
+
writes.set(name, { earliestStatementStart: Math.min(existing?.earliestStatementStart ?? Infinity, statement?.range[0] ?? Infinity), unknownOrder: (existing?.unknownOrder ?? false) || statement === null });
|
|
7073
|
+
};
|
|
7074
|
+
for (const scope of sourceCode.scopeManager?.scopes ?? []) {
|
|
7075
|
+
for (const reference of scope.references) {
|
|
7076
|
+
const name = reference.identifier.name;
|
|
7077
|
+
if (reference.identifier.type === "Identifier" && reference.isWrite() && TRACKED_BUILTINS.has(name) && (reference.resolved === null || reference.resolved.defs.length === 0) && !writePreservesBuiltin(reference.identifier, sourceCode)) record(name, reference.identifier);
|
|
7078
|
+
}
|
|
7079
|
+
}
|
|
7080
|
+
const propertyReceiver = (expression) => {
|
|
7081
|
+
const native = nativeObjectName(expression, sourceCode);
|
|
7082
|
+
if (native !== null) return native;
|
|
7083
|
+
const value = unwrapExpression(expression);
|
|
7084
|
+
if (value.type === "Identifier") return import_utils41.ASTUtils.findVariable(sourceCode.getScope(value), value.name);
|
|
7085
|
+
if (value.type === "MemberExpression" && staticPropertyName(value, sourceCode) === "prototype") {
|
|
7086
|
+
const constructor = globalBuiltinName(value.object, sourceCode);
|
|
7087
|
+
if (constructor !== null && BUILTIN_ERROR_CONSTRUCTORS.has(constructor)) return constructor + ".prototype";
|
|
7088
|
+
}
|
|
7089
|
+
return null;
|
|
7090
|
+
};
|
|
7091
|
+
const propertyWrite = (receiver, name, node) => {
|
|
7092
|
+
if (receiver === "JSON") {
|
|
7093
|
+
if (name === null || name === "stringify") record("JSON.stringify", node);
|
|
7094
|
+
} else if (receiver === "globalThis") {
|
|
7095
|
+
if (name === null) {
|
|
7096
|
+
for (const builtin of TRACKED_BUILTINS) record(builtin, node);
|
|
7097
|
+
} else if (name !== "JSON.stringify" && TRACKED_BUILTINS.has(name)) record(name, node);
|
|
7098
|
+
} else if (name === null || name === "toJSON") record(receiver, node);
|
|
7099
|
+
};
|
|
7100
|
+
const visit = (node) => {
|
|
7101
|
+
if (node.type === "AssignmentExpression") propertyTarget(node.left);
|
|
7102
|
+
else if (node.type === "UpdateExpression") propertyTarget(node.argument);
|
|
7103
|
+
else if (node.type === "ForInStatement" || node.type === "ForOfStatement") propertyTarget(node.left);
|
|
7104
|
+
else if (node.type === "UnaryExpression" && node.operator === "delete") propertyTarget(node.argument);
|
|
7105
|
+
else if (node.type === "CallExpression") mutationCall(node);
|
|
7106
|
+
forEachAstChild(node, sourceCode.visitorKeys, visit);
|
|
7107
|
+
};
|
|
7108
|
+
function propertyTarget(target) {
|
|
7109
|
+
if (target.type === "MemberExpression") {
|
|
7110
|
+
memberPropertyWrite(target);
|
|
7111
|
+
return;
|
|
7112
|
+
}
|
|
7113
|
+
switch (target.type) {
|
|
7114
|
+
case "ObjectPattern":
|
|
7115
|
+
for (const property of target.properties) propertyTarget(property.type === "RestElement" ? property.argument : property.value);
|
|
7116
|
+
return;
|
|
7117
|
+
case "ArrayPattern":
|
|
7118
|
+
for (const element of target.elements) if (element !== null) propertyTarget(element);
|
|
7119
|
+
return;
|
|
7120
|
+
case "AssignmentPattern":
|
|
7121
|
+
propertyTarget(target.left);
|
|
7122
|
+
return;
|
|
7123
|
+
case "RestElement":
|
|
7124
|
+
propertyTarget(target.argument);
|
|
7125
|
+
}
|
|
7126
|
+
}
|
|
7127
|
+
function memberPropertyWrite(target) {
|
|
7128
|
+
const receiver = propertyReceiver(target.object);
|
|
7129
|
+
if (receiver === null || writePreservesBuiltin(target, sourceCode)) return;
|
|
7130
|
+
const name = staticPropertyName(target, sourceCode);
|
|
7131
|
+
if (name === "toJSON") {
|
|
7132
|
+
const assignment = target.parent;
|
|
7133
|
+
if (assignment?.type === "UnaryExpression" && assignment.operator === "delete") return;
|
|
7134
|
+
if (assignment?.type === "AssignmentExpression" && assignment.operator === "=" && !mayBeCallable(assignment.right)) return;
|
|
7135
|
+
}
|
|
7136
|
+
propertyWrite(receiver, name, target);
|
|
7137
|
+
}
|
|
7138
|
+
function mutationCall(node) {
|
|
7139
|
+
const callee = unwrapExpression(node.callee);
|
|
7140
|
+
if (callee.type !== "MemberExpression" || callee.object.type !== "Identifier") return;
|
|
7141
|
+
const owner = callee.object.name;
|
|
7142
|
+
if (!["Reflect", "Object"].includes(owner) || !isGlobalIdentifier(owner, sourceCode.getScope(callee))) return;
|
|
7143
|
+
const method = staticPropertyName(callee, sourceCode);
|
|
7144
|
+
const [target, key, value, receiver] = node.arguments;
|
|
7145
|
+
if (target === void 0 || target.type === "SpreadElement" || key === void 0) return;
|
|
7146
|
+
const object = propertyReceiver(target);
|
|
7147
|
+
if (object === null) return;
|
|
7148
|
+
switch (method) {
|
|
7149
|
+
case "set":
|
|
7150
|
+
if (owner === "Reflect") reflectSet(object, scopedStaticString(key, sourceCode), value, receiver, node);
|
|
7151
|
+
return;
|
|
7152
|
+
case "defineProperty":
|
|
7153
|
+
descriptorWrite(object, scopedStaticString(key, sourceCode), value, node);
|
|
7154
|
+
return;
|
|
7155
|
+
case "defineProperties":
|
|
7156
|
+
if (owner === "Object") descriptorBatch(object, key, node);
|
|
7157
|
+
}
|
|
7158
|
+
}
|
|
7159
|
+
function reflectSet(object, name, value, receiver, node) {
|
|
7160
|
+
if (receiver !== void 0 && receiver.type !== "SpreadElement" && ["ObjectExpression", "ArrayExpression", "Literal"].includes(unwrapExpression(receiver).type)) return;
|
|
7161
|
+
const builtin = builtinPropertyName(object, name);
|
|
7162
|
+
if (value !== void 0 && value.type !== "SpreadElement" && builtin !== null && globalBuiltinName(value, sourceCode) === builtin) return;
|
|
7163
|
+
if (name === "toJSON" && value !== void 0 && !mayBeCallable(value)) return;
|
|
7164
|
+
propertyWrite(object, name, node);
|
|
7165
|
+
}
|
|
7166
|
+
function descriptorBatch(object, descriptors, node) {
|
|
7167
|
+
if (descriptors.type !== "ObjectExpression") {
|
|
7168
|
+
propertyWrite(object, null, node);
|
|
7169
|
+
return;
|
|
7170
|
+
}
|
|
7171
|
+
for (const property of descriptors.properties) {
|
|
7172
|
+
if (property.type !== "Property") {
|
|
7173
|
+
propertyWrite(object, null, node);
|
|
7174
|
+
continue;
|
|
7175
|
+
}
|
|
7176
|
+
descriptorWrite(object, staticPropertyName(property, sourceCode), property.value, node);
|
|
7177
|
+
}
|
|
7178
|
+
}
|
|
7179
|
+
function descriptorWrite(object, name, descriptor, node) {
|
|
7180
|
+
if (descriptor !== void 0 && !descriptorChangesValue(descriptor, builtinPropertyName(object, name))) return;
|
|
7181
|
+
propertyWrite(object, name, node);
|
|
7182
|
+
}
|
|
7183
|
+
function descriptorChangesValue(descriptor, name) {
|
|
7184
|
+
if (descriptor.type !== "ObjectExpression") return true;
|
|
7185
|
+
return descriptor.properties.some((property) => {
|
|
7186
|
+
if (property.type !== "Property") return true;
|
|
7187
|
+
const key = staticPropertyName(property, sourceCode);
|
|
7188
|
+
if (key === "value" && name === "toJSON" && !mayBeCallable(property.value)) return false;
|
|
7189
|
+
if (key === "value" && property.value.type !== "AssignmentPattern" && property.value.type !== "ArrayPattern" && property.value.type !== "ObjectPattern" && property.value.type !== "TSEmptyBodyFunctionExpression") return name === null || globalBuiltinName(property.value, sourceCode) !== name;
|
|
7190
|
+
return key === null || key === "get" || key === "set";
|
|
7191
|
+
});
|
|
7192
|
+
}
|
|
7193
|
+
function builtinPropertyName(object, name) {
|
|
7194
|
+
return object === "JSON" && name === "stringify" ? "JSON.stringify" : name;
|
|
7195
|
+
}
|
|
7196
|
+
visit(sourceCode.ast);
|
|
7197
|
+
BUILTIN_WRITES.set(sourceCode, writes);
|
|
7198
|
+
return writes;
|
|
7199
|
+
}
|
|
7200
|
+
function hasDefaultErrorSerialization(expression, call, sourceCode) {
|
|
7201
|
+
let constructor = null;
|
|
7202
|
+
if (expression.type === "Identifier") {
|
|
7203
|
+
const variable = import_utils41.ASTUtils.findVariable(sourceCode.getScope(expression), expression.name);
|
|
7204
|
+
if (variable !== null && !hasUnchangedBuiltin(variable, call, sourceCode)) return false;
|
|
7205
|
+
const definition = variable?.defs[0];
|
|
7206
|
+
const initializer = definition?.type === "Variable" ? definition.node.init : null;
|
|
7207
|
+
if (initializer?.type === "NewExpression" && initializer.callee.type === "Identifier") constructor = initializer.callee.name;
|
|
7208
|
+
} else if (expression.type === "NewExpression" && expression.callee.type === "Identifier") constructor = expression.callee.name;
|
|
7209
|
+
const families = constructor === null ? BUILTIN_ERROR_CONSTRUCTORS : ["Error", constructor];
|
|
7210
|
+
return [...families].every((name) => hasUnchangedBuiltin(name + ".prototype", call, sourceCode));
|
|
7211
|
+
}
|
|
7212
|
+
function isBuiltinErrorConstructor(identifier, sourceCode) {
|
|
7213
|
+
return sourceCode.scopeManager !== null && BUILTIN_ERROR_CONSTRUCTORS.has(identifier.name) && isGlobalIdentifier(identifier.name, sourceCode.getScope(identifier)) && hasUnchangedBuiltin(identifier.name, identifier, sourceCode);
|
|
6879
7214
|
}
|
|
6880
7215
|
function isGlobalIdentifier(name, scope) {
|
|
6881
7216
|
const binding = import_utils41.ASTUtils.findVariable(scope, name);
|
|
@@ -6886,7 +7221,7 @@ function positiveErrorSubject(test, sourceCode) {
|
|
|
6886
7221
|
}
|
|
6887
7222
|
var TYPE_GUARD_PATTERN = /^(is|has)[A-Z]/;
|
|
6888
7223
|
function instanceofErrorSubject(test, sourceCode) {
|
|
6889
|
-
if (test.type === "BinaryExpression" && test.operator === "instanceof" && test.right.type === "Identifier" && test.right.name === "Error" &&
|
|
7224
|
+
if (test.type === "BinaryExpression" && test.operator === "instanceof" && test.right.type === "Identifier" && test.right.name === "Error" && isBuiltinErrorConstructor(test.right, sourceCode)) {
|
|
6890
7225
|
return test.left;
|
|
6891
7226
|
}
|
|
6892
7227
|
return null;
|
|
@@ -6954,16 +7289,17 @@ function sameSubjectBinding(subject, value, sourceCode) {
|
|
|
6954
7289
|
function nodeWithin(node, container) {
|
|
6955
7290
|
return container !== null && node.range[0] >= container.range[0] && node.range[1] <= container.range[1];
|
|
6956
7291
|
}
|
|
6957
|
-
function isJsonStringify(callee) {
|
|
7292
|
+
function isJsonStringify(callee, sourceCode) {
|
|
6958
7293
|
if (callee.type !== "MemberExpression") return false;
|
|
6959
7294
|
const receiver = unwrapExpression(callee.object);
|
|
6960
|
-
return callee.type === "MemberExpression" && receiver.type === "Identifier" && receiver.name === "JSON" &&
|
|
7295
|
+
return callee.type === "MemberExpression" && receiver.type === "Identifier" && receiver.name === "JSON" && staticPropertyName(callee, sourceCode) === "stringify";
|
|
6961
7296
|
}
|
|
6962
|
-
function directLiteralValues(argument) {
|
|
7297
|
+
function directLiteralValues(argument, sourceCode) {
|
|
6963
7298
|
argument = unwrapExpression(argument);
|
|
6964
7299
|
if (argument.type === "ObjectExpression") {
|
|
7300
|
+
if (literalHasSerializer(argument, sourceCode)) return [];
|
|
6965
7301
|
return argument.properties.flatMap((property) => {
|
|
6966
|
-
if (property.type !== "Property" ||
|
|
7302
|
+
if (property.type !== "Property" || staticPropertyName(property, sourceCode) === null) return [];
|
|
6967
7303
|
const value = property.value;
|
|
6968
7304
|
if (value.type === "AssignmentPattern" || value.type === "ArrayPattern" || value.type === "ObjectPattern" || value.type === "TSEmptyBodyFunctionExpression") {
|
|
6969
7305
|
return [];
|
|
@@ -6978,6 +7314,20 @@ function directLiteralValues(argument) {
|
|
|
6978
7314
|
}
|
|
6979
7315
|
return argument.type === "SpreadElement" ? [] : [argument];
|
|
6980
7316
|
}
|
|
7317
|
+
function literalHasSerializer(argument, sourceCode) {
|
|
7318
|
+
for (const property of argument.properties.toReversed()) {
|
|
7319
|
+
if (property.type !== "Property") return true;
|
|
7320
|
+
const key = staticPropertyName(property, sourceCode);
|
|
7321
|
+
if (key === null) return true;
|
|
7322
|
+
if (key === "toJSON") return mayBeCallable(property.value);
|
|
7323
|
+
}
|
|
7324
|
+
for (const property of argument.properties) {
|
|
7325
|
+
if (property.type !== "Property" || property.computed || property.method || property.shorthand || property.kind !== "init" || staticPropertyName(property, sourceCode) !== "__proto__") continue;
|
|
7326
|
+
const prototype = property.value;
|
|
7327
|
+
return prototype.type === "ObjectExpression" ? literalHasSerializer(prototype, sourceCode) : prototype.type !== "Literal" || "regex" in prototype && prototype.regex !== void 0;
|
|
7328
|
+
}
|
|
7329
|
+
return false;
|
|
7330
|
+
}
|
|
6981
7331
|
function expressionSuggestsError(expression, sourceCode) {
|
|
6982
7332
|
expression = unwrapExpression(expression);
|
|
6983
7333
|
const unwrappedExpressionCallee = expression.type === "CallExpression" || expression.type === "NewExpression" ? unwrapExpression(expression.callee) : null;
|
|
@@ -6985,23 +7335,19 @@ function expressionSuggestsError(expression, sourceCode) {
|
|
|
6985
7335
|
return identifierIsProvenError(expression, sourceCode);
|
|
6986
7336
|
}
|
|
6987
7337
|
if (expression.type === "NewExpression" && unwrappedExpressionCallee?.type === "Identifier") {
|
|
6988
|
-
return
|
|
6989
|
-
}
|
|
6990
|
-
return expression.type === "MemberExpression" && memberSuggestsError(expression, sourceCode);
|
|
6991
|
-
}
|
|
6992
|
-
function memberSuggestsError(member, sourceCode) {
|
|
6993
|
-
const propName2 = import_utils41.ASTUtils.getPropertyName(member);
|
|
6994
|
-
const base = member.object;
|
|
6995
|
-
const baseSuggestsError = base.type === "Identifier" && identifierIsProvenError(base, sourceCode);
|
|
6996
|
-
if (baseSuggestsError) {
|
|
6997
|
-
if (propName2 === null) {
|
|
6998
|
-
return true;
|
|
6999
|
-
}
|
|
7000
|
-
const lowered = propName2.toLowerCase();
|
|
7001
|
-
return !SAFE_STRING_PROPS.has(lowered) && !PAYLOAD_PROPS.has(lowered);
|
|
7338
|
+
return isBuiltinErrorConstructor(unwrappedExpressionCallee, sourceCode);
|
|
7002
7339
|
}
|
|
7003
7340
|
return false;
|
|
7004
7341
|
}
|
|
7342
|
+
function identifierIsProvenError(identifier, sourceCode) {
|
|
7343
|
+
const variable = import_utils41.ASTUtils.findVariable(sourceCode.getScope(identifier), identifier.name);
|
|
7344
|
+
if (variable === null || variable.defs.length !== 1 || variable.references.some((reference) => reference.isWrite() && reference.init !== true)) return false;
|
|
7345
|
+
const definition = variable.defs[0];
|
|
7346
|
+
if (definition?.type === "CatchClause") return true;
|
|
7347
|
+
if (definition?.type !== "Variable") return false;
|
|
7348
|
+
const initializer = definition.node.init;
|
|
7349
|
+
return initializer?.type === "NewExpression" && initializer.callee.type === "Identifier" && isBuiltinErrorConstructor(initializer.callee, sourceCode);
|
|
7350
|
+
}
|
|
7005
7351
|
var no_json_stringify_error_default = createRule({
|
|
7006
7352
|
name: "no-json-stringify-error",
|
|
7007
7353
|
documentation: NO_JSON_STRINGIFY_ERROR_DOCUMENTATION,
|
|
@@ -7020,7 +7366,7 @@ var no_json_stringify_error_default = createRule({
|
|
|
7020
7366
|
return {
|
|
7021
7367
|
CallExpression(node) {
|
|
7022
7368
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
7023
|
-
if (!isJsonStringify(unwrappedNodeCallee)) {
|
|
7369
|
+
if (!isJsonStringify(unwrappedNodeCallee, context.sourceCode)) {
|
|
7024
7370
|
return;
|
|
7025
7371
|
}
|
|
7026
7372
|
const firstArg = node.arguments[0];
|
|
@@ -7028,11 +7374,11 @@ var no_json_stringify_error_default = createRule({
|
|
|
7028
7374
|
return;
|
|
7029
7375
|
}
|
|
7030
7376
|
const scope = context.sourceCode.getScope(firstArg);
|
|
7031
|
-
if (!isGlobalIdentifier("JSON", scope)) return;
|
|
7377
|
+
if (!isGlobalIdentifier("JSON", scope) || !hasUnchangedBuiltin("JSON", node, context.sourceCode) || !hasUnchangedBuiltin("JSON.stringify", node, context.sourceCode)) return;
|
|
7032
7378
|
const replacer = node.arguments[1] === void 0 ? void 0 : unwrapExpression(node.arguments[1]);
|
|
7033
7379
|
if (replacer !== void 0 && !(replacer.type === "Literal" && replacer.value === null) && !(replacer.type === "Identifier" && replacer.name === "undefined" && isGlobalIdentifier("undefined", scope))) return;
|
|
7034
|
-
const unsafeValue = directLiteralValues(firstArg).find(
|
|
7035
|
-
(value) => expressionSuggestsError(value, context.sourceCode) && !isGuardedByInstanceofError(node, value, context.sourceCode) && !isNarrowedByEarlyReturn(node, value, context.sourceCode)
|
|
7380
|
+
const unsafeValue = directLiteralValues(firstArg, context.sourceCode).find(
|
|
7381
|
+
(value) => expressionSuggestsError(value, context.sourceCode) && hasDefaultErrorSerialization(unwrapExpression(value), node, context.sourceCode) && !isGuardedByInstanceofError(node, value, context.sourceCode) && !isNarrowedByEarlyReturn(node, value, context.sourceCode)
|
|
7036
7382
|
);
|
|
7037
7383
|
if (unsafeValue === void 0) {
|
|
7038
7384
|
return;
|
|
@@ -11506,10 +11852,12 @@ var NO_SILENT_PROMISE_CATCH_DOCUMENTATION = {
|
|
|
11506
11852
|
rationale: "A swallowed rejection hides failures and gives callers an indistinguishable fallback value.",
|
|
11507
11853
|
remediation: "Log, rethrow, or explicitly recover from the rejection; explain intentional teardown suppression.",
|
|
11508
11854
|
category: "correctness",
|
|
11509
|
-
limitations: ["Test files, teardown calls, explanatory comments, non-function handlers, and handlers that consume or report the error are excluded.", "Recognized imported Zod construction chains and their stable local aliases are excluded. Other untyped catch-like APIs are not proven to be Promises."],
|
|
11855
|
+
limitations: ["Test files, teardown calls, explanatory comments, non-function handlers, and handlers that consume or report the error are excluded.", "Recognized imported Zod construction chains and their stable local aliases are excluded. Other untyped catch-like APIs are not proven to be Promises.", "Computed methods resolve literal syntax and stable local string aliases in lexical scope. Function-derived, object-derived and mutated computed keys remain unproven."],
|
|
11510
11856
|
examples: [
|
|
11511
11857
|
{ id: "reported-rejection", title: "Report the rejection", outcome: "no-match", files: [{ path: "src/load.ts", source: "load().catch((error) => logger.error({ error }, 'load failed'));" }], focusPath: "src/load.ts", expectedCount: 0, public: true },
|
|
11512
|
-
{ id: "silent-rejection", title: "Do not swallow the rejection", outcome: "match", files: [{ path: "src/load.ts", source: "load().catch(() => null);" }], focusPath: "src/load.ts", expectedCount: 1, public: true }
|
|
11858
|
+
{ id: "silent-rejection", title: "Do not swallow the rejection", outcome: "match", files: [{ path: "src/load.ts", source: "load().catch(() => null);" }], focusPath: "src/load.ts", expectedCount: 1, public: true },
|
|
11859
|
+
{ id: "stable-computed-catch", scenarioId: "computed-method-scope", title: "Report a rejection through a stable computed method", outcome: "match", files: [{ path: "src/load.ts", source: "const method = 'catch'; Promise.reject(new Error('lost'))[method](() => null);" }], focusPath: "src/load.ts", expectedCount: 1, public: true },
|
|
11860
|
+
{ id: "stable-computed-body-parser", scenarioId: "computed-method-scope", title: "Preserve a recognized optional body parse fallback", outcome: "no-match", files: [{ path: "src/load.ts", source: "const method = 'json'; new Response('')[method]().catch(() => null);" }], focusPath: "src/load.ts", expectedCount: 0, public: true }
|
|
11513
11861
|
]
|
|
11514
11862
|
};
|
|
11515
11863
|
var BODY_PARSE_METHODS = /* @__PURE__ */ new Set([
|
|
@@ -11557,9 +11905,11 @@ var ZOD_CHAIN_METHODS = /* @__PURE__ */ new Set([
|
|
|
11557
11905
|
"superRefine",
|
|
11558
11906
|
"transform"
|
|
11559
11907
|
]);
|
|
11560
|
-
function isBodyParseCall(node) {
|
|
11908
|
+
function isBodyParseCall(node, sourceCode) {
|
|
11561
11909
|
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
11562
|
-
|
|
11910
|
+
if (node.type !== import_utils68.AST_NODE_TYPES.CallExpression || node.arguments.length !== 0 || unwrappedNodeCallee?.type !== import_utils68.AST_NODE_TYPES.MemberExpression) return false;
|
|
11911
|
+
const method = staticPropertyName(unwrappedNodeCallee, sourceCode);
|
|
11912
|
+
return method !== null && BODY_PARSE_METHODS.has(method);
|
|
11563
11913
|
}
|
|
11564
11914
|
var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
|
|
11565
11915
|
"cancel",
|
|
@@ -11573,13 +11923,15 @@ var TEARDOWN_METHODS = /* @__PURE__ */ new Set([
|
|
|
11573
11923
|
]);
|
|
11574
11924
|
var DIRECTIVE_COMMENT_RE = /^\s*(eslint-|@ts-|prettier-ignore|biome-ignore|c8 |v8 |istanbul )/;
|
|
11575
11925
|
var isExplanatory = (comment) => !DIRECTIVE_COMMENT_RE.test(comment.value);
|
|
11576
|
-
function isTeardownCall(node) {
|
|
11926
|
+
function isTeardownCall(node, sourceCode) {
|
|
11577
11927
|
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
11578
|
-
|
|
11928
|
+
if (node.type !== import_utils68.AST_NODE_TYPES.CallExpression || unwrappedNodeCallee?.type !== import_utils68.AST_NODE_TYPES.MemberExpression) return false;
|
|
11929
|
+
const method = staticPropertyName(unwrappedNodeCallee, sourceCode);
|
|
11930
|
+
return method !== null && TEARDOWN_METHODS.has(method);
|
|
11579
11931
|
}
|
|
11580
|
-
function isCancelledWebShare(node) {
|
|
11932
|
+
function isCancelledWebShare(node, sourceCode) {
|
|
11581
11933
|
const unwrappedNodeCallee = node.type === "CallExpression" || node.type === "NewExpression" ? unwrapExpression(node.callee) : null;
|
|
11582
|
-
return node.type === import_utils68.AST_NODE_TYPES.CallExpression && unwrappedNodeCallee?.type === import_utils68.AST_NODE_TYPES.MemberExpression && unwrappedNodeCallee.object.type === import_utils68.AST_NODE_TYPES.Identifier && unwrappedNodeCallee.object.name === "navigator" &&
|
|
11934
|
+
return node.type === import_utils68.AST_NODE_TYPES.CallExpression && unwrappedNodeCallee?.type === import_utils68.AST_NODE_TYPES.MemberExpression && unwrappedNodeCallee.object.type === import_utils68.AST_NODE_TYPES.Identifier && unwrappedNodeCallee.object.name === "navigator" && staticPropertyName(unwrappedNodeCallee, sourceCode) === "share";
|
|
11583
11935
|
}
|
|
11584
11936
|
function isSilentHandler(handler) {
|
|
11585
11937
|
const body2 = handler.body;
|
|
@@ -11643,9 +11995,9 @@ var no_silent_promise_catch_default = createRule({
|
|
|
11643
11995
|
const [definition] = binding.defs;
|
|
11644
11996
|
return binding.defs.length === 1 && definition?.node.type === import_utils68.AST_NODE_TYPES.VariableDeclarator && definition.node.init !== null && isZodSchema(definition.node.init, seen);
|
|
11645
11997
|
}
|
|
11646
|
-
if (node.type !== import_utils68.AST_NODE_TYPES.CallExpression || unwrappedNodeCallee?.type !== import_utils68.AST_NODE_TYPES.MemberExpression
|
|
11998
|
+
if (node.type !== import_utils68.AST_NODE_TYPES.CallExpression || unwrappedNodeCallee?.type !== import_utils68.AST_NODE_TYPES.MemberExpression) return false;
|
|
11647
11999
|
const { object } = unwrappedNodeCallee;
|
|
11648
|
-
const method =
|
|
12000
|
+
const method = staticPropertyName(unwrappedNodeCallee, context.sourceCode);
|
|
11649
12001
|
if (object.type === import_utils68.AST_NODE_TYPES.Identifier && method !== null && ZOD_CONSTRUCTORS.has(method)) {
|
|
11650
12002
|
const binding = import_utils68.ASTUtils.findVariable(context.sourceCode.getScope(object), object.name);
|
|
11651
12003
|
if (binding?.defs.some((definition) => {
|
|
@@ -11674,23 +12026,23 @@ var no_silent_promise_catch_default = createRule({
|
|
|
11674
12026
|
return {
|
|
11675
12027
|
CallExpression(node) {
|
|
11676
12028
|
const unwrappedNodeCallee = unwrapExpression(node.callee);
|
|
11677
|
-
if (unwrappedNodeCallee.type !== import_utils68.AST_NODE_TYPES.MemberExpression
|
|
12029
|
+
if (unwrappedNodeCallee.type !== import_utils68.AST_NODE_TYPES.MemberExpression) {
|
|
11678
12030
|
return;
|
|
11679
12031
|
}
|
|
11680
|
-
const method =
|
|
12032
|
+
const method = staticPropertyName(unwrappedNodeCallee, context.sourceCode);
|
|
11681
12033
|
const handlerIndex = method === "catch" ? 0 : method === "then" ? 1 : null;
|
|
11682
12034
|
if (handlerIndex === null) return;
|
|
11683
12035
|
if (method === "catch" && isZodSchema(unwrappedNodeCallee.object)) return;
|
|
11684
|
-
if (isBodyParseCall(unwrappedNodeCallee.object)) {
|
|
12036
|
+
if (isBodyParseCall(unwrappedNodeCallee.object, context.sourceCode)) {
|
|
11685
12037
|
return;
|
|
11686
12038
|
}
|
|
11687
|
-
if (isTeardownCall(unwrappedNodeCallee.object)) {
|
|
12039
|
+
if (isTeardownCall(unwrappedNodeCallee.object, context.sourceCode)) {
|
|
11688
12040
|
return;
|
|
11689
12041
|
}
|
|
11690
|
-
if (isCancelledWebShare(unwrappedNodeCallee.object)) {
|
|
12042
|
+
if (isCancelledWebShare(unwrappedNodeCallee.object, context.sourceCode)) {
|
|
11691
12043
|
return;
|
|
11692
12044
|
}
|
|
11693
|
-
if (node.parent.type === import_utils68.AST_NODE_TYPES.MemberExpression && node.parent.object === node &&
|
|
12045
|
+
if (node.parent.type === import_utils68.AST_NODE_TYPES.MemberExpression && node.parent.object === node && staticPropertyName(node.parent, context.sourceCode) === "then") {
|
|
11694
12046
|
return;
|
|
11695
12047
|
}
|
|
11696
12048
|
const expectedArguments = method === "catch" ? 1 : 2;
|
|
@@ -22208,7 +22560,7 @@ var REQUIRE_USE_FORM_DEFAULT_VALUES_DOCUMENTATION = {
|
|
|
22208
22560
|
}
|
|
22209
22561
|
]
|
|
22210
22562
|
};
|
|
22211
|
-
function
|
|
22563
|
+
function staticPropertyName2(property) {
|
|
22212
22564
|
if (property.computed) return null;
|
|
22213
22565
|
if (property.key.type === import_utils122.AST_NODE_TYPES.Identifier) return property.key.name;
|
|
22214
22566
|
if (property.key.type === import_utils122.AST_NODE_TYPES.Literal && typeof property.key.value === "string") return property.key.value;
|
|
@@ -22257,7 +22609,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22257
22609
|
for (const property of node.properties) {
|
|
22258
22610
|
if (property.type === import_utils122.AST_NODE_TYPES.SpreadElement || property.computed) return "unknown";
|
|
22259
22611
|
if (property.type !== import_utils122.AST_NODE_TYPES.Property) continue;
|
|
22260
|
-
const name =
|
|
22612
|
+
const name = staticPropertyName2(property);
|
|
22261
22613
|
if (name === "defaultValues" || name === "values") initialization.set(name, !isDefinitelyUndefined(property.value));
|
|
22262
22614
|
}
|
|
22263
22615
|
return [...initialization.values()].some(Boolean) ? "initialized" : "uninitialized";
|
|
@@ -22283,7 +22635,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22283
22635
|
for (const property of node.properties) {
|
|
22284
22636
|
if (property.type === import_utils122.AST_NODE_TYPES.SpreadElement || property.computed) return false;
|
|
22285
22637
|
if (property.type !== import_utils122.AST_NODE_TYPES.Property) continue;
|
|
22286
|
-
const name =
|
|
22638
|
+
const name = staticPropertyName2(property);
|
|
22287
22639
|
if (name === "control") control = property.value;
|
|
22288
22640
|
if (name === "defaultValue") hasDefault = !isDefinitelyUndefined(property.value);
|
|
22289
22641
|
}
|
|
@@ -22299,7 +22651,7 @@ var require_use_form_default_values_default = createRule({
|
|
|
22299
22651
|
};
|
|
22300
22652
|
const trackDestructuredControl = (pattern) => {
|
|
22301
22653
|
for (const property of pattern.properties) {
|
|
22302
|
-
if (property.type !== import_utils122.AST_NODE_TYPES.Property ||
|
|
22654
|
+
if (property.type !== import_utils122.AST_NODE_TYPES.Property || staticPropertyName2(property) !== "control" || property.value.type !== import_utils122.AST_NODE_TYPES.Identifier) continue;
|
|
22303
22655
|
const variable = bindingOf(property.value);
|
|
22304
22656
|
if (variable !== null) uninitializedControls.add(variable);
|
|
22305
22657
|
}
|
|
@@ -24333,7 +24685,7 @@ var RULES = {
|
|
|
24333
24685
|
};
|
|
24334
24686
|
var meta = {
|
|
24335
24687
|
name: "@sarj/eslint-plugin",
|
|
24336
|
-
version:
|
|
24688
|
+
version: package_default.version
|
|
24337
24689
|
};
|
|
24338
24690
|
var APPLICATION_ONLY_RULES = [];
|
|
24339
24691
|
var LIBRARY_IMPORT_POLICY = ["error", {
|