-
-
Notifications
You must be signed in to change notification settings - Fork 714
Open
Labels
S-Needs triageStatus: this issue needs to be triagedStatus: this issue needs to be triaged
Description
Environment information
CLI:
Version: 2.2.5
Color support: true
Platform:
CPU Architecture: aarch64
OS: macos
Environment:
BIOME_LOG_PATH: unset
BIOME_LOG_PREFIX_NAME: unset
BIOME_CONFIG_PATH: unset
BIOME_THREADS: unset
NO_COLOR: unset
TERM: xterm-256color
JS_RUNTIME_VERSION: v22.20.0
JS_RUNTIME_NAME: node
NODE_PACKAGE_MANAGER: npm/11.6.1
Biome Configuration:
Status: Not set
Path: unset
Workspace:
Open Documents: 0
What happened?
Import Sorting Breaks Subclass Dependencies
ES module import order matters at runtime because ES modules use live bindings and respect top-down evaluation. Tools like Biome that automatically sort imports alphabetically are not aware of dependency order between exports, which can easily break code. Even a simple subclass can fail if its superclass is referenced before it is initialized.
Minimal Reproduction
Project Structure
├── dist
│ └── bundle.js
├── package-lock.json
├── package.json
├── rollup.config.js
└── src
├── Aardvark.js
├── Animal.js
└── index.js
1️⃣ src/Animal.js
// src/Animal.js
export class Animal{} // Base class
2️⃣ src/Aardvark.js
// src/Aardvark.js
export class Aardvark extends Animal{} // Depends on Animal being initialized first
3️⃣ src/index.js
// src/index.js
export { Animal } from './Animal.js';
export { Aardvark } from './Aardvark.js'; // Depends on Animal being exported first
4️⃣ rollup.config.js
import path from 'path';
export default {
input: path.resolve('./src/index.js'),
output: {
file: path.resolve('./dist/bundle.js'),
format: 'esm'
}
};
5️⃣ Build Steps
# Normal Rollup build preserves order -> works
rollup -c rollup.config.js
Generated dist/bundle.js
:
const Animal$1 = class Animal {}; // Animal defined first
class Aardvark extends Animal {} // Aardvark safe: Animal exists
export { Aardvark, Animal$1 as Animal };
✅ Works correctly because Animal
is initialized before Aardvark
.
6️⃣ Biome "fix" (alphabetic sorting)
npx biome check --fix
rollup -c rollup.config.js
Generated dist/bundle.js
:
class Aardvark extends Animal {} // ❌ Illegal forward reference
let Animal$1 = class Animal {};
export { Aardvark, Animal$1 as Animal };
Aardvark
now referencesAnimal
before it is initialized.- Runtime error:
Illegal forward reference of let variable
.
Why Alphabetic Sorting Is Unsafe
- ES module evaluation is top-down. Classes and
let
/const
cannot be referenced before initialization. - Dependencies matter. Any subclass or code referencing another export must come after its dependency.
- Live bindings make re-exports sensitive. Even if it looks like a harmless re-export, evaluation order determines correctness.
- Alphabetic sorting ignores semantics. Tools cannot infer the correct initialization order, so automatic reordering can break code.
Conclusion: Sorting ES module imports alphabetically is fundamentally unsafe in the presence of subclassing, circular dependencies, or any dependent exports.
Expected result
It should not sort imports unless --unsafe
is also used
Code of Conduct
- I agree to follow Biome's Code of Conduct
Metadata
Metadata
Assignees
Labels
S-Needs triageStatus: this issue needs to be triagedStatus: this issue needs to be triaged