webpack 5.5.1 → 5.9.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 (63) hide show
  1. package/bin/webpack.js +10 -3
  2. package/lib/Compilation.js +132 -17
  3. package/lib/Compiler.js +2 -2
  4. package/lib/ExportsInfo.js +1 -1
  5. package/lib/FlagDependencyUsagePlugin.js +4 -2
  6. package/lib/HotModuleReplacementPlugin.js +170 -36
  7. package/lib/NormalModule.js +13 -1
  8. package/lib/RuntimeTemplate.js +0 -3
  9. package/lib/SourceMapDevToolPlugin.js +2 -1
  10. package/lib/Template.js +0 -1
  11. package/lib/TemplatedPathPlugin.js +8 -0
  12. package/lib/Watching.js +0 -1
  13. package/lib/cache/ResolverCachePlugin.js +0 -1
  14. package/lib/config/defaults.js +1 -1
  15. package/lib/dependencies/AMDDefineDependency.js +3 -1
  16. package/lib/dependencies/AMDRequireArrayDependency.js +3 -1
  17. package/lib/dependencies/AMDRequireDependency.js +3 -1
  18. package/lib/dependencies/CachedConstDependency.js +3 -1
  19. package/lib/dependencies/CommonJsExportRequireDependency.js +3 -2
  20. package/lib/dependencies/CommonJsExportsDependency.js +3 -1
  21. package/lib/dependencies/CommonJsFullRequireDependency.js +3 -1
  22. package/lib/dependencies/CommonJsSelfReferenceDependency.js +3 -1
  23. package/lib/dependencies/ConstDependency.js +3 -1
  24. package/lib/dependencies/ExportsInfoDependency.js +3 -1
  25. package/lib/dependencies/HarmonyAcceptDependency.js +3 -1
  26. package/lib/dependencies/HarmonyAcceptImportDependency.js +3 -1
  27. package/lib/dependencies/HarmonyCompatibilityDependency.js +3 -1
  28. package/lib/dependencies/HarmonyExportExpressionDependency.js +3 -1
  29. package/lib/dependencies/HarmonyExportHeaderDependency.js +3 -1
  30. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +11 -2
  31. package/lib/dependencies/HarmonyExportSpecifierDependency.js +3 -1
  32. package/lib/dependencies/HarmonyImportDependency.js +50 -46
  33. package/lib/dependencies/HarmonyImportSideEffectDependency.js +3 -1
  34. package/lib/dependencies/HarmonyImportSpecifierDependency.js +11 -1
  35. package/lib/dependencies/ImportDependency.js +3 -2
  36. package/lib/dependencies/ImportEagerDependency.js +3 -1
  37. package/lib/dependencies/ImportWeakDependency.js +3 -1
  38. package/lib/dependencies/LocalModuleDependency.js +3 -1
  39. package/lib/dependencies/ModuleDecoratorDependency.js +3 -2
  40. package/lib/dependencies/NullDependency.js +3 -2
  41. package/lib/dependencies/PureExpressionDependency.js +3 -1
  42. package/lib/dependencies/RequireEnsureDependency.js +3 -1
  43. package/lib/dependencies/RequireHeaderDependency.js +3 -1
  44. package/lib/dependencies/RequireIncludeDependency.js +3 -2
  45. package/lib/dependencies/RequireResolveHeaderDependency.js +3 -1
  46. package/lib/dependencies/RuntimeRequirementsDependency.js +3 -1
  47. package/lib/dependencies/URLDependency.js +3 -1
  48. package/lib/dependencies/UnsupportedDependency.js +3 -1
  49. package/lib/dependencies/WorkerDependency.js +3 -2
  50. package/lib/hmr/HotModuleReplacement.runtime.js +1 -0
  51. package/lib/index.js +3 -0
  52. package/lib/javascript/JavascriptParser.js +29 -11
  53. package/lib/optimize/RealContentHashPlugin.js +127 -32
  54. package/lib/optimize/SideEffectsFlagPlugin.js +224 -204
  55. package/lib/optimize/SplitChunksPlugin.js +0 -1
  56. package/lib/runtime/GetMainFilenameRuntimeModule.js +4 -2
  57. package/lib/runtime/LoadScriptRuntimeModule.js +0 -1
  58. package/lib/serialization/FileMiddleware.js +4 -2
  59. package/lib/util/runtime.js +4 -0
  60. package/lib/wasm-async/AsyncWebAssemblyModulesPlugin.js +0 -1
  61. package/lib/webpack.js +0 -2
  62. package/package.json +14 -14
  63. package/types.d.ts +179 -149
@@ -33,6 +33,7 @@ module.exports = function () {
33
33
  var currentUpdateApplyHandlers;
34
34
  var queuedInvalidatedModules;
35
35
 
36
+ // eslint-disable-next-line no-unused-vars
36
37
  $hmrModuleData$ = currentModuleData;
37
38
 
38
39
  $interceptModuleExecution$.push(function (options) {
package/lib/index.js CHANGED
@@ -355,6 +355,9 @@ module.exports = mergeExports(fn, {
355
355
  get ModuleConcatenationPlugin() {
356
356
  return require("./optimize/ModuleConcatenationPlugin");
357
357
  },
358
+ get RealContentHashPlugin() {
359
+ return require("./optimize/RealContentHashPlugin");
360
+ },
358
361
  get RuntimeChunkPlugin() {
359
362
  return require("./optimize/RuntimeChunkPlugin");
360
363
  },
@@ -1551,6 +1551,18 @@ class JavascriptParser extends Parser {
1551
1551
  this.prevStatement = this.statementPath.pop();
1552
1552
  }
1553
1553
 
1554
+ /**
1555
+ * Walks a statements that is nested within a parent statement
1556
+ * and can potentially be a non-block statement.
1557
+ * This enforces the nested statement to never be in ASI position.
1558
+ * @param {StatementNode} statement the nested statement
1559
+ * @returns {void}
1560
+ */
1561
+ walkNestedStatement(statement) {
1562
+ this.prevStatement = undefined;
1563
+ this.walkStatement(statement);
1564
+ }
1565
+
1554
1566
  // Real Statements
1555
1567
  preWalkBlockStatement(statement) {
1556
1568
  this.preWalkStatements(statement.body);
@@ -1581,15 +1593,15 @@ class JavascriptParser extends Parser {
1581
1593
  const result = this.hooks.statementIf.call(statement);
1582
1594
  if (result === undefined) {
1583
1595
  this.walkExpression(statement.test);
1584
- this.walkStatement(statement.consequent);
1596
+ this.walkNestedStatement(statement.consequent);
1585
1597
  if (statement.alternate) {
1586
- this.walkStatement(statement.alternate);
1598
+ this.walkNestedStatement(statement.alternate);
1587
1599
  }
1588
1600
  } else {
1589
1601
  if (result) {
1590
- this.walkStatement(statement.consequent);
1602
+ this.walkNestedStatement(statement.consequent);
1591
1603
  } else if (statement.alternate) {
1592
- this.walkStatement(statement.alternate);
1604
+ this.walkNestedStatement(statement.alternate);
1593
1605
  }
1594
1606
  }
1595
1607
  }
@@ -1604,7 +1616,7 @@ class JavascriptParser extends Parser {
1604
1616
  const result = hook.call(statement);
1605
1617
  if (result === true) return;
1606
1618
  }
1607
- this.walkStatement(statement.body);
1619
+ this.walkNestedStatement(statement.body);
1608
1620
  }
1609
1621
 
1610
1622
  preWalkWithStatement(statement) {
@@ -1613,7 +1625,7 @@ class JavascriptParser extends Parser {
1613
1625
 
1614
1626
  walkWithStatement(statement) {
1615
1627
  this.walkExpression(statement.object);
1616
- this.walkStatement(statement.body);
1628
+ this.walkNestedStatement(statement.body);
1617
1629
  }
1618
1630
 
1619
1631
  preWalkSwitchStatement(statement) {
@@ -1661,7 +1673,7 @@ class JavascriptParser extends Parser {
1661
1673
 
1662
1674
  walkWhileStatement(statement) {
1663
1675
  this.walkExpression(statement.test);
1664
- this.walkStatement(statement.body);
1676
+ this.walkNestedStatement(statement.body);
1665
1677
  }
1666
1678
 
1667
1679
  preWalkDoWhileStatement(statement) {
@@ -1669,7 +1681,7 @@ class JavascriptParser extends Parser {
1669
1681
  }
1670
1682
 
1671
1683
  walkDoWhileStatement(statement) {
1672
- this.walkStatement(statement.body);
1684
+ this.walkNestedStatement(statement.body);
1673
1685
  this.walkExpression(statement.test);
1674
1686
  }
1675
1687
 
@@ -1687,6 +1699,7 @@ class JavascriptParser extends Parser {
1687
1699
  if (statement.init) {
1688
1700
  if (statement.init.type === "VariableDeclaration") {
1689
1701
  this.blockPreWalkVariableDeclaration(statement.init);
1702
+ this.prevStatement = undefined;
1690
1703
  this.walkStatement(statement.init);
1691
1704
  } else {
1692
1705
  this.walkExpression(statement.init);
@@ -1706,7 +1719,7 @@ class JavascriptParser extends Parser {
1706
1719
  this.prevStatement = prev;
1707
1720
  this.walkStatements(body.body);
1708
1721
  } else {
1709
- this.walkStatement(body);
1722
+ this.walkNestedStatement(body);
1710
1723
  }
1711
1724
  });
1712
1725
  }
@@ -1735,7 +1748,7 @@ class JavascriptParser extends Parser {
1735
1748
  this.prevStatement = prev;
1736
1749
  this.walkStatements(body.body);
1737
1750
  } else {
1738
- this.walkStatement(body);
1751
+ this.walkNestedStatement(body);
1739
1752
  }
1740
1753
  });
1741
1754
  }
@@ -1767,7 +1780,7 @@ class JavascriptParser extends Parser {
1767
1780
  this.prevStatement = prev;
1768
1781
  this.walkStatements(body.body);
1769
1782
  } else {
1770
- this.walkStatement(body);
1783
+ this.walkNestedStatement(body);
1771
1784
  }
1772
1785
  });
1773
1786
  }
@@ -3376,9 +3389,14 @@ class JavascriptParser extends Parser {
3376
3389
  const currentStatement = this.statementPath[this.statementPath.length - 1];
3377
3390
  if (currentStatement === undefined) throw new Error("Not in statement");
3378
3391
  return (
3392
+ // Either asking directly for the end position of the current statement
3379
3393
  (currentStatement.range[1] === pos && this.semicolons.has(pos)) ||
3394
+ // Or asking for the start position of the current statement,
3395
+ // here we have to check multiple things
3380
3396
  (currentStatement.range[0] === pos &&
3397
+ // is there a previous statement which might be relevant?
3381
3398
  this.prevStatement !== undefined &&
3399
+ // is the end position of the previous statement an ASI position?
3382
3400
  this.semicolons.has(this.prevStatement.range[1]))
3383
3401
  );
3384
3402
  }
@@ -5,12 +5,15 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const { SyncBailHook } = require("tapable");
8
9
  const { RawSource, CachedSource, CompatSource } = require("webpack-sources");
9
10
  const Compilation = require("../Compilation");
10
11
  const WebpackError = require("../WebpackError");
11
12
  const { compareSelect, compareStrings } = require("../util/comparators");
12
13
  const createHash = require("../util/createHash");
13
14
 
15
+ /** @typedef {import("webpack-sources").Source} Source */
16
+ /** @typedef {import("../Compilation").AssetInfo} AssetInfo */
14
17
  /** @typedef {import("../Compiler")} Compiler */
15
18
 
16
19
  const EMPTY_SET = new Set();
@@ -47,7 +50,50 @@ const toCachedSource = source => {
47
50
  return newSource;
48
51
  };
49
52
 
53
+ /**
54
+ * @typedef {Object} AssetInfoForRealContentHash
55
+ * @property {string} name
56
+ * @property {AssetInfo} info
57
+ * @property {Source} source
58
+ * @property {RawSource | undefined} newSource
59
+ * @property {RawSource | undefined} newSourceWithoutOwn
60
+ * @property {string} content
61
+ * @property {Set<string>} ownHashes
62
+ * @property {Promise} contentComputePromise
63
+ * @property {Promise} contentComputeWithoutOwnPromise
64
+ * @property {Set<string>} referencedHashes
65
+ * @property {Set<string>} hashes
66
+ */
67
+
68
+ /**
69
+ * @typedef {Object} CompilationHooks
70
+ * @property {SyncBailHook<[Buffer[], string], string>} updateHash
71
+ */
72
+
73
+ /** @type {WeakMap<Compilation, CompilationHooks>} */
74
+ const compilationHooksMap = new WeakMap();
75
+
50
76
  class RealContentHashPlugin {
77
+ /**
78
+ * @param {Compilation} compilation the compilation
79
+ * @returns {CompilationHooks} the attached hooks
80
+ */
81
+ static getCompilationHooks(compilation) {
82
+ if (!(compilation instanceof Compilation)) {
83
+ throw new TypeError(
84
+ "The 'compilation' argument must be an instance of Compilation"
85
+ );
86
+ }
87
+ let hooks = compilationHooksMap.get(compilation);
88
+ if (hooks === undefined) {
89
+ hooks = {
90
+ updateHash: new SyncBailHook(["content", "oldHash"])
91
+ };
92
+ compilationHooksMap.set(compilation, hooks);
93
+ }
94
+ return hooks;
95
+ }
96
+
51
97
  constructor({ hashFunction, hashDigest }) {
52
98
  this._hashFunction = hashFunction;
53
99
  this._hashDigest = hashDigest;
@@ -66,6 +112,7 @@ class RealContentHashPlugin {
66
112
  const cacheGenerate = compilation.getCache(
67
113
  "RealContentHashPlugin|generate"
68
114
  );
115
+ const hooks = RealContentHashPlugin.getCompilationHooks(compilation);
69
116
  compilation.hooks.processAssets.tapPromise(
70
117
  {
71
118
  name: "RealContentHashPlugin",
@@ -73,6 +120,7 @@ class RealContentHashPlugin {
73
120
  },
74
121
  async () => {
75
122
  const assets = compilation.getAssets();
123
+ /** @type {AssetInfoForRealContentHash[]} */
76
124
  const assetsWithInfo = [];
77
125
  const hashToAssets = new Map();
78
126
  for (const { source, info, name } of assets) {
@@ -87,9 +135,13 @@ class RealContentHashPlugin {
87
135
  source: cachedSource,
88
136
  /** @type {RawSource | undefined} */
89
137
  newSource: undefined,
138
+ /** @type {RawSource | undefined} */
139
+ newSourceWithoutOwn: undefined,
90
140
  content,
91
- hasOwnHash: false,
92
- contentComputePromise: false,
141
+ /** @type {Set<string>} */
142
+ ownHashes: undefined,
143
+ contentComputePromise: undefined,
144
+ contentComputeWithoutOwnPromise: undefined,
93
145
  /** @type {Set<string>} */
94
146
  referencedHashes: undefined,
95
147
  hashes
@@ -114,6 +166,7 @@ class RealContentHashPlugin {
114
166
  const { name, source, content, hashes } = asset;
115
167
  if (Buffer.isBuffer(content)) {
116
168
  asset.referencedHashes = EMPTY_SET;
169
+ asset.ownHashes = EMPTY_SET;
117
170
  return;
118
171
  }
119
172
  const etag = cacheAnalyse.mergeEtags(
@@ -122,21 +175,21 @@ class RealContentHashPlugin {
122
175
  );
123
176
  [
124
177
  asset.referencedHashes,
125
- asset.hasOwnHash
178
+ asset.ownHashes
126
179
  ] = await cacheAnalyse.providePromise(name, etag, () => {
127
180
  const referencedHashes = new Set();
128
- let hasOwnHash = false;
181
+ let ownHashes = new Set();
129
182
  const inContent = content.match(hashRegExp);
130
183
  if (inContent) {
131
184
  for (const hash of inContent) {
132
185
  if (hashes.has(hash)) {
133
- hasOwnHash = true;
186
+ ownHashes.add(hash);
134
187
  continue;
135
188
  }
136
189
  referencedHashes.add(hash);
137
190
  }
138
191
  }
139
- return [referencedHashes, hasOwnHash];
192
+ return [referencedHashes, ownHashes];
140
193
  });
141
194
  })
142
195
  );
@@ -163,7 +216,12 @@ ${referencingAssets
163
216
  return undefined;
164
217
  }
165
218
  const hashes = new Set();
166
- for (const { referencedHashes } of assets) {
219
+ for (const { referencedHashes, ownHashes } of assets) {
220
+ if (!ownHashes.has(hash)) {
221
+ for (const hash of ownHashes) {
222
+ hashes.add(hash);
223
+ }
224
+ }
167
225
  for (const hash of referencedHashes) {
168
226
  hashes.add(hash);
169
227
  }
@@ -199,32 +257,57 @@ ${referencingAssets
199
257
  add(hash, new Set());
200
258
  }
201
259
  const hashToNewHash = new Map();
202
- const computeNewContent = (asset, includeOwn) => {
260
+ const getEtag = asset =>
261
+ cacheGenerate.mergeEtags(
262
+ cacheGenerate.getLazyHashedEtag(asset.source),
263
+ Array.from(asset.referencedHashes, hash =>
264
+ hashToNewHash.get(hash)
265
+ ).join("|")
266
+ );
267
+ const computeNewContent = asset => {
203
268
  if (asset.contentComputePromise) return asset.contentComputePromise;
204
269
  return (asset.contentComputePromise = (async () => {
205
270
  if (
206
- asset.hasOwnHash ||
271
+ asset.ownHashes.size > 0 ||
207
272
  Array.from(asset.referencedHashes).some(
208
273
  hash => hashToNewHash.get(hash) !== hash
209
274
  )
210
275
  ) {
211
- const identifier =
212
- asset.name +
213
- (includeOwn && asset.hasOwnHash ? "|with-own" : "");
214
- const etag = cacheGenerate.mergeEtags(
215
- cacheGenerate.getLazyHashedEtag(asset.source),
216
- Array.from(asset.referencedHashes, hash =>
217
- hashToNewHash.get(hash)
218
- ).join("|")
219
- );
276
+ const identifier = asset.name;
277
+ const etag = getEtag(asset);
220
278
  asset.newSource = await cacheGenerate.providePromise(
279
+ identifier,
280
+ etag,
281
+ () => {
282
+ const newContent = asset.content.replace(hashRegExp, hash =>
283
+ hashToNewHash.get(hash)
284
+ );
285
+ return new RawSource(newContent);
286
+ }
287
+ );
288
+ }
289
+ })());
290
+ };
291
+ const computeNewContentWithoutOwn = asset => {
292
+ if (asset.contentComputeWithoutOwnPromise)
293
+ return asset.contentComputeWithoutOwnPromise;
294
+ return (asset.contentComputeWithoutOwnPromise = (async () => {
295
+ if (
296
+ asset.ownHashes.size > 0 ||
297
+ Array.from(asset.referencedHashes).some(
298
+ hash => hashToNewHash.get(hash) !== hash
299
+ )
300
+ ) {
301
+ const identifier = asset.name + "|without-own";
302
+ const etag = getEtag(asset);
303
+ asset.newSourceWithoutOwn = await cacheGenerate.providePromise(
221
304
  identifier,
222
305
  etag,
223
306
  () => {
224
307
  const newContent = asset.content.replace(
225
308
  hashRegExp,
226
309
  hash => {
227
- if (!includeOwn && asset.hashes.has(hash)) {
310
+ if (asset.ownHashes.has(hash)) {
228
311
  return "";
229
312
  }
230
313
  return hashToNewHash.get(hash);
@@ -241,25 +324,37 @@ ${referencingAssets
241
324
  const assets = hashToAssets.get(oldHash);
242
325
  assets.sort(comparator);
243
326
  const hash = createHash(this._hashFunction);
244
- await Promise.all(assets.map(computeNewContent));
245
- for (const asset of assets) {
246
- hash.update(
247
- asset.newSource
327
+ await Promise.all(
328
+ assets.map(asset =>
329
+ asset.ownHashes.has(oldHash)
330
+ ? computeNewContentWithoutOwn(asset)
331
+ : computeNewContent(asset)
332
+ )
333
+ );
334
+ const assetsContent = assets.map(asset => {
335
+ if (asset.ownHashes.has(oldHash)) {
336
+ return asset.newSourceWithoutOwn
337
+ ? asset.newSourceWithoutOwn.buffer()
338
+ : asset.source.buffer();
339
+ } else {
340
+ return asset.newSource
248
341
  ? asset.newSource.buffer()
249
- : asset.source.buffer()
250
- );
342
+ : asset.source.buffer();
343
+ }
344
+ });
345
+ let newHash = hooks.updateHash.call(assetsContent, oldHash);
346
+ if (!newHash) {
347
+ for (const content of assetsContent) {
348
+ hash.update(content);
349
+ }
350
+ const digest = hash.digest(this._hashDigest);
351
+ newHash = /** @type {string} */ (digest.slice(0, oldHash.length));
251
352
  }
252
- const digest = hash.digest(this._hashDigest);
253
- const newHash = digest.slice(0, oldHash.length);
254
353
  hashToNewHash.set(oldHash, newHash);
255
354
  }
256
355
  await Promise.all(
257
356
  assetsWithInfo.map(async asset => {
258
- // recomputed content with it's own hash
259
- if (asset.hasOwnHash) {
260
- asset.contentComputePromise = undefined;
261
- }
262
- await computeNewContent(asset, true);
357
+ await computeNewContent(asset);
263
358
  const newName = asset.name.replace(hashRegExp, hash =>
264
359
  hashToNewHash.get(hash)
265
360
  );