webpack 5.27.2 → 5.31.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.

@@ -27,11 +27,12 @@ const RBDT_RESOLVE_CJS = 0;
27
27
  const RBDT_RESOLVE_ESM = 1;
28
28
  const RBDT_RESOLVE_DIRECTORY = 2;
29
29
  const RBDT_RESOLVE_CJS_FILE = 3;
30
- const RBDT_RESOLVE_ESM_FILE = 4;
31
- const RBDT_DIRECTORY = 5;
32
- const RBDT_FILE = 6;
33
- const RBDT_DIRECTORY_DEPENDENCIES = 7;
34
- const RBDT_FILE_DEPENDENCIES = 8;
30
+ const RBDT_RESOLVE_CJS_FILE_AS_CHILD = 4;
31
+ const RBDT_RESOLVE_ESM_FILE = 5;
32
+ const RBDT_DIRECTORY = 6;
33
+ const RBDT_FILE = 7;
34
+ const RBDT_DIRECTORY_DEPENDENCIES = 8;
35
+ const RBDT_FILE_DEPENDENCIES = 9;
35
36
 
36
37
  const INVALID = Symbol("invalid");
37
38
 
@@ -63,7 +64,7 @@ const INVALID = Symbol("invalid");
63
64
  * @property {Set<string>} files list of files
64
65
  * @property {Set<string>} directories list of directories
65
66
  * @property {Set<string>} missing list of missing entries
66
- * @property {Map<string, string>} resolveResults stored resolve results
67
+ * @property {Map<string, string | false>} resolveResults stored resolve results
67
68
  * @property {Object} resolveDependencies dependencies of the resolving
68
69
  * @property {Set<string>} resolveDependencies.files list of files
69
70
  * @property {Set<string>} resolveDependencies.directories list of directories
@@ -412,6 +413,14 @@ class SnapshotOptimization {
412
413
  } times referenced)`;
413
414
  }
414
415
 
416
+ clear() {
417
+ this._map.clear();
418
+ this._statItemsShared = 0;
419
+ this._statItemsUnshared = 0;
420
+ this._statSharedSnapshots = 0;
421
+ this._statReusedSharedSnapshots = 0;
422
+ }
423
+
415
424
  storeUnsharedSnapshot(snapshot, locations) {
416
425
  if (locations === undefined) return;
417
426
  const optimizationEntry = {
@@ -984,6 +993,42 @@ class FileSystemInfo {
984
993
  }
985
994
  }
986
995
 
996
+ clear() {
997
+ this._remainingLogs = this.logger ? 40 : 0;
998
+ if (this._loggedPaths !== undefined) this._loggedPaths.clear();
999
+
1000
+ this._snapshotCache = new WeakMap();
1001
+ this._fileTimestampsOptimization.clear();
1002
+ this._fileHashesOptimization.clear();
1003
+ this._fileTshsOptimization.clear();
1004
+ this._contextTimestampsOptimization.clear();
1005
+ this._contextHashesOptimization.clear();
1006
+ this._contextTshsOptimization.clear();
1007
+ this._missingExistenceOptimization.clear();
1008
+ this._managedItemInfoOptimization.clear();
1009
+ this._managedFilesOptimization.clear();
1010
+ this._managedContextsOptimization.clear();
1011
+ this._managedMissingOptimization.clear();
1012
+ this._fileTimestamps.clear();
1013
+ this._fileHashes.clear();
1014
+ this._fileTshs.clear();
1015
+ this._contextTimestamps.clear();
1016
+ this._contextHashes.clear();
1017
+ this._contextTshs.clear();
1018
+ this._managedItems.clear();
1019
+ this._managedItems.clear();
1020
+
1021
+ this._cachedDeprecatedFileTimestamps = undefined;
1022
+ this._cachedDeprecatedContextTimestamps = undefined;
1023
+
1024
+ this._statCreatedSnapshots = 0;
1025
+ this._statTestedSnapshotsCached = 0;
1026
+ this._statTestedSnapshotsNotCached = 0;
1027
+ this._statTestedChildrenCached = 0;
1028
+ this._statTestedChildrenNotCached = 0;
1029
+ this._statTestedEntries = 0;
1030
+ }
1031
+
987
1032
  /**
988
1033
  * @param {Map<string, FileSystemInfoEntry | "ignore" | null>} map timestamps
989
1034
  * @returns {void}
@@ -1059,15 +1104,23 @@ class FileSystemInfo {
1059
1104
  const resolveCjs = createResolver({
1060
1105
  extensions: [".js", ".json", ".node"],
1061
1106
  conditionNames: ["require", "node"],
1107
+ exportsFields: ["exports"],
1108
+ fileSystem: this.fs
1109
+ });
1110
+ const resolveCjsAsChild = createResolver({
1111
+ extensions: [".js", ".json", ".node"],
1112
+ conditionNames: ["require", "node"],
1113
+ exportsFields: [],
1062
1114
  fileSystem: this.fs
1063
1115
  });
1064
1116
  const resolveEsm = createResolver({
1065
1117
  extensions: [".js", ".json", ".node"],
1066
1118
  fullySpecified: true,
1067
1119
  conditionNames: ["import", "node"],
1120
+ exportsFields: ["exports"],
1068
1121
  fileSystem: this.fs
1069
1122
  });
1070
- return { resolveContext, resolveEsm, resolveCjs };
1123
+ return { resolveContext, resolveEsm, resolveCjs, resolveCjsAsChild };
1071
1124
  }
1072
1125
 
1073
1126
  /**
@@ -1080,7 +1133,8 @@ class FileSystemInfo {
1080
1133
  const {
1081
1134
  resolveContext,
1082
1135
  resolveEsm,
1083
- resolveCjs
1136
+ resolveCjs,
1137
+ resolveCjsAsChild
1084
1138
  } = this._createBuildDependenciesResolvers();
1085
1139
 
1086
1140
  /** @type {Set<string>} */
@@ -1099,7 +1153,7 @@ class FileSystemInfo {
1099
1153
  const resolveDirectories = new Set();
1100
1154
  /** @type {Set<string>} */
1101
1155
  const resolveMissing = new Set();
1102
- /** @type {Map<string, string>} */
1156
+ /** @type {Map<string, string | false>} */
1103
1157
  const resolveResults = new Map();
1104
1158
  const invalidResolveResults = new Set();
1105
1159
  const resolverContext = {
@@ -1107,15 +1161,58 @@ class FileSystemInfo {
1107
1161
  contextDependencies: resolveDirectories,
1108
1162
  missingDependencies: resolveMissing
1109
1163
  };
1164
+ const expectedToString = expected => {
1165
+ return expected ? ` (expected ${expected})` : "";
1166
+ };
1167
+ const jobToString = job => {
1168
+ switch (job.type) {
1169
+ case RBDT_RESOLVE_CJS:
1170
+ return `resolve commonjs ${job.path}${expectedToString(
1171
+ job.expected
1172
+ )}`;
1173
+ case RBDT_RESOLVE_ESM:
1174
+ return `resolve esm ${job.path}${expectedToString(job.expected)}`;
1175
+ case RBDT_RESOLVE_DIRECTORY:
1176
+ return `resolve directory ${job.path}`;
1177
+ case RBDT_RESOLVE_CJS_FILE:
1178
+ return `resolve commonjs file ${job.path}${expectedToString(
1179
+ job.expected
1180
+ )}`;
1181
+ case RBDT_RESOLVE_ESM_FILE:
1182
+ return `resolve esm file ${job.path}${expectedToString(
1183
+ job.expected
1184
+ )}`;
1185
+ case RBDT_DIRECTORY:
1186
+ return `directory ${job.path}`;
1187
+ case RBDT_FILE:
1188
+ return `file ${job.path}`;
1189
+ case RBDT_DIRECTORY_DEPENDENCIES:
1190
+ return `directory dependencies ${job.path}`;
1191
+ case RBDT_FILE_DEPENDENCIES:
1192
+ return `file dependencies ${job.path}`;
1193
+ }
1194
+ return `unknown ${job.type} ${job.path}`;
1195
+ };
1196
+ const pathToString = job => {
1197
+ let result = ` at ${jobToString(job)}`;
1198
+ job = job.issuer;
1199
+ while (job !== undefined) {
1200
+ result += `\n at ${jobToString(job)}`;
1201
+ job = job.issuer;
1202
+ }
1203
+ return result;
1204
+ };
1110
1205
  processAsyncTree(
1111
1206
  Array.from(deps, dep => ({
1112
1207
  type: RBDT_RESOLVE_CJS,
1113
1208
  context,
1114
1209
  path: dep,
1115
- expected: undefined
1210
+ expected: undefined,
1211
+ issuer: undefined
1116
1212
  })),
1117
1213
  20,
1118
- ({ type, context, path, expected }, push, callback) => {
1214
+ (job, push, callback) => {
1215
+ const { type, context, path, expected } = job;
1119
1216
  const resolveDirectory = path => {
1120
1217
  const key = `d\n${context}\n${path}`;
1121
1218
  if (resolveResults.has(key)) {
@@ -1124,13 +1221,11 @@ class FileSystemInfo {
1124
1221
  resolveResults.set(key, undefined);
1125
1222
  resolveContext(context, path, resolverContext, (err, result) => {
1126
1223
  if (err) {
1127
- invalidResolveResults.add(key);
1128
- if (
1129
- err.code === "ENOENT" ||
1130
- err.code === "UNDECLARED_DEPENDENCY"
1131
- ) {
1224
+ if (expected === false) {
1225
+ resolveResults.set(key, false);
1132
1226
  return callback();
1133
1227
  }
1228
+ invalidResolveResults.add(key);
1134
1229
  err.message += `\nwhile resolving '${path}' in ${context} to a directory`;
1135
1230
  return callback(err);
1136
1231
  }
@@ -1139,7 +1234,8 @@ class FileSystemInfo {
1139
1234
  type: RBDT_DIRECTORY,
1140
1235
  context: undefined,
1141
1236
  path: result,
1142
- expected: undefined
1237
+ expected: undefined,
1238
+ issuer: job
1143
1239
  });
1144
1240
  callback();
1145
1241
  });
@@ -1151,25 +1247,27 @@ class FileSystemInfo {
1151
1247
  }
1152
1248
  resolveResults.set(key, undefined);
1153
1249
  resolve(context, path, resolverContext, (err, result) => {
1154
- if (expected) {
1250
+ if (typeof expected === "string") {
1155
1251
  if (result === expected) {
1156
1252
  resolveResults.set(key, result);
1157
1253
  } else {
1158
1254
  invalidResolveResults.add(key);
1159
- this.logger.debug(
1160
- `Resolving '${path}' in ${context} for build dependencies doesn't lead to expected result '${expected}', but to '${result}' instead. Resolving dependencies are ignored for this path.`
1255
+ this.logger.warn(
1256
+ `Resolving '${path}' in ${context} for build dependencies doesn't lead to expected result '${expected}', but to '${result}' instead. Resolving dependencies are ignored for this path.\n${pathToString(
1257
+ job
1258
+ )}`
1161
1259
  );
1162
1260
  }
1163
1261
  } else {
1164
1262
  if (err) {
1165
- invalidResolveResults.add(key);
1166
- if (
1167
- err.code === "ENOENT" ||
1168
- err.code === "UNDECLARED_DEPENDENCY"
1169
- ) {
1263
+ if (expected === false) {
1264
+ resolveResults.set(key, false);
1170
1265
  return callback();
1171
1266
  }
1172
- err.message += `\nwhile resolving '${path}' in ${context} as file`;
1267
+ invalidResolveResults.add(key);
1268
+ err.message += `\nwhile resolving '${path}' in ${context} as file\n${pathToString(
1269
+ job
1270
+ )}`;
1173
1271
  return callback(err);
1174
1272
  }
1175
1273
  resolveResults.set(key, result);
@@ -1177,7 +1275,8 @@ class FileSystemInfo {
1177
1275
  type: RBDT_FILE,
1178
1276
  context: undefined,
1179
1277
  path: result,
1180
- expected: undefined
1278
+ expected: undefined,
1279
+ issuer: job
1181
1280
  });
1182
1281
  }
1183
1282
  callback();
@@ -1210,6 +1309,10 @@ class FileSystemInfo {
1210
1309
  resolveFile(path, "f", resolveCjs);
1211
1310
  break;
1212
1311
  }
1312
+ case RBDT_RESOLVE_CJS_FILE_AS_CHILD: {
1313
+ resolveFile(path, "c", resolveCjsAsChild);
1314
+ break;
1315
+ }
1213
1316
  case RBDT_RESOLVE_ESM_FILE: {
1214
1317
  resolveFile(path, "e", resolveEsm);
1215
1318
  break;
@@ -1233,7 +1336,8 @@ class FileSystemInfo {
1233
1336
  type: RBDT_FILE_DEPENDENCIES,
1234
1337
  context: undefined,
1235
1338
  path: realPath,
1236
- expected: undefined
1339
+ expected: undefined,
1340
+ issuer: job
1237
1341
  });
1238
1342
  callback();
1239
1343
  });
@@ -1258,7 +1362,8 @@ class FileSystemInfo {
1258
1362
  type: RBDT_DIRECTORY_DEPENDENCIES,
1259
1363
  context: undefined,
1260
1364
  path: realPath,
1261
- expected: undefined
1365
+ expected: undefined,
1366
+ issuer: job
1262
1367
  });
1263
1368
  callback();
1264
1369
  });
@@ -1281,19 +1386,39 @@ class FileSystemInfo {
1281
1386
  type: RBDT_FILE,
1282
1387
  context: undefined,
1283
1388
  path: childPath,
1284
- expected: undefined
1389
+ expected: undefined,
1390
+ issuer: job
1285
1391
  });
1286
1392
  const context = dirname(this.fs, path);
1287
1393
  for (const modulePath of module.paths) {
1288
1394
  if (childPath.startsWith(modulePath)) {
1289
- let request = childPath.slice(modulePath.length + 1);
1395
+ let subPath = childPath.slice(modulePath.length + 1);
1396
+ const packageMatch = /^(@[^\\/]+[\\/])[^\\/]+/.exec(
1397
+ subPath
1398
+ );
1399
+ if (packageMatch) {
1400
+ push({
1401
+ type: RBDT_FILE,
1402
+ context: undefined,
1403
+ path:
1404
+ modulePath +
1405
+ childPath[modulePath.length] +
1406
+ packageMatch[0] +
1407
+ childPath[modulePath.length] +
1408
+ "package.json",
1409
+ expected: false,
1410
+ issuer: job
1411
+ });
1412
+ }
1413
+ let request = subPath.replace(/\\/g, "/");
1290
1414
  if (request.endsWith(".js"))
1291
1415
  request = request.slice(0, -3);
1292
1416
  push({
1293
- type: RBDT_RESOLVE_CJS_FILE,
1417
+ type: RBDT_RESOLVE_CJS_FILE_AS_CHILD,
1294
1418
  context,
1295
1419
  path: request,
1296
- expected: child.filename
1420
+ expected: child.filename,
1421
+ issuer: job
1297
1422
  });
1298
1423
  continue children;
1299
1424
  }
@@ -1306,7 +1431,8 @@ class FileSystemInfo {
1306
1431
  type: RBDT_RESOLVE_CJS_FILE,
1307
1432
  context,
1308
1433
  path: request,
1309
- expected: child.filename
1434
+ expected: child.filename,
1435
+ issuer: job
1310
1436
  });
1311
1437
  }
1312
1438
  }
@@ -1351,7 +1477,8 @@ class FileSystemInfo {
1351
1477
  type: RBDT_RESOLVE_ESM_FILE,
1352
1478
  context,
1353
1479
  path: dependency,
1354
- expected: undefined
1480
+ expected: undefined,
1481
+ issuer: job
1355
1482
  });
1356
1483
  } catch (e) {
1357
1484
  this.logger.warn(
@@ -1361,6 +1488,7 @@ class FileSystemInfo {
1361
1488
  )})'.\n` +
1362
1489
  "Build dependencies behind this expression are ignored and might cause incorrect cache invalidation."
1363
1490
  );
1491
+ this.logger.debug(pathToString(job));
1364
1492
  this.logger.debug(e.stack);
1365
1493
  }
1366
1494
  }
@@ -1368,6 +1496,7 @@ class FileSystemInfo {
1368
1496
  this.logger.warn(
1369
1497
  `Parsing of ${path} for build dependencies failed and all dependencies of this file are ignored, which might cause incorrect cache invalidation..`
1370
1498
  );
1499
+ this.logger.debug(pathToString(job));
1371
1500
  this.logger.debug(e.stack);
1372
1501
  }
1373
1502
  process.nextTick(callback);
@@ -1378,6 +1507,7 @@ class FileSystemInfo {
1378
1507
  this.logger.log(
1379
1508
  `Assuming ${path} has no dependencies as we were unable to assign it to any module system.`
1380
1509
  );
1510
+ this.logger.debug(pathToString(job));
1381
1511
  }
1382
1512
  process.nextTick(callback);
1383
1513
  break;
@@ -1398,7 +1528,8 @@ class FileSystemInfo {
1398
1528
  type: RBDT_DIRECTORY_DEPENDENCIES,
1399
1529
  context: undefined,
1400
1530
  path: parent,
1401
- expected: undefined
1531
+ expected: undefined,
1532
+ issuer: job
1402
1533
  });
1403
1534
  }
1404
1535
  callback();
@@ -1414,16 +1545,32 @@ class FileSystemInfo {
1414
1545
  return callback(e);
1415
1546
  }
1416
1547
  const depsObject = packageData.dependencies;
1548
+ const optionalDepsObject = packageData.optionalDependencies;
1549
+ const allDeps = new Set();
1550
+ const optionalDeps = new Set();
1417
1551
  if (typeof depsObject === "object" && depsObject) {
1418
1552
  for (const dep of Object.keys(depsObject)) {
1419
- push({
1420
- type: RBDT_RESOLVE_DIRECTORY,
1421
- context: packagePath,
1422
- path: dep,
1423
- expected: undefined
1424
- });
1553
+ allDeps.add(dep);
1554
+ }
1555
+ }
1556
+ if (
1557
+ typeof optionalDepsObject === "object" &&
1558
+ optionalDepsObject
1559
+ ) {
1560
+ for (const dep of Object.keys(optionalDepsObject)) {
1561
+ allDeps.add(dep);
1562
+ optionalDeps.add(dep);
1425
1563
  }
1426
1564
  }
1565
+ for (const dep of allDeps) {
1566
+ push({
1567
+ type: RBDT_RESOLVE_DIRECTORY,
1568
+ context: packagePath,
1569
+ path: dep,
1570
+ expected: !optionalDeps.has(dep),
1571
+ issuer: job
1572
+ });
1573
+ }
1427
1574
  callback();
1428
1575
  });
1429
1576
  break;
@@ -1451,13 +1598,14 @@ class FileSystemInfo {
1451
1598
  }
1452
1599
 
1453
1600
  /**
1454
- * @param {Map<string, string>} resolveResults results from resolving
1601
+ * @param {Map<string, string | false>} resolveResults results from resolving
1455
1602
  * @param {function(Error=, boolean=): void} callback callback with true when resolveResults resolve the same way
1456
1603
  * @returns {void}
1457
1604
  */
1458
1605
  checkResolveResultsValid(resolveResults, callback) {
1459
1606
  const {
1460
1607
  resolveCjs,
1608
+ resolveCjsAsChild,
1461
1609
  resolveEsm,
1462
1610
  resolveContext
1463
1611
  } = this._createBuildDependenciesResolvers();
@@ -1469,6 +1617,8 @@ class FileSystemInfo {
1469
1617
  switch (type) {
1470
1618
  case "d":
1471
1619
  resolveContext(context, path, {}, (err, result) => {
1620
+ if (expectedResult === false)
1621
+ return callback(err ? undefined : INVALID);
1472
1622
  if (err) return callback(err);
1473
1623
  if (result !== expectedResult) return callback(INVALID);
1474
1624
  callback();
@@ -1476,6 +1626,17 @@ class FileSystemInfo {
1476
1626
  break;
1477
1627
  case "f":
1478
1628
  resolveCjs(context, path, {}, (err, result) => {
1629
+ if (expectedResult === false)
1630
+ return callback(err ? undefined : INVALID);
1631
+ if (err) return callback(err);
1632
+ if (result !== expectedResult) return callback(INVALID);
1633
+ callback();
1634
+ });
1635
+ break;
1636
+ case "c":
1637
+ resolveCjsAsChild(context, path, {}, (err, result) => {
1638
+ if (expectedResult === false)
1639
+ return callback(err ? undefined : INVALID);
1479
1640
  if (err) return callback(err);
1480
1641
  if (result !== expectedResult) return callback(INVALID);
1481
1642
  callback();
@@ -1483,6 +1644,8 @@ class FileSystemInfo {
1483
1644
  break;
1484
1645
  case "e":
1485
1646
  resolveEsm(context, path, {}, (err, result) => {
1647
+ if (expectedResult === false)
1648
+ return callback(err ? undefined : INVALID);
1486
1649
  if (err) return callback(err);
1487
1650
  if (result !== expectedResult) return callback(INVALID);
1488
1651
  callback();
@@ -119,6 +119,7 @@ class FlagDependencyExportsPlugin {
119
119
  const exports = exportDesc.exports;
120
120
  const globalCanMangle = exportDesc.canMangle;
121
121
  const globalFrom = exportDesc.from;
122
+ const globalPriority = exportDesc.priority;
122
123
  const globalTerminalBinding =
123
124
  exportDesc.terminalBinding || false;
124
125
  const exportDeps = exportDesc.dependencies;
@@ -135,7 +136,8 @@ class FlagDependencyExportsPlugin {
135
136
  globalCanMangle,
136
137
  exportDesc.excludeExports,
137
138
  globalFrom && dep,
138
- globalFrom
139
+ globalFrom,
140
+ globalPriority
139
141
  )
140
142
  ) {
141
143
  changed = true;
@@ -154,6 +156,7 @@ class FlagDependencyExportsPlugin {
154
156
  let exports = undefined;
155
157
  let from = globalFrom;
156
158
  let fromExport = undefined;
159
+ let priority = globalPriority;
157
160
  let hidden = false;
158
161
  if (typeof exportNameOrSpec === "string") {
159
162
  name = exportNameOrSpec;
@@ -167,6 +170,8 @@ class FlagDependencyExportsPlugin {
167
170
  exports = exportNameOrSpec.exports;
168
171
  if (exportNameOrSpec.from !== undefined)
169
172
  from = exportNameOrSpec.from;
173
+ if (exportNameOrSpec.priority !== undefined)
174
+ priority = exportNameOrSpec.priority;
170
175
  if (exportNameOrSpec.terminalBinding !== undefined)
171
176
  terminalBinding = exportNameOrSpec.terminalBinding;
172
177
  if (exportNameOrSpec.hidden !== undefined)
@@ -174,7 +179,10 @@ class FlagDependencyExportsPlugin {
174
179
  }
175
180
  const exportInfo = exportsInfo.getExportInfo(name);
176
181
 
177
- if (exportInfo.provided === false) {
182
+ if (
183
+ exportInfo.provided === false ||
184
+ exportInfo.provided === null
185
+ ) {
178
186
  exportInfo.provided = true;
179
187
  changed = true;
180
188
  }
@@ -204,7 +212,8 @@ class FlagDependencyExportsPlugin {
204
212
  : exportInfo.setTarget(
205
213
  dep,
206
214
  from,
207
- fromExport === undefined ? [name] : fromExport
215
+ fromExport === undefined ? [name] : fromExport,
216
+ priority
208
217
  ))
209
218
  ) {
210
219
  changed = true;
@@ -367,6 +367,7 @@ class NormalModule extends Module {
367
367
  * @param {NormalModuleFactory} normalModuleFactory the normal module factory handling the unsafe caching
368
368
  */
369
369
  _restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory) {
370
+ super._restoreFromUnsafeCache(unsafeCacheData, normalModuleFactory);
370
371
  this.parserOptions = unsafeCacheData.parserOptions;
371
372
  this.parser = normalModuleFactory.getParser(this.type, this.parserOptions);
372
373
  this.generatorOptions = unsafeCacheData.generatorOptions;
@@ -748,6 +749,9 @@ class NormalModule extends Module {
748
749
  }
749
750
  },
750
751
  (err, result) => {
752
+ // Cleanup loaderContext to avoid leaking memory in ICs
753
+ loaderContext._compilation = loaderContext._compiler = loaderContext._module = loaderContext.fs = undefined;
754
+
751
755
  if (!result) {
752
756
  return processResult(
753
757
  err || new Error("No result from loader-runner processing"),
@@ -521,9 +521,17 @@ class WebpackOptionsApply extends OptionsApply {
521
521
  const cacheOptions = options.cache;
522
522
  switch (cacheOptions.type) {
523
523
  case "memory": {
524
- //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
525
- const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
526
- new MemoryCachePlugin().apply(compiler);
524
+ if (isFinite(cacheOptions.maxGenerations)) {
525
+ //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
526
+ const MemoryWithGcCachePlugin = require("./cache/MemoryWithGcCachePlugin");
527
+ new MemoryWithGcCachePlugin({
528
+ maxGenerations: cacheOptions.maxGenerations
529
+ }).apply(compiler);
530
+ } else {
531
+ //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
532
+ const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
533
+ new MemoryCachePlugin().apply(compiler);
534
+ }
527
535
  break;
528
536
  }
529
537
  case "filesystem": {
@@ -532,9 +540,17 @@ class WebpackOptionsApply extends OptionsApply {
532
540
  const list = cacheOptions.buildDependencies[key];
533
541
  new AddBuildDependenciesPlugin(list).apply(compiler);
534
542
  }
535
- //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
536
- const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
537
- new MemoryCachePlugin().apply(compiler);
543
+ if (!isFinite(cacheOptions.maxMemoryGenerations)) {
544
+ //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
545
+ const MemoryCachePlugin = require("./cache/MemoryCachePlugin");
546
+ new MemoryCachePlugin().apply(compiler);
547
+ } else if (cacheOptions.maxMemoryGenerations !== 0) {
548
+ //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
549
+ const MemoryWithGcCachePlugin = require("./cache/MemoryWithGcCachePlugin");
550
+ new MemoryWithGcCachePlugin({
551
+ maxGenerations: cacheOptions.maxMemoryGenerations
552
+ }).apply(compiler);
553
+ }
538
554
  switch (cacheOptions.store) {
539
555
  case "pack": {
540
556
  const IdleFileCachePlugin = require("./cache/IdleFileCachePlugin");
@@ -549,7 +565,8 @@ class WebpackOptionsApply extends OptionsApply {
549
565
  logger: compiler.getInfrastructureLogger(
550
566
  "webpack.cache.PackFileCacheStrategy"
551
567
  ),
552
- snapshot: options.snapshot
568
+ snapshot: options.snapshot,
569
+ maxAge: cacheOptions.maxAge
553
570
  }),
554
571
  cacheOptions.idleTimeout,
555
572
  cacheOptions.idleTimeoutForInitialStore