fix: emit DUPLICATE_SHEBANG warning when banner contains shebang#9026
fix: emit DUPLICATE_SHEBANG warning when banner contains shebang#9026graphite-app[bot] merged 1 commit intomainfrom
Conversation
How to use the Graphite Merge QueueAdd the label graphite: merge-when-ready to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
✅ Deploy Preview for rolldown-rs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for rolldown-rs canceled.
|
a0e9f7a to
ca32214
Compare
Merging this PR will not alter performance
Comparing Footnotes
|
Merge activity
|
## Summary The existing `DUPLICATE_SHEBANG` diagnostic only checked `postBanner` against the chunk content, and it ran in `post_banner_footer` — **after** `minify_chunks`. This meant: 1. `output.banner` with a shebang was never checked, so no warning was emitted. 2. Because `minify_chunks` reparses the rendered chunk (which already contains two shebangs from entry + banner), the invalid JS produces a broken AST, and the codegen silently drops the bundle body — leaving only a shebang line in the output. The fix moves the duplicate shebang detection to `ecma_generator` (pre-rendering), where all three shebang sources (entry hashbang, banner, postBanner) are available as resolved values. This catches conflicts **before** minification can destroy the output. ### Changes - Add `has_shebang` utility for efficient shebang detection without unnecessary newline scanning - Check all pairwise combinations of entry hashbang, banner, and postBanner for duplicate shebangs - Skip the entry hashbang check for UMD format (which silently drops it), while still warning when UMD banner and postBanner both have shebangs - Add `source` field to `DuplicateShebang` diagnostic so the warning message specifies which addon caused the conflict Fixes #9024 ## Test plan - [x] `banner/duplicate-shebang-fn` — function-based banner with shebang warns - [x] `post-banner/duplicate-shebang-fn` — function-based postBanner with shebang warns - [x] `post-banner/duplicate-shebang` — existing static postBanner test still passes - [x] `esbuild/hashbang_banner_use_strict_order` — snapshot updated with warning - [x] `umd_entry_hashbang_post_banner_shebang` — UMD entry hashbang + postBanner: no false positive - [x] `umd_banner_post_banner_duplicate_shebang` — UMD banner + postBanner: warns correctly 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ca32214 to
9dd533a
Compare
## [1.0.0-rc.16] - 2026-04-16 ### 🚀 Features - const enum cross-module inlining support (#8796) by @Dunqing - implement module tagging system for code splitting (#9045) by @hyf0 ### 🐛 Bug Fixes - rolldown_plugin_vite_manifest: handle duplicate chunk names for CSS entries (#9059) by @sapphi-red - improve error message for invalid return values in function options (#9125) by @shulaoda - await async export-star init wrappers (#9101) by @thezzisu - never panic during diagnostic emission (#9091) by @IWANABETHATGUY - include array rest pattern in binding_identifiers (#9112) by @IWANABETHATGUY - rolldown: set worker thread count with ROLLDOWN_WORKER_THREADS (#9086) by @fpotter - rolldown_plugin_lazy_compilation: escape request ID in proxy modules (#9102) by @h-a-n-a - treat namespace member access as side-effect-free (#9099) by @IWANABETHATGUY - relax overly conservative side-effect leak check in chunk optimizer (#9085) by @IWANABETHATGUY - runtime: release `cb` reference after `__commonJS` factory initialization (#9067) by @hyf0-agent - `@__NO_SIDE_EFFECTS__` wrapper should not remove dynamic imports (#9075) by @IWANABETHATGUY - rolldown_plugin_vite_import_glob: use POSIX path join/normalize for glob resolution (#9077) by @shulaoda - emit REQUIRE_TLA error when require() loads a module with top-level await (#9071) by @jaehafe - emit namespace declaration for empty modules in manual chunks (#8993) by @privatenumber - rolldown_plugin_vite_import_glob: keep common base on path segment boundary (#9070) by @shulaoda - prevent circular runtime helper imports during facade elimination (#8989) (#9057) by @IWANABETHATGUY - correct circular dependency check in facade elimination (#9047) by @h-a-n-a - docs: correct dead link in CodeSplittingGroup.tags JSDoc (#9051) by @hyf0 - emit DUPLICATE_SHEBANG warning when banner contains shebang (#9026) by @IWANABETHATGUY ### 🚜 Refactor - use semantic reference flags for member write detection (#9060) by @Dunqing - extract UsedSymbolRefs newtype wrapper (#9130) by @IWANABETHATGUY - dedupe await wrapping in export-star init emit (#9119) by @IWANABETHATGUY - calculate side-effect-free function symbols on demand (#9120) by @IWANABETHATGUY - extract duplicated top-level await handling into shared helper (#9087) by @IWANABETHATGUY - rolldown_plugin_vite_import_glob: use split_first for get_common_base (#9069) by @shulaoda - simplify ESM init deduplication with idiomatic insert check (#9044) by @IWANABETHATGUY ### 📚 Documentation - document runtime module placement strategy in code-splitting design (#9062) by @IWANABETHATGUY - clarify `options` hook behavior difference with Rollup in watch mode (#9053) by @sapphi-red - meta/design: introduce module tags (#9017) by @hyf0 ### ⚡ Performance - convert `generate_transitive_esm_init` to iterative (#9046) by @IWANABETHATGUY ### 🧪 Testing - merge strict/non_strict test variants using configVariants (#9089) by @IWANABETHATGUY ### ⚙️ Miscellaneous Tasks - disable Renovate auto-updates for oxc packages (#9129) by @IWANABETHATGUY - upgrade oxc@0.126.0 (#9127) by @Dunqing - deps: update napi to v3.8.5 (#9126) by @renovate[bot] - deps: update dependency @napi-rs/cli to v3.6.2 (#9123) by @renovate[bot] - move lazy-compilation design doc (#9117) by @h-a-n-a - deps: update dependency vite-plus to v0.1.18 (#9118) by @renovate[bot] - deps: update dependency vite-plus to v0.1.17 (#9113) by @renovate[bot] - deps: update oxc to v0.125.0 (#9094) by @renovate[bot] - deps: update dependency follow-redirects to v1.16.0 [security] (#9103) by @renovate[bot] - deps: update test262 submodule for tests (#9097) by @sapphi-red - deps: update crate-ci/typos action to v1.45.1 (#9096) by @renovate[bot] - deps: update rust crates (#9081) by @renovate[bot] - deps: update npm packages (#9080) by @renovate[bot] - remove outdated TODO in determine_module_exports_kind (#9072) by @jaehafe - rust/test: support `extendedTests: false` shorthand in test config (#9050) by @hyf0 - ci: extract shared infra-changes anchor in path filters (#9054) by @hyf0 - add docs build check to catch dead links in PRs (#9052) by @hyf0 ### ❤️ New Contributors * @thezzisu made their first contribution in [#9101](#9101) * @fpotter made their first contribution in [#9086](#9086) * @jaehafe made their first contribution in [#9071](#9071) * @privatenumber made their first contribution in [#8993](#8993) Co-authored-by: shulaoda <165626830+shulaoda@users.noreply.github.com>

Summary
The existing
DUPLICATE_SHEBANGdiagnostic only checkedpostBanneragainst the chunk content, and it ran inpost_banner_footer— afterminify_chunks. This meant:output.bannerwith a shebang was never checked, so no warning was emitted.minify_chunksreparses the rendered chunk (which already contains two shebangs from entry + banner), the invalid JS produces a broken AST, and the codegen silently drops the bundle body — leaving only a shebang line in the output.The fix moves the duplicate shebang detection to
ecma_generator(pre-rendering), where all three shebang sources (entry hashbang, banner, postBanner) are available as resolved values. This catches conflicts before minification can destroy the output.Changes
has_shebangutility for efficient shebang detection without unnecessary newline scanningsourcefield toDuplicateShebangdiagnostic so the warning message specifies which addon caused the conflictFixes #9024
Test plan
banner/duplicate-shebang-fn— function-based banner with shebang warnspost-banner/duplicate-shebang-fn— function-based postBanner with shebang warnspost-banner/duplicate-shebang— existing static postBanner test still passesesbuild/hashbang_banner_use_strict_order— snapshot updated with warningumd_entry_hashbang_post_banner_shebang— UMD entry hashbang + postBanner: no false positiveumd_banner_post_banner_duplicate_shebang— UMD banner + postBanner: warns correctly🤖 Generated with Claude Code