fix(resolution): resolve object-literal function references safely (#1932) (#2031)

* fix(resolution): resolve same-file calls through object-literal aliases (#1932)

`api.getUser()` where `api` is `const api = { getUser }` (or
`{ getUser: fetchUser }`) and the function is declared outside the literal
resolved to nothing in the literal's own file: the #1573 containment lookup
only finds members defined inside the literal, and the binding-following
alias path existed only on the import side, so same-file callers were
missing from callers / impact / blast radius.

- Extract the member-binding read into `objectLiteralMemberBinding`, which
  splits the literal into its own top-level members on comment- and
  string-blanked source, so a nested object, a member body, a comment or a
  string never donates a binding, and `{ fn: 1 }` names nothing. The import
  path now uses it too.
- In the same-file object-literal receiver strategy, fall back to that
  binding: a symbol of the file, else one of its imports, skipped when a
  parameter or nested declaration shadows the name where the literal is
  written.

Resolution-only change; extraction output (and kernel parity) unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(resolution): a literal wrapped in Object.freeze still names its members (#1932)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(resolution): resolve object-literal function references safely (#1932)

Same-file object-member calls only found functions defined inside the literal.
Share lexical binding resolution across same-file, import, and alias-forwarding paths.
Respect exact source columns, top-level membership, shadowing, and property overwrites while preserving wrappers and inline members.
Add JavaScript and TypeScript regressions and verify kernel/WASM parity.

Co-authored-by: danusha2345 <ewidusoc498@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: danusha2345 <ewidusoc498@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Colby Mchenry
2026-09-27 13:39:18 +00:00
committed by GitHub
co-authored by danusha2345 Claude Opus 5.5
parent 86708bf519
commit 17d09bf506
5 changed files with 357 additions and 52 deletions
+10
View File
@@ -21,6 +21,7 @@
import type { Node } from '../types';
import type { ResolutionContext } from './types';
import { resolveObjectLiteralBinding } from './name-matcher';
/** Kinds that can be a pure alias for another symbol. */
const ALIAS_BINDING_KINDS = new Set<string>(['constant', 'variable', 'property']);
@@ -79,6 +80,15 @@ export function resolveAliasBinding(
): Node | null {
if (!ALIAS_BINDING_KINDS.has(aliasNode.kind)) return null;
if (memberName && ['typescript', 'tsx', 'javascript', 'jsx', 'arkts'].includes(aliasNode.language)) {
const resolved = resolveObjectLiteralBinding(aliasNode, memberName, {
fromNodeId: aliasNode.id, referenceName: memberName, referenceKind: 'calls',
filePath: aliasNode.filePath, language: aliasNode.language,
line: aliasNode.startLine, column: aliasNode.startColumn,
}, context);
return resolved ? context.getNodeById?.(resolved.targetNodeId) ?? null : null;
}
const targetName = aliasTargetName(aliasNode.signature, memberName);
if (!targetName || targetName === aliasNode.name) return null;