Skip to content

[Bug]: lazyBarrel emits undefined bindings for unused barrel re-export initializers #9806

Description

Reproduction link or steps

Create this minimal package:

{
  "type": "module",
  "scripts": {
    "build": "rolldown -c",
    "start": "node dist/out.mjs"
  },
  "dependencies": {
    "mnemonist": "0.40.4",
    "rolldown": "1.1.0"
  }
}

entry.mjs:

import { LRUCacheWithDelete } from 'mnemonist';

const cache = new LRUCacheWithDelete(2);
cache.set('a', 1);

console.log(cache.get('a'));

rolldown.config.mjs:

export default {
  input: 'entry.mjs',
  output: {
    file: 'dist/out.mjs',
    format: 'esm'
  }
};

Run:

npm install
npm run build
npm run start

What is expected?

The bundled output should execute successfully and print:

1

What is actually happening?

The generated bundle throws at module evaluation time:

file:///private/tmp/rolldown-mnemonist-repro/dist/out.mjs:845
FibonacciHeap.MinFibonacciHeap;
^

ReferenceError: FibonacciHeap is not defined
    at file:///private/tmp/rolldown-mnemonist-repro/dist/out.mjs:845:1

The emitted bundle contains property reads for unused barrel re-export-derived bindings, but no bindings for the imported names:

module.exports = LRUCacheWithDelete;
})))(), 1);
FibonacciHeap.MinFibonacciHeap;
FibonacciHeap.MaxFibonacciHeap;
Heap.MinHeap;
Heap.MaxHeap;
SuffixArray.GeneralizedSuffixArray;
Vector.Uint8Vector;
Vector.Uint8ClampedVector;
Vector.Int8Vector;
Vector.Uint16Vector;
Vector.Int16Vector;
Vector.Uint32Vector;
Vector.Int32Vector;
Vector.Float32Vector;
Vector.Float64Vector;
Vector.PointerVector;
//#endregion
//#region entry.mjs
const cache = new import_lru_cache_with_delete.default(2);
cache.set("a", 1);
console.log(cache.get("a"));
//#endregion

A quick scan of the generated file shows no declaration/import for FibonacciHeap:

FibonacciHeap.MinFibonacciHeap 26168
FibonacciHeap = -1
var FibonacciHeap -1
const FibonacciHeap -1
import_fibonacci -1

System Info

System:
  OS: macOS 26.5
  CPU: (14) arm64 Apple M4 Pro
  Memory: 636.27 MB / 48.00 GB
  Shell: 4.7.1 - /opt/homebrew/bin/fish
Binaries:
  Node: 26.0.0 - /opt/homebrew/bin/node
  Yarn: 1.22.22 - /opt/homebrew/bin/yarn
  npm: 11.12.1 - /opt/homebrew/bin/npm
  pnpm: 10.33.0 - /opt/homebrew/bin/pnpm
  bun: 1.3.11 - /Users/abhi/.local/share/mise/installs/bun/latest/bin/bun
npmPackages:
  rolldown: 1.1.0 => 1.1.0

Any additional comments?

mnemonist/index.mjs is a side-effect-free ESM barrel. It imports defaults from several modules and derives named re-export values, for example:

import {default as FibonacciHeap} from './fibonacci-heap.js';
const MinFibonacciHeap = FibonacciHeap.MinFibonacciHeap;
const MaxFibonacciHeap = FibonacciHeap.MaxFibonacciHeap;

export {FibonacciHeap, MinFibonacciHeap, MaxFibonacciHeap};
export {default as LRUCacheWithDelete} from './lru-cache-with-delete.js';

The entry only imports LRUCacheWithDelete, but Rolldown keeps bare property reads for the other derived re-export values while dropping the imports that define the objects being read.

Adding this config makes the same repro execute successfully and print 1:

export default {
  input: 'entry.mjs',
  output: {
    file: 'dist/out.mjs',
    format: 'esm'
  },
  experimental: {
    lazyBarrel: false
  }
};

Metadata

Metadata

Labels

No labels
No labels

Type

Fields

Priority

None yet

Effort

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions