webpack 5.105.3 → 5.106.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 (131) hide show
  1. package/README.md +3 -6
  2. package/lib/BannerPlugin.js +13 -13
  3. package/lib/Chunk.js +25 -0
  4. package/lib/ChunkGraph.js +8 -4
  5. package/lib/CleanPlugin.js +23 -20
  6. package/lib/CompatibilityPlugin.js +1 -1
  7. package/lib/Compilation.js +36 -13
  8. package/lib/Compiler.js +59 -1
  9. package/lib/CssModule.js +17 -2
  10. package/lib/Dependency.js +1 -1
  11. package/lib/DllPlugin.js +17 -17
  12. package/lib/DllReferencePlugin.js +20 -18
  13. package/lib/DotenvPlugin.js +29 -27
  14. package/lib/ExternalModule.js +39 -6
  15. package/lib/FileSystemInfo.js +3 -1
  16. package/lib/IgnorePlugin.js +12 -11
  17. package/lib/LoaderOptionsPlugin.js +17 -15
  18. package/lib/ManifestPlugin.js +27 -25
  19. package/lib/Module.js +84 -4
  20. package/lib/ModuleGraph.js +3 -0
  21. package/lib/ModuleParseError.js +1 -1
  22. package/lib/ModuleTypeConstants.js +1 -1
  23. package/lib/MultiStats.js +5 -5
  24. package/lib/NormalModule.js +7 -3
  25. package/lib/NormalModuleFactory.js +20 -1
  26. package/lib/ProgressPlugin.js +39 -29
  27. package/lib/RuntimeGlobals.js +6 -0
  28. package/lib/RuntimeModule.js +18 -1
  29. package/lib/RuntimeTemplate.js +1 -1
  30. package/lib/SourceMapDevToolPlugin.js +13 -11
  31. package/lib/Stats.js +3 -2
  32. package/lib/TemplatedPathPlugin.js +4 -3
  33. package/lib/WatchIgnorePlugin.js +15 -13
  34. package/lib/WebpackOptionsApply.js +4 -4
  35. package/lib/asset/AssetModulesPlugin.js +50 -29
  36. package/lib/cli.js +3 -1
  37. package/lib/config/defaults.js +27 -13
  38. package/lib/config/normalization.js +3 -2
  39. package/lib/container/ContainerPlugin.js +46 -42
  40. package/lib/container/ContainerReferencePlugin.js +42 -26
  41. package/lib/container/FallbackModule.js +1 -1
  42. package/lib/container/ModuleFederationPlugin.js +17 -13
  43. package/lib/container/RemoteModule.js +18 -1
  44. package/lib/css/CssGenerator.js +315 -191
  45. package/lib/css/CssInjectStyleRuntimeModule.js +179 -0
  46. package/lib/css/CssLoadingRuntimeModule.js +1 -4
  47. package/lib/css/CssModulesPlugin.js +197 -98
  48. package/lib/css/CssParser.js +231 -134
  49. package/lib/css/walkCssTokens.js +115 -12
  50. package/lib/debug/ProfilingPlugin.js +16 -13
  51. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +20 -15
  52. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +4 -3
  53. package/lib/dependencies/CommonJsExportRequireDependency.js +4 -2
  54. package/lib/dependencies/CommonJsExportsDependency.js +1 -1
  55. package/lib/dependencies/CommonJsExportsParserPlugin.js +1 -1
  56. package/lib/dependencies/CommonJsFullRequireDependency.js +1 -1
  57. package/lib/dependencies/CommonJsImportsParserPlugin.js +63 -2
  58. package/lib/dependencies/CommonJsRequireContextDependency.js +21 -0
  59. package/lib/dependencies/CommonJsRequireDependency.js +42 -1
  60. package/lib/dependencies/CommonJsSelfReferenceDependency.js +1 -1
  61. package/lib/dependencies/ContextElementDependency.js +1 -1
  62. package/lib/dependencies/CreateRequireParserPlugin.js +11 -0
  63. package/lib/dependencies/CssIcssExportDependency.js +210 -87
  64. package/lib/dependencies/CssIcssImportDependency.js +13 -70
  65. package/lib/dependencies/CssIcssSymbolDependency.js +19 -30
  66. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +13 -2
  67. package/lib/dependencies/HarmonyExportExpressionDependency.js +28 -2
  68. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +13 -3
  69. package/lib/dependencies/HarmonyExportInitFragment.js +1 -1
  70. package/lib/dependencies/HarmonyImportDependency.js +21 -8
  71. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +124 -205
  72. package/lib/dependencies/HarmonyImportSideEffectDependency.js +12 -6
  73. package/lib/dependencies/HarmonyImportSpecifierDependency.js +13 -2
  74. package/lib/dependencies/ImportContextDependency.js +1 -1
  75. package/lib/dependencies/ImportDependency.js +16 -2
  76. package/lib/dependencies/ImportMetaPlugin.js +39 -29
  77. package/lib/dependencies/ImportParserPlugin.js +4 -5
  78. package/lib/dependencies/ImportPhase.js +65 -22
  79. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +1 -1
  80. package/lib/esm/ModuleChunkFormatPlugin.js +1 -4
  81. package/lib/ids/HashedModuleIdsPlugin.js +21 -23
  82. package/lib/ids/OccurrenceChunkIdsPlugin.js +15 -11
  83. package/lib/ids/OccurrenceModuleIdsPlugin.js +15 -11
  84. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +1 -4
  85. package/lib/javascript/CommonJsChunkFormatPlugin.js +1 -4
  86. package/lib/javascript/EnableChunkLoadingPlugin.js +1 -2
  87. package/lib/javascript/JavascriptModulesPlugin.js +38 -12
  88. package/lib/javascript/JavascriptParser.js +5 -3
  89. package/lib/json/JsonModulesPlugin.js +28 -21
  90. package/lib/library/AssignLibraryPlugin.js +1 -1
  91. package/lib/library/ExportPropertyLibraryPlugin.js +1 -1
  92. package/lib/library/ModuleLibraryPlugin.js +35 -13
  93. package/lib/library/SystemLibraryPlugin.js +1 -1
  94. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +22 -0
  95. package/lib/optimize/AggressiveSplittingPlugin.js +18 -31
  96. package/lib/optimize/ConcatenatedModule.js +6 -2
  97. package/lib/optimize/InnerGraphPlugin.js +11 -5
  98. package/lib/optimize/LimitChunkCountPlugin.js +22 -18
  99. package/lib/optimize/MergeDuplicateChunksPlugin.js +15 -12
  100. package/lib/optimize/MinChunkSizePlugin.js +20 -16
  101. package/lib/optimize/ModuleConcatenationPlugin.js +4 -1
  102. package/lib/optimize/RemoveEmptyChunksPlugin.js +0 -1
  103. package/lib/rules/RuleSetCompiler.js +1 -0
  104. package/lib/schemes/HttpUriPlugin.js +20 -11
  105. package/lib/schemes/VirtualUrlPlugin.js +77 -30
  106. package/lib/serialization/FileMiddleware.js +7 -7
  107. package/lib/sharing/ConsumeSharedModule.js +18 -1
  108. package/lib/sharing/ConsumeSharedPlugin.js +32 -25
  109. package/lib/sharing/ProvideSharedPlugin.js +29 -25
  110. package/lib/util/AppendOnlyStackedSet.js +22 -1
  111. package/lib/util/{propertyName.js → property.js} +26 -1
  112. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +148 -0
  113. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +54 -0
  114. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +105 -0
  115. package/lib/wasm-async/AsyncWebAssemblyParser.js +30 -6
  116. package/lib/wasm-async/UniversalCompileAsyncWasmPlugin.js +26 -2
  117. package/lib/web/FetchCompileAsyncWasmPlugin.js +23 -0
  118. package/lib/web/JsonpTemplatePlugin.js +1 -0
  119. package/lib/webpack.js +34 -4
  120. package/package.json +20 -18
  121. package/schemas/WebpackOptions.check.js +1 -1
  122. package/schemas/WebpackOptions.json +82 -22
  123. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +1 -1
  124. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  125. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  126. package/schemas/plugins/optimize/LimitChunkCountPlugin.json +1 -1
  127. package/schemas/plugins/schemes/VirtualUrlPlugin.check.js +1 -1
  128. package/schemas/plugins/schemes/VirtualUrlPlugin.json +8 -0
  129. package/types.d.ts +606 -150
  130. package/lib/util/create-schema-validation.js +0 -41
  131. package/lib/util/propertyAccess.js +0 -30
@@ -25,11 +25,14 @@ const ImportPhase = Object.freeze({
25
25
  Source: 0b10
26
26
  });
27
27
 
28
+ /** @typedef {"defer" | "source" | "evaluation"} ImportPhaseName */
29
+
28
30
  /**
29
31
  * @typedef {object} ImportPhaseUtils
30
- * @property {(phase: ImportPhaseType) => boolean} isEvaluation true if phase is evaluation
31
- * @property {(phase: ImportPhaseType) => boolean} isDefer true if phase is defer
32
- * @property {(phase: ImportPhaseType) => boolean} isSource true if phase is source
32
+ * @property {(phase: ImportPhaseType | undefined) => boolean} isEvaluation true if phase is evaluation
33
+ * @property {(phase: ImportPhaseType | undefined) => boolean} isDefer true if phase is defer
34
+ * @property {(phase: ImportPhaseType | undefined) => boolean} isSource true if phase is source
35
+ * @property {(phase: ImportPhaseType) => ImportPhaseName} stringify return stringified name of phase
33
36
  */
34
37
 
35
38
  /** @type {ImportPhaseUtils} */
@@ -42,6 +45,16 @@ const ImportPhaseUtils = {
42
45
  },
43
46
  isSource(phase) {
44
47
  return phase === ImportPhase.Source;
48
+ },
49
+ stringify(phase) {
50
+ switch (phase) {
51
+ case ImportPhase.Defer:
52
+ return "defer";
53
+ case ImportPhase.Source:
54
+ return "source";
55
+ default:
56
+ return "evaluation";
57
+ }
45
58
  }
46
59
  };
47
60
 
@@ -58,17 +71,22 @@ const ImportPhaseUtils = {
58
71
  */
59
72
 
60
73
  /**
61
- * @param {boolean=} enableImportPhase enable import phase detection
74
+ * @param {boolean=} enableDeferPhase enable import phase detection
75
+ * @param {boolean=} enableSourcePhase enable import phase detection
62
76
  * @returns {GetImportPhase} evaluates the import phase for ast node
63
77
  */
64
- function createGetImportPhase(enableImportPhase) {
78
+ function createGetImportPhase(enableDeferPhase, enableSourcePhase) {
65
79
  return (parser, node, getCommentOptions) => {
66
- if (!enableImportPhase) return ImportPhase.Evaluation;
80
+ if (!enableDeferPhase && !enableSourcePhase) return ImportPhase.Evaluation;
67
81
 
68
- // We now only support `defer import`
82
+ // We now only support `defer import` and `source import` syntax
69
83
  const phaseBySyntax =
70
- "phase" in node && node.phase === "defer"
71
- ? ImportPhase.Defer
84
+ "phase" in node
85
+ ? node.phase === "defer" && enableDeferPhase
86
+ ? ImportPhase.Defer
87
+ : node.phase === "source" && enableSourcePhase
88
+ ? ImportPhase.Source
89
+ : ImportPhase.Evaluation
72
90
  : ImportPhase.Evaluation;
73
91
 
74
92
  if (!node.range) {
@@ -99,19 +117,44 @@ function createGetImportPhase(enableImportPhase) {
99
117
 
100
118
  const options = getCommentOptions();
101
119
 
102
- if (!options || !options.webpackDefer) return phaseBySyntax;
103
-
104
- const { webpackDefer } = options;
105
- if (typeof webpackDefer === "boolean") {
106
- return webpackDefer ? ImportPhase.Defer : phaseBySyntax;
107
- } else if (node.loc) {
108
- const CommentCompilationWarning = getCommentCompilationWarning();
109
- parser.state.module.addWarning(
110
- new CommentCompilationWarning(
111
- "webpackDefer magic comment expected a boolean value.",
112
- node.loc
113
- )
114
- );
120
+ if (!options) {
121
+ return phaseBySyntax;
122
+ }
123
+
124
+ if (!options.webpackDefer && !options.webpackSource) {
125
+ return phaseBySyntax;
126
+ }
127
+
128
+ const { webpackDefer, webpackSource } = options;
129
+
130
+ if (enableDeferPhase && typeof options.webpackDefer !== "undefined") {
131
+ if (typeof webpackDefer === "boolean") {
132
+ return webpackDefer ? ImportPhase.Defer : phaseBySyntax;
133
+ } else if (node.loc) {
134
+ const CommentCompilationWarning = getCommentCompilationWarning();
135
+
136
+ parser.state.module.addWarning(
137
+ new CommentCompilationWarning(
138
+ "webpackDefer magic comment expected a boolean value.",
139
+ node.loc
140
+ )
141
+ );
142
+ }
143
+ }
144
+
145
+ if (enableSourcePhase && typeof options.webpackSource !== "undefined") {
146
+ if (typeof webpackSource === "boolean") {
147
+ return webpackSource ? ImportPhase.Source : phaseBySyntax;
148
+ } else if (node.loc) {
149
+ const CommentCompilationWarning = getCommentCompilationWarning();
150
+
151
+ parser.state.module.addWarning(
152
+ new CommentCompilationWarning(
153
+ "webpackSource magic comment expected a boolean value.",
154
+ node.loc
155
+ )
156
+ );
157
+ }
115
158
  }
116
159
 
117
160
  return phaseBySyntax;
@@ -93,7 +93,7 @@ module.exports = class RequireEnsureDependenciesBlockParserPlugin {
93
93
  parser.state.current = /** @type {EXPECTED_ANY} */ (depBlock);
94
94
  try {
95
95
  let failed = false;
96
- parser.inScope([], () => {
96
+ parser.inFunctionScope(true, [], () => {
97
97
  for (const ee of dependenciesItems) {
98
98
  if (ee.isString()) {
99
99
  const ensureDependency = new RequireEnsureItemDependency(
@@ -255,10 +255,7 @@ class ModuleChunkFormatPlugin {
255
255
  hooks.renderStartup.call(
256
256
  startupSource,
257
257
  entries[entries.length - 1][0],
258
- {
259
- ...renderContext,
260
- inlined: false
261
- }
258
+ renderContext
262
259
  )
263
260
  );
264
261
  return entrySource;
@@ -9,7 +9,6 @@ const { DEFAULTS } = require("../config/defaults");
9
9
  const {
10
10
  compareModulesByPreOrderIndexOrIdentifier
11
11
  } = require("../util/comparators");
12
- const createSchemaValidation = require("../util/create-schema-validation");
13
12
  const createHash = require("../util/createHash");
14
13
  const {
15
14
  getFullModuleName,
@@ -19,15 +18,6 @@ const {
19
18
  /** @typedef {import("../../declarations/plugins/ids/HashedModuleIdsPlugin").HashedModuleIdsPluginOptions} HashedModuleIdsPluginOptions */
20
19
  /** @typedef {import("../Compiler")} Compiler */
21
20
 
22
- const validate = createSchemaValidation(
23
- require("../../schemas/plugins/ids/HashedModuleIdsPlugin.check"),
24
- () => require("../../schemas/plugins/ids/HashedModuleIdsPlugin.json"),
25
- {
26
- name: "Hashed Module Ids Plugin",
27
- baseDataPath: "options"
28
- }
29
- );
30
-
31
21
  const PLUGIN_NAME = "HashedModuleIdsPlugin";
32
22
 
33
23
  class HashedModuleIdsPlugin {
@@ -35,16 +25,8 @@ class HashedModuleIdsPlugin {
35
25
  * @param {HashedModuleIdsPluginOptions=} options options object
36
26
  */
37
27
  constructor(options = {}) {
38
- validate(options);
39
-
40
- /** @type {Required<Omit<HashedModuleIdsPluginOptions, "context">> & { context?: string | undefined }} */
41
- this.options = {
42
- context: undefined,
43
- hashFunction: DEFAULTS.HASH_FUNCTION,
44
- hashDigest: "base64",
45
- hashDigestLength: 4,
46
- ...options
47
- };
28
+ /** @type {HashedModuleIdsPluginOptions} */
29
+ this.options = options;
48
30
  }
49
31
 
50
32
  /**
@@ -53,6 +35,20 @@ class HashedModuleIdsPlugin {
53
35
  * @returns {void}
54
36
  */
55
37
  apply(compiler) {
38
+ compiler.hooks.validate.tap(PLUGIN_NAME, () => {
39
+ compiler.validate(
40
+ () => require("../../schemas/plugins/ids/HashedModuleIdsPlugin.json"),
41
+ this.options,
42
+ {
43
+ name: "Hashed Module Ids Plugin",
44
+ baseDataPath: "options"
45
+ },
46
+ (options) =>
47
+ require("../../schemas/plugins/ids/HashedModuleIdsPlugin.check")(
48
+ options
49
+ )
50
+ );
51
+ });
56
52
  compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
57
53
  compilation.hooks.moduleIds.tap(PLUGIN_NAME, () => {
58
54
  const chunkGraph = compilation.chunkGraph;
@@ -66,10 +62,12 @@ class HashedModuleIdsPlugin {
66
62
  );
67
63
  for (const module of modulesInNaturalOrder) {
68
64
  const ident = getFullModuleName(module, context, compiler.root);
69
- const hash = createHash(this.options.hashFunction);
65
+ const hash = createHash(
66
+ this.options.hashFunction || DEFAULTS.HASH_FUNCTION
67
+ );
70
68
  hash.update(ident || "");
71
- const hashId = hash.digest(this.options.hashDigest);
72
- let len = this.options.hashDigestLength;
69
+ const hashId = hash.digest(this.options.hashDigest || "base64");
70
+ let len = this.options.hashDigestLength || 4;
73
71
  while (usedIds.has(hashId.slice(0, len))) {
74
72
  /** @type {number} */ (len)++;
75
73
  }
@@ -6,22 +6,12 @@
6
6
  "use strict";
7
7
 
8
8
  const { compareChunksNatural } = require("../util/comparators");
9
- const createSchemaValidation = require("../util/create-schema-validation");
10
9
  const { assignAscendingChunkIds } = require("./IdHelpers");
11
10
 
12
11
  /** @typedef {import("../../declarations/plugins/ids/OccurrenceChunkIdsPlugin").OccurrenceChunkIdsPluginOptions} OccurrenceChunkIdsPluginOptions */
13
12
  /** @typedef {import("../Chunk")} Chunk */
14
13
  /** @typedef {import("../Compiler")} Compiler */
15
14
 
16
- const validate = createSchemaValidation(
17
- require("../../schemas/plugins/ids/OccurrenceChunkIdsPlugin.check"),
18
- () => require("../../schemas/plugins/ids/OccurrenceChunkIdsPlugin.json"),
19
- {
20
- name: "Occurrence Order Chunk Ids Plugin",
21
- baseDataPath: "options"
22
- }
23
- );
24
-
25
15
  const PLUGIN_NAME = "OccurrenceChunkIdsPlugin";
26
16
 
27
17
  class OccurrenceChunkIdsPlugin {
@@ -29,7 +19,6 @@ class OccurrenceChunkIdsPlugin {
29
19
  * @param {OccurrenceChunkIdsPluginOptions=} options options object
30
20
  */
31
21
  constructor(options = {}) {
32
- validate(options);
33
22
  /** @type {OccurrenceChunkIdsPluginOptions} */
34
23
  this.options = options;
35
24
  }
@@ -40,6 +29,21 @@ class OccurrenceChunkIdsPlugin {
40
29
  * @returns {void}
41
30
  */
42
31
  apply(compiler) {
32
+ compiler.hooks.validate.tap(PLUGIN_NAME, () => {
33
+ compiler.validate(
34
+ () =>
35
+ require("../../schemas/plugins/ids/OccurrenceChunkIdsPlugin.json"),
36
+ this.options,
37
+ {
38
+ name: "Occurrence Order Chunk Ids Plugin",
39
+ baseDataPath: "options"
40
+ },
41
+ (options) =>
42
+ require("../../schemas/plugins/ids/OccurrenceChunkIdsPlugin.check")(
43
+ options
44
+ )
45
+ );
46
+ });
43
47
  compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
44
48
  compilation.hooks.chunkIds.tap(PLUGIN_NAME, (chunks) => {
45
49
  const chunkGraph = compilation.chunkGraph;
@@ -8,7 +8,6 @@
8
8
  const {
9
9
  compareModulesByPreOrderIndexOrIdentifier
10
10
  } = require("../util/comparators");
11
- const createSchemaValidation = require("../util/create-schema-validation");
12
11
  const {
13
12
  assignAscendingModuleIds,
14
13
  getUsedModuleIdsAndModules
@@ -18,15 +17,6 @@ const {
18
17
  /** @typedef {import("../Compiler")} Compiler */
19
18
  /** @typedef {import("../Module")} Module */
20
19
 
21
- const validate = createSchemaValidation(
22
- require("../../schemas/plugins/ids/OccurrenceModuleIdsPlugin.check"),
23
- () => require("../../schemas/plugins/ids/OccurrenceModuleIdsPlugin.json"),
24
- {
25
- name: "Occurrence Order Module Ids Plugin",
26
- baseDataPath: "options"
27
- }
28
- );
29
-
30
20
  const PLUGIN_NAME = "OccurrenceModuleIdsPlugin";
31
21
 
32
22
  class OccurrenceModuleIdsPlugin {
@@ -34,7 +24,6 @@ class OccurrenceModuleIdsPlugin {
34
24
  * @param {OccurrenceModuleIdsPluginOptions=} options options object
35
25
  */
36
26
  constructor(options = {}) {
37
- validate(options);
38
27
  /** @type {OccurrenceModuleIdsPluginOptions} */
39
28
  this.options = options;
40
29
  }
@@ -45,6 +34,21 @@ class OccurrenceModuleIdsPlugin {
45
34
  * @returns {void}
46
35
  */
47
36
  apply(compiler) {
37
+ compiler.hooks.validate.tap(PLUGIN_NAME, () => {
38
+ compiler.validate(
39
+ () =>
40
+ require("../../schemas/plugins/ids/OccurrenceModuleIdsPlugin.json"),
41
+ this.options,
42
+ {
43
+ name: "Occurrence Order Module Ids Plugin",
44
+ baseDataPath: "options"
45
+ },
46
+ (options) =>
47
+ require("../../schemas/plugins/ids/OccurrenceModuleIdsPlugin.check")(
48
+ options
49
+ )
50
+ );
51
+ });
48
52
  compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
49
53
  const moduleGraph = compilation.moduleGraph;
50
54
 
@@ -110,10 +110,7 @@ class ArrayPushCallbackChunkFormatPlugin {
110
110
  hooks.renderStartup.call(
111
111
  startupSource,
112
112
  entries[entries.length - 1][0],
113
- {
114
- ...renderContext,
115
- inlined: false
116
- }
113
+ renderContext
117
114
  )
118
115
  );
119
116
  if (
@@ -128,10 +128,7 @@ class CommonJsChunkFormatPlugin {
128
128
  hooks.renderStartup.call(
129
129
  startupSource,
130
130
  entries[entries.length - 1][0],
131
- {
132
- ...renderContext,
133
- inlined: false
134
- }
131
+ renderContext
135
132
  )
136
133
  );
137
134
  entrySource.add("\n})()");
@@ -106,8 +106,7 @@ class EnableChunkLoadingPlugin {
106
106
  }).apply(compiler);
107
107
  break;
108
108
  }
109
- case "import":
110
- case "universal": {
109
+ case "import": {
111
110
  const ModuleChunkLoadingPlugin = require("../esm/ModuleChunkLoadingPlugin");
112
111
 
113
112
  new ModuleChunkLoadingPlugin().apply(compiler);
@@ -225,8 +225,9 @@ const printGeneratedCodeForStack = (module, code) => {
225
225
  * @property {ChunkGraph} chunkGraph the chunk graph
226
226
  * @property {CodeGenerationResults} codeGenerationResults results of code generation
227
227
  * @property {boolean | undefined} strictMode rendering in strict context
228
- * @property {boolean} inlined inlined
228
+ * @property {boolean=} inlined inlined
229
229
  * @property {boolean=} inlinedInIIFE the inlined entry module is wrapped in an IIFE
230
+ * @property {boolean=} needExportsDeclaration whether the top-level exports declaration needs to be generated
230
231
  */
231
232
 
232
233
  /**
@@ -1019,10 +1020,6 @@ class JavascriptModulesPlugin {
1019
1020
  const lastInlinedModule = /** @type {Module} */ (last(inlinedModules));
1020
1021
  const startupSource = new ConcatSource();
1021
1022
 
1022
- if (runtimeRequirements.has(RuntimeGlobals.exports)) {
1023
- startupSource.add(`var ${RuntimeGlobals.exports} = {};\n`);
1024
- }
1025
-
1026
1023
  const avoidEntryIife = compilation.options.optimization.avoidEntryIife;
1027
1024
  /** @type {Map<Module, Source> | false} */
1028
1025
  let renamedInlinedModule = false;
@@ -1118,13 +1115,41 @@ class JavascriptModulesPlugin {
1118
1115
  `${RuntimeGlobals.exports} = ${RuntimeGlobals.onChunksLoaded}(${RuntimeGlobals.exports});\n`
1119
1116
  );
1120
1117
  }
1121
- source.add(
1122
- hooks.renderStartup.call(startupSource, lastInlinedModule, {
1123
- ...renderContext,
1124
- inlined: true,
1125
- inlinedInIIFE
1126
- })
1118
+ /** @type {StartupRenderContext} */
1119
+ const startupRenderContext = {
1120
+ ...renderContext,
1121
+ inlined: true,
1122
+ inlinedInIIFE,
1123
+ needExportsDeclaration: runtimeRequirements.has(RuntimeGlobals.exports)
1124
+ };
1125
+ let renderedStartup = hooks.renderStartup.call(
1126
+ startupSource,
1127
+ lastInlinedModule,
1128
+ startupRenderContext
1127
1129
  );
1130
+ const lastInlinedModuleRequirements =
1131
+ chunkGraph.getModuleRuntimeRequirements(
1132
+ lastInlinedModule,
1133
+ chunk.runtime
1134
+ );
1135
+ if (
1136
+ // `onChunksLoaded` reads and reassigns `__webpack_exports__`
1137
+ runtimeRequirements.has(RuntimeGlobals.onChunksLoaded) ||
1138
+ // Top-level `__webpack_exports__` will be returned
1139
+ runtimeRequirements.has(RuntimeGlobals.returnExportsFromRuntime) ||
1140
+ // Custom exports argument aliases from `__webpack_exports__`
1141
+ (lastInlinedModuleRequirements.has(RuntimeGlobals.exports) &&
1142
+ lastInlinedModule.exportsArgument !== RuntimeGlobals.exports)
1143
+ ) {
1144
+ startupRenderContext.needExportsDeclaration = true;
1145
+ }
1146
+ if (startupRenderContext.needExportsDeclaration) {
1147
+ renderedStartup = new ConcatSource(
1148
+ `var ${RuntimeGlobals.exports} = {};\n`,
1149
+ renderedStartup
1150
+ );
1151
+ }
1152
+ source.add(renderedStartup);
1128
1153
  if (bootstrap.afterStartup.length > 0) {
1129
1154
  const afterStartup = `${Template.asString(bootstrap.afterStartup)}\n`;
1130
1155
  source.add(
@@ -1156,7 +1181,8 @@ class JavascriptModulesPlugin {
1156
1181
  lastEntryModule,
1157
1182
  {
1158
1183
  ...renderContext,
1159
- inlined: false
1184
+ inlined: false,
1185
+ needExportsDeclaration: true
1160
1186
  }
1161
1187
  ),
1162
1188
  toSource(bootstrap.afterStartup, "webpack/after-startup"),
@@ -125,7 +125,7 @@ const BasicEvaluatedExpression = require("./BasicEvaluatedExpression");
125
125
  /** @typedef {Set<DestructuringAssignmentProperty>} DestructuringAssignmentProperties */
126
126
 
127
127
  // TODO remove cast when @types/estree has been updated to import assertions
128
- /** @typedef {import("estree").ImportExpression & { phase?: "defer" }} ImportExpression */
128
+ /** @typedef {import("estree").ImportExpression & { phase?: "defer" | "source" }} ImportExpression */
129
129
 
130
130
  /** @type {string[]} */
131
131
  const EMPTY_ARRAY = [];
@@ -4868,13 +4868,15 @@ class JavascriptParser extends Parser {
4868
4868
  return true;
4869
4869
  });
4870
4870
  }
4871
-
4871
+ case "TemplateLiteral":
4872
+ return expr.expressions.every((expr) =>
4873
+ this.isPure(expr, /** @type {Range} */ (expr.range)[0])
4874
+ );
4872
4875
  case "FunctionDeclaration":
4873
4876
  case "FunctionExpression":
4874
4877
  case "ArrowFunctionExpression":
4875
4878
  case "ThisExpression":
4876
4879
  case "Literal":
4877
- case "TemplateLiteral":
4878
4880
  case "Identifier":
4879
4881
  case "PrivateIdentifier":
4880
4882
  return true;
@@ -6,30 +6,11 @@
6
6
  "use strict";
7
7
 
8
8
  const { JSON_MODULE_TYPE } = require("../ModuleTypeConstants");
9
- const createSchemaValidation = require("../util/create-schema-validation");
10
9
  const JsonGenerator = require("./JsonGenerator");
11
10
  const JsonParser = require("./JsonParser");
12
11
 
13
12
  /** @typedef {import("../Compiler")} Compiler */
14
13
 
15
- const validate = createSchemaValidation(
16
- require("../../schemas/plugins/json/JsonModulesPluginParser.check"),
17
- () => require("../../schemas/plugins/json/JsonModulesPluginParser.json"),
18
- {
19
- name: "Json Modules Plugin",
20
- baseDataPath: "parser"
21
- }
22
- );
23
-
24
- const validateGenerator = createSchemaValidation(
25
- require("../../schemas/plugins/json/JsonModulesPluginGenerator.check"),
26
- () => require("../../schemas/plugins/json/JsonModulesPluginGenerator.json"),
27
- {
28
- name: "Json Modules Plugin",
29
- baseDataPath: "generator"
30
- }
31
- );
32
-
33
14
  const PLUGIN_NAME = "JsonModulesPlugin";
34
15
 
35
16
  /**
@@ -49,13 +30,39 @@ class JsonModulesPlugin {
49
30
  normalModuleFactory.hooks.createParser
50
31
  .for(JSON_MODULE_TYPE)
51
32
  .tap(PLUGIN_NAME, (parserOptions) => {
52
- validate(parserOptions);
33
+ compiler.validate(
34
+ () =>
35
+ require("../../schemas/plugins/json/JsonModulesPluginParser.json"),
36
+ parserOptions,
37
+ {
38
+ name: "Json Modules Plugin",
39
+ baseDataPath: "parser"
40
+ },
41
+ (options) =>
42
+ require("../../schemas/plugins/json/JsonModulesPluginParser.check")(
43
+ options
44
+ )
45
+ );
46
+
53
47
  return new JsonParser(parserOptions);
54
48
  });
55
49
  normalModuleFactory.hooks.createGenerator
56
50
  .for(JSON_MODULE_TYPE)
57
51
  .tap(PLUGIN_NAME, (generatorOptions) => {
58
- validateGenerator(generatorOptions);
52
+ compiler.validate(
53
+ () =>
54
+ require("../../schemas/plugins/json/JsonModulesPluginGenerator.json"),
55
+ generatorOptions,
56
+ {
57
+ name: "Json Modules Plugin",
58
+ baseDataPath: "generator"
59
+ },
60
+ (options) =>
61
+ require("../../schemas/plugins/json/JsonModulesPluginGenerator.check")(
62
+ options
63
+ )
64
+ );
65
+
59
66
  return new JsonGenerator(generatorOptions);
60
67
  });
61
68
  }
@@ -9,7 +9,7 @@ const { ConcatSource } = require("webpack-sources");
9
9
  const { UsageState } = require("../ExportsInfo");
10
10
  const RuntimeGlobals = require("../RuntimeGlobals");
11
11
  const Template = require("../Template");
12
- const propertyAccess = require("../util/propertyAccess");
12
+ const { propertyAccess } = require("../util/property");
13
13
  const { getEntryRuntime } = require("../util/runtime");
14
14
  const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
15
15
 
@@ -8,7 +8,7 @@
8
8
  const { ConcatSource } = require("webpack-sources");
9
9
  const { UsageState } = require("../ExportsInfo");
10
10
  const RuntimeGlobals = require("../RuntimeGlobals");
11
- const propertyAccess = require("../util/propertyAccess");
11
+ const { propertyAccess } = require("../util/property");
12
12
  const { getEntryRuntime } = require("../util/runtime");
13
13
  const AbstractLibraryPlugin = require("./AbstractLibraryPlugin");
14
14