webpack 5.57.1 → 5.59.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.

@@ -19,6 +19,7 @@ const {
19
19
  /** @typedef {import("../../declarations/WebpackOptions").EntryDescription} EntryDescription */
20
20
  /** @typedef {import("../../declarations/WebpackOptions").EntryNormalized} Entry */
21
21
  /** @typedef {import("../../declarations/WebpackOptions").Experiments} Experiments */
22
+ /** @typedef {import("../../declarations/WebpackOptions").ExperimentsNormalized} ExperimentsNormalized */
22
23
  /** @typedef {import("../../declarations/WebpackOptions").ExternalsPresets} ExternalsPresets */
23
24
  /** @typedef {import("../../declarations/WebpackOptions").ExternalsType} ExternalsType */
24
25
  /** @typedef {import("../../declarations/WebpackOptions").InfrastructureLogging} InfrastructureLogging */
@@ -161,6 +162,8 @@ const applyWebpackOptionsDefaults = options => {
161
162
 
162
163
  applyExperimentsDefaults(options.experiments, { production, development });
163
164
 
165
+ const futureDefaults = options.experiments.futureDefaults;
166
+
164
167
  F(options, "cache", () =>
165
168
  development ? { type: /** @type {"memory"} */ ("memory") } : false
166
169
  );
@@ -172,7 +175,10 @@ const applyWebpackOptionsDefaults = options => {
172
175
  });
173
176
  const cache = !!options.cache;
174
177
 
175
- applySnapshotDefaults(options.snapshot, { production });
178
+ applySnapshotDefaults(options.snapshot, {
179
+ production,
180
+ futureDefaults
181
+ });
176
182
 
177
183
  applyModuleDefaults(options.module, {
178
184
  cache,
@@ -192,7 +198,7 @@ const applyWebpackOptionsDefaults = options => {
192
198
  development,
193
199
  entry: options.entry,
194
200
  module: options.module,
195
- futureDefaults: options.experiments.futureDefaults
201
+ futureDefaults
196
202
  });
197
203
 
198
204
  applyExternalsPresetsDefaults(options.externalsPresets, {
@@ -252,7 +258,7 @@ const applyWebpackOptionsDefaults = options => {
252
258
  };
253
259
 
254
260
  /**
255
- * @param {Experiments} experiments options
261
+ * @param {ExperimentsNormalized} experiments options
256
262
  * @param {Object} options options
257
263
  * @param {boolean} options.production is production
258
264
  * @param {boolean} options.development is development mode
@@ -265,14 +271,14 @@ const applyExperimentsDefaults = (experiments, { production, development }) => {
265
271
  D(experiments, "outputModule", false);
266
272
  D(experiments, "asset", false);
267
273
  D(experiments, "layers", false);
268
- D(experiments, "lazyCompilation", false);
269
- D(experiments, "buildHttp", false);
274
+ D(experiments, "lazyCompilation", undefined);
275
+ D(experiments, "buildHttp", undefined);
270
276
  D(experiments, "futureDefaults", false);
271
277
  D(experiments, "cacheUnaffected", experiments.futureDefaults);
272
278
 
273
279
  if (typeof experiments.buildHttp === "object") {
274
280
  D(experiments.buildHttp, "frozen", production);
275
- D(experiments.buildHttp, "upgrade", development);
281
+ D(experiments.buildHttp, "upgrade", false);
276
282
  }
277
283
  };
278
284
 
@@ -348,49 +354,65 @@ const applyCacheDefaults = (
348
354
  * @param {SnapshotOptions} snapshot options
349
355
  * @param {Object} options options
350
356
  * @param {boolean} options.production is production
357
+ * @param {boolean} options.futureDefaults is future defaults enabled
351
358
  * @returns {void}
352
359
  */
353
- const applySnapshotDefaults = (snapshot, { production }) => {
354
- A(snapshot, "managedPaths", () => {
355
- if (process.versions.pnp === "3") {
356
- const match =
357
- /^(.+?)[\\/]cache[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
358
- require.resolve("watchpack")
359
- );
360
- if (match) {
361
- return [path.resolve(match[1], "unplugged")];
362
- }
363
- } else {
364
- const match = /^(.+?[\\/]node_modules)[\\/]/.exec(
365
- // eslint-disable-next-line node/no-extraneous-require
366
- require.resolve("watchpack")
367
- );
368
- if (match) {
369
- return [match[1]];
370
- }
371
- }
372
- return [];
373
- });
374
- A(snapshot, "immutablePaths", () => {
375
- if (process.versions.pnp === "1") {
376
- const match =
377
- /^(.+?[\\/]v4)[\\/]npm-watchpack-[^\\/]+-[\da-f]{40}[\\/]node_modules[\\/]/.exec(
360
+ const applySnapshotDefaults = (snapshot, { production, futureDefaults }) => {
361
+ if (futureDefaults) {
362
+ F(snapshot, "managedPaths", () =>
363
+ process.versions.pnp === "3"
364
+ ? [
365
+ /^(.+?(?:[\\/]\.yarn[\\/]unplugged[\\/][^\\/]+)?[\\/]node_modules[\\/])/
366
+ ]
367
+ : [/^(.+?[\\/]node_modules[\\/])/]
368
+ );
369
+ F(snapshot, "immutablePaths", () =>
370
+ process.versions.pnp === "3"
371
+ ? [/^(.+?[\\/]cache[\\/][^\\/]+\.zip[\\/]node_modules[\\/])/]
372
+ : []
373
+ );
374
+ } else {
375
+ A(snapshot, "managedPaths", () => {
376
+ if (process.versions.pnp === "3") {
377
+ const match =
378
+ /^(.+?)[\\/]cache[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
379
+ require.resolve("watchpack")
380
+ );
381
+ if (match) {
382
+ return [path.resolve(match[1], "unplugged")];
383
+ }
384
+ } else {
385
+ const match = /^(.+?[\\/]node_modules)[\\/]/.exec(
386
+ // eslint-disable-next-line node/no-extraneous-require
378
387
  require.resolve("watchpack")
379
388
  );
380
- if (match) {
381
- return [match[1]];
389
+ if (match) {
390
+ return [match[1]];
391
+ }
382
392
  }
383
- } else if (process.versions.pnp === "3") {
384
- const match =
385
- /^(.+?)[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
386
- require.resolve("watchpack")
387
- );
388
- if (match) {
389
- return [match[1]];
393
+ return [];
394
+ });
395
+ A(snapshot, "immutablePaths", () => {
396
+ if (process.versions.pnp === "1") {
397
+ const match =
398
+ /^(.+?[\\/]v4)[\\/]npm-watchpack-[^\\/]+-[\da-f]{40}[\\/]node_modules[\\/]/.exec(
399
+ require.resolve("watchpack")
400
+ );
401
+ if (match) {
402
+ return [match[1]];
403
+ }
404
+ } else if (process.versions.pnp === "3") {
405
+ const match =
406
+ /^(.+?)[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
407
+ require.resolve("watchpack")
408
+ );
409
+ if (match) {
410
+ return [match[1]];
411
+ }
390
412
  }
391
- }
392
- return [];
393
- });
413
+ return [];
414
+ });
415
+ }
394
416
  F(snapshot, "resolveBuildDependencies", () => ({
395
417
  timestamp: true,
396
418
  hash: true
@@ -174,7 +174,12 @@ const getNormalizedWebpackOptions = config => {
174
174
  experiments: nestedConfig(config.experiments, experiments => ({
175
175
  ...experiments,
176
176
  buildHttp: optionalNestedConfig(experiments.buildHttp, options =>
177
- options === true ? {} : options
177
+ Array.isArray(options) ? { allowedUris: options } : options
178
+ ),
179
+ lazyCompilation: optionalNestedConfig(
180
+ experiments.lazyCompilation,
181
+ options =>
182
+ options === true ? {} : options === false ? undefined : options
178
183
  )
179
184
  })),
180
185
  externals: config.externals,
@@ -155,6 +155,7 @@ class WebpackLogger {
155
155
  if (this[TIMERS_AGGREGATES_SYMBOL] === undefined) return;
156
156
  const time = this[TIMERS_AGGREGATES_SYMBOL].get(label);
157
157
  if (time === undefined) return;
158
+ this[TIMERS_AGGREGATES_SYMBOL].delete(label);
158
159
  this[LOG_SYMBOL](LogType.time, [label, ...time]);
159
160
  }
160
161
  }
@@ -19,6 +19,7 @@ const builtins = [
19
19
  "constants",
20
20
  "crypto",
21
21
  "dgram",
22
+ "diagnostics_channel",
22
23
  "dns",
23
24
  "dns/promises",
24
25
  "domain",
@@ -564,7 +564,7 @@ const getFinalName = (
564
564
  ? `(0,${reference})`
565
565
  : asiSafe === false
566
566
  ? `;(0,${reference})`
567
- : `Object(${reference})`;
567
+ : `/*#__PURE__*/Object(${reference})`;
568
568
  }
569
569
  return reference;
570
570
  }
@@ -30,6 +30,7 @@ class EnsureChunkConditionsPlugin {
30
30
  /** @type {Set<ChunkGroup>} */
31
31
  const chunkGroups = new Set();
32
32
  for (const module of compilation.modules) {
33
+ if (!module.hasChunkCondition()) continue;
33
34
  for (const chunk of chunkGraph.getModuleChunksIterable(module)) {
34
35
  if (!module.chunkCondition(chunk, compilation)) {
35
36
  sourceChunks.add(chunk);
@@ -59,6 +59,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
59
59
  * @property {ChunkFilterFunction=} chunksFilter
60
60
  * @property {boolean=} enforce
61
61
  * @property {SplitChunksSizes} minSize
62
+ * @property {SplitChunksSizes} minSizeReduction
62
63
  * @property {SplitChunksSizes} minRemainingSize
63
64
  * @property {SplitChunksSizes} enforceSizeThreshold
64
65
  * @property {SplitChunksSizes} maxAsyncSize
@@ -80,6 +81,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
80
81
  * @property {GetName=} getName
81
82
  * @property {ChunkFilterFunction=} chunksFilter
82
83
  * @property {SplitChunksSizes} minSize
84
+ * @property {SplitChunksSizes} minSizeReduction
83
85
  * @property {SplitChunksSizes} minRemainingSize
84
86
  * @property {SplitChunksSizes} enforceSizeThreshold
85
87
  * @property {SplitChunksSizes} maxAsyncSize
@@ -132,6 +134,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
132
134
  * @property {ChunkFilterFunction} chunksFilter
133
135
  * @property {string[]} defaultSizeTypes
134
136
  * @property {SplitChunksSizes} minSize
137
+ * @property {SplitChunksSizes} minSizeReduction
135
138
  * @property {SplitChunksSizes} minRemainingSize
136
139
  * @property {SplitChunksSizes} enforceSizeThreshold
137
140
  * @property {SplitChunksSizes} maxInitialSize
@@ -336,6 +339,21 @@ const checkMinSize = (sizes, minSize) => {
336
339
  return true;
337
340
  };
338
341
 
342
+ /**
343
+ * @param {SplitChunksSizes} sizes the sizes
344
+ * @param {SplitChunksSizes} minSizeReduction the min sizes
345
+ * @param {number} chunkCount number of chunks
346
+ * @returns {boolean} true if there are sizes and all existing sizes are at least `minSizeReduction`
347
+ */
348
+ const checkMinSizeReduction = (sizes, minSizeReduction, chunkCount) => {
349
+ for (const key of Object.keys(minSizeReduction)) {
350
+ const size = sizes[key];
351
+ if (size === undefined || size === 0) continue;
352
+ if (size * chunkCount < minSizeReduction[key]) return false;
353
+ }
354
+ return true;
355
+ };
356
+
339
357
  /**
340
358
  * @param {SplitChunksSizes} sizes the sizes
341
359
  * @param {SplitChunksSizes} minSize the min sizes
@@ -548,6 +566,10 @@ const checkModuleLayer = (test, module) => {
548
566
  */
549
567
  const createCacheGroupSource = (options, key, defaultSizeTypes) => {
550
568
  const minSize = normalizeSizes(options.minSize, defaultSizeTypes);
569
+ const minSizeReduction = normalizeSizes(
570
+ options.minSizeReduction,
571
+ defaultSizeTypes
572
+ );
551
573
  const maxSize = normalizeSizes(options.maxSize, defaultSizeTypes);
552
574
  return {
553
575
  key,
@@ -556,6 +578,7 @@ const createCacheGroupSource = (options, key, defaultSizeTypes) => {
556
578
  chunksFilter: normalizeChunksFilter(options.chunks),
557
579
  enforce: options.enforce,
558
580
  minSize,
581
+ minSizeReduction,
559
582
  minRemainingSize: mergeSizes(
560
583
  normalizeSizes(options.minRemainingSize, defaultSizeTypes),
561
584
  minSize
@@ -594,6 +617,10 @@ module.exports = class SplitChunksPlugin {
594
617
  ];
595
618
  const fallbackCacheGroup = options.fallbackCacheGroup || {};
596
619
  const minSize = normalizeSizes(options.minSize, defaultSizeTypes);
620
+ const minSizeReduction = normalizeSizes(
621
+ options.minSizeReduction,
622
+ defaultSizeTypes
623
+ );
597
624
  const maxSize = normalizeSizes(options.maxSize, defaultSizeTypes);
598
625
 
599
626
  /** @type {SplitChunksOptions} */
@@ -601,6 +628,7 @@ module.exports = class SplitChunksPlugin {
601
628
  chunksFilter: normalizeChunksFilter(options.chunks || "all"),
602
629
  defaultSizeTypes,
603
630
  minSize,
631
+ minSizeReduction,
604
632
  minRemainingSize: mergeSizes(
605
633
  normalizeSizes(options.minRemainingSize, defaultSizeTypes),
606
634
  minSize
@@ -668,6 +696,10 @@ module.exports = class SplitChunksPlugin {
668
696
  cacheGroupSource.minSize,
669
697
  cacheGroupSource.enforce ? undefined : this.options.minSize
670
698
  );
699
+ const minSizeReduction = mergeSizes(
700
+ cacheGroupSource.minSizeReduction,
701
+ cacheGroupSource.enforce ? undefined : this.options.minSizeReduction
702
+ );
671
703
  const minRemainingSize = mergeSizes(
672
704
  cacheGroupSource.minRemainingSize,
673
705
  cacheGroupSource.enforce ? undefined : this.options.minRemainingSize
@@ -681,6 +713,7 @@ module.exports = class SplitChunksPlugin {
681
713
  priority: cacheGroupSource.priority || 0,
682
714
  chunksFilter: cacheGroupSource.chunksFilter || this.options.chunksFilter,
683
715
  minSize,
716
+ minSizeReduction,
684
717
  minRemainingSize,
685
718
  enforceSizeThreshold,
686
719
  maxAsyncSize: mergeSizes(
@@ -774,9 +807,13 @@ module.exports = class SplitChunksPlugin {
774
807
  const chunkIndexMap = new Map();
775
808
  const ZERO = BigInt("0");
776
809
  const ONE = BigInt("1");
777
- let index = ONE;
810
+ const START = ONE << BigInt("31");
811
+ let index = START;
778
812
  for (const chunk of chunks) {
779
- chunkIndexMap.set(chunk, index);
813
+ chunkIndexMap.set(
814
+ chunk,
815
+ index | BigInt((Math.random() * 0x7fffffff) | 0)
816
+ );
780
817
  index = index << ONE;
781
818
  }
782
819
  /**
@@ -793,7 +830,8 @@ module.exports = class SplitChunksPlugin {
793
830
  let key =
794
831
  chunkIndexMap.get(first) | chunkIndexMap.get(result.value);
795
832
  while (!(result = iterator.next()).done) {
796
- key = key | chunkIndexMap.get(result.value);
833
+ const raw = chunkIndexMap.get(result.value);
834
+ key = key ^ raw;
797
835
  }
798
836
  return key;
799
837
  };
@@ -1239,6 +1277,14 @@ module.exports = class SplitChunksPlugin {
1239
1277
  for (const [key, info] of chunksInfoMap) {
1240
1278
  if (removeMinSizeViolatingModules(info)) {
1241
1279
  chunksInfoMap.delete(key);
1280
+ } else if (
1281
+ !checkMinSizeReduction(
1282
+ info.sizes,
1283
+ info.cacheGroup.minSizeReduction,
1284
+ info.chunks.size
1285
+ )
1286
+ ) {
1287
+ chunksInfoMap.delete(key);
1242
1288
  }
1243
1289
  }
1244
1290
 
@@ -1526,7 +1572,14 @@ module.exports = class SplitChunksPlugin {
1526
1572
  chunksInfoMap.delete(key);
1527
1573
  continue;
1528
1574
  }
1529
- if (removeMinSizeViolatingModules(info)) {
1575
+ if (
1576
+ removeMinSizeViolatingModules(info) ||
1577
+ !checkMinSizeReduction(
1578
+ info.sizes,
1579
+ info.cacheGroup.minSizeReduction,
1580
+ info.chunks.size
1581
+ )
1582
+ ) {
1530
1583
  chunksInfoMap.delete(key);
1531
1584
  continue;
1532
1585
  }
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const { URL, fileURLToPath } = require("url");
9
+ const { NormalModule } = require("..");
9
10
 
10
11
  /** @typedef {import("../Compiler")} Compiler */
11
12
 
@@ -32,6 +33,14 @@ class FileUriPlugin {
32
33
  resourceData.resource = path + query + fragment;
33
34
  return true;
34
35
  });
36
+ const hooks = NormalModule.getCompilationHooks(compilation);
37
+ hooks.readResource
38
+ .for(undefined)
39
+ .tapAsync("FileUriPlugin", (loaderContext, callback) => {
40
+ const { resourcePath } = loaderContext;
41
+ loaderContext.addDependency(resourcePath);
42
+ loaderContext.fs.readFile(resourcePath, callback);
43
+ });
35
44
  }
36
45
  );
37
46
  }
@@ -5,12 +5,13 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const { resolve, extname, dirname } = require("path");
8
+ const { extname, basename } = require("path");
9
9
  const { URL } = require("url");
10
10
  const { createGunzip, createBrotliDecompress, createInflate } = require("zlib");
11
11
  const NormalModule = require("../NormalModule");
12
+ const createSchemaValidation = require("../util/create-schema-validation");
12
13
  const createHash = require("../util/createHash");
13
- const { mkdirp } = require("../util/fs");
14
+ const { mkdirp, dirname, join } = require("../util/fs");
14
15
  const memoize = require("../util/memoize");
15
16
 
16
17
  /** @typedef {import("../../declarations/plugins/schemes/HttpUriPlugin").HttpUriPluginOptions} HttpUriPluginOptions */
@@ -19,6 +20,18 @@ const memoize = require("../util/memoize");
19
20
  const getHttp = memoize(() => require("http"));
20
21
  const getHttps = memoize(() => require("https"));
21
22
 
23
+ /** @type {(() => void)[] | undefined} */
24
+ let inProgressWrite = undefined;
25
+
26
+ const validate = createSchemaValidation(
27
+ require("../../schemas/plugins/schemes/HttpUriPlugin.check.js"),
28
+ () => require("../../schemas/plugins/schemes/HttpUriPlugin.json"),
29
+ {
30
+ name: "Http Uri Plugin",
31
+ baseDataPath: "options"
32
+ }
33
+ );
34
+
22
35
  const toSafePath = str =>
23
36
  str
24
37
  .replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, "")
@@ -104,7 +117,6 @@ class Lockfile {
104
117
  this.version = 1;
105
118
  /** @type {Map<string, LockfileEntry | "ignore" | "no-cache">} */
106
119
  this.entries = new Map();
107
- this.outdated = false;
108
120
  }
109
121
 
110
122
  static parse(content) {
@@ -251,25 +263,17 @@ const cachedWithKey = (fn, forceFn = fn) => {
251
263
  return resultFn;
252
264
  };
253
265
 
254
- /**
255
- * @typedef {Object} HttpUriPluginAdvancedOptions
256
- * @property {string | typeof import("../util/Hash")=} hashFunction
257
- * @property {string=} hashDigest
258
- * @property {number=} hashDigestLength
259
- */
260
-
261
266
  class HttpUriPlugin {
262
267
  /**
263
- * @param {HttpUriPluginOptions & HttpUriPluginAdvancedOptions} options options
268
+ * @param {HttpUriPluginOptions} options options
264
269
  */
265
- constructor(options = {}) {
270
+ constructor(options) {
271
+ validate(options);
266
272
  this._lockfileLocation = options.lockfileLocation;
267
273
  this._cacheLocation = options.cacheLocation;
268
274
  this._upgrade = options.upgrade;
269
275
  this._frozen = options.frozen;
270
- this._hashFunction = options.hashFunction;
271
- this._hashDigest = options.hashDigest;
272
- this._hashDigestLength = options.hashDigestLength;
276
+ this._allowedUris = options.allowedUris;
273
277
  }
274
278
 
275
279
  /**
@@ -299,7 +303,8 @@ class HttpUriPlugin {
299
303
  const logger = compilation.getLogger("webpack.HttpUriPlugin");
300
304
  const lockfileLocation =
301
305
  this._lockfileLocation ||
302
- resolve(
306
+ join(
307
+ intermediateFs,
303
308
  compiler.context,
304
309
  compiler.name
305
310
  ? `${toSafePath(compiler.name)}.webpack.lock`
@@ -311,11 +316,10 @@ class HttpUriPlugin {
311
316
  : lockfileLocation + ".data";
312
317
  const upgrade = this._upgrade || false;
313
318
  const frozen = this._frozen || false;
314
- const hashFunction = this._hashFunction || "sha512";
315
- const hashDigest =
316
- this._hashDigest || compilation.outputOptions.hashDigest;
317
- const hashDigestLength =
318
- this._hashDigestLength || compilation.outputOptions.hashDigestLength;
319
+ const hashFunction = "sha512";
320
+ const hashDigest = "hex";
321
+ const hashDigestLength = 20;
322
+ const allowedUris = this._allowedUris;
319
323
 
320
324
  let warnedAboutEol = false;
321
325
 
@@ -400,11 +404,13 @@ class HttpUriPlugin {
400
404
  }
401
405
  );
402
406
 
403
- let outdatedLockfile = undefined;
407
+ /** @type {Map<string, LockfileEntry | "ignore" | "no-cache"> | undefined} */
408
+ let lockfileUpdates = undefined;
404
409
  const storeLockEntry = (lockfile, url, entry) => {
405
410
  const oldEntry = lockfile.entries.get(url);
411
+ if (lockfileUpdates === undefined) lockfileUpdates = new Map();
412
+ lockfileUpdates.set(url, entry);
406
413
  lockfile.entries.set(url, entry);
407
- outdatedLockfile = lockfile;
408
414
  if (!oldEntry) {
409
415
  logger.log(`${url} added to lockfile`);
410
416
  } else if (typeof oldEntry === "string") {
@@ -440,8 +446,8 @@ class HttpUriPlugin {
440
446
  if (!cacheLocation || !result.content)
441
447
  return callback(null, result);
442
448
  const key = getCacheKey(result.entry.resolved);
443
- const filePath = resolve(cacheLocation, key);
444
- mkdirp(intermediateFs, dirname(filePath), err => {
449
+ const filePath = join(intermediateFs, cacheLocation, key);
450
+ mkdirp(intermediateFs, dirname(intermediateFs, filePath), err => {
445
451
  if (err) return callback(err);
446
452
  intermediateFs.writeFile(filePath, result.content, err => {
447
453
  if (err) return callback(err);
@@ -671,6 +677,19 @@ class HttpUriPlugin {
671
677
  (url, callback) => fetchContentRaw(url, undefined, callback)
672
678
  );
673
679
 
680
+ const isAllowed = uri => {
681
+ for (const allowed of allowedUris) {
682
+ if (typeof allowed === "string") {
683
+ if (uri.startsWith(allowed)) return true;
684
+ } else if (typeof allowed === "function") {
685
+ if (allowed(uri)) return true;
686
+ } else {
687
+ if (allowed.test(uri)) return true;
688
+ }
689
+ }
690
+ return false;
691
+ };
692
+
674
693
  const getInfo = cachedWithKey(
675
694
  /**
676
695
  * @param {string} url the url
@@ -678,6 +697,15 @@ class HttpUriPlugin {
678
697
  * @returns {void}
679
698
  */
680
699
  (url, callback) => {
700
+ if (!isAllowed(url)) {
701
+ return callback(
702
+ new Error(
703
+ `${url} doesn't match the allowedUris policy. These URIs are allowed:\n${allowedUris
704
+ .map(uri => ` - ${uri}`)
705
+ .join("\n")}`
706
+ )
707
+ );
708
+ }
681
709
  getLockfile((err, lockfile) => {
682
710
  if (err) return callback(err);
683
711
  const entryOrString = lockfile.entries.get(url);
@@ -789,7 +817,7 @@ Remove this line from the lockfile to force upgrading.`
789
817
  // When there is a lockfile cache
790
818
  // we read the content from there
791
819
  const key = getCacheKey(entry.resolved);
792
- const filePath = resolve(cacheLocation, key);
820
+ const filePath = join(intermediateFs, cacheLocation, key);
793
821
  fs.readFile(filePath, (err, result) => {
794
822
  const content = /** @type {Buffer} */ (result);
795
823
  if (err) {
@@ -934,6 +962,7 @@ Run build with un-frozen lockfile to automatically fix lockfile.`
934
962
  .tapAsync("HttpUriPlugin", (resource, module, callback) => {
935
963
  return getInfo(resource, (err, result) => {
936
964
  if (err) return callback(err);
965
+ module.buildInfo.resourceIntegrity = result.entry.integrity;
937
966
  callback(null, result.content);
938
967
  });
939
968
  });
@@ -963,12 +992,59 @@ Run build with un-frozen lockfile to automatically fix lockfile.`
963
992
  compilation.hooks.finishModules.tapAsync(
964
993
  "HttpUriPlugin",
965
994
  (modules, callback) => {
966
- if (!outdatedLockfile) return callback();
967
- intermediateFs.writeFile(
968
- lockfileLocation,
969
- outdatedLockfile.toString(),
970
- callback
995
+ if (!lockfileUpdates) return callback();
996
+ const ext = extname(lockfileLocation);
997
+ const tempFile = join(
998
+ intermediateFs,
999
+ dirname(intermediateFs, lockfileLocation),
1000
+ `.${basename(lockfileLocation, ext)}.${
1001
+ (Math.random() * 10000) | 0
1002
+ }${ext}`
971
1003
  );
1004
+
1005
+ const writeDone = () => {
1006
+ const nextOperation = inProgressWrite.shift();
1007
+ if (nextOperation) {
1008
+ nextOperation();
1009
+ } else {
1010
+ inProgressWrite = undefined;
1011
+ }
1012
+ };
1013
+ const runWrite = () => {
1014
+ intermediateFs.readFile(lockfileLocation, (err, buffer) => {
1015
+ if (err && err.code !== "ENOENT") {
1016
+ writeDone();
1017
+ return callback(err);
1018
+ }
1019
+ const lockfile = buffer
1020
+ ? Lockfile.parse(buffer.toString("utf-8"))
1021
+ : new Lockfile();
1022
+ for (const [key, value] of lockfileUpdates) {
1023
+ lockfile.entries.set(key, value);
1024
+ }
1025
+ intermediateFs.writeFile(tempFile, lockfile.toString(), err => {
1026
+ if (err) {
1027
+ writeDone();
1028
+ return intermediateFs.unlink(tempFile, () => callback(err));
1029
+ }
1030
+ intermediateFs.rename(tempFile, lockfileLocation, err => {
1031
+ if (err) {
1032
+ writeDone();
1033
+ return intermediateFs.unlink(tempFile, () =>
1034
+ callback(err)
1035
+ );
1036
+ }
1037
+ writeDone();
1038
+ callback();
1039
+ });
1040
+ });
1041
+ });
1042
+ };
1043
+ if (inProgressWrite) {
1044
+ inProgressWrite.push(runWrite);
1045
+ } else {
1046
+ inProgressWrite = [];
1047
+ }
972
1048
  }
973
1049
  );
974
1050
  }
@@ -16,9 +16,7 @@ class Serializer {
16
16
  let current = obj;
17
17
  for (const middleware of this.serializeMiddlewares) {
18
18
  if (current && typeof current.then === "function") {
19
- current = current.then(
20
- data => data && middleware.serialize(data, context)
21
- );
19
+ current = current.then(data => data && middleware.serialize(data, ctx));
22
20
  } else if (current) {
23
21
  try {
24
22
  current = middleware.serialize(current, ctx);
@@ -36,7 +34,7 @@ class Serializer {
36
34
  let current = value;
37
35
  for (const middleware of this.deserializeMiddlewares) {
38
36
  if (current && typeof current.then === "function") {
39
- current = current.then(data => middleware.deserialize(data, context));
37
+ current = current.then(data => middleware.deserialize(data, ctx));
40
38
  } else {
41
39
  current = middleware.deserialize(current, ctx);
42
40
  }
package/lib/util/fs.js CHANGED
@@ -83,6 +83,8 @@ const path = require("path");
83
83
  * @returns {Watcher} a watcher
84
84
  */
85
85
 
86
+ // TODO webpack 6 make optional methods required
87
+
86
88
  /**
87
89
  * @typedef {Object} OutputFileSystem
88
90
  * @property {function(string, Buffer|string, Callback): void} writeFile