-
Notifications
You must be signed in to change notification settings - Fork 737
export let reassignment is incorrectly tree-shaken (live binding broken in production build) #8916
Description
Description
When an export let variable is initialized as a no-op function and later reassigned inside another exported function, Rolldown's tree-shaking incorrectly removes both the reassignment and the call site — even though the reassignment contains real side effects (document.title assignment).
This violates ES module semantics where export let creates a live binding that should reflect reassignment to importers.
Reproduction
git clone https://github.com/y-masuda-saraits/rolldown-treeshake-bug-repro.git
cd rolldown-treeshake-bug-repro
npm install
npx vite buildThen inspect dist/assets/index-*.js. The relevant section in the output:
var setup = () => {};
var doWork = () => {};
setup();
doWork();Source files (3 modules)
src/logger.js — exports a mutable binding and a function that reassigns it:
export let send = () => {}
export const setup = () => {
send = (msg) => {
document.title = msg // side effect
console.log('[send]', msg)
}
}src/consumer.js — imports and calls the live binding:
import { send } from './logger.js'
export const doWork = () => {
send('hello from doWork')
}src/main.js — entry point:
import { setup } from './logger.js'
import { doWork } from './consumer.js'
setup()
doWork()Expected behavior
The bundled output should preserve:
- The
send = (msg) => { document.title = msg; ... }reassignment insidesetup - The
send('hello from doWork')call insidedoWork
At runtime, document.title should be set to "hello from doWork".
Actual behavior
Rolldown replaces both setup and doWork with () => {}, completely removing:
- The
sendreassignment (including thedocument.titleside effect) - The
send(...)call indoWork
The bundler appears to inline the initial value () => {} for the export let binding and then determine all call sites have no side effects, triggering cascading dead-code elimination.
Environment
- Vite 8.0.3 (Rolldown bundled)
build.minify: falsein vite.config.js (to keep output readable)- Windows 11, Node v22
Metadata
Metadata
Assignees
Labels
Type
Fields
Give feedbackPriority