Skip to content

compiler: dynamic import loses aliased local variable exports #9778

Description

@proggeramlug

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
./repro

The 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, and const values 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regressionparityCompatibility gap with Node.js, ECMAScript, or the supported ecosystem

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions