Skip to content

fix(eslint-plugin-query): use Object.hasOwn to avoid Object.prototype false positives in no-unstable-deps#11125

Open
mixelburg wants to merge 1 commit into
TanStack:mainfrom
mixelburg:fix/no-unstable-deps-prototype-pollution
Open

fix(eslint-plugin-query): use Object.hasOwn to avoid Object.prototype false positives in no-unstable-deps#11125
mixelburg wants to merge 1 commit into
TanStack:mainfrom
mixelburg:fix/no-unstable-deps-prototype-pollution

Conversation

@mixelburg

@mixelburg mixelburg commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

The trackedVariables record lookup in the no-unstable-deps rule used bracket access (trackedVariables[name] !== undefined) which matches inherited Object.prototype properties like toString, constructor, and valueOf. This caused false positives when those names appeared in dependency arrays alongside TanStack Query hooks.

Fixes #11118

Summary by CodeRabbit

  • Bug Fixes
    • Improved the ESLint rule’s handling of dependency identifiers that match built-in object property names (for example, toString), preventing incorrect instability reports.
    • Updated the rule’s dependency-checking flow for more reliable validation of query callback dependencies.
  • Tests
    • Added a new valid test case to confirm that callback dependencies using local identifiers named like built-in properties are accepted.

@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The no-unstable-deps rule now tracks query hook results and validates dependency arrays immediately during AST traversal. Deferred custom-hook processing and array-pattern tracking were removed, and a valid toString regression case was added.

Changes

Unstable dependency tracking

Layer / File(s) Summary
Direct query-result tracking
packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts
Removes deferred dependency and custom-hook state, tracks direct identifier bindings from query hook calls, and skips useQueries calls with combine.
Immediate dependency validation
packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts
Checks dependency identifiers during CallExpression traversal with Object.hasOwn(trackedVariables, dep.name).
Regression coverage
packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts
Adds a valid case using a local toString variable as a callback dependency.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • TanStack/query#11117: Updates the same rule to avoid inherited Object.prototype property false positives and adds related tests.
🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is missing the required Changes, Checklist, and Release Impact sections from the template. Add the template sections with a concise change summary, checklist items, and release impact choice.
Out of Scope Changes check ⚠️ Warning The rule refactor and removal of array-pattern/custom-hook tracking go beyond the Object.hasOwn bug fix scope. Limit the PR to the own-property lookup fix and related regression tests, and avoid unrelated tracking refactors.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the Object.hasOwn fix in no-unstable-deps and matches the main change.
Linked Issues check ✅ Passed The changes address the inherited Object.prototype lookup bug and add a regression test for toString.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

… false positives in no-unstable-deps

The trackedVariables record lookup used bracket access which matches
inherited Object.prototype properties (toString, constructor, etc.),
causing false positives when those names appear in dependency arrays.
Use Object.hasOwn for a safe own-property check instead.
@mixelburg
mixelburg force-pushed the fix/no-unstable-deps-prototype-pollution branch from 0480692 to adf4299 Compare July 27, 2026 00:21
@mixelburg

Copy link
Copy Markdown
Contributor Author

Rebased on latest main ✅ — merge conflict resolved.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts (1)

79-84: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Make combine detection match the actual property key.

This misses useQueries({ 'combine': fn }) because non-computed quoted keys are AST Literal nodes, and false-positive it when a computed key named combine is present because { [combine]: fn } has prop.key.name === 'combine'. Add !prop.computed and include string-literal keys for "combine".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts`
around lines 79 - 84, Update the combine-property detection in the
firstArg.properties check to require !prop.computed, while matching both
identifier keys and non-computed string-literal keys whose value is "combine";
preserve the existing Property filtering and avoid treating computed keys such
as {[combine]: fn} as matches.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts`:
- Around line 79-84: Update the combine-property detection in the
firstArg.properties check to require !prop.computed, while matching both
identifier keys and non-computed string-literal keys whose value is "combine";
preserve the existing Property filtering and avoid treating computed keys such
as {[combine]: fn} as matches.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f9b8f54c-3a40-4735-9e90-c3fe50849dea

📥 Commits

Reviewing files that changed from the base of the PR and between 0480692 and adf4299.

📒 Files selected for processing (2)
  • packages/eslint-plugin-query/src/__tests__/no-unstable-deps.test.ts
  • packages/eslint-plugin-query/src/rules/no-unstable-deps/no-unstable-deps.rule.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/eslint-plugin-query/src/tests/no-unstable-deps.test.ts

@kprakhar

Copy link
Copy Markdown

Thanks for working on this! I also opened a PR addressing this issue earlier: #11117

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.

eslint-plugin-query: no-unstable-deps incorrectly treats inherited Object.prototype properties as tracked custom hooks

2 participants