Skip to content

feat(resolver): resolve property calls on object destructuring rest parameters (JS)#1350

Open
carlos-alm wants to merge 5 commits into
mainfrom
feat/resolver-destructuring-rest-params-1336
Open

feat(resolver): resolve property calls on object destructuring rest parameters (JS)#1350
carlos-alm wants to merge 5 commits into
mainfrom
feat/resolver-destructuring-rest-params-1336

Conversation

@carlos-alm
Copy link
Copy Markdown
Contributor

Summary

Resolves #1336. When a function parameter uses object destructuring with a rest element (...rest) and the rest object's property is called, codegraph now resolves the callee.

Pattern:

function e4() {}
var obj = { e4 };

function f3({ e1: eee1, ...eerest }) {
    eerest.e4();  // expected edge: f3 → e4 — now resolved ✓
}
f3(obj);

Resolution chain (Phase 8.3f)

  1. Object literal property seedinghandleVarDeclaratorTypeMap now calls seedProtoProperties for object literals: var obj = { e4 } seeds typeMap['obj.e4'] = { type: 'e4' }.
  2. Rest-param binding extraction — new extractObjectRestParamBindingsWalk records { callee: 'f3', argIndex: 0, restName: 'eerest' } from function f3({ a, ...eerest }).
  3. Cross-reference in build-edgesbuildCallEdgesJS cross-references objectRestParamBindings with paramBindings to seed typeMap['eerest'] = { type: 'obj' } when f3(obj) is called.
  4. ResolutionresolveByMethodOrGlobal: typeMap['eerest'] → obj; typeMap['obj.e4'] → 'e4'; lookup.byName('e4') → resolved edge.

Changes

  • src/types.ts — add ObjectRestParamBinding interface and ExtractorOutput.objectRestParamBindings optional field
  • src/extractors/javascript.ts — add extractObjectRestParamBindingsWalk; extend handleVarDeclaratorTypeMap to seed object literal shorthand/pair properties into typeMap
  • src/domain/graph/builder/stages/build-edges.ts — Phase 8.3f typeMap seeding from rest param bindings × param bindings
  • src/domain/wasm-worker-protocol.ts / wasm-worker-entry.ts / wasm-worker-pool.ts — serialize/deserialize objectRestParamBindings through WASM worker boundary
  • tests/parsers/javascript.test.ts — 6 unit tests for extraction and seeding
  • tests/integration/issue-1336-object-rest-param-resolution.test.ts — integration test (WASM engine)
  • tests/benchmarks/resolution/fixtures/jelly-micro/rest/ — fixture + expected-edges for the Jelly micro-test corpus

Follow-up issues

…arameters (JS)

When a function parameter uses object destructuring with a rest element
(`...rest`) and the rest object's property is then called, codegraph now
resolves the callee.

Resolution chain (Phase 8.3f):
1. JS extractor seeds typeMap['obj.X'] = { type: 'X' } for shorthand
   properties in object literals (`var obj = { e4 }`).
2. New extractObjectRestParamBindingsWalk records objectRestParamBinding
   { callee, argIndex, restName } from `function f({ a, ...rest })`.
3. build-edges.ts cross-references with paramBindings from f(obj) calls
   to seed typeMap[restName] = { type: argName, confidence: 0.65 }.
4. resolveByMethodOrGlobal: typeMap[restName] → obj; typeMap[obj.method]
   → method → resolved edge.

Adds:
- ObjectRestParamBinding type + ExtractorOutput.objectRestParamBindings field
- objectRestParamBindings serialised through WASM worker boundary
- extractObjectRestParamBindingsWalk in javascript.ts
- Object literal shorthand property seeding in handleVarDeclaratorTypeMap
- Phase 8.3f typeMap seeding in buildCallEdgesJS
- 6 unit tests in tests/parsers/javascript.test.ts
- Integration test (WASM engine) in issue-1336-object-rest-param-resolution.test.ts
- Jelly micro-test fixture tests/benchmarks/resolution/fixtures/jelly-micro/rest/

Files issue #1348 (missing WASM worker serialisation for paramBindings/
returnTypeMap/callAssignments) and #1349 (native engine parity) as follow-ups.

Closes #1336
@claude
Copy link
Copy Markdown

claude Bot commented Jun 6, 2026

Claude finished @carlos-alm's task —— View job


PR Review: feat(resolver): resolve property calls on object destructuring rest parameters (JS)

  • Read changed files and gather context
  • Phase 1: Root cause analysis
  • Phase 2: Configuration change detection
  • Phase 3: Test integrity
  • Phase 4: Code quality
  • Phase 5: Backlog compliance
  • Final assessment

Root Cause Analysis

Problem Being Solved: When a JS function uses function f({ a, ...rest }) { rest.method() } and f(obj) is called with an object literal, the call rest.method() was not being resolved to the underlying function. This is a genuine resolution gap in the WASM engine's points-to analysis.

Why This Approach: The PR adds a 4-step chain:

  1. Seed typeMap['obj.e4'] = { type: 'e4' } from var obj = { e4 } (Phase 8.3f object literal seeding in handleVarDeclaratorTypeMap)
  2. Record objectRestParamBindings from function f({ ...rest }) parameter patterns
  3. Cross-reference with existing paramBindings at call sites to derive typeMap['rest'] = { type: 'obj' }
  4. Let existing resolveByMethodOrGlobal chain do the rest: rest → obj → obj.e4 → e4

This approach correctly reuses the existing resolution machinery rather than inventing a new mechanism.

Risk Assessment: Low-to-medium. The feature is WASM-only, purely additive, and explicitly scoped. The known gaps (paramBindings not serialized through WASM worker, native parity) are acknowledged and tracked.


Backlog Compliance

  • Zero-dep: ✓ — no new runtime dependencies
  • Foundation-aligned: ✓ — pure static analysis, local processing, no cloud calls, no file mutation
  • Problem-fit: 4/5 — directly improves call edge accuracy for AI agents navigating codebases that use rest-destructuring patterns (common in modern JS), reducing false "dead code" classifications and missing blast-radius paths
  • Breaking: No — purely additive, no API/CLI/schema changes
  • Tier: Tier 1

Critical Concerns

🔴 C1: objectRestParamBindings depends on paramBindings, but paramBindings is NOT serialized through the WASM worker boundary

This is the most significant issue. The entire Phase 8.3f resolution chain in build-edges.ts:844-854 depends on both symbols.objectRestParamBindings and symbols.paramBindings being present simultaneously:

// build-edges.ts:844
if (symbols.objectRestParamBindings?.length && symbols.paramBindings?.length) {

The PR correctly adds objectRestParamBindings to:

  • SerializedExtractorOutput (protocol.ts:67)
  • serializeExtractorOutput (worker-entry.ts:809-811)
  • deserializeResult (worker-pool.ts:111-112)

But paramBindings is not in SerializedExtractorOutput and is not serialized/deserialized through the WASM worker boundary at all (wasm-worker-protocol.ts has no paramBindings field). The PR author acknowledged this in follow-up issue #1348.

Consequence: When running buildGraph({ engine: 'wasm' }), the WASM worker path produces ExtractorOutput objects with objectRestParamBindings populated but paramBindings = undefined. The condition on line 844 short-circuits, and the typeMap seeding never happens. The integration test at tests/integration/issue-1336-object-rest-param-resolution.test.ts:47 forces engine: 'wasm' — but the actual build pipeline uses the worker pool path, not the direct extractSymbols path. Let me verify: the unit tests (parsers/javascript.test.ts) call extractSymbols directly, so they see paramBindings. But the integration test calls buildGraph({ engine: 'wasm' }) — does this go through the worker pool or directly?

Looking at build-edges.ts:832-870, buildCallEdgesJS operates on fileSymbols, which comes from ctx.fileSymbols. These are populated from the worker pool output. Since paramBindings is not in SerializedExtractorOutput, the worker pool's deserializeResult cannot reconstruct it. If the integration test is passing, it means either: (a) the test is exercising the direct-parse path (not the worker pool), or (b) paramBindings happens to be preserved on the main-thread path for this fixture.

This needs verification — if the integration test passes via the non-worker path but fails via the worker path, the PR is shipping incomplete functionality with a misleading passing test.

🟡 C2: seedProtoProperties duplicates existing logic

The new seedProtoProperties function in javascript.ts:1728-1746 seeds typeMap['obj.key'] = { type: 'key' } for object literals. This is called from handleVarDeclaratorTypeMap. However, there is already existing logic in handlePropWriteTypeMap (line 1626) for the assignment case, and handleDefinePropertyTypeMap (line 1660) for Object.defineProperty. The seedProtoProperties function is specific and clean, but it also means object literal seeding is now inconsistently split: var obj = { e4 } is handled, but let obj = { e4 } via let declarator — is the handleVarDeclaratorTypeMap function called for all declarator kinds?

Checking javascript.ts:1596-1602: handleVarDeclaratorTypeMap is called for variable_declarator nodes. var, let, and const all produce variable_declarator children, so this should be consistent. ✓

🟡 C3: The extractObjectRestParamBindingsWalk recursive walk does not skip function scopes

extractObjectRestParamBindingsWalk at line 1849 recurses into all children including function bodies. If there's a nested function that also uses rest-destructuring, its rest bindings will be collected with correct fnName, but the callee name comes from the function's name node (the inner function), not the outer. This is actually correct behavior — but it means deeply nested function definitions are scanned even though they're separately tracked. This is consistent with how extractParamBindingsWalk works (also doesn't skip function scopes). Low risk.

🟡 C4: Confidence value (0.65) is a magic number

build-edges.ts:849: typeMap.set(orpb.restName, { type: pb.argName, confidence: 0.65 }) uses a hardcoded 0.65. Per CLAUDE.md:

When adding new behavioral constants, always add them to DEFAULTS and wire them through config — never introduce new hardcoded magic numbers in individual modules.

0.65 is below the threshold for PROPAGATION_HOP_PENALTY-based adjustments and appears to be a deliberate choice, but it should be a named constant (e.g., REST_BINDING_CONFIDENCE = 0.65) at minimum, or a DEFAULTS entry.

🟡 C5: Missing serialization parity — paramBindings gap creates an asymmetry

The PR opens issue #1348 for the missing paramBindings serialization. However, the current state creates an asymmetry: objectRestParamBindings is now serialized through the worker boundary, but paramBindings — which it depends on — is not. This means objectRestParamBindings in the deserialized output is essentially dead data: it's present but can never trigger the build-edges.ts:844 condition when coming from the worker pool. The fix is incomplete without #1348.


Code Quality Observations

Positive:

  • The resolution chain is cleanly decomposed into existing phases — no new architectural patterns introduced
  • extractObjectRestParamBindingsWalk correctly handles all three function forms (declaration, arrow, function-expression)
  • The seedProtoProperties function is clean and handles both shorthand_property_identifier and pair node types
  • Test coverage is solid: 4 unit tests for extraction + 2 for typeMap seeding + 1 integration test + benchmark fixture

Minor issues:

  • javascript.ts:1807: findChild(node, 'formal_parameters') — JavaScript doesn't use formal_parameters as the field name for tree-sitter (it's parameters). This is likely a dead fallback that never matches, but is harmless.
  • The integration test comment // Force WASM engine — native engine parity tracked in #1349 is honest and appropriate.

Final Recommendation

Rating: ⭐⭐⭐ (3/5)
Action: REQUEST CHANGES

Reasoning:

The approach is architecturally sound and the extraction logic is correct. However, the PR ships objectRestParamBindings serialization (C1) without its dependency paramBindings serialization, creating an asymmetry where the new field is technically in the worker output but the cross-referencing condition in build-edges.ts:844 can never fire in the worker pool path. The integration test passes, but it should be verified to confirm it exercises the full worker pool path (not just the direct parse path).

Before merging:

  1. Verify the integration test exercises the WASM worker pool path (not direct extractSymbols)
  2. Either add paramBindings to SerializedExtractorOutput + worker serialization in this PR (making the feature actually work end-to-end via the worker pool), or document explicitly in code that Phase 8.3f seeding only works on the non-worker-pool WASM path and is blocked until fix(wasm-worker): paramBindings, returnTypeMap, callAssignments silently dropped at worker thread boundary #1348
  3. Extract the 0.65 magic constant to a named constant (CLAUDE.md requirement)

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Jun 6, 2026

Greptile Summary

This PR implements Phase 8.3f of the codegraph resolution pipeline, enabling call-edge resolution for property calls on object-destructuring rest parameters in JavaScript (e.g. eerest.e4() where eerest is the rest binding of a destructured argument). The resolution chains from object-literal property seeding → rest-param binding extraction → cross-reference in buildCallEdgesJS → typeMap-based resolution.

  • New extractor extractObjectRestParamBindingsWalk records { callee, argIndex, restName } triples for function/arrow/generator declarations with object-destructuring rest params; paramIdx accounting is consistent with extractParamBindingsWalk.
  • handleVarDeclaratorTypeMap now calls seedProtoProperties for plain object literals (var obj = { e4 }typeMap['obj.e4'] = 'e4'), enabling the downstream cross-reference to work.
  • WASM worker boundary is updated to serialize/deserialize objectRestParamBindings; paramBindings serialization remains a tracked follow-up (fix(wasm-worker): paramBindings, returnTypeMap, callAssignments silently dropped at worker thread boundary #1348), which means the integration test (WASM engine) is currently blocked by that gap.

Confidence Score: 5/5

Safe to merge; all changes are additive and guarded by optional-chaining short-circuits that prevent any impact on files without the new fields.

The extraction logic is correct and well-tested; the object-literal seeding in handleVarDeclaratorTypeMap is properly placed after all existing early-return paths; the WASM serialization is symmetric; and the two WASM-parity gaps (#1348, #1349) are explicitly acknowledged and tracked as follow-ups. No existing behavior is changed.

No files require special attention. The integration test in issue-1336-object-rest-param-resolution.test.ts is expected to remain blocked until #1348 lands.

Important Files Changed

Filename Overview
src/types.ts Adds ObjectRestParamBinding interface and optional objectRestParamBindings field to ExtractorOutput; well-documented and consistent with surrounding optional fields.
src/extractors/javascript.ts Adds extractObjectRestParamBindingsWalk (handles function/arrow/generator declarations) and object-literal seeding in handleVarDeclaratorTypeMap; paramIdx counting is correct; minor style issues: redundant ?. after null guard and confusing local variable name objectRestParamBindingsWalk.
src/domain/graph/builder/stages/build-edges.ts Phase 8.3f cross-reference seeding is correct for the single-file path; the double-guard safely short-circuits when either field is absent, matching the WASM gap documented in #1348.
src/domain/wasm-worker-protocol.ts Adds objectRestParamBindings to SerializedExtractorOutput; type-safe and consistent with adjacent optional fields.
src/domain/wasm-worker-entry.ts Serializes objectRestParamBindings using the same conditional spread pattern used for fnRefBindings and newExpressions; correct.
src/domain/wasm-worker-pool.ts Deserializes objectRestParamBindings symmetrically; consistent with the rest of the deserialization block.
tests/integration/issue-1336-object-rest-param-resolution.test.ts Integration test correctly exercises the WASM engine path; expected to be blocked by #1348 (missing paramBindings WASM serialization) until that follow-up lands.
tests/parsers/javascript.test.ts Six new unit tests cover rest-binding extraction for function declarations, arrow functions, multi-param argIndex, no-rest guard, shorthand seeding, and pair seeding; comprehensive for the new paths.
tests/benchmarks/resolution/fixtures/jelly-micro/rest/rest.js Benchmark fixture correctly illustrates the target pattern; the eee1() direct call is intentionally omitted from expected-edges as it is out of scope for Phase 8.3f.
tests/benchmarks/resolution/fixtures/jelly-micro/rest/expected-edges.json Single expected edge f3 → e4 correctly reflects the one new resolution the feature enables; schema and format consistent with adjacent fixtures.

Sequence Diagram

sequenceDiagram
    participant Extractor as javascript.ts (Extractor)
    participant TypeMap as typeMap
    participant BuildEdges as build-edges.ts
    participant Resolver as resolveByMethodOrGlobal

    Extractor->>TypeMap: "seedProtoProperties(obj, objectNode)<br/>typeMap[obj.e4] = { type: e4, conf: 0.85 }"
    Extractor->>BuildEdges: "objectRestParamBindings<br/>[ { callee:f3, argIndex:0, restName:eerest } ]"
    Extractor->>BuildEdges: "paramBindings<br/>[ { callee:f3, argIndex:0, argName:obj } ]"

    Note over BuildEdges: Phase 8.3f cross-reference
    BuildEdges->>TypeMap: "typeMap.set(eerest, { type:obj, conf:0.65 })"

    Note over BuildEdges: buildFileCallEdges processes eerest.e4()
    BuildEdges->>Resolver: resolve receiver eerest, prop e4
    Resolver->>TypeMap: "typeMap.get(eerest) → { type: obj }"
    Resolver->>TypeMap: "typeMap.get(obj.e4) → { type: e4 }"
    Resolver-->>BuildEdges: edge: f3 → e4
Loading

Fix All in Claude Code

Reviews (2): Last reviewed commit: "Merge branch 'main' into feat/resolver-d..." | Re-trigger Greptile

Comment on lines +844 to +854
if (symbols.objectRestParamBindings?.length && symbols.paramBindings?.length) {
for (const orpb of symbols.objectRestParamBindings) {
for (const pb of symbols.paramBindings) {
if (pb.callee === orpb.callee && pb.argIndex === orpb.argIndex) {
if (!typeMap.has(orpb.restName)) {
typeMap.set(orpb.restName, { type: pb.argName, confidence: 0.65 });
}
}
}
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Phase 8.3f silently skipped in WASM engine path

symbols.paramBindings is never populated when the WASM engine is used because paramBindings is not included in SerializedExtractorOutput (or the serializeExtractorOutput function in wasm-worker-entry.ts). The condition symbols.paramBindings?.length is therefore always falsy in WASM mode, so the typeMap seeding on lines 847-851 never runs and eerest.e4() is never resolved.

The integration test in issue-1336-object-rest-param-resolution.test.ts forces engine: 'wasm' and expects the f3 → e4 edge to exist, but this seeding step is silently bypassed. PR #1348 (follow-up for serialising paramBindings) must be resolved before this code path is functional with the WASM engine, or paramBindings must be added to the WASM protocol in this PR alongside objectRestParamBindings.

Fix in Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Added paramBindings to SerializedExtractorOutput in wasm-worker-protocol.ts, serialized it in wasm-worker-entry.ts serializeExtractorOutput, and deserialized it in wasm-worker-pool.ts deserializeResult. The Phase 8.3f condition in build-edges.ts:844 now fires correctly in the WASM worker pool path.

Also updated the integration test to use a two-file fixture (callee in helpers.js, caller in main.js) so the test actually forces Phase 8.3f to be the resolution mechanism — the previous single-file fixture accidentally resolved f3→e4 via the same-file name-lookup fallback, not Phase 8.3f.

Comment on lines +847 to +851
if (pb.callee === orpb.callee && pb.argIndex === orpb.argIndex) {
if (!typeMap.has(orpb.restName)) {
typeMap.set(orpb.restName, { type: pb.argName, confidence: 0.65 });
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 First matching call-site wins; subsequent call sites with different arguments are silently dropped

The if (!typeMap.has(orpb.restName)) guard prevents seeding the rest name more than once. When the same function is called from multiple sites with different arguments — e.g. f3(objA) followed by f3(objB) — only the first matching paramBinding (whichever appears first in the array) seeds typeMap['restName']. Property calls exercised through the second call site's argument type are never resolved. This is an expected constraint of the single-typeMap model, but it means callers relying on objB's properties will silently produce no edges.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Acknowledged. The !typeMap.has(orpb.restName) guard implements first-call-site-wins semantics, which is an accepted limitation of the single-typeMap-per-file model. A comment has been added to build-edges.ts documenting this constraint and explaining that a multi-typeMap or constraint-based solver would be needed to cover all call sites. No code change is needed for this PR.

Comment on lines +1818 to +1830
fnName = nameN.text;
paramsNode =
valueN.childForFieldName('parameters') ?? findChild(valueN, 'formal_parameters');
}
}
}

if (fnName && paramsNode) {
let paramIdx = 0;
for (let i = 0; i < paramsNode.childCount; i++) {
const child = paramsNode.child(i);
if (!child) continue;
const ct = child.type;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Class methods and object-literal methods not covered

extractObjectRestParamBindingsWalk handles function_declaration, generator_function_declaration, and variable_declarator (arrow/function expressions), but not method_definition nodes inside class bodies or method shorthand inside object literals. A pattern like class Foo { bar({ a, ...rest }) { rest.m(); } } would never emit a binding for bar. This is a known scope limitation of this phase, but worth noting as a gap for follow-up if class-method patterns become relevant.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Acknowledged as a known scope limitation of Phase 8.3f. Tracked in #1357 for follow-up. Out of scope for this PR which focuses on the core function/arrow-function case.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 6, 2026

Codegraph Impact Analysis

18 functions changed18 callers affected across 6 files

  • buildCallEdgesJS in src/domain/graph/builder/stages/build-edges.ts:823 (3 transitive callers)
  • serializeExtractorOutput in src/domain/wasm-worker-entry.ts:790 (2 transitive callers)
  • deserializeResult in src/domain/wasm-worker-pool.ts:89 (1 transitive callers)
  • SerializedExtractorOutput.objectRestParamBindings in src/domain/wasm-worker-protocol.ts:67 (0 transitive callers)
  • extractSymbolsQuery in src/extractors/javascript.ts:317 (1 transitive callers)
  • extractSymbolsWalk in src/extractors/javascript.ts:605 (1 transitive callers)
  • handleVarDeclaratorTypeMap in src/extractors/javascript.ts:1467 (14 transitive callers)
  • extractObjectRestParamBindingsWalk in src/extractors/javascript.ts:1794 (3 transitive callers)
  • walk in src/extractors/javascript.ts:1798 (14 transitive callers)
  • ObjectRestParamBinding.callee in src/types.ts:574 (0 transitive callers)
  • ObjectRestParamBinding.argIndex in src/types.ts:576 (0 transitive callers)
  • ObjectRestParamBinding.restName in src/types.ts:578 (0 transitive callers)
  • ExtractorOutput.objectRestParamBindings in src/types.ts:618 (0 transitive callers)
  • e1 in tests/benchmarks/resolution/fixtures/jelly-micro/rest/rest.js:5 (0 transitive callers)
  • e2 in tests/benchmarks/resolution/fixtures/jelly-micro/rest/rest.js:8 (0 transitive callers)
  • e3 in tests/benchmarks/resolution/fixtures/jelly-micro/rest/rest.js:11 (0 transitive callers)
  • e4 in tests/benchmarks/resolution/fixtures/jelly-micro/rest/rest.js:14 (2 transitive callers)
  • f3 in tests/benchmarks/resolution/fixtures/jelly-micro/rest/rest.js:22 (1 transitive callers)

@carlos-alm
Copy link
Copy Markdown
Contributor Author

Superseded by #1355 which includes both WASM and native engine implementations in one self-contained PR.

@carlos-alm carlos-alm closed this Jun 6, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 6, 2026
… Phase 8.3f (#1350)

paramBindings was missing from SerializedExtractorOutput, wasm-worker-entry.ts
serializeExtractorOutput, and wasm-worker-pool.ts deserializeResult. Without it,
build-edges.ts Phase 8.3f typeMap seeding (line 844) was never triggered in the
WASM engine path — symbols.paramBindings was always undefined after deserialization.
Closes the gap identified in the PR #1350 review.
…irst-call-site-wins (#1350)

- Extract magic 0.65 into REST_BINDING_CONFIDENCE constant in javascript.ts,
  per CLAUDE.md convention for behavioral constants
- Add comment in build-edges.ts documenting the first-call-site-wins limitation
  of the single-typeMap model
…tion mechanism (#1350)

The previous single-file fixture resolved f3→e4 via the same-file name-lookup
fallback, not through Phase 8.3f typeMap seeding. The updated fixture defines e4
in helpers.js (imported) so the same-file fallback cannot trigger: the edge must
be produced by Phase 8.3f cross-referencing objectRestParamBindings with
paramBindings from the WASM worker output.
@carlos-alm
Copy link
Copy Markdown
Contributor Author

Addressed all feedback from the Claude and Greptile reviews:

C1 / Greptile P1 — paramBindings not serialized through WASM worker boundary:
Fixed. Added paramBindings to SerializedExtractorOutput, serializeExtractorOutput, and deserializeResult. Phase 8.3f typeMap seeding now fires in the WASM worker pool path.

The integration test was also updated to use a two-file fixture (callee defined in helpers.js, caller in main.js). The previous single-file test accidentally resolved f3→e4 via the same-file name-lookup fallback — not Phase 8.3f. The new test forces the edge to come from Phase 8.3f by ensuring e4 is not in the same file as the call site, validating that the WASM worker boundary fix actually works end-to-end.

C4 / CLAUDE.md — 0.65 magic constant:
Fixed. Extracted to REST_BINDING_CONFIDENCE = 0.65 in javascript.ts with a doc comment explaining the rationale. Imported and used in build-edges.ts.

Greptile P2 — First-call-site-wins:
Documented with a comment in build-edges.ts explaining the constraint and what a full fix would require.

Greptile P2 — Class methods not covered:
Deferred to #1357 (out of scope for this PR).

@carlos-alm
Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm
Copy link
Copy Markdown
Contributor Author

@claude

@carlos-alm carlos-alm reopened this Jun 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(resolver): resolve property calls on object destructuring rest parameters (JS)

1 participant