webpack 5.69.0 → 5.71.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 (73) hide show
  1. package/hot/poll.js +1 -1
  2. package/hot/signal.js +1 -1
  3. package/lib/BannerPlugin.js +10 -4
  4. package/lib/Chunk.js +1 -1
  5. package/lib/ChunkGroup.js +1 -1
  6. package/lib/CleanPlugin.js +64 -18
  7. package/lib/Compilation.js +51 -25
  8. package/lib/Compiler.js +16 -3
  9. package/lib/ConstPlugin.js +2 -2
  10. package/lib/ContextModule.js +54 -22
  11. package/lib/ContextModuleFactory.js +13 -12
  12. package/lib/DelegatedModuleFactoryPlugin.js +1 -1
  13. package/lib/Dependency.js +7 -0
  14. package/lib/EntryOptionPlugin.js +1 -0
  15. package/lib/ErrorHelpers.js +2 -2
  16. package/lib/ExternalModuleFactoryPlugin.js +4 -4
  17. package/lib/FileSystemInfo.js +8 -0
  18. package/lib/Generator.js +1 -0
  19. package/lib/LoaderOptionsPlugin.js +1 -1
  20. package/lib/Module.js +2 -0
  21. package/lib/ModuleFilenameHelpers.js +3 -3
  22. package/lib/ModuleHashingError.js +29 -0
  23. package/lib/NodeStuffPlugin.js +10 -0
  24. package/lib/NormalModule.js +23 -18
  25. package/lib/NormalModuleFactory.js +17 -10
  26. package/lib/ProgressPlugin.js +3 -4
  27. package/lib/RuntimePlugin.js +18 -0
  28. package/lib/RuntimeTemplate.js +1 -0
  29. package/lib/WebpackOptionsApply.js +2 -0
  30. package/lib/asset/AssetGenerator.js +119 -31
  31. package/lib/cache/ResolverCachePlugin.js +15 -6
  32. package/lib/config/browserslistTargetHandler.js +3 -5
  33. package/lib/config/defaults.js +9 -1
  34. package/lib/config/normalization.js +1 -0
  35. package/lib/dependencies/CommonJsExportsParserPlugin.js +1 -2
  36. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  37. package/lib/dependencies/ContextElementDependency.js +33 -1
  38. package/lib/dependencies/HarmonyAcceptImportDependency.js +5 -3
  39. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +95 -0
  40. package/lib/dependencies/HarmonyExportInitFragment.js +4 -1
  41. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +127 -43
  42. package/lib/dependencies/HarmonyImportSpecifierDependency.js +22 -8
  43. package/lib/dependencies/HarmonyModulesPlugin.js +10 -0
  44. package/lib/dependencies/ImportContextDependency.js +0 -2
  45. package/lib/dependencies/ImportMetaContextDependency.js +35 -0
  46. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +252 -0
  47. package/lib/dependencies/ImportMetaContextPlugin.js +59 -0
  48. package/lib/dependencies/LoaderPlugin.js +2 -0
  49. package/lib/dependencies/RequireContextDependency.js +0 -16
  50. package/lib/esm/ModuleChunkLoadingPlugin.js +3 -1
  51. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +24 -8
  52. package/lib/hmr/HotModuleReplacement.runtime.js +29 -14
  53. package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +4 -3
  54. package/lib/ids/HashedModuleIdsPlugin.js +2 -2
  55. package/lib/ids/IdHelpers.js +1 -1
  56. package/lib/javascript/BasicEvaluatedExpression.js +5 -2
  57. package/lib/javascript/JavascriptParser.js +66 -40
  58. package/lib/library/UmdLibraryPlugin.js +5 -3
  59. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -7
  60. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -7
  61. package/lib/runtime/BaseUriRuntimeModule.js +31 -0
  62. package/lib/schemes/HttpUriPlugin.js +44 -3
  63. package/lib/stats/DefaultStatsFactoryPlugin.js +1 -1
  64. package/lib/util/internalSerializables.js +4 -0
  65. package/lib/web/JsonpChunkLoadingRuntimeModule.js +17 -6
  66. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +30 -20
  67. package/module.d.ts +15 -0
  68. package/package.json +2 -2
  69. package/schemas/WebpackOptions.check.js +1 -1
  70. package/schemas/WebpackOptions.json +17 -1
  71. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  72. package/schemas/plugins/schemes/HttpUriPlugin.json +4 -0
  73. package/types.d.ts +179 -83
package/hot/poll.js CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
  /*globals __resourceQuery */
6
6
  if (module.hot) {
7
- var hotPollInterval = +__resourceQuery.substr(1) || 10 * 60 * 1000;
7
+ var hotPollInterval = +__resourceQuery.slice(1) || 10 * 60 * 1000;
8
8
  var log = require("./log");
9
9
 
10
10
  var checkForUpdate = function checkForUpdate(fromUpdate) {
package/hot/signal.js CHANGED
@@ -45,7 +45,7 @@ if (module.hot) {
45
45
  });
46
46
  };
47
47
 
48
- process.on(__resourceQuery.substr(1) || "SIGUSR2", function () {
48
+ process.on(__resourceQuery.slice(1) || "SIGUSR2", function () {
49
49
  if (module.hot.status() !== "idle") {
50
50
  log(
51
51
  "warning",
@@ -77,6 +77,7 @@ class BannerPlugin {
77
77
  undefined,
78
78
  options
79
79
  );
80
+ const cache = new WeakMap();
80
81
 
81
82
  compiler.hooks.compilation.tap("BannerPlugin", compilation => {
82
83
  compilation.hooks.processAssets.tap(
@@ -102,10 +103,15 @@ class BannerPlugin {
102
103
 
103
104
  const comment = compilation.getPath(banner, data);
104
105
 
105
- compilation.updateAsset(
106
- file,
107
- old => new ConcatSource(comment, "\n", old)
108
- );
106
+ compilation.updateAsset(file, old => {
107
+ let cached = cache.get(old);
108
+ if (!cached || cached.comment !== comment) {
109
+ const source = new ConcatSource(comment, "\n", old);
110
+ cache.set(old, { source, comment });
111
+ return source;
112
+ }
113
+ return cached.source;
114
+ });
109
115
  }
110
116
  }
111
117
  }
package/lib/Chunk.js CHANGED
@@ -690,7 +690,7 @@ class Chunk {
690
690
  for (const childGroup of group.childrenIterable) {
691
691
  for (const key of Object.keys(childGroup.options)) {
692
692
  if (key.endsWith("Order")) {
693
- const name = key.substr(0, key.length - "Order".length);
693
+ const name = key.slice(0, key.length - "Order".length);
694
694
  let list = lists.get(name);
695
695
  if (list === undefined) {
696
696
  list = [];
package/lib/ChunkGroup.js CHANGED
@@ -486,7 +486,7 @@ class ChunkGroup {
486
486
  for (const childGroup of this._children) {
487
487
  for (const key of Object.keys(childGroup.options)) {
488
488
  if (key.endsWith("Order")) {
489
- const name = key.substr(0, key.length - "Order".length);
489
+ const name = key.slice(0, key.length - "Order".length);
490
490
  let list = lists.get(name);
491
491
  if (list === undefined) {
492
492
  lists.set(name, (list = []));
@@ -19,6 +19,7 @@ const processAsyncTree = require("./util/processAsyncTree");
19
19
  /** @typedef {import("./util/fs").StatsCallback} StatsCallback */
20
20
 
21
21
  /** @typedef {(function(string):boolean)|RegExp} IgnoreItem */
22
+ /** @typedef {Map<string, number>} Assets */
22
23
  /** @typedef {function(IgnoreItem): void} AddToIgnoreCallback */
23
24
 
24
25
  /**
@@ -40,18 +41,32 @@ const validate = createSchemaValidation(
40
41
  baseDataPath: "options"
41
42
  }
42
43
  );
44
+ const _10sec = 10 * 1000;
45
+
46
+ /**
47
+ * marge assets map 2 into map 1
48
+ * @param {Assets} as1 assets
49
+ * @param {Assets} as2 assets
50
+ * @returns {void}
51
+ */
52
+ const mergeAssets = (as1, as2) => {
53
+ for (const [key, value1] of as2) {
54
+ const value2 = as1.get(key);
55
+ if (!value2 || value1 > value2) as1.set(key, value1);
56
+ }
57
+ };
43
58
 
44
59
  /**
45
60
  * @param {OutputFileSystem} fs filesystem
46
61
  * @param {string} outputPath output path
47
- * @param {Set<string>} currentAssets filename of the current assets (must not start with .. or ., must only use / as path separator)
62
+ * @param {Map<string, number>} currentAssets filename of the current assets (must not start with .. or ., must only use / as path separator)
48
63
  * @param {function((Error | null)=, Set<string>=): void} callback returns the filenames of the assets that shouldn't be there
49
64
  * @returns {void}
50
65
  */
51
66
  const getDiffToFs = (fs, outputPath, currentAssets, callback) => {
52
67
  const directories = new Set();
53
68
  // get directories of assets
54
- for (const asset of currentAssets) {
69
+ for (const [asset] of currentAssets) {
55
70
  directories.add(asset.replace(/(^|\/)[^/]*$/, ""));
56
71
  }
57
72
  // and all parent directories
@@ -91,13 +106,15 @@ const getDiffToFs = (fs, outputPath, currentAssets, callback) => {
91
106
  };
92
107
 
93
108
  /**
94
- * @param {Set<string>} currentAssets assets list
95
- * @param {Set<string>} oldAssets old assets list
109
+ * @param {Assets} currentAssets assets list
110
+ * @param {Assets} oldAssets old assets list
96
111
  * @returns {Set<string>} diff
97
112
  */
98
113
  const getDiffToOldAssets = (currentAssets, oldAssets) => {
99
114
  const diff = new Set();
100
- for (const asset of oldAssets) {
115
+ const now = Date.now();
116
+ for (const [asset, ts] of oldAssets) {
117
+ if (ts >= now) continue;
101
118
  if (!currentAssets.has(asset)) diff.add(asset);
102
119
  }
103
120
  return diff;
@@ -124,7 +141,7 @@ const doStat = (fs, filename, callback) => {
124
141
  * @param {Logger} logger logger
125
142
  * @param {Set<string>} diff filenames of the assets that shouldn't be there
126
143
  * @param {function(string): boolean} isKept check if the entry is ignored
127
- * @param {function(Error=): void} callback callback
144
+ * @param {function(Error=, Assets=): void} callback callback
128
145
  * @returns {void}
129
146
  */
130
147
  const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
@@ -137,11 +154,13 @@ const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
137
154
  };
138
155
  /** @typedef {{ type: "check" | "unlink" | "rmdir", filename: string, parent: { remaining: number, job: Job } | undefined }} Job */
139
156
  /** @type {Job[]} */
140
- const jobs = Array.from(diff, filename => ({
157
+ const jobs = Array.from(diff.keys(), filename => ({
141
158
  type: "check",
142
159
  filename,
143
160
  parent: undefined
144
161
  }));
162
+ /** @type {Assets} */
163
+ const keptAssets = new Map();
145
164
  processAsyncTree(
146
165
  jobs,
147
166
  10,
@@ -161,6 +180,7 @@ const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
161
180
  switch (type) {
162
181
  case "check":
163
182
  if (isKept(filename)) {
183
+ keptAssets.set(filename, 0);
164
184
  // do not decrement parent entry as we don't want to delete the parent
165
185
  log(`${filename} will be kept`);
166
186
  return process.nextTick(callback);
@@ -247,7 +267,10 @@ const applyDiff = (fs, outputPath, dry, logger, diff, isKept, callback) => {
247
267
  break;
248
268
  }
249
269
  },
250
- callback
270
+ err => {
271
+ if (err) return callback(err);
272
+ callback(undefined, keptAssets);
273
+ }
251
274
  );
252
275
  };
253
276
 
@@ -302,6 +325,7 @@ class CleanPlugin {
302
325
  // We assume that no external modification happens while the compiler is active
303
326
  // So we can store the old assets and only diff to them to avoid fs access on
304
327
  // incremental builds
328
+ /** @type {undefined|Assets} */
305
329
  let oldAssets;
306
330
 
307
331
  compiler.hooks.emit.tapAsync(
@@ -322,7 +346,9 @@ class CleanPlugin {
322
346
  );
323
347
  }
324
348
 
325
- const currentAssets = new Set();
349
+ /** @type {Assets} */
350
+ const currentAssets = new Map();
351
+ const now = Date.now();
326
352
  for (const asset of Object.keys(compilation.assets)) {
327
353
  if (/^[A-Za-z]:\\|^\/|^\\\\/.test(asset)) continue;
328
354
  let normalizedAsset;
@@ -335,7 +361,12 @@ class CleanPlugin {
335
361
  );
336
362
  } while (newNormalizedAsset !== normalizedAsset);
337
363
  if (normalizedAsset.startsWith("../")) continue;
338
- currentAssets.add(normalizedAsset);
364
+ const assetInfo = compilation.assetsInfo.get(asset);
365
+ if (assetInfo && assetInfo.hotModuleReplacement) {
366
+ currentAssets.set(normalizedAsset, now + _10sec);
367
+ } else {
368
+ currentAssets.set(normalizedAsset, 0);
369
+ }
339
370
  }
340
371
 
341
372
  const outputPath = compilation.getPath(compiler.outputPath, {});
@@ -346,19 +377,34 @@ class CleanPlugin {
346
377
  return keepFn(path);
347
378
  };
348
379
 
380
+ /**
381
+ * @param {Error=} err err
382
+ * @param {Set<string>=} diff diff
383
+ */
349
384
  const diffCallback = (err, diff) => {
350
385
  if (err) {
351
386
  oldAssets = undefined;
352
- return callback(err);
387
+ callback(err);
388
+ return;
353
389
  }
354
- applyDiff(fs, outputPath, dry, logger, diff, isKept, err => {
355
- if (err) {
356
- oldAssets = undefined;
357
- } else {
358
- oldAssets = currentAssets;
390
+ applyDiff(
391
+ fs,
392
+ outputPath,
393
+ dry,
394
+ logger,
395
+ diff,
396
+ isKept,
397
+ (err, keptAssets) => {
398
+ if (err) {
399
+ oldAssets = undefined;
400
+ } else {
401
+ if (oldAssets) mergeAssets(currentAssets, oldAssets);
402
+ oldAssets = currentAssets;
403
+ if (keptAssets) mergeAssets(oldAssets, keptAssets);
404
+ }
405
+ callback(err);
359
406
  }
360
- callback(err);
361
- });
407
+ );
362
408
  };
363
409
 
364
410
  if (oldAssets) {
@@ -43,6 +43,7 @@ const Module = require("./Module");
43
43
  const ModuleDependencyError = require("./ModuleDependencyError");
44
44
  const ModuleDependencyWarning = require("./ModuleDependencyWarning");
45
45
  const ModuleGraph = require("./ModuleGraph");
46
+ const ModuleHashingError = require("./ModuleHashingError");
46
47
  const ModuleNotFoundError = require("./ModuleNotFoundError");
47
48
  const ModuleProfile = require("./ModuleProfile");
48
49
  const ModuleRestoreError = require("./ModuleRestoreError");
@@ -1435,7 +1436,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1435
1436
  * @returns {void}
1436
1437
  */
1437
1438
  _processModuleDependencies(module, callback) {
1438
- /** @type {Array<{factory: ModuleFactory, dependencies: Dependency[], originModule: Module|null}>} */
1439
+ /** @type {Array<{factory: ModuleFactory, dependencies: Dependency[], context: string|undefined, originModule: Module|null}>} */
1439
1440
  const sortedDependencies = [];
1440
1441
 
1441
1442
  /** @type {DependenciesBlock} */
@@ -1667,6 +1668,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1667
1668
  sortedDependencies.push({
1668
1669
  factory: factoryCacheKey2,
1669
1670
  dependencies: list,
1671
+ context: dep.getContext(),
1670
1672
  originModule: module
1671
1673
  });
1672
1674
  }
@@ -3327,7 +3329,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3327
3329
  dependencyTemplates,
3328
3330
  runtimeTemplate,
3329
3331
  runtime,
3330
- codeGenerationResults: results
3332
+ codeGenerationResults: results,
3333
+ compilation: this
3331
3334
  });
3332
3335
  } catch (err) {
3333
3336
  errors.push(new CodeGenerationError(module, err));
@@ -3883,6 +3886,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3883
3886
  let statModulesFromCache = 0;
3884
3887
  const { chunkGraph, runtimeTemplate, moduleMemCaches2 } = this;
3885
3888
  const { hashFunction, hashDigest, hashDigestLength } = this.outputOptions;
3889
+ const errors = [];
3886
3890
  for (const module of this.modules) {
3887
3891
  const memCache = moduleMemCaches2 && moduleMemCaches2.get(module);
3888
3892
  for (const runtime of chunkGraph.getModuleRuntimes(module)) {
@@ -3893,7 +3897,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3893
3897
  module,
3894
3898
  runtime,
3895
3899
  digest,
3896
- digest.substr(0, hashDigestLength)
3900
+ digest.slice(0, hashDigestLength)
3897
3901
  );
3898
3902
  statModulesFromCache++;
3899
3903
  continue;
@@ -3907,13 +3911,20 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3907
3911
  hashFunction,
3908
3912
  runtimeTemplate,
3909
3913
  hashDigest,
3910
- hashDigestLength
3914
+ hashDigestLength,
3915
+ errors
3911
3916
  );
3912
3917
  if (memCache) {
3913
3918
  memCache.set(`moduleHash-${getRuntimeKey(runtime)}`, digest);
3914
3919
  }
3915
3920
  }
3916
3921
  }
3922
+ if (errors.length > 0) {
3923
+ errors.sort(compareSelect(err => err.module, compareModulesByIdentifier));
3924
+ for (const error of errors) {
3925
+ this.errors.push(error);
3926
+ }
3927
+ }
3917
3928
  this.logger.log(
3918
3929
  `${statModulesHashed} modules hashed, ${statModulesFromCache} from cache (${
3919
3930
  Math.round(
@@ -3930,22 +3941,27 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
3930
3941
  hashFunction,
3931
3942
  runtimeTemplate,
3932
3943
  hashDigest,
3933
- hashDigestLength
3944
+ hashDigestLength,
3945
+ errors
3934
3946
  ) {
3935
- const moduleHash = createHash(hashFunction);
3936
- module.updateHash(moduleHash, {
3937
- chunkGraph,
3938
- runtime,
3939
- runtimeTemplate
3940
- });
3941
- const moduleHashDigest = /** @type {string} */ (
3942
- moduleHash.digest(hashDigest)
3943
- );
3947
+ let moduleHashDigest;
3948
+ try {
3949
+ const moduleHash = createHash(hashFunction);
3950
+ module.updateHash(moduleHash, {
3951
+ chunkGraph,
3952
+ runtime,
3953
+ runtimeTemplate
3954
+ });
3955
+ moduleHashDigest = /** @type {string} */ (moduleHash.digest(hashDigest));
3956
+ } catch (err) {
3957
+ errors.push(new ModuleHashingError(module, err));
3958
+ moduleHashDigest = "XXXXXX";
3959
+ }
3944
3960
  chunkGraph.setModuleHashes(
3945
3961
  module,
3946
3962
  runtime,
3947
3963
  moduleHashDigest,
3948
- moduleHashDigest.substr(0, hashDigestLength)
3964
+ moduleHashDigest.slice(0, hashDigestLength)
3949
3965
  );
3950
3966
  return moduleHashDigest;
3951
3967
  }
@@ -4091,6 +4107,7 @@ This prevents using hashes of each other and should be avoided.`);
4091
4107
  const codeGenerationJobs = [];
4092
4108
  /** @type {Map<string, Map<Module, {module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}>>} */
4093
4109
  const codeGenerationJobsMap = new Map();
4110
+ const errors = [];
4094
4111
 
4095
4112
  const processChunk = chunk => {
4096
4113
  // Last minute module hash generation for modules that depend on chunk hashes
@@ -4105,7 +4122,8 @@ This prevents using hashes of each other and should be avoided.`);
4105
4122
  hashFunction,
4106
4123
  runtimeTemplate,
4107
4124
  hashDigest,
4108
- hashDigestLength
4125
+ hashDigestLength,
4126
+ errors
4109
4127
  );
4110
4128
  let hashMap = codeGenerationJobsMap.get(hash);
4111
4129
  if (hashMap) {
@@ -4129,9 +4147,9 @@ This prevents using hashes of each other and should be avoided.`);
4129
4147
  }
4130
4148
  }
4131
4149
  this.logger.timeAggregate("hashing: hash runtime modules");
4132
- this.logger.time("hashing: hash chunks");
4133
- const chunkHash = createHash(hashFunction);
4134
4150
  try {
4151
+ this.logger.time("hashing: hash chunks");
4152
+ const chunkHash = createHash(hashFunction);
4135
4153
  if (outputOptions.hashSalt) {
4136
4154
  chunkHash.update(outputOptions.hashSalt);
4137
4155
  }
@@ -4147,7 +4165,7 @@ This prevents using hashes of each other and should be avoided.`);
4147
4165
  );
4148
4166
  hash.update(chunkHashDigest);
4149
4167
  chunk.hash = chunkHashDigest;
4150
- chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
4168
+ chunk.renderedHash = chunk.hash.slice(0, hashDigestLength);
4151
4169
  const fullHashModules =
4152
4170
  chunkGraph.getChunkFullHashModulesIterable(chunk);
4153
4171
  if (fullHashModules) {
@@ -4162,13 +4180,19 @@ This prevents using hashes of each other and should be avoided.`);
4162
4180
  };
4163
4181
  otherChunks.forEach(processChunk);
4164
4182
  for (const chunk of runtimeChunks) processChunk(chunk);
4183
+ if (errors.length > 0) {
4184
+ errors.sort(compareSelect(err => err.module, compareModulesByIdentifier));
4185
+ for (const error of errors) {
4186
+ this.errors.push(error);
4187
+ }
4188
+ }
4165
4189
 
4166
4190
  this.logger.timeAggregateEnd("hashing: hash runtime modules");
4167
4191
  this.logger.timeAggregateEnd("hashing: hash chunks");
4168
4192
  this.logger.time("hashing: hash digest");
4169
4193
  this.hooks.fullHash.call(hash);
4170
4194
  this.fullHash = /** @type {string} */ (hash.digest(hashDigest));
4171
- this.hash = this.fullHash.substr(0, hashDigestLength);
4195
+ this.hash = this.fullHash.slice(0, hashDigestLength);
4172
4196
  this.logger.timeEnd("hashing: hash digest");
4173
4197
 
4174
4198
  this.logger.time("hashing: process full hash modules");
@@ -4188,7 +4212,7 @@ This prevents using hashes of each other and should be avoided.`);
4188
4212
  module,
4189
4213
  chunk.runtime,
4190
4214
  moduleHashDigest,
4191
- moduleHashDigest.substr(0, hashDigestLength)
4215
+ moduleHashDigest.slice(0, hashDigestLength)
4192
4216
  );
4193
4217
  codeGenerationJobsMap.get(oldHash).get(module).hash = moduleHashDigest;
4194
4218
  }
@@ -4199,7 +4223,7 @@ This prevents using hashes of each other and should be avoided.`);
4199
4223
  chunkHash.digest(hashDigest)
4200
4224
  );
4201
4225
  chunk.hash = chunkHashDigest;
4202
- chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
4226
+ chunk.renderedHash = chunk.hash.slice(0, hashDigestLength);
4203
4227
  this.hooks.contentHash.call(chunk);
4204
4228
  }
4205
4229
  this.logger.timeEnd("hashing: process full hash modules");
@@ -4801,6 +4825,9 @@ This prevents using hashes of each other and should be avoided.`);
4801
4825
  chunkGraph.connectChunkAndModule(chunk, module);
4802
4826
  }
4803
4827
 
4828
+ /** @type {WebpackError[]} */
4829
+ const errors = [];
4830
+
4804
4831
  // Hash modules
4805
4832
  for (const module of modules) {
4806
4833
  this._createModuleHash(
@@ -4810,15 +4837,14 @@ This prevents using hashes of each other and should be avoided.`);
4810
4837
  hashFunction,
4811
4838
  runtimeTemplate,
4812
4839
  hashDigest,
4813
- hashDigestLength
4840
+ hashDigestLength,
4841
+ errors
4814
4842
  );
4815
4843
  }
4816
4844
 
4817
4845
  const codeGenerationResults = new CodeGenerationResults(
4818
4846
  this.outputOptions.hashFunction
4819
4847
  );
4820
- /** @type {WebpackError[]} */
4821
- const errors = [];
4822
4848
  /**
4823
4849
  * @param {Module} module the module
4824
4850
  * @param {Callback} callback callback
package/lib/Compiler.js CHANGED
@@ -545,8 +545,21 @@ class Compiler {
545
545
  */
546
546
  runAsChild(callback) {
547
547
  const startTime = Date.now();
548
+
549
+ const finalCallback = (err, entries, compilation) => {
550
+ try {
551
+ callback(err, entries, compilation);
552
+ } catch (e) {
553
+ const err = new WebpackError(
554
+ `compiler.runAsChild callback error: ${e}`
555
+ );
556
+ err.details = e.stack;
557
+ this.parentCompilation.errors.push(err);
558
+ }
559
+ };
560
+
548
561
  this.compile((err, compilation) => {
549
- if (err) return callback(err);
562
+ if (err) return finalCallback(err);
550
563
 
551
564
  this.parentCompilation.children.push(compilation);
552
565
  for (const { name, source, info } of compilation.getAssets()) {
@@ -561,7 +574,7 @@ class Compiler {
561
574
  compilation.startTime = startTime;
562
575
  compilation.endTime = Date.now();
563
576
 
564
- return callback(null, entries, compilation);
577
+ return finalCallback(null, entries, compilation);
565
578
  });
566
579
  }
567
580
 
@@ -596,7 +609,7 @@ class Compiler {
596
609
  let immutable = info.immutable;
597
610
  const queryStringIdx = targetFile.indexOf("?");
598
611
  if (queryStringIdx >= 0) {
599
- targetFile = targetFile.substr(0, queryStringIdx);
612
+ targetFile = targetFile.slice(0, queryStringIdx);
600
613
  // We may remove the hash, which is in the query string
601
614
  // So we recheck if the file is immutable
602
615
  // This doesn't cover all cases, but immutable is only a performance optimization anyway
@@ -324,7 +324,7 @@ class ConstPlugin {
324
324
  }
325
325
  } else if (expression.operator === "??") {
326
326
  const param = parser.evaluateExpression(expression.left);
327
- const keepRight = param && param.asNullish();
327
+ const keepRight = param.asNullish();
328
328
  if (typeof keepRight === "boolean") {
329
329
  // ------------------------------------------
330
330
  //
@@ -407,7 +407,7 @@ class ConstPlugin {
407
407
  const expression = optionalExpressionsStack.pop();
408
408
  const evaluated = parser.evaluateExpression(expression);
409
409
 
410
- if (evaluated && evaluated.asNullish()) {
410
+ if (evaluated.asNullish()) {
411
411
  // ------------------------------------------
412
412
  //
413
413
  // Given the following code:
@@ -19,7 +19,11 @@ const {
19
19
  keepOriginalOrder,
20
20
  compareModulesById
21
21
  } = require("./util/comparators");
22
- const { contextify, parseResource } = require("./util/identifier");
22
+ const {
23
+ contextify,
24
+ parseResource,
25
+ makePathsRelative
26
+ } = require("./util/identifier");
23
27
  const makeSerializable = require("./util/makeSerializable");
24
28
 
25
29
  /** @typedef {import("webpack-sources").Source} Source */
@@ -61,7 +65,7 @@ const makeSerializable = require("./util/makeSerializable");
61
65
 
62
66
  /**
63
67
  * @typedef {Object} ContextModuleOptionsExtras
64
- * @property {string|string[]} resource
68
+ * @property {false|string|string[]} resource
65
69
  * @property {string=} resourceQuery
66
70
  * @property {string=} resourceFragment
67
71
  * @property {TODO} resolveOptions
@@ -170,8 +174,9 @@ class ContextModule extends Module {
170
174
  _createIdentifier() {
171
175
  let identifier =
172
176
  this.context ||
173
- (typeof this.options.resource === "string"
174
- ? this.options.resource
177
+ (typeof this.options.resource === "string" ||
178
+ this.options.resource === false
179
+ ? `${this.options.resource}`
175
180
  : this.options.resource.join("|"));
176
181
  if (this.options.resourceQuery) {
177
182
  identifier += `|${this.options.resourceQuery}`;
@@ -240,8 +245,11 @@ class ContextModule extends Module {
240
245
  let identifier;
241
246
  if (this.context) {
242
247
  identifier = requestShortener.shorten(this.context) + "/";
243
- } else if (typeof this.options.resource === "string") {
244
- identifier = requestShortener.shorten(this.options.resource) + "/";
248
+ } else if (
249
+ typeof this.options.resource === "string" ||
250
+ this.options.resource === false
251
+ ) {
252
+ identifier = requestShortener.shorten(`${this.options.resource}`) + "/";
245
253
  } else {
246
254
  identifier = this.options.resource
247
255
  .map(r => requestShortener.shorten(r) + "/")
@@ -310,14 +318,14 @@ class ContextModule extends Module {
310
318
  this.options.resource,
311
319
  options.associatedObjectForCache
312
320
  );
321
+ } else if (this.options.resource === false) {
322
+ identifier = "false";
313
323
  } else {
314
- const arr = [];
315
- for (const res of this.options.resource) {
316
- arr.push(
324
+ identifier = this.options.resource
325
+ .map(res =>
317
326
  contextify(options.context, res, options.associatedObjectForCache)
318
- );
319
- }
320
- identifier = arr.join(" ");
327
+ )
328
+ .join(" ");
321
329
  }
322
330
 
323
331
  if (this.layer) identifier = `(${this.layer})/${identifier}`;
@@ -368,8 +376,9 @@ class ContextModule extends Module {
368
376
  // build if enforced
369
377
  if (this._forceBuild) return callback(null, true);
370
378
 
371
- // always build when we have no snapshot
372
- if (!this.buildInfo.snapshot) return callback(null, true);
379
+ // always build when we have no snapshot and context
380
+ if (!this.buildInfo.snapshot)
381
+ return callback(null, Boolean(this.context || this.options.resource));
373
382
 
374
383
  fileSystemInfo.checkSnapshotValid(this.buildInfo.snapshot, (err, valid) => {
375
384
  callback(err, !valid);
@@ -484,6 +493,8 @@ class ContextModule extends Module {
484
493
  );
485
494
  return;
486
495
  }
496
+ if (!this.context && !this.options.resource) return callback();
497
+
487
498
  compilation.fileSystemInfo.createSnapshot(
488
499
  startTime,
489
500
  null,
@@ -491,7 +502,7 @@ class ContextModule extends Module {
491
502
  ? [this.context]
492
503
  : typeof this.options.resource === "string"
493
504
  ? [this.options.resource]
494
- : this.options.resource,
505
+ : /** @type {string[]} */ (this.options.resource),
495
506
  null,
496
507
  SNAPSHOT_OPTIONS,
497
508
  (err, snapshot) => {
@@ -519,6 +530,8 @@ class ContextModule extends Module {
519
530
  contextDependencies.add(this.context);
520
531
  } else if (typeof this.options.resource === "string") {
521
532
  contextDependencies.add(this.options.resource);
533
+ } else if (this.options.resource === false) {
534
+ return;
522
535
  } else {
523
536
  for (const res of this.options.resource) contextDependencies.add(res);
524
537
  }
@@ -1057,9 +1070,21 @@ module.exports = webpackEmptyAsyncContext;`;
1057
1070
  return this.getSourceForEmptyContext(id, runtimeTemplate);
1058
1071
  }
1059
1072
 
1060
- getSource(sourceString) {
1073
+ /**
1074
+ * @param {string} sourceString source content
1075
+ * @param {Compilation=} compilation the compilation
1076
+ * @returns {Source} generated source
1077
+ */
1078
+ getSource(sourceString, compilation) {
1061
1079
  if (this.useSourceMap || this.useSimpleSourceMap) {
1062
- return new OriginalSource(sourceString, this.identifier());
1080
+ return new OriginalSource(
1081
+ sourceString,
1082
+ `webpack://${makePathsRelative(
1083
+ (compilation && compilation.compiler.context) || "",
1084
+ this.identifier(),
1085
+ compilation && compilation.compiler.root
1086
+ )}`
1087
+ );
1063
1088
  }
1064
1089
  return new RawSource(sourceString);
1065
1090
  }
@@ -1069,16 +1094,23 @@ module.exports = webpackEmptyAsyncContext;`;
1069
1094
  * @returns {CodeGenerationResult} result
1070
1095
  */
1071
1096
  codeGeneration(context) {
1072
- const { chunkGraph } = context;
1097
+ const { chunkGraph, compilation } = context;
1073
1098
  const sources = new Map();
1074
1099
  sources.set(
1075
1100
  "javascript",
1076
- this.getSource(this.getSourceString(this.options.mode, context))
1101
+ this.getSource(
1102
+ this.getSourceString(this.options.mode, context),
1103
+ compilation
1104
+ )
1077
1105
  );
1078
1106
  const set = new Set();
1079
- const allDeps = /** @type {ContextElementDependency[]} */ (
1080
- this.dependencies.concat(this.blocks.map(b => b.dependencies[0]))
1081
- );
1107
+ const allDeps =
1108
+ this.dependencies.length > 0
1109
+ ? /** @type {ContextElementDependency[]} */ (this.dependencies).slice()
1110
+ : [];
1111
+ for (const block of this.blocks)
1112
+ for (const dep of block.dependencies)
1113
+ allDeps.push(/** @type {ContextElementDependency} */ (dep));
1082
1114
  set.add(RuntimeGlobals.module);
1083
1115
  set.add(RuntimeGlobals.hasOwnProperty);
1084
1116
  if (allDeps.length > 0) {