Skip to content

[Bug]: Minifier produces broken code with nested forEach/reduce variable scoping in @ant-design/cssinjs #8791

Description

@BigFaceMaster

Describe the Bug

Rolldown's built-in minifier (oxc-minifier) produces incorrect code when minifying @ant-design/cssinjs's parseStyle function, which uses nested forEach and reduce callbacks with variable shadowing. The minified output causes a runtime TypeError: Cannot read properties of undefined error.

This does not occur with minify: false or minify: 'esbuild'.

Reproduction

The issue occurs in a WXT (browser extension framework) project built with Vite 8 + Rolldown, using [email protected] and @ant-design/[email protected].

WXT wraps each content script entry in an IIFE via Rolldown, and the default minifier is inherited from Vite 8 (which delegates to Rolldown/oxc-minifier). The bug surfaces at runtime when the minified content script is injected into a host page.

Source code (from @ant-design/cssinjs)

flattenList(Array.isArray(interpolation) ? interpolation : [interpolation]).forEach((originStyle) => {
    const style = typeof originStyle === "string" && !root ? {} : originStyle;
    if (typeof style === "string") styleStr += `${style}\n`;
    else if (style._keyframe) parseKeyframes(style);
    else {
        const mergedStyle = transformers.reduce((prev, trans) => trans?.visit?.(prev) || prev, style);
        Object.keys(mergedStyle).forEach((key) => {
            const value = mergedStyle[key];
            if (typeof value === "object" && value && (key !== "animationName" || !value._keyframe) && !isCompoundCSSProperty(value)) {
                let subInjectHash = false;
                let mergedKey = key.trim();
                let nextRoot = false;
                // ... more code using mergedKey, subInjectHash, nextRoot
            }
        });
    }
});

Minified output (broken)

// Variable names after minification:
// forEach(e => {                    -- outer: originStyle → e
//   let o = typeof e == 'string' ...  -- style → o
//   else {
//     let e = l.reduce(...)           -- mergedStyle → e (shadows outer e!)
//     Object.keys(e).forEach(o => {   -- key → o (shadows outer o!)
//       let s = e[o];                 -- value → s
//       if (...) {
//         let e = !1, l = o.trim()    -- subInjectHash → e (shadows again!), mergedKey → l

The minifier reuses variable names (e, o, l) across nested scopes. While this is normally valid JavaScript, it appears the minifier's variable reference resolution becomes incorrect in this specific pattern of deeply nested callbacks with reduce + forEach + shadowed variables.

Runtime error

Uncaught TypeError: Cannot read properties of undefined (reading '.anticon')
    at zoho.js:5:30747   // let s = e[o]  -- e is undefined here
    at Array.forEach (<anonymous>)
    at zoho.js:5:30728   // Object.keys(e).forEach(o => {...})
    at Array.forEach (<anonymous>)
    at _r (zoho.js:5:30561)  // parseStyle function
    at ee.mark (zoho.js:5:29481)
    at De.opUpdate (zoho.js:5:12095)

Expected Behavior

The minified code should produce the same runtime behavior as the unminified code. All three test cases:

Build config Result
minify: false ✅ Works
minify: 'esbuild' ✅ Works
Default (rolldown/oxc minifier) ❌ Runtime TypeError

Environment

Additional Context

  • WXT uses Vite as its build engine and inherits Rolldown as the default bundler/minifier in Vite 8.
  • The content script output format is IIFE (format: 'iife'), bundled as a single file per entry.
  • The same codebase built with WXT 0.20.19 + Vite 8 works correctly when switching to build.minify: 'esbuild'.
  • A previous version of the project (fewer antd components) did not trigger this bug, suggesting the issue is sensitive to code size or specific nesting patterns.

Workaround

Setting build.minify: 'esbuild' in Vite config avoids the issue.

Metadata

Metadata

Assignees

No one assigned

    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