webpack 5.108.3 → 5.109.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/lib/APIPlugin.js +48 -29
  2. package/lib/CacheFacade.js +8 -0
  3. package/lib/ChunkGroup.js +1 -0
  4. package/lib/CompatibilityPlugin.js +31 -29
  5. package/lib/Compilation.js +50 -8
  6. package/lib/ConstPlugin.js +11 -11
  7. package/lib/ContextModule.js +239 -6
  8. package/lib/ContextModuleFactory.js +139 -14
  9. package/lib/DefinePlugin.js +396 -101
  10. package/lib/Entrypoint.js +1 -1
  11. package/lib/ExportsInfoApiPlugin.js +2 -2
  12. package/lib/ExternalModule.js +107 -5
  13. package/lib/ExternalModuleFactoryPlugin.js +20 -1
  14. package/lib/FileSystemInfo.js +130 -74
  15. package/lib/FlagDependencyExportsPlugin.js +55 -8
  16. package/lib/HotModuleReplacementPlugin.js +18 -15
  17. package/lib/LazyBarrel.js +30 -3
  18. package/lib/Module.js +3 -0
  19. package/lib/ModuleFilenameHelpers.js +2 -2
  20. package/lib/ModuleTypeConstants.js +8 -1
  21. package/lib/MultiCompiler.js +13 -2
  22. package/lib/MultiWatching.js +1 -0
  23. package/lib/NodeStuffPlugin.js +51 -33
  24. package/lib/NormalModule.js +169 -405
  25. package/lib/NormalModuleFactory.js +76 -2
  26. package/lib/ProgressPlugin.js +211 -119
  27. package/lib/ProvidePlugin.js +2 -2
  28. package/lib/RuntimeGlobals.js +47 -0
  29. package/lib/RuntimePlugin.js +33 -0
  30. package/lib/RuntimeTemplate.js +304 -16
  31. package/lib/UseStrictPlugin.js +1 -1
  32. package/lib/WebpackIsIncludedPlugin.js +1 -1
  33. package/lib/WebpackOptionsApply.js +24 -19
  34. package/lib/asset/AssetGenerator.js +110 -28
  35. package/lib/asset/AssetModulesPlugin.js +92 -2
  36. package/lib/asset/WebManifestGenerator.js +164 -0
  37. package/lib/asset/WebManifestParser.js +130 -0
  38. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  39. package/lib/async-modules/isGeneratorLowered.js +26 -0
  40. package/lib/cache/PackFileCacheStrategy.js +9 -3
  41. package/lib/config/browserslistTargetHandler.js +40 -0
  42. package/lib/config/defaults.js +222 -32
  43. package/lib/config/normalization.js +26 -0
  44. package/lib/config/target.js +9 -1
  45. package/lib/css/CssGenerator.js +73 -73
  46. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  47. package/lib/css/CssModulesPlugin.js +92 -53
  48. package/lib/css/CssParser.js +843 -302
  49. package/lib/css/syntax.js +1219 -483
  50. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  51. package/lib/dependencies/AMDPlugin.js +2 -2
  52. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  53. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  54. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  55. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  56. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  57. package/lib/dependencies/CommonJsPlugin.js +2 -2
  58. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  59. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  60. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  61. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  62. package/lib/dependencies/CssIcssExportDependency.js +190 -87
  63. package/lib/dependencies/CssUrlDependency.js +35 -4
  64. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  65. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  66. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  67. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  68. package/lib/dependencies/HarmonyImportDependency.js +12 -1
  69. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +34 -107
  70. package/lib/dependencies/HarmonyImportGuard.js +192 -20
  71. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  72. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  73. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  74. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  75. package/lib/dependencies/ImportDependency.js +43 -1
  76. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  77. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  78. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  79. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  80. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  81. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  82. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  83. package/lib/dependencies/ImportParserPlugin.js +87 -26
  84. package/lib/dependencies/ImportPhase.js +10 -8
  85. package/lib/dependencies/LoaderPlugin.js +5 -1
  86. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  87. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  88. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  89. package/lib/dependencies/SystemPlugin.js +2 -4
  90. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  91. package/lib/dependencies/URLDependency.js +141 -21
  92. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  93. package/lib/dependencies/WorkerDependency.js +86 -18
  94. package/lib/dependencies/WorkletDependency.js +278 -0
  95. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  96. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  97. package/lib/errors/LoaderLoadingError.js +20 -0
  98. package/lib/errors/ModuleParseError.js +39 -22
  99. package/lib/errors/NodeStuffInWebError.js +1 -1
  100. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  101. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  102. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  103. package/lib/hmr/lazyCompilationBackend.js +32 -8
  104. package/lib/html/HtmlGenerator.js +940 -91
  105. package/lib/html/HtmlModule.js +3 -2
  106. package/lib/html/HtmlModulesPlugin.js +625 -170
  107. package/lib/html/HtmlParser.js +812 -340
  108. package/lib/html/favicon.svg +1 -0
  109. package/lib/html/syntax.js +2116 -834
  110. package/lib/ids/IdHelpers.js +1 -1
  111. package/lib/index.js +6 -0
  112. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  113. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  114. package/lib/javascript/JavascriptGenerator.js +197 -49
  115. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  116. package/lib/javascript/JavascriptParser.js +711 -355
  117. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  118. package/lib/javascript/syntax.js +4380 -0
  119. package/lib/library/ModuleLibraryPlugin.js +38 -1
  120. package/lib/loaders/LoaderRunner.js +714 -0
  121. package/lib/loaders/loadLoader.js +100 -0
  122. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +19 -0
  123. package/lib/node/ReadFileCompileWasmPlugin.js +14 -0
  124. package/lib/optimize/ConcatenatedModule.js +120 -16
  125. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  126. package/lib/optimize/InnerGraphPlugin.js +50 -30
  127. package/lib/optimize/ModuleConcatenationPlugin.js +69 -3
  128. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  129. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  130. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  131. package/lib/prefetch/ResourceHintPlugin.js +663 -0
  132. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  133. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  134. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  135. package/lib/rules/RuleSetCompiler.js +114 -0
  136. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  137. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  138. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  139. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  140. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  141. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  142. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  143. package/lib/schemes/HttpUriPlugin.js +40 -1
  144. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  145. package/lib/serialization/FileMiddleware.js +29 -3
  146. package/lib/stats/DefaultStatsFactoryPlugin.js +32 -3
  147. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  148. package/lib/stats/DefaultStatsPrinterPlugin.js +12 -2
  149. package/lib/stats/StatsFactory.js +15 -8
  150. package/lib/url/URLParserPlugin.js +98 -19
  151. package/lib/util/AsyncQueue.js +122 -72
  152. package/lib/util/LocConverter.js +9 -8
  153. package/lib/util/SetHelpers.js +1 -1
  154. package/lib/util/SourceProcessor.js +41 -28
  155. package/lib/util/StackedMap.js +122 -48
  156. package/lib/util/binarySearchBounds.js +2 -2
  157. package/lib/util/concatenate.js +40 -14
  158. package/lib/util/createHooksRegistry.js +13 -5
  159. package/lib/util/dataURL.js +2 -2
  160. package/lib/util/deterministicGrouping.js +7 -5
  161. package/lib/util/formatSize.js +6 -2
  162. package/lib/util/globUtils.js +710 -0
  163. package/lib/util/identifier.js +23 -6
  164. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  165. package/lib/util/internalSerializables.js +88 -71
  166. package/lib/util/magicComment.js +121 -25
  167. package/lib/util/numberHash.js +2 -2
  168. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  169. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  170. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  171. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  172. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  173. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  174. package/lib/webpack.js +65 -0
  175. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  176. package/module.d.ts +21 -0
  177. package/package.json +14 -13
  178. package/schemas/WebpackOptions.check.js +1 -1
  179. package/schemas/WebpackOptions.json +759 -36
  180. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  181. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  182. package/schemas/plugins/ProgressPlugin.json +17 -1
  183. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  184. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  185. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  186. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  187. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  188. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  189. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  190. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  191. package/types.d.ts +1300 -325
@@ -22,9 +22,11 @@ const {
22
22
  evaluateToString,
23
23
  toConstantDependency
24
24
  } = require("../javascript/JavascriptParserHelpers");
25
+ const { getInnerGraphUtils } = require("../optimize/InnerGraph");
25
26
  const createHooksRegistry = require("../util/createHooksRegistry");
26
27
  const { propertyAccess } = require("../util/property");
27
28
  const ConstDependency = require("./ConstDependency");
29
+ const ImportMetaResolveDependency = require("./ImportMetaResolveDependency");
28
30
  const ModuleInitFragmentDependency = require("./ModuleInitFragmentDependency");
29
31
 
30
32
  // Loaded at module scope, not inside the parser handler: the async resolver
@@ -36,9 +38,15 @@ const WEBPACK_VERSION = Number.parseInt(
36
38
 
37
39
  /** @typedef {import("estree").MemberExpression} MemberExpression */
38
40
  /** @typedef {import("estree").Identifier} Identifier */
41
+ /** @typedef {import("estree").CallExpression} CallExpression */
42
+ /** @typedef {import("estree").Expression} Expression */
43
+ /** @typedef {import("estree").Super} Super */
39
44
  /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
40
45
  /** @typedef {import("../Compiler")} Compiler */
46
+ /** @typedef {import("../DefinePlugin").MergedDefinitionNode} MergedDefinitionNode */
41
47
  /** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
48
+ /** @typedef {import("../Module").ValueCacheVersion} ValueCacheVersion */
49
+ /** @typedef {import("../NormalModule").NormalModuleBuildInfo} NormalModuleBuildInfo */
42
50
  /** @typedef {import("../NormalModule")} NormalModule */
43
51
  /** @typedef {import("../javascript/JavascriptParser")} Parser */
44
52
  /** @typedef {import("../javascript/JavascriptParser").Range} Range */
@@ -55,6 +63,19 @@ const IMPORT_META_MAIN = "import.meta.main";
55
63
  const IMPORT_META_ENV = "import.meta.env";
56
64
  const IMPORT_META_DIRNAME = "import.meta.dirname";
57
65
  const IMPORT_META_FILENAME = "import.meta.filename";
66
+ const IMPORT_META_RESOLVE = "import.meta.resolve";
67
+
68
+ const IMPORT_META_FIELDS = new Set([
69
+ "url",
70
+ "webpack",
71
+ "main",
72
+ "env",
73
+ "dirname",
74
+ "filename",
75
+ "resolve",
76
+ "webpackContext",
77
+ "webpackHot"
78
+ ]);
58
79
 
59
80
  // Single source of truth for `import.meta` accesses that only exist in ES modules
60
81
  // and therefore mark a module as ESM (consumed by HarmonyDetectionParserPlugin).
@@ -68,39 +89,115 @@ const IMPORT_META_NAMES = [
68
89
  IMPORT_META_MAIN,
69
90
  IMPORT_META_ENV,
70
91
  IMPORT_META_DIRNAME,
71
- IMPORT_META_FILENAME
92
+ IMPORT_META_FILENAME,
93
+ IMPORT_META_RESOLVE
72
94
  ];
73
95
 
74
- /** @type {WeakMap<Compilation, { stringify: string, env: Record<string, string> }>} */
75
- const compilationMetaEnvMap = new WeakMap();
96
+ // Ordering contract for import.meta parser hooks across plugins: ESM detection
97
+ // (HarmonyDetectionParserPlugin, non-bailing) must observe every access before
98
+ // any bailing replacement; the merged replacements here must run before
99
+ // DefinePlugin object defines (default stage 0) and its nested destructuring
100
+ // handler (stage 100).
101
+ const IMPORT_META_STAGE_ESM_DETECTION = -1000;
102
+ const IMPORT_META_STAGE_REPLACEMENT = -100;
76
103
 
77
104
  /**
78
- * Collect import.meta.env definitions from DefinePlugin and build JSON string
105
+ * import.meta definitions collected from DefinePlugin's merged view.
106
+ * @typedef {object} ImportMetaDefinitions
107
+ * @property {MergedDefinitionNode | undefined} envNode `import.meta.env` node (a map unless custom-defined)
108
+ * @property {Map<string, MergedDefinitionNode>} customProps custom (non-field) property nodes
109
+ */
110
+
111
+ /** @type {WeakMap<Compilation, ImportMetaDefinitions>} */
112
+ const compilationMetaDefinitionsMap = new WeakMap();
113
+
114
+ /**
115
+ * Returns true if unknown import.meta properties should be preserved.
116
+ * @param {JavascriptParserOptions["importMeta"]} importMeta parser option
117
+ * @returns {boolean} true when unknown properties should be preserved
118
+ */
119
+ const preserveUnknown = (importMeta) =>
120
+ importMeta === "preserve-unknown" ||
121
+ (Boolean(importMeta) && typeof importMeta === "object");
122
+
123
+ /**
124
+ * Checks whether webpack should handle an import.meta field.
125
+ * @param {JavascriptParserOptions["importMeta"]} importMeta parser option
126
+ * @param {string} field field name
127
+ * @returns {boolean} true when the field should be handled
128
+ */
129
+ const isImportMetaFieldEnabled = (importMeta, field) => {
130
+ if (importMeta === false) {
131
+ return false;
132
+ }
133
+ return !(
134
+ Boolean(importMeta) &&
135
+ typeof importMeta === "object" &&
136
+ /** @type {Record<string, boolean | undefined>} */ (importMeta)[field] ===
137
+ false
138
+ );
139
+ };
140
+
141
+ /**
142
+ * Checks whether the callee is the `import.meta.resolve` member.
143
+ * @param {Expression | Super} callee call callee
144
+ * @returns {boolean} true when the callee is `import.meta.resolve`
145
+ */
146
+ const isImportMetaResolveCallee = (callee) =>
147
+ callee.type === "MemberExpression" &&
148
+ callee.object.type === "MetaProperty" &&
149
+ callee.object.meta.name === "import" &&
150
+ callee.object.property.name === "meta" &&
151
+ (callee.computed
152
+ ? callee.property.type === "Literal" && callee.property.value === "resolve"
153
+ : callee.property.type === "Identifier" &&
154
+ callee.property.name === "resolve");
155
+
156
+ /**
157
+ * Only a single statically known specifier maps to an asset.
158
+ * @param {CallExpression} call the call expression
159
+ * @param {Parser} parser the parser
160
+ * @returns {string | undefined} the resolved static specifier, if any
161
+ */
162
+ const getImportMetaResolveRequest = (call, parser) => {
163
+ if (call.arguments.length !== 1) return undefined;
164
+ const [arg] = call.arguments;
165
+ if (arg.type === "SpreadElement") return undefined;
166
+ return parser.evaluateExpression(arg).asString();
167
+ };
168
+
169
+ /**
170
+ * Collects import.meta definitions from DefinePlugin's merged view
171
+ * (object form and dotted keys of every instance).
79
172
  * @param {Compilation} compilation the compilation
80
- * @returns {{ stringify: string, env: Record<string, string> }} env object as JSON string
173
+ * @returns {ImportMetaDefinitions} collected definitions
81
174
  */
82
- const collectImportMetaEnvDefinitions = (compilation) => {
83
- const cached = compilationMetaEnvMap.get(compilation);
175
+ const collectImportMetaDefinitions = (compilation) => {
176
+ const cached = compilationMetaDefinitionsMap.get(compilation);
84
177
  if (cached) {
85
178
  return cached;
86
179
  }
87
180
 
88
- const definePluginHooks = DefinePlugin.getCompilationHooks(compilation);
89
- const definitions = definePluginHooks.definitions.call({});
90
- /** @type {Record<string, string>} */
91
- const env = {};
92
- /** @type {string[]} */
93
- const pairs = [];
94
- for (const key of Object.keys(definitions)) {
95
- if (key.startsWith("import.meta.env.")) {
96
- const envKey = key.slice("import.meta.env.".length);
97
- const value = definitions[key];
98
- pairs.push(`${JSON.stringify(envKey)}:${value}`);
99
- env[envKey] = /** @type {string} */ (value);
181
+ const metaNode = DefinePlugin.getMergedDefinitionNode(
182
+ compilation,
183
+ IMPORT_META
184
+ );
185
+ /** @type {MergedDefinitionNode | undefined} */
186
+ let envNode;
187
+ /** @type {Map<string, MergedDefinitionNode>} */
188
+ const customProps = new Map();
189
+ if (metaNode instanceof Map) {
190
+ for (const [prop, node] of metaNode) {
191
+ if (prop === "env") {
192
+ envNode = node;
193
+ } else if (!IMPORT_META_FIELDS.has(prop)) {
194
+ // fields (url, webpack, …) are handled by their own logic
195
+ customProps.set(prop, node);
196
+ }
100
197
  }
101
198
  }
102
- const result = { stringify: `{${pairs.join(",")}}`, env };
103
- compilationMetaEnvMap.set(compilation, result);
199
+ const result = { envNode, customProps };
200
+ compilationMetaDefinitionsMap.set(compilation, result);
104
201
  return result;
105
202
  };
106
203
 
@@ -125,6 +222,14 @@ class ImportMetaPlugin {
125
222
  ModuleInitFragmentDependency,
126
223
  new ModuleInitFragmentDependency.Template()
127
224
  );
225
+ compilation.dependencyFactories.set(
226
+ ImportMetaResolveDependency,
227
+ normalModuleFactory
228
+ );
229
+ compilation.dependencyTemplates.set(
230
+ ImportMetaResolveDependency,
231
+ new ImportMetaResolveDependency.Template()
232
+ );
128
233
 
129
234
  /**
130
235
  * Returns file url.
@@ -138,7 +243,7 @@ class ImportMetaPlugin {
138
243
  * @param {JavascriptParserOptions} parserOptions parserOptions
139
244
  * @returns {void}
140
245
  */
141
- const parserHandler = (parser, { importMeta }) => {
246
+ const parserHandler = (parser, { importMeta, url }) => {
142
247
  if (importMeta === false) {
143
248
  const { importMetaName } = compilation.outputOptions;
144
249
  if (importMetaName === "import.meta") return;
@@ -150,13 +255,92 @@ class ImportMetaPlugin {
150
255
  /** @type {string} */ (importMetaName),
151
256
  /** @type {Range} */ (metaProperty.range)
152
257
  );
153
- dep.loc = /** @type {DependencyLocation} */ (metaProperty.loc);
258
+ dep.loc = parser.getLocation(metaProperty);
154
259
  parser.state.module.addPresentationalDependency(dep);
155
260
  return true;
156
261
  });
157
262
  return;
158
263
  }
159
264
 
265
+ const { envNode, customProps: allCustomProps } =
266
+ collectImportMetaDefinitions(compilation);
267
+ // a non-object definition: DefinePlugin replaces the whole object
268
+ const envIsCustom =
269
+ envNode !== undefined && !(envNode instanceof Map);
270
+ // per-field parser options may disable custom properties too
271
+ /** @type {Map<string, MergedDefinitionNode>} */
272
+ const customProps = new Map();
273
+ for (const [prop, node] of allCustomProps) {
274
+ if (isImportMetaFieldEnabled(importMeta, prop)) {
275
+ customProps.set(prop, node);
276
+ }
277
+ }
278
+
279
+ /** @type {Map<string, ValueCacheVersion>} */
280
+ const definitionValueDependencies = new Map();
281
+ /**
282
+ * @param {string} name value cache key
283
+ */
284
+ const addDefinitionValueDependency = (name) => {
285
+ const version = compilation.valueCacheVersions.get(name);
286
+ // an undefined version would force a rebuild on every build
287
+ if (version !== undefined) {
288
+ definitionValueDependencies.set(name, version);
289
+ }
290
+ };
291
+ addDefinitionValueDependency(DefinePlugin.VALUE_DEP_MAIN);
292
+ if (isImportMetaFieldEnabled(importMeta, "env")) {
293
+ addDefinitionValueDependency(
294
+ DefinePlugin.VALUE_DEP_PREFIX + IMPORT_META_ENV
295
+ );
296
+ if (envNode instanceof Map) {
297
+ for (const envKey of envNode.keys()) {
298
+ addDefinitionValueDependency(
299
+ `${DefinePlugin.VALUE_DEP_PREFIX + IMPORT_META_ENV}.${envKey}`
300
+ );
301
+ }
302
+ }
303
+ }
304
+ for (const prop of customProps.keys()) {
305
+ addDefinitionValueDependency(
306
+ `${DefinePlugin.VALUE_DEP_PREFIX + IMPORT_META}.${prop}`
307
+ );
308
+ }
309
+ /**
310
+ * Records value dependencies for every inlined definition so
311
+ * cached modules rebuild when a definition value changes.
312
+ * @returns {void}
313
+ */
314
+ const addDefinitionValueDependencies = () => {
315
+ if (definitionValueDependencies.size === 0) return;
316
+ const buildInfo = /** @type {NormalModuleBuildInfo} */ (
317
+ parser.state.module.buildInfo
318
+ );
319
+ const valueDependencies =
320
+ buildInfo.valueDependencies ||
321
+ (buildInfo.valueDependencies = new Map());
322
+ for (const [name, version] of definitionValueDependencies) {
323
+ valueDependencies.set(name, version);
324
+ }
325
+ };
326
+ /**
327
+ * Renders a merged definition node at a use site.
328
+ * @param {MergedDefinitionNode | undefined} node node
329
+ * @param {string} key definition key
330
+ * @param {Set<string>=} objKeys used keys
331
+ * @returns {string} code
332
+ */
333
+ const renderDefinition = (node, key, objKeys) =>
334
+ node === undefined
335
+ ? "{}"
336
+ : DefinePlugin.stringifyMergedDefinition(
337
+ compilation,
338
+ parser,
339
+ node,
340
+ key,
341
+ objKeys
342
+ );
343
+
160
344
  // import.meta direct
161
345
  const importMetaUrl = () =>
162
346
  JSON.stringify(getUrl(parser.state.module));
@@ -168,13 +352,25 @@ class ImportMetaPlugin {
168
352
  * @returns {string} error message
169
353
  */
170
354
  const importMetaUnknownProperty = (members) => {
171
- if (importMeta === "preserve-unknown") {
355
+ if (
356
+ preserveUnknown(importMeta) ||
357
+ (IMPORT_META_FIELDS.has(members[0]) &&
358
+ !isImportMetaFieldEnabled(importMeta, members[0]))
359
+ ) {
172
360
  return `import.meta${propertyAccess(members, 0)}`;
173
361
  }
174
362
  return `${Template.toNormalComment(
175
363
  `unsupported import.meta.${members.join(".")}`
176
364
  )} undefined${propertyAccess(members, 1)}`;
177
365
  };
366
+ /**
367
+ * @param {string} field field name
368
+ * @returns {string} generated property
369
+ */
370
+ const importMetaRuntimeProperty = (field) =>
371
+ `[${JSON.stringify(field)}]: ${importMetaUnknownProperty([
372
+ field
373
+ ])},`;
178
374
 
179
375
  parser.hooks.typeof
180
376
  .for(IMPORT_META)
@@ -188,6 +384,15 @@ class ImportMetaPlugin {
188
384
  if (expr.type === "MetaProperty") return true;
189
385
  }
190
386
  );
387
+ // `import.meta` is always replaced by the synthesized object, so it
388
+ // must never become a variable alias: the alias declaration would keep
389
+ // the raw MetaProperty. Staged before DefinePlugin's canRename taps.
390
+ parser.hooks.canRename
391
+ .for(IMPORT_META)
392
+ .tap(
393
+ { name: PLUGIN_NAME, stage: IMPORT_META_STAGE_REPLACEMENT },
394
+ () => false
395
+ );
191
396
  parser.hooks.expression
192
397
  .for(IMPORT_META)
193
398
  .tap(PLUGIN_NAME, (metaProperty) => {
@@ -199,43 +404,75 @@ class ImportMetaPlugin {
199
404
  parser.destructuringAssignmentPropertiesFor(metaProperty);
200
405
  if (!referencedPropertiesInDestructuring) {
201
406
  const varName = "__webpack_import_meta__";
202
- const { stringify: envStringify } =
203
- collectImportMetaEnvDefinitions(compilation);
204
- const knownProps =
205
- `{url: ${importMetaUrl()}, ` +
206
- `webpack: ${importMetaWebpackVersion()}, ` +
207
- `main: ${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}] === ${moduleArgument}, ` +
208
- `env: ${envStringify}}`;
209
- const initCode =
210
- importMeta === "preserve-unknown"
211
- ? `var ${varName} = Object.assign(import.meta, ${knownProps});\n`
212
- : `var ${varName} = ${knownProps};\n`;
407
+ const knownProps = [];
408
+ if (isImportMetaFieldEnabled(importMeta, "url")) {
409
+ knownProps.push(`url: ${importMetaUrl()}`);
410
+ }
411
+ if (isImportMetaFieldEnabled(importMeta, "webpack")) {
412
+ knownProps.push(`webpack: ${importMetaWebpackVersion()}`);
413
+ }
414
+ if (isImportMetaFieldEnabled(importMeta, "main")) {
415
+ knownProps.push(
416
+ `main: ${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}] === ${moduleArgument}`
417
+ );
418
+ }
419
+ if (isImportMetaFieldEnabled(importMeta, "env")) {
420
+ addDefinitionValueDependencies();
421
+ knownProps.push(
422
+ `env: ${renderDefinition(envNode, IMPORT_META_ENV)}`
423
+ );
424
+ }
425
+ for (const [prop, node] of customProps) {
426
+ addDefinitionValueDependencies();
427
+ knownProps.push(
428
+ `${DefinePlugin.toPropertyKey(prop)}: ${renderDefinition(
429
+ node,
430
+ `${IMPORT_META}.${prop}`
431
+ )}`
432
+ );
433
+ }
434
+ const initCode = preserveUnknown(importMeta)
435
+ ? `var ${varName} = Object.assign(import.meta, {${knownProps.join(
436
+ ", "
437
+ )}});\n`
438
+ : `var ${varName} = {${knownProps.join(", ")}};\n`;
439
+ /** @type {RawRuntimeRequirements} */
440
+ const initRuntimeRequirements = [
441
+ RuntimeGlobals.moduleCache,
442
+ RuntimeGlobals.entryModuleId,
443
+ RuntimeGlobals.module
444
+ ];
445
+ const initCodeRequirements =
446
+ DefinePlugin.getRuntimeRequirements(initCode);
447
+ if (initCodeRequirements) {
448
+ initRuntimeRequirements.push(...initCodeRequirements);
449
+ }
213
450
  const initDep = new ModuleInitFragmentDependency(
214
451
  initCode,
215
- [
216
- RuntimeGlobals.moduleCache,
217
- RuntimeGlobals.entryModuleId,
218
- RuntimeGlobals.module
219
- ],
452
+ initRuntimeRequirements,
220
453
  varName
221
454
  );
222
- initDep.loc = /** @type {DependencyLocation} */ (
223
- metaProperty.loc
224
- );
455
+ initDep.loc = parser.getLocation(metaProperty);
225
456
  parser.state.module.addPresentationalDependency(initDep);
226
457
  const dep = new ConstDependency(
227
458
  varName,
228
459
  /** @type {Range} */ (metaProperty.range),
229
460
  runtimeRequirements
230
461
  );
231
- dep.loc = /** @type {DependencyLocation} */ (metaProperty.loc);
462
+ dep.loc = parser.getLocation(metaProperty);
232
463
  parser.state.module.addPresentationalDependency(dep);
233
464
  return true;
234
465
  }
235
466
 
236
467
  let str = "";
237
468
  for (const prop of referencedPropertiesInDestructuring) {
238
- const value = hooks.propertyInDestructuring.call(prop);
469
+ const fieldEnabled = isImportMetaFieldEnabled(
470
+ importMeta,
471
+ prop.id
472
+ );
473
+ const value = fieldEnabled
474
+ ? hooks.propertyInDestructuring.call(prop)
475
+ : undefined;
239
476
 
240
477
  if (value) {
241
478
  str += value;
@@ -244,37 +481,62 @@ class ImportMetaPlugin {
244
481
 
245
482
  switch (prop.id) {
246
483
  case "url":
247
- str += `url: ${importMetaUrl()},`;
484
+ str += fieldEnabled
485
+ ? `url: ${importMetaUrl()},`
486
+ : importMetaRuntimeProperty(prop.id);
248
487
  break;
249
488
  case "webpack":
250
- str += `webpack: ${importMetaWebpackVersion()},`;
489
+ str += fieldEnabled
490
+ ? `webpack: ${importMetaWebpackVersion()},`
491
+ : importMetaRuntimeProperty(prop.id);
251
492
  break;
252
493
  case "main":
253
- str += `main: ${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}] === ${moduleArgument},`;
254
- runtimeRequirements.push(
255
- RuntimeGlobals.moduleCache,
256
- RuntimeGlobals.entryModuleId,
257
- RuntimeGlobals.module
258
- );
494
+ if (fieldEnabled) {
495
+ str += `main: ${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}] === ${moduleArgument},`;
496
+ runtimeRequirements.push(
497
+ RuntimeGlobals.moduleCache,
498
+ RuntimeGlobals.entryModuleId,
499
+ RuntimeGlobals.module
500
+ );
501
+ } else {
502
+ str += importMetaRuntimeProperty(prop.id);
503
+ }
259
504
  break;
260
505
  case "env":
261
- str += `env: ${
262
- collectImportMetaEnvDefinitions(compilation).stringify
263
- },`;
506
+ if (fieldEnabled) {
507
+ addDefinitionValueDependencies();
508
+ str += `env: ${renderDefinition(envNode, IMPORT_META_ENV)},`;
509
+ } else {
510
+ str += importMetaRuntimeProperty(prop.id);
511
+ }
264
512
  break;
265
- default:
266
- str += `[${JSON.stringify(
267
- prop.id
268
- )}]: ${importMetaUnknownProperty([prop.id])},`;
513
+ default: {
514
+ const node = customProps.get(prop.id);
515
+ if (node !== undefined) {
516
+ addDefinitionValueDependencies();
517
+ str += `${DefinePlugin.toPropertyKey(prop.id)}: ${renderDefinition(
518
+ node,
519
+ `${IMPORT_META}.${prop.id}`
520
+ )},`;
521
+ } else {
522
+ str += importMetaRuntimeProperty(prop.id);
523
+ }
269
524
  break;
525
+ }
270
526
  }
271
527
  }
528
+ const strCode = `({${str}})`;
529
+ const codeRequirements =
530
+ DefinePlugin.getRuntimeRequirements(strCode);
531
+ if (codeRequirements) {
532
+ runtimeRequirements.push(...codeRequirements);
533
+ }
272
534
  const dep = new ConstDependency(
273
- `({${str}})`,
535
+ strCode,
274
536
  /** @type {Range} */ (metaProperty.range),
275
537
  runtimeRequirements
276
538
  );
277
- dep.loc = /** @type {DependencyLocation} */ (metaProperty.loc);
539
+ dep.loc = parser.getLocation(metaProperty);
278
540
  parser.state.module.addPresentationalDependency(dep);
279
541
  return true;
280
542
  });
@@ -286,135 +548,216 @@ class ImportMetaPlugin {
286
548
  evaluateToIdentifier(IMPORT_META, IMPORT_META, () => [], true)
287
549
  );
288
550
 
551
+ // custom import.meta properties defined only via nested dotted keys,
552
+ // e.g. reading `import.meta.build` with `"import.meta.build.time"` defined
553
+ if (customProps.size > 0) {
554
+ parser.hooks.expressionMemberChain
555
+ .for(IMPORT_META)
556
+ .tap(PLUGIN_NAME, (expr, members) => {
557
+ const node = customProps.get(members[0]);
558
+ if (node === undefined) return;
559
+ addDefinitionValueDependencies();
560
+ const strCode = `(${renderDefinition(
561
+ node,
562
+ `${IMPORT_META}.${members[0]}`
563
+ )})${propertyAccess(members, 1)}`;
564
+ return toConstantDependency(
565
+ parser,
566
+ strCode,
567
+ DefinePlugin.getRuntimeRequirements(strCode)
568
+ )(expr);
569
+ });
570
+ }
571
+
572
+ // import.meta.resolve — resolve a static specifier to the emitted
573
+ // asset URL string (the string form of `new URL(x, import.meta.url)`).
574
+ if (isImportMetaFieldEnabled(importMeta, "resolve")) {
575
+ const relative = url === "relative";
576
+ parser.hooks.call
577
+ .for(IMPORT_META_RESOLVE)
578
+ .tap(PLUGIN_NAME, (expr) => {
579
+ const call = /** @type {CallExpression} */ (expr);
580
+ // Non-static forms are left untouched for runtime evaluation.
581
+ const request = getImportMetaResolveRequest(call, parser);
582
+ if (request === undefined) return;
583
+ const range = /** @type {Range} */ (call.range);
584
+ const dep = new ImportMetaResolveDependency(
585
+ request,
586
+ range,
587
+ range,
588
+ relative
589
+ );
590
+ dep.loc = parser.getLocation(call);
591
+ parser.state.current.addDependency(dep);
592
+ getInnerGraphUtils(parser.state.compilation).onUsage(
593
+ parser.state,
594
+ (e) => (dep.usedByExports = e)
595
+ );
596
+ return true;
597
+ });
598
+ // Computing a URL string is side-effect free, so an unused result
599
+ // can be tree-shaken (matching `new URL(..., import.meta.url)`).
600
+ parser.hooks.isPure
601
+ .for("CallExpression")
602
+ .tap(PLUGIN_NAME, (expr) => {
603
+ const call = /** @type {CallExpression} */ (expr);
604
+ if (!isImportMetaResolveCallee(call.callee)) return;
605
+ if (getImportMetaResolveRequest(call, parser) !== undefined) {
606
+ return true;
607
+ }
608
+ });
609
+ }
610
+
289
611
  // import.meta.url
290
- parser.hooks.typeof
291
- .for(IMPORT_META_URL)
292
- .tap(
293
- PLUGIN_NAME,
294
- toConstantDependency(parser, JSON.stringify("string"))
295
- );
296
- parser.hooks.expression
297
- .for(IMPORT_META_URL)
298
- .tap(PLUGIN_NAME, (expr) => {
299
- const dep = new ConstDependency(
300
- importMetaUrl(),
301
- /** @type {Range} */ (expr.range)
612
+ if (isImportMetaFieldEnabled(importMeta, "url")) {
613
+ parser.hooks.typeof
614
+ .for(IMPORT_META_URL)
615
+ .tap(
616
+ PLUGIN_NAME,
617
+ toConstantDependency(parser, JSON.stringify("string"))
302
618
  );
303
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
304
- parser.state.module.addPresentationalDependency(dep);
305
- return true;
306
- });
307
- parser.hooks.evaluateTypeof
308
- .for(IMPORT_META_URL)
309
- .tap(PLUGIN_NAME, evaluateToString("string"));
310
- parser.hooks.evaluateIdentifier
311
- .for(IMPORT_META_URL)
312
- .tap(PLUGIN_NAME, (expr) =>
313
- new BasicEvaluatedExpression()
314
- .setString(getUrl(parser.state.module))
315
- .setRange(/** @type {Range} */ (expr.range))
316
- );
619
+ parser.hooks.expression
620
+ .for(IMPORT_META_URL)
621
+ .tap(PLUGIN_NAME, (expr) => {
622
+ const dep = new ConstDependency(
623
+ importMetaUrl(),
624
+ /** @type {Range} */ (expr.range)
625
+ );
626
+ dep.loc = parser.getLocation(expr);
627
+ parser.state.module.addPresentationalDependency(dep);
628
+ return true;
629
+ });
630
+ parser.hooks.evaluateTypeof
631
+ .for(IMPORT_META_URL)
632
+ .tap(PLUGIN_NAME, evaluateToString("string"));
633
+ parser.hooks.evaluateIdentifier
634
+ .for(IMPORT_META_URL)
635
+ .tap(PLUGIN_NAME, (expr) =>
636
+ new BasicEvaluatedExpression()
637
+ .setString(getUrl(parser.state.module))
638
+ .setRange(/** @type {Range} */ (expr.range))
639
+ );
640
+ }
317
641
 
318
642
  // import.meta.webpack
319
- parser.hooks.expression
320
- .for(IMPORT_META_WEBPACK)
321
- .tap(
322
- PLUGIN_NAME,
323
- toConstantDependency(parser, importMetaWebpackVersion())
324
- );
325
- parser.hooks.typeof
326
- .for(IMPORT_META_WEBPACK)
327
- .tap(
328
- PLUGIN_NAME,
329
- toConstantDependency(parser, JSON.stringify("number"))
330
- );
331
- parser.hooks.evaluateTypeof
332
- .for(IMPORT_META_WEBPACK)
333
- .tap(PLUGIN_NAME, evaluateToString("number"));
334
- parser.hooks.evaluateIdentifier
335
- .for(IMPORT_META_WEBPACK)
336
- .tap(PLUGIN_NAME, evaluateToNumber(WEBPACK_VERSION));
643
+ if (isImportMetaFieldEnabled(importMeta, "webpack")) {
644
+ parser.hooks.expression
645
+ .for(IMPORT_META_WEBPACK)
646
+ .tap(
647
+ PLUGIN_NAME,
648
+ toConstantDependency(parser, importMetaWebpackVersion())
649
+ );
650
+ parser.hooks.typeof
651
+ .for(IMPORT_META_WEBPACK)
652
+ .tap(
653
+ PLUGIN_NAME,
654
+ toConstantDependency(parser, JSON.stringify("number"))
655
+ );
656
+ parser.hooks.evaluateTypeof
657
+ .for(IMPORT_META_WEBPACK)
658
+ .tap(PLUGIN_NAME, evaluateToString("number"));
659
+ parser.hooks.evaluateIdentifier
660
+ .for(IMPORT_META_WEBPACK)
661
+ .tap(PLUGIN_NAME, evaluateToNumber(WEBPACK_VERSION));
662
+ }
337
663
 
338
- parser.hooks.expression
339
- .for(IMPORT_META_MAIN)
340
- .tap(
341
- PLUGIN_NAME,
342
- toConstantDependency(
343
- parser,
344
- `${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}] === ${RuntimeGlobals.module}`,
345
- [
346
- RuntimeGlobals.moduleCache,
347
- RuntimeGlobals.entryModuleId,
348
- RuntimeGlobals.module
349
- ]
350
- )
351
- );
352
- parser.hooks.typeof
353
- .for(IMPORT_META_MAIN)
354
- .tap(
355
- PLUGIN_NAME,
356
- toConstantDependency(parser, JSON.stringify("boolean"))
357
- );
358
- parser.hooks.evaluateTypeof
359
- .for(IMPORT_META_MAIN)
360
- .tap(PLUGIN_NAME, evaluateToString("boolean"));
664
+ if (isImportMetaFieldEnabled(importMeta, "main")) {
665
+ parser.hooks.expression
666
+ .for(IMPORT_META_MAIN)
667
+ .tap(
668
+ PLUGIN_NAME,
669
+ toConstantDependency(
670
+ parser,
671
+ `${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}] === ${RuntimeGlobals.module}`,
672
+ [
673
+ RuntimeGlobals.moduleCache,
674
+ RuntimeGlobals.entryModuleId,
675
+ RuntimeGlobals.module
676
+ ]
677
+ )
678
+ );
679
+ parser.hooks.typeof
680
+ .for(IMPORT_META_MAIN)
681
+ .tap(
682
+ PLUGIN_NAME,
683
+ toConstantDependency(parser, JSON.stringify("boolean"))
684
+ );
685
+ parser.hooks.evaluateTypeof
686
+ .for(IMPORT_META_MAIN)
687
+ .tap(PLUGIN_NAME, evaluateToString("boolean"));
688
+ }
361
689
 
362
690
  // import.meta.env
363
- parser.hooks.typeof
364
- .for(IMPORT_META_ENV)
365
- .tap(
366
- PLUGIN_NAME,
367
- toConstantDependency(parser, JSON.stringify("object"))
368
- );
369
- parser.hooks.expressionMemberChain
370
- .for(IMPORT_META)
371
- .tap(PLUGIN_NAME, (expr, members) => {
372
- if (members[0] === "env" && members[1]) {
373
- const name = members[1];
374
- const { env } = collectImportMetaEnvDefinitions(compilation);
375
- if (!Object.prototype.hasOwnProperty.call(env, name)) {
376
- const dep = new ConstDependency(
377
- "undefined",
378
- /** @type {Range} */ (expr.range)
379
- );
380
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
381
- parser.state.module.addPresentationalDependency(dep);
382
- return true;
691
+ if (isImportMetaFieldEnabled(importMeta, "env")) {
692
+ parser.hooks.typeof
693
+ .for(IMPORT_META_ENV)
694
+ .tap(
695
+ PLUGIN_NAME,
696
+ toConstantDependency(parser, JSON.stringify("object"))
697
+ );
698
+ parser.hooks.expressionMemberChain
699
+ .for(IMPORT_META)
700
+ .tap(PLUGIN_NAME, (expr, members) => {
701
+ if (members[0] === "env" && members[1]) {
702
+ // members of a custom definition resolve on it at runtime
703
+ if (envIsCustom) return;
704
+ if (!(envNode instanceof Map) || !envNode.has(members[1])) {
705
+ return toConstantDependency(parser, "undefined")(expr);
706
+ }
383
707
  }
708
+ });
709
+ parser.hooks.expression.for(IMPORT_META_ENV).tap(
710
+ // before DefinePlugin object defines: merge every definition source
711
+ { name: PLUGIN_NAME, stage: IMPORT_META_STAGE_REPLACEMENT },
712
+ (expr) => {
713
+ // a custom definition replaces the whole object via DefinePlugin
714
+ if (envIsCustom) return;
715
+ addDefinitionValueDependencies();
716
+ const destructured =
717
+ parser.destructuringAssignmentPropertiesFor(expr);
718
+ const objKeys =
719
+ destructured &&
720
+ new Set([...destructured].map((prop) => prop.id));
721
+ const code = renderDefinition(
722
+ envNode,
723
+ IMPORT_META_ENV,
724
+ objKeys
725
+ );
726
+ const strCode = parser.isAsiPosition(
727
+ /** @type {Range} */ (expr.range)[0]
728
+ )
729
+ ? `;(${code})`
730
+ : `(${code})`;
731
+ return toConstantDependency(
732
+ parser,
733
+ strCode,
734
+ DefinePlugin.getRuntimeRequirements(strCode)
735
+ )(expr);
384
736
  }
385
- });
386
- parser.hooks.expression
387
- .for(IMPORT_META_ENV)
388
- .tap(PLUGIN_NAME, (expr) => {
389
- const { stringify } =
390
- collectImportMetaEnvDefinitions(compilation);
391
-
392
- const dep = new ConstDependency(
393
- stringify,
394
- /** @type {Range} */ (expr.range)
395
- );
396
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
397
- parser.state.module.addPresentationalDependency(dep);
398
- return true;
399
- });
400
- parser.hooks.evaluateTypeof
401
- .for(IMPORT_META_ENV)
402
- .tap(PLUGIN_NAME, evaluateToString("object"));
403
- parser.hooks.evaluateIdentifier
404
- .for(IMPORT_META_ENV)
405
- .tap(PLUGIN_NAME, (expr) =>
406
- new BasicEvaluatedExpression()
407
- .setTruthy()
408
- .setSideEffects(false)
409
- .setRange(/** @type {Range} */ (expr.range))
410
737
  );
738
+ parser.hooks.evaluateTypeof
739
+ .for(IMPORT_META_ENV)
740
+ .tap(PLUGIN_NAME, evaluateToString("object"));
741
+ parser.hooks.evaluateIdentifier
742
+ .for(IMPORT_META_ENV)
743
+ .tap(PLUGIN_NAME, (expr) =>
744
+ new BasicEvaluatedExpression()
745
+ .setTruthy()
746
+ .setSideEffects(false)
747
+ .setRange(/** @type {Range} */ (expr.range))
748
+ );
749
+ }
411
750
 
412
751
  // Unknown properties
413
752
  parser.hooks.unhandledExpressionMemberChain
414
753
  .for(IMPORT_META)
415
754
  .tap(PLUGIN_NAME, (expr, members) => {
416
755
  // unknown import.meta properties should be determined at runtime
417
- if (importMeta === "preserve-unknown") {
756
+ if (
757
+ preserveUnknown(importMeta) ||
758
+ (IMPORT_META_FIELDS.has(members[0]) &&
759
+ !isImportMetaFieldEnabled(importMeta, members[0]))
760
+ ) {
418
761
  return true;
419
762
  }
420
763
 
@@ -432,7 +775,7 @@ class ImportMetaPlugin {
432
775
  importMetaUnknownProperty(members),
433
776
  /** @type {Range} */ (expr.range)
434
777
  );
435
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
778
+ dep.loc = parser.getLocation(expr);
436
779
  parser.state.module.addPresentationalDependency(dep);
437
780
  return true;
438
781
  });
@@ -452,14 +795,20 @@ class ImportMetaPlugin {
452
795
  ? /** @type {import("estree").Literal} */ (expr.property)
453
796
  .value
454
797
  : /** @type {Identifier} */ (expr.property).name;
455
- // dirname/filename are resolved by NodeStuffPlugin; main is a runtime value
456
798
  if (
457
- prop === "dirname" ||
458
- prop === "filename" ||
459
- prop === "main"
799
+ !isImportMetaFieldEnabled(importMeta, String(prop)) ||
800
+ (preserveUnknown(importMeta) &&
801
+ !IMPORT_META_FIELDS.has(String(prop)))
460
802
  ) {
461
803
  return;
462
804
  }
805
+ if (IMPORT_META_FIELDS.has(String(prop))) {
806
+ return;
807
+ }
808
+ // custom-defined properties evaluate via DefinePlugin/runtime
809
+ if (customProps.has(String(prop))) {
810
+ return;
811
+ }
463
812
  return new BasicEvaluatedExpression()
464
813
  .setUndefined()
465
814
  .setRange(/** @type {Range} */ (expr.range));
@@ -489,3 +838,6 @@ module.exports = ImportMetaPlugin;
489
838
  module.exports.IMPORT_META_DIRNAME = IMPORT_META_DIRNAME;
490
839
  module.exports.IMPORT_META_FILENAME = IMPORT_META_FILENAME;
491
840
  module.exports.IMPORT_META_NAMES = IMPORT_META_NAMES;
841
+ module.exports.IMPORT_META_STAGE_ESM_DETECTION =
842
+ IMPORT_META_STAGE_ESM_DETECTION;
843
+ module.exports.isImportMetaFieldEnabled = isImportMetaFieldEnabled;