Handle chained awaited fetch calls in require-fetch-try-catch - #47963
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
require-fetch-try-catch
|
Hey ✅ Single, focused change — extends the rule to detect member-chained awaited fetch calls ( ✅ Comprehensive test coverage — new test cases cover the flagged invalid pattern and the valid rejection-handled cases. ✅ Clear documentation — the PR body and README updates explain the rule logic, scope, and acceptance criteria. This PR is ready for review and merge. Well done! 🎉
|
There was a problem hiding this comment.
Pull request overview
Extends require-fetch-try-catch to detect chained awaited fetch calls while exempting handled rejections.
Changes:
- Traverses fetch member/call chains and detects rejection handlers.
- Adds chained-fetch rule tests.
- Documents the rule and supported forms.
Show a summary per file
| File | Description |
|---|---|
eslint-factory/src/rules/require-fetch-try-catch.ts |
Adds chained-fetch detection. |
eslint-factory/src/rules/require-fetch-try-catch.test.ts |
Tests chained promise behavior. |
eslint-factory/README.md |
Documents rule scope and examples. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 3/3 changed files
- Comments generated: 2
- Review effort level: Medium
| while (true) { | ||
| if (current.type === AST_NODE_TYPES.Super) return null; |
There was a problem hiding this comment.
Fixed in commit fix(require-fetch-try-catch): unwrap ChainExpression and validate rejection handler callability. The traversal loop now checks for AST_NODE_TYPES.ChainExpression and unwraps it to current.expression before continuing, so await fetch(url)?.then(ok) (and any other optional-chain form) is correctly walked back to the root fetch(...) call. Added await fetch(url)?.then(x => x.json()) as an invalid test case and await fetch(url)?.catch(handler) / await fetch(url)?.then(ok, onErr) as valid ones.
| if (methodName === "catch" && current.arguments.length >= 1) hasRejectionHandler = true; | ||
| if (methodName === "then" && current.arguments.length >= 2) hasRejectionHandler = true; |
There was a problem hiding this comment.
Fixed in the same commit. Added an isStaticallyNonCallable helper that returns true for null, undefined (identifier), any other literal, and spread elements. Both the .catch(arg) and .then(onFulfilled, onRejected) checks now gate on !isStaticallyNonCallable(arg), so .catch(null), .then(ok, null), .then(ok, undefined), and .then(ok, 0) are all flagged. Regression tests for each case added.
|
@copilot run pr-finisher skill |
…ection handler callability - Unwrap ChainExpression nodes in the traversal loop so optional chains like `await fetch(url)?.then(ok)` are correctly detected - Add isStaticallyNonCallable helper that returns true for null, undefined, other literals, and spread elements — Promise treats these as the default thrower rather than a real rejection handler - Apply isStaticallyNonCallable check to .catch() and .then(,) argument positions so .catch(null) and .then(ok, undefined) are flagged - Add regression tests for optional-chain and non-callable rejection cases Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
|
@copilot please run the Run: https://github.com/github/gh-aw/actions/runs/30155206984
|
|
🎉 This pull request is included in a new release. Release: |
require-fetch-try-catchonly recognizedawait fetch(...)when the awaited call target was the barefetchidentifier, so chained forms likeawait fetch(url).then(...)escaped detection. This change extends the rule to follow awaited fetch member chains while preserving the existing exemption for chains that already handle rejection.Rule logic
CallExpression/MemberExpressionchains to recover the rootfetch(...)call.fetch(...)as in scope, not just bareawait fetch(...)..catch(handler).then(onFulfilled, onRejected)try/catchexemption and localfetchshadowing behavior.Coverage added
await fetch(url).then(x => x.json())await fetch(url).catch(handler)await fetch(url).then(ok, onErr)try { await fetch(url).then(...) } catch {}Docs
require-fetch-try-catchto the eslint-factory rule index.await fetch(...).then()/.catch()/.<responseMethod>()escapes detection #47932