webpack 5.37.0 → 5.37.1

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 (94) hide show
  1. package/README.md +5 -8
  2. package/lib/CacheFacade.js +3 -3
  3. package/lib/Chunk.js +2 -3
  4. package/lib/Compilation.js +43 -55
  5. package/lib/Compiler.js +4 -4
  6. package/lib/ConcatenationScope.js +2 -1
  7. package/lib/ContextModule.js +3 -3
  8. package/lib/ContextReplacementPlugin.js +4 -3
  9. package/lib/DefinePlugin.js +16 -12
  10. package/lib/EvalSourceMapDevToolPlugin.js +3 -1
  11. package/lib/FileSystemInfo.js +24 -30
  12. package/lib/FlagDependencyExportsPlugin.js +8 -7
  13. package/lib/FlagDependencyUsagePlugin.js +2 -4
  14. package/lib/HotModuleReplacementPlugin.js +20 -30
  15. package/lib/JavascriptMetaInfoPlugin.js +2 -1
  16. package/lib/MainTemplate.js +2 -3
  17. package/lib/ModuleFilenameHelpers.js +4 -2
  18. package/lib/ModuleGraphConnection.js +6 -2
  19. package/lib/ModuleInfoHeaderPlugin.js +2 -3
  20. package/lib/MultiCompiler.js +31 -27
  21. package/lib/NormalModule.js +22 -5
  22. package/lib/RecordIdsPlugin.js +5 -4
  23. package/lib/ResolverFactory.js +10 -7
  24. package/lib/SourceMapDevToolPlugin.js +13 -14
  25. package/lib/Template.js +4 -2
  26. package/lib/Watching.js +83 -46
  27. package/lib/asset/AssetGenerator.js +19 -23
  28. package/lib/buildChunkGraph.js +21 -21
  29. package/lib/cache/PackFileCacheStrategy.js +12 -9
  30. package/lib/config/defaults.js +12 -9
  31. package/lib/config/normalization.js +7 -7
  32. package/lib/debug/ProfilingPlugin.js +4 -3
  33. package/lib/dependencies/AMDRequireDependency.js +3 -3
  34. package/lib/dependencies/CommonJsExportRequireDependency.js +2 -3
  35. package/lib/dependencies/CommonJsExportsParserPlugin.js +3 -1
  36. package/lib/dependencies/CommonJsImportsParserPlugin.js +2 -4
  37. package/lib/dependencies/CommonJsPlugin.js +8 -7
  38. package/lib/dependencies/CommonJsRequireContextDependency.js +2 -1
  39. package/lib/dependencies/ContextDependencyHelpers.js +10 -8
  40. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +11 -13
  41. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +2 -4
  42. package/lib/dependencies/HarmonyImportSpecifierDependency.js +4 -11
  43. package/lib/dependencies/ImportDependency.js +3 -3
  44. package/lib/dependencies/ImportParserPlugin.js +2 -4
  45. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +2 -3
  46. package/lib/dependencies/RequireEnsureDependency.js +3 -3
  47. package/lib/dependencies/WorkerDependency.js +6 -6
  48. package/lib/dependencies/WorkerPlugin.js +18 -19
  49. package/lib/hmr/LazyCompilationPlugin.js +6 -4
  50. package/lib/ids/HashedModuleIdsPlugin.js +3 -3
  51. package/lib/ids/OccurrenceModuleIdsPlugin.js +2 -3
  52. package/lib/index.js +5 -3
  53. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -6
  54. package/lib/javascript/CommonJsChunkFormatPlugin.js +2 -3
  55. package/lib/javascript/JavascriptGenerator.js +3 -1
  56. package/lib/javascript/JavascriptModulesPlugin.js +15 -23
  57. package/lib/javascript/JavascriptParser.js +10 -8
  58. package/lib/library/AssignLibraryPlugin.js +4 -2
  59. package/lib/node/NodeWatchFileSystem.js +19 -4
  60. package/lib/optimize/AggressiveSplittingPlugin.js +5 -4
  61. package/lib/optimize/ConcatenatedModule.js +22 -27
  62. package/lib/optimize/FlagIncludedChunksPlugin.js +4 -6
  63. package/lib/optimize/InnerGraph.js +9 -11
  64. package/lib/optimize/InnerGraphPlugin.js +3 -1
  65. package/lib/optimize/ModuleConcatenationPlugin.js +7 -10
  66. package/lib/optimize/RealContentHashPlugin.js +14 -16
  67. package/lib/optimize/SideEffectsFlagPlugin.js +6 -5
  68. package/lib/optimize/SplitChunksPlugin.js +13 -15
  69. package/lib/runtime/EnsureChunkRuntimeModule.js +9 -8
  70. package/lib/runtime/LoadScriptRuntimeModule.js +2 -3
  71. package/lib/runtime/OnChunksLoadedRuntimeModule.js +38 -37
  72. package/lib/serialization/BinaryMiddleware.js +2 -3
  73. package/lib/serialization/FileMiddleware.js +3 -1
  74. package/lib/serialization/ObjectMiddleware.js +11 -7
  75. package/lib/stats/DefaultStatsFactoryPlugin.js +2 -3
  76. package/lib/stats/DefaultStatsPrinterPlugin.js +11 -9
  77. package/lib/stats/StatsFactory.js +2 -1
  78. package/lib/stats/StatsPrinter.js +3 -3
  79. package/lib/util/LazyBucketSortedSet.js +3 -3
  80. package/lib/util/cleverMerge.js +3 -1
  81. package/lib/util/comparators.js +13 -13
  82. package/lib/util/identifier.js +2 -1
  83. package/lib/validateSchema.js +5 -3
  84. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +4 -4
  85. package/lib/wasm-sync/WasmFinalizeExportsPlugin.js +5 -4
  86. package/lib/wasm-sync/WebAssemblyGenerator.js +89 -83
  87. package/lib/wasm-sync/WebAssemblyModulesPlugin.js +2 -1
  88. package/lib/wasm-sync/WebAssemblyParser.js +6 -5
  89. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -4
  90. package/lib/webpack.js +11 -7
  91. package/package.json +6 -3
  92. package/schemas/WebpackOptions.check.js +1 -1
  93. package/schemas/WebpackOptions.json +68 -60
  94. package/types.d.ts +89 -257
@@ -12,14 +12,16 @@ const ModuleFilenameHelpers = exports;
12
12
 
13
13
  // TODO webpack 6: consider removing these
14
14
  ModuleFilenameHelpers.ALL_LOADERS_RESOURCE = "[all-loaders][resource]";
15
- ModuleFilenameHelpers.REGEXP_ALL_LOADERS_RESOURCE = /\[all-?loaders\]\[resource\]/gi;
15
+ ModuleFilenameHelpers.REGEXP_ALL_LOADERS_RESOURCE =
16
+ /\[all-?loaders\]\[resource\]/gi;
16
17
  ModuleFilenameHelpers.LOADERS_RESOURCE = "[loaders][resource]";
17
18
  ModuleFilenameHelpers.REGEXP_LOADERS_RESOURCE = /\[loaders\]\[resource\]/gi;
18
19
  ModuleFilenameHelpers.RESOURCE = "[resource]";
19
20
  ModuleFilenameHelpers.REGEXP_RESOURCE = /\[resource\]/gi;
20
21
  ModuleFilenameHelpers.ABSOLUTE_RESOURCE_PATH = "[absolute-resource-path]";
21
22
  // cSpell:words olute
22
- ModuleFilenameHelpers.REGEXP_ABSOLUTE_RESOURCE_PATH = /\[abs(olute)?-?resource-?path\]/gi;
23
+ ModuleFilenameHelpers.REGEXP_ABSOLUTE_RESOURCE_PATH =
24
+ /\[abs(olute)?-?resource-?path\]/gi;
23
25
  ModuleFilenameHelpers.RESOURCE_PATH = "[resource-path]";
24
26
  ModuleFilenameHelpers.REGEXP_RESOURCE_PATH = /\[resource-?path\]/gi;
25
27
  ModuleFilenameHelpers.ALL_LOADERS = "[all-loaders]";
@@ -183,5 +183,9 @@ class ModuleGraphConnection {
183
183
 
184
184
  module.exports = ModuleGraphConnection;
185
185
  module.exports.addConnectionStates = addConnectionStates;
186
- module.exports.TRANSITIVE_ONLY = /** @type {typeof TRANSITIVE_ONLY} */ (TRANSITIVE_ONLY);
187
- module.exports.CIRCULAR_CONNECTION = /** @type {typeof CIRCULAR_CONNECTION} */ (CIRCULAR_CONNECTION);
186
+ module.exports.TRANSITIVE_ONLY = /** @type {typeof TRANSITIVE_ONLY} */ (
187
+ TRANSITIVE_ONLY
188
+ );
189
+ module.exports.CIRCULAR_CONNECTION = /** @type {typeof CIRCULAR_CONNECTION} */ (
190
+ CIRCULAR_CONNECTION
191
+ );
@@ -222,9 +222,8 @@ class ModuleInfoHeaderPlugin {
222
222
  )}`
223
223
  ) + "\n"
224
224
  );
225
- const optimizationBailout = moduleGraph.getOptimizationBailout(
226
- module
227
- );
225
+ const optimizationBailout =
226
+ moduleGraph.getOptimizationBailout(module);
228
227
  if (optimizationBailout) {
229
228
  for (const text of optimizationBailout) {
230
229
  let code;
@@ -318,16 +318,17 @@ module.exports = class MultiCompiler {
318
318
  * @returns {SetupResult[]} result of setup
319
319
  */
320
320
  _runGraph(setup, run, callback) {
321
- /** @typedef {{ compiler: Compiler, result: Stats, state: "pending" | "blocked" | "queued" | "running" | "running-outdated" | "done", children: Node[], parents: Node[] }} Node */
321
+ /** @typedef {{ compiler: Compiler, result: Stats, state: "pending" | "blocked" | "queued" | "starting" | "running" | "running-outdated" | "done", children: Node[], parents: Node[] }} Node */
322
322
 
323
323
  // State transitions for nodes:
324
324
  // -> blocked (initial)
325
- // blocked -> queued [add to queue] (when all parents done)
326
- // queued -> running [running++] (when processing the queue)
325
+ // blocked -> starting [running++] (when all parents done)
326
+ // queued -> starting [running++] (when processing the queue)
327
+ // starting -> running (when run has been called)
327
328
  // running -> done [running--] (when compilation is done)
328
329
  // done -> pending (when invalidated from file change)
329
- // pending -> blocked (when invalidated from aggregated changes)
330
- // done -> blocked (when invalidated, from parent invalidation)
330
+ // pending -> blocked [add to queue] (when invalidated from aggregated changes)
331
+ // done -> blocked [add to queue] (when invalidated, from parent invalidation)
331
332
  // running -> running-outdated (when invalidated, either from change or parent invalidation)
332
333
  // running-outdated -> blocked [running--] (when compilation is done)
333
334
 
@@ -351,6 +352,7 @@ module.exports = class MultiCompiler {
351
352
  parent.children.push(node);
352
353
  }
353
354
  }
355
+ /** @type {ArrayQueue<Node>} */
354
356
  const queue = new ArrayQueue();
355
357
  for (const node of nodes) {
356
358
  if (node.parents.length === 0) {
@@ -388,13 +390,13 @@ module.exports = class MultiCompiler {
388
390
  if (node.state === "running") {
389
391
  node.state = "done";
390
392
  for (const child of node.children) {
391
- checkUnblocked(child);
393
+ if (child.state === "blocked") queue.enqueue(child);
392
394
  }
393
395
  } else if (node.state === "running-outdated") {
394
396
  node.state = "blocked";
395
- checkUnblocked(node);
397
+ queue.enqueue(node);
396
398
  }
397
- process.nextTick(processQueue);
399
+ processQueue();
398
400
  };
399
401
  /**
400
402
  * @param {Node} node node
@@ -433,20 +435,9 @@ module.exports = class MultiCompiler {
433
435
  if (node.state === "pending") {
434
436
  node.state = "blocked";
435
437
  }
436
- checkUnblocked(node);
437
- processQueue();
438
- };
439
- /**
440
- * @param {Node} node node
441
- * @returns {void}
442
- */
443
- const checkUnblocked = node => {
444
- if (
445
- node.state === "blocked" &&
446
- node.parents.every(p => p.state === "done")
447
- ) {
448
- node.state = "queued";
438
+ if (node.state === "blocked") {
449
439
  queue.enqueue(node);
440
+ processQueue();
450
441
  }
451
442
  };
452
443
 
@@ -457,20 +448,33 @@ module.exports = class MultiCompiler {
457
448
  node.compiler,
458
449
  i,
459
450
  nodeDone.bind(null, node),
460
- () => node.state !== "done" && node.state !== "running",
451
+ () => node.state !== "starting" && node.state !== "running",
461
452
  () => nodeChange(node),
462
453
  () => nodeInvalid(node)
463
454
  )
464
455
  );
465
456
  });
457
+ let processing = true;
466
458
  const processQueue = () => {
459
+ if (processing) return;
460
+ processing = true;
461
+ process.nextTick(processQueueWorker);
462
+ };
463
+ const processQueueWorker = () => {
467
464
  while (running < parallelism && queue.length > 0 && !errored) {
468
465
  const node = queue.dequeue();
469
- if (node.state !== "queued") continue;
470
- running++;
471
- node.state = "running";
472
- run(node.compiler, nodeDone.bind(null, node));
466
+ if (
467
+ node.state === "queued" ||
468
+ (node.state === "blocked" &&
469
+ node.parents.every(p => p.state === "done"))
470
+ ) {
471
+ running++;
472
+ node.state = "starting";
473
+ run(node.compiler, nodeDone.bind(null, node));
474
+ node.state = "running";
475
+ }
473
476
  }
477
+ processing = false;
474
478
  if (
475
479
  !errored &&
476
480
  running === 0 &&
@@ -489,7 +493,7 @@ module.exports = class MultiCompiler {
489
493
  }
490
494
  }
491
495
  };
492
- processQueue();
496
+ processQueueWorker();
493
497
  return setupResults;
494
498
  }
495
499
 
@@ -276,6 +276,8 @@ class NormalModule extends Module {
276
276
  this._source = null;
277
277
  /** @private @type {Map<string, number> | undefined} **/
278
278
  this._sourceSizes = undefined;
279
+ /** @private @type {Set<string>} */
280
+ this._sourceTypes = undefined;
279
281
 
280
282
  // Cache
281
283
  this._lastSuccessfulBuildMeta = {};
@@ -347,12 +349,19 @@ class NormalModule extends Module {
347
349
  this.resource = m.resource;
348
350
  this.matchResource = m.matchResource;
349
351
  this.loaders = m.loaders;
352
+ this._sourceTypes = m._sourceTypes;
353
+ this._sourceSizes = m._sourceSizes;
350
354
  }
351
355
 
352
356
  /**
353
357
  * Assuming this module is in the cache. Remove internal references to allow freeing some memory.
354
358
  */
355
359
  cleanupForCache() {
360
+ // Make sure to cache types and sizes before cleanup
361
+ if (this._sourceTypes === undefined) this.getSourceTypes();
362
+ for (const type of this._sourceTypes) {
363
+ this.size(type);
364
+ }
356
365
  super.cleanupForCache();
357
366
  this.parser = undefined;
358
367
  this.parserOptions = undefined;
@@ -390,6 +399,7 @@ class NormalModule extends Module {
390
399
  this.type,
391
400
  this.generatorOptions
392
401
  );
402
+ // we assume the generator behaves identically and keep cached sourceTypes/Sizes
393
403
  }
394
404
 
395
405
  /**
@@ -765,7 +775,11 @@ class NormalModule extends Module {
765
775
  },
766
776
  (err, result) => {
767
777
  // Cleanup loaderContext to avoid leaking memory in ICs
768
- loaderContext._compilation = loaderContext._compiler = loaderContext._module = loaderContext.fs = undefined;
778
+ loaderContext._compilation =
779
+ loaderContext._compiler =
780
+ loaderContext._module =
781
+ loaderContext.fs =
782
+ undefined;
769
783
 
770
784
  if (!result) {
771
785
  return processResult(
@@ -869,6 +883,7 @@ class NormalModule extends Module {
869
883
  this._forceBuild = false;
870
884
  this._source = null;
871
885
  if (this._sourceSizes !== undefined) this._sourceSizes.clear();
886
+ this._sourceTypes = undefined;
872
887
  this._ast = null;
873
888
  this.error = null;
874
889
  this.clearWarningsAndErrors();
@@ -958,7 +973,8 @@ class NormalModule extends Module {
958
973
  checkDependencies(this.buildInfo.missingDependencies);
959
974
  checkDependencies(this.buildInfo.contextDependencies);
960
975
  if (nonAbsoluteDependencies !== undefined) {
961
- const InvalidDependenciesModuleWarning = getInvalidDependenciesModuleWarning();
976
+ const InvalidDependenciesModuleWarning =
977
+ getInvalidDependenciesModuleWarning();
962
978
  this.addWarning(
963
979
  new InvalidDependenciesModuleWarning(this, nonAbsoluteDependencies)
964
980
  );
@@ -1070,7 +1086,10 @@ class NormalModule extends Module {
1070
1086
  * @returns {Set<string>} types available (do not mutate)
1071
1087
  */
1072
1088
  getSourceTypes() {
1073
- return this.generator.getTypes(this);
1089
+ if (this._sourceTypes === undefined) {
1090
+ this._sourceTypes = this.generator.getTypes(this);
1091
+ }
1092
+ return this._sourceTypes;
1074
1093
  }
1075
1094
 
1076
1095
  /**
@@ -1259,7 +1278,6 @@ class NormalModule extends Module {
1259
1278
  const { write } = context;
1260
1279
  // deserialize
1261
1280
  write(this._source);
1262
- write(this._sourceSizes);
1263
1281
  write(this.error);
1264
1282
  write(this._lastSuccessfulBuildMeta);
1265
1283
  write(this._forceBuild);
@@ -1291,7 +1309,6 @@ class NormalModule extends Module {
1291
1309
  deserialize(context) {
1292
1310
  const { read } = context;
1293
1311
  this._source = read();
1294
- this._sourceSizes = read();
1295
1312
  this.error = read();
1296
1313
  this._lastSuccessfulBuildMeta = read();
1297
1314
  this._forceBuild = read();
@@ -48,10 +48,11 @@ class RecordIdsPlugin {
48
48
  apply(compiler) {
49
49
  const portableIds = this.options.portableIds;
50
50
 
51
- const makePathsRelative = identifierUtils.makePathsRelative.bindContextCache(
52
- compiler.context,
53
- compiler.root
54
- );
51
+ const makePathsRelative =
52
+ identifierUtils.makePathsRelative.bindContextCache(
53
+ compiler.context,
54
+ compiler.root
55
+ );
55
56
 
56
57
  /**
57
58
  * @param {Module} module the module
@@ -42,9 +42,9 @@ const convertToResolveOptions = resolveOptionsWithDepType => {
42
42
  ...remaining,
43
43
  plugins:
44
44
  plugins &&
45
- /** @type {ResolvePluginInstance[]} */ (plugins.filter(
46
- item => item !== "..."
47
- ))
45
+ /** @type {ResolvePluginInstance[]} */ (
46
+ plugins.filter(item => item !== "...")
47
+ )
48
48
  };
49
49
 
50
50
  if (!partialOptions.fileSystem) {
@@ -53,7 +53,10 @@ const convertToResolveOptions = resolveOptionsWithDepType => {
53
53
  );
54
54
  }
55
55
  // These weird types validate that we checked all non-optional properties
56
- const options = /** @type {Partial<ResolveOptions> & Pick<ResolveOptions, "fileSystem">} */ (partialOptions);
56
+ const options =
57
+ /** @type {Partial<ResolveOptions> & Pick<ResolveOptions, "fileSystem">} */ (
58
+ partialOptions
59
+ );
57
60
 
58
61
  return removeOperations(
59
62
  resolveByProperty(options, "byDependency", dependencyType)
@@ -124,9 +127,9 @@ module.exports = class ResolverFactory {
124
127
  const resolveOptions = convertToResolveOptions(
125
128
  this.hooks.resolveOptions.for(type).call(resolveOptionsWithDepType)
126
129
  );
127
- const resolver = /** @type {ResolverWithOptions} */ (Factory.createResolver(
128
- resolveOptions
129
- ));
130
+ const resolver = /** @type {ResolverWithOptions} */ (
131
+ Factory.createResolver(resolveOptions)
132
+ );
130
133
  if (!resolver) {
131
134
  throw new Error("No resolver created");
132
135
  }
@@ -430,19 +430,20 @@ class SourceMapDevToolPlugin {
430
430
  currentSourceMappingURLComment !== false &&
431
431
  /\.css($|\?)/i.test(file)
432
432
  ) {
433
- currentSourceMappingURLComment = currentSourceMappingURLComment.replace(
434
- /^\n\/\/(.*)$/,
435
- "\n/*$1*/"
436
- );
433
+ currentSourceMappingURLComment =
434
+ currentSourceMappingURLComment.replace(
435
+ /^\n\/\/(.*)$/,
436
+ "\n/*$1*/"
437
+ );
437
438
  }
438
439
  const sourceMapString = JSON.stringify(sourceMap);
439
440
  if (sourceMapFilename) {
440
441
  let filename = file;
441
442
  const sourceMapContentHash =
442
443
  usesContentHash &&
443
- /** @type {string} */ (createHash("md4")
444
- .update(sourceMapString)
445
- .digest("hex"));
444
+ /** @type {string} */ (
445
+ createHash("md4").update(sourceMapString).digest("hex")
446
+ );
446
447
  const pathParams = {
447
448
  chunk,
448
449
  filename: options.fileContext
@@ -454,13 +455,11 @@ class SourceMapDevToolPlugin {
454
455
  : filename,
455
456
  contentHash: sourceMapContentHash
456
457
  };
457
- const {
458
- path: sourceMapFile,
459
- info: sourceMapInfo
460
- } = compilation.getPathWithInfo(
461
- sourceMapFilename,
462
- pathParams
463
- );
458
+ const { path: sourceMapFile, info: sourceMapInfo } =
459
+ compilation.getPathWithInfo(
460
+ sourceMapFilename,
461
+ pathParams
462
+ );
464
463
  const sourceMapUrl = options.publicPath
465
464
  ? options.publicPath + sourceMapFile
466
465
  : relative(
package/lib/Template.js CHANGED
@@ -413,5 +413,7 @@ class Template {
413
413
  }
414
414
 
415
415
  module.exports = Template;
416
- module.exports.NUMBER_OF_IDENTIFIER_START_CHARS = NUMBER_OF_IDENTIFIER_START_CHARS;
417
- module.exports.NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS = NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS;
416
+ module.exports.NUMBER_OF_IDENTIFIER_START_CHARS =
417
+ NUMBER_OF_IDENTIFIER_START_CHARS;
418
+ module.exports.NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS =
419
+ NUMBER_OF_IDENTIFIER_CONTINUATION_CHARS;
package/lib/Watching.js CHANGED
@@ -57,16 +57,53 @@ class Watching {
57
57
  this._needRecords = true;
58
58
  this.watcher = undefined;
59
59
  this.pausedWatcher = undefined;
60
+ /** @type {Set<string>} */
61
+ this._collectedChangedFiles = undefined;
62
+ /** @type {Set<string>} */
63
+ this._collectedRemovedFiles = undefined;
60
64
  this._done = this._done.bind(this);
61
65
  process.nextTick(() => {
62
66
  if (this._initial) this._invalidate();
63
67
  });
64
68
  }
65
69
 
66
- _go() {
70
+ _mergeWithCollected(changedFiles, removedFiles) {
71
+ if (!changedFiles) return;
72
+ if (!this._collectedChangedFiles) {
73
+ this._collectedChangedFiles = new Set(changedFiles);
74
+ this._collectedRemovedFiles = new Set(removedFiles);
75
+ } else {
76
+ for (const file of changedFiles) {
77
+ this._collectedChangedFiles.add(file);
78
+ this._collectedRemovedFiles.delete(file);
79
+ }
80
+ for (const file of removedFiles) {
81
+ this._collectedChangedFiles.delete(file);
82
+ this._collectedRemovedFiles.add(file);
83
+ }
84
+ }
85
+ }
86
+
87
+ _go(fileTimeInfoEntries, contextTimeInfoEntries, changedFiles, removedFiles) {
67
88
  this._initial = false;
68
89
  this.startTime = Date.now();
69
90
  this.running = true;
91
+ if (this.watcher) {
92
+ this.pausedWatcher = this.watcher;
93
+ this.watcher.pause();
94
+ this.watcher = null;
95
+ }
96
+ this._mergeWithCollected(
97
+ changedFiles ||
98
+ (this.pausedWatcher &&
99
+ this.pausedWatcher.getAggregatedChanges &&
100
+ this.pausedWatcher.getAggregatedChanges()),
101
+ (this.compiler.removedFiles =
102
+ removedFiles ||
103
+ (this.pausedWatcher &&
104
+ this.pausedWatcher.getAggregatedRemovals &&
105
+ this.pausedWatcher.getAggregatedRemovals()))
106
+ );
70
107
  const run = () => {
71
108
  if (this.compiler.idle) {
72
109
  return this.compiler.cache.endIdle(err => {
@@ -83,6 +120,19 @@ class Watching {
83
120
  run();
84
121
  });
85
122
  }
123
+
124
+ this.compiler.modifiedFiles = this._collectedChangedFiles;
125
+ this._collectedChangedFiles = undefined;
126
+ this.compiler.removedFiles = this._collectedRemovedFiles;
127
+ this._collectedRemovedFiles = undefined;
128
+
129
+ this.compiler.fileTimestamps =
130
+ fileTimeInfoEntries ||
131
+ (this.pausedWatcher && this.pausedWatcher.getFileTimeInfoEntries());
132
+ this.compiler.contextTimestamps =
133
+ contextTimeInfoEntries ||
134
+ (this.pausedWatcher && this.pausedWatcher.getContextTimeInfoEntries());
135
+
86
136
  this.invalid = false;
87
137
  this._invalidReported = false;
88
138
  this.compiler.hooks.watchRun.callAsync(this.compiler, err => {
@@ -159,13 +209,16 @@ class Watching {
159
209
 
160
210
  let stats = null;
161
211
 
162
- const handleError = err => {
212
+ const handleError = (err, cbs) => {
163
213
  this.compiler.hooks.failed.call(err);
164
214
  this.compiler.cache.beginIdle();
165
215
  this.compiler.idle = true;
166
216
  this.handler(err, stats);
167
- for (const cb of this.callbacks) cb();
168
- this.callbacks.length = 0;
217
+ if (!cbs) {
218
+ cbs = this.callbacks;
219
+ this.callbacks = [];
220
+ }
221
+ for (const cb of cbs) cb(err);
169
222
  };
170
223
 
171
224
  if (
@@ -197,17 +250,19 @@ class Watching {
197
250
  }
198
251
  if (err) return handleError(err);
199
252
 
253
+ const cbs = this.callbacks;
254
+ this.callbacks = [];
200
255
  logger.time("done hook");
201
256
  this.compiler.hooks.done.callAsync(stats, err => {
202
257
  logger.timeEnd("done hook");
203
- if (err) return handleError(err);
258
+ if (err) return handleError(err, cbs);
204
259
  this.handler(null, stats);
205
260
  logger.time("storeBuildDependencies");
206
261
  this.compiler.cache.storeBuildDependencies(
207
262
  compilation.buildDependencies,
208
263
  err => {
209
264
  logger.timeEnd("storeBuildDependencies");
210
- if (err) return handleError(err);
265
+ if (err) return handleError(err, cbs);
211
266
  logger.time("beginIdle");
212
267
  this.compiler.cache.beginIdle();
213
268
  this.compiler.idle = true;
@@ -221,8 +276,7 @@ class Watching {
221
276
  );
222
277
  }
223
278
  });
224
- for (const cb of this.callbacks) cb();
225
- this.callbacks.length = 0;
279
+ for (const cb of cbs) cb(null);
226
280
  this.compiler.hooks.afterDone.call(stats);
227
281
  }
228
282
  );
@@ -250,8 +304,6 @@ class Watching {
250
304
  changedFiles,
251
305
  removedFiles
252
306
  ) => {
253
- this.pausedWatcher = this.watcher;
254
- this.watcher = null;
255
307
  if (err) {
256
308
  this.compiler.modifiedFiles = undefined;
257
309
  this.compiler.removedFiles = undefined;
@@ -259,16 +311,12 @@ class Watching {
259
311
  this.compiler.contextTimestamps = undefined;
260
312
  return this.handler(err);
261
313
  }
262
- this.compiler.fileTimestamps = fileTimeInfoEntries;
263
- this.compiler.contextTimestamps = contextTimeInfoEntries;
264
- this.compiler.removedFiles = removedFiles;
265
- this.compiler.modifiedFiles = changedFiles;
266
- if (this.watcher) {
267
- this.pausedWatcher = this.watcher;
268
- this.watcher.pause();
269
- this.watcher = null;
270
- }
271
- this._invalidate();
314
+ this._invalidate(
315
+ fileTimeInfoEntries,
316
+ contextTimeInfoEntries,
317
+ changedFiles,
318
+ removedFiles
319
+ );
272
320
  this._onChange();
273
321
  },
274
322
  (fileName, changeTime) => {
@@ -293,33 +341,30 @@ class Watching {
293
341
  this._invalidReported = true;
294
342
  this.compiler.hooks.invalid.call(null, Date.now());
295
343
  }
344
+ this._onChange();
296
345
  this._invalidate();
297
346
  }
298
347
 
299
- _invalidate() {
300
- if (this.suspended) return;
301
- if (this._isBlocked()) {
302
- this.blocked = true;
348
+ _invalidate(
349
+ fileTimeInfoEntries,
350
+ contextTimeInfoEntries,
351
+ changedFiles,
352
+ removedFiles
353
+ ) {
354
+ if (this.suspended || (this._isBlocked() && (this.blocked = true))) {
355
+ this._mergeWithCollected(changedFiles, removedFiles);
303
356
  return;
304
357
  }
305
- if (this.watcher) {
306
- this.compiler.modifiedFiles =
307
- this.watcher.getAggregatedChanges &&
308
- this.watcher.getAggregatedChanges();
309
- this.compiler.removedFiles =
310
- this.watcher.getAggregatedRemovals &&
311
- this.watcher.getAggregatedRemovals();
312
- this.compiler.fileTimestamps = this.watcher.getFileTimeInfoEntries();
313
- this.compiler.contextTimestamps = this.watcher.getContextTimeInfoEntries();
314
- this.pausedWatcher = this.watcher;
315
- this.watcher.pause();
316
- this.watcher = null;
317
- }
318
358
 
319
359
  if (this.running) {
320
360
  this.invalid = true;
321
361
  } else {
322
- this._go();
362
+ this._go(
363
+ fileTimeInfoEntries,
364
+ contextTimeInfoEntries,
365
+ changedFiles,
366
+ removedFiles
367
+ );
323
368
  }
324
369
  }
325
370
 
@@ -334,14 +379,6 @@ class Watching {
334
379
  }
335
380
  }
336
381
 
337
- _checkUnblocked() {
338
- if (this.blocked && !this._isBlocked()) {
339
- this.blocked = false;
340
- this._needWatcherInfo = true;
341
- this._invalidate();
342
- }
343
- }
344
-
345
382
  /**
346
383
  * @param {Callback<void>} callback signals when the watcher is closed
347
384
  * @returns {void}
@@ -170,9 +170,9 @@ class AssetGenerator extends Generator {
170
170
  hash.update(runtimeTemplate.outputOptions.hashSalt);
171
171
  }
172
172
  hash.update(originalSource.buffer());
173
- const fullHash = /** @type {string} */ (hash.digest(
174
- runtimeTemplate.outputOptions.hashDigest
175
- ));
173
+ const fullHash = /** @type {string} */ (
174
+ hash.digest(runtimeTemplate.outputOptions.hashDigest)
175
+ );
176
176
  const contentHash = fullHash.slice(
177
177
  0,
178
178
  runtimeTemplate.outputOptions.hashDigestLength
@@ -183,26 +183,9 @@ class AssetGenerator extends Generator {
183
183
  module.matchResource || module.resource,
184
184
  runtimeTemplate.compilation.compiler.root
185
185
  ).replace(/^\.\//, "");
186
- let {
187
- path: filename,
188
- info: assetInfo
189
- } = runtimeTemplate.compilation.getAssetPathWithInfo(
190
- assetModuleFilename,
191
- {
192
- module,
193
- runtime,
194
- filename: sourceFilename,
195
- chunkGraph,
196
- contentHash
197
- }
198
- );
199
- let publicPath;
200
- if (this.publicPath) {
201
- const {
202
- path,
203
- info
204
- } = runtimeTemplate.compilation.getAssetPathWithInfo(
205
- this.publicPath,
186
+ let { path: filename, info: assetInfo } =
187
+ runtimeTemplate.compilation.getAssetPathWithInfo(
188
+ assetModuleFilename,
206
189
  {
207
190
  module,
208
191
  runtime,
@@ -211,6 +194,19 @@ class AssetGenerator extends Generator {
211
194
  contentHash
212
195
  }
213
196
  );
197
+ let publicPath;
198
+ if (this.publicPath) {
199
+ const { path, info } =
200
+ runtimeTemplate.compilation.getAssetPathWithInfo(
201
+ this.publicPath,
202
+ {
203
+ module,
204
+ runtime,
205
+ filename: sourceFilename,
206
+ chunkGraph,
207
+ contentHash
208
+ }
209
+ );
214
210
  publicPath = JSON.stringify(path);
215
211
  assetInfo = mergeAssetInfo(assetInfo, info);
216
212
  } else {