webpack 5.46.0 → 5.49.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.

Potentially problematic release.


This version of webpack might be problematic. Click here for more details.

Files changed (39) hide show
  1. package/lib/Compilation.js +5 -2
  2. package/lib/ExternalModuleFactoryPlugin.js +1 -1
  3. package/lib/HotModuleReplacementPlugin.js +4 -4
  4. package/lib/Module.js +1 -0
  5. package/lib/MultiCompiler.js +0 -2
  6. package/lib/NormalModule.js +44 -19
  7. package/lib/NormalModuleFactory.js +145 -76
  8. package/lib/Template.js +1 -4
  9. package/lib/WebpackOptionsApply.js +8 -0
  10. package/lib/asset/AssetGenerator.js +1 -1
  11. package/lib/asset/AssetModulesPlugin.js +0 -1
  12. package/lib/config/defaults.js +44 -17
  13. package/lib/config/normalization.js +6 -1
  14. package/lib/dependencies/AMDRequireDependency.js +2 -8
  15. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +6 -3
  16. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +4 -2
  17. package/lib/dependencies/HarmonyImportDependency.js +5 -1
  18. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +40 -5
  19. package/lib/dependencies/HarmonyImportSideEffectDependency.js +2 -2
  20. package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -2
  21. package/lib/dependencies/ModuleDependency.js +8 -1
  22. package/lib/hmr/HotModuleReplacement.runtime.js +5 -1
  23. package/lib/index.js +0 -3
  24. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +2 -8
  25. package/lib/javascript/JavascriptModulesPlugin.js +48 -29
  26. package/lib/javascript/JavascriptParser.js +14 -9
  27. package/lib/optimize/SplitChunksPlugin.js +4 -4
  28. package/lib/rules/{DescriptionDataMatcherRulePlugin.js → ObjectMatcherRulePlugin.js} +14 -10
  29. package/lib/schemes/HttpUriPlugin.js +942 -25
  30. package/lib/serialization/BinaryMiddleware.js +0 -2
  31. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +2 -2
  32. package/package.json +3 -2
  33. package/schemas/WebpackOptions.check.js +1 -1
  34. package/schemas/WebpackOptions.json +50 -0
  35. package/schemas/plugins/schemes/HttpUriPlugin.check.d.ts +7 -0
  36. package/schemas/plugins/schemes/HttpUriPlugin.check.js +6 -0
  37. package/schemas/plugins/schemes/HttpUriPlugin.json +42 -0
  38. package/types.d.ts +148 -18
  39. package/lib/schemes/HttpsUriPlugin.js +0 -63
@@ -276,6 +276,14 @@ class WebpackOptionsApply extends OptionsApply {
276
276
  }).apply(compiler);
277
277
  }
278
278
 
279
+ if (options.experiments.buildHttp) {
280
+ const HttpUriPlugin = require("./schemes/HttpUriPlugin");
281
+ const httpOptions = options.experiments.buildHttp;
282
+ if (httpOptions === true)
283
+ throw new Error("Unexpected due to normalization");
284
+ new HttpUriPlugin(httpOptions).apply(compiler);
285
+ }
286
+
279
287
  new EntryOptionPlugin().apply(compiler);
280
288
  compiler.hooks.entryOption.call(options.context, options.entry);
281
289
 
@@ -229,7 +229,7 @@ class AssetGenerator extends Generator {
229
229
  }
230
230
  );
231
231
  let publicPath;
232
- if (this.publicPath) {
232
+ if (this.publicPath !== undefined) {
233
233
  const { path, info } =
234
234
  runtimeTemplate.compilation.getAssetPathWithInfo(
235
235
  this.publicPath,
@@ -120,7 +120,6 @@ class AssetModulesPlugin {
120
120
  for (const type of ["asset", "asset/inline", "asset/resource"]) {
121
121
  normalModuleFactory.hooks.createGenerator
122
122
  .for(type)
123
- // eslint-disable-next-line no-loop-func
124
123
  .tap(plugin, generatorOptions => {
125
124
  validateGeneratorOptions[type](generatorOptions);
126
125
 
@@ -171,7 +171,7 @@ const applyWebpackOptionsDefaults = options => {
171
171
 
172
172
  applySnapshotDefaults(options.snapshot, { production });
173
173
 
174
- applyExperimentsDefaults(options.experiments);
174
+ applyExperimentsDefaults(options.experiments, { production, development });
175
175
 
176
176
  applyModuleDefaults(options.module, {
177
177
  cache,
@@ -193,7 +193,10 @@ const applyWebpackOptionsDefaults = options => {
193
193
  module: options.module
194
194
  });
195
195
 
196
- applyExternalsPresetsDefaults(options.externalsPresets, { targetProperties });
196
+ applyExternalsPresetsDefaults(options.externalsPresets, {
197
+ targetProperties,
198
+ buildHttp: !!options.experiments.buildHttp
199
+ });
197
200
 
198
201
  applyLoaderDefaults(options.loader, { targetProperties });
199
202
 
@@ -245,13 +248,26 @@ const applyWebpackOptionsDefaults = options => {
245
248
 
246
249
  /**
247
250
  * @param {Experiments} experiments options
251
+ * @param {Object} options options
252
+ * @param {boolean} options.production is production
253
+ * @param {boolean} options.development is development mode
248
254
  * @returns {void}
249
255
  */
250
- const applyExperimentsDefaults = experiments => {
256
+ const applyExperimentsDefaults = (experiments, { production, development }) => {
251
257
  D(experiments, "topLevelAwait", false);
252
258
  D(experiments, "syncWebAssembly", false);
253
259
  D(experiments, "asyncWebAssembly", false);
254
260
  D(experiments, "outputModule", false);
261
+ D(experiments, "asset", false);
262
+ D(experiments, "executeModule", false);
263
+ D(experiments, "layers", false);
264
+ D(experiments, "lazyCompilation", false);
265
+ D(experiments, "buildHttp", false);
266
+
267
+ if (typeof experiments.buildHttp === "object") {
268
+ D(experiments.buildHttp, "frozen", production);
269
+ D(experiments.buildHttp, "upgrade", development);
270
+ }
255
271
  };
256
272
 
257
273
  /**
@@ -482,18 +498,6 @@ const applyModuleDefaults = (
482
498
  or: ["text/javascript", "application/javascript"]
483
499
  },
484
500
  ...esm
485
- },
486
- {
487
- dependency: "url",
488
- oneOf: [
489
- {
490
- scheme: /^data$/,
491
- type: "asset/inline"
492
- },
493
- {
494
- type: "asset/resource"
495
- }
496
- ]
497
501
  }
498
502
  ];
499
503
  if (asyncWebAssembly) {
@@ -541,6 +545,24 @@ const applyModuleDefaults = (
541
545
  ...wasm
542
546
  });
543
547
  }
548
+ rules.push(
549
+ {
550
+ dependency: "url",
551
+ oneOf: [
552
+ {
553
+ scheme: /^data$/,
554
+ type: "asset/inline"
555
+ },
556
+ {
557
+ type: "asset/resource"
558
+ }
559
+ ]
560
+ },
561
+ {
562
+ assert: { type: "json" },
563
+ type: "json"
564
+ }
565
+ );
544
566
  return rules;
545
567
  });
546
568
  };
@@ -854,13 +876,18 @@ const applyOutputDefaults = (
854
876
  * @param {ExternalsPresets} externalsPresets options
855
877
  * @param {Object} options options
856
878
  * @param {TargetProperties | false} options.targetProperties target properties
879
+ * @param {boolean} options.buildHttp buildHttp experiment enabled
857
880
  * @returns {void}
858
881
  */
859
882
  const applyExternalsPresetsDefaults = (
860
883
  externalsPresets,
861
- { targetProperties }
884
+ { targetProperties, buildHttp }
862
885
  ) => {
863
- D(externalsPresets, "web", targetProperties && targetProperties.web);
886
+ D(
887
+ externalsPresets,
888
+ "web",
889
+ !buildHttp && targetProperties && targetProperties.web
890
+ );
864
891
  D(externalsPresets, "node", targetProperties && targetProperties.node);
865
892
  D(externalsPresets, "nwjs", targetProperties && targetProperties.nwjs);
866
893
  D(
@@ -171,7 +171,12 @@ const getNormalizedWebpackOptions = config => {
171
171
  Promise.resolve().then(fn).then(getNormalizedEntryStatic)
172
172
  )(config.entry)
173
173
  : getNormalizedEntryStatic(config.entry),
174
- experiments: cloneObject(config.experiments),
174
+ experiments: nestedConfig(config.experiments, experiments => ({
175
+ ...experiments,
176
+ buildHttp: optionalNestedConfig(experiments.buildHttp, options =>
177
+ options === true ? {} : options
178
+ )
179
+ })),
175
180
  externals: config.externals,
176
181
  externalsPresets: cloneObject(config.externalsPresets),
177
182
  externalsType: config.externalsType,
@@ -123,10 +123,7 @@ AMDRequireDependency.Template = class AMDRequireDependencyTemplate extends (
123
123
 
124
124
  source.replace(dep.outerRange[0], dep.arrayRange[0] - 1, startBlock);
125
125
 
126
- source.insert(
127
- dep.arrayRange[0] + 0.9,
128
- "var __WEBPACK_AMD_REQUIRE_ARRAY__ = "
129
- );
126
+ source.insert(dep.arrayRange[0], "var __WEBPACK_AMD_REQUIRE_ARRAY__ = ");
130
127
 
131
128
  source.replace(dep.arrayRange[1], dep.functionRange[0] - 1, "; (");
132
129
 
@@ -160,10 +157,7 @@ AMDRequireDependency.Template = class AMDRequireDependencyTemplate extends (
160
157
 
161
158
  source.replace(dep.outerRange[0], dep.arrayRange[0] - 1, startBlock);
162
159
 
163
- source.insert(
164
- dep.arrayRange[0] + 0.9,
165
- "var __WEBPACK_AMD_REQUIRE_ARRAY__ = "
166
- );
160
+ source.insert(dep.arrayRange[0], "var __WEBPACK_AMD_REQUIRE_ARRAY__ = ");
167
161
 
168
162
  source.replace(dep.arrayRange[1], dep.functionRange[0] - 1, "; (");
169
163
 
@@ -12,7 +12,8 @@ const HarmonyExportHeaderDependency = require("./HarmonyExportHeaderDependency")
12
12
  const HarmonyExportImportedSpecifierDependency = require("./HarmonyExportImportedSpecifierDependency");
13
13
  const HarmonyExportSpecifierDependency = require("./HarmonyExportSpecifierDependency");
14
14
  const {
15
- harmonySpecifierTag
15
+ harmonySpecifierTag,
16
+ getAssertions
16
17
  } = require("./HarmonyImportDependencyParserPlugin");
17
18
  const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
18
19
 
@@ -48,7 +49,8 @@ module.exports = class HarmonyExportDependencyParserPlugin {
48
49
  parser.state.module.addPresentationalDependency(clearDep);
49
50
  const sideEffectDep = new HarmonyImportSideEffectDependency(
50
51
  source,
51
- parser.state.lastHarmonyImportOrder
52
+ parser.state.lastHarmonyImportOrder,
53
+ getAssertions(statement)
52
54
  );
53
55
  sideEffectDep.loc = Object.create(statement.loc);
54
56
  sideEffectDep.loc.index = -1;
@@ -127,7 +129,8 @@ module.exports = class HarmonyExportDependencyParserPlugin {
127
129
  harmonyNamedExports,
128
130
  null,
129
131
  this.strictExportPresence,
130
- null
132
+ null,
133
+ settings.assertions
131
134
  );
132
135
  } else {
133
136
  dep = new HarmonyExportSpecifierDependency(id, name);
@@ -159,6 +159,7 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
159
159
  * @param {ReadonlyArray<HarmonyExportImportedSpecifierDependency> | Iterable<HarmonyExportImportedSpecifierDependency>} otherStarExports other star exports in the module before this import
160
160
  * @param {boolean} strictExportPresence when true, missing exports in the imported module lead to errors instead of warnings
161
161
  * @param {HarmonyStarExportsList} allStarExports all star exports in the module
162
+ * @param {Record<string, any>=} assertions import assertions
162
163
  */
163
164
  constructor(
164
165
  request,
@@ -168,9 +169,10 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
168
169
  activeExports,
169
170
  otherStarExports,
170
171
  strictExportPresence,
171
- allStarExports
172
+ allStarExports,
173
+ assertions
172
174
  ) {
173
- super(request, sourceOrder);
175
+ super(request, sourceOrder, assertions);
174
176
 
175
177
  this.ids = ids;
176
178
  this.name = name;
@@ -32,10 +32,12 @@ class HarmonyImportDependency extends ModuleDependency {
32
32
  *
33
33
  * @param {string} request request string
34
34
  * @param {number} sourceOrder source order
35
+ * @param {Record<string, any>=} assertions import assertions
35
36
  */
36
- constructor(request, sourceOrder) {
37
+ constructor(request, sourceOrder, assertions) {
37
38
  super(request);
38
39
  this.sourceOrder = sourceOrder;
40
+ this.assertions = assertions;
39
41
  }
40
42
 
41
43
  get category() {
@@ -201,12 +203,14 @@ class HarmonyImportDependency extends ModuleDependency {
201
203
  serialize(context) {
202
204
  const { write } = context;
203
205
  write(this.sourceOrder);
206
+ write(this.assertions);
204
207
  super.serialize(context);
205
208
  }
206
209
 
207
210
  deserialize(context) {
208
211
  const { read } = context;
209
212
  this.sourceOrder = read();
213
+ this.assertions = read();
210
214
  super.deserialize(context);
211
215
  }
212
216
  }
@@ -14,7 +14,11 @@ const HarmonyExports = require("./HarmonyExports");
14
14
  const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDependency");
15
15
  const HarmonyImportSpecifierDependency = require("./HarmonyImportSpecifierDependency");
16
16
 
17
+ /** @typedef {import("estree").ExportAllDeclaration} ExportAllDeclaration */
18
+ /** @typedef {import("estree").ExportNamedDeclaration} ExportNamedDeclaration */
17
19
  /** @typedef {import("estree").Identifier} Identifier */
20
+ /** @typedef {import("estree").ImportDeclaration} ImportDeclaration */
21
+ /** @typedef {import("estree").ImportExpression} ImportExpression */
18
22
  /** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
19
23
  /** @typedef {import("../optimize/InnerGraph").InnerGraph} InnerGraph */
20
24
  /** @typedef {import("../optimize/InnerGraph").TopLevelSymbol} TopLevelSymbol */
@@ -29,8 +33,32 @@ const harmonySpecifierTag = Symbol("harmony import");
29
33
  * @property {number} sourceOrder
30
34
  * @property {string} name
31
35
  * @property {boolean} await
36
+ * @property {Record<string, any> | undefined} assertions
32
37
  */
33
38
 
39
+ /**
40
+ * @param {ImportDeclaration | ExportNamedDeclaration | ExportAllDeclaration | ImportExpression} node node with assertions
41
+ * @returns {Record<string, any> | undefined} assertions
42
+ */
43
+ function getAssertions(node) {
44
+ // TODO remove cast when @types/estree has been updated to import assertions
45
+ const assertions = /** @type {{ assertions?: ImportAttributeNode[] }} */ (
46
+ node
47
+ ).assertions;
48
+ if (assertions === undefined) {
49
+ return undefined;
50
+ }
51
+ const result = {};
52
+ for (const assertion of assertions) {
53
+ const key =
54
+ assertion.key.type === "Identifier"
55
+ ? assertion.key.name
56
+ : assertion.key.value;
57
+ result[key] = assertion.value.value;
58
+ }
59
+ return result;
60
+ }
61
+
34
62
  module.exports = class HarmonyImportDependencyParserPlugin {
35
63
  constructor(options) {
36
64
  this.strictExportPresence = options.strictExportPresence;
@@ -65,9 +93,11 @@ module.exports = class HarmonyImportDependencyParserPlugin {
65
93
  clearDep.loc = statement.loc;
66
94
  parser.state.module.addPresentationalDependency(clearDep);
67
95
  parser.unsetAsiPosition(statement.range[1]);
96
+ const assertions = getAssertions(statement);
68
97
  const sideEffectDep = new HarmonyImportSideEffectDependency(
69
98
  source,
70
- parser.state.lastHarmonyImportOrder
99
+ parser.state.lastHarmonyImportOrder,
100
+ assertions
71
101
  );
72
102
  sideEffectDep.loc = statement.loc;
73
103
  parser.state.module.addDependency(sideEffectDep);
@@ -82,7 +112,8 @@ module.exports = class HarmonyImportDependencyParserPlugin {
82
112
  name,
83
113
  source,
84
114
  ids,
85
- sourceOrder: parser.state.lastHarmonyImportOrder
115
+ sourceOrder: parser.state.lastHarmonyImportOrder,
116
+ assertions: getAssertions(statement)
86
117
  });
87
118
  return true;
88
119
  }
@@ -97,7 +128,8 @@ module.exports = class HarmonyImportDependencyParserPlugin {
97
128
  settings.ids,
98
129
  settings.name,
99
130
  expr.range,
100
- this.strictExportPresence
131
+ this.strictExportPresence,
132
+ settings.assertions
101
133
  );
102
134
  dep.shorthand = parser.scope.inShorthand;
103
135
  dep.directImport = true;
@@ -118,7 +150,8 @@ module.exports = class HarmonyImportDependencyParserPlugin {
118
150
  ids,
119
151
  settings.name,
120
152
  expr.range,
121
- this.strictExportPresence
153
+ this.strictExportPresence,
154
+ settings.assertions
122
155
  );
123
156
  dep.asiSafe = !parser.isAsiPosition(expr.range[0]);
124
157
  dep.loc = expr.loc;
@@ -138,7 +171,8 @@ module.exports = class HarmonyImportDependencyParserPlugin {
138
171
  ids,
139
172
  settings.name,
140
173
  callee.range,
141
- this.strictExportPresence
174
+ this.strictExportPresence,
175
+ settings.assertions
142
176
  );
143
177
  dep.directImport = members.length === 0;
144
178
  dep.call = true;
@@ -206,3 +240,4 @@ module.exports = class HarmonyImportDependencyParserPlugin {
206
240
  };
207
241
 
208
242
  module.exports.harmonySpecifierTag = harmonySpecifierTag;
243
+ module.exports.getAssertions = getAssertions;
@@ -20,8 +20,8 @@ const HarmonyImportDependency = require("./HarmonyImportDependency");
20
20
  /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
21
21
 
22
22
  class HarmonyImportSideEffectDependency extends HarmonyImportDependency {
23
- constructor(request, sourceOrder) {
24
- super(request, sourceOrder);
23
+ constructor(request, sourceOrder, assertions) {
24
+ super(request, sourceOrder, assertions);
25
25
  }
26
26
 
27
27
  get type() {
@@ -29,8 +29,16 @@ const HarmonyImportDependency = require("./HarmonyImportDependency");
29
29
  const idsSymbol = Symbol("HarmonyImportSpecifierDependency.ids");
30
30
 
31
31
  class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
32
- constructor(request, sourceOrder, ids, name, range, strictExportPresence) {
33
- super(request, sourceOrder);
32
+ constructor(
33
+ request,
34
+ sourceOrder,
35
+ ids,
36
+ name,
37
+ range,
38
+ strictExportPresence,
39
+ assertions
40
+ ) {
41
+ super(request, sourceOrder, assertions);
34
42
  this.ids = ids;
35
43
  this.name = name;
36
44
  this.range = range;
@@ -22,13 +22,20 @@ class ModuleDependency extends Dependency {
22
22
  this.request = request;
23
23
  this.userRequest = request;
24
24
  this.range = undefined;
25
+ // assertions must be serialized by subclasses that use it
26
+ /** @type {Record<string, any> | undefined} */
27
+ this.assertions = undefined;
25
28
  }
26
29
 
27
30
  /**
28
31
  * @returns {string | null} an identifier to merge equal requests
29
32
  */
30
33
  getResourceIdentifier() {
31
- return `module${this.request}`;
34
+ let str = `module${this.request}`;
35
+ if (this.assertions !== undefined) {
36
+ str += JSON.stringify(this.assertions);
37
+ }
38
+ return str;
32
39
  }
33
40
 
34
41
  /**
@@ -252,7 +252,11 @@ module.exports = function () {
252
252
  .then($hmrDownloadManifest$)
253
253
  .then(function (update) {
254
254
  if (!update) {
255
- return setStatus(applyInvalidatedModules() ? "ready" : "idle");
255
+ return setStatus(applyInvalidatedModules() ? "ready" : "idle").then(
256
+ function () {
257
+ return null;
258
+ }
259
+ );
256
260
  }
257
261
 
258
262
  return setStatus("prepare").then(function () {
package/lib/index.js CHANGED
@@ -554,9 +554,6 @@ module.exports = mergeExports(fn, {
554
554
  schemes: {
555
555
  get HttpUriPlugin() {
556
556
  return require("./schemes/HttpUriPlugin");
557
- },
558
- get HttpsUriPlugin() {
559
- return require("./schemes/HttpsUriPlugin");
560
557
  }
561
558
  }
562
559
  }
@@ -82,23 +82,17 @@ class ArrayPushCallbackChunkFormatPlugin {
82
82
  chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
83
83
  );
84
84
  if (runtimeModules.length > 0 || entries.length > 0) {
85
- const strictBailout =
86
- hooks.strictRuntimeBailout.call(renderContext);
87
85
  const runtime = new ConcatSource(
88
86
  (runtimeTemplate.supportsArrowFunction()
89
87
  ? "__webpack_require__ =>"
90
88
  : "function(__webpack_require__)") +
91
- " { // webpackRuntimeModules\n",
92
- strictBailout
93
- ? `// runtime can't be in strict mode because ${strictBailout}.\n\n`
94
- : '"use strict";\n\n'
89
+ " { // webpackRuntimeModules\n"
95
90
  );
96
91
  if (runtimeModules.length > 0) {
97
92
  runtime.add(
98
93
  Template.renderRuntimeModules(runtimeModules, {
99
94
  ...renderContext,
100
- codeGenerationResults: compilation.codeGenerationResults,
101
- useStrict: !!strictBailout
95
+ codeGenerationResults: compilation.codeGenerationResults
102
96
  })
103
97
  );
104
98
  }
@@ -72,6 +72,7 @@ const printGeneratedCodeForStack = (module, code) => {
72
72
  * @property {ModuleGraph} moduleGraph the module graph
73
73
  * @property {ChunkGraph} chunkGraph the chunk graph
74
74
  * @property {CodeGenerationResults} codeGenerationResults results of code generation
75
+ * @property {boolean} strictMode rendering in strict context
75
76
  */
76
77
 
77
78
  /**
@@ -83,6 +84,7 @@ const printGeneratedCodeForStack = (module, code) => {
83
84
  * @property {ChunkGraph} chunkGraph the chunk graph
84
85
  * @property {CodeGenerationResults} codeGenerationResults results of code generation
85
86
  * @property {string} hash hash to be used for render call
87
+ * @property {boolean} strictMode rendering in strict context
86
88
  */
87
89
 
88
90
  /**
@@ -94,6 +96,7 @@ const printGeneratedCodeForStack = (module, code) => {
94
96
  * @property {ChunkGraph} chunkGraph the chunk graph
95
97
  * @property {CodeGenerationResults} codeGenerationResults results of code generation
96
98
  * @property {InitFragment<ChunkRenderContext>[]} chunkInitFragments init fragments for the chunk
99
+ * @property {boolean} strictMode rendering in strict context
97
100
  */
98
101
 
99
102
  /**
@@ -256,7 +259,8 @@ class JavascriptModulesPlugin {
256
259
  runtimeTemplate,
257
260
  moduleGraph,
258
261
  chunkGraph,
259
- codeGenerationResults
262
+ codeGenerationResults,
263
+ strictMode: runtimeTemplate.isModule()
260
264
  },
261
265
  hooks
262
266
  );
@@ -270,7 +274,8 @@ class JavascriptModulesPlugin {
270
274
  runtimeTemplate,
271
275
  moduleGraph,
272
276
  chunkGraph,
273
- codeGenerationResults
277
+ codeGenerationResults,
278
+ strictMode: runtimeTemplate.isModule()
274
279
  },
275
280
  hooks,
276
281
  compilation
@@ -288,7 +293,8 @@ class JavascriptModulesPlugin {
288
293
  runtimeTemplate,
289
294
  moduleGraph,
290
295
  chunkGraph,
291
- codeGenerationResults
296
+ codeGenerationResults,
297
+ strictMode: runtimeTemplate.isModule()
292
298
  },
293
299
  hooks
294
300
  );
@@ -478,12 +484,17 @@ class JavascriptModulesPlugin {
478
484
  * @param {Module} module the rendered module
479
485
  * @param {ChunkRenderContext} renderContext options object
480
486
  * @param {CompilationHooks} hooks hooks
481
- * @param {boolean | "strict"} factory true: renders as factory method, "strict": renders as factory method already in strict scope, false: pure module content
487
+ * @param {boolean} factory true: renders as factory method, false: pure module content
482
488
  * @returns {Source} the newly generated source from rendering
483
489
  */
484
490
  renderModule(module, renderContext, hooks, factory) {
485
- const { chunk, chunkGraph, runtimeTemplate, codeGenerationResults } =
486
- renderContext;
491
+ const {
492
+ chunk,
493
+ chunkGraph,
494
+ runtimeTemplate,
495
+ codeGenerationResults,
496
+ strictMode
497
+ } = renderContext;
487
498
  try {
488
499
  const codeGenResult = codeGenerationResults.get(module, chunk.runtime);
489
500
  const moduleSource = codeGenResult.sources.get("javascript");
@@ -514,7 +525,7 @@ class JavascriptModulesPlugin {
514
525
  const needThisAsExports = runtimeRequirements.has(
515
526
  RuntimeGlobals.thisAsExports
516
527
  );
517
- const needStrict = module.buildInfo.strict && factory !== "strict";
528
+ const needStrict = module.buildInfo.strict && !strictMode;
518
529
  const cacheEntry = this._moduleFactoryCache.get(
519
530
  moduleSourcePostContent
520
531
  );
@@ -598,16 +609,25 @@ class JavascriptModulesPlugin {
598
609
  "javascript",
599
610
  compareModulesByIdentifier
600
611
  );
612
+ const allModules = modules ? Array.from(modules) : [];
613
+ let strictHeader;
614
+ let allStrict = renderContext.strictMode;
615
+ if (!allStrict && allModules.every(m => m.buildInfo.strict)) {
616
+ const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
617
+ strictHeader = strictBailout
618
+ ? `// runtime can't be in strict mode because ${strictBailout}.\n`
619
+ : '"use strict";\n';
620
+ if (!strictBailout) allStrict = true;
621
+ }
601
622
  /** @type {ChunkRenderContext} */
602
623
  const chunkRenderContext = {
603
624
  ...renderContext,
604
- chunkInitFragments: []
625
+ chunkInitFragments: [],
626
+ strictMode: allStrict
605
627
  };
606
628
  const moduleSources =
607
- Template.renderChunkModules(
608
- chunkRenderContext,
609
- modules ? Array.from(modules) : [],
610
- module => this.renderModule(module, chunkRenderContext, hooks, true)
629
+ Template.renderChunkModules(chunkRenderContext, allModules, module =>
630
+ this.renderModule(module, chunkRenderContext, hooks, true)
611
631
  ) || new RawSource("{}");
612
632
  let source = tryRunOrWebpackError(
613
633
  () => hooks.renderChunk.call(moduleSources, chunkRenderContext),
@@ -637,7 +657,11 @@ class JavascriptModulesPlugin {
637
657
  );
638
658
  }
639
659
  chunk.rendered = true;
640
- return new ConcatSource(source, ";");
660
+ return strictHeader
661
+ ? new ConcatSource(strictHeader, source, ";")
662
+ : renderContext.runtimeTemplate.isModule()
663
+ ? source
664
+ : new ConcatSource(source, ";");
641
665
  }
642
666
 
643
667
  /**
@@ -649,12 +673,6 @@ class JavascriptModulesPlugin {
649
673
  renderMain(renderContext, hooks, compilation) {
650
674
  const { chunk, chunkGraph, runtimeTemplate } = renderContext;
651
675
 
652
- /** @type {ChunkRenderContext} */
653
- const chunkRenderContext = {
654
- ...renderContext,
655
- chunkInitFragments: []
656
- };
657
-
658
676
  const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
659
677
  const iife = runtimeTemplate.isIIFE();
660
678
 
@@ -687,8 +705,8 @@ class JavascriptModulesPlugin {
687
705
  } else {
688
706
  prefix = "/******/ ";
689
707
  }
690
- let allStrict = false;
691
- if (allModules.every(m => m.buildInfo.strict)) {
708
+ let allStrict = renderContext.strictMode;
709
+ if (!allStrict && allModules.every(m => m.buildInfo.strict)) {
692
710
  const strictBailout = hooks.strictRuntimeBailout.call(renderContext);
693
711
  if (strictBailout) {
694
712
  source.add(
@@ -701,18 +719,19 @@ class JavascriptModulesPlugin {
701
719
  }
702
720
  }
703
721
 
722
+ /** @type {ChunkRenderContext} */
723
+ const chunkRenderContext = {
724
+ ...renderContext,
725
+ chunkInitFragments: [],
726
+ strictMode: allStrict
727
+ };
728
+
704
729
  const chunkModules = Template.renderChunkModules(
705
730
  chunkRenderContext,
706
731
  inlinedModules
707
732
  ? allModules.filter(m => !inlinedModules.has(m))
708
733
  : allModules,
709
- module =>
710
- this.renderModule(
711
- module,
712
- chunkRenderContext,
713
- hooks,
714
- allStrict ? "strict" : true
715
- ),
734
+ module => this.renderModule(module, chunkRenderContext, hooks, true),
716
735
  prefix
717
736
  );
718
737
  if (
@@ -751,7 +770,7 @@ class JavascriptModulesPlugin {
751
770
  source.add(
752
771
  new PrefixSource(
753
772
  prefix,
754
- Template.renderRuntimeModules(runtimeModules, renderContext)
773
+ Template.renderRuntimeModules(runtimeModules, chunkRenderContext)
755
774
  )
756
775
  );
757
776
  source.add(