From e9c10258a7be881ddf50efb7c793bb68c27fe8b8 Mon Sep 17 00:00:00 2001 From: ayushcodes10 Date: Mon, 14 Sep 2026 14:48:00 +0530 Subject: [PATCH] Add a regression test for unexported require destructures Pins the exact interaction the fix commit already describes: a CommonJS const equals require of a module destructure must still resolve to exactly one EXTRACTED calls edge, not zero, confirming the export only gate keeps it out of the per name split entirely. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_017qfdzgbA5KedGEjD1AayNh --- tests/test_js_destructured_export.py | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/test_js_destructured_export.py b/tests/test_js_destructured_export.py index d7b5a0982..ede9c8ebb 100644 --- a/tests/test_js_destructured_export.py +++ b/tests/test_js_destructured_export.py @@ -84,3 +84,34 @@ def test_rest_pattern_is_skipped_not_mangled(tmp_path): assert "auth" in labels assert "rest" not in labels assert not any("rest" in label for label in labels) + + +def test_unexported_require_destructure_does_not_create_a_colliding_node(tmp_path): + """The gate that gives an EXPORTED destructure one node per name must not + fire for an un-exported destructure of the same shape -- CommonJS + `const { doWork } = require('./lib')` is a local IMPORT binding, not a + module export. Splitting it would emit a bare-named node in the + IMPORTING file that collides with the real definition it merely imports, + turning a clean cross-file call resolution into a false "ambiguous name" + (this reproduces the #2604 fix regressing + test_cross_file_call_promoted_to_extracted_with_import_evidence).""" + r, lbl = _extract(tmp_path, { + "lib.js": ( + "function doWork() { return 1; }\n" + "module.exports = { doWork };\n" + ), + "caller.js": ( + "const { doWork } = require('./lib');\n" + "function run() { doWork(); }\n" + ), + }) + calls = [ + (lbl.get(e["source"]), lbl.get(e["target"]), e.get("confidence")) + for e in r["edges"] if e["relation"] == "calls" + ] + matches = [c for c in calls if c[0] == "run()" and c[1] == "doWork()"] + assert len(matches) == 1, ( + f"expected exactly one run() -> doWork() calls edge, got {matches}; " + f"all calls={calls}" + ) + assert matches[0][2] == "EXTRACTED"