[email protected] (which pins [email protected]) miscompiles class fields
that live in a CJS-classified source module when build.target is below
ES2022. The downleveled _defineProperty(this, …) call cannot resolve
its helper at module-init time, throwing:
Uncaught (in promise) TypeError: _defineProperty is not a function
at new EraParser (assets/index-XXXXXXXX.js:…)
Inside every CJS-classified module that uses class fields, Rolldown emits:
var require_EraParser = /* @__PURE__ */ __commonJSMin(((exports) => {
var _defineProperty = (init_defineProperty(), __toCommonJS(defineProperty_exports));
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// __toCommonJS returns the namespace { __esModule: true, default: <fn> },
// not the function itself. The next line throws.
var EraParser = class extends _Parser.Parser {
constructor(..._args) {
super(..._args);
_defineProperty(this, "priority", 140); // TypeError here
…
}
};
}));Compare with the helper definition Rolldown emits at the top of the bundle:
var defineProperty_exports = /* @__PURE__ */ __exportAll({ default: () => _defineProperty });
function _defineProperty(e, r, t) { … }So _defineProperty exists as a real function — but the wrapper in each
CJS-classified module re-binds the name to the namespace object instead
of to that function. The local _defineProperty shadow is broken.
In an ESM-classified module Rolldown calls the function directly, with
no __toCommonJS indirection, and the build works. The bug only fires
inside a __commonJSMin wrapper.
npm install
npm run build
npm run preview # open http://localhost:4173In the browser console you will see:
TypeError: _defineProperty is not a function
at new EraParser (assets/index-XXXXXXXX.js:1112:4)
The bundle is unminified (build.minify: false) so the broken expression
is plainly visible — see the grep snippet below.
# This expression must exist at least once for the bug to fire:
grep -c '(init_defineProperty(), __toCommonJS(defineProperty_exports))' dist/assets/*.js
# In this repro it appears 32 times (once per CJS-wrapped class-field module).
# And the parser sources that triggered it must resolve to .cjs files:
grep -o 'parse/_lib/parsers/[A-Za-z]*\.\(cjs\|js\)' dist/assets/*.js.map | sort -u
# → all results end in `.cjs`If dist/ lacks the literal (init_defineProperty(), __toCommonJS(defineProperty_exports))
substring, you are not hitting this bug — you are probably looking at
rolldown#7843
(an eval-mangler shadow bug fixed in 1.0.0-rc.13), which only manifests
when build.minify is on.
The vite.config.ts in this repo sets:
resolve: { conditions: ["require", "node", "default"] }[email protected]'s exports map is
With Vite's default browser conditions, Rolldown selects the import
branch and the .js parsers are bundled as ESM — the bug stays hidden.
The repro pins require to deterministically resolve to the .cjs
files (which is what real consumers hit when their dep graph reaches
date-fns through a transitive CJS package, or when a plugin/preset
narrows resolve.conditions).
If you want to demonstrate the bug without changing resolve.conditions,
you can also add a local .cjs file with class fields and import it
from your entry — Rolldown classifies any .cjs source the same way.
npx vite build --config vite.config.es2022.ts
grep -c '(init_defineProperty(), __toCommonJS(defineProperty_exports))' dist-es2022/assets/*.js # → 0
grep -c '_defineProperty(this' dist-es2022/assets/*.js # → 0Class fields are emitted natively, so there is nothing to downlevel and the broken helper binding is never generated.
npx vite build --config vite.config.force-esm.ts
grep -c '(init_defineProperty(), __toCommonJS(defineProperty_exports))' dist-force-esm/assets/*.js # → 0
grep -c '_defineProperty(this' dist-force-esm/assets/*.js # → 67vite.config.force-esm.ts rewrites every resolution that lands on a
date-fns/**/*.cjs file to its sibling .js. Class fields are still
downleveled (we kept target: ['safari13']), but _defineProperty is
now hoisted as a plain top-level function and called directly — no
CJS wrapper, no __toCommonJS, no bug.
npm i -D vite@7The Rollup-based build path does not have this transform, so the bug disappears. Useful as a sanity check that the regression is in Rolldown, not in date-fns.
package.json— pins[email protected]and[email protected].vite.config.ts— the broken-by-default config (targetsafari13,minify: false,resolve.conditions: ["require", …]).vite.config.es2022.ts— knob #1.vite.config.force-esm.ts— knob #2.index.html,src/entry.js— minimal entry that importsdate-fns/parseand uses the result so it isn't tree-shaken.
| package | version |
|---|---|
vite |
8.0.10 |
rolldown |
1.0.0-rc.17 |
date-fns |
4.1.0 |
@oxc-project/runtime (helpers) |
0.127.0 |
To try a newer rolldown rc:
npm i -D 'https://pkg.pr.new/rolldown@HEAD'
npm run build