sourceverity 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +188 -0
  3. package/bin/sourceverity.js +12 -0
  4. package/dist/analysis/controlFlow.d.ts +10 -0
  5. package/dist/analysis/controlFlow.d.ts.map +1 -0
  6. package/dist/analysis/controlFlow.js +278 -0
  7. package/dist/analysis/controlFlow.js.map +1 -0
  8. package/dist/analysis/frameworks.d.ts +11 -0
  9. package/dist/analysis/frameworks.d.ts.map +1 -0
  10. package/dist/analysis/frameworks.js +189 -0
  11. package/dist/analysis/frameworks.js.map +1 -0
  12. package/dist/analysis/functions.d.ts +27 -0
  13. package/dist/analysis/functions.d.ts.map +1 -0
  14. package/dist/analysis/functions.js +628 -0
  15. package/dist/analysis/functions.js.map +1 -0
  16. package/dist/analysis/promiseFlow.d.ts +44 -0
  17. package/dist/analysis/promiseFlow.d.ts.map +1 -0
  18. package/dist/analysis/promiseFlow.js +261 -0
  19. package/dist/analysis/promiseFlow.js.map +1 -0
  20. package/dist/analysis/values.d.ts +24 -0
  21. package/dist/analysis/values.d.ts.map +1 -0
  22. package/dist/analysis/values.js +189 -0
  23. package/dist/analysis/values.js.map +1 -0
  24. package/dist/baseline/manager.d.ts +20 -0
  25. package/dist/baseline/manager.d.ts.map +1 -0
  26. package/dist/baseline/manager.js +77 -0
  27. package/dist/baseline/manager.js.map +1 -0
  28. package/dist/baseline/types.d.ts +20 -0
  29. package/dist/baseline/types.d.ts.map +1 -0
  30. package/dist/baseline/types.js +2 -0
  31. package/dist/baseline/types.js.map +1 -0
  32. package/dist/cli/args.d.ts +26 -0
  33. package/dist/cli/args.d.ts.map +1 -0
  34. package/dist/cli/args.js +126 -0
  35. package/dist/cli/args.js.map +1 -0
  36. package/dist/cli/exitCodes.d.ts +8 -0
  37. package/dist/cli/exitCodes.d.ts.map +1 -0
  38. package/dist/cli/exitCodes.js +7 -0
  39. package/dist/cli/exitCodes.js.map +1 -0
  40. package/dist/cli/help.d.ts +5 -0
  41. package/dist/cli/help.d.ts.map +1 -0
  42. package/dist/cli/help.js +46 -0
  43. package/dist/cli/help.js.map +1 -0
  44. package/dist/cli/main.d.ts +7 -0
  45. package/dist/cli/main.d.ts.map +1 -0
  46. package/dist/cli/main.js +156 -0
  47. package/dist/cli/main.js.map +1 -0
  48. package/dist/core/fingerprint.d.ts +18 -0
  49. package/dist/core/fingerprint.d.ts.map +1 -0
  50. package/dist/core/fingerprint.js +26 -0
  51. package/dist/core/fingerprint.js.map +1 -0
  52. package/dist/core/paths.d.ts +10 -0
  53. package/dist/core/paths.d.ts.map +1 -0
  54. package/dist/core/paths.js +30 -0
  55. package/dist/core/paths.js.map +1 -0
  56. package/dist/core/suppressions.d.ts +24 -0
  57. package/dist/core/suppressions.d.ts.map +1 -0
  58. package/dist/core/suppressions.js +100 -0
  59. package/dist/core/suppressions.js.map +1 -0
  60. package/dist/core/terminal.d.ts +18 -0
  61. package/dist/core/terminal.d.ts.map +1 -0
  62. package/dist/core/terminal.js +39 -0
  63. package/dist/core/terminal.js.map +1 -0
  64. package/dist/core/types.d.ts +119 -0
  65. package/dist/core/types.d.ts.map +1 -0
  66. package/dist/core/types.js +2 -0
  67. package/dist/core/types.js.map +1 -0
  68. package/dist/engine/context.d.ts +16 -0
  69. package/dist/engine/context.d.ts.map +1 -0
  70. package/dist/engine/context.js +57 -0
  71. package/dist/engine/context.js.map +1 -0
  72. package/dist/engine/registry.d.ts +26 -0
  73. package/dist/engine/registry.d.ts.map +1 -0
  74. package/dist/engine/registry.js +38 -0
  75. package/dist/engine/registry.js.map +1 -0
  76. package/dist/engine/runner.d.ts +14 -0
  77. package/dist/engine/runner.d.ts.map +1 -0
  78. package/dist/engine/runner.js +166 -0
  79. package/dist/engine/runner.js.map +1 -0
  80. package/dist/engine/symbols.d.ts +46 -0
  81. package/dist/engine/symbols.d.ts.map +1 -0
  82. package/dist/engine/symbols.js +278 -0
  83. package/dist/engine/symbols.js.map +1 -0
  84. package/dist/index.d.ts +20 -0
  85. package/dist/index.d.ts.map +1 -0
  86. package/dist/index.js +32 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/reporters/agent.d.ts +45 -0
  89. package/dist/reporters/agent.d.ts.map +1 -0
  90. package/dist/reporters/agent.js +40 -0
  91. package/dist/reporters/agent.js.map +1 -0
  92. package/dist/reporters/json.d.ts +6 -0
  93. package/dist/reporters/json.d.ts.map +1 -0
  94. package/dist/reporters/json.js +7 -0
  95. package/dist/reporters/json.js.map +1 -0
  96. package/dist/reporters/sarif.d.ts +6 -0
  97. package/dist/reporters/sarif.d.ts.map +1 -0
  98. package/dist/reporters/sarif.js +60 -0
  99. package/dist/reporters/sarif.js.map +1 -0
  100. package/dist/reporters/terminal.d.ts +10 -0
  101. package/dist/reporters/terminal.d.ts.map +1 -0
  102. package/dist/reporters/terminal.js +105 -0
  103. package/dist/reporters/terminal.js.map +1 -0
  104. package/dist/repository/detector.d.ts +6 -0
  105. package/dist/repository/detector.d.ts.map +1 -0
  106. package/dist/repository/detector.js +231 -0
  107. package/dist/repository/detector.js.map +1 -0
  108. package/dist/repository/fileFilter.d.ts +10 -0
  109. package/dist/repository/fileFilter.d.ts.map +1 -0
  110. package/dist/repository/fileFilter.js +78 -0
  111. package/dist/repository/fileFilter.js.map +1 -0
  112. package/dist/repository/git.d.ts +7 -0
  113. package/dist/repository/git.d.ts.map +1 -0
  114. package/dist/repository/git.js +53 -0
  115. package/dist/repository/git.js.map +1 -0
  116. package/dist/repository/tsLoader.d.ts +15 -0
  117. package/dist/repository/tsLoader.d.ts.map +1 -0
  118. package/dist/repository/tsLoader.js +27 -0
  119. package/dist/repository/tsLoader.js.map +1 -0
  120. package/dist/repository/types.d.ts +38 -0
  121. package/dist/repository/types.d.ts.map +1 -0
  122. package/dist/repository/types.js +2 -0
  123. package/dist/repository/types.js.map +1 -0
  124. package/dist/rules/async/asyncForeach.d.ts +3 -0
  125. package/dist/rules/async/asyncForeach.d.ts.map +1 -0
  126. package/dist/rules/async/asyncForeach.js +76 -0
  127. package/dist/rules/async/asyncForeach.js.map +1 -0
  128. package/dist/rules/async/floatingPromise.d.ts +3 -0
  129. package/dist/rules/async/floatingPromise.d.ts.map +1 -0
  130. package/dist/rules/async/floatingPromise.js +359 -0
  131. package/dist/rules/async/floatingPromise.js.map +1 -0
  132. package/dist/rules/browser/eventListenerCleanup.d.ts +3 -0
  133. package/dist/rules/browser/eventListenerCleanup.d.ts.map +1 -0
  134. package/dist/rules/browser/eventListenerCleanup.js +378 -0
  135. package/dist/rules/browser/eventListenerCleanup.js.map +1 -0
  136. package/dist/rules/browser/observerCleanup.d.ts +3 -0
  137. package/dist/rules/browser/observerCleanup.d.ts.map +1 -0
  138. package/dist/rules/browser/observerCleanup.js +184 -0
  139. package/dist/rules/browser/observerCleanup.js.map +1 -0
  140. package/dist/rules/browser/timerCleanup.d.ts +3 -0
  141. package/dist/rules/browser/timerCleanup.d.ts.map +1 -0
  142. package/dist/rules/browser/timerCleanup.js +115 -0
  143. package/dist/rules/browser/timerCleanup.js.map +1 -0
  144. package/dist/rules/index.d.ts +19 -0
  145. package/dist/rules/index.d.ts.map +1 -0
  146. package/dist/rules/index.js +41 -0
  147. package/dist/rules/index.js.map +1 -0
  148. package/dist/rules/network/fetchStatusUnchecked.d.ts +3 -0
  149. package/dist/rules/network/fetchStatusUnchecked.d.ts.map +1 -0
  150. package/dist/rules/network/fetchStatusUnchecked.js +96 -0
  151. package/dist/rules/network/fetchStatusUnchecked.js.map +1 -0
  152. package/dist/rules/react/asyncEffectCallback.d.ts +3 -0
  153. package/dist/rules/react/asyncEffectCallback.d.ts.map +1 -0
  154. package/dist/rules/react/asyncEffectCallback.js +62 -0
  155. package/dist/rules/react/asyncEffectCallback.js.map +1 -0
  156. package/dist/rules/react/derivedStateEffect.d.ts +3 -0
  157. package/dist/rules/react/derivedStateEffect.d.ts.map +1 -0
  158. package/dist/rules/react/derivedStateEffect.js +172 -0
  159. package/dist/rules/react/derivedStateEffect.js.map +1 -0
  160. package/dist/rules/react/missingEffectCleanup.d.ts +3 -0
  161. package/dist/rules/react/missingEffectCleanup.d.ts.map +1 -0
  162. package/dist/rules/react/missingEffectCleanup.js +86 -0
  163. package/dist/rules/react/missingEffectCleanup.js.map +1 -0
  164. package/dist/rules/typescript/nonNullAssertionRisk.d.ts +3 -0
  165. package/dist/rules/typescript/nonNullAssertionRisk.d.ts.map +1 -0
  166. package/dist/rules/typescript/nonNullAssertionRisk.js +65 -0
  167. package/dist/rules/typescript/nonNullAssertionRisk.js.map +1 -0
  168. package/dist/rules/typescript/uncheckedIndexAccess.d.ts +3 -0
  169. package/dist/rules/typescript/uncheckedIndexAccess.d.ts.map +1 -0
  170. package/dist/rules/typescript/uncheckedIndexAccess.js +79 -0
  171. package/dist/rules/typescript/uncheckedIndexAccess.js.map +1 -0
  172. package/dist/rules/typescript/unsafeUnvalidatedAssertion.d.ts +3 -0
  173. package/dist/rules/typescript/unsafeUnvalidatedAssertion.d.ts.map +1 -0
  174. package/dist/rules/typescript/unsafeUnvalidatedAssertion.js +94 -0
  175. package/dist/rules/typescript/unsafeUnvalidatedAssertion.js.map +1 -0
  176. package/dist/strictness/evaluator.d.ts +28 -0
  177. package/dist/strictness/evaluator.d.ts.map +1 -0
  178. package/dist/strictness/evaluator.js +141 -0
  179. package/dist/strictness/evaluator.js.map +1 -0
  180. package/dist/strictness/matrix.d.ts +8 -0
  181. package/dist/strictness/matrix.d.ts.map +1 -0
  182. package/dist/strictness/matrix.js +63 -0
  183. package/dist/strictness/matrix.js.map +1 -0
  184. package/dist/typescript/programManager.d.ts +18 -0
  185. package/dist/typescript/programManager.d.ts.map +1 -0
  186. package/dist/typescript/programManager.js +46 -0
  187. package/dist/typescript/programManager.js.map +1 -0
  188. package/dist/typescript/projectResolver.d.ts +17 -0
  189. package/dist/typescript/projectResolver.d.ts.map +1 -0
  190. package/dist/typescript/projectResolver.js +75 -0
  191. package/dist/typescript/projectResolver.js.map +1 -0
  192. package/package.json +56 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SourceVerity Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,188 @@
1
+ # SourceVerity
2
+
3
+ SourceVerity is a repository-aware frontend correctness and quality auditor for JavaScript, TypeScript, and React applications.
4
+
5
+ It identifies high-value correctness defects, resource leaks, async hazards, and hidden type-safety gaps that standard compilation, weak TypeScript configurations, or style linters do not reject.
6
+
7
+ ```bash
8
+ npx sourceverity scan .
9
+ ```
10
+
11
+ ---
12
+
13
+ ## Philosophy & Scope
14
+
15
+ SourceVerity operates on the principle: **Respect the repository. Audit beyond the repository.**
16
+
17
+ Many production codebases maintain loose TypeScript compiler options (such as `strictNullChecks: false` or `noUncheckedIndexedAccess: false`) for historical migration reasons. SourceVerity understands what your compiler accepts while independently determining whether runtime operations are genuinely safe.
18
+
19
+ ### What SourceVerity Detects
20
+ - **Async Hazards**: Unawaited callbacks in array iterations, floating/unhandled Promises, missing error rejection handling.
21
+ - **Hidden Type-Safety Gaps**: Unvalidated runtime data (`JSON.parse()`, `response.json()`) asserted directly to domain types, risky non-null assertions on nullable types, unsafe unchecked index accesses.
22
+ - **Browser Resource Leaks**: Missing or mismatched `addEventListener` cleanup in lifecycle scopes, uncleaned intervals (`setInterval`), un-disconnected DOM Observers (`ResizeObserver`, `MutationObserver`).
23
+ - **Network Misuse**: Unchecked HTTP response status prior to consuming response bodies.
24
+ - **React Lifecycle Deficiencies**: Direct async callbacks passed to `useEffect`, derived local state unnecessarily synchronized inside effects, uncleaned resource subscriptions.
25
+ - **TypeScript Strictness Migration Gaps**: Measurable evaluation of potential compiler diagnostics if strict compiler flags were enabled.
26
+
27
+ ### What SourceVerity Is Not
28
+ - Not a code formatter or style enforcer (not an alternative to Prettier or Biome formatting).
29
+ - Not a subjective opinion generator or naming linter.
30
+ - Not an LLM wrapper or AI reviewer (all diagnostics are computed deterministically via static AST and TypeScript semantic analysis).
31
+
32
+ ---
33
+
34
+ ## Installation & CLI Usage
35
+
36
+ Run SourceVerity directly using `npx`:
37
+
38
+ ```bash
39
+ # Audit the current repository
40
+ npx sourceverity scan .
41
+
42
+ # Run with custom failure threshold (error, warning, never)
43
+ npx sourceverity scan . --fail-on warning
44
+
45
+ # Report only high-confidence findings
46
+ npx sourceverity scan . --min-confidence high
47
+
48
+ # Analyze only git-changed files
49
+ npx sourceverity scan . --changed
50
+ ```
51
+
52
+ ### Output Formats
53
+
54
+ ```bash
55
+ # Default human-readable terminal format
56
+ npx sourceverity scan . --format pretty
57
+
58
+ # Deterministic JSON format
59
+ npx sourceverity scan . --format json
60
+
61
+ # Machine format tailored for LLMs and coding agents (e.g. Codex)
62
+ npx sourceverity scan . --format agent
63
+
64
+ # Standard SARIF 2.1.0 format for GitHub Code Scanning
65
+ npx sourceverity scan . --format sarif
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Using SourceVerity with Coding Agents
71
+
72
+ SourceVerity's `agent` format provides structured, deterministic diagnostics optimized for coding assistants like Codex.
73
+
74
+ Example prompt for a coding agent:
75
+
76
+ ```text
77
+ Run `npx sourceverity scan . --format agent`.
78
+ Review high-confidence correctness findings.
79
+ Fix verified correctness issues without modifying unrelated formatting or architecture.
80
+ Run the project's test suite to verify no regressions.
81
+ Run SourceVerity again to verify resolution.
82
+ ```
83
+
84
+ ---
85
+
86
+ ## TypeScript Strictness Gap Analysis
87
+
88
+ Inspect the safety gaps in your existing `tsconfig.json` and measure migration impact:
89
+
90
+ ```bash
91
+ npx sourceverity strictness .
92
+ ```
93
+
94
+ Example output:
95
+
96
+ ```text
97
+ TypeScript Strictness Gap Analysis
98
+
99
+ Current Configuration:
100
+ strict false
101
+ strictNullChecks false
102
+ noUncheckedIndexedAccess false
103
+ exactOptionalPropertyTypes false
104
+
105
+ Migration Impact (New Compiler Diagnostics):
106
+ strictNullChecks 42 diagnostics
107
+ noUncheckedIndexedAccess 18 diagnostics
108
+ exactOptionalPropertyTypes 4 diagnostics
109
+
110
+ Top Affected Files:
111
+ src/api/client.ts 12
112
+ src/state/user.ts 8
113
+ ```
114
+
115
+ ---
116
+
117
+ ## Baseline Management
118
+
119
+ When adopting SourceVerity on an existing codebase with existing findings, generate a baseline to track new regressions without blocking current work:
120
+
121
+ ```bash
122
+ # Create or update baseline
123
+ npx sourceverity baseline create
124
+
125
+ # Run scan checking only new findings against baseline
126
+ npx sourceverity scan . --baseline
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Suppressions
132
+
133
+ To suppress an intentional exception, use a line-level suppression comment with a required or strongly recommended explanation:
134
+
135
+ ```ts
136
+ // sourceverity-disable-next-line typescript/unsafe-unvalidated-assertion -- verified by upstream API gateway schema
137
+ const user = JSON.parse(payload) as User;
138
+ ```
139
+
140
+ ---
141
+
142
+ ## Initial Production Rule Set
143
+
144
+ | Rule ID | Category | Default Severity | Confidence | Description |
145
+ | ------- | -------- | ---------------- | ---------- | ----------- |
146
+ | `async/async-foreach` | Async | Error | High | Asynchronous callback passed to `Array.prototype.forEach`. |
147
+ | `async/floating-promise` | Async | Error | High | Unhandled Promise returned in statement position without handling or void operator. |
148
+ | `typescript/unsafe-unvalidated-assertion` | TypeScript | Error | High | Unvalidated runtime data (`JSON.parse`, `response.json()`) asserted directly to a type. |
149
+ | `typescript/non-null-assertion-risk` | TypeScript | Warning | High | Non-null assertion (`!`) on value whose semantic type contains null or undefined. |
150
+ | `typescript/unchecked-index-access` | TypeScript | Warning | Medium | Dynamic property or index access dereferenced without presence check in loose config. |
151
+ | `network/fetch-status-unchecked` | Network | Warning | High | Consuming `fetch()` response body without checking `response.ok` or `response.status`. |
152
+ | `browser/event-listener-cleanup` | Browser | Error | High | `addEventListener` registered in lifecycle scope without matching `removeEventListener`. |
153
+ | `browser/timer-cleanup` | Browser | Error | High | `setInterval` registered in lifecycle scope without corresponding `clearInterval`. |
154
+ | `browser/observer-cleanup` | Browser | Error | High | DOM Observer (`ResizeObserver`, etc.) created in lifecycle scope without `.disconnect()`. |
155
+ | `react/async-effect-callback` | React | Error | High | Async function passed directly as `useEffect` callback argument. |
156
+ | `react/derived-state-effect` | React | Warning | High | `useEffect` used exclusively to derive local state from render inputs. |
157
+ | `react/missing-effect-cleanup` | React | Warning | High | Subscriptions or event targets instantiated in `useEffect` without returned cleanup. |
158
+
159
+ ---
160
+
161
+ ## Programmatic API
162
+
163
+ SourceVerity exposes a TypeScript programmatic API for build tool and custom CI integrations:
164
+
165
+ ```ts
166
+ import { scanRepository } from "sourceverity";
167
+
168
+ const result = await scanRepository({
169
+ targetDir: process.cwd(),
170
+ minConfidence: "high",
171
+ });
172
+
173
+ console.log(`Found ${result.findings.length} findings across ${result.summary.filesAnalyzed} files.`);
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Requirements & Engines
179
+
180
+ - Node.js >= 20.12.0
181
+ - Supports npm, pnpm, Yarn, and Bun workspaces
182
+ - Analyzes TypeScript (using project's local TypeScript installation) and JavaScript
183
+
184
+ ---
185
+
186
+ ## License
187
+
188
+ MIT © 2026 SourceVerity Contributors
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { runCli } from "../dist/cli/main.js";
4
+
5
+ try {
6
+ const code = await runCli(process.argv.slice(2));
7
+ process.exitCode = code;
8
+ } catch (error) {
9
+ const message = error instanceof Error ? error.message : String(error);
10
+ process.stderr.write(`sourceverity: fatal error: ${message}\n`);
11
+ process.exitCode = 3;
12
+ }
@@ -0,0 +1,10 @@
1
+ import type * as tsType from "typescript";
2
+ export interface GuardCheckResult {
3
+ readonly isGuarded: boolean;
4
+ readonly evidence?: string | undefined;
5
+ }
6
+ /**
7
+ * Checks if a non-null assertion operand is guarded against null/undefined or out-of-bounds access.
8
+ */
9
+ export declare function isGuardedNonNullAssertion(node: tsType.NonNullExpression, ts: typeof tsType, checker?: tsType.TypeChecker | undefined): GuardCheckResult;
10
+ //# sourceMappingURL=controlFlow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controlFlow.d.ts","sourceRoot":"","sources":["../../src/analysis/controlFlow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,MAAM,YAAY,CAAC;AAG1C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACxC;AAmQD;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,MAAM,CAAC,iBAAiB,EAC9B,EAAE,EAAE,OAAO,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,WAAW,GAAG,SAAS,GACvC,gBAAgB,CAsGlB"}
@@ -0,0 +1,278 @@
1
+ import { unwrapExpression } from "./values.js";
2
+ /**
3
+ * Checks if a statement definitely exits control flow (return, throw, break, continue).
4
+ */
5
+ function statementExitsControlFlow(stmt, ts) {
6
+ if (ts.isReturnStatement(stmt) ||
7
+ ts.isThrowStatement(stmt) ||
8
+ ts.isBreakStatement(stmt) ||
9
+ ts.isContinueStatement(stmt)) {
10
+ return true;
11
+ }
12
+ if (ts.isBlock(stmt)) {
13
+ const stmts = stmt.statements;
14
+ if (stmts.length === 0)
15
+ return false;
16
+ const last = stmts[stmts.length - 1];
17
+ return last !== undefined && statementExitsControlFlow(last, ts);
18
+ }
19
+ return false;
20
+ }
21
+ function normalizeIndexExpression(expr, ts, checker) {
22
+ const unwrapped = unwrapExpression(expr, ts);
23
+ if (ts.isIdentifier(unwrapped)) {
24
+ const sym = checker?.getSymbolAtLocation(unwrapped);
25
+ return { baseText: unwrapped.text, baseSymbol: sym, offset: 0 };
26
+ }
27
+ if (ts.isBinaryExpression(unwrapped)) {
28
+ const left = unwrapExpression(unwrapped.left, ts);
29
+ const right = unwrapExpression(unwrapped.right, ts);
30
+ if (ts.isIdentifier(left) && ts.isNumericLiteral(right)) {
31
+ const num = Number(right.text);
32
+ if (!Number.isNaN(num)) {
33
+ const sym = checker?.getSymbolAtLocation(left);
34
+ if (unwrapped.operatorToken.kind === ts.SyntaxKind.PlusToken) {
35
+ return { baseText: left.text, baseSymbol: sym, offset: num };
36
+ }
37
+ if (unwrapped.operatorToken.kind === ts.SyntaxKind.MinusToken) {
38
+ return { baseText: left.text, baseSymbol: sym, offset: -num };
39
+ }
40
+ }
41
+ }
42
+ }
43
+ return undefined;
44
+ }
45
+ function normalizeArrayTarget(expr, ts, checker) {
46
+ const unwrapped = unwrapExpression(expr, ts);
47
+ if (ts.isIdentifier(unwrapped)) {
48
+ const sym = checker?.getSymbolAtLocation(unwrapped);
49
+ return { text: unwrapped.text, symbol: sym };
50
+ }
51
+ if (ts.isPropertyAccessExpression(unwrapped)) {
52
+ const sym = checker?.getSymbolAtLocation(unwrapped);
53
+ return { text: unwrapped.getText(), symbol: sym };
54
+ }
55
+ return undefined;
56
+ }
57
+ /**
58
+ * Checks if a binary condition expression guards an index lower bound (e.g. index === -1 or index < 0).
59
+ */
60
+ function isLowerBoundNegativeGuard(cond, indexInfo, ts) {
61
+ const unwrapped = unwrapExpression(cond, ts);
62
+ if (!ts.isBinaryExpression(unwrapped))
63
+ return false;
64
+ const left = unwrapExpression(unwrapped.left, ts);
65
+ const right = unwrapExpression(unwrapped.right, ts);
66
+ const op = unwrapped.operatorToken.kind;
67
+ // index === -1 or -1 === index
68
+ if (op === ts.SyntaxKind.EqualsEqualsToken || op === ts.SyntaxKind.EqualsEqualsEqualsToken) {
69
+ if (ts.isIdentifier(left) && left.text === indexInfo.baseText) {
70
+ if (ts.isPrefixUnaryExpression(right) && right.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(right.operand) && right.operand.text === "1") {
71
+ return true;
72
+ }
73
+ }
74
+ if (ts.isIdentifier(right) && right.text === indexInfo.baseText) {
75
+ if (ts.isPrefixUnaryExpression(left) && left.operator === ts.SyntaxKind.MinusToken && ts.isNumericLiteral(left.operand) && left.operand.text === "1") {
76
+ return true;
77
+ }
78
+ }
79
+ }
80
+ // index < 0
81
+ if (op === ts.SyntaxKind.LessThanToken) {
82
+ if (ts.isIdentifier(left) && left.text === indexInfo.baseText && ts.isNumericLiteral(right) && right.text === "0") {
83
+ return true;
84
+ }
85
+ }
86
+ // 0 > index
87
+ if (op === ts.SyntaxKind.GreaterThanToken) {
88
+ if (ts.isNumericLiteral(left) && left.text === "0" && ts.isIdentifier(right) && right.text === indexInfo.baseText) {
89
+ return true;
90
+ }
91
+ }
92
+ return false;
93
+ }
94
+ /**
95
+ * Checks if an expression represents `array.length` or `array.length - K`.
96
+ */
97
+ function parseArrayLengthOffset(expr, arrayInfo, ts) {
98
+ const unwrapped = unwrapExpression(expr, ts);
99
+ // array.length
100
+ if (ts.isPropertyAccessExpression(unwrapped) && unwrapped.name.text === "length") {
101
+ const obj = unwrapExpression(unwrapped.expression, ts);
102
+ if (ts.isIdentifier(obj) && obj.text === arrayInfo.text) {
103
+ return 0;
104
+ }
105
+ }
106
+ // array.length - K
107
+ if (ts.isBinaryExpression(unwrapped) && unwrapped.operatorToken.kind === ts.SyntaxKind.MinusToken) {
108
+ const left = unwrapExpression(unwrapped.left, ts);
109
+ const right = unwrapExpression(unwrapped.right, ts);
110
+ if (ts.isPropertyAccessExpression(left) && left.name.text === "length") {
111
+ const obj = unwrapExpression(left.expression, ts);
112
+ if (ts.isIdentifier(obj) && obj.text === arrayInfo.text && ts.isNumericLiteral(right)) {
113
+ const k = Number(right.text);
114
+ if (!Number.isNaN(k))
115
+ return k;
116
+ }
117
+ }
118
+ }
119
+ return undefined;
120
+ }
121
+ /**
122
+ * Checks if a binary condition expression guards an upper bound against array.length.
123
+ * e.g. `index >= array.length` or `index >= array.length - 1` or `index > array.length - 1`.
124
+ */
125
+ function isUpperBoundLengthGuard(cond, indexInfo, arrayInfo, ts) {
126
+ const unwrapped = unwrapExpression(cond, ts);
127
+ if (!ts.isBinaryExpression(unwrapped))
128
+ return { isGuard: false, maxAllowedOffset: 0 };
129
+ const left = unwrapExpression(unwrapped.left, ts);
130
+ const right = unwrapExpression(unwrapped.right, ts);
131
+ const op = unwrapped.operatorToken.kind;
132
+ // Pattern: `index >= [length expression]`
133
+ if (op === ts.SyntaxKind.GreaterThanEqualsToken && ts.isIdentifier(left) && left.text === indexInfo.baseText) {
134
+ const lengthMinus = parseArrayLengthOffset(right, arrayInfo, ts);
135
+ if (lengthMinus !== undefined) {
136
+ // index >= array.length - lengthMinus (exit)
137
+ // after exit: index < array.length - lengthMinus
138
+ // => index + offset < array.length is safe if offset <= lengthMinus - (lengthMinus === 0 ? 0 : 0) -> offset < lengthMinus + 1 => offset <= lengthMinus
139
+ // Specifically: if lengthMinus === 1 (index >= array.length - 1), then index < array.length - 1, so index + 1 < array.length (offset 1 is safe).
140
+ // If lengthMinus === 0 (index >= array.length), then index < array.length (offset 0 is safe).
141
+ return { isGuard: true, maxAllowedOffset: lengthMinus };
142
+ }
143
+ }
144
+ // Pattern: `index > [length expression]`
145
+ if (op === ts.SyntaxKind.GreaterThanToken && ts.isIdentifier(left) && left.text === indexInfo.baseText) {
146
+ const lengthMinus = parseArrayLengthOffset(right, arrayInfo, ts);
147
+ if (lengthMinus !== undefined) {
148
+ // index > array.length - 1 (exit) => index <= array.length - 1 => index < array.length (offset 0 safe)
149
+ return { isGuard: true, maxAllowedOffset: lengthMinus - 1 };
150
+ }
151
+ }
152
+ return { isGuard: false, maxAllowedOffset: 0 };
153
+ }
154
+ /**
155
+ * Checks if an exit condition contains both a lower-bound check and an upper-bound check.
156
+ */
157
+ function isCompleteBoundsExitGuard(cond, indexInfo, arrayInfo, ts) {
158
+ // Collect all OR disjuncts: A || B || C
159
+ const disjuncts = [];
160
+ function collectOrs(e) {
161
+ const u = unwrapExpression(e, ts);
162
+ if (ts.isBinaryExpression(u) && u.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
163
+ collectOrs(u.left);
164
+ collectOrs(u.right);
165
+ }
166
+ else {
167
+ disjuncts.push(u);
168
+ }
169
+ }
170
+ collectOrs(cond);
171
+ let hasLower = false;
172
+ let maxUpperOffset = -1;
173
+ for (const d of disjuncts) {
174
+ if (isLowerBoundNegativeGuard(d, indexInfo, ts)) {
175
+ hasLower = true;
176
+ }
177
+ const upper = isUpperBoundLengthGuard(d, indexInfo, arrayInfo, ts);
178
+ if (upper.isGuard) {
179
+ maxUpperOffset = Math.max(maxUpperOffset, upper.maxAllowedOffset);
180
+ }
181
+ }
182
+ if (hasLower && maxUpperOffset >= indexInfo.offset) {
183
+ return true;
184
+ }
185
+ return false;
186
+ }
187
+ /**
188
+ * Checks if a non-null assertion operand is guarded against null/undefined or out-of-bounds access.
189
+ */
190
+ export function isGuardedNonNullAssertion(node, ts, checker) {
191
+ const operand = unwrapExpression(node.expression, ts);
192
+ // Case 1: Indexed access non-null assertion: `array[index]!`
193
+ if (ts.isElementAccessExpression(operand)) {
194
+ const arrayInfo = normalizeArrayTarget(operand.expression, ts, checker);
195
+ const indexInfo = normalizeIndexExpression(operand.argumentExpression, ts, checker);
196
+ if (arrayInfo && indexInfo) {
197
+ // Find enclosing block / function containing the statement of this node
198
+ let stmt = node;
199
+ while (stmt.parent && !ts.isBlock(stmt.parent) && !ts.isSourceFile(stmt.parent)) {
200
+ stmt = stmt.parent;
201
+ }
202
+ if (stmt.parent && (ts.isBlock(stmt.parent) || ts.isSourceFile(stmt.parent))) {
203
+ const statements = ts.isBlock(stmt.parent) ? stmt.parent.statements : stmt.parent.statements;
204
+ const targetIndex = statements.indexOf(stmt);
205
+ if (targetIndex > 0) {
206
+ // Look at prior sibling statements
207
+ for (let i = 0; i < targetIndex; i++) {
208
+ const prior = statements[i];
209
+ if (!prior)
210
+ continue;
211
+ // Look for early-exit if guard: if (index === -1 || index >= array.length - 1) return null;
212
+ if (ts.isIfStatement(prior)) {
213
+ if (statementExitsControlFlow(prior.thenStatement, ts)) {
214
+ if (isCompleteBoundsExitGuard(prior.expression, indexInfo, arrayInfo, ts)) {
215
+ return {
216
+ isGuarded: true,
217
+ evidence: `Dominating guard '${prior.expression.getText()}' proves index '${indexInfo.baseText}${indexInfo.offset ? ` + ${indexInfo.offset}` : ""}' is strictly in-bounds for '${arrayInfo.text}'.`,
218
+ };
219
+ }
220
+ }
221
+ }
222
+ }
223
+ }
224
+ }
225
+ }
226
+ }
227
+ // Case 2: Direct variable / identifier non-null assertion: `target!`
228
+ if (ts.isIdentifier(operand)) {
229
+ const targetName = operand.text;
230
+ let stmt = node;
231
+ while (stmt.parent && !ts.isBlock(stmt.parent) && !ts.isSourceFile(stmt.parent)) {
232
+ stmt = stmt.parent;
233
+ }
234
+ if (stmt.parent && (ts.isBlock(stmt.parent) || ts.isSourceFile(stmt.parent))) {
235
+ const statements = ts.isBlock(stmt.parent) ? stmt.parent.statements : stmt.parent.statements;
236
+ const targetIndex = statements.indexOf(stmt);
237
+ if (targetIndex > 0) {
238
+ for (let i = 0; i < targetIndex; i++) {
239
+ const prior = statements[i];
240
+ if (!prior)
241
+ continue;
242
+ if (ts.isIfStatement(prior) && statementExitsControlFlow(prior.thenStatement, ts)) {
243
+ const cond = unwrapExpression(prior.expression, ts);
244
+ // if (!target) return;
245
+ if (ts.isPrefixUnaryExpression(cond) && cond.operator === ts.SyntaxKind.ExclamationToken) {
246
+ const inner = unwrapExpression(cond.operand, ts);
247
+ if (ts.isIdentifier(inner) && inner.text === targetName) {
248
+ return {
249
+ isGuarded: true,
250
+ evidence: `Dominating guard '!${targetName}' proves operand is non-null.`,
251
+ };
252
+ }
253
+ }
254
+ // if (target === null || target === undefined || target == null) return;
255
+ if (ts.isBinaryExpression(cond)) {
256
+ const left = unwrapExpression(cond.left, ts);
257
+ const right = unwrapExpression(cond.right, ts);
258
+ if ((ts.isIdentifier(left) && left.text === targetName) ||
259
+ (ts.isIdentifier(right) && right.text === targetName)) {
260
+ const other = ts.isIdentifier(left) && left.text === targetName ? right : left;
261
+ if (other.kind === ts.SyntaxKind.NullKeyword ||
262
+ other.kind === ts.SyntaxKind.UndefinedKeyword ||
263
+ (ts.isIdentifier(other) && other.text === "undefined")) {
264
+ return {
265
+ isGuarded: true,
266
+ evidence: `Dominating null check proves '${targetName}' is non-null.`,
267
+ };
268
+ }
269
+ }
270
+ }
271
+ }
272
+ }
273
+ }
274
+ }
275
+ }
276
+ return { isGuarded: false };
277
+ }
278
+ //# sourceMappingURL=controlFlow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controlFlow.js","sourceRoot":"","sources":["../../src/analysis/controlFlow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type * as tsType from "typescript";
2
+ export interface FrameworkHandlingResult {
3
+ readonly isHandled: boolean;
4
+ readonly isKnownRejecting?: boolean | undefined;
5
+ readonly reason?: string | undefined;
6
+ }
7
+ /**
8
+ * Evaluates whether a CallExpression represents a verified, handled framework API call.
9
+ */
10
+ export declare function evaluateFrameworkPromiseCall(callExpr: tsType.CallExpression, ts: typeof tsType, checker?: tsType.TypeChecker | undefined): FrameworkHandlingResult;
11
+ //# sourceMappingURL=frameworks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frameworks.d.ts","sourceRoot":"","sources":["../../src/analysis/frameworks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,MAAM,YAAY,CAAC;AAG1C,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAyDD;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,MAAM,CAAC,cAAc,EAC/B,EAAE,EAAE,OAAO,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,WAAW,GAAG,SAAS,GACvC,uBAAuB,CA4JzB"}