From 7eabdd46d6c1b60cac14c8f3a4a14e22efb0eee6 Mon Sep 17 00:00:00 2001 From: ReidenXerx Date: Thu, 6 Aug 2026 00:01:04 +0300 Subject: [PATCH] test(javascript): pin A1/A5 plain-object property acceptance criteria MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixture plus todo specs for the four shapes plain-object property access has to answer: object-literal keys indexed as Property nodes, a read through the holding variable, a property WRITE, and a read through an untyped param. Records the investigation so the work is resumable: the parse-query pattern scoped to literals bound to a variable matches correctly (verified against the raw JAVASCRIPT_QUERIES), but no Property node reaches the graph and local-symbol-pruner is not the cause — it drops only Const/Variable/Static. The remaining gate is in the parse worker's node-creation path. No production code — specs only, so the suite stays green. Co-Authored-By: Claude Opus 5 (1M context) --- .../javascript-object-properties/rules.js | 20 +++++++ .../javascript-object-properties.test.ts | 54 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 gitnexus/test/fixtures/lang-resolution/javascript-object-properties/rules.js create mode 100644 gitnexus/test/integration/resolvers/javascript-object-properties.test.ts diff --git a/gitnexus/test/fixtures/lang-resolution/javascript-object-properties/rules.js b/gitnexus/test/fixtures/lang-resolution/javascript-object-properties/rules.js new file mode 100644 index 000000000..15b3a7929 --- /dev/null +++ b/gitnexus/test/fixtures/lang-resolution/javascript-object-properties/rules.js @@ -0,0 +1,20 @@ +// A1/A5: a plain object literal held by a module const — no class anywhere. +export const exitRules = { + exitMinAtrMult: 1.5, + stopAtrMult: 2.0, +}; + +// A5: property WRITE on a plain object (the "where is this field SET?" case). +export function tightenExit() { + exitRules.exitMinAtrMult = 3.0; +} + +// A1: property READ through the holding variable — receiver IS typeable. +export function readViaVariable() { + return exitRules.exitMinAtrMult; +} + +// A1: property READ through an untyped param (the option-bag case). +export function applyRules(cfg) { + return cfg.exitMinAtrMult * cfg.stopAtrMult; +} diff --git a/gitnexus/test/integration/resolvers/javascript-object-properties.test.ts b/gitnexus/test/integration/resolvers/javascript-object-properties.test.ts new file mode 100644 index 000000000..2bea184d1 --- /dev/null +++ b/gitnexus/test/integration/resolvers/javascript-object-properties.test.ts @@ -0,0 +1,54 @@ +/** + * A1/A5 — property access on a PLAIN OBJECT LITERAL must be answerable. + * + * Verified root cause: `Property` definition nodes are created only for + * DECLARED CLASS FIELDS. Object-literal keys mint no node, so `ACCESSES` has + * no target and "who reads/writes this config field?" returns a confident + * zero. Capture and emission are already correct and language-neutral — a + * `read`/`write` site maps to `ACCESSES` for any resolved target — so this is + * purely definition-node coverage plus receiver resolution. + * + * Two receiver shapes, deliberately separated: + * - through the holding variable (`exitRules.exitMinAtrMult`) — the receiver + * is typeable, so this must resolve precisely. + * - through an untyped param (`cfg.exitMinAtrMult`) — the option-bag shape + * that dominates idiomatic JS. Not precisely solvable without types; + * covered by name-based fallback at reduced confidence. + * + * STATUS — not yet implemented; these are the acceptance criteria. + * + * Established so far: + * - A parse-query pattern scoped to object literals BOUND TO A VARIABLE + * (`(variable_declarator name: (identifier) value: (object (pair key: + * (property_identifier) @name) @definition.property))`) matches correctly: + * verified against the raw JAVASCRIPT_QUERIES, 4 captures on this fixture + * with the right names. It is NOT enough on its own — no `Property` node + * reaches the graph, and `local-symbol-pruner` is not the cause (it drops + * only Const/Variable/Static). The remaining gate is in the parse worker's + * node-creation path for `@definition.property` captures. + * - The two receiver shapes need different mechanisms. Through the holding + * variable the receiver is typeable and must resolve precisely. Through an + * untyped param it is not, and needs name-based matching — sanctioned for + * dynamic languages here (`fieldFallbackOnMethodLookup` defaults on, and + * the Vue provider documents it recovering plain-object-literal cases) but + * it must carry reduced confidence so precision is not overclaimed. + */ +import { describe, it, beforeAll } from 'vitest'; +import path from 'path'; +import { FIXTURES, runPipelineFromRepo, type PipelineResult } from './helpers.js'; + +describe('JavaScript plain-object property access (A1/A5)', () => { + let result: PipelineResult; + + beforeAll(async () => { + result = await runPipelineFromRepo( + path.join(FIXTURES, 'javascript-object-properties'), + () => {}, + ); + }, 60000); + + it.todo('indexes object-literal keys as Property nodes'); + it.todo('emits ACCESSES for a read through the holding variable'); + it.todo('emits ACCESSES for the property WRITE (A5)'); + it.todo('emits ACCESSES for a read through an untyped param (option bag)'); +});