Commit ec78d95
authored
feat(resolver): resolve this-dispatch inside Object.defineProperty accessor functions (JS) (#1351)
* feat(resolver): resolve this-dispatch inside Object.defineProperty accessor functions (JS)
Closes #1335
When a function is registered as a `get`/`set` accessor via
`Object.defineProperty(obj, key, { get: getter })`, `this` inside
`getter` equals `obj`. Codegraph previously emitted no edge for
`this.method()` calls inside such accessors when the callee was
defined as an object literal property.
Three layered mechanisms introduced:
1. **Object literal function extraction** — `const obj = { baz: () => {} }`
now extracts `baz` as a named `function` definition (WASM query path via
`extractConstDeclarators`, walk path via `handleVariableDecl`, Rust path
via `extract_object_literal_functions`). This makes the callee visible to
the same-file definition lookup used by `resolveCallTargets` step 2.
2. **Composite typeMap seeding for object literal properties** —
`typeMap['obj.baz'] = 'baz'` seeded for shorthand properties
(`{ baz }`), identifier values (`{ baz: fn }`), and inline
function/arrow values. Enables the accessor receiver path.
3. **Accessor receiver tracking** — `Object.defineProperty(obj, key, { get: getter })`
seeds `typeMap['getter:this'] = 'obj'`. `resolveByMethodOrGlobal` (WASM/TS)
and `resolve_call_targets` (Rust) check this entry first for plain-function
callers (no class prefix), then look up `typeMap['obj.method']` to reach
the concrete target — providing precision over the broad same-file fallback.
Benchmark impact:
- Jelly micro-test `accessors3`: 0% -> 100% recall (TP=1, FP=0, FN=0)
- JS fixture `define-property-accessor.js`: new edge `accessorGetter -> accessMethod`
- JS benchmark total expected edges: 33 -> 34 (precision 1.0 maintained, recall >= 0.9)
* fix(wasm-worker): wire paramBindings, returnTypeMap, callAssignments through worker boundary
These three ExtractorOutput fields were populated by the JS/TS extractor
but never included in SerializedExtractorOutput, causing them to be silently
dropped when results crossed the Worker thread boundary. The main thread
always received undefined for these fields regardless of what the worker
computed, breaking cross-file return-type propagation, param binding
resolution, and call-assignment tracking in the WASM engine.
Fixes #1348
* Revert "fix(wasm-worker): wire paramBindings, returnTypeMap, callAssignments through worker boundary"
This reverts commit 6402681.
* fix(resolver): add empty-string guard to Rust caller_name check for accessor this-dispatch (#1351)
Parity with the TypeScript guard: `callerName && !callerName.includes('.')`.
When caller_name is empty the key would be ':this' which is never seeded,
so no incorrect edge is produced today — but adding the guard removes the
latent risk and makes the two engines explicitly equivalent.
* fix(resolver): qualify object literal defs and seed all get/set accessors (#1351)
Two fixes:
1. findDescriptorAccessors (TS) / find_descriptor_accessors (Rust): changed from
returning the first accessor to returning all of them. For { get: getter, set: setter },
both 'getter:this = obj' and 'setter:this = obj' are now seeded so both functions
can resolve this-dispatch via Phase 8.3f.
2. extractObjectLiteralFunctions (TS) / extract_object_literal_functions (Rust): definitions
are now emitted under qualified names ('obj.baz' instead of bare 'baz') to avoid
polluting the global definition index with common property names that could produce
false-positive edges via the broad exact-name fallback. The typeMap value for
function/arrow entries is also updated to the qualified name so the resolver calls
lookup.byName('obj.baz'). Also adds complexity metrics for method_definition nodes
in the Rust branch (parity with the pair branch which already computed them).
* fix(resolver): clarify scope guard and :this key convention in accessor this-dispatch (#1351)
- Add comment to extractConstDeclarators explaining that the function-scope guard
is upheld by the caller (extractConstantsWalk) — future refactors must add a
hasFunctionScopeAncestor check before calling extractObjectLiteralFunctions from
any other context.
- Add comment at the setTypeMapEntry call noting that ':' is a reserved separator for
Phase 8.3f keys and cannot collide with real JS identifier names.
* fix(bench): use qualified node name accessorTarget.accessMethod in JS expected-edges (#1351)
The graph registers object literal arrow properties under qualified names
(e.g. 'accessorTarget.accessMethod' not bare 'accessMethod') since
extractObjectLiteralFunctions was updated to avoid polluting the global
definition index. The expected edge must match the stored node name so
the precision check passes for both WASM and native engines.
* fix(extractor): scope guard for object literal walk path and jelly-micro target names (#1351)
Two fixes:
1. handleVariableDecl (walk path): add !hasFunctionScopeAncestor(node) guard before
calling extractObjectLiteralFunctions, matching the Rust path's find_parent_of_types
check and the sibling destructured-binding branch. Without the guard, const object
literals inside function bodies registered their qualified properties (e.g. localObj.fn)
into the global definition index.
2. jelly-micro accessors3/expected-edges.json: update target name from bare 'baz' to
qualified 'obj.baz' to match the actual node name stored by extractObjectLiteralFunctions.
recall was 0% (TP=0) since qualified names were introduced; now recall=100%.
* fix(extractor): seed typeMap entry for method-shorthand object properties (#1351)
Method-shorthand properties (`const obj = { baz() {} }`) produced a
qualified definition `obj.baz` via extractObjectLiteralFunctions but no
matching typeMap entry. The two-step Phase 8.3f lookup
(callerName:this → obj → obj.baz) would find the typeMap key but then
lookup.byName('obj.baz') would fail because no typeMap['obj.baz'] was
ever seeded. Add a method_definition branch in handleVarDeclaratorTypeMap
(TS) and in extract_object_literal_functions (Rust) to seed
typeMap['obj.baz'] = 'obj.baz', matching the pair (arrow/function) branch.
* chore: include ROADMAP.md updates from main merge (#1351)
* fix(extractor): add scope guard to object-literal typeMap seeding and fix phase label (#1351)
- Add !hasFunctionScopeAncestor(node) guard to the object-literal seeding block in
handleVarDeclaratorTypeMap, matching Rust handle_var_decl's find_parent_of_types check.
Prevents function-scoped const obj = { fn: ... } from seeding typeMap entries that could
shadow module-level declarations with the same property names.
- Fix Phase 8.3g → Phase 8.3f label in resolution-benchmark.test.ts comment (all
implementation files use Phase 8.3f; the test comment was inconsistent).1 parent 428edb4 commit ec78d95
9 files changed
Lines changed: 409 additions & 13 deletions
File tree
- crates/codegraph-core/src
- extractors
- src
- domain/graph/builder
- extractors
- tests/benchmarks/resolution
- fixtures
- javascript
- jelly-micro/accessors3
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
457 | 457 | | |
458 | 458 | | |
459 | 459 | | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
| 480 | + | |
460 | 481 | | |
461 | 482 | | |
462 | 483 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
231 | 231 | | |
232 | 232 | | |
233 | 233 | | |
234 | | - | |
| 234 | + | |
235 | 235 | | |
236 | 236 | | |
237 | 237 | | |
238 | 238 | | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
245 | 255 | | |
246 | 256 | | |
247 | 257 | | |
| |||
349 | 359 | | |
350 | 360 | | |
351 | 361 | | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
| 477 | + | |
| 478 | + | |
| 479 | + | |
352 | 480 | | |
353 | 481 | | |
354 | 482 | | |
| |||
837 | 965 | | |
838 | 966 | | |
839 | 967 | | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
840 | 975 | | |
841 | 976 | | |
842 | 977 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
134 | 163 | | |
135 | 164 | | |
136 | 165 | | |
| |||
0 commit comments