Repository navigation
Description
Methods defined the classic JavaScript way, Ctor.prototype.m = function () {…}, get no node. The calls inside them are attributed to the file, and this.m() between them resolves by bare name to whatever else in the project is called m: an unrelated function in another file, or an interface method in a .d.ts.
// lib/hooks.js
'use strict'
function Hooks () { this.list = [] }
Hooks.prototype.validate = function (hook, fn) { return typeof fn === 'function' }
Hooks.prototype.add = function (hook, fn) {
this.validate(hook, fn) // line 5
this.list.push(fn)
}
module.exports = Hooks
// lib/validation.js
function validate (schema, data) { return true }
module.exports = { validate }
// lib/reply.js
function Reply () {}
Reply.prototype.getHeader = function (k) { return k }
Reply.prototype.send = function () { return this.getHeader('content-type') } // line 3
module.exports = Reply
// lib/types.d.ts
export interface FastifyReply { getHeader(key: string): string | undefined; }on main |
expected | |
|---|---|---|
nodes for Hooks.prototype.validate, .add, Reply.prototype.getHeader, .send |
none | a method node each (on Hooks / Reply) |
this.validate(hook, fn) (line 5) |
hooks.js (file) → validate in lib/validation.js (exact-match) ✗ |
add → Hooks.prototype.validate |
this.getHeader(…) (line 3) |
reply.js (file) → FastifyReply.getHeader in types.d.ts (exact-match) ✗ |
send → Reply.prototype.getHeader |
Reproduced on main at 72f398a, with CODEGRAPH_KERNEL=0 and with the native kernel. Linux/WSL2, Node 22.23.2.
Where it shows up. fastify (5df959f) defines its request/reply/hooks API this way: 35 X.prototype.m = function methods in lib/, for example Reply.prototype.header, .getHeader, .send and .compileSerializationSchema. None of them are in the graph as methods. Their internal this.m() calls show up as calls from the file to the type declarations (types/reply.d.ts) or to same-named helpers elsewhere (lib/hooks.js:69 this.validate(…) → lib/validation.js). Older Node libraries and much of npm's CommonJS code still define classes like this.
Same root, two more shapes (both reproduced on 72f398a with CODEGRAPH_KERNEL=0):
Static methods assigned to the constructor. The function expressions are indexed as plain functions, not as members of Model, so Model.x() doesn't reach them:
// lib/model.js
function Model () {}
Model.insertMany = async function insertMany (arr) { return arr }
Model.init = function init () { return Model.insertMany([]) } // → Cast.insertMany in lib/other.js ✗
module.exports = Model
// lib/other.js
class Cast { init () { return 1 } insertMany () { return 2 } }
// test/model.test.js
const Model = require('../lib/model')
async function t () { await Model.init(); await Model.insertMany([1]) } // → links the `Model` constructor onlymongoose (f59e13a) defines its model API this way (Model.insertMany, Model.init, Model.validate, Model.discriminator, … in lib/model.js). Those calls land on types/models.d.ts declarations or on other classes' same-named methods.
Methods of an object literal assigned to module.exports. They get no node, and this.m() inside links to another file's m:
// lib/context.js
module.exports = {
inspect () { return this.toJSON() }, // → Application.toJSON in lib/application.js ✗
toJSON () { return {} }
}koa (b786e7b) writes context, request and response like this. lib/context.js this.toJSON() links to lib/application.js's toJSON.
Expected. Index X.prototype.m = function () {} (and = async function, = () => {}) as a method m of X when X is a function or class in the file. Attribute calls inside it to that method, and resolve this.m() inside it against X's members first, never by bare name across files.
Related: #1771 (exports.x = function indexed as a function), #2954 / #2958 (other this./self. calls that fall through to an unrelated same-named function).
Edited 2026-11-04: re-checked on main at f72c9d2 (with CODEGRAPH_KERNEL=0 and with the native kernel, Node 22.22.2): still reproduces. Corrected two slips: the this.getHeader call is on line 3 of the snippet, not line 4, and the Model test links the Model constructor (not init or insertMany) rather than nothing. Related: #3171 (stops one lone-method guess, doesn't index these members) and #2300 (object-literal members get no node).
Activity