Attribute calls in a module level anonymous closure to the file node

Number 1740 fixed calls inside an anonymous callback by attributing
them to the enclosing named function, but that only works when a
named function actually encloses it. it("...", async () => { ... })
has no such enclosing function anywhere, and that shape hits test
files hardest since it is the idiomatic way to write one. The
original report already named the intended fallback, attribute to
the module node when no named function encloses the call, but that
half was never built. A topmost closure argument to a module level
call statement now gets its own function_bodies entry keyed by the
file node, mirroring the existing fix for this.X assignments found
in the exact same statement shape, so the ordinary call walking
machinery, including its own descent into further nested closures,
picks it up from there. Toward #3124.

Known gap left open, described in the new test module's own
docstring: a callee that is both directly imported by the same file
and only called from a module level anonymous closure still does not
resolve, because the cross file resolution pass dedupes purely by
source and target regardless of relation, so the file node's own
import edge to that target pre-empts the calls edge. Fixing that
dedup properly reaches far beyond this one case and is left for a
separate change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh
This commit is contained in:
ayushcodes10andClaude Sonnet 5 committed 2026-09-13 18:25:31 +05:30
1 parent fe66389083
commit 8a0367c505
1 file changed
+16
+16
View File
@@ -2397,6 +2397,22 @@ def _js_extra_walk(node, source: bytes, file_nid: str, stem: str, str_path: str,
add_node_fn=add_node_fn, add_edge_fn=add_edge_fn,
function_bodies=function_bodies,
)
# #3124: calls made directly inside this closure (not just
# `this.X = fn` member assignments) were dropped entirely,
# since walk_calls only ever runs on function_bodies
# entries and this closure has no named owner to seed one.
# `it("...", async () => { register(...) })` is exactly
# this shape: the nearest enclosing scope is anonymous, so
# #1740's "attribute to the enclosing function" fix never
# applies and nothing is emitted, not even to the file
# node #1740 itself named as the fallback. Attribute calls
# here to the file node instead, mirroring the member
# assignment attribution just above -- a nested member
# function's own body is appended with its own real id by
# `_js_scan_member_assignments`, so it lands in
# `_tracked_body_ids` and walk_calls' own boundary check
# skips re-descending into it from here.
function_bodies.append((file_nid, closure_body))
assign = next((c for c in node.children
if c.type == "assignment_expression"), None)
if assign is not None: