Repository navigation
fix(typescript): recognise CommonJS exports, and widen the labels gate - #73
Merged
Merged
Conversation
Most of npm is still CommonJS, where nothing carries the ESM `export` keyword.
The front-end set is_public only from `export`, so every CommonJS file reported
zero public symbols: the declarations were parsed, then discarded as private,
and the file contributed no seams at all.
Found by pointing `detect --language typescript` at commander, where lib/ — the
whole implementation, including the documented Command and Help classes —
produced nothing, and the ranking was made up entirely of type declarations from
typings/index.d.ts.
Now `exports.X = X`, `module.exports.X = X`, `module.exports = X` and
`module.exports = { X, Y }` mark the named declarations public. A class that is
never exported stays private.
The self-check earned its keep immediately: it caught that the first version of
this fix missed `module.exports.Help = Help`, a three-level member expression
where the object is itself `module.exports`.
Also widens the benchmark-labels gate. It refused a PR touching both the ground
truth and detector.py/graph.py, but a language front-end decides what even
becomes a candidate — so a front-end change can flatter a score exactly as a
weight change can. The gate now covers modscan/languages/ too. This commit is
itself the case in point: it changes a front-end, so it deliberately carries no
label change.
Python benchmark unchanged at 9/20 (this touches no Python path); suite 25/25.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
MODScan attack-surface diff —
|
MODScan extension-point diffNo breaking changes to extension points |
Rinkia
added a commit
that referenced
this pull request
Jul 23, 2026
Bump to 0.1.7 and move the [Unreleased] entries under [0.1.7]. Ships the Java front-end, the security lens over MCP and for TypeScript/JavaScript, the process sinks the Bandit cross-check exposed, and two TypeScript front-end fixes. Also adds the two CHANGELOG entries that were missing: recognising CommonJS exports (#73) and no longer scanning .d.ts declaration files (#76). Both change what `--language typescript` returns, so both belong in a user-facing changelog. The cross-check harnesses (#70, #72) and benchmark targets (#74, #78) stay out: they are repository artifacts, not shipped in the wheel. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
Most of npm is still CommonJS, where nothing carries the ESM
exportkeyword. The front-end setis_publiconly fromexport, so every CommonJS file reported zero public symbols — declarations parsed, then discarded as private, contributing no seams at all.Found while starting #63 (TS moddability benchmark): pointing
detect --language typescriptat commander produced a ranking made entirely of type declarations fromtypings/index.d.ts, whilelib/— the whole implementation, including the documentedCommandandHelpclasses — yielded nothing.The fix
exports.X = X,module.exports.X = X,module.exports = Xandmodule.exports = { X, Y }now mark the named declarations public. A class that is never exported stays private.After the fix, commander's
lib/surfacesCommand,Help,Option,Argumentas it should.The self-check earned its keep immediately — it caught that my first version missed
module.exports.Help = Help, a three-level member expression where the object is itselfmodule.exports.Also: widening the benchmark-labels gate
The gate refused a PR touching both the ground truth and
detector.py/graph.py. But a language front-end decides what even becomes a candidate, so a front-end change can flatter a score exactly as a weight change can. It now coversmodscan/languages/too.This PR is the case in point: it changes a front-end, so it deliberately carries no label change. The commander labels land separately, on their own evidence.
Known, not fixed here
With
lib/now visible, commander's top 8 are still TS interfaces (ParseOptions,HelpContext,OutputConfiguration) scoring 0.70 as "meant to be subclassed", above the actually-documentedCommand/Helpat 0.10.interface → abstractis a deliberate choice in the front-end and is a ranking question — so it gets measured against a benchmark, not asserted. That's the next PR's job.Test plan
tests/test_typescript.py: new CommonJS case —exports.X,module.exports.Xrecognised; never-exported class stays private; exported/private functions distinguished. Skips cleanly without tree-sitter.ci.ymlparses.🤖 Generated with Claude Code