webpack 5.102.0 → 5.103.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 (146) hide show
  1. package/README.md +121 -134
  2. package/lib/ChunkGraph.js +2 -2
  3. package/lib/CodeGenerationResults.js +1 -1
  4. package/lib/CompatibilityPlugin.js +25 -2
  5. package/lib/Compilation.js +30 -13
  6. package/lib/ConcatenationScope.js +0 -15
  7. package/lib/ContextModule.js +3 -1
  8. package/lib/CssModule.js +6 -1
  9. package/lib/DefinePlugin.js +12 -12
  10. package/lib/Dependency.js +8 -1
  11. package/lib/DependencyTemplate.js +1 -0
  12. package/lib/DependencyTemplates.js +1 -1
  13. package/lib/DotenvPlugin.js +457 -0
  14. package/lib/EnvironmentPlugin.js +19 -16
  15. package/lib/EvalSourceMapDevToolPlugin.js +16 -0
  16. package/lib/ExportsInfo.js +6 -2
  17. package/lib/ExternalModule.js +20 -28
  18. package/lib/ExternalModuleFactoryPlugin.js +10 -8
  19. package/lib/ExternalsPlugin.js +2 -1
  20. package/lib/FileSystemInfo.js +9 -12
  21. package/lib/ManifestPlugin.js +235 -0
  22. package/lib/Module.js +3 -0
  23. package/lib/ModuleFilenameHelpers.js +1 -1
  24. package/lib/ModuleGraph.js +2 -1
  25. package/lib/ModuleSourceTypesConstants.js +0 -6
  26. package/lib/MultiCompiler.js +1 -1
  27. package/lib/NodeStuffPlugin.js +419 -121
  28. package/lib/NormalModule.js +18 -17
  29. package/lib/NormalModuleFactory.js +75 -4
  30. package/lib/RuntimeGlobals.js +22 -4
  31. package/lib/RuntimePlugin.js +27 -6
  32. package/lib/RuntimeTemplate.js +125 -57
  33. package/lib/SourceMapDevToolPlugin.js +26 -8
  34. package/lib/WebpackOptionsApply.js +33 -9
  35. package/lib/asset/AssetBytesGenerator.js +2 -1
  36. package/lib/asset/AssetGenerator.js +3 -5
  37. package/lib/asset/AssetSourceGenerator.js +1 -1
  38. package/lib/cache/getLazyHashedEtag.js +1 -1
  39. package/lib/config/browserslistTargetHandler.js +82 -76
  40. package/lib/config/defaults.js +105 -20
  41. package/lib/config/normalization.js +2 -1
  42. package/lib/config/target.js +7 -1
  43. package/lib/css/CssGenerator.js +283 -57
  44. package/lib/css/CssLoadingRuntimeModule.js +2 -0
  45. package/lib/css/CssMergeStyleSheetsRuntimeModule.js +56 -0
  46. package/lib/css/CssModulesPlugin.js +86 -40
  47. package/lib/css/CssParser.js +1174 -667
  48. package/lib/css/walkCssTokens.js +98 -1
  49. package/lib/dependencies/CommonJsImportsParserPlugin.js +0 -9
  50. package/lib/dependencies/CommonJsPlugin.js +12 -0
  51. package/lib/dependencies/ContextElementDependency.js +2 -2
  52. package/lib/dependencies/CssIcssExportDependency.js +247 -8
  53. package/lib/dependencies/CssIcssFromIdentifierDependency.js +124 -0
  54. package/lib/dependencies/CssIcssGlobalIdentifierDependency.js +48 -0
  55. package/lib/dependencies/CssIcssImportDependency.js +60 -54
  56. package/lib/dependencies/CssIcssLocalIdentifierDependency.js +61 -0
  57. package/lib/dependencies/{CssSelfLocalIdentifierDependency.js → CssIcssSelfLocalIdentifierDependency.js} +88 -10
  58. package/lib/dependencies/CssIcssSymbolDependency.js +31 -29
  59. package/lib/dependencies/CssImportDependency.js +15 -5
  60. package/lib/dependencies/ExternalModuleInitFragment.js +1 -1
  61. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +95 -0
  62. package/lib/dependencies/HarmonyAcceptDependency.js +6 -1
  63. package/lib/dependencies/HarmonyAcceptImportDependency.js +2 -1
  64. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +12 -1
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +32 -21
  66. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +12 -8
  67. package/lib/dependencies/HarmonyImportDependency.js +27 -28
  68. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +28 -69
  69. package/lib/dependencies/HarmonyImportSideEffectDependency.js +4 -3
  70. package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -8
  71. package/lib/dependencies/ImportContextDependency.js +13 -0
  72. package/lib/dependencies/ImportDependency.js +10 -4
  73. package/lib/dependencies/ImportEagerDependency.js +6 -3
  74. package/lib/dependencies/ImportMetaPlugin.js +98 -10
  75. package/lib/dependencies/ImportParserPlugin.js +19 -21
  76. package/lib/dependencies/ImportPhase.js +121 -0
  77. package/lib/dependencies/ImportWeakDependency.js +6 -3
  78. package/lib/dependencies/ModuleDependency.js +5 -1
  79. package/lib/dependencies/ModuleHotAcceptDependency.js +1 -1
  80. package/lib/dependencies/WorkerPlugin.js +1 -3
  81. package/lib/esm/ExportWebpackRequireRuntimeModule.js +1 -8
  82. package/lib/hmr/LazyCompilationPlugin.js +1 -0
  83. package/lib/ids/HashedModuleIdsPlugin.js +5 -7
  84. package/lib/ids/IdHelpers.js +5 -2
  85. package/lib/index.js +6 -0
  86. package/lib/javascript/ChunkHelpers.js +16 -5
  87. package/lib/javascript/JavascriptGenerator.js +101 -101
  88. package/lib/javascript/JavascriptModulesPlugin.js +25 -16
  89. package/lib/javascript/JavascriptParser.js +143 -39
  90. package/lib/json/JsonParser.js +7 -1
  91. package/lib/library/ModuleLibraryPlugin.js +0 -10
  92. package/lib/library/SystemLibraryPlugin.js +19 -5
  93. package/lib/library/UmdLibraryPlugin.js +1 -1
  94. package/lib/node/NodeTargetPlugin.js +9 -1
  95. package/lib/node/ReadFileCompileWasmPlugin.js +0 -2
  96. package/lib/optimize/ConcatenatedModule.js +161 -135
  97. package/lib/optimize/RealContentHashPlugin.js +5 -3
  98. package/lib/runtime/AsyncModuleRuntimeModule.js +28 -18
  99. package/lib/runtime/AutoPublicPathRuntimeModule.js +8 -3
  100. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +89 -55
  101. package/lib/serialization/FileMiddleware.js +1 -1
  102. package/lib/serialization/ObjectMiddleware.js +1 -1
  103. package/lib/stats/DefaultStatsFactoryPlugin.js +1 -1
  104. package/lib/util/Hash.js +35 -5
  105. package/lib/util/comparators.js +4 -3
  106. package/lib/util/create-schema-validation.js +1 -1
  107. package/lib/util/createHash.js +85 -15
  108. package/lib/util/hash/BatchedHash.js +47 -8
  109. package/lib/util/hash/wasm-hash.js +53 -13
  110. package/lib/util/internalSerializables.js +4 -4
  111. package/lib/util/jsonParseEvenBetterErrors.js +10 -0
  112. package/lib/wasm/EnableWasmLoadingPlugin.js +10 -4
  113. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +8 -5
  114. package/lib/wasm-async/AsyncWebAssemblyParser.js +0 -9
  115. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +8 -4
  116. package/lib/wasm-sync/WebAssemblyParser.js +0 -9
  117. package/lib/web/FetchCompileWasmPlugin.js +0 -2
  118. package/lib/web/JsonpChunkLoadingRuntimeModule.js +1 -1
  119. package/lib/webpack.js +85 -82
  120. package/module.d.ts +5 -0
  121. package/package.json +28 -26
  122. package/schemas/WebpackOptions.check.js +1 -1
  123. package/schemas/WebpackOptions.json +110 -15
  124. package/schemas/plugins/{HashedModuleIdsPlugin.check.d.ts → ManifestPlugin.check.d.ts} +1 -1
  125. package/schemas/plugins/ManifestPlugin.check.js +6 -0
  126. package/schemas/plugins/ManifestPlugin.json +98 -0
  127. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  128. package/schemas/plugins/SourceMapDevToolPlugin.json +16 -3
  129. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  130. package/schemas/plugins/container/ContainerReferencePlugin.json +4 -1
  131. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  132. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  133. package/schemas/plugins/container/ModuleFederationPlugin.json +4 -1
  134. package/schemas/plugins/css/CssAutoParserOptions.check.js +1 -1
  135. package/schemas/plugins/css/CssGlobalGeneratorOptions.check.js +1 -1
  136. package/schemas/plugins/css/CssGlobalParserOptions.check.js +1 -1
  137. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +1 -1
  138. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  139. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  140. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.d.ts +7 -0
  141. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +6 -0
  142. package/schemas/plugins/{HashedModuleIdsPlugin.json → ids/HashedModuleIdsPlugin.json} +15 -2
  143. package/schemas/plugins/json/JsonModulesPluginParser.check.js +1 -1
  144. package/types.d.ts +788 -127
  145. package/lib/dependencies/CssLocalIdentifierDependency.js +0 -252
  146. package/schemas/plugins/HashedModuleIdsPlugin.check.js +0 -6
@@ -7,17 +7,17 @@
7
7
 
8
8
  const {
9
9
  JAVASCRIPT_MODULE_TYPE_AUTO,
10
- JAVASCRIPT_MODULE_TYPE_DYNAMIC
10
+ JAVASCRIPT_MODULE_TYPE_DYNAMIC,
11
+ JAVASCRIPT_MODULE_TYPE_ESM
11
12
  } = require("./ModuleTypeConstants");
12
13
  const NodeStuffInWebError = require("./NodeStuffInWebError");
13
14
  const RuntimeGlobals = require("./RuntimeGlobals");
14
15
  const CachedConstDependency = require("./dependencies/CachedConstDependency");
15
16
  const ConstDependency = require("./dependencies/ConstDependency");
16
17
  const ExternalModuleDependency = require("./dependencies/ExternalModuleDependency");
17
- const {
18
- evaluateToString,
19
- expressionIsUnsupported
20
- } = require("./javascript/JavascriptParserHelpers");
18
+ const ExternalModuleInitFragmentDependency = require("./dependencies/ExternalModuleInitFragmentDependency");
19
+ const ImportMetaPlugin = require("./dependencies/ImportMetaPlugin");
20
+ const { evaluateToString } = require("./javascript/JavascriptParserHelpers");
21
21
  const { relative } = require("./util/fs");
22
22
  const { parseResource } = require("./util/identifier");
23
23
 
@@ -27,10 +27,12 @@ const { parseResource } = require("./util/identifier");
27
27
  /** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
28
28
  /** @typedef {import("./NormalModule")} NormalModule */
29
29
  /** @typedef {import("./javascript/JavascriptParser")} JavascriptParser */
30
+ /** @typedef {import("./javascript/JavascriptParser").Expression} Expression */
30
31
  /** @typedef {import("./javascript/JavascriptParser").Range} Range */
31
32
  /** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
32
33
 
33
34
  const PLUGIN_NAME = "NodeStuffPlugin";
35
+ const URL_MODULE_CONSTANT_FUNCTION_NAME = "__webpack_fileURLToPath__";
34
36
 
35
37
  class NodeStuffPlugin {
36
38
  /**
@@ -46,7 +48,8 @@ class NodeStuffPlugin {
46
48
  * @returns {void}
47
49
  */
48
50
  apply(compiler) {
49
- const options = this.options;
51
+ const { options } = this;
52
+
50
53
  compiler.hooks.compilation.tap(
51
54
  PLUGIN_NAME,
52
55
  (compilation, { normalModuleFactory }) => {
@@ -54,132 +57,312 @@ class NodeStuffPlugin {
54
57
  ExternalModuleDependency,
55
58
  new ExternalModuleDependency.Template()
56
59
  );
60
+ compilation.dependencyTemplates.set(
61
+ ExternalModuleInitFragmentDependency,
62
+ new ExternalModuleInitFragmentDependency.Template()
63
+ );
57
64
 
58
65
  /**
59
66
  * @param {JavascriptParser} parser the parser
60
- * @param {JavascriptParserOptions} parserOptions options
67
+ * @param {NodeOptions} nodeOptions options
61
68
  * @returns {void}
62
69
  */
63
- const handler = (parser, parserOptions) => {
64
- if (parserOptions.node === false) return;
70
+ const globalHandler = (parser, nodeOptions) => {
71
+ /**
72
+ * @param {Expression} expr expression
73
+ * @returns {ConstDependency} const dependency
74
+ */
75
+ const getGlobalDep = (expr) => {
76
+ if (compilation.outputOptions.environment.globalThis) {
77
+ return new ConstDependency(
78
+ "globalThis",
79
+ /** @type {Range} */ (expr.range)
80
+ );
81
+ }
65
82
 
66
- let localOptions = options;
67
- if (parserOptions.node) {
68
- localOptions = { ...localOptions, ...parserOptions.node };
69
- }
83
+ return new ConstDependency(
84
+ RuntimeGlobals.global,
85
+ /** @type {Range} */ (expr.range),
86
+ [RuntimeGlobals.global]
87
+ );
88
+ };
70
89
 
71
- if (localOptions.global !== false) {
72
- const withWarning = localOptions.global === "warn";
73
- parser.hooks.expression.for("global").tap(PLUGIN_NAME, (expr) => {
90
+ const withWarning = nodeOptions.global === "warn";
91
+
92
+ parser.hooks.expression.for("global").tap(PLUGIN_NAME, (expr) => {
93
+ const dep = getGlobalDep(expr);
94
+ dep.loc = /** @type {DependencyLocation} */ (expr.loc);
95
+ parser.state.module.addPresentationalDependency(dep);
96
+
97
+ if (withWarning) {
98
+ parser.state.module.addWarning(
99
+ new NodeStuffInWebError(
100
+ dep.loc,
101
+ "global",
102
+ "The global namespace object is a Node.js feature and isn't available in browsers."
103
+ )
104
+ );
105
+ }
106
+ });
107
+
108
+ parser.hooks.rename.for("global").tap(PLUGIN_NAME, (expr) => {
109
+ const dep = getGlobalDep(expr);
110
+ dep.loc = /** @type {DependencyLocation} */ (expr.loc);
111
+ parser.state.module.addPresentationalDependency(dep);
112
+ return false;
113
+ });
114
+ };
115
+
116
+ const hooks = ImportMetaPlugin.getCompilationHooks(compilation);
117
+
118
+ /**
119
+ * @param {JavascriptParser} parser the parser
120
+ * @param {"__filename" | "__dirname" | "import.meta.filename" | "import.meta.dirname"} expressionName expression name
121
+ * @param {(module: NormalModule) => string} fn function
122
+ * @param {"filename" | "dirname"} property a property
123
+ * @returns {void}
124
+ */
125
+ const setModuleConstant = (parser, expressionName, fn, property) => {
126
+ parser.hooks.expression
127
+ .for(expressionName)
128
+ .tap(PLUGIN_NAME, (expr) => {
74
129
  const dep = new ConstDependency(
75
- RuntimeGlobals.global,
76
- /** @type {Range} */ (expr.range),
77
- [RuntimeGlobals.global]
130
+ fn(parser.state.module),
131
+ /** @type {Range} */
132
+ (expr.range)
78
133
  );
79
134
  dep.loc = /** @type {DependencyLocation} */ (expr.loc);
80
135
  parser.state.module.addPresentationalDependency(dep);
136
+ return true;
137
+ });
81
138
 
82
- // TODO webpack 6 remove
83
- if (withWarning) {
84
- parser.state.module.addWarning(
85
- new NodeStuffInWebError(
86
- dep.loc,
87
- "global",
88
- "The global namespace object is a Node.js feature and isn't available in browsers."
89
- )
90
- );
139
+ if (
140
+ expressionName === "import.meta.filename" ||
141
+ expressionName === "import.meta.dirname"
142
+ ) {
143
+ hooks.propertyInDestructuring.tap(PLUGIN_NAME, (usingProperty) => {
144
+ if (usingProperty.id === property) {
145
+ return `${property}: ${fn(parser.state.module)},`;
91
146
  }
92
147
  });
93
- parser.hooks.rename.for("global").tap(PLUGIN_NAME, (expr) => {
94
- const dep = new ConstDependency(
95
- RuntimeGlobals.global,
96
- /** @type {Range} */ (expr.range),
97
- [RuntimeGlobals.global]
148
+ }
149
+ };
150
+
151
+ /**
152
+ * @param {JavascriptParser} parser the parser
153
+ * @param {"__filename" | "__dirname" | "import.meta.filename" | "import.meta.dirname"} expressionName expression name
154
+ * @param {(module: NormalModule) => string} fn function
155
+ * @param {"filename" | "dirname"} property a property
156
+ * @param {string=} warning warning
157
+ * @returns {void}
158
+ */
159
+ const setCachedModuleConstant = (
160
+ parser,
161
+ expressionName,
162
+ fn,
163
+ property,
164
+ warning
165
+ ) => {
166
+ parser.hooks.expression
167
+ .for(expressionName)
168
+ .tap(PLUGIN_NAME, (expr) => {
169
+ const dep = new CachedConstDependency(
170
+ JSON.stringify(fn(parser.state.module)),
171
+ /** @type {Range} */
172
+ (expr.range),
173
+ `__webpack_${property}__`
98
174
  );
99
175
  dep.loc = /** @type {DependencyLocation} */ (expr.loc);
100
176
  parser.state.module.addPresentationalDependency(dep);
101
- return false;
102
- });
103
- }
104
177
 
105
- /**
106
- * @param {string} expressionName expression name
107
- * @param {(module: NormalModule) => string} fn function
108
- * @param {string=} warning warning
109
- * @returns {void}
110
- */
111
- const setModuleConstant = (expressionName, fn, warning) => {
112
- parser.hooks.expression
113
- .for(expressionName)
114
- .tap(PLUGIN_NAME, (expr) => {
115
- const dep = new CachedConstDependency(
116
- JSON.stringify(fn(parser.state.module)),
117
- /** @type {Range} */
118
- (expr.range),
119
- expressionName
178
+ if (warning) {
179
+ parser.state.module.addWarning(
180
+ new NodeStuffInWebError(dep.loc, expressionName, warning)
120
181
  );
121
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
122
- parser.state.module.addPresentationalDependency(dep);
182
+ }
183
+
184
+ return true;
185
+ });
123
186
 
124
- // TODO webpack 6 remove
187
+ if (
188
+ expressionName === "import.meta.filename" ||
189
+ expressionName === "import.meta.dirname"
190
+ ) {
191
+ hooks.propertyInDestructuring.tap(PLUGIN_NAME, (usingProperty) => {
192
+ if (property === usingProperty.id) {
125
193
  if (warning) {
126
194
  parser.state.module.addWarning(
127
- new NodeStuffInWebError(dep.loc, expressionName, warning)
195
+ new NodeStuffInWebError(
196
+ usingProperty.loc,
197
+ expressionName,
198
+ warning
199
+ )
128
200
  );
129
201
  }
130
202
 
203
+ return `${property}: ${JSON.stringify(fn(parser.state.module))},`;
204
+ }
205
+ });
206
+ }
207
+ };
208
+
209
+ /**
210
+ * @param {JavascriptParser} parser the parser
211
+ * @param {"__filename" | "__dirname" | "import.meta.filename" | "import.meta.dirname"} expressionName expression name
212
+ * @param {string} value value
213
+ * @param {"filename" | "dirname"} property a property
214
+ * @param {string=} warning warning
215
+ * @returns {void}
216
+ */
217
+ const setConstant = (
218
+ parser,
219
+ expressionName,
220
+ value,
221
+ property,
222
+ warning
223
+ ) =>
224
+ setCachedModuleConstant(
225
+ parser,
226
+ expressionName,
227
+ () => value,
228
+ property,
229
+ warning
230
+ );
231
+
232
+ /**
233
+ * @param {JavascriptParser} parser the parser
234
+ * @param {"__filename" | "__dirname" | "import.meta.filename" | "import.meta.dirname"} expressionName expression name
235
+ * @param {"dirname" | "filename"} property property
236
+ * @param {() => string} value function to get value
237
+ * @returns {void}
238
+ */
239
+ const setUrlModuleConstant = (
240
+ parser,
241
+ expressionName,
242
+ property,
243
+ value
244
+ ) => {
245
+ parser.hooks.expression
246
+ .for(expressionName)
247
+ .tap(PLUGIN_NAME, (expr) => {
248
+ const { importMetaName, environment, module } =
249
+ compilation.outputOptions;
250
+
251
+ if (
252
+ module &&
253
+ importMetaName === "import.meta" &&
254
+ (expressionName === "import.meta.filename" ||
255
+ expressionName === "import.meta.dirname") &&
256
+ environment.importMetaDirnameAndFilename
257
+ ) {
131
258
  return true;
132
- });
133
- };
259
+ }
134
260
 
135
- /**
136
- * @param {string} expressionName expression name
137
- * @param {(value: string) => string} fn function
138
- * @returns {void}
139
- */
140
- const setUrlModuleConstant = (expressionName, fn) => {
141
- parser.hooks.expression
142
- .for(expressionName)
143
- .tap(PLUGIN_NAME, (expr) => {
144
- const dep = new ExternalModuleDependency(
261
+ // Generate `import.meta.dirname` and `import.meta.filename` when:
262
+ // - they are supported by the environment
263
+ // - it is a universal target, because we can't use `import mod from "node:url"; ` at the top file
264
+ const dep =
265
+ environment.importMetaDirnameAndFilename ||
266
+ (compiler.platform.web === null &&
267
+ compiler.platform.node === null &&
268
+ module)
269
+ ? new ConstDependency(
270
+ `${importMetaName}.${property}`,
271
+ /** @type {Range} */
272
+ (expr.range)
273
+ )
274
+ : new ExternalModuleDependency(
275
+ "url",
276
+ [
277
+ {
278
+ name: "fileURLToPath",
279
+ value: URL_MODULE_CONSTANT_FUNCTION_NAME
280
+ }
281
+ ],
282
+ undefined,
283
+ `${URL_MODULE_CONSTANT_FUNCTION_NAME}(${value()})`,
284
+ /** @type {Range} */ (expr.range),
285
+ `__webpack_${property}__`
286
+ );
287
+ dep.loc = /** @type {DependencyLocation} */ (expr.loc);
288
+ parser.state.module.addPresentationalDependency(dep);
289
+
290
+ return true;
291
+ });
292
+
293
+ if (
294
+ expressionName === "import.meta.filename" ||
295
+ expressionName === "import.meta.dirname"
296
+ ) {
297
+ hooks.propertyInDestructuring.tap(PLUGIN_NAME, (usingProperty) => {
298
+ if (property === usingProperty.id) {
299
+ const { importMetaName, environment, module } =
300
+ compilation.outputOptions;
301
+
302
+ if (
303
+ module &&
304
+ importMetaName === "import.meta" &&
305
+ (expressionName === "import.meta.filename" ||
306
+ expressionName === "import.meta.dirname") &&
307
+ environment.importMetaDirnameAndFilename
308
+ ) {
309
+ return `${property}: ${importMetaName}.${property},`;
310
+ }
311
+
312
+ if (environment.importMetaDirnameAndFilename) {
313
+ return `${property}: ${importMetaName}.${property},`;
314
+ }
315
+
316
+ const dep = new ExternalModuleInitFragmentDependency(
145
317
  "url",
146
318
  [
147
319
  {
148
320
  name: "fileURLToPath",
149
- value: "__webpack_fileURLToPath__"
321
+ value: URL_MODULE_CONSTANT_FUNCTION_NAME
150
322
  }
151
323
  ],
152
- undefined,
153
- fn("__webpack_fileURLToPath__"),
154
- /** @type {Range} */ (expr.range),
155
- expressionName
324
+ undefined
156
325
  );
157
- dep.loc = /** @type {DependencyLocation} */ (expr.loc);
326
+
327
+ dep.loc = /** @type {DependencyLocation} */ (usingProperty.loc);
158
328
  parser.state.module.addPresentationalDependency(dep);
159
329
 
160
- return true;
161
- });
162
- };
330
+ return `${property}: ${URL_MODULE_CONSTANT_FUNCTION_NAME}(${value()}),`;
331
+ }
332
+ });
333
+ }
334
+ };
163
335
 
164
- /**
165
- * @param {string} expressionName expression name
166
- * @param {string} value value
167
- * @param {string=} warning warning
168
- * @returns {void}
169
- */
170
- const setConstant = (expressionName, value, warning) =>
171
- setModuleConstant(expressionName, () => value, warning);
336
+ /**
337
+ * @param {JavascriptParser} parser the parser
338
+ * @param {NodeOptions} nodeOptions options
339
+ * @param {{ dirname: "__dirname" | "import.meta.dirname", filename: "__filename" | "import.meta.filename" }} identifiers options
340
+ * @returns {void}
341
+ */
342
+ const dirnameAndFilenameHandler = (
343
+ parser,
344
+ nodeOptions,
345
+ { dirname, filename }
346
+ ) => {
347
+ // Keep `import.meta.filename` in code
348
+ if (
349
+ nodeOptions.__filename === false &&
350
+ filename === "import.meta.filename"
351
+ ) {
352
+ setModuleConstant(parser, filename, () => filename, "filename");
353
+ }
172
354
 
173
- const context = compiler.context;
174
- if (localOptions.__filename) {
175
- switch (localOptions.__filename) {
355
+ if (nodeOptions.__filename) {
356
+ switch (nodeOptions.__filename) {
176
357
  case "mock":
177
- setConstant("__filename", "/index.js");
358
+ setConstant(parser, filename, "/index.js", "filename");
178
359
  break;
179
360
  case "warn-mock":
180
361
  setConstant(
181
- "__filename",
362
+ parser,
363
+ filename,
182
364
  "/index.js",
365
+ "filename",
183
366
  "__filename is a Node.js feature and isn't available in browsers."
184
367
  );
185
368
  break;
@@ -187,18 +370,46 @@ class NodeStuffPlugin {
187
370
  const importMetaName = compilation.outputOptions.importMetaName;
188
371
 
189
372
  setUrlModuleConstant(
190
- "__filename",
191
- (functionName) => `${functionName}(${importMetaName}.url)`
373
+ parser,
374
+ filename,
375
+ "filename",
376
+ () => `${importMetaName}.url`
192
377
  );
193
378
  break;
194
379
  }
380
+ case "eval-only":
381
+ // Keep `import.meta.filename` in the source code for the ES module output, or create a fallback using `import.meta.url` if possible
382
+ if (compilation.outputOptions.module) {
383
+ const { importMetaName } = compilation.outputOptions;
384
+
385
+ setUrlModuleConstant(
386
+ parser,
387
+ filename,
388
+ "filename",
389
+ () => `${importMetaName}.url`
390
+ );
391
+ }
392
+ // Replace `import.meta.filename` with `__filename` for the non-ES module output
393
+ else if (filename === "import.meta.filename") {
394
+ setModuleConstant(
395
+ parser,
396
+ filename,
397
+ () => "__filename",
398
+ "filename"
399
+ );
400
+ }
401
+ break;
195
402
  case true:
196
- setModuleConstant("__filename", (module) =>
197
- relative(
198
- /** @type {InputFileSystem} */ (compiler.inputFileSystem),
199
- context,
200
- module.resource
201
- )
403
+ setCachedModuleConstant(
404
+ parser,
405
+ filename,
406
+ (module) =>
407
+ relative(
408
+ /** @type {InputFileSystem} */ (compiler.inputFileSystem),
409
+ compiler.context,
410
+ module.resource
411
+ ),
412
+ "filename"
202
413
  );
203
414
  break;
204
415
  }
@@ -211,15 +422,26 @@ class NodeStuffPlugin {
211
422
  return evaluateToString(resource.path)(expr);
212
423
  });
213
424
  }
214
- if (localOptions.__dirname) {
215
- switch (localOptions.__dirname) {
425
+
426
+ // Keep `import.meta.dirname` in code
427
+ if (
428
+ nodeOptions.__dirname === false &&
429
+ dirname === "import.meta.dirname"
430
+ ) {
431
+ setModuleConstant(parser, dirname, () => dirname, "dirname");
432
+ }
433
+
434
+ if (nodeOptions.__dirname) {
435
+ switch (nodeOptions.__dirname) {
216
436
  case "mock":
217
- setConstant("__dirname", "/");
437
+ setConstant(parser, dirname, "/", "dirname");
218
438
  break;
219
439
  case "warn-mock":
220
440
  setConstant(
221
- "__dirname",
441
+ parser,
442
+ dirname,
222
443
  "/",
444
+ "dirname",
223
445
  "__dirname is a Node.js feature and isn't available in browsers."
224
446
  );
225
447
  break;
@@ -227,25 +449,52 @@ class NodeStuffPlugin {
227
449
  const importMetaName = compilation.outputOptions.importMetaName;
228
450
 
229
451
  setUrlModuleConstant(
230
- "__dirname",
231
- (functionName) =>
232
- `${functionName}(${importMetaName}.url + "/..").slice(0, -1)`
452
+ parser,
453
+ dirname,
454
+ "dirname",
455
+ () => `${importMetaName}.url.replace(/\\/(?:[^\\/]*)$/, "")`
233
456
  );
234
457
  break;
235
458
  }
459
+ case "eval-only":
460
+ // Keep `import.meta.dirname` in the source code for the ES module output and replace `__dirname` on `import.meta.dirname`
461
+ if (compilation.outputOptions.module) {
462
+ const { importMetaName } = compilation.outputOptions;
463
+
464
+ setUrlModuleConstant(
465
+ parser,
466
+ dirname,
467
+ "dirname",
468
+ () => `${importMetaName}.url.replace(/\\/(?:[^\\/]*)$/, "")`
469
+ );
470
+ }
471
+ // Replace `import.meta.dirname` with `__dirname` for the non-ES module output
472
+ else if (dirname === "import.meta.dirname") {
473
+ setModuleConstant(
474
+ parser,
475
+ dirname,
476
+ () => "__dirname",
477
+ "dirname"
478
+ );
479
+ }
480
+ break;
236
481
  case true:
237
- setModuleConstant("__dirname", (module) =>
238
- relative(
239
- /** @type {InputFileSystem} */ (compiler.inputFileSystem),
240
- context,
241
- /** @type {string} */ (module.context)
242
- )
482
+ setCachedModuleConstant(
483
+ parser,
484
+ dirname,
485
+ (module) =>
486
+ relative(
487
+ /** @type {InputFileSystem} */ (compiler.inputFileSystem),
488
+ compiler.context,
489
+ /** @type {string} */ (module.context)
490
+ ),
491
+ "dirname"
243
492
  );
244
493
  break;
245
494
  }
246
495
 
247
496
  parser.hooks.evaluateIdentifier
248
- .for("__dirname")
497
+ .for(dirname)
249
498
  .tap(PLUGIN_NAME, (expr) => {
250
499
  if (!parser.state.module) return;
251
500
  return evaluateToString(
@@ -254,23 +503,72 @@ class NodeStuffPlugin {
254
503
  )(expr);
255
504
  });
256
505
  }
257
- parser.hooks.expression
258
- .for("require.extensions")
259
- .tap(
260
- PLUGIN_NAME,
261
- expressionIsUnsupported(
262
- parser,
263
- "require.extensions is not supported by webpack. Use a loader instead."
264
- )
506
+ };
507
+
508
+ /**
509
+ * @param {JavascriptParser} parser the parser
510
+ * @param {JavascriptParserOptions} parserOptions the javascript parser options
511
+ * @param {boolean} a true when we need to handle `__filename` and `__dirname`, otherwise false
512
+ * @param {boolean} b true when we need to handle `import.meta.filename` and `import.meta.dirname`, otherwise false
513
+ */
514
+ const handler = (parser, parserOptions, a, b) => {
515
+ if (b && parserOptions.node === false) {
516
+ // Keep `import.meta.dirname` and `import.meta.filename` in code
517
+ setModuleConstant(
518
+ parser,
519
+ "import.meta.dirname",
520
+ () => "import.meta.dirname",
521
+ "dirname"
522
+ );
523
+ setModuleConstant(
524
+ parser,
525
+ "import.meta.filename",
526
+ () => "import.meta.filename",
527
+ "filename"
265
528
  );
529
+ return;
530
+ }
531
+
532
+ let localOptions = options;
533
+
534
+ if (parserOptions.node) {
535
+ localOptions = { ...localOptions, ...parserOptions.node };
536
+ }
537
+
538
+ if (localOptions.global !== false) {
539
+ globalHandler(parser, localOptions);
540
+ }
541
+
542
+ if (a) {
543
+ dirnameAndFilenameHandler(parser, localOptions, {
544
+ dirname: "__dirname",
545
+ filename: "__filename"
546
+ });
547
+ }
548
+
549
+ if (b && parserOptions.importMeta !== false) {
550
+ dirnameAndFilenameHandler(parser, localOptions, {
551
+ dirname: "import.meta.dirname",
552
+ filename: "import.meta.filename"
553
+ });
554
+ }
266
555
  };
267
556
 
268
557
  normalModuleFactory.hooks.parser
269
558
  .for(JAVASCRIPT_MODULE_TYPE_AUTO)
270
- .tap(PLUGIN_NAME, handler);
559
+ .tap(PLUGIN_NAME, (parser, parserOptions) => {
560
+ handler(parser, parserOptions, true, true);
561
+ });
271
562
  normalModuleFactory.hooks.parser
272
563
  .for(JAVASCRIPT_MODULE_TYPE_DYNAMIC)
273
- .tap(PLUGIN_NAME, handler);
564
+ .tap(PLUGIN_NAME, (parser, parserOptions) => {
565
+ handler(parser, parserOptions, true, false);
566
+ });
567
+ normalModuleFactory.hooks.parser
568
+ .for(JAVASCRIPT_MODULE_TYPE_ESM)
569
+ .tap(PLUGIN_NAME, (parser, parserOptions) => {
570
+ handler(parser, parserOptions, false, true);
571
+ });
274
572
  }
275
573
  );
276
574
  }