Skip to content

fix(js): resolve calls through default-exported object methods - #4967

Open
xiongjianxu wants to merge 1 commit into
Graphify-Labs:v8from
xiongjianxu:fix/ts-default-object
Open

xiongjianxu wants to merge 1 commit into
Graphify-Labs:v8from
xiongjianxu:fix/ts-default-object

Conversation

@xiongjianxu

@xiongjianxu xiongjianxu commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

export default { toast() {} } already creates a method node, but import native from './native'; native.toast() produces no cross-file call edge. Resolve the call through existing default-import facts and raw calls, matching the target module, method label and source line to the existing node.

Renamed imports and unchanged target nodes supplied as incremental context work. Lexical binding checks exclude shadowed receivers, including captured outer bindings and function/class declarations. Constructor expressions are excluded. The scope is directly default-exported object literals with static methods; computed keys, spread, duplicate keys, accessors and dynamic aliases remain unresolved.

The caller and target must be visible to the extraction or its resolution context, and existing import resolution must locate the module. This supports a unified scan of a monorepo or multiple repository directories under those conditions. It does not rerun this resolution during global add of independently extracted graphs.

Validation after rebasing onto v8 8e6a6d21, using the existing macOS environment without installing dependencies:

  • Core new regressions reproduced against the original implementation: 4 failed; earlier review also reproduced shadowing and constructor failures before their guards.
  • JS/TS, incremental, cache and architecture checks across 44 modules: 932 passed, 13 skipped, 1 xfailed.
  • python -m ruff check . and git diff --check: passed; added Python lines are at most 99 Unicode code points.
  • Full Pyright: 705 errors / 4 warnings, matching the current baseline; diagnostic comparison has zero additions and zero removals.
  • AST-only python -m graphify update . --no-cluster: succeeded. Generated graphs and caches are excluded.

JS/TS already bypass the per-file AST cache, so this cross-file resolution change does not bump its schema.

Coordinated full-suite validation on v8 8e6a6d21 used UV_OFFLINE=1 PYTHONHASHSEED=0 python -m pytest tests -q --tb=short --disable-warnings, with PYTHONPATH pointing to each checkout: baseline 9,094 passed / 15 failed, all four changes combined 9,224 passed / 15 failed, with identical failure lists and zero added failures. Both had 357 skipped and 1 xfailed. The 15 baseline failures cover SQL grammar, wheel-build dependency, shell-parser control and Terraform parallel-cache cases. Combined full Pyright had 704 errors / 4 warnings versus baseline 705 / 4, with zero added diagnostics. Combined validation uses cache schema 39 to keep its namespace separate from the individual extraction patches.

Closes #4963

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown

Thanks for the pull request, @xiongjianxu. A maintainer will review it soon.

Want to talk it through while it is in review? Come join us on our Discord server. For longer-form discussion there is also GitHub Discussions.

A couple of things that speed up review: make sure the test suite passes on Python 3.10 and 3.13, and that the change keeps extraction deterministic.

@github-actions github-actions Bot added the contributor Pull request from a returning community contributor label Nov 3, 2026
@xiongjianxu
xiongjianxu force-pushed the fix/ts-default-object branch from 58d9fb8 to fadb09d Compare November 3, 2026 02:48

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

No issues found by static checks — no coupling regressions or blocking issues in the code graph. That is not the same as safe to merge: see what was not checked.

Not checked: tests were not run; no formal proof of the changed code.


Graphify review — findings

Adds cross-file call resolution for JS/TS member calls made through a default import of a module whose default export is a plain object literal (e.g. api.get() where export default { get() {} }), linking the caller to the existing method node instead of leaving the call unresolved. Matching is by imported module path, exact method label and source line, and it skips shadowed receivers, new calls, this fields, spreads, computed keys, getters/setters, duplicate keys and escaped names; the extractor now tags each member call with _js_receiver_shadowed and _js_construct by walking all lexical ancestors, and extract passes raw_calls through to the resolution step. Files involved already bypass the per-file AST cache, so no cache schema bump is needed.

No blocking issues surfaced. 2 lower-confidence candidates did not survive cross-model review.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 4838 functions depend on the 1049 functions this change touches.

Health — this change adds coupling hotspots:

  • worse: extract() — 1117 callers, 66 callees
  • worse: _apply_symbol_resolution_facts() — 6 callers, 13 callees
  • worse: walk_calls() — 1 callers, 38 callees
  • worse: _parse_js_tree() — 9 callers, 4 callees

Verification — 4838 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 4312 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

501 of 501 test file(s) selected (100%) via static blast radius.

Escalated to a full run for safety — the selection is not trustworthy on its own (see below). CI should run the whole suite.

  • tests/pi.test.ts — full-run-safety
  • tests/test_4874_jvm_resolution.py — impact, full-run-safety
  • tests/test_4909_reference_binding_scale.py — impact, full-run-safety
  • tests/test_affected_cli.py — full-run-safety
  • tests/test_affected_defines.py — full-run-safety
  • tests/test_affected_member_seed.py — full-run-safety
  • tests/test_affected_overrides.py — impact, full-run-safety
  • tests/test_affected_path_file_node.py — full-run-safety
  • tests/test_affected_seed_reference_forms.py — full-run-safety
  • tests/test_agents_platform.py — full-run-safety
  • tests/test_alias_folding.py — impact, full-run-safety
  • tests/test_analyze.py — impact, full-run-safety
  • tests/test_anthropic_custom_endpoint.py — full-run-safety
  • tests/test_antigravity_install.py — full-run-safety
  • tests/test_apm_fallback_version.py — full-run-safety
  • tests/test_architecture_doc.py — full-run-safety
  • tests/test_astro_extraction.py — impact, full-run-safety
  • tests/test_astro_import_ids.py — impact, full-run-safety
  • tests/test_atomic_canvas_export.py — full-run-safety
  • tests/test_atomic_version_stamp.py — full-run-safety
  • tests/test_atomic_writes.py — full-run-safety
  • tests/test_backend_env_isolation.py — full-run-safety
  • tests/test_backend_extras.py — full-run-safety
  • tests/test_backend_opt_in.py — full-run-safety
  • tests/test_benchmark.py — full-run-safety
  • tests/test_benchmark_raw_graph.py — full-run-safety
  • tests/test_benchmark_real_query.py — full-run-safety
  • tests/test_binary_media_words.py — full-run-safety
  • tests/test_blade_extractor.py — impact, full-run-safety
  • tests/test_build.py — impact, full-run-safety
  • tests/test_build_located_semantic_identity.py — impact, full-run-safety
  • tests/test_build_merge_dedup_scope.py — impact, full-run-safety
  • tests/test_build_merge_hyperedges_and_prune.py — impact, full-run-safety
  • tests/test_build_merge_shrink_guard.py — impact, full-run-safety
  • tests/test_builtin_global_type_refs.py — impact, full-run-safety
  • tests/test_c_include_resolution.py — impact, full-run-safety
  • tests/test_cache.py — impact, full-run-safety
  • tests/test_cache_long_paths.py — full-run-safety
  • tests/test_cache_stale_import_target.py — full-run-safety
  • tests/test_cache_windows_case_4925.py — full-run-safety
  • tests/test_callflow_html.py — full-run-safety
  • tests/test_cargo_introspect.py — full-run-safety
  • tests/test_cargo_missing_manifest.py — full-run-safety
  • tests/test_carried_hyperedge_remap.py — impact, full-run-safety
  • tests/test_case_only_decl_ids_4904.py — impact, full-run-safety
  • tests/test_case_sensitive_resolution.py — impact, full-run-safety
  • tests/test_charmap_encoding.py — full-run-safety
  • tests/test_chunking.py — impact, full-run-safety
  • tests/test_cjs_module_extension.py — impact, full-run-safety
  • tests/test_claude_cli_backend.py — full-run-safety
  • … and 451 more

non-code file(s) changed (ARCHITECTURE.md) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (ARCHITECTURE.md) — a coverage gap or a missing link — running the full suite rather than only the selected tests

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

· 4 more finding(s) on lines outside this diff (see the check run).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor Pull request from a returning community contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Default-imported object literal methods have nodes but no cross-file call edges

1 participant