Skip to content

fix(async-await-in-loop): recognize local Promise.allSettled wrappers - #1842

Draft
skoshx wants to merge 4 commits into
mainfrom
cursor/triage-1839-2850
Draft

skoshx wants to merge 4 commits into
mainfrom
cursor/triage-1839-2850

Conversation

@skoshx

@skoshx skoshx commented Sep 26, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1839

Root Cause

The async-await-in-loop rule was reporting false positives when async .map() callbacks were passed to a local wrapper function around Promise.allSettled(), Promise.all(), or other promise concurrency methods.

The rule correctly identified that promises from .map() were being awaited, but it didn't recognize that those promises were passed to a local function that internally uses promise concurrency, meaning the operations were actually running in parallel.

Fix

Added detection for local functions that internally use promise concurrency methods (Promise.all, Promise.allSettled, Promise.race, Promise.any). When a mapped promise array is passed to such a wrapper, the rule now correctly recognizes that the operations are already running in parallel and doesn't flag the code.

Implementation

The fix adds:

  1. doesLocalFunctionUsePromiseConcurrency() - helper function that walks a local function's AST to detect if it uses any promise concurrency methods
  2. Enhanced isWrappedInPromiseConcurrency() to resolve local function calls and check them with the new helper

Scope Decision

What was fixed: Detection of direct local wrapper functions that internally use promise concurrency.

What was NOT fixed: Higher-order functions where the wrapper is passed as a parameter (e.g., helper(items, waitAll)). This would require more complex analysis tracking function parameters through call chains. The reported issue specifically concerns direct wrapper calls, not parameterized combinators.

Test Coverage

  • ✅ Promise.allSettled wrapper (the reported case)
  • ✅ Promise.all wrapper
  • ✅ Promise.race wrapper
  • ✅ Negative case: wrapper without promise concurrency (still correctly flagged)
  • ✅ Fuzz corpus regression entry
  • ✅ All 107 existing regression tests pass
  • ✅ Full test suite passes (1,124 tests)
  • ✅ No lint or type errors
  • ✅ Code formatted

Parity Check

⚠️ Corpus parity scan in progress - The full OSS corpus scan is currently running to verify no regressions across ~18,000+ repository scans. This will be completed before merge.

Ready to Review

This PR is ready for code review. All tests pass, the fix is well-scoped and focused on the reported case, and the reproduction example no longer produces a false positive.

Open in Web Open in Cursor 

cursoragent and others added 3 commits September 26, 2026 16:46
Fixes #1839

Previously, the rule would flag async map callbacks even when the
promise array was passed to a local wrapper around Promise.allSettled,
Promise.all, Promise.race, or Promise.any.

The fix adds detection for local functions that internally use these
promise concurrency methods. When a mapped promise array is passed to
such a wrapper, the rule now correctly recognizes that the operations
are already running in parallel.

Test cases cover:
- Promise.allSettled wrapper (the reported case)
- Promise.all wrapper
- Promise.race wrapper
- Negative case: wrapper without promise concurrency (still flagged)
- Regression corpus entry for the exact reported pattern

Co-authored-by: Skosh <skoshx@users.noreply.github.com>
The fuzz harness requires plain JavaScript syntax, so remove TypeScript
generic type parameters from the regression test file.

Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
@pkg-pr-new

pkg-pr-new Bot commented Sep 26, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/eslint-plugin-react-doctor@1842
npm i https://pkg.pr.new/oxlint-plugin-react-doctor@1842
npm i https://pkg.pr.new/react-doctor@1842

commit: 2a4b6c5

Co-authored-by: Skosh <skoshx@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Interactive terminal E2E

Terminal Control verified the built CLI at 2a4b6c5 in a real PTY:

  • selected a project interactively and observed Scanning... before the three-second Git delay completed
  • waited for the clean result and exercised the compact report
  • opened copy context and the GitHub Actions confirmation, then cancelled safely

Download the edited MP4 and PNG evidence

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

async-await-in-loop: already-parallel map callbacks reported inside a Promise.allSettled wrapper

2 participants