Skip to content

fix(extractors): unwrap computed property keys in object-literal key resolution#1945

Closed
carlos-alm wants to merge 1 commit into
fix/issue-1763-busytimeout-readonly-wiringfrom
fix/issue-1764-object-literal-computed-method-keys-extract
Closed

fix(extractors): unwrap computed property keys in object-literal key resolution#1945
carlos-alm wants to merge 1 commit into
fix/issue-1763-busytimeout-readonly-wiringfrom
fix/issue-1764-object-literal-computed-method-keys-extract

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Fixes #1764

Bug

extractObjectLiteralFunctions's pair branch only stripped quotes for plain string-typed keys. For a computed string-literal key like { ['foo']: () => {} }, the key node type is computed_property_name, so it fell through to the raw bracket/quote text, producing obj.['foo'] instead of obj.foo. Call sites like obj.foo() could never resolve to it. Reproduced identically on both engines.

Fix

Auditing the codebase turned up the identical bug pattern duplicated across five other key-resolution call sites in the JS/TS extractor (typeMap seeding for object literals, Object.defineProperties, Object.create/prototype-literal seeding, prototype assignment), and mirrored in the native Rust extractor. Per the project's "best architecture over smallest diff" guidance, I added one shared helper per engine — resolvePropertyKeyName (WASM/TS) and resolve_property_key_name (native/Rust) — that unwraps computed_property_name string literals the same way the existing resolveMethodDefinitionName / resolve_method_def_name already did for method_definition name nodes, and switched all six affected call sites in each engine to use it. This fixes the whole bug class identically in both engines instead of leaving four latent copies of the same defect behind.

Non-string computed keys (e.g. [Symbol.iterator]) are skipped rather than producing a garbage name, matching the existing method_definition behavior.

Out of scope

Found a separate, distinct bug while auditing this code: resolveMethodDefinitionName/resolve_method_def_name don't strip quotes for non-computed quoted string keys ({ 'foo'() {} }A.'foo' instead of A.foo). Filed as #1944, not fixed here.

Validation

  • New unit tests in tests/parsers/javascript.test.ts covering the pair branch (arrow/function values, non-string computed keys).
  • New integration test tests/integration/issue-1764-computed-objlit-key.test.ts exercising both WASM and native engines end-to-end (build graph, verify plain node name, verify call edge resolves, verify no bracketed names leak).
  • New Rust unit tests in crates/codegraph-core/src/extractors/javascript.rs covering extract_object_literal_functions, extract_js_prototype_object_literal, and seed_descriptor_object with computed keys.
  • Manually reproduced the issue's exact repro (codegraph where --file sample.js -T --json) with both --engine native and --engine wasm before and after the fix — both now report obj.foo identically.
  • Full suite: npm test (214 files, 3550 passed), cargo test --release (451 passed), npm run lint clean, npm run build clean.
  • codegraph diff-impact --staged -T confirmed the blast radius matched intent: the 5 fixed call sites plus the new shared helper, 21 transitive callers, no unexpected files touched.

…resolution

Object-literal computed string-literal keys (`{ ['foo']: () => {} }`) were
extracted as the literal bracketed/quoted text (`obj.['foo']`) instead of the
plain property name (`obj.foo`), since the `pair` key resolution only handled
plain `string`-typed keys and fell through to raw node text for
`computed_property_name` nodes. Call sites like `obj.foo()` could never
resolve to the emitted definition.

The identical bug pattern was duplicated across five other key-resolution call
sites in the JS/TS extractor (typeMap seeding, Object.defineProperties,
Object.create/prototype-literal seeding, prototype assignment) and mirrored in
the native Rust extractor. Added a shared `resolvePropertyKeyName` (WASM) /
`resolve_property_key_name` (native) helper — mirroring the existing
`resolveMethodDefinitionName` / `resolve_method_def_name` treatment of
`method_definition` name nodes — and switched all affected call sites to use
it, fixing the whole bug class in both engines identically.

Impact: 6 functions changed, 21 affected
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

6 functions changed21 callers affected across 1 files

  • extractObjectLiteralFunctions in src/extractors/javascript.ts:1287 (8 transitive callers)
  • resolvePropertyKeyName in src/extractors/javascript.ts:2099 (17 transitive callers)
  • handleObjectLiteralTypeMap in src/extractors/javascript.ts:2484 (3 transitive callers)
  • handleDefinePropertyTypeMap in src/extractors/javascript.ts:2699 (7 transitive callers)
  • seedProtoProperties in src/extractors/javascript.ts:2796 (3 transitive callers)
  • extractPrototypeObjectLiteral in src/extractors/javascript.ts:4181 (7 transitive callers)

@greptile-apps

greptile-apps Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Fixes a key-resolution bug in both WASM/TS and native/Rust JS extractors where computed string-literal object-literal keys (e.g., ['foo']: () => {}) were stored as obj.['foo'] instead of obj.foo, preventing call-site resolution. The fix centralizes the unwrapping logic into a single resolvePropertyKeyName / resolve_property_key_name helper per engine, applied consistently across six previously duplicated call sites in each engine.

  • Adds resolvePropertyKeyName (TS) and resolve_property_key_name (Rust) helpers mirroring the existing resolveMethodDefinitionName/resolve_method_def_name pattern; non-string computed keys (e.g., [Symbol.iterator]) are correctly skipped.
  • Applies the helper uniformly to extractObjectLiteralFunctions, handleObjectLiteralTypeMap, handleDefinePropertyTypeMap, seedProtoProperties, extractPrototypeObjectLiteral, and match_js_objlit_qualified_method_defs — eliminating the previous per-site inline pattern.
  • As a side-effect, handleDefinePropertyTypeMap and seedProtoProperties (TS) now correctly skip empty/non-resolvable computed keys, where the old code would have propagated a garbage key like obj.[Symbol.iterator] into the type map.

Confidence Score: 5/5

Safe to merge — well-scoped extraction fix with symmetric dual-engine helpers, comprehensive unit and integration test coverage, and no mutations to data-store schema or public APIs.

All six previously duplicated inline key-resolution patterns are replaced by a single helper per engine that is demonstrably equivalent for existing cases and correct for the newly fixed computed-string case. The !key guard additions in handleDefinePropertyTypeMap and seedProtoProperties close a real gap where garbage type-map entries could have been inserted. Test coverage for both engines is thorough.

No files require special attention.

Important Files Changed

Filename Overview
src/extractors/javascript.ts Adds resolvePropertyKeyName helper and replaces five inline key-resolution patterns across object-literal pair, typeMap, defineProperties, protoProperties, and prototype-literal call sites; also fixes missing !key guard in handleDefinePropertyTypeMap and seedProtoProperties.
crates/codegraph-core/src/extractors/javascript.rs Adds resolve_property_key_name Rust helper and replaces five inline key-resolution patterns; adds four targeted regression unit tests.
tests/integration/issue-1764-computed-objlit-key.test.ts New integration test exercising both WASM and native engines end-to-end; verifies plain node name storage, absence of bracket-leaked names, and call-edge resolution.
tests/parsers/javascript.test.ts Adds four unit tests covering computed arrow-function and function-expression pair extraction, absence of bracket-leaked names, and skipping of non-string computed keys.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Object-literal pair key node] --> B{key node type}
    B -->|computed_property_name| C[Get inner node at index 1]
    C --> D{inner node type}
    D -->|string| E[strip quotes via extract_string_fragment]
    D -->|string_fragment| F[use text as-is]
    D -->|other e.g. member_expression| G[return None or empty string]
    B -->|string| H[strip surrounding quotes]
    B -->|identifier etc.| I[use text as-is]
    E --> J[qualify as varName.plainName]
    F --> J
    H --> J
    I --> J
    J --> K[emit Definition / TypeMapEntry / prototype method]
    G --> L[skip — no emission]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Object-literal pair key node] --> B{key node type}
    B -->|computed_property_name| C[Get inner node at index 1]
    C --> D{inner node type}
    D -->|string| E[strip quotes via extract_string_fragment]
    D -->|string_fragment| F[use text as-is]
    D -->|other e.g. member_expression| G[return None or empty string]
    B -->|string| H[strip surrounding quotes]
    B -->|identifier etc.| I[use text as-is]
    E --> J[qualify as varName.plainName]
    F --> J
    H --> J
    I --> J
    J --> K[emit Definition / TypeMapEntry / prototype method]
    G --> L[skip — no emission]
Loading

Reviews (1): Last reviewed commit: "fix(extractors): unwrap computed propert..." | Re-trigger Greptile

@carlos-alm

Copy link
Copy Markdown
Contributor Author

Closing — this duplicates already in-progress work on #1885 for the same issue (#1764). Continuing the existing stacked chain (#1885#1939) instead of a competing branch.

@carlos-alm carlos-alm closed this Jul 7, 2026
@carlos-alm carlos-alm deleted the fix/issue-1764-object-literal-computed-method-keys-extract branch July 7, 2026 08:20
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 7, 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.

1 participant