@depup/webpack 5.109.0-depup.0 → 5.109.2-depup.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.
Files changed (62) hide show
  1. package/README.md +4 -4
  2. package/bin/webpack.js +12 -0
  3. package/changes.json +4 -4
  4. package/lib/ChunkGraph.js +17 -15
  5. package/lib/CleanPlugin.js +11 -9
  6. package/lib/CompatibilityPlugin.js +31 -0
  7. package/lib/Compilation.js +21 -5
  8. package/lib/Compiler.js +16 -4
  9. package/lib/DefinePlugin.js +47 -20
  10. package/lib/ExportsInfo.js +22 -5
  11. package/lib/ExternalModule.js +10 -7
  12. package/lib/FileSystemInfo.js +126 -26
  13. package/lib/FlagDependencyUsagePlugin.js +33 -12
  14. package/lib/InitFragment.js +20 -32
  15. package/lib/ModuleFilenameHelpers.js +13 -2
  16. package/lib/NormalModule.js +80 -71
  17. package/lib/NormalModuleFactory.js +8 -2
  18. package/lib/RuntimePlugin.js +40 -113
  19. package/lib/Template.js +23 -3
  20. package/lib/cache/PackFileCacheStrategy.js +259 -5
  21. package/lib/config/defaults.js +21 -2
  22. package/lib/container/HoistContainerReferencesPlugin.js +47 -55
  23. package/lib/container/ModuleFederationPlugin.js +15 -9
  24. package/lib/css/CssGenerator.js +8 -2
  25. package/lib/css/CssLoadingRuntimeModule.js +25 -12
  26. package/lib/css/CssModulesPlugin.js +29 -18
  27. package/lib/css/CssParser.js +135 -50
  28. package/lib/css/syntax.js +862 -765
  29. package/lib/dependencies/CommonJsExportRequireDependency.js +19 -0
  30. package/lib/dependencies/CommonJsFullRequireDependency.js +33 -4
  31. package/lib/dependencies/CommonJsImportsParserPlugin.js +2 -0
  32. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +2 -1
  33. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +17 -9
  34. package/lib/dependencies/HarmonyImportDependency.js +1 -1
  35. package/lib/dependencies/HarmonyImportGuard.js +2 -1
  36. package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -7
  37. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +15 -9
  38. package/lib/hmr/lazyCompilationBackend.js +19 -4
  39. package/lib/html/HtmlGenerator.js +23 -3
  40. package/lib/html/HtmlModulesPlugin.js +30 -12
  41. package/lib/html/syntax.js +2485 -2399
  42. package/lib/ids/IdHelpers.js +24 -10
  43. package/lib/javascript/JavascriptModulesPlugin.js +83 -49
  44. package/lib/javascript/JavascriptParser.js +49 -13
  45. package/lib/javascript/syntax.js +700 -43
  46. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +10 -2
  47. package/lib/node/ReadFileCompileWasmPlugin.js +10 -2
  48. package/lib/optimize/AggressiveMergingPlugin.js +19 -15
  49. package/lib/optimize/ConcatenatedModule.js +19 -15
  50. package/lib/optimize/ModuleConcatenationPlugin.js +73 -24
  51. package/lib/optimize/RealContentHashPlugin.js +10 -7
  52. package/lib/optimize/SplitChunksPlugin.js +146 -44
  53. package/lib/prefetch/ResourceHintPlugin.js +96 -72
  54. package/lib/serialization/BinaryMiddleware.js +270 -938
  55. package/lib/serialization/FileMiddleware.js +299 -60
  56. package/lib/stats/DefaultStatsFactoryPlugin.js +204 -198
  57. package/lib/stats/DefaultStatsPrinterPlugin.js +24 -166
  58. package/lib/stats/StatsFactory.js +31 -9
  59. package/lib/util/identifier.js +21 -1
  60. package/package.json +10 -10
  61. package/schemas/WebpackOptions.json +110 -55
  62. package/types.d.ts +832 -247
@@ -47,6 +47,7 @@ const { makePathsRelative, parseResource } = require("../util/identifier");
47
47
  /** @typedef {import("../Module")} Module */
48
48
  /** @typedef {import("../Module").NameForCondition} NameForCondition */
49
49
  /** @typedef {import("../Module").BuildInfo} BuildInfo */
50
+ /** @typedef {import("../ModuleGraph")} ModuleGraph */
50
51
  /** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
51
52
  /** @typedef {import("../ModuleProfile")} ModuleProfile */
52
53
  /** @typedef {import("../errors/WebpackError")} WebpackError */
@@ -834,22 +835,24 @@ const SIMPLE_EXTRACTORS = {
834
835
  }
835
836
 
836
837
  object.assetsByChunkName = {};
837
- for (const [file, chunks] of [
838
- ...compilationFileToChunks,
839
- ...compilationAuxiliaryFileToChunks
838
+ for (const fileToChunks of [
839
+ compilationFileToChunks,
840
+ compilationAuxiliaryFileToChunks
840
841
  ]) {
841
- for (const chunk of chunks) {
842
- const name = chunk.name;
843
- if (!name) continue;
844
- if (
845
- !Object.prototype.hasOwnProperty.call(
846
- object.assetsByChunkName,
847
- name
848
- )
849
- ) {
850
- object.assetsByChunkName[name] = [];
842
+ for (const [file, chunks] of fileToChunks) {
843
+ for (const chunk of chunks) {
844
+ const name = chunk.name;
845
+ if (!name) continue;
846
+ if (
847
+ !Object.prototype.hasOwnProperty.call(
848
+ object.assetsByChunkName,
849
+ name
850
+ )
851
+ ) {
852
+ object.assetsByChunkName[name] = [];
853
+ }
854
+ object.assetsByChunkName[name].push(file);
851
855
  }
852
- object.assetsByChunkName[name].push(file);
853
856
  }
854
857
  }
855
858
 
@@ -1279,19 +1282,16 @@ const SIMPLE_EXTRACTORS = {
1279
1282
  for (const sourceType of module.getSourceTypes()) {
1280
1283
  sizes[sourceType] = module.size(sourceType);
1281
1284
  }
1282
- /** @type {KnownStatsModule} */
1283
- const statsModule = {
1284
- type: "module",
1285
- moduleType: module.type,
1286
- layer: module.layer,
1287
- size: module.size(),
1288
- sizes,
1289
- built,
1290
- codeGenerated,
1291
- buildTimeExecuted,
1292
- cached: !built && !codeGenerated
1293
- };
1294
- Object.assign(object, statsModule);
1285
+ // assign fields directly to avoid an intermediate object + copy per module
1286
+ object.type = "module";
1287
+ object.moduleType = module.type;
1288
+ object.layer = module.layer;
1289
+ object.size = module.size();
1290
+ object.sizes = sizes;
1291
+ object.built = built;
1292
+ object.codeGenerated = codeGenerated;
1293
+ object.buildTimeExecuted = buildTimeExecuted;
1294
+ object.cached = !built && !codeGenerated;
1295
1295
  if (built || codeGenerated || options.cachedModules) {
1296
1296
  Object.assign(
1297
1297
  object,
@@ -1323,42 +1323,40 @@ const SIMPLE_EXTRACTORS = {
1323
1323
  const { cacheable, notCacheableReasons } = /** @type {BuildInfo} */ (
1324
1324
  module.buildInfo
1325
1325
  );
1326
- /** @type {KnownStatsModule} */
1327
- const statsModule = {
1328
- identifier: module.identifier(),
1329
- name: module.readableIdentifier(requestShortener),
1330
- nameForCondition: module.nameForCondition(),
1331
- index: /** @type {number} */ (moduleGraph.getPreOrderIndex(module)),
1332
- preOrderIndex: /** @type {number} */ (
1333
- moduleGraph.getPreOrderIndex(module)
1334
- ),
1335
- index2: /** @type {number} */ (moduleGraph.getPostOrderIndex(module)),
1336
- postOrderIndex: /** @type {number} */ (
1337
- moduleGraph.getPostOrderIndex(module)
1338
- ),
1339
- cacheable,
1340
- notCacheableReasons:
1341
- notCacheableReasons &&
1342
- notCacheableReasons.map(
1343
- (request) =>
1344
- /** @type {string} */ (requestShortener.shorten(request))
1345
- ),
1346
- optional: module.isOptional(moduleGraph),
1347
- orphan:
1348
- !type.endsWith("module.modules[].module$visible") &&
1349
- compilation.chunkGraph.getNumberOfModuleChunks(module) === 0,
1350
- dependent: rootModules ? !rootModules.has(module) : undefined,
1351
- issuer: issuer && issuer.identifier(),
1352
- issuerName: issuer && issuer.readableIdentifier(requestShortener),
1353
- issuerPath:
1354
- issuer &&
1355
- /** @type {StatsModuleIssuer[] | undefined} */
1356
- (factory.create(`${type.slice(0, -8)}.issuerPath`, path, context)),
1357
- failed: errorsCount > 0,
1358
- errors: errorsCount,
1359
- warnings: warningsCount
1360
- };
1361
- Object.assign(object, statsModule);
1326
+ const preOrderIndex = /** @type {number} */ (
1327
+ moduleGraph.getPreOrderIndex(module)
1328
+ );
1329
+ const postOrderIndex = /** @type {number} */ (
1330
+ moduleGraph.getPostOrderIndex(module)
1331
+ );
1332
+ // assign fields directly to avoid an intermediate object + copy per module
1333
+ object.identifier = module.identifier();
1334
+ object.name = module.readableIdentifier(requestShortener);
1335
+ object.nameForCondition = module.nameForCondition();
1336
+ object.index = preOrderIndex;
1337
+ object.preOrderIndex = preOrderIndex;
1338
+ object.index2 = postOrderIndex;
1339
+ object.postOrderIndex = postOrderIndex;
1340
+ object.cacheable = cacheable;
1341
+ object.notCacheableReasons =
1342
+ notCacheableReasons &&
1343
+ notCacheableReasons.map(
1344
+ (request) => /** @type {string} */ (requestShortener.shorten(request))
1345
+ );
1346
+ object.optional = module.isOptional(moduleGraph);
1347
+ object.orphan =
1348
+ !type.endsWith("module.modules[].module$visible") &&
1349
+ compilation.chunkGraph.getNumberOfModuleChunks(module) === 0;
1350
+ object.dependent = rootModules ? !rootModules.has(module) : undefined;
1351
+ object.issuer = issuer && issuer.identifier();
1352
+ object.issuerName = issuer && issuer.readableIdentifier(requestShortener);
1353
+ object.issuerPath =
1354
+ issuer &&
1355
+ /** @type {StatsModuleIssuer[] | undefined} */
1356
+ (factory.create(`${type.slice(0, -8)}.issuerPath`, path, context));
1357
+ object.failed = errorsCount > 0;
1358
+ object.errors = errorsCount;
1359
+ object.warnings = warningsCount;
1362
1360
  if (profile) {
1363
1361
  object.profile = factory.create(
1364
1362
  `${type.slice(0, -8)}.profile`,
@@ -1470,27 +1468,24 @@ const SIMPLE_EXTRACTORS = {
1470
1468
  },
1471
1469
  profile: {
1472
1470
  _: (object, profile) => {
1473
- /** @type {KnownStatsProfile} */
1474
- const statsProfile = {
1475
- total:
1476
- profile.factory +
1477
- profile.restoring +
1478
- profile.integration +
1479
- profile.building +
1480
- profile.storing,
1481
- resolving: profile.factory,
1482
- restoring: profile.restoring,
1483
- building: profile.building,
1484
- integration: profile.integration,
1485
- storing: profile.storing,
1486
- additionalResolving: profile.additionalFactories,
1487
- additionalIntegration: profile.additionalIntegration,
1488
- // TODO remove this in webpack 6
1489
- factory: profile.factory,
1490
- // TODO remove this in webpack 6
1491
- dependencies: profile.additionalFactories
1492
- };
1493
- Object.assign(object, statsProfile);
1471
+ // assign fields directly to avoid an intermediate object + copy
1472
+ object.total =
1473
+ profile.factory +
1474
+ profile.restoring +
1475
+ profile.integration +
1476
+ profile.building +
1477
+ profile.storing;
1478
+ object.resolving = profile.factory;
1479
+ object.restoring = profile.restoring;
1480
+ object.building = profile.building;
1481
+ object.integration = profile.integration;
1482
+ object.storing = profile.storing;
1483
+ object.additionalResolving = profile.additionalFactories;
1484
+ object.additionalIntegration = profile.additionalIntegration;
1485
+ // TODO remove this in webpack 6
1486
+ object.factory = profile.factory;
1487
+ // TODO remove this in webpack 6
1488
+ object.dependencies = profile.additionalFactories;
1494
1489
  }
1495
1490
  },
1496
1491
  moduleIssuer: {
@@ -1499,12 +1494,9 @@ const SIMPLE_EXTRACTORS = {
1499
1494
  const compilation = /** @type {Compilation} */ (context.compilation);
1500
1495
  const { moduleGraph } = compilation;
1501
1496
  const profile = moduleGraph.getProfile(module);
1502
- /** @type {Partial<KnownStatsModuleIssuer>} */
1503
- const statsModuleIssuer = {
1504
- identifier: module.identifier(),
1505
- name: module.readableIdentifier(requestShortener)
1506
- };
1507
- Object.assign(object, statsModuleIssuer);
1497
+ // assign fields directly to avoid an intermediate object + copy per issuer
1498
+ object.identifier = module.identifier();
1499
+ object.name = module.readableIdentifier(requestShortener);
1508
1500
  if (profile) {
1509
1501
  object.profile = factory.create(`${type}.profile`, profile, context);
1510
1502
  }
@@ -1518,31 +1510,26 @@ const SIMPLE_EXTRACTORS = {
1518
1510
  const dep = reason.dependency;
1519
1511
  const moduleDep =
1520
1512
  dep && dep instanceof ModuleDependency ? dep : undefined;
1521
- /** @type {KnownStatsModuleReason} */
1522
- const statsModuleReason = {
1523
- moduleIdentifier: reason.originModule
1524
- ? reason.originModule.identifier()
1525
- : null,
1526
- module: reason.originModule
1527
- ? reason.originModule.readableIdentifier(requestShortener)
1528
- : null,
1529
- moduleName: reason.originModule
1530
- ? reason.originModule.readableIdentifier(requestShortener)
1531
- : null,
1532
- resolvedModuleIdentifier: reason.resolvedOriginModule
1533
- ? reason.resolvedOriginModule.identifier()
1534
- : null,
1535
- resolvedModule: reason.resolvedOriginModule
1536
- ? reason.resolvedOriginModule.readableIdentifier(requestShortener)
1537
- : null,
1538
- type: reason.dependency ? reason.dependency.type : null,
1539
- active: reason.isActive(runtime),
1540
- explanation: reason.explanation,
1541
- userRequest: (moduleDep && moduleDep.userRequest) || null
1542
- };
1543
- Object.assign(object, statsModuleReason);
1544
- if (reason.dependency) {
1545
- const locInfo = formatLocation(reason.dependency.loc);
1513
+ const { originModule, resolvedOriginModule } = reason;
1514
+ const originName = originModule
1515
+ ? originModule.readableIdentifier(requestShortener)
1516
+ : null;
1517
+ // assign fields directly to avoid an intermediate object + copy per reason
1518
+ object.moduleIdentifier = originModule ? originModule.identifier() : null;
1519
+ object.module = originName;
1520
+ object.moduleName = originName;
1521
+ object.resolvedModuleIdentifier = resolvedOriginModule
1522
+ ? resolvedOriginModule.identifier()
1523
+ : null;
1524
+ object.resolvedModule = resolvedOriginModule
1525
+ ? resolvedOriginModule.readableIdentifier(requestShortener)
1526
+ : null;
1527
+ object.type = dep ? dep.type : null;
1528
+ object.active = reason.isActive(runtime);
1529
+ object.explanation = reason.explanation;
1530
+ object.userRequest = (moduleDep && moduleDep.userRequest) || null;
1531
+ if (dep) {
1532
+ const locInfo = formatLocation(dep.loc);
1546
1533
  if (locInfo) {
1547
1534
  object.loc = locInfo;
1548
1535
  }
@@ -1561,29 +1548,26 @@ const SIMPLE_EXTRACTORS = {
1561
1548
  _: (object, chunk, { makePathsRelative, compilation: { chunkGraph } }) => {
1562
1549
  const childIdByOrder = chunk.getChildIdsByOrders(chunkGraph);
1563
1550
 
1564
- /** @type {KnownStatsChunk} */
1565
- const statsChunk = {
1566
- rendered: chunk.rendered,
1567
- initial: chunk.canBeInitial(),
1568
- entry: chunk.hasRuntime(),
1569
- recorded: AggressiveSplittingPlugin.wasChunkRecorded(chunk),
1570
- reason: chunk.chunkReason,
1571
- size: chunkGraph.getChunkModulesSize(chunk),
1572
- sizes: chunkGraph.getChunkModulesSizes(chunk),
1573
- names: chunk.name ? [chunk.name] : [],
1574
- idHints: [...chunk.idNameHints],
1575
- runtime:
1576
- chunk.runtime === undefined
1577
- ? undefined
1578
- : typeof chunk.runtime === "string"
1579
- ? [makePathsRelative(chunk.runtime)]
1580
- : Array.from(chunk.runtime.sort(), makePathsRelative),
1581
- files: [...chunk.files],
1582
- auxiliaryFiles: [...chunk.auxiliaryFiles].sort(compareIds),
1583
- hash: /** @type {string} */ (chunk.renderedHash),
1584
- childrenByOrder: childIdByOrder
1585
- };
1586
- Object.assign(object, statsChunk);
1551
+ // assign fields directly to avoid an intermediate object + copy per chunk
1552
+ object.rendered = chunk.rendered;
1553
+ object.initial = chunk.canBeInitial();
1554
+ object.entry = chunk.hasRuntime();
1555
+ object.recorded = AggressiveSplittingPlugin.wasChunkRecorded(chunk);
1556
+ object.reason = chunk.chunkReason;
1557
+ object.size = chunkGraph.getChunkModulesSize(chunk);
1558
+ object.sizes = chunkGraph.getChunkModulesSizes(chunk);
1559
+ object.names = chunk.name ? [chunk.name] : [];
1560
+ object.idHints = [...chunk.idNameHints];
1561
+ object.runtime =
1562
+ chunk.runtime === undefined
1563
+ ? undefined
1564
+ : typeof chunk.runtime === "string"
1565
+ ? [makePathsRelative(chunk.runtime)]
1566
+ : Array.from(chunk.runtime.sort(), makePathsRelative);
1567
+ object.files = [...chunk.files];
1568
+ object.auxiliaryFiles = [...chunk.auxiliaryFiles].sort(compareIds);
1569
+ object.hash = /** @type {string} */ (chunk.renderedHash);
1570
+ object.childrenByOrder = childIdByOrder;
1587
1571
  },
1588
1572
  ids: (object, chunk) => {
1589
1573
  object.id = /** @type {ChunkId} */ (chunk.id);
@@ -1660,17 +1644,16 @@ const SIMPLE_EXTRACTORS = {
1660
1644
  },
1661
1645
  chunkOrigin: {
1662
1646
  _: (object, origin, context, { requestShortener }) => {
1663
- /** @type {KnownStatsChunkOrigin} */
1664
- const statsChunkOrigin = {
1665
- module: origin.module ? origin.module.identifier() : "",
1666
- moduleIdentifier: origin.module ? origin.module.identifier() : "",
1667
- moduleName: origin.module
1668
- ? origin.module.readableIdentifier(requestShortener)
1669
- : "",
1670
- loc: formatLocation(origin.loc),
1671
- request: origin.request
1672
- };
1673
- Object.assign(object, statsChunkOrigin);
1647
+ const originModule = origin.module;
1648
+ const identifier = originModule ? originModule.identifier() : "";
1649
+ // assign fields directly to avoid an intermediate object + copy per origin
1650
+ object.module = identifier;
1651
+ object.moduleIdentifier = identifier;
1652
+ object.moduleName = originModule
1653
+ ? originModule.readableIdentifier(requestShortener)
1654
+ : "";
1655
+ object.loc = formatLocation(origin.loc);
1656
+ object.request = origin.request;
1674
1657
  },
1675
1658
  ids: (object, origin, { compilation: { chunkGraph } }) => {
1676
1659
  object.moduleId = origin.module
@@ -1691,13 +1674,16 @@ const SIMPLE_EXTRACTORS = {
1691
1674
  object.originName = origin.readableIdentifier(requestShortener);
1692
1675
  object.moduleIdentifier = module.identifier();
1693
1676
  object.moduleName = module.readableIdentifier(requestShortener);
1694
- const dependencies = [...moduleGraph.getIncomingConnections(module)]
1695
- .filter((c) => c.resolvedOriginModule === origin && c.dependency)
1696
- .map((c) => c.dependency);
1677
+ /** @type {Set<Dependency>} */
1678
+ const dependencies = new Set();
1679
+ for (const c of moduleGraph.getIncomingConnections(module)) {
1680
+ if (c.resolvedOriginModule === origin && c.dependency) {
1681
+ dependencies.add(c.dependency);
1682
+ }
1683
+ }
1697
1684
  object.dependencies = factory.create(
1698
1685
  `${type}.dependencies`,
1699
- /** @type {Dependency[]} */
1700
- ([...new Set(dependencies)]),
1686
+ [...dependencies],
1701
1687
  context
1702
1688
  );
1703
1689
  },
@@ -1749,17 +1735,50 @@ const FILTER_RESULTS = {
1749
1735
  }
1750
1736
  };
1751
1737
 
1738
+ // module sort selectors close over moduleGraph, so cache the built comparators per
1739
+ // moduleGraph (stable per compilation) instead of rebuilding them on every sort
1740
+ /** @type {WeakMap<ModuleGraph, Comparator<Module>[]>} */
1741
+ const modulesSorterCache = new WeakMap();
1742
+
1752
1743
  /** @type {Record<string, (comparators: Comparator<Module>[], context: StatsFactoryContext) => void>} */
1753
1744
  const MODULES_SORTER = {
1754
1745
  _: (comparators, { compilation: { moduleGraph } }) => {
1755
- comparators.push(
1756
- compareSelect((m) => moduleGraph.getDepth(m), compareNumbers),
1757
- compareSelect((m) => moduleGraph.getPreOrderIndex(m), compareNumbers),
1758
- compareSelect((m) => m.identifier(), compareIds)
1759
- );
1746
+ let cached = modulesSorterCache.get(moduleGraph);
1747
+ if (cached === undefined) {
1748
+ cached = [
1749
+ compareSelect((m) => moduleGraph.getDepth(m), compareNumbers),
1750
+ compareSelect((m) => moduleGraph.getPreOrderIndex(m), compareNumbers),
1751
+ compareSelect((m) => m.identifier(), compareIds)
1752
+ ];
1753
+ modulesSorterCache.set(moduleGraph, cached);
1754
+ }
1755
+ comparators.push(...cached);
1760
1756
  }
1761
1757
  };
1762
1758
 
1759
+ // reason comparators use only pure selectors, so build them once instead of per
1760
+ // module.reasons sort (which runs once per module and otherwise thrashes the caches)
1761
+ /** @type {Comparator<ModuleGraphConnection>[]} */
1762
+ const MODULE_REASONS_COMPARATORS = [
1763
+ compareSelect((x) => x.originModule, compareModulesByIdentifier),
1764
+ compareSelect((x) => x.resolvedOriginModule, compareModulesByIdentifier),
1765
+ compareSelect(
1766
+ (x) => x.dependency,
1767
+ concatComparators(
1768
+ compareSelect(
1769
+ /**
1770
+ * Handles the callback for this hook.
1771
+ * @param {Dependency} x dependency
1772
+ * @returns {DependencyLocation} location
1773
+ */
1774
+ (x) => x.loc,
1775
+ compareLocations
1776
+ ),
1777
+ compareSelect((x) => x.type, compareIds)
1778
+ )
1779
+ )
1780
+ ];
1781
+
1763
1782
  /**
1764
1783
  * @type {{
1765
1784
  * "compilation.chunks": Record<string, (comparators: Comparator<Chunk>[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void>,
@@ -1782,30 +1801,8 @@ const SORTERS = {
1782
1801
  "chunk.modules": MODULES_SORTER,
1783
1802
  "module.modules": MODULES_SORTER,
1784
1803
  "module.reasons": {
1785
- _: (comparators, _context) => {
1786
- comparators.push(
1787
- compareSelect((x) => x.originModule, compareModulesByIdentifier)
1788
- );
1789
- comparators.push(
1790
- compareSelect((x) => x.resolvedOriginModule, compareModulesByIdentifier)
1791
- );
1792
- comparators.push(
1793
- compareSelect(
1794
- (x) => x.dependency,
1795
- concatComparators(
1796
- compareSelect(
1797
- /**
1798
- * Handles the callback for this hook.
1799
- * @param {Dependency} x dependency
1800
- * @returns {DependencyLocation} location
1801
- */
1802
- (x) => x.loc,
1803
- compareLocations
1804
- ),
1805
- compareSelect((x) => x.type, compareIds)
1806
- )
1807
- )
1808
- );
1804
+ _: (comparators) => {
1805
+ comparators.push(...MODULE_REASONS_COMPARATORS);
1809
1806
  }
1810
1807
  },
1811
1808
  "chunk.origins": {
@@ -2588,6 +2585,17 @@ const sortOrderRegular = (field) => {
2588
2585
  return true;
2589
2586
  };
2590
2587
 
2588
+ /**
2589
+ * Returns zero.
2590
+ * @param {EXPECTED_ANY} a first
2591
+ * @param {EXPECTED_ANY} b second
2592
+ * @returns {-1 | 0 | 1} zero
2593
+ */
2594
+ const noSort = (a, b) => 0;
2595
+
2596
+ /** @type {Map<string, (a: EXPECTED_ANY, b: EXPECTED_ANY) => 0 | 1 | -1>} */
2597
+ const sortByFieldCache = new Map();
2598
+
2591
2599
  /**
2592
2600
  * Returns comparators.
2593
2601
  * @template T
@@ -2595,29 +2603,24 @@ const sortOrderRegular = (field) => {
2595
2603
  * @returns {(a: T, b: T) => 0 | 1 | -1} comparators
2596
2604
  */
2597
2605
  const sortByField = (field) => {
2598
- if (!field) {
2599
- /**
2600
- * Returns zero.
2601
- * @param {T} a first
2602
- * @param {T} b second
2603
- * @returns {-1 | 0 | 1} zero
2604
- */
2605
- const noSort = (a, b) => 0;
2606
- return noSort;
2607
- }
2606
+ if (!field) return noSort;
2607
+
2608
+ // memoize per field: the comparator (and its selector) is pure, so building it
2609
+ // once keeps compareSelect's cache warm instead of allocating a new entry per sort
2610
+ let sortFn = sortByFieldCache.get(field);
2611
+ if (sortFn !== undefined) return sortFn;
2608
2612
 
2609
2613
  const fieldKey = normalizeFieldKey(field);
2610
2614
 
2611
- let sortFn = compareSelect((m) => m[fieldKey], compareIds);
2615
+ sortFn = compareSelect((m) => m[fieldKey], compareIds);
2612
2616
 
2613
2617
  // if a field is prefixed with a "!" the sort is reversed!
2614
- const sortIsRegular = sortOrderRegular(field);
2615
-
2616
- if (!sortIsRegular) {
2618
+ if (!sortOrderRegular(field)) {
2617
2619
  const oldSortFn = sortFn;
2618
2620
  sortFn = (a, b) => oldSortFn(b, a);
2619
2621
  }
2620
2622
 
2623
+ sortByFieldCache.set(field, sortFn);
2621
2624
  return sortFn;
2622
2625
  };
2623
2626
 
@@ -2629,13 +2632,16 @@ const sortByField = (field) => {
2629
2632
  * }} AssetSorters
2630
2633
  */
2631
2634
 
2635
+ /** @type {Comparator<Asset>} */
2636
+ const compareAssetsByName = compareSelect((asset) => asset.name, compareIds);
2637
+
2632
2638
  /** @type {AssetSorters} */
2633
2639
  const ASSET_SORTERS = {
2634
2640
  assetsSort: (comparators, context, { assetsSort }) => {
2635
2641
  comparators.push(sortByField(assetsSort));
2636
2642
  },
2637
2643
  _: (comparators) => {
2638
- comparators.push(compareSelect((a) => a.name, compareIds));
2644
+ comparators.push(compareAssetsByName);
2639
2645
  }
2640
2646
  };
2641
2647