Reproduction link or steps
A repository-style minimal reproduction (mirrors the test added in #9329):
.
├── entry.js
├── route.js
├── child.js
└── node_modules/react/
├── package.json
├── index.js
├── jsx-runtime.js
└── cjs/
├── react.production.js
└── react-jsx-runtime.production.js
entry.js:
import React from 'react';
import { jsx } from 'react/jsx-runtime';
console.log('entry', React.version, jsx('main', {}));
import('./route.js');
route.js:
import React from 'react';
import { jsx } from 'react/jsx-runtime';
console.log('route', React.version, jsx('route', {}));
import('./child.js');
child.js:
import { jsx } from 'react/jsx-runtime';
console.log('child', jsx('child', {}));
node_modules/react/package.json:
{
"name": "react",
"main": "./index.js",
"exports": {
".": "./index.js",
"./jsx-runtime": "./jsx-runtime.js"
}
}
node_modules/react/index.js:
'use strict'
module.exports = require('./cjs/react.production.js')
node_modules/react/jsx-runtime.js:
'use strict'
module.exports = require('./cjs/react-jsx-runtime.production.js')
node_modules/react/cjs/react.production.js:
'use strict'
exports.version = '19'
node_modules/react/cjs/react-jsx-runtime.production.js:
'use strict'
exports.jsx = (type) => ({ type })
exports.jsxs = exports.jsx
exports.Fragment = Symbol.for('react.fragment')
Build with a single user entry (entry.js).
What is expected?
All consumers of react/jsx-runtime (entry, route, child) are reachable through the same user entry, so its modules should merge into entry.js. Output should be 3 chunks:
- child.js (dynamic entry)
- entry.js (user entry, contains react + jsx-runtime modules)
- route.js (dynamic entry)
What is actually happening?
A separate jsx-runtime.js common chunk is emitted, even though there is no other user entry that could share it:
- child.js (dynamic entry)
- entry.js (user entry)
- jsx-runtime.js (common chunk, exports ["n", "r", "t"]) <-- unexpected
- route.js (dynamic entry)
Root cause (per #9329): when multiple pending common chunks should all merge into the same target entry, the optimizer's would_create_circular_dependency check treats sibling pending merges as still external, so they appear to form a transient cycle and get split into a standalone common chunk.
System Info
rolldown: 1.0.0-rc.18 (also reproducible on current main @ d3ae8ba2f)
OS: Windows 11
Any additional comments?
Reproduction link or steps
A repository-style minimal reproduction (mirrors the test added in #9329):
entry.js:route.js:child.js:node_modules/react/package.json:{ "name": "react", "main": "./index.js", "exports": { ".": "./index.js", "./jsx-runtime": "./jsx-runtime.js" } }node_modules/react/index.js:node_modules/react/jsx-runtime.js:node_modules/react/cjs/react.production.js:node_modules/react/cjs/react-jsx-runtime.production.js:Build with a single user entry (
entry.js).What is expected?
All consumers of
react/jsx-runtime(entry, route, child) are reachable through the same user entry, so its modules should merge intoentry.js. Output should be 3 chunks:What is actually happening?
A separate
jsx-runtime.jscommon chunk is emitted, even though there is no other user entry that could share it:Root cause (per #9329): when multiple pending common chunks should all merge into the same target entry, the optimizer's
would_create_circular_dependencycheck treats sibling pending merges as still external, so they appear to form a transient cycle and get split into a standalone common chunk.System Info
Any additional comments?
react/jsx-runtimefacade (module.exports = require('./cjs/...')) when combined with nested dynamic imports.