Repository navigation
compiler: dynamic import loses aliased local variable exports #9778
Description
await import() exposes local variable alias exports as undefined, while direct variable exports and function aliases work. This blocks startup of split bundles, but the reproducer below is independent of any application and does not use Bun-specific APIs.
Reproduced on unmodified main 12efed12220ee87b1bec504a9fda1f2340fcffad (Perry 0.5.1520, macOS arm64), and on the compiler branch in #9775. It is not caused by that PR's import.meta.require() change.
commands.js:
var commands = new Set(['doctor']);
function check(args) { return args.includes('doctor'); }
export { commands as COMMANDS, check as checkArgs };main.js:
async function main() {
const { COMMANDS, checkArgs } = await import('./commands.js');
console.log(typeof COMMANDS, typeof checkArgs);
console.log(COMMANDS.has('doctor'), checkArgs(['doctor']));
}
main();Run with a matching compiler/runtime installation:
perry compile main.js -o repro --platform bun --enable-wasm-runtime --no-auto-optimize
./reproThe WebAssembly flag is needed for the locally prebuilt full stdlib archive; this repro itself uses no WebAssembly.
Bun 1.3.14 prints:
object function
true true
Perry links successfully but exits 1 after:
undefined function
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'has')
A six-export matrix confirms the distinction: var, let, and const initialized with new Set(...) all become undefined when exported through export { local as PUBLIC }; the corresponding export var/let/const PUBLIC = new Set(...) declarations all produce objects. The aliased function in the minimal repro remains callable.
Acceptance:
- The two-file repro matches Bun and exits 0 after native compilation.
- Cover aliased local
var,let, andconstvalues with initializers that run at module initialization, alongside direct exports and function-alias controls. - Preserve live bindings when the exported mutable variable is reassigned after import; avoid fixing only the initial namespace snapshot.
- Keep this regression in an application-independent compiler integration test. No extracted bundle, special filesystem layout, or worktree from fix(compile): bound and unblock extracted Bun bundles #9775 should be required.
Likely investigation points are flatten_exports, the LocalVar/ForeignVar namespace-entry classification, and the getter/global name chosen for local export aliases. This is an investigation lead, not a confirmed root cause. There are no re-export barrels or import cycles in the reproducer, unlike the closed #6304 / #6463 cases.
Activity
proggeramlug commentedon Sep 6, 2026
Fixed by #9879, landed on
mainvia merge train #9888. The train merged as its own branch, so the close-keyword never fired — closing manually, verified on main.