Skip to content

webpack@5.108.0 generates invalid property access for escaped namespace imports with export mangling #21278

Description

@ZZITE

Bug report

After upgrading to webpack@5.108.0, our production bundle started throwing a runtime error:

TypeError: Cannot read properties of undefined (reading 'y')

The generated bundle contains code like this:

useLocation: () => y.z.y

But the actual exported name on the imported module is a mangled export named zy, so the generated code should be:

useLocation: () => y.zy

It looks like the mangled export name string "zy" is being passed to propertyAccess(...) as an ArrayLike<string>, causing it to be rendered as .z.y.

Regression

This only started after webpack@5.108.0.

With webpack@5.107.2, the same project builds correctly.

This looks related to:

Triggering pattern

The issue appears when a namespace import is used as a whole value / escapes, for example code like this from a dependency:

import * as tmp from "react-router";

const rc = tmp;

const location = rc.useLocation();

In our case this comes from @ahooksjs/use-url-state, which imports react-router this way.

The generated namespace getter incorrectly accesses the mangled export as a property path:

useLocation: () => y.z.y

instead of:

useLocation: () => y.zy

Suspected cause

In lib/optimize/ConcatenatedModule.js, the new decoupled namespace object generation path seems to call:

const usedName = exportInfo.getUsedName(undefined, runtime);

ExportInfo#getUsedName(...) returns a string such as "zy".

Later, for external modules, it is rendered with:

`${info.name}${propertyAccess(usedName)}`

But propertyAccess(...) expects an array-like path. Since strings are also array-like, "zy" becomes .z.y.

Relevant code path in the 5.108.0 release appears to be around:

const usedName = exportInfo.getUsedName(undefined, runtime);
// ...
info.type === "external"
  ? `${info.name}${propertyAccess(usedName)}`
  : getFinalName(...)

A possible fix may be to wrap string used names before passing them to propertyAccess, for example:

propertyAccess([usedName])

or use exportsInfo.getUsedName([exportInfo.name], runtime) consistently with the other path in RuntimeTemplate.

Expected behavior

If an export is mangled to a multi-character name like "zy", webpack should generate:

module.zy

not:

module.z.y

Actual behavior

webpack generates:

module.z.y

which crashes at runtime because module.z is undefined.

Environment

webpack: 5.108.0
webpack 5.107.2: works
target: web
mode: production
optimization.mangleExports: enabled

The affected runtime dependency in my bundle is react-router, accessed through @ahooksjs/use-url-state.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

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