Skip to content

dataToEsm emits a duplicate default export for a default key with includeArbitraryNames #2001

@semimikoh

Description

@semimikoh
  • Rollup Plugin Name: @rollup/pluginutils
  • Rollup Plugin Version: 5.3.0 (and current master)
  • Rollup Version: N/A — dataToEsm is a standalone utility, no bundling involved
  • Operating System (or Browser): macOS
  • Node Version: 20+
  • Link to reproduction (⚠️ read below): self-contained snippet below (pure function, no bundler needed)

Expected Behavior

When dataToEsm is called with includeArbitraryNames: true on data that has a
key named default, it should produce valid JavaScript. Since dataToEsm always
emits a trailing export default {...}, the default key can only be exposed
through that default export object — it must not also be emitted as a named
export.

Actual Behavior

dataToEsm emits export { _arbitrary0 as "default" } in addition to the
trailing export default {...}. Both forms declare the module's default export,
so the generated code is invalid:

SyntaxError: Duplicate export of 'default'

Generated output for the reproduction below:

const _arbitrary0 = "a";
export const normal = "b";
export {
	_arbitrary0 as "default"
};
export default {
	"default": "a",
	normal: normal
};

Additional Information

Reproduction (pure function — runs in Node, no bundler required):

import { dataToEsm } from '@rollup/pluginutils';

const code = dataToEsm(
  { default: 'a', normal: 'b' },
  { namedExports: true, preferConst: true, includeArbitraryNames: true }
);

// Throws: SyntaxError: Duplicate export of 'default'
await import('data:text/javascript,' + encodeURIComponent(code));

A default key falls into the includeArbitraryNames branch and is emitted as
export { _x as "default" }. But both the string form export { x as "default" }
and the identifier form export { x as default } create the module's default
export, which conflicts with the export default {...} that dataToEsm always
appends.

This surfaced while working on Vite's CSS-modules named exports
(vitejs/vite#22393): a .default {} class name compiled
for a modern target produces broken output.

A fix (skip a default key from named exports, keeping it object-only) with a
test is ready and will be opened as a PR referencing this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions