feat(check): flag __dirname/__filename and suggest ESM path APIs#590
feat(check): flag __dirname/__filename and suggest ESM path APIs#590james-elicx merged 6 commits intomainfrom
Conversation
Closes #583 Scan server source files for free uses of the CJS globals __dirname and __filename and report them as a partial compatibility issue in the vinext check output. Uses a single-pass alternation regex that skips string literals, template literals, and comments in one pass, so identifiers inside those tokens are never matched.
commit: |
|
|
/bigbonk review |
There was a problem hiding this comment.
Good feature — clean implementation, well-tested, and the single-pass alternation regex is a reasonable approach for an advisory scanner. A few observations:
The template expression blind spot is worth knowing about. The template literal branch treats ${...} interpolations as literal content, so `${__dirname}/views` won't be detected. This is the most natural path-building idiom in CJS code (`${__dirname}/templates`), so it's a meaningful false negative for the feature's purpose. Not necessarily a blocker since this is an advisory check, but worth deciding whether to address now or file an issue for later.
The rest of the edge cases (regex literals, property access like obj.__dirname, the ESM reassignment idiom) are minor and acceptable for a migration compatibility scanner.
Tests are thorough and cover the important cases well.
Co-authored-by: james-elicx <james-elicx@users.noreply.github.com>
|
Review posted. Here's a summary of what I found: PR #590 Review Summary The implementation is clean and well-tested. The single-pass alternation regex is a solid approach for an advisory scanner — it correctly skips Key finding: The template literal branch has a blind spot for Other minor edge cases (regex literals, Tests: All 79 tests pass. The 7 new tests cover the important positive and negative cases well. |
…r match
The previous template literal skip branch consumed `${...}` bodies as
literal content, so __dirname in e.g. `${__dirname}/views` was silently
skipped.
Change the template branch to stop at ${ boundaries by excluding $ from
the non-interpolation character class: [^`\\$]. A bare $ not followed
by { is still allowed via |$(?!\{). This means the ${...} body is never
consumed by the skip branch and __dirname inside template expressions is
correctly caught by the identifier branch.
Adds two new tests: one verifying plain template content (no interpolation)
is still ignored, one verifying __dirname inside ${} is detected.
|
/bigbonk review |
|
UnknownError: "Overloaded" |
|
@james-elicx Bonk workflow failed. Check the logs for details. View workflow run · To retry, trigger Bonk again. |
|
/bigbonk review |
|
UnknownError: "Overloaded" |
|
/bigbonk review |
|
UnknownError: "Overloaded" |
|
/bigbonk review |
|
UnknownError: "Overloaded" |
…es in issues section There is no vinext shim for __dirname/__filename in user app code — it is a hard runtime failure, so partial was wrong. Changed to unsupported. Also fixed formatReport to list affected files under each unsupported item in the 'Issues to address' section. Previously files were only shown in the per-section detail view (imports), leaving the summary section without the context needed to actually fix the issue. Adds a test verifying the file path appears in the formatted report.
|
/bigbonk review this pr please |
There was a problem hiding this comment.
Implementation is correct and well-tested. The regex approach, code integration, and test coverage are all solid.
Regex correctness: The single-pass alternation regex correctly handles:
- String literals (single/double-quoted), line comments, block comments — all skipped
- Plain template literals (no interpolation) — skipped via
[^\\$]` character class - Template expressions
${...}— correctly not consumed by the skip branch (the$(?!\{)lookahead ensures${breaks out of the template-content match, exposing the expression body to the identifier branch) - Nested template literals — works correctly since inner backtick-delimited content is matched by the template-skip branch, and
__dirnamein inner${...}is still exposed
Known acceptable edge case: obj.__dirname (property access) will be flagged as a false positive. This is fine for an advisory migration scanner — the \b word boundary matches but can't distinguish property access from a free identifier without a full parser. The PR description and previous review both acknowledge this.
ESM reassignment pattern (const __dirname = dirname(fileURLToPath(import.meta.url))) — the test correctly notes this will be detected (the identifier appears on the LHS of assignment). The test only asserts no crash, which is the right call. Users writing this pattern are already on the ESM path, so a spurious mention in the report is low-harm.
Integration with existing code: Clean merge into the existing file loop — each file is read once, rel is computed once and reused for both ViewTransition and CJS-global tracking. The cjsGlobalScanRegex.lastIndex = 0 reset before each file is correct since the regex has the g flag.
formatReport fix: The file-listing addition under "Issues to address" is straightforward and tested.
Unrelated files: The 4 files under examples/fumadocs-docs-template/.source/ appear to be generated fumadocs output that got included in this PR. They're unrelated to the __dirname/__filename detection feature. Consider splitting them into a separate commit or PR for cleaner history, but not a blocker.
Test coverage: 10 new tests cover positive detection, false-negative avoidance (strings, comments, plain templates), template expression detection, multi-file tracking, ESM reassignment resilience, and the formatReport file listing. Thorough.
|
I've reviewed and approved PR #590. Here's a summary: Verdict: Approved The implementation is correct and well-tested. Key findings:
|
Summary
Closes #583
Migration hint shown to users
Tests
9 new tests in `tests/check.test.ts` covering: