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.
- package/lib/AsyncDependenciesBlock.js +0 -2
- package/lib/ChunkGraph.js +0 -26
- package/lib/Compilation.js +222 -115
- package/lib/Compiler.js +2 -2
- package/lib/DefinePlugin.js +1 -1
- package/lib/DependenciesBlock.js +9 -0
- package/lib/Dependency.js +2 -0
- package/lib/FileSystemInfo.js +112 -30
- package/lib/Module.js +4 -0
- package/lib/ModuleGraph.js +11 -17
- package/lib/NormalModule.js +64 -27
- package/lib/NormalModuleFactory.js +57 -55
- package/lib/RuntimeTemplate.js +1 -1
- package/lib/WebpackOptionsApply.js +0 -2
- package/lib/buildChunkGraph.js +157 -100
- package/lib/cache/AddManagedPathsPlugin.js +2 -2
- package/lib/cache/PackFileCacheStrategy.js +2 -2
- package/lib/config/defaults.js +65 -43
- package/lib/config/normalization.js +6 -1
- package/lib/logging/Logger.js +1 -0
- package/lib/node/NodeTargetPlugin.js +1 -0
- package/lib/optimize/ConcatenatedModule.js +1 -1
- package/lib/optimize/EnsureChunkConditionsPlugin.js +1 -0
- package/lib/optimize/SplitChunksPlugin.js +57 -4
- package/lib/schemes/FileUriPlugin.js +9 -0
- package/lib/schemes/HttpUriPlugin.js +107 -31
- package/lib/serialization/Serializer.js +2 -4
- package/lib/util/fs.js +2 -0
- package/lib/util/propertyAccess.js +2 -2
- package/package.json +1 -1
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +258 -55
- package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
- package/schemas/plugins/schemes/HttpUriPlugin.json +28 -0
- package/types.d.ts +118 -91
package/lib/config/defaults.js
CHANGED
@@ -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, {
|
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
|
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 {
|
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",
|
269
|
-
D(experiments, "buildHttp",
|
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",
|
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
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
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
|
-
|
381
|
-
|
389
|
+
if (match) {
|
390
|
+
return [match[1]];
|
391
|
+
}
|
382
392
|
}
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
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
|
-
|
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
|
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,
|
package/lib/logging/Logger.js
CHANGED
@@ -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
|
}
|
@@ -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
|
-
|
810
|
+
const START = ONE << BigInt("31");
|
811
|
+
let index = START;
|
778
812
|
for (const chunk of chunks) {
|
779
|
-
chunkIndexMap.set(
|
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
|
-
|
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 (
|
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 {
|
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
|
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.
|
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
|
-
|
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 =
|
315
|
-
const hashDigest =
|
316
|
-
|
317
|
-
const
|
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
|
-
|
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 =
|
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 =
|
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 (!
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
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,
|
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