Skip to content

fix(js): extract methods assigned to factory object APIs - #2745

Closed
rajanpanth wants to merge 1 commit into
Graphify-Labs:v8from
rajanpanth:fix/factory-object-method-extraction
Closed

fix(js): extract methods assigned to factory object APIs#2745
rajanpanth wants to merge 1 commit into
Graphify-Labs:v8from
rajanpanth:fix/factory-object-method-extraction

Conversation

@rajanpanth

Copy link
Copy Markdown
Contributor

Summary

  • preserve callable members assigned to an object literal inside a JavaScript/TypeScript factory
  • model the local API object beneath its factory and attach assigned functions as methods
  • cover named async/function-expression assignments and their intra-factory call edge

Verification

  • uv run pytest tests/test_extract.py -q
  • uv run ruff check graphify/extractors/engine.py tests/test_extract.py
  • uv run graphify update .

Fixes #2524

@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.

Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

This PR extends the JavaScript/TypeScript extractor in graphify/extractors/engine.py to capture callable members assigned to local object-literal variables inside a function body (e.g. factory patterns like const api = {}; api.foo = fn), in addition to the existing this.X = fn handling. The _js_member_assignment_target helper now returns an ("object", name, member) tuple for arbitrary identifier receivers instead of returning None, and the caller in _extract_generic collects object-literal bindings and materializes owner nodes/edges only for those tracked identifiers. A new test, test_extract_js_factory_object_assigned_methods, is added to exercise this factory-object scenario and assert the expected node labels and contains/method/calls edges. The large set of other changed test symbols appears to reflect incidental renumbering/shifts in the test module. The surface area is the JS/TS member-assignment extraction path and the associated test file.

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

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 897 functions depend on the 534 functions this change touches.

Health — this change adds coupling hotspots:

  • worse: extract_js() — 77 callers, 3 callees

Verification — 897 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: 838 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_extract\_generic.

The verifier did not have enough to check \_extract\_generic, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `path` is annotated `Path` — outside the synthesizable primitive/collection set

Could not verify: Could not verify \_js\_member\_assignment\_target.

The verifier did not have enough to check \_js\_member\_assignment\_target, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: not verifiable: all 182 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly AttributeError — names the real obstacle, not a sampling gap)

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

safishamsi pushed a commit that referenced this pull request Aug 19, 2026
Preserve callable members assigned to a local object-literal factory API
(`const api = {}; api.foo = fn`), modeling the API object beneath its factory
and attaching the assigned functions as methods. The lazy owner-node minting
(only for identifiers proven to be object-literal bindings in the enclosing
function) avoids the #1077 config-object flood.

Partially addresses #2524 (the object-literal-method shorthand form
`return { foo() {} }` remains out of scope).
safishamsi added a commit that referenced this pull request Aug 19, 2026
…ver (#2745)

The factory-object owner path emitted the `contains` edge inside the per-member
loop; add_node dedups on id but add_edge does not, so N methods assigned to one
object flooded the graph with N identical contains edges. Emit it once per owner.

Tests: assert a single contains edge across four methods, cover arrow-function
assignment (the dominant modern factory shape), and lock the negative case that a
non-object-literal receiver (`external.handler = fn`) is not captured.
safishamsi added a commit that referenced this pull request Aug 19, 2026
Ships this cycle: the graph-correctness/UX batch — JS/TS factory-object methods
(#2745), stable graph.json field order (#2582), query names its graph (#2789),
ThinkingBlock-safe claude backend (#2697), manifest churn guard (#2838), C# primary
ctor refs (#2829), AST INFERRED rubric confidence_score (#2813), legacy numeric
confidence normalization; plus the small-fix batch — chunk-bisect on timeout (#2866),
symlink cache identity (#2832), sidecar cache root (#2787), driveless Windows path
guard (#2795), actionable partial-parse warning (#2788), and non-ASCII Obsidian tags
(#2862).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@safishamsi

Copy link
Copy Markdown
Collaborator

Shipped in v0.9.47 via authorship-preserving cherry-pick. On the way in I deduped the factory contains edge (it was being emitted once per method) and added arrow-assignment and bare-receiver tests. This fully resolves #2524. Thanks @rajanpanth! Release: https://github.com/Graphify-Labs/graphify/releases/tag/v0.9.47

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JS extractor misses property-assigned functions (api.foo = function) — factory/DI modules become near-invisible

2 participants