Skip to content

fix: avoid ProvidePlugin injection for local const require bindings#21041

Merged
alexander-akait merged 2 commits into
webpack:mainfrom
fireairforce:fix-cjs-provider-conflict1
May 26, 2026
Merged

fix: avoid ProvidePlugin injection for local const require bindings#21041
alexander-akait merged 2 commits into
webpack:mainfrom
fireairforce:fix-cjs-provider-conflict1

Conversation

@fireairforce

Copy link
Copy Markdown
Contributor

Summary

Fix a parser interaction introduced by the CommonJS const NAME = require(LITERAL) binding tracking.

When a local const require binding has the same name as a ProvidePlugin definition, for example:

const process = require("process");
process.cwd();

with:

new ProvidePlugin({
  process: "process"
});

webpack could still fall through from the local require-binding hook to the ProvidePlugin hook for process. That caused webpack to emit both a provided dependency declaration and the local const binding in the same scope, eventually failing with:

Identifier 'process' has already been declared

This change returns true after handling bare reads of tagged CommonJS require bindings, so the local binding is treated as handled and does not trigger same-name free variable hooks.

What kind of change does this PR introduce?

fix

Did you add tests for your changes?

Yes. Added a regression test in test/configCases/plugins/provide-plugin-require-binding covering a local const process = require(...) binding together with ProvidePlugin({ process }) and module concatenation enabled.

Validated with:

yarn test:base --testMatch "<rootDir>/test/ConfigTestCases.basictest.js" --runInBand --testNamePattern "provide-plugin-require-binding"
yarn test:base --testMatch "<rootDir>/test/TestCasesNormal.basictest.js" --runInBand --testNamePattern "cjs-tree-shaking.*require-member-access"
yarn test:base --testMatch "<rootDir>/test/ConfigTestCases.basictest.js" --runInBand --testNamePattern "plugins.*provide-plugin"

Does this PR introduce a breaking change?

No.

This only prevents a local const NAME = require(...) binding from falling through to same-name free variable hooks after webpack has already handled that local binding. Existing ProvidePlugin behavior for actual free variables is unchanged.

If relevant, what needs to be documented once your changes are merged or what have you already documented?

No documentation changes are needed. This is a bug fix for parser behavior.

Use of AI

AI assistance was used to help investigate the regression, identify the parser fallback path, draft the minimal code change, and prepare the PR description. The generated code and text were reviewed and validated by a human before submission, following webpack's AI usage policy.

Copilot AI review requested due to automatic review settings May 26, 2026 03:15
@changeset-bot

changeset-bot Bot commented May 26, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9d4c234

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
webpack Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Fixes a parser-hook interaction where a local const NAME = require("...") binding could still fall through to ProvidePlugin’s free-variable handling when both use the same identifier, causing duplicate declarations during module concatenation.

Changes:

  • Update CommonJS imports parser handling to “bail out” after processing tagged const require(...) bindings.
  • Add a regression config-case covering ProvidePlugin({ process }) + local const process = require(...) with module concatenation enabled.
  • Add simple fixture module used by the regression case.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
test/configCases/plugins/provide-plugin-require-binding/webpack.config.js Adds a dedicated config-case enabling ProvidePlugin and concatenateModules for the regression
test/configCases/plugins/provide-plugin-require-binding/process.js Adds a minimal process-like module used by both the local binding and ProvidePlugin
test/configCases/plugins/provide-plugin-require-binding/index.js Adds runtime assertion ensuring the local binding wins over ProvidePlugin injection
lib/dependencies/CommonJsImportsParserPlugin.js Stops hook fall-through by returning true after handling the tagged require-binding

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -732,6 +732,7 @@ class CommonJsImportsParserPlugin {
// chain), so we have to assume the whole exports object is used.
binding.dep.referencedExports = null;
}
@codecov

codecov Bot commented May 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.65%. Comparing base (224f3ee) to head (9d4c234).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21041      +/-   ##
==========================================
- Coverage   91.67%   91.65%   -0.02%     
==========================================
  Files         573      573              
  Lines       59874    59875       +1     
  Branches    16159    16159              
==========================================
- Hits        54888    54877      -11     
- Misses       4986     4998      +12     
Flag Coverage Δ
integration 89.55% <100.00%> (-0.02%) ⬇️
test262 45.37% <0.00%> (-0.01%) ⬇️
unit 38.06% <0.00%> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq

codspeed-hq Bot commented May 26, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

⚡ 3 improved benchmarks
❌ 4 regressed benchmarks
✅ 137 untouched benchmarks
⏩ 72 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory benchmark "asset-modules-bytes", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 139.3 KB 325.1 KB -57.15%
Memory benchmark "cache-filesystem", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 493.9 KB 252.5 KB +95.64%
Memory benchmark "css-modules", scenario '{"name":"mode-production","mode":"production"}' 10 MB 7.6 MB +31.14%
Memory benchmark "concatenate-modules", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 150.8 KB 488.4 KB -69.12%
Memory benchmark "wasm-modules-sync", scenario '{"name":"mode-production","mode":"production"}' 7.6 MB 6.2 MB +22.66%
Memory benchmark "many-chunks-commonjs", scenario '{"name":"mode-production","mode":"production"}' 6.9 MB 10.2 MB -32.94%
Memory benchmark "many-chunks-commonjs", scenario '{"name":"mode-development","mode":"development"}' 844.4 KB 1,063.9 KB -20.63%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing fireairforce:fix-cjs-provider-conflict1 (9d4c234) with main (224f3ee)

Open in CodSpeed

Footnotes

  1. 72 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@hai-x

hai-x commented May 26, 2026

Copy link
Copy Markdown
Member

Thanks for the fix. ❤️

@alexander-akait alexander-akait merged commit a87ce98 into webpack:main May 26, 2026
54 of 56 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants