Related plugins
Describe the bug
When a Babel plugin runs after @vitejs/plugin-react's OXC transform (using @rolldown/plugin-babel with enforce: 'post' or a custom plugin), the Babel AST loc values refer to the OXC-transformed code, not the original source. Any Babel plugin that reads loc.start.line / loc.start.column to embed source positions in the output will produce incorrect values.
This was not an issue with @vitejs/plugin-react v5 where Babel handled both JSX transform and custom plugins in a single pass — loc always pointed to the original source.
Example
We have a Babel plugin that inserts ComponentName.__debugSourceDefine = { fileName, lineNumber, columnNumber } after each React function component, using the function body's loc:
FunctionDeclaration(path, state) {
const name = path.node.id.name;
const loc = path.node.body.loc; // ← wrong after OXC transform
// inserts: Foo.__debugSourceDefine = { fileName: "...", lineNumber: loc.start.line, ... }
path.insertAfter(createDebugInfo(name, state.file.opts.filename, loc));
}
With v5 (react({ babel: { plugins: [myPlugin] } })), loc.start.line referred to the original .tsx file. With v6, OXC transforms JSX first, changing line numbers. Babel sees the transformed code and its loc values are offset.
The dilemma — no configuration produces correct results
With enforce: 'pre' (default) — Babel runs before OXC:
- ✅
__debugSourceDefine line numbers are correct (Babel sees original source)
- ❌ OXC's
jsxDEV() source info is wrong — every JSX element in the app gets shifted line numbers because Babel inserted __debugSourceDefine blocks (4+ lines each) before OXC processed the file
With enforce: 'post' — Babel runs after OXC:
- ❌
__debugSourceDefine line numbers are wrong (Babel AST loc refers to OXC-transformed code, not the original source)
- ✅ OXC's
jsxDEV() source info is correct (OXC saw the original source)
Reproduction
https://github.com/Artur-/vite-babel-order-repro
Steps to reproduce
Open in browser — the page automatically verifies source positions.
System Info
System:
OS: macOS 26.3.1
CPU: (10) arm64 Apple M1 Max
Binaries:
Node: 24.14.0
npm: 11.9.0
Used Package Manager
npm
Logs
No response
Validations
Related plugins
plugin-react
plugin-react-swc
plugin-rsc
Describe the bug
When a Babel plugin runs after
@vitejs/plugin-react's OXC transform (using@rolldown/plugin-babelwithenforce: 'post'or a custom plugin), the Babel ASTlocvalues refer to the OXC-transformed code, not the original source. Any Babel plugin that readsloc.start.line/loc.start.columnto embed source positions in the output will produce incorrect values.This was not an issue with
@vitejs/plugin-reactv5 where Babel handled both JSX transform and custom plugins in a single pass —localways pointed to the original source.Example
We have a Babel plugin that inserts
ComponentName.__debugSourceDefine = { fileName, lineNumber, columnNumber }after each React function component, using the function body'sloc:With v5 (
react({ babel: { plugins: [myPlugin] } })),loc.start.linereferred to the original.tsxfile. With v6, OXC transforms JSX first, changing line numbers. Babel sees the transformed code and itslocvalues are offset.The dilemma — no configuration produces correct results
With
enforce: 'pre'(default) — Babel runs before OXC:__debugSourceDefineline numbers are correct (Babel sees original source)jsxDEV()source info is wrong — every JSX element in the app gets shifted line numbers because Babel inserted__debugSourceDefineblocks (4+ lines each) before OXC processed the fileWith
enforce: 'post'— Babel runs after OXC:__debugSourceDefineline numbers are wrong (Babel ASTlocrefers to OXC-transformed code, not the original source)jsxDEV()source info is correct (OXC saw the original source)Reproduction
https://github.com/Artur-/vite-babel-order-repro
Steps to reproduce
Open in browser — the page automatically verifies source positions.
System Info
System: OS: macOS 26.3.1 CPU: (10) arm64 Apple M1 Max Binaries: Node: 24.14.0 npm: 11.9.0Used Package Manager
npm
Logs
No response
Validations