Skip to content

fix(js,ts): a function inside an object literal's method is a local, not a member - #3161

Merged
colbymchenry merged 1 commit into
mainfrom
claude/fx-object-literal-locals
Nov 1, 2026
Merged

colbymchenry merged 1 commit into
mainfrom
claude/fx-object-literal-locals

Conversation

@colbymchenry

Copy link
Copy Markdown
Owner

A bare call between two functions declared in a method of an object behind
satisfies or as const linked to nothing: 34 calls in react's ESLint rules,
where const rule = {...} satisfies Rule.RuleModule holds everything in
create, like reportProblem(...) from visitCallExpression. 1.6.2 linked
them. Regression from f40db4b (PR #2363), which never shipped.

Traced: the extractor makes a literal's direct function members nodes only
when the initializer is the literal itself, so behind satisfies the method
create has no node, and what it declares is qualified under the constant:
rule::reportProblem. objectLiteralOwnerOf took any function qualified under
a holder whose initializer opens with { for a member of the literal, and a
member is never reached by a bare name. So the shape is wider than the report
says: a method of a nested object, a computed key, a function a member's value
passes on, and a literal read through [key] all lost the same calls, in
Vue and Svelte script blocks too.

Fix (resolver only): a holder's own text is read once for its {...} blocks.
A function directly in the literal's braces is a member. One deeper down is a
local of the block it is written in: reachable by name from inside that block
and from nowhere else, which is tighter than 1.6.2, where such a function
answered a bare name from anywhere. No extraction change, so no kernel change.

Validation

  • Tests: fail on main, pass here, on this head.
  • No extraction change, so nothing to compare between engines.
  • A/B against 4499d007:
Repo Added Removed Moved
react, where it was found 35 0 0
outline 5 0 0
excalidraw, vscode-be, taxonomy, vben 0 0 0
Controls: express, flask, gin 0 0 0

All 40 read against source. react's 34 calls are the ones REG listed, in ExhaustiveDeps.ts and RulesOfHooks.ts, plus the visitCallExpression reference; outline's 5 are its oxlint rules, a literal's rules: { x: { create(context) { const check = …; … } } }.

1.6.2 linked one more reference at each such site, from the file as well as from the constant. That was a duplicate main dropped on purpose and it stays dropped.

  • Index CPU: the six together, median of 3 interleaved: react 131.0 to 132.4 s (+1.1%, rounds spread 112 to 145 s; wall -6.4%), vscode-be 43.8 to 44.0 s (+0.6%), django 68.0 to 66.4 s (-2.3%). Level within noise.
  • Suite: the six PRs of this set ran as one stack, 97cd3800, all six on 4499d007: 853 files passed, 6 skipped; 10,610 tests passed, 2 expected fail, 87 skipped, 0 failed; 4 workers, Vitest 4.1.11, CODEGRAPH_KERNEL_EXPECT=1. This PR's own test files pass on this head.

🤖 Generated with Claude Code

…not a member

A bare call between two functions declared in a method of an object behind
`satisfies` or `as const` linked to nothing: 34 calls in react's ESLint rules,
where `const rule = {...} satisfies Rule.RuleModule` holds everything in
`create`, like `reportProblem(...)` from `visitCallExpression`. 1.6.2 linked
them. Regression from f40db4b (PR #2363), which never shipped.

Traced: the extractor makes a literal's direct function members nodes only
when the initializer is the literal itself, so behind `satisfies` the method
`create` has no node, and what it declares is qualified under the constant:
`rule::reportProblem`. objectLiteralOwnerOf took any function qualified under
a holder whose initializer opens with `{` for a member of the literal, and a
member is never reached by a bare name. So the shape is wider than the report
says: a method of a nested object, a computed key, a function a member's value
passes on, and a literal read through `[key]` all lost the same calls, in
Vue and Svelte script blocks too.

Fix (resolver only): a holder's own text is read once for its `{...}` blocks.
A function directly in the literal's braces is a member. One deeper down is a
local of the block it is written in: reachable by name from inside that block
and from nowhere else, which is tighter than 1.6.2, where such a function
answered a bare name from anywhere. No extraction change, so no kernel change.

Validation: object-literal tests red on main (16), green here, on both
engines. A/B against 4499d00: react +35 (34 calls and 1
reference, all in the two ESLint rules), outline +5 (its oxlint rules);
excalidraw, vscode-be, taxonomy, express, vben, flask, gin identical. All 40
read against source. Index CPU: level (see the PR).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@colbymchenry
colbymchenry merged commit 9c5cf97 into main Nov 1, 2026
@colbymchenry
colbymchenry deleted the claude/fx-object-literal-locals branch November 1, 2026 04:10
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.

1 participant