Skip to content

fix: hoist import.meta as module-level variable with complete properties#20658

Merged
alexander-akait merged 11 commits intomainfrom
fix/import-meta-standalone-expression
Mar 17, 2026
Merged

fix: hoist import.meta as module-level variable with complete properties#20658
alexander-akait merged 11 commits intomainfrom
fix/import-meta-standalone-expression

Conversation

@xiaoxiaojx
Copy link
Copy Markdown
Member

Summary
Previously, standalone import.meta expressions (e.g., return import.meta, const meta = import.meta) were replaced with an empty object ({}), losing all known properties and creating a new object on each reference.

Now uses ModuleInitFragmentDependency to hoist a __webpack_import_meta__ variable at module scope with url, webpack, main, and env properties. All standalone import.meta references resolve to this single variable, ensuring object identity (import.meta === import.meta) and property preservation.

In preserve-unknown mode (ESM output), the hoisted variable uses Object.assign(import.meta, {...}) to retain runtime-assigned properties.

What kind of change does this PR introduce?
fix

Did you add tests for your changes?
Yes

Does this PR introduce a breaking change?
No

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

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Mar 17, 2026

🦋 Changeset detected

Latest commit: 269ad30

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 17, 2026

This PR is packaged and the instant preview is available (f757352).

Install it locally:

  • npm
npm i -D webpack@https://pkg.pr.new/webpack@f757352
  • yarn
yarn add -D webpack@https://pkg.pr.new/webpack@f757352
  • pnpm
pnpm add -D webpack@https://pkg.pr.new/webpack@f757352

Copy link
Copy Markdown
Member

@alexander-akait alexander-akait left a comment

Choose a reason for hiding this comment

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

Let's remove from skipping tests from test262 which now we are passed

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Mar 17, 2026

Merging this PR will degrade performance by 25.39%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 3 improved benchmarks
❌ 2 regressed benchmarks
✅ 139 untouched benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation benchmark "devtool-source-map", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 40.1 ms 33.2 ms +20.65%
Memory benchmark "many-modules-commonjs", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 534.3 KB 387.1 KB +38.05%
Memory benchmark "context-esm", scenario '{"name":"mode-production","mode":"production"}' 8 MB 10.1 MB -20.42%
Memory benchmark "devtool-eval-source-map", scenario '{"name":"mode-production","mode":"production"}' 7.8 MB 6.3 MB +24.32%
Memory benchmark "react", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 645 KB 864.4 KB -25.39%

Comparing fix/import-meta-standalone-expression (269ad30) with main (8e6aed2)

Open in CodSpeed

"webpack": patch
---

fix: `import.meta` as standalone expression now returns a complete object with known properties (`url`, `webpack`, `main`, `env`) instead of an empty object `({})`, and hoists it as a module-level variable to ensure `import.meta === import.meta` identity. In `preserve-unknown` mode (ESM output), the hoisted object merges runtime `import.meta` properties via `Object.assign`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's remove fix: from here too, it will be in the patch section already

@alexander-akait
Copy link
Copy Markdown
Member

Ignore:

Github Actions / integration (ubuntu-latest, lts/*, a, 1) (pull_request)

it is already fixed in the main, it is due a new fix in enhanced-resolve, just another error message right now

@alexander-akait
Copy link
Copy Markdown
Member

@xiaoxiaojx looks like we still have some problems with test262

@xiaoxiaojx xiaoxiaojx force-pushed the fix/import-meta-standalone-expression branch 2 times, most recently from eda4b30 to 4678f05 Compare March 17, 2026 15:34
@xiaoxiaojx
Copy link
Copy Markdown
Member Author

@alexander-akait Yeah, the latest failure in import-attributes (text) doesn’t seem related to my changes — pulling the latest submodule on the main branch also fails. I'll continue looking into it tomorrow.

@alexander-akait
Copy link
Copy Markdown
Member

@xiaoxiaojx Yeah, let's add them to skip test and fix in other PR, I think they will be easy to fix

xiaoxiaojx and others added 11 commits March 18, 2026 01:39
Previously, standalone `import.meta` expressions (e.g., `return import.meta`,
`const meta = import.meta`) were replaced with an empty object `({})`, losing
all known properties and creating a new object on each reference.

Now uses ModuleInitFragmentDependency to hoist a `__webpack_import_meta__`
variable at module scope with url, webpack, main, and env properties. All
standalone `import.meta` references resolve to this single variable, ensuring
object identity (`import.meta === import.meta`) and property preservation.

In `preserve-unknown` mode (ESM output), the hoisted variable uses
`Object.assign(import.meta, {...})` to retain runtime-assigned properties.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Move comprehensive standalone import.meta tests (variable assignment,
return value, argument passing, object identity, runtime properties)
from test/cases/ to test/configCases/parsing/import-meta-standalone/
with ESM output config to avoid SyntaxError in non-module test suites.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Remove 5 import.meta test262 cases from the known bugs list:
- same-object-returned.js
- import-meta-is-an-ordinary-object.js
- distinct-for-each-module.js
- syntax/goal-module-nested-function.js
- syntax/goal-module.js

These now pass because standalone import.meta is hoisted as a
module-level variable with Object.assign(import.meta, {...}).

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Use parser.state.module.moduleArgument instead of RuntimeGlobals.module
in both standalone and destructuring paths. ModuleInitFragmentDependency
uses raw strings, so RuntimeGlobals.module resolves to literal "module"
but in ESM output the parameter is named __webpack_module__.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Bundler limitation: all modules in the bundle share a single
bundle-level import.meta object, so distinct-per-module identity
cannot be satisfied when using Object.assign(import.meta, {...}).

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
@xiaoxiaojx xiaoxiaojx force-pushed the fix/import-meta-standalone-expression branch from aac0c28 to 269ad30 Compare March 17, 2026 17:40
@github-actions
Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging fix/import-meta-standalone-expression into main will be
98.94%
Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
bin
   webpack.js98.77%100%100%98.77%91
examples
   build-common.js100%100%100%100%
   buildAll.js100%100%100%100%
   examples.js100%100%100%100%
   template-common.js98.21%100%100%98.21%72
examples/custom-javascript-parser
   test.filter.js100%100%100%100%
examples/custom-javascript-parser/internals
   acorn-parse.js100%100%100%100%
   meriyah-parse.js100%100%100%100%
   oxc-parse.js91.30%100%100%91.30%140, 142–143, 145, 147, 153–154, 161, 168, 90
examples/markdown
   webpack.config.mjs100%100%100%100%
examples/typescript
   test.filter.js50%100%100%50%5
examples/virtual-modules
   test.filter.js100%100%100%100%
examples/wasm-bindgen-esm
   test.filter.js100%100%100%100%
examples/wasm-complex
   test.filter.js100%100%100%100%
examples/wasm-simple
   test.filter.js100%100%100%100%
lib
   APIPlugin.js100%100%100%100%
   AbstractMethodError.js100%100%100%100%
   AsyncDependenciesBlock.js100%100%100%100%
   AsyncDependencyToInitialChunkError.js100%100%100%100%
   AutomaticPrefetchPlugin.js100%100%100%100%
   BannerPlugin.js100%100%100%100%
   Cache.js98.21%100%100%98.21%87
   CacheFacade.js100%100%100%100%
   CaseSensitiveModulesWarning.js100%100%100%100%
   Chunk.js99.72%100%100%99.72%37
   ChunkGraph.js100%100%100%100%
   ChunkGroup.js100%100%100%100%
   ChunkRenderError.js100%100%100%100%
   ChunkTemplate.js100%100%100%100%
   CleanPlugin.js98.72%100%100%98.72%196, 216, 371
   CodeGenerationError.js100%100%100%100%
   CodeGenerationResults.js100%100%100%100%
   CommentCompilationWarning.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.54%100%100%98.54%1510, 1799, 1806, 1814, 1836, 2712, 3130, 3778, 3807, 3859–3860, 3864, 3869, 3885–3886, 3900–3901, 3906–3907, 4369, 4395, 469, 474, 5078, 5158, 5173, 5198–5199, 5201, 5517, 5522, 5528, 5531, 5543, 5545, 5549, 5565, 5580, 5611, 5665, 5689, 5799, 680–681
   Compiler.js99.56%100%100%99.56%1091–1092, 1100
   ConcatenationScope.js98.59%100%100%98.59%166
   ConcurrentCompilationError.js100%100%100%100%
   ConditionalInitFragment.js100%100%100%100%
   ConstPlugin.js100%100%100%100%
   ContextExclusionPlugin.js100%100%100%100%
   ContextModule.js100%100%100%100%
   ContextModuleFactory.js97.75%100%100%97.75%253, 385, 410, 435, 439, 450
   ContextReplacementPlugin.js100%100%100%100%
   CssModule.js81.32%100%100%81.32%152, 157–172
   DefinePlugin.js98.92%100%100%98.92%153–154, 170, 189, 263
   DelegatedModule.js95.24%100%100%95.24%240–244
   DelegatedModuleFactoryPlugin.js98.15%100%100%98.15%103
   DelegatedPlugin.js100%100%100%100%
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.13%100%100%98.13%351, 381
   DependencyTemplate.js100%100%100%100%
   DependencyTemplates.js100%100%100%100%
   DllEntryPlugin.js100%100%100%100%
   DllModule.js100%100%100%100%
   DllModuleFactory.js100%100%100%100%
   DllPlugin.js100%100%100%100%
   DllReferencePlugin.js100%100%100%100%
   DotenvPlugin.js97.88%100%100%97.88%235, 375, 388–389
   DynamicEntryPlugin.js100%100%100%100%
   EntryOptionPlugin.js100%100%100%100%
   EntryPlugin.js100%100%100%100%
   Entrypoint.js100%100%100%100%
   EnvironmentNotSupportAsyncWarning.js100%100%100%100%
   EnvironmentPlugin.js97.14%100%100%97.14%48
   ErrorHelpers.js100%100%100%100%
   EvalDevToolModulePlugin.js100%100%100%100%
   EvalSourceMapDevToolPlugin.js100%100%100%100%
   ExportsInfo.js100%100%100%100%
   ExportsInfoApiPlugin.js100%100%100%100%
   ExternalModule.js98.89%100%100%98.89%385–389, 526
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FalseIIFEUmdWarning.js100%100%100%100%
   FileSystemInfo.js99.49%100%100%99.49%168, 2142–2143, 2146, 2157, 2168, 2179, 261, 3497, 3512, 3536
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.74%100%100%98.74%396, 398, 402
   FlagDependencyUsagePlugin.js100%100%100%100%
   FlagEntryExportAsUsedPlugin.js100%100%100%100%
   Generator.js100%100%100%100%
   GraphHelpers.js100%100%100%100%
   HarmonyLinkingError.js100%100%100%100%
   HookWebpackError.js100%100%100%100%
   HotModuleReplacementPlugin.js100%100%100%100%
   HotUpdateChunk.js100%100%100%100%
   IgnoreErrorModuleFactory.js100%100%100%100%
   IgnorePlugin.js100%100%100%100%
   IgnoreWarningsPlugin.js100%100%100%100%
   InitFragment.js100%100%100%100%
   InvalidDependenciesModuleWarning.js100%100%100%100%
   JavascriptMetaInfoPlugin.js100%100%100%100%
   LibManifestPlugin.js97.14%100%100%97.14%114, 117
   LibraryTemplatePlugin.js100%100%100%100%
   LoaderOptionsPlugin.js100%100%100%100%
   LoaderTargetPlugin.js100%100%100%100%
   MainTemplate.js100%100%100%100%
   ManifestPlugin.js100%100%100%100%
   Module.js98.50%100%100%98.50%1186, 1191, 1249, 1262, 1319, 1327
   ModuleBuildError.js100%100%100%100%
   ModuleDependencyError.js100%100%100%100%
   ModuleDependencyWarning.js100%100%100%100%
   ModuleError.js100%100%100%100%
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.85%100%100%98.85%105, 107
   ModuleGraph.js99.73%100%100%99.73%942
   ModuleGraphConnection.js100%100%100%100%
   ModuleHashingError.js100%100%100%100%
   ModuleInfoHeaderPlugin.js100%100%100%100%
   ModuleNotFoundError.js100%100%100%100%
   ModuleParseError.js100%100%100%100%
   ModuleProfile.js100%100%100%100%
   ModuleRestoreError.js100%100%100%100%
   ModuleSourceTypeConstants.js100%100%100%100%
   ModuleStoreError.js100%100%100%100%
   ModuleTemplate.js100%100%100%100%
   ModuleTypeConstants.js100%100%100%100%
   ModuleWarning.js100%100%100%100%
   MultiCompiler.js99.69%100%100%99.69%619
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NoModeWarning.js100%100%100%100%
   NodeStuffInWebError.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.78%100%100%97.78%1032, 1048, 1135, 1765, 1770–1780, 214, 722, 740, 757, 998
   NormalModuleFactory.js99.46%100%100%99.46%1032, 1337, 447, 459
   NormalModuleReplacementPlugin.js100%100%100%100%
   NullFactory.js100%100%100%100%
   OptimizationStages.js100%100%100%100%
   OptionsApply.js100%100%100%100%
   Parser.js100%100%100%100%
   PlatformPlugin.js100%100%100%100%
   PrefetchPlugin.js100%100%100%100%
   ProgressPlugin.js98.75%100%100%98.75%431–432, 437, 439, 503
   ProvidePlugin.js100%100%100%100%
   RawModule.js100%100%100%100%
   RecordIdsPlugin.js100%100%100%100%
   RequestShortener.js100%100%100%100%
   RequireJsStuffPlugin.js100%100%100%100%
   ResolverFactory.js100%100%100%100%
   RuntimeGlobals.js100%100%100%100%
   RuntimeModule.js100%100%100%100%
   RuntimePlugin.js100%100%100%100%
   RuntimeTemplate.js100%100%100%100%
   SelfModuleFactory.js100%100%100%100%
   SingleEntryPlugin.js100%100%100%100%
   SizeFormatHelpers.js100%100%100%100%
   SourceMapDevToolModuleOptionsPlugin.js100%100%100%100%
   SourceMapDevToolPlugin.js99.16%100%100%99.16%265–266, 608
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js98.84%100%100%98.84%128–129
   UnhandledSchemeError.js100%100%100%100%
   UnsupportedFeatureWarning.js100%100%100%100%
   UseStrictPlugin.js100%100%100%100%
   WarnCaseSensitiveModulesPlugin.js100%100%100%100%
   WarnDeprecatedOptionPlugin.js100%100%100%100%
   WarnNoModeSetPlugin.js100%100%100%100%
   WatchIgnorePlugin.js100%100%100%100%
   Watching.js100%100%100%100%
   WebpackError.js96.97%100%100%96.97%43
   WebpackIsIncludedPlugin.js100%100%100%100%
   WebpackOptionsApply.js100%100%100%100%
   WebpackOptionsDefaulter.js100%100%100%100%
   buildChunkGraph.js99.87%100%100%99.87%317
   cli.js98.71%100%100%98.71%109, 453, 485, 527, 785
   formatLocation.js100%100%100%100%
   index.js100%100%100%100%
   validateSchema.js94.67%100%100%94.67%86, 88, 97, 99
   webpack.js97.22%100%100%97.22%186, 208, 210
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModulesPlugin.js97.77%100%100%97.77%282, 306, 309, 361, 39
   AssetParser.js100%100%100%100%
   AssetSourceGenerator.js100%100%100%100%
   AssetSourceParser.js100%100%100%100%
   RawDataUrlModule.js100%100%100%100%
lib/async-modules
   AsyncModuleHelpers.js100%100%100%100%
   AwaitDependenciesInitFragment.js100%100%100%100%
   InferAsyncModulesPlugin.js100%100%100%100%
lib/cache
   AddBuildDependenciesPlugin.js100%100%100%100%
   AddManagedPathsPlugin.js100%100%100%100%
   IdleFileCachePlugin.js97.92%100%100%97.92%70, 82, 90
   MemoryCachePlugin.js95.83%100%100%95.83%33
   MemoryWithGcCachePlugin.js93.15%100%100%93.15%104, 111–112, 120, 87
   PackFileCacheStrategy.js96.40%100%100%96.40%1225,

@alexander-akait alexander-akait merged commit f757352 into main Mar 17, 2026
54 of 55 checks passed
@alexander-akait alexander-akait deleted the fix/import-meta-standalone-expression branch March 17, 2026 18:32
/Critical dependency: 'import\.meta' cannot be used as a standalone expression\. For static analysis, its properties must be accessed directly \(e\.g\., 'import\.meta\.url'\) or through destructuring\./
]
];
module.exports = [];
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pedantic: because this warnings.js file (and, similarly, import-meta/warnings.js) now exports an empty list of expected warnings: can it be removed entirely?

(I wonder whether eslint could have detected this if warnings.js files were not in the ignore-list?)

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.

3 participants