fix: localStorage exception in Node 25+#60
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a compatibility issue with Node.js 25+ environments where the Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request refactors the creation of the vmContext within the HtmlRspackPlugin. The change involves creating a deep clone of the global object, explicitly removing the eval property to prevent conflicts, and then assigning specific plugin-related and environment variables. This addresses potential issues with localStorage in Node 25+ and eval conflicts when directly spreading the global object. There are no review comments to address.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fc1b782496
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const globalClone = Object.create( | ||
| Object.getPrototypeOf(global), | ||
| Object.getOwnPropertyDescriptors(global), | ||
| ); |
There was a problem hiding this comment.
Avoid cloning host globalThis into VM context
Copying all descriptors from global also copies the non-enumerable globalThis data property, whose value is the host process global object. In a vm context this makes globalThis inside templates point to the outer global (globalThis !== this), so template code that uses globalThis cannot see injected context values like HTML_WEBPACK_PLUGIN and can accidentally read/mutate host-global state. This is a behavior regression from the previous ...global approach, which did not copy globalThis.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Fixes template-evaluation failures on newer Node versions (25+) by changing how the VM sandbox is constructed, avoiding eager access to globals (notably localStorage) that can throw during cloning.
Changes:
- Replace
...global-based sandbox creation with aglobalclone built from property descriptors. - Remove
evalfrom the cloned sandbox to avoid interfering with templateevalbehavior. - Keep nonstandard globals (
require,__filename,__dirname,htmlWebpackPluginPublicPath) explicitly injected into the VM context.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const globalClone = Object.create( | ||
| Object.getPrototypeOf(global), | ||
| Object.getOwnPropertyDescriptors(global), | ||
| ); | ||
|
|
||
| // Presence of `eval` breaks template's explicit `eval` call, might be a bug in Node | ||
| delete globalClone.eval; | ||
|
|
||
| // Not using `...global` as it throws when localStorage is not explicitly enabled in Node 25+ | ||
| const vmContext = vm.createContext( | ||
| Object.assign(globalClone, { | ||
| HTML_WEBPACK_PLUGIN: true, | ||
| // Copying nonstandard globals like `require` explicitly as they may be absent from `global` | ||
| require: require, | ||
| htmlWebpackPluginPublicPath: publicPath, | ||
| __filename: templateWithoutLoaders, | ||
| __dirname: path.dirname(templateWithoutLoaders), | ||
| }), | ||
| ); |
There was a problem hiding this comment.
This change alters the VM context creation to avoid triggering throwing getters (e.g. Node 25+ localStorage). There’s no regression test ensuring evaluateCompilationResult doesn’t throw when an enumerable global property getter throws during context setup. Consider adding a Jest test that temporarily defines global.localStorage (or another property) as an enumerable getter that throws, then runs a minimal template through evaluateCompilationResult/a compilation to assert it still succeeds (and cleans up the property after).
Port jantimon/html-webpack-plugin#1880