webpack 5.10.0 → 5.11.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 (40) hide show
  1. package/bin/webpack.js +0 -0
  2. package/lib/Compilation.js +5 -21
  3. package/lib/Compiler.js +58 -13
  4. package/lib/FlagAllModulesAsUsedPlugin.js +4 -0
  5. package/lib/MainTemplate.js +2 -2
  6. package/lib/Module.js +1 -1
  7. package/lib/ModuleInfoHeaderPlugin.js +1 -1
  8. package/lib/NormalModule.js +4 -2
  9. package/lib/RuntimeGlobals.js +11 -1
  10. package/lib/RuntimeModule.js +20 -0
  11. package/lib/RuntimeTemplate.js +4 -0
  12. package/lib/cache/PackFileCacheStrategy.js +4 -2
  13. package/lib/hmr/HotModuleReplacementRuntimeModule.js +1 -1
  14. package/lib/index.js +5 -0
  15. package/lib/javascript/JavascriptModulesPlugin.js +82 -26
  16. package/lib/node/NodeTargetPlugin.js +4 -0
  17. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +1 -1
  18. package/lib/node/RequireChunkLoadingRuntimeModule.js +1 -1
  19. package/lib/optimize/SideEffectsFlagPlugin.js +9 -13
  20. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +1 -1
  21. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +1 -1
  22. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +1 -1
  23. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +1 -1
  24. package/lib/rules/RuleSetCompiler.js +4 -2
  25. package/lib/runtime/AutoPublicPathRuntimeModule.js +1 -1
  26. package/lib/runtime/CompatRuntimeModule.js +1 -1
  27. package/lib/runtime/PublicPathRuntimeModule.js +1 -1
  28. package/lib/serialization/BinaryMiddleware.js +467 -136
  29. package/lib/serialization/FileMiddleware.js +227 -37
  30. package/lib/serialization/ObjectMiddleware.js +89 -5
  31. package/lib/sharing/ConsumeSharedRuntimeModule.js +1 -1
  32. package/lib/util/fs.js +4 -0
  33. package/lib/util/source.js +61 -0
  34. package/lib/validateSchema.js +84 -73
  35. package/lib/wasm-async/AsyncWasmChunkLoadingRuntimeModule.js +1 -1
  36. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +1 -1
  37. package/lib/web/JsonpChunkLoadingRuntimeModule.js +54 -55
  38. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +1 -1
  39. package/package.json +8 -8
  40. package/types.d.ts +1170 -578
package/bin/webpack.js CHANGED
File without changes
@@ -71,6 +71,7 @@ const {
71
71
  createFakeHook
72
72
  } = require("./util/deprecation");
73
73
  const { getRuntimeKey } = require("./util/runtime");
74
+ const { isSourceEqual } = require("./util/source");
74
75
 
75
76
  /** @template T @typedef {import("tapable").AsArray<T>} AsArray<T> */
76
77
  /** @typedef {import("webpack-sources").Source} Source */
@@ -166,7 +167,7 @@ const { getRuntimeKey } = require("./util/runtime");
166
167
  */
167
168
 
168
169
  /**
169
- * @typedef {Object} AssetInfo
170
+ * @typedef {Object} KnownAssetInfo
170
171
  * @property {boolean=} immutable true, if the asset can be long term cached forever (contains a hash)
171
172
  * @property {boolean=} minimized whether the asset is minimized
172
173
  * @property {string | string[]=} fullhash the value(s) of the full hash used for this asset
@@ -181,6 +182,8 @@ const { getRuntimeKey } = require("./util/runtime");
181
182
  * @property {Record<string, string | string[]>=} related object of pointers to other assets, keyed by type of relation (only points from parent to child)
182
183
  */
183
184
 
185
+ /** @typedef {KnownAssetInfo & Record<string, any>} AssetInfo */
186
+
184
187
  /**
185
188
  * @typedef {Object} Asset
186
189
  * @property {string} name the filename of the asset
@@ -263,25 +266,6 @@ const byLocation = compareSelect(err => err.loc, compareLocations);
263
266
 
264
267
  const compareErrors = concatComparators(byModule, byLocation, byMessage);
265
268
 
266
- /**
267
- * @param {Source} a a source
268
- * @param {Source} b another source
269
- * @returns {boolean} true, when both sources are equal
270
- */
271
- const isSourceEqual = (a, b) => {
272
- if (a === b) return true;
273
- // TODO webpack 5: check .buffer() instead, it's called anyway during emit
274
- /** @type {Buffer|string} */
275
- let aSource = a.source();
276
- /** @type {Buffer|string} */
277
- let bSource = b.source();
278
- if (aSource === bSource) return true;
279
- if (typeof aSource === "string" && typeof bSource === "string") return false;
280
- if (!Buffer.isBuffer(aSource)) aSource = Buffer.from(aSource, "utf-8");
281
- if (!Buffer.isBuffer(bSource)) bSource = Buffer.from(bSource, "utf-8");
282
- return aSource.equals(bSource);
283
- };
284
-
285
269
  class Compilation {
286
270
  /**
287
271
  * Creates an instance of Compilation.
@@ -309,7 +293,7 @@ class Compilation {
309
293
  processAssetsHook.intercept({
310
294
  name: "Compilation",
311
295
  call: () => {
312
- savedAssets.clear();
296
+ savedAssets = new Set(Object.keys(this.assets));
313
297
  },
314
298
  register: tap => {
315
299
  const { type, name } = tap;
package/lib/Compiler.js CHANGED
@@ -29,6 +29,7 @@ const WebpackError = require("./WebpackError");
29
29
  const { Logger } = require("./logging/Logger");
30
30
  const { join, dirname, mkdirp } = require("./util/fs");
31
31
  const { makePathsRelative } = require("./util/identifier");
32
+ const { isSourceEqual } = require("./util/source");
32
33
 
33
34
  /** @typedef {import("webpack-sources").Source} Source */
34
35
  /** @typedef {import("../declarations/WebpackOptions").EntryNormalized} Entry */
@@ -530,6 +531,7 @@ class Compiler {
530
531
 
531
532
  const assets = compilation.getAssets();
532
533
  compilation.assets = { ...compilation.assets };
534
+ /** @type {Map<string, { path: string, source: Source, size: number, waiting: { cacheEntry: any, file: string }[] }>} */
533
535
  const caseInsensitiveMap = new Map();
534
536
  asyncLib.forEachLimit(
535
537
  assets,
@@ -559,19 +561,6 @@ class Compiler {
559
561
  targetFile
560
562
  );
561
563
 
562
- const caseInsensitiveTargetPath = targetPath.toLowerCase();
563
- if (caseInsensitiveMap.has(caseInsensitiveTargetPath)) {
564
- const other = caseInsensitiveMap.get(caseInsensitiveTargetPath);
565
- const err = new WebpackError(`Prevent writing to file that only differs in casing or query string from already written file.
566
- This will lead to a race-condition and corrupted files on case-insensitive file systems.
567
- ${targetPath}
568
- ${other}`);
569
- err.file = file;
570
- return callback(err);
571
- } else {
572
- caseInsensitiveMap.set(caseInsensitiveTargetPath, targetPath);
573
- }
574
-
575
564
  // check if the target file has already been written by this Compiler
576
565
  const targetFileGeneration = this._assetEmittingWrittenFiles.get(
577
566
  targetPath
@@ -587,6 +576,46 @@ ${other}`);
587
576
  this._assetEmittingSourceCache.set(source, cacheEntry);
588
577
  }
589
578
 
579
+ let similarEntry;
580
+
581
+ const checkSimilarFile = () => {
582
+ const caseInsensitiveTargetPath = targetPath.toLowerCase();
583
+ similarEntry = caseInsensitiveMap.get(caseInsensitiveTargetPath);
584
+ if (similarEntry !== undefined) {
585
+ const { path: other, source: otherSource } = similarEntry;
586
+ if (isSourceEqual(otherSource, source)) {
587
+ // Size may or may not be available at this point.
588
+ // If it's not available add to "waiting" list and it will be updated once available
589
+ if (similarEntry.size !== undefined) {
590
+ updateWithReplacementSource(similarEntry.size);
591
+ } else {
592
+ if (!similarEntry.waiting) similarEntry.waiting = [];
593
+ similarEntry.waiting.push({ file, cacheEntry });
594
+ }
595
+ alreadyWritten();
596
+ } else {
597
+ const err = new WebpackError(`Prevent writing to file that only differs in casing or query string from already written file.
598
+ This will lead to a race-condition and corrupted files on case-insensitive file systems.
599
+ ${targetPath}
600
+ ${other}`);
601
+ err.file = file;
602
+ callback(err);
603
+ }
604
+ return true;
605
+ } else {
606
+ caseInsensitiveMap.set(
607
+ caseInsensitiveTargetPath,
608
+ (similarEntry = {
609
+ path: targetPath,
610
+ source,
611
+ size: undefined,
612
+ waiting: undefined
613
+ })
614
+ );
615
+ return false;
616
+ }
617
+ };
618
+
590
619
  /**
591
620
  * get the binary (Buffer) content from the Source
592
621
  * @returns {Buffer} content for the source
@@ -650,6 +679,20 @@ ${other}`);
650
679
  };
651
680
 
652
681
  const updateWithReplacementSource = size => {
682
+ updateFileWithReplacementSource(file, cacheEntry, size);
683
+ similarEntry.size = size;
684
+ if (similarEntry.waiting !== undefined) {
685
+ for (const { file, cacheEntry } of similarEntry.waiting) {
686
+ updateFileWithReplacementSource(file, cacheEntry, size);
687
+ }
688
+ }
689
+ };
690
+
691
+ const updateFileWithReplacementSource = (
692
+ file,
693
+ cacheEntry,
694
+ size
695
+ ) => {
653
696
  // Create a replacement resource which only allows to ask for size
654
697
  // This allows to GC all memory allocated by the Source
655
698
  // (expect when the Source is stored in any other cache)
@@ -718,6 +761,7 @@ ${other}`);
718
761
  }
719
762
 
720
763
  if (!immutable) {
764
+ if (checkSimilarFile()) return;
721
765
  // We wrote to this file before which has very likely a different content
722
766
  // skip comparing and assume content is different for performance
723
767
  // This case happens often during watch mode.
@@ -725,6 +769,7 @@ ${other}`);
725
769
  }
726
770
  }
727
771
 
772
+ if (checkSimilarFile()) return;
728
773
  if (this.options.output.compareBeforeEmit) {
729
774
  this.outputFileSystem.stat(targetPath, (err, stats) => {
730
775
  const exists = !err && stats.isFile();
@@ -40,6 +40,10 @@ class FlagAllModulesAsUsedPlugin {
40
40
  const exportsInfo = moduleGraph.getExportsInfo(module);
41
41
  exportsInfo.setUsedInUnknownWay(runtime);
42
42
  moduleGraph.addExtraReason(module, this.explanation);
43
+ if (module.factoryMeta === undefined) {
44
+ module.factoryMeta = {};
45
+ }
46
+ module.factoryMeta.sideEffectFree = false;
43
47
  }
44
48
  }
45
49
  );
@@ -91,7 +91,7 @@ class MainTemplate {
91
91
  beforeStartup: {
92
92
  tap: () => {
93
93
  throw new Error(
94
- "MainTemplate.hooks.beforeStartup has been removed (use RuntimeGlobals.startup instead)"
94
+ "MainTemplate.hooks.beforeStartup has been removed (use RuntimeGlobals.startupOnlyBefore instead)"
95
95
  );
96
96
  }
97
97
  },
@@ -105,7 +105,7 @@ class MainTemplate {
105
105
  afterStartup: {
106
106
  tap: () => {
107
107
  throw new Error(
108
- "MainTemplate.hooks.afterStartup has been removed (use RuntimeGlobals.startup instead)"
108
+ "MainTemplate.hooks.afterStartup has been removed (use RuntimeGlobals.startupOnlyAfter instead)"
109
109
  );
110
110
  }
111
111
  },
package/lib/Module.js CHANGED
@@ -153,7 +153,7 @@ class Module extends DependenciesBlock {
153
153
  this._errors = undefined;
154
154
  /** @type {BuildMeta} */
155
155
  this.buildMeta = undefined;
156
- /** @type {object} */
156
+ /** @type {Record<string, any>} */
157
157
  this.buildInfo = undefined;
158
158
  /** @type {Dependency[] | undefined} */
159
159
  this.presentationalDependencies = undefined;
@@ -191,7 +191,7 @@ class ModuleInfoHeaderPlugin {
191
191
  const req = module.readableIdentifier(requestShortener);
192
192
  const reqStr = req.replace(/\*\//g, "*_/");
193
193
  const reqStrStar = "*".repeat(reqStr.length);
194
- const headerStr = `/*!****${reqStrStar}****!*\n !*** ${reqStr} ***!\n \\****${reqStrStar}****/\n`;
194
+ const headerStr = `/*!****${reqStrStar}****!*\\\n !*** ${reqStr} ***!\n \\****${reqStrStar}****/\n`;
195
195
  header = new RawSource(headerStr);
196
196
  cacheEntry.header = header;
197
197
  }
@@ -868,8 +868,10 @@ class NormalModule extends Module {
868
868
  * @returns {ConnectionState} how this module should be connected to referencing modules when consumed for side-effects only
869
869
  */
870
870
  getSideEffectsConnectionState(moduleGraph) {
871
- if (this.factoryMeta !== undefined && this.factoryMeta.sideEffectFree)
872
- return false;
871
+ if (this.factoryMeta !== undefined) {
872
+ if (this.factoryMeta.sideEffectFree) return false;
873
+ if (this.factoryMeta.sideEffectFree === false) return true;
874
+ }
873
875
  if (this.buildMeta !== undefined && this.buildMeta.sideEffectFree) {
874
876
  if (this._isEvaluatingSideEffects)
875
877
  return ModuleGraphConnection.CIRCULAR_CONNECTION;
@@ -194,10 +194,20 @@ exports.getChunkUpdateScriptFilename = "__webpack_require__.hu";
194
194
  exports.startup = "__webpack_require__.x";
195
195
 
196
196
  /**
197
- * startup signal from runtime
197
+ * creating a default startup function with the entry modules
198
198
  */
199
199
  exports.startupNoDefault = "__webpack_require__.x (no default handler)";
200
200
 
201
+ /**
202
+ * startup signal from runtime but only used to add logic after the startup
203
+ */
204
+ exports.startupOnlyAfter = "__webpack_require__.x (only after)";
205
+
206
+ /**
207
+ * startup signal from runtime but only used to add sync logic before the startup
208
+ */
209
+ exports.startupOnlyBefore = "__webpack_require__.x (only before)";
210
+
201
211
  /**
202
212
  * method to startup an entrypoint with needed chunks.
203
213
  * Signature: (moduleId: Id, chunkIds: Id[]) => any.
@@ -185,4 +185,24 @@ class RuntimeModule extends Module {
185
185
  }
186
186
  }
187
187
 
188
+ /**
189
+ * Runtime modules without any dependencies to other runtime modules
190
+ */
191
+ RuntimeModule.STAGE_NORMAL = 0;
192
+
193
+ /**
194
+ * Runtime modules with simple dependencies on other runtime modules
195
+ */
196
+ RuntimeModule.STAGE_BASIC = 5;
197
+
198
+ /**
199
+ * Runtime modules which attach to handlers of other runtime modules
200
+ */
201
+ RuntimeModule.STAGE_ATTACH = 10;
202
+
203
+ /**
204
+ * Runtime modules which trigger actions on bootstrap
205
+ */
206
+ RuntimeModule.STAGE_TRIGGER = 20;
207
+
188
208
  module.exports = RuntimeModule;
@@ -113,6 +113,10 @@ class RuntimeTemplate {
113
113
  : `function(${args}) {\n${Template.indent(body)}\n}`;
114
114
  }
115
115
 
116
+ emptyFunction() {
117
+ return this.supportsArrowFunction() ? "x => {}" : "function() {}";
118
+ }
119
+
116
120
  destructureArray(items, value) {
117
121
  return this.supportsDestructuring()
118
122
  ? `var [${items.join(", ")}] = ${value};`
@@ -961,10 +961,8 @@ class PackFileCacheStrategy {
961
961
  for (const dep of this.newBuildDependencies) {
962
962
  if (!this.buildDependencies.has(dep)) {
963
963
  newBuildDependencies.add(dep);
964
- this.buildDependencies.add(dep);
965
964
  }
966
965
  }
967
- this.newBuildDependencies.clear();
968
966
  if (newBuildDependencies.size > 0 || !this.buildSnapshot) {
969
967
  if (reportProgress) reportProgress(0.5, "resolve build dependencies");
970
968
  this.logger.debug(
@@ -1093,6 +1091,10 @@ class PackFileCacheStrategy {
1093
1091
  logger: this.logger
1094
1092
  })
1095
1093
  .then(() => {
1094
+ for (const dep of newBuildDependencies) {
1095
+ this.buildDependencies.add(dep);
1096
+ }
1097
+ this.newBuildDependencies.clear();
1096
1098
  this.logger.timeEnd(`store pack`);
1097
1099
  this.logger.log(`Stored pack`);
1098
1100
  })
@@ -11,7 +11,7 @@ const Template = require("../Template");
11
11
 
12
12
  class HotModuleReplacementRuntimeModule extends RuntimeModule {
13
13
  constructor() {
14
- super("hot module replacement", 5);
14
+ super("hot module replacement", RuntimeModule.STAGE_BASIC);
15
15
  }
16
16
  /**
17
17
  * @returns {string} runtime code
package/lib/index.js CHANGED
@@ -22,6 +22,8 @@ const memorize = require("./util/memorize");
22
22
  /** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptionsNormalized */
23
23
  /** @typedef {import("../declarations/WebpackOptions").WebpackPluginFunction} WebpackPluginFunction */
24
24
  /** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */
25
+ /** @typedef {import("./Compilation").Asset} Asset */
26
+ /** @typedef {import("./Compilation").AssetInfo} AssetInfo */
25
27
  /** @typedef {import("./Parser").ParserState} ParserState */
26
28
 
27
29
  /**
@@ -260,6 +262,9 @@ module.exports = mergeExports(fn, {
260
262
  get WatchIgnorePlugin() {
261
263
  return require("./WatchIgnorePlugin");
262
264
  },
265
+ get WebpackError() {
266
+ return require("./WebpackError");
267
+ },
263
268
  get WebpackOptionsApply() {
264
269
  return require("./WebpackOptionsApply");
265
270
  },
@@ -630,6 +630,17 @@ class JavascriptModulesPlugin {
630
630
  }
631
631
  }
632
632
  if (inlinedModules) {
633
+ if (bootstrap.beforeStartup.length > 0) {
634
+ const beforeStartup = Template.asString(bootstrap.beforeStartup) + "\n";
635
+ source.add(
636
+ new PrefixSource(
637
+ prefix,
638
+ useSourceMap
639
+ ? new OriginalSource(beforeStartup, "webpack/before-startup")
640
+ : new RawSource(beforeStartup)
641
+ )
642
+ );
643
+ }
633
644
  for (const m of inlinedModules) {
634
645
  const renderedModule = this.renderModule(
635
646
  m,
@@ -658,8 +669,24 @@ class JavascriptModulesPlugin {
658
669
  }
659
670
  }
660
671
  }
672
+ if (bootstrap.afterStartup.length > 0) {
673
+ const afterStartup = Template.asString(bootstrap.afterStartup) + "\n";
674
+ source.add(
675
+ new PrefixSource(
676
+ prefix,
677
+ useSourceMap
678
+ ? new OriginalSource(afterStartup, "webpack/after-startup")
679
+ : new RawSource(afterStartup)
680
+ )
681
+ );
682
+ }
661
683
  } else {
662
- const startup = Template.asString(bootstrap.startup) + "\n";
684
+ const startup =
685
+ Template.asString([
686
+ ...bootstrap.beforeStartup,
687
+ ...bootstrap.startup,
688
+ ...bootstrap.afterStartup
689
+ ]) + "\n";
663
690
  source.add(
664
691
  new PrefixSource(
665
692
  prefix,
@@ -718,7 +745,7 @@ class JavascriptModulesPlugin {
718
745
  /**
719
746
  * @param {RenderBootstrapContext} renderContext options object
720
747
  * @param {CompilationHooks} hooks hooks
721
- * @returns {{ header: string[], startup: string[], allowInlineStartup: boolean }} the generated source of the bootstrap code
748
+ * @returns {{ header: string[], beforeStartup: string[], startup: string[], afterStartup: string[], allowInlineStartup: boolean }} the generated source of the bootstrap code
722
749
  */
723
750
  renderBootstrap(renderContext, hooks) {
724
751
  const { chunkGraph, moduleGraph, chunk, runtimeTemplate } = renderContext;
@@ -751,12 +778,13 @@ class JavascriptModulesPlugin {
751
778
 
752
779
  const result = {
753
780
  header: [],
781
+ beforeStartup: [],
754
782
  startup: [],
783
+ afterStartup: [],
755
784
  allowInlineStartup: true
756
785
  };
757
786
 
758
- let buf = result.header;
759
- let startup = result.startup;
787
+ let { header: buf, startup, beforeStartup, afterStartup } = result;
760
788
 
761
789
  if (result.allowInlineStartup && moduleFactories) {
762
790
  startup.push(
@@ -889,40 +917,68 @@ class JavascriptModulesPlugin {
889
917
  buf2.push(`__webpack_modules__[${moduleIdExpr}]();`);
890
918
  }
891
919
  }
892
- if (runtimeRequirements.has(RuntimeGlobals.startup)) {
920
+ if (
921
+ runtimeRequirements.has(RuntimeGlobals.startup) ||
922
+ ((returnExportsFromRuntime ||
923
+ runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) &&
924
+ runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter))
925
+ ) {
893
926
  result.allowInlineStartup = false;
927
+ buf.push("// the startup function");
894
928
  buf.push(
895
- Template.asString([
896
- "// the startup function",
897
- `${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction(
898
- "",
899
- buf2
900
- )};`
901
- ])
929
+ `${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction(
930
+ "",
931
+ buf2
932
+ )};`
902
933
  );
903
934
  buf.push("");
904
935
  startup.push("// run startup");
905
936
  startup.push(`return ${RuntimeGlobals.startup}();`);
906
- } else {
907
- startup.push(
908
- Template.asString(["// startup", Template.asString(buf2)])
937
+ } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore)) {
938
+ buf.push("// the startup function");
939
+ buf.push(
940
+ `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
941
+ );
942
+ beforeStartup.push("// run runtime startup");
943
+ beforeStartup.push(`${RuntimeGlobals.startup}();`);
944
+ startup.push("// startup");
945
+ startup.push(Template.asString(buf2));
946
+ } else if (runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)) {
947
+ buf.push("// the startup function");
948
+ buf.push(
949
+ `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()};`
909
950
  );
951
+ startup.push("// startup");
952
+ startup.push(Template.asString(buf2));
953
+ afterStartup.push("// run runtime startup");
954
+ afterStartup.push(`return ${RuntimeGlobals.startup}();`);
955
+ } else {
956
+ startup.push("// startup");
957
+ startup.push(Template.asString(buf2));
910
958
  }
911
- } else if (runtimeRequirements.has(RuntimeGlobals.startup)) {
959
+ } else if (
960
+ runtimeRequirements.has(RuntimeGlobals.startup) ||
961
+ runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
962
+ runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
963
+ ) {
912
964
  buf.push(
913
- Template.asString([
914
- "// the startup function",
915
- "// It's empty as no entry modules are in this chunk",
916
- `${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction(
917
- "",
918
- ""
919
- )}`
920
- ])
965
+ "// the startup function",
966
+ "// It's empty as no entry modules are in this chunk",
967
+ `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()}`,
968
+ ""
921
969
  );
922
- buf.push("");
923
970
  }
924
- } else if (runtimeRequirements.has(RuntimeGlobals.startup)) {
971
+ } else if (
972
+ runtimeRequirements.has(RuntimeGlobals.startup) ||
973
+ runtimeRequirements.has(RuntimeGlobals.startupOnlyBefore) ||
974
+ runtimeRequirements.has(RuntimeGlobals.startupOnlyAfter)
975
+ ) {
925
976
  result.allowInlineStartup = false;
977
+ buf.push(
978
+ "// the startup function",
979
+ "// It's empty as some runtime module handles the default behavior",
980
+ `${RuntimeGlobals.startup} = ${runtimeTemplate.emptyFunction()}`
981
+ );
926
982
  startup.push("// run startup");
927
983
  startup.push(`return ${RuntimeGlobals.startup}();`);
928
984
  }
@@ -20,6 +20,7 @@ const builtins = [
20
20
  "crypto",
21
21
  "dgram",
22
22
  "dns",
23
+ "dns/promises",
23
24
  "domain",
24
25
  "events",
25
26
  "fs",
@@ -39,9 +40,11 @@ const builtins = [
39
40
  "readline",
40
41
  "repl",
41
42
  "stream",
43
+ "stream/promises",
42
44
  "string_decoder",
43
45
  "sys",
44
46
  "timers",
47
+ "timers/promises",
45
48
  "tls",
46
49
  "trace_events",
47
50
  "tty",
@@ -49,6 +52,7 @@ const builtins = [
49
52
  "util",
50
53
  "v8",
51
54
  "vm",
55
+ "wasi", // cSpell:ignore wasi
52
56
  "worker_threads",
53
57
  "zlib"
54
58
  ];
@@ -16,7 +16,7 @@ const { getUndoPath } = require("../util/identifier");
16
16
 
17
17
  class ReadFileChunkLoadingRuntimeModule extends RuntimeModule {
18
18
  constructor(runtimeRequirements) {
19
- super("readFile chunk loading", 10);
19
+ super("readFile chunk loading", RuntimeModule.STAGE_ATTACH);
20
20
  this.runtimeRequirements = runtimeRequirements;
21
21
  }
22
22
 
@@ -16,7 +16,7 @@ const { getUndoPath } = require("../util/identifier");
16
16
 
17
17
  class RequireChunkLoadingRuntimeModule extends RuntimeModule {
18
18
  constructor(runtimeRequirements) {
19
- super("require chunk loading", 10);
19
+ super("require chunk loading", RuntimeModule.STAGE_ATTACH);
20
20
  this.runtimeRequirements = runtimeRequirements;
21
21
  }
22
22
 
@@ -82,16 +82,16 @@ class SideEffectsFlagPlugin {
82
82
  resolveData.relativePath
83
83
  ) {
84
84
  const sideEffects = resolveData.descriptionFileData.sideEffects;
85
- const hasSideEffects = SideEffectsFlagPlugin.moduleHasSideEffects(
86
- resolveData.relativePath,
87
- sideEffects,
88
- cache
89
- );
90
- if (!hasSideEffects) {
85
+ if (sideEffects !== undefined) {
91
86
  if (module.factoryMeta === undefined) {
92
87
  module.factoryMeta = {};
93
88
  }
94
- module.factoryMeta.sideEffectFree = true;
89
+ const hasSideEffects = SideEffectsFlagPlugin.moduleHasSideEffects(
90
+ resolveData.relativePath,
91
+ sideEffects,
92
+ cache
93
+ );
94
+ module.factoryMeta.sideEffectFree = !hasSideEffects;
95
95
  }
96
96
  }
97
97
 
@@ -101,15 +101,11 @@ class SideEffectsFlagPlugin {
101
101
  normalModuleFactory.hooks.module.tap(
102
102
  "SideEffectsFlagPlugin",
103
103
  (module, data) => {
104
- if (data.settings.sideEffects === false) {
104
+ if (typeof data.settings.sideEffects === "boolean") {
105
105
  if (module.factoryMeta === undefined) {
106
106
  module.factoryMeta = {};
107
107
  }
108
- module.factoryMeta.sideEffectFree = true;
109
- } else if (data.settings.sideEffects === true) {
110
- if (module.factoryMeta !== undefined) {
111
- module.factoryMeta.sideEffectFree = false;
112
- }
108
+ module.factoryMeta.sideEffectFree = !data.settings.sideEffects;
113
109
  }
114
110
  return module;
115
111
  }
@@ -16,7 +16,7 @@ class ChunkPrefetchFunctionRuntimeModule extends RuntimeModule {
16
16
  * @param {string} runtimeHandlers TODO
17
17
  */
18
18
  constructor(childType, runtimeFunction, runtimeHandlers) {
19
- super(`chunk ${childType} function`, 5);
19
+ super(`chunk ${childType} function`);
20
20
  this.childType = childType;
21
21
  this.runtimeFunction = runtimeFunction;
22
22
  this.runtimeHandlers = runtimeHandlers;
@@ -29,7 +29,7 @@ class ChunkPrefetchPreloadPlugin {
29
29
  const startupChildChunks = chunk.getChildIdsByOrders(chunkGraph);
30
30
  if (startupChildChunks.prefetch) {
31
31
  set.add(RuntimeGlobals.prefetchChunk);
32
- set.add(RuntimeGlobals.startup);
32
+ set.add(RuntimeGlobals.startupOnlyAfter);
33
33
  compilation.addRuntimeModule(
34
34
  chunk,
35
35
  new ChunkPrefetchStartupRuntimeModule(
@@ -17,7 +17,7 @@ class ChunkPrefetchStartupRuntimeModule extends RuntimeModule {
17
17
  * @param {(string|number)[]} startupChunks chunk ids to trigger after startup
18
18
  */
19
19
  constructor(childType, runtimeFunction, startupChunks) {
20
- super(`startup ${childType}`, 5);
20
+ super(`startup ${childType}`, RuntimeModule.STAGE_TRIGGER);
21
21
  this.childType = childType;
22
22
  this.runtimeFunction = runtimeFunction;
23
23
  this.startupChunks = startupChunks;
@@ -18,7 +18,7 @@ class ChunkPrefetchTriggerRuntimeModule extends RuntimeModule {
18
18
  * @param {boolean} afterChunkLoad true: start after chunk has been loaded, false: start after chunk loading has started
19
19
  */
20
20
  constructor(childType, runtimeFunction, chunkMap, afterChunkLoad) {
21
- super(`chunk ${childType} trigger`, 20);
21
+ super(`chunk ${childType} trigger`, RuntimeModule.STAGE_TRIGGER);
22
22
  this.childType = childType;
23
23
  this.runtimeFunction = runtimeFunction;
24
24
  this.chunkMap = chunkMap;
@@ -96,8 +96,10 @@ class RuleSetCompiler {
96
96
  }
97
97
  } else if (p in data) {
98
98
  const value = data[p];
99
- if (!condition.fn(value)) return false;
100
- continue;
99
+ if (value !== undefined) {
100
+ if (!condition.fn(value)) return false;
101
+ continue;
102
+ }
101
103
  }
102
104
  if (!condition.matchWhenEmpty) {
103
105
  return false;
@@ -12,7 +12,7 @@ const { getUndoPath } = require("../util/identifier");
12
12
 
13
13
  class AutoPublicPathRuntimeModule extends RuntimeModule {
14
14
  constructor() {
15
- super("publicPath", 5);
15
+ super("publicPath", RuntimeModule.STAGE_BASIC);
16
16
  }
17
17
 
18
18
  /**