You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
JavaScript: every mod.x() through a CommonJS require links to the module's one anonymous exports.y = function #2952
In a CommonJS module that assigns functions to exports.x, an anonymous function expression is indexed as exported but a named one isn't. A caller that does const mod = require('./mod'); mod.anything() then links every member call to the one anonymous export, through the "first exported function" default fallback. Calls to the named exports get no edge.
// lib/utils.jsfunctioncreateETagGenerator(options){returnfunctiongenerateETag(body){returnbody;};}exports.etag=createETagGenerator({weak: false});exports.normalizeType=function(type){returntype;};// line 4, anonymousexports.compileTrust=functioncompileTrust(val){returnval;};// line 5, named// test/utils.jsvarutils=require('../lib/utils');functiont(){utils.etag('x');utils.compileTrust(1);utils.missing();}module.exports=t;
call
edge on main
expected
utils.etag('x')
normalizeType (resolvedBy: import) ✗
none (a value, not a declared function)
utils.compileTrust(1)
normalizeType ✗
compileTrust
utils.missing()
normalizeType ✗
none
The indexed nodes show why:
function normalizeType lib/utils.js:4 isExported=1
function compileTrust lib/utils.js:5 isExported=0
With only the named form (exports.a = function a() {} for every export) there are no wrong edges, but utils.a() doesn't link to a either. const vs var makes no difference.
Reproduced on main at 2577601 with CODEGRAPH_KERNEL=0. Linux/WSL2, Node 22.23.2. Not fixed by #2754 or #2800 (I ran this fixture on both heads).
Where it shows up. express (1c6f1b0) writes lib/utils.js this way: exports.normalizeType = function(type){…} and exports.compileTrust = function(val){…} are anonymous, and exports.etag = createETagGenerator(…) is a value. In test/utils.js (var utils = require('../lib/utils')), utils.etag(…) links to normalizeType.
Separately, the default fallback (the first exported function when the module has no export default) shouldn't answer a member call through a require binding: mod.x() reads property x, not the default. Fixing 1 alone makes this worse, because the fallback then has more functions to pick from. fix: unify export-status detection and fix ambient export handling (#1721) #2896 shows the same thing for module.exports = { … } modules.
Related: #2189 (calls through CommonJS require bindings), #2432 (ES default imports no longer take the first exported function), #1721, #2896.
Activity