fix: provide module/exports in VM sandbox for Node.js 25+ compatibility#1889
Merged
alexander-akait merged 1 commit intojantimon:mainfrom Apr 17, 2026
Merged
Conversation
Templates whose child compilation output is a CommonJS module (for
example Rspack's HtmlWebpackPlugin child compilation, which wraps the
evaluated template in `module.exports = ...`) were failing at evaluation
time with `ReferenceError: module is not defined` under Node.js 25+.
In 5.6.5 the VM context was switched away from a `...global` spread
because spreading `global` on Node 25 throws once `localStorage` is
touched without `--localstorage-file`. The replacement clone only
exposes the standard globals plus `require`, so any CommonJS-wrapped
source that assigned to `module.exports` hit the ReferenceError.
Provide a throwaway `module = { exports: {} }` pair (plus `exports`
aliasing it) in the sandbox so CommonJS-style outputs can evaluate
without assuming the host Node version populates them.
Refs: PR jantimon#1880, facebook/docusaurus#11545
alexander-akait
approved these changes
Apr 17, 2026
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1889 +/- ##
=======================================
Coverage ? 92.40%
=======================================
Files ? 18
Lines ? 750
Branches ? 208
=======================================
Hits ? 693
Misses ? 54
Partials ? 3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Templates whose child compilation output is a CommonJS module — for example,
HtmlWebpackPlugin's child compilation under Rspack — fail at evaluation time
with
ReferenceError: module is not definedunder Node.js 25+.The VM sandbox built in
evaluateCompilationResult(reshaped in #1880 to workaround a
localStorageregression in Node.js 25.2) no longer exposesmodule/exports. Any source that assigns tomodule.exports = ...now throws.This PR adds a throwaway
module = { exports: {} }pair (plusexports) to thesandbox so CommonJS-wrapped sources evaluate without relying on Node populating
them.
Reproduction
With a Docusaurus 3.10 site using
future.faster: true(Rspack) under Node 25.9.0:Both
docusaurus buildanddocusaurus startfail.Root cause
The child compilation emitted for the template under Rspack is a regular
CommonJS module that looks roughly like:
runInContextexecutes it against the sandbox built inevaluateCompilationResult, which since #1880 only exposes thecloned globals plus
require,HTML_WEBPACK_PLUGIN,htmlWebpackPluginPublicPath,__filename, and__dirname. With neithermodulenorexportspresent, the assignment throws before the string can bereturned.
Under Webpack 5 the child compilation output tends not to reference
module.exportsdirectly, which is why this did not surface there.Fix
Expose a local
{ exports: {} }container asmodule(and a mirror asexports) in the sandbox. Nothing in the plugin reads from them — they onlyexist so a CommonJS-wrapped result can evaluate without throwing:
This mirrors what a normal Node module boundary would provide, without pulling
anything else into the sandbox.
Tests
Added a focused unit test in
spec/basic.spec.jsthat callsevaluateCompilationResultwith amodule.exports = "…"source and assertsthe string result.
Verified locally on Node 25.9.0 (macOS):
npm run test:only— 161/161 passed (includes new test)npm run lint— clean (addedRspackto.cspell.jsonfor the new code comment)End-to-end: patching
node_modules/html-webpack-plugininside a Docusaurus3.10 project with
future.faster: true:docusaurus startanddocusaurus buildboth succeed.
Related
...globalfor the Node 25localStorageregression.Docusaurus author @slorber flagged "Docusaurus dev server still won't start"
in that thread; this PR addresses the Rspack side of that symptom.
docusaurus buildbroken with NodeJS 25 facebook/docusaurus#11545 — downstream issue, currently worked around withNODE_OPTIONS=--no-webstorage.moduleinto thevmContext#1634 proposed addingmoduletoo but was closed because thatreporter's root cause was a
file-loadermisconfiguration — this PR's rootcause is different (Rspack's CommonJS-wrapped child compilation output).