mirror of
https://github.com/safishamsi/graphify.git
synced 2026-08-26 16:26:42 +00:00
test(js): cover external-import-shadow vs same-named local callable (#2757)
Adds the collision case the fix must survive: a name both imported externally and defined as a callable in another corpus file. The external use must not fabricate a cross-file indirect_call while a genuine local by-name reference still binds. Also adds the CHANGELOG entry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ceeafb05ce
commit
94c2050f93
@@ -4,6 +4,7 @@ Full release notes with details on each version: [GitHub Releases](https://githu
|
||||
|
||||
## 0.9.44 (unreleased)
|
||||
|
||||
- Fix: a JS/TS identifier bound by an import whose target resolves outside the scanned corpus (e.g. a `lucide-react` icon) is now shadowed, so using it as a value no longer fabricates an INFERRED `indirect_call` onto an unrelated same-named callable elsewhere in the corpus; a relative/in-corpus import still resolves to its real target (#2757, thanks @phudayyy).
|
||||
- Fix: an OCaml qualified call `M.f` to an external module (one not defined in the same file, e.g. Hardcaml's `Reg_spec.create`) no longer binds to a same-named local `let f` — which produced a false `calls` edge and, when the caller was that local `f`, a `f -> f` self-loop. External qualified calls are kept as a distinct target labelled by the full path; unqualified calls and calls into a locally-defined module still resolve locally, and cross-file `Geo.area` still collapses onto another file's `area`.
|
||||
|
||||
## 0.9.43 (2026-08-14)
|
||||
|
||||
@@ -152,3 +152,24 @@ def test_unimported_same_file_callable_still_emits(tmp_path):
|
||||
)})
|
||||
indirect = _rels(r, "indirect_call")
|
||||
assert (nid["run"], nid["handler"]) in indirect
|
||||
|
||||
|
||||
def test_external_import_shadow_does_not_bind_to_a_same_named_local_callable(tmp_path):
|
||||
"""The precise collision the fix must survive: a name that is BOTH imported
|
||||
externally AND defined as a callable in another corpus file. Using the
|
||||
external `Filter` value must not fabricate an indirect_call onto the unrelated
|
||||
corpus `Filter` — while a genuine by-name use of a local callable still binds."""
|
||||
r, nid = _extract_js_dir(tmp_path, {
|
||||
"table.ts": "export function Filter() { return null; }\n", # unrelated corpus callable
|
||||
"toolbar.tsx": (
|
||||
"import { Filter } from 'lucide-react';\n" # external, same name
|
||||
"function onClick(x) { return x; }\n"
|
||||
"export function build(sink, pool) {\n"
|
||||
" sink.push(Filter);\n" # external -> must NOT bind to table.ts Filter
|
||||
" pool.submit(onClick);\n" # local -> must still bind
|
||||
"}\n"
|
||||
),
|
||||
})
|
||||
indirect = _rels(r, "indirect_call")
|
||||
assert (nid["build"], nid["Filter"]) not in indirect # no cross-file phantom
|
||||
assert (nid["build"], nid["onClick"]) in indirect # real local reference preserved
|
||||
|
||||
Reference in New Issue
Block a user