Skip to content

TypeScript/JavaScript literal receivers bind a confident false edge — "x".replace() hits an unrelated user function (#59) #163

Description

@joyful-ii-V-I

What is wrong

In every TypeScript and JavaScript codebase ripwire indexes, a built-in method call can link to an
unrelated user function that happens to share its name. "a-b".replace(…), [3, 1, 2].map(…) and
/x/.test(s) all do it. The graph's ambiguity gauge stays at zero, so the wrong edge reads as
confident, and an agent is sent to code that never runs. This is issue #59.

An earlier fix vetoed built-in method names wholesale and was backed out, because it deleted true
edges: on webpack, --callers=stringify went from 361 to 0. The safe first step is to decide by the
receiver's type, not its name — starting with receivers whose type the syntax already proves,
which is to say literals. Everything else keeps today's behaviour.

The evidence

test/fieldnarrowcheck.sh carries a KNOWN GAP block on a freshly generated fixture, rewritten
minimally from #59's own reproduction:

  • Five arms pin today's wrong behaviour — a string, a template, an array, a regex, and a chain
    starting from a string literal. Each binds an unrelated function in src/unrelated.ts, with
    graph_ambiguous="0". They pass today. Flipping them is the finish line.
  • Two controls pin true edges any fix must keep: a typed user-object receiver r.replace() binding
    Rewriter.replace, and "x".shout() binding the repo's own String.prototype.shout.
  • A presence guard keeps the block from passing vacuously.

Confirm the arms pass today with bash test/fieldnarrowcheck.sh on a plain dev build.

Size

Medium. The code is small: a receiver classification at extraction (an append-only enum, with a
version bump and its mirror) and one resolver arm. Most of the work is measurement — establishing
the full population of edges the change removes on a real corpus, not a sample. webpack is the
historical corpus for this one.

Where to start

prompts/help-wanted/ts-literal-receivers.md is a self-contained prompt for a coding agent. It
carries why this matters, the file pointers, the rejected attempt and why it failed, the
reproductions, the design space and constraints, the acceptance criteria, the known traps — every
one of them measured on main while the kit was written — and what the fix PR's description should
contain. Like every prompt in prompts/, it ends by writing a plan and stopping — a maintainer
agrees the plan before any code is written.

Nothing else has to merge first; the gap is on main today.

Comment here to claim it.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions