rollup 3.21.8 → 3.22.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.
package/dist/bin/rollup CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  /*
4
4
  @license
5
- Rollup.js v3.21.8
6
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
5
+ Rollup.js v3.22.0
6
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
7
7
 
8
8
  https://github.com/rollup/rollup
9
9
 
package/dist/es/rollup.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -16,7 +16,7 @@ import { lstat, realpath, readdir, readFile, mkdir, writeFile } from 'node:fs/pr
16
16
  import { EventEmitter } from 'node:events';
17
17
  import * as tty from 'tty';
18
18
 
19
- var version$1 = "3.21.8";
19
+ var version$1 = "3.22.0";
20
20
 
21
21
  const comma = ','.charCodeAt(0);
22
22
  const semicolon = ';'.charCodeAt(0);
@@ -13451,6 +13451,16 @@ class Module {
13451
13451
  this.addLocationToLogProps(properties, pos);
13452
13452
  return error(properties);
13453
13453
  }
13454
+ // sum up the length of all ast nodes that are included
13455
+ estimateSize() {
13456
+ let size = 0;
13457
+ for (const node of this.ast.body) {
13458
+ if (node.included) {
13459
+ size += node.end - node.start;
13460
+ }
13461
+ }
13462
+ return size;
13463
+ }
13454
13464
  getAllExportNames() {
13455
13465
  if (this.allExportNames) {
13456
13466
  return this.allExportNames;
@@ -15488,13 +15498,18 @@ class Chunk {
15488
15498
  }
15489
15499
  canModuleBeFacade(module, exposedVariables) {
15490
15500
  const moduleExportNamesByVariable = module.getExportNamesByVariable();
15501
+ // All exports of this chunk need to be exposed by the candidate module
15491
15502
  for (const exposedVariable of this.exports) {
15492
15503
  if (!moduleExportNamesByVariable.has(exposedVariable)) {
15493
15504
  return false;
15494
15505
  }
15495
15506
  }
15507
+ // Additionally, we need to expose namespaces of dynamic entries that are not the facade module and exports from other entry modules
15496
15508
  for (const exposedVariable of exposedVariables) {
15497
- if (!(moduleExportNamesByVariable.has(exposedVariable) || exposedVariable.module === module)) {
15509
+ if (!(exposedVariable.module === module ||
15510
+ moduleExportNamesByVariable.has(exposedVariable) ||
15511
+ (exposedVariable instanceof SyntheticNamedExportVariable &&
15512
+ moduleExportNamesByVariable.has(exposedVariable.getBaseVariable())))) {
15498
15513
  return false;
15499
15514
  }
15500
15515
  }
@@ -15549,7 +15564,10 @@ class Chunk {
15549
15564
  for (const module of entryModules) {
15550
15565
  if (module.preserveSignature) {
15551
15566
  for (const exportedVariable of module.getExportNamesByVariable().keys()) {
15552
- exposedVariables.add(exportedVariable);
15567
+ // We need to expose all entry exports from this chunk
15568
+ if (this.chunkByModule.get(exportedVariable.module) === this) {
15569
+ exposedVariables.add(exportedVariable);
15570
+ }
15553
15571
  }
15554
15572
  }
15555
15573
  }
@@ -16526,11 +16544,14 @@ function getChunkAssignments(entries, manualChunkAliasByEntry, minChunkSize) {
16526
16544
  const { chunkDefinitions, modulesInManualChunks } = getChunkDefinitionsFromManualChunks(manualChunkAliasByEntry);
16527
16545
  const { allEntries, dependentEntriesByModule, dynamicallyDependentEntriesByDynamicEntry, dynamicImportsByEntry } = analyzeModuleGraph(entries);
16528
16546
  // Each chunk is identified by its position in this array
16529
- const initialChunks = Object.values(getChunksBySignature(getModulesWithDependentEntries(dependentEntriesByModule, modulesInManualChunks)));
16547
+ const initialChunks = getChunksFromDependentEntries(getModulesWithDependentEntries(dependentEntriesByModule, modulesInManualChunks));
16530
16548
  // This mutates initialChunks but also clears
16531
16549
  // dynamicallyDependentEntriesByDynamicEntry as side effect
16532
16550
  removeUnnecessaryDependentEntries(initialChunks, dynamicallyDependentEntriesByDynamicEntry, dynamicImportsByEntry, allEntries);
16533
- chunkDefinitions.push(...createChunks(allEntries, getChunksBySignature(initialChunks), minChunkSize));
16551
+ chunkDefinitions.push(...getOptimizedChunks(getChunksFromDependentEntries(initialChunks), allEntries.length, minChunkSize).map(({ modules }) => ({
16552
+ alias: null,
16553
+ modules
16554
+ })));
16534
16555
  return chunkDefinitions;
16535
16556
  }
16536
16557
  function getChunkDefinitionsFromManualChunks(manualChunkAliasByEntry) {
@@ -16636,7 +16657,7 @@ function getDynamicallyDependentEntriesByDynamicEntry(dependentEntriesByModule,
16636
16657
  }
16637
16658
  return dynamicallyDependentEntriesByDynamicEntry;
16638
16659
  }
16639
- function getChunksBySignature(modulesWithDependentEntries) {
16660
+ function getChunksFromDependentEntries(modulesWithDependentEntries) {
16640
16661
  var _a;
16641
16662
  const chunkModules = Object.create(null);
16642
16663
  for (const { dependentEntries, modules } of modulesWithDependentEntries) {
@@ -16649,7 +16670,7 @@ function getChunksBySignature(modulesWithDependentEntries) {
16649
16670
  modules: []
16650
16671
  })).modules.push(...modules);
16651
16672
  }
16652
- return chunkModules;
16673
+ return Object.values(chunkModules);
16653
16674
  }
16654
16675
  function* getModulesWithDependentEntries(dependentEntriesByModule, modulesInManualChunks) {
16655
16676
  for (const [module, dependentEntries] of dependentEntriesByModule) {
@@ -16707,17 +16728,6 @@ function removeUnnecessaryDependentEntries(chunks, dynamicallyDependentEntriesBy
16707
16728
  chunkMask <<= 1n;
16708
16729
  }
16709
16730
  }
16710
- function createChunks(allEntries, chunkModulesBySignature, minChunkSize) {
16711
- return minChunkSize === 0
16712
- ? Object.values(chunkModulesBySignature).map(({ modules }) => ({
16713
- alias: null,
16714
- modules
16715
- }))
16716
- : getOptimizedChunks(chunkModulesBySignature, allEntries.length, minChunkSize).map(({ modules }) => ({
16717
- alias: null,
16718
- modules
16719
- }));
16720
- }
16721
16731
  /**
16722
16732
  * This function tries to get rid of small chunks by merging them with other
16723
16733
  * chunks.
@@ -16760,239 +16770,270 @@ function createChunks(allEntries, chunkModulesBySignature, minChunkSize) {
16760
16770
  * dependency side effects are AF.
16761
16771
  * For entry chunks, dependency and correlated side effects are the same.
16762
16772
  *
16763
- * With these concepts, merging chunks is allowed if the correlated side effects
16764
- * of each entry do not change. Thus, we are allowed to merge two chunks if
16773
+ * With these concepts, merging chunks is allowed if the correlated side
16774
+ * effects of each entry do not change. Thus, we are allowed to merge two
16775
+ * chunks if
16776
+ *
16765
16777
  * a) the dependency side effects of each chunk are a subset of the correlated
16766
16778
  * side effects of the other chunk, so no additional side effects are
16767
16779
  * triggered for any entry, or
16768
- * b) The signature of chunk A is a subset of the signature of chunk B while the
16769
- * dependency side effects of A are a subset of the correlated side effects
16770
- * of B. Because in that scenario, whenever A is loaded, B is loaded as well.
16771
- * But there are cases when B is loaded where A is not loaded. So if we merge
16772
- * the chunks, all dependency side effects of A will be added to the
16773
- * correlated side effects of B, and as the latter is not allowed to change,
16774
- * the former need to be a subset of the latter.
16780
+ * b) The dependent entry points of chunk A are a subset of the dependent entry
16781
+ * points of chunk B while the dependency side effects of A are a subset of
16782
+ * the correlated side effects of B. Because in that scenario, whenever A is
16783
+ * loaded, B is loaded as well. But there are cases when B is loaded where A
16784
+ * is not loaded. So if we merge the chunks, all dependency side effects of
16785
+ * A will be added to the correlated side effects of B, and as the latter is
16786
+ * not allowed to change, the former need to be a subset of the latter.
16775
16787
  *
16776
- * Another consideration when merging small chunks into other chunks is to avoid
16788
+ * Another consideration when merging small chunks into other chunks is to
16789
+ * avoid
16777
16790
  * that too much additional code is loaded. This is achieved when the dependent
16778
- * entries of the small chunk are a subset of the dependent entries of the other
16791
+ * entries of the small chunk are a subset of the dependent entries of the
16792
+ * other
16779
16793
  * chunk. Because then when the small chunk is loaded, the other chunk was
16780
16794
  * loaded/in memory anyway, so at most when the other chunk is loaded, the
16781
16795
  * additional size of the small chunk is loaded unnecessarily.
16782
16796
  *
16783
16797
  * So the algorithm performs merges in two passes:
16798
+ *
16784
16799
  * 1. First we try to merge small chunks A only into other chunks B if the
16785
16800
  * dependent entries of A are a subset of the dependent entries of B and the
16786
16801
  * dependency side effects of A are a subset of the correlated side effects
16787
16802
  * of B.
16788
16803
  * 2. Only then for all remaining small chunks, we look for arbitrary merges
16789
- * following the above rules (a) and (b), starting with the smallest chunks
16790
- * to look for possible merge targets.
16804
+ * following the rule (a), starting with the smallest chunks to look for
16805
+ * possible merge targets.
16791
16806
  */
16792
- // TODO instead of picking the "closest" chunk, we could actually use a
16793
- // technique similar to what we do for side effects to compare the size of the
16794
- // static dependencies that are not part of the correlated dependencies
16795
- function getOptimizedChunks(chunkModulesBySignature, numberOfEntries, minChunkSize) {
16807
+ function getOptimizedChunks(initialChunks, numberOfEntries, minChunkSize) {
16796
16808
  timeStart('optimize chunks', 3);
16797
- const chunkPartition = getPartitionedChunks(chunkModulesBySignature, numberOfEntries, minChunkSize);
16798
- console.log('Before eliminating small chunks, there were\n', Object.keys(chunkModulesBySignature).length, 'chunks, of which\n', chunkPartition.small.size, 'were below minChunkSize.');
16799
- if (chunkPartition.small.size > 0) {
16800
- mergeChunks(chunkPartition, minChunkSize);
16801
- }
16802
- console.log('After merging chunks,\n', chunkPartition.small.size + chunkPartition.big.size, 'chunks remain, of which\n', chunkPartition.small.size, 'are below minChunkSize.');
16809
+ const chunkPartition = getPartitionedChunks(initialChunks, numberOfEntries, minChunkSize);
16810
+ if (!chunkPartition) {
16811
+ timeEnd('optimize chunks', 3);
16812
+ return initialChunks; // the actual modules
16813
+ }
16814
+ minChunkSize > 1 &&
16815
+ console.log('Before eliminating small chunks, there were\n', initialChunks.length, 'chunks, of which\n', chunkPartition.small.size, 'were below minChunkSize.');
16816
+ mergeChunks(chunkPartition, minChunkSize);
16817
+ minChunkSize > 1 &&
16818
+ console.log('After merging chunks,\n', chunkPartition.small.size + chunkPartition.big.size, 'chunks remain, of which\n', chunkPartition.small.size, 'are below minChunkSize.');
16803
16819
  timeEnd('optimize chunks', 3);
16804
16820
  return [...chunkPartition.small, ...chunkPartition.big];
16805
16821
  }
16806
- function getPartitionedChunks(chunkModulesBySignature, numberOfEntries, minChunkSize) {
16822
+ function getPartitionedChunks(initialChunks, numberOfEntries, minChunkSize) {
16807
16823
  const smallChunks = [];
16808
16824
  const bigChunks = [];
16809
16825
  const chunkByModule = new Map();
16810
- const sideEffectsByEntry = [];
16811
- for (let index = 0; index < numberOfEntries; index++) {
16812
- sideEffectsByEntry.push(new Set());
16813
- }
16814
- for (const [signature, { dependentEntries, modules }] of Object.entries(chunkModulesBySignature)) {
16826
+ const sizeByAtom = [];
16827
+ let sideEffectAtoms = 0n;
16828
+ let containedAtoms = 1n;
16829
+ for (const { dependentEntries, modules } of initialChunks) {
16815
16830
  const chunkDescription = {
16816
- correlatedSideEffects: new Set(),
16831
+ containedAtoms,
16832
+ correlatedAtoms: 0n,
16817
16833
  dependencies: new Set(),
16818
16834
  dependentChunks: new Set(),
16819
16835
  dependentEntries,
16820
16836
  modules,
16821
16837
  pure: true,
16822
- sideEffects: new Set(),
16823
16838
  size: 0
16824
16839
  };
16825
16840
  let size = 0;
16826
16841
  let pure = true;
16827
16842
  for (const module of modules) {
16828
16843
  chunkByModule.set(module, chunkDescription);
16829
- pure && (pure = !module.hasEffects());
16830
16844
  // Unfortunately, we cannot take tree-shaking into account here because
16831
- // rendering did not happen yet
16832
- size += module.originalCode.length;
16845
+ // rendering did not happen yet, but we can detect empty modules
16846
+ if (module.isIncluded()) {
16847
+ pure && (pure = !module.hasEffects());
16848
+ // we use a trivial size for the default minChunkSize to improve
16849
+ // performance
16850
+ size += minChunkSize > 1 ? module.estimateSize() : 1;
16851
+ }
16833
16852
  }
16834
16853
  chunkDescription.pure = pure;
16835
16854
  chunkDescription.size = size;
16855
+ sizeByAtom.push(size);
16836
16856
  if (!pure) {
16837
- for (const entryIndex of dependentEntries) {
16838
- sideEffectsByEntry[entryIndex].add(signature);
16839
- }
16840
- // In the beginning, each chunk is only its own side effect. After
16841
- // merging, additional side effects can accumulate.
16842
- chunkDescription.sideEffects.add(signature);
16857
+ sideEffectAtoms |= containedAtoms;
16843
16858
  }
16844
16859
  (size < minChunkSize ? smallChunks : bigChunks).push(chunkDescription);
16860
+ containedAtoms <<= 1n;
16845
16861
  }
16846
- sortChunksAndAddDependenciesAndEffects([bigChunks, smallChunks], chunkByModule, sideEffectsByEntry);
16862
+ // If there are no small chunks, we will not optimize
16863
+ if (smallChunks.length === 0) {
16864
+ return null;
16865
+ }
16866
+ sideEffectAtoms |= addChunkDependenciesAndAtomsAndGetSideEffectAtoms([bigChunks, smallChunks], chunkByModule, numberOfEntries, containedAtoms);
16847
16867
  return {
16848
16868
  big: new Set(bigChunks),
16869
+ sideEffectAtoms,
16870
+ sizeByAtom,
16849
16871
  small: new Set(smallChunks)
16850
16872
  };
16851
16873
  }
16852
- function sortChunksAndAddDependenciesAndEffects(chunkLists, chunkByModule, sideEffectsByEntry) {
16874
+ function mergeChunks(chunkPartition, minChunkSize) {
16875
+ const { small } = chunkPartition;
16876
+ for (const mergedChunk of small) {
16877
+ const bestTargetChunk = findBestMergeTarget(mergedChunk, chunkPartition,
16878
+ // In the default case, we do not accept size increases
16879
+ minChunkSize <= 1 ? 1 : Infinity);
16880
+ if (bestTargetChunk) {
16881
+ const { containedAtoms, correlatedAtoms, modules, pure, size } = mergedChunk;
16882
+ small.delete(mergedChunk);
16883
+ getChunksInPartition(bestTargetChunk, minChunkSize, chunkPartition).delete(bestTargetChunk);
16884
+ bestTargetChunk.modules.push(...modules);
16885
+ bestTargetChunk.size += size;
16886
+ bestTargetChunk.pure && (bestTargetChunk.pure = pure);
16887
+ const { dependencies, dependentChunks, dependentEntries } = bestTargetChunk;
16888
+ bestTargetChunk.correlatedAtoms &= correlatedAtoms;
16889
+ bestTargetChunk.containedAtoms |= containedAtoms;
16890
+ for (const entry of mergedChunk.dependentEntries) {
16891
+ dependentEntries.add(entry);
16892
+ }
16893
+ for (const dependency of mergedChunk.dependencies) {
16894
+ dependencies.add(dependency);
16895
+ dependency.dependentChunks.delete(mergedChunk);
16896
+ dependency.dependentChunks.add(bestTargetChunk);
16897
+ }
16898
+ for (const dependentChunk of mergedChunk.dependentChunks) {
16899
+ dependentChunks.add(dependentChunk);
16900
+ dependentChunk.dependencies.delete(mergedChunk);
16901
+ dependentChunk.dependencies.add(bestTargetChunk);
16902
+ }
16903
+ dependencies.delete(bestTargetChunk);
16904
+ dependentChunks.delete(bestTargetChunk);
16905
+ getChunksInPartition(bestTargetChunk, minChunkSize, chunkPartition).add(bestTargetChunk);
16906
+ }
16907
+ }
16908
+ }
16909
+ function addChunkDependenciesAndAtomsAndGetSideEffectAtoms(chunkLists, chunkByModule, numberOfEntries, nextAtomSignature) {
16910
+ const signatureByExternalModule = new Map();
16911
+ let sideEffectAtoms = 0n;
16912
+ const atomsByEntry = [];
16913
+ for (let index = 0; index < numberOfEntries; index++) {
16914
+ atomsByEntry.push(0n);
16915
+ }
16853
16916
  for (const chunks of chunkLists) {
16854
16917
  chunks.sort(compareChunkSize);
16855
16918
  for (const chunk of chunks) {
16856
- const { dependencies, modules, correlatedSideEffects, dependentEntries } = chunk;
16919
+ const { dependencies, dependentEntries, modules } = chunk;
16857
16920
  for (const module of modules) {
16858
16921
  for (const dependency of module.getDependenciesToBeIncluded()) {
16859
- const dependencyChunk = chunkByModule.get(dependency);
16860
- if (dependencyChunk && dependencyChunk !== chunk) {
16861
- dependencies.add(dependencyChunk);
16862
- dependencyChunk.dependentChunks.add(chunk);
16863
- }
16864
- }
16865
- }
16866
- let firstEntry = true;
16867
- // Correlated side effects is the intersection of all entry side effects
16868
- for (const entryIndex of dependentEntries) {
16869
- const entryEffects = sideEffectsByEntry[entryIndex];
16870
- if (firstEntry) {
16871
- for (const sideEffect of entryEffects) {
16872
- correlatedSideEffects.add(sideEffect);
16922
+ if (dependency instanceof ExternalModule) {
16923
+ if (dependency.info.moduleSideEffects) {
16924
+ chunk.containedAtoms |= getOrCreate(signatureByExternalModule, dependency, () => {
16925
+ const signature = nextAtomSignature;
16926
+ nextAtomSignature <<= 1n;
16927
+ sideEffectAtoms |= signature;
16928
+ return signature;
16929
+ });
16930
+ }
16873
16931
  }
16874
- firstEntry = false;
16875
- }
16876
- else {
16877
- for (const sideEffect of correlatedSideEffects) {
16878
- if (!entryEffects.has(sideEffect)) {
16879
- correlatedSideEffects.delete(sideEffect);
16932
+ else {
16933
+ const dependencyChunk = chunkByModule.get(dependency);
16934
+ if (dependencyChunk && dependencyChunk !== chunk) {
16935
+ dependencies.add(dependencyChunk);
16936
+ dependencyChunk.dependentChunks.add(chunk);
16880
16937
  }
16881
16938
  }
16882
16939
  }
16883
16940
  }
16941
+ const { containedAtoms } = chunk;
16942
+ for (const entryIndex of dependentEntries) {
16943
+ atomsByEntry[entryIndex] |= containedAtoms;
16944
+ }
16884
16945
  }
16885
16946
  }
16886
- }
16887
- function compareChunkSize({ size: sizeA }, { size: sizeB }) {
16888
- return sizeA - sizeB;
16889
- }
16890
- function mergeChunks(chunkPartition, minChunkSize) {
16891
- for (const allowArbitraryMerges of [false, true]) {
16892
- for (const mergedChunk of chunkPartition.small) {
16893
- let closestChunk = null;
16894
- let closestChunkDistance = Infinity;
16895
- const { modules, pure, size } = mergedChunk;
16896
- for (const targetChunk of concatLazy([chunkPartition.small, chunkPartition.big])) {
16897
- if (mergedChunk === targetChunk)
16898
- continue;
16899
- // If both chunks are small, we also allow for unrelated merges during
16900
- // the first pass
16901
- const onlySubsetMerge = !allowArbitraryMerges && targetChunk.size >= minChunkSize;
16902
- const distance = getChunkEntryDistance(mergedChunk, targetChunk, onlySubsetMerge);
16903
- if (distance < closestChunkDistance &&
16904
- isValidMerge(mergedChunk, targetChunk, onlySubsetMerge)) {
16905
- closestChunk = targetChunk;
16906
- closestChunkDistance = distance;
16907
- }
16908
- }
16909
- if (closestChunk) {
16910
- chunkPartition.small.delete(mergedChunk);
16911
- getChunksInPartition(closestChunk, minChunkSize, chunkPartition).delete(closestChunk);
16912
- closestChunk.modules.push(...modules);
16913
- closestChunk.size += size;
16914
- closestChunk.pure && (closestChunk.pure = pure);
16915
- const { correlatedSideEffects, dependencies, dependentChunks, dependentEntries, sideEffects } = closestChunk;
16916
- for (const sideEffect of correlatedSideEffects) {
16917
- if (!mergedChunk.correlatedSideEffects.has(sideEffect)) {
16918
- correlatedSideEffects.delete(sideEffect);
16919
- }
16920
- }
16921
- for (const entry of mergedChunk.dependentEntries) {
16922
- dependentEntries.add(entry);
16923
- }
16924
- for (const sideEffect of mergedChunk.sideEffects) {
16925
- sideEffects.add(sideEffect);
16926
- }
16927
- for (const dependency of mergedChunk.dependencies) {
16928
- dependencies.add(dependency);
16929
- dependency.dependentChunks.delete(mergedChunk);
16930
- dependency.dependentChunks.add(closestChunk);
16931
- }
16932
- for (const dependentChunk of mergedChunk.dependentChunks) {
16933
- dependentChunks.add(dependentChunk);
16934
- dependentChunk.dependencies.delete(mergedChunk);
16935
- dependentChunk.dependencies.add(closestChunk);
16936
- }
16937
- dependencies.delete(closestChunk);
16938
- dependentChunks.delete(closestChunk);
16939
- getChunksInPartition(closestChunk, minChunkSize, chunkPartition).add(closestChunk);
16947
+ for (const chunks of chunkLists) {
16948
+ for (const chunk of chunks) {
16949
+ const { dependentEntries } = chunk;
16950
+ // Correlated atoms are the intersection of all entry atoms
16951
+ chunk.correlatedAtoms = -1n;
16952
+ for (const entryIndex of dependentEntries) {
16953
+ chunk.correlatedAtoms &= atomsByEntry[entryIndex];
16940
16954
  }
16941
16955
  }
16942
16956
  }
16957
+ return sideEffectAtoms;
16943
16958
  }
16944
- // Merging will not produce cycles if none of the direct non-merged dependencies
16945
- // of a chunk have the other chunk as a transitive dependency
16946
- function isValidMerge(mergedChunk, targetChunk, onlySubsetMerge) {
16947
- return !(hasTransitiveDependencyOrNonCorrelatedSideEffect(mergedChunk, targetChunk, true) ||
16948
- hasTransitiveDependencyOrNonCorrelatedSideEffect(targetChunk, mergedChunk, !onlySubsetMerge));
16949
- }
16950
- function hasTransitiveDependencyOrNonCorrelatedSideEffect(dependentChunk, dependencyChunk, checkSideEffects) {
16951
- const { correlatedSideEffects } = dependencyChunk;
16952
- if (checkSideEffects) {
16953
- for (const sideEffect of dependentChunk.sideEffects) {
16954
- if (!correlatedSideEffects.has(sideEffect)) {
16955
- return true;
16956
- }
16959
+ function findBestMergeTarget(mergedChunk, { big, sideEffectAtoms, sizeByAtom, small }, smallestAdditionalSize) {
16960
+ let bestTargetChunk = null;
16961
+ // In the default case, we do not accept size increases
16962
+ for (const targetChunk of concatLazy([small, big])) {
16963
+ if (mergedChunk === targetChunk)
16964
+ continue;
16965
+ const additionalSizeAfterMerge = getAdditionalSizeAfterMerge(mergedChunk, targetChunk, smallestAdditionalSize, sideEffectAtoms, sizeByAtom);
16966
+ if (additionalSizeAfterMerge < smallestAdditionalSize) {
16967
+ bestTargetChunk = targetChunk;
16968
+ if (additionalSizeAfterMerge === 0)
16969
+ break;
16970
+ smallestAdditionalSize = additionalSizeAfterMerge;
16957
16971
  }
16958
16972
  }
16973
+ return bestTargetChunk;
16974
+ }
16975
+ function getChunksInPartition(chunk, minChunkSize, chunkPartition) {
16976
+ return chunk.size < minChunkSize ? chunkPartition.small : chunkPartition.big;
16977
+ }
16978
+ function compareChunkSize({ size: sizeA }, { size: sizeB }) {
16979
+ return sizeA - sizeB;
16980
+ }
16981
+ /**
16982
+ * Determine the additional unused code size that would be added by merging the
16983
+ * two chunks. This is not an exact measurement but rather an upper bound. If
16984
+ * the merge produces cycles or adds non-correlated side effects, `Infinity`
16985
+ * is returned.
16986
+ * Merging will not produce cycles if none of the direct non-merged
16987
+ * dependencies of a chunk have the other chunk as a transitive dependency.
16988
+ */
16989
+ function getAdditionalSizeAfterMerge(mergedChunk, targetChunk,
16990
+ // The maximum additional unused code size allowed to be added by the merge,
16991
+ // taking dependencies into account, needs to be below this number
16992
+ currentAdditionalSize, sideEffectAtoms, sizeByAtom) {
16993
+ const firstSize = getAdditionalSizeIfNoTransitiveDependencyOrNonCorrelatedSideEffect(mergedChunk, targetChunk, currentAdditionalSize, sideEffectAtoms, sizeByAtom);
16994
+ return firstSize < currentAdditionalSize
16995
+ ? firstSize +
16996
+ getAdditionalSizeIfNoTransitiveDependencyOrNonCorrelatedSideEffect(targetChunk, mergedChunk, currentAdditionalSize - firstSize, sideEffectAtoms, sizeByAtom)
16997
+ : Infinity;
16998
+ }
16999
+ function getAdditionalSizeIfNoTransitiveDependencyOrNonCorrelatedSideEffect(dependentChunk, dependencyChunk, currentAdditionalSize, sideEffectAtoms, sizeByAtom) {
17000
+ const { correlatedAtoms } = dependencyChunk;
17001
+ let dependencyAtoms = dependentChunk.containedAtoms;
17002
+ const dependentContainedSideEffects = dependencyAtoms & sideEffectAtoms;
17003
+ if ((correlatedAtoms & dependentContainedSideEffects) !== dependentContainedSideEffects) {
17004
+ return Infinity;
17005
+ }
16959
17006
  const chunksToCheck = new Set(dependentChunk.dependencies);
16960
- for (const { dependencies, sideEffects } of chunksToCheck) {
17007
+ for (const { dependencies, containedAtoms } of chunksToCheck) {
17008
+ dependencyAtoms |= containedAtoms;
17009
+ const containedSideEffects = containedAtoms & sideEffectAtoms;
17010
+ if ((correlatedAtoms & containedSideEffects) !== containedSideEffects) {
17011
+ return Infinity;
17012
+ }
16961
17013
  for (const dependency of dependencies) {
16962
17014
  if (dependency === dependencyChunk) {
16963
- return true;
17015
+ return Infinity;
16964
17016
  }
16965
17017
  chunksToCheck.add(dependency);
16966
17018
  }
16967
- if (checkSideEffects) {
16968
- for (const sideEffect of sideEffects) {
16969
- if (!correlatedSideEffects.has(sideEffect)) {
16970
- return true;
16971
- }
16972
- }
16973
- }
16974
17019
  }
16975
- return false;
16976
- }
16977
- function getChunksInPartition(chunk, minChunkSize, chunkPartition) {
16978
- return chunk.size < minChunkSize ? chunkPartition.small : chunkPartition.big;
17020
+ return getAtomsSizeIfBelowLimit(dependencyAtoms & ~correlatedAtoms, currentAdditionalSize, sizeByAtom);
16979
17021
  }
16980
- function getChunkEntryDistance({ dependentEntries: sourceEntries }, { dependentEntries: targetEntries }, enforceSubest) {
16981
- let distance = 0;
16982
- for (const entryIndex of targetEntries) {
16983
- if (!sourceEntries.has(entryIndex)) {
16984
- distance++;
17022
+ function getAtomsSizeIfBelowLimit(atoms, currentAdditionalSize, sizeByAtom) {
17023
+ let size = 0;
17024
+ let atomIndex = 0;
17025
+ let atomSignature = 1n;
17026
+ const { length } = sizeByAtom;
17027
+ for (; atomIndex < length; atomIndex++) {
17028
+ if ((atoms & atomSignature) === atomSignature) {
17029
+ size += sizeByAtom[atomIndex];
16985
17030
  }
16986
- }
16987
- for (const entryIndex of sourceEntries) {
16988
- if (!targetEntries.has(entryIndex)) {
16989
- if (enforceSubest) {
16990
- return Infinity;
16991
- }
16992
- distance++;
17031
+ atomSignature <<= 1n;
17032
+ if (size >= currentAdditionalSize) {
17033
+ return Infinity;
16993
17034
  }
16994
17035
  }
16995
- return distance;
17036
+ return size;
16996
17037
  }
16997
17038
 
16998
17039
  // ported from https://github.com/substack/node-commondir
@@ -25465,7 +25506,7 @@ async function normalizeOutputOptions(config, inputOptions, unsetInputOptions) {
25465
25506
  entryFileNames: getEntryFileNames(config, unsetOptions),
25466
25507
  esModule: config.esModule ?? 'if-default-prop',
25467
25508
  experimentalDeepDynamicChunkOptimization: getExperimentalDeepDynamicChunkOptimization(config, inputOptions),
25468
- experimentalMinChunkSize: config.experimentalMinChunkSize || 0,
25509
+ experimentalMinChunkSize: config.experimentalMinChunkSize ?? 1,
25469
25510
  exports: getExports(config, unsetOptions),
25470
25511
  extend: config.extend || false,
25471
25512
  externalImportAssertions: config.externalImportAssertions ?? true,
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
package/dist/rollup.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -31,7 +31,7 @@ function _interopNamespaceDefault(e) {
31
31
 
32
32
  const tty__namespace = /*#__PURE__*/_interopNamespaceDefault(tty);
33
33
 
34
- var version$1 = "3.21.8";
34
+ var version$1 = "3.22.0";
35
35
 
36
36
  function ensureArray$1(items) {
37
37
  if (Array.isArray(items)) {
@@ -13946,6 +13946,16 @@ class Module {
13946
13946
  this.addLocationToLogProps(properties, pos);
13947
13947
  return error(properties);
13948
13948
  }
13949
+ // sum up the length of all ast nodes that are included
13950
+ estimateSize() {
13951
+ let size = 0;
13952
+ for (const node of this.ast.body) {
13953
+ if (node.included) {
13954
+ size += node.end - node.start;
13955
+ }
13956
+ }
13957
+ return size;
13958
+ }
13949
13959
  getAllExportNames() {
13950
13960
  if (this.allExportNames) {
13951
13961
  return this.allExportNames;
@@ -15983,13 +15993,18 @@ class Chunk {
15983
15993
  }
15984
15994
  canModuleBeFacade(module, exposedVariables) {
15985
15995
  const moduleExportNamesByVariable = module.getExportNamesByVariable();
15996
+ // All exports of this chunk need to be exposed by the candidate module
15986
15997
  for (const exposedVariable of this.exports) {
15987
15998
  if (!moduleExportNamesByVariable.has(exposedVariable)) {
15988
15999
  return false;
15989
16000
  }
15990
16001
  }
16002
+ // Additionally, we need to expose namespaces of dynamic entries that are not the facade module and exports from other entry modules
15991
16003
  for (const exposedVariable of exposedVariables) {
15992
- if (!(moduleExportNamesByVariable.has(exposedVariable) || exposedVariable.module === module)) {
16004
+ if (!(exposedVariable.module === module ||
16005
+ moduleExportNamesByVariable.has(exposedVariable) ||
16006
+ (exposedVariable instanceof SyntheticNamedExportVariable &&
16007
+ moduleExportNamesByVariable.has(exposedVariable.getBaseVariable())))) {
15993
16008
  return false;
15994
16009
  }
15995
16010
  }
@@ -16044,7 +16059,10 @@ class Chunk {
16044
16059
  for (const module of entryModules) {
16045
16060
  if (module.preserveSignature) {
16046
16061
  for (const exportedVariable of module.getExportNamesByVariable().keys()) {
16047
- exposedVariables.add(exportedVariable);
16062
+ // We need to expose all entry exports from this chunk
16063
+ if (this.chunkByModule.get(exportedVariable.module) === this) {
16064
+ exposedVariables.add(exportedVariable);
16065
+ }
16048
16066
  }
16049
16067
  }
16050
16068
  }
@@ -17021,11 +17039,14 @@ function getChunkAssignments(entries, manualChunkAliasByEntry, minChunkSize) {
17021
17039
  const { chunkDefinitions, modulesInManualChunks } = getChunkDefinitionsFromManualChunks(manualChunkAliasByEntry);
17022
17040
  const { allEntries, dependentEntriesByModule, dynamicallyDependentEntriesByDynamicEntry, dynamicImportsByEntry } = analyzeModuleGraph(entries);
17023
17041
  // Each chunk is identified by its position in this array
17024
- const initialChunks = Object.values(getChunksBySignature(getModulesWithDependentEntries(dependentEntriesByModule, modulesInManualChunks)));
17042
+ const initialChunks = getChunksFromDependentEntries(getModulesWithDependentEntries(dependentEntriesByModule, modulesInManualChunks));
17025
17043
  // This mutates initialChunks but also clears
17026
17044
  // dynamicallyDependentEntriesByDynamicEntry as side effect
17027
17045
  removeUnnecessaryDependentEntries(initialChunks, dynamicallyDependentEntriesByDynamicEntry, dynamicImportsByEntry, allEntries);
17028
- chunkDefinitions.push(...createChunks(allEntries, getChunksBySignature(initialChunks), minChunkSize));
17046
+ chunkDefinitions.push(...getOptimizedChunks(getChunksFromDependentEntries(initialChunks), allEntries.length, minChunkSize).map(({ modules }) => ({
17047
+ alias: null,
17048
+ modules
17049
+ })));
17029
17050
  return chunkDefinitions;
17030
17051
  }
17031
17052
  function getChunkDefinitionsFromManualChunks(manualChunkAliasByEntry) {
@@ -17131,7 +17152,7 @@ function getDynamicallyDependentEntriesByDynamicEntry(dependentEntriesByModule,
17131
17152
  }
17132
17153
  return dynamicallyDependentEntriesByDynamicEntry;
17133
17154
  }
17134
- function getChunksBySignature(modulesWithDependentEntries) {
17155
+ function getChunksFromDependentEntries(modulesWithDependentEntries) {
17135
17156
  var _a;
17136
17157
  const chunkModules = Object.create(null);
17137
17158
  for (const { dependentEntries, modules } of modulesWithDependentEntries) {
@@ -17144,7 +17165,7 @@ function getChunksBySignature(modulesWithDependentEntries) {
17144
17165
  modules: []
17145
17166
  })).modules.push(...modules);
17146
17167
  }
17147
- return chunkModules;
17168
+ return Object.values(chunkModules);
17148
17169
  }
17149
17170
  function* getModulesWithDependentEntries(dependentEntriesByModule, modulesInManualChunks) {
17150
17171
  for (const [module, dependentEntries] of dependentEntriesByModule) {
@@ -17202,17 +17223,6 @@ function removeUnnecessaryDependentEntries(chunks, dynamicallyDependentEntriesBy
17202
17223
  chunkMask <<= 1n;
17203
17224
  }
17204
17225
  }
17205
- function createChunks(allEntries, chunkModulesBySignature, minChunkSize) {
17206
- return minChunkSize === 0
17207
- ? Object.values(chunkModulesBySignature).map(({ modules }) => ({
17208
- alias: null,
17209
- modules
17210
- }))
17211
- : getOptimizedChunks(chunkModulesBySignature, allEntries.length, minChunkSize).map(({ modules }) => ({
17212
- alias: null,
17213
- modules
17214
- }));
17215
- }
17216
17226
  /**
17217
17227
  * This function tries to get rid of small chunks by merging them with other
17218
17228
  * chunks.
@@ -17255,239 +17265,270 @@ function createChunks(allEntries, chunkModulesBySignature, minChunkSize) {
17255
17265
  * dependency side effects are AF.
17256
17266
  * For entry chunks, dependency and correlated side effects are the same.
17257
17267
  *
17258
- * With these concepts, merging chunks is allowed if the correlated side effects
17259
- * of each entry do not change. Thus, we are allowed to merge two chunks if
17268
+ * With these concepts, merging chunks is allowed if the correlated side
17269
+ * effects of each entry do not change. Thus, we are allowed to merge two
17270
+ * chunks if
17271
+ *
17260
17272
  * a) the dependency side effects of each chunk are a subset of the correlated
17261
17273
  * side effects of the other chunk, so no additional side effects are
17262
17274
  * triggered for any entry, or
17263
- * b) The signature of chunk A is a subset of the signature of chunk B while the
17264
- * dependency side effects of A are a subset of the correlated side effects
17265
- * of B. Because in that scenario, whenever A is loaded, B is loaded as well.
17266
- * But there are cases when B is loaded where A is not loaded. So if we merge
17267
- * the chunks, all dependency side effects of A will be added to the
17268
- * correlated side effects of B, and as the latter is not allowed to change,
17269
- * the former need to be a subset of the latter.
17275
+ * b) The dependent entry points of chunk A are a subset of the dependent entry
17276
+ * points of chunk B while the dependency side effects of A are a subset of
17277
+ * the correlated side effects of B. Because in that scenario, whenever A is
17278
+ * loaded, B is loaded as well. But there are cases when B is loaded where A
17279
+ * is not loaded. So if we merge the chunks, all dependency side effects of
17280
+ * A will be added to the correlated side effects of B, and as the latter is
17281
+ * not allowed to change, the former need to be a subset of the latter.
17270
17282
  *
17271
- * Another consideration when merging small chunks into other chunks is to avoid
17283
+ * Another consideration when merging small chunks into other chunks is to
17284
+ * avoid
17272
17285
  * that too much additional code is loaded. This is achieved when the dependent
17273
- * entries of the small chunk are a subset of the dependent entries of the other
17286
+ * entries of the small chunk are a subset of the dependent entries of the
17287
+ * other
17274
17288
  * chunk. Because then when the small chunk is loaded, the other chunk was
17275
17289
  * loaded/in memory anyway, so at most when the other chunk is loaded, the
17276
17290
  * additional size of the small chunk is loaded unnecessarily.
17277
17291
  *
17278
17292
  * So the algorithm performs merges in two passes:
17293
+ *
17279
17294
  * 1. First we try to merge small chunks A only into other chunks B if the
17280
17295
  * dependent entries of A are a subset of the dependent entries of B and the
17281
17296
  * dependency side effects of A are a subset of the correlated side effects
17282
17297
  * of B.
17283
17298
  * 2. Only then for all remaining small chunks, we look for arbitrary merges
17284
- * following the above rules (a) and (b), starting with the smallest chunks
17285
- * to look for possible merge targets.
17299
+ * following the rule (a), starting with the smallest chunks to look for
17300
+ * possible merge targets.
17286
17301
  */
17287
- // TODO instead of picking the "closest" chunk, we could actually use a
17288
- // technique similar to what we do for side effects to compare the size of the
17289
- // static dependencies that are not part of the correlated dependencies
17290
- function getOptimizedChunks(chunkModulesBySignature, numberOfEntries, minChunkSize) {
17302
+ function getOptimizedChunks(initialChunks, numberOfEntries, minChunkSize) {
17291
17303
  timeStart('optimize chunks', 3);
17292
- const chunkPartition = getPartitionedChunks(chunkModulesBySignature, numberOfEntries, minChunkSize);
17293
- console.log('Before eliminating small chunks, there were\n', Object.keys(chunkModulesBySignature).length, 'chunks, of which\n', chunkPartition.small.size, 'were below minChunkSize.');
17294
- if (chunkPartition.small.size > 0) {
17295
- mergeChunks(chunkPartition, minChunkSize);
17296
- }
17297
- console.log('After merging chunks,\n', chunkPartition.small.size + chunkPartition.big.size, 'chunks remain, of which\n', chunkPartition.small.size, 'are below minChunkSize.');
17304
+ const chunkPartition = getPartitionedChunks(initialChunks, numberOfEntries, minChunkSize);
17305
+ if (!chunkPartition) {
17306
+ timeEnd('optimize chunks', 3);
17307
+ return initialChunks; // the actual modules
17308
+ }
17309
+ minChunkSize > 1 &&
17310
+ console.log('Before eliminating small chunks, there were\n', initialChunks.length, 'chunks, of which\n', chunkPartition.small.size, 'were below minChunkSize.');
17311
+ mergeChunks(chunkPartition, minChunkSize);
17312
+ minChunkSize > 1 &&
17313
+ console.log('After merging chunks,\n', chunkPartition.small.size + chunkPartition.big.size, 'chunks remain, of which\n', chunkPartition.small.size, 'are below minChunkSize.');
17298
17314
  timeEnd('optimize chunks', 3);
17299
17315
  return [...chunkPartition.small, ...chunkPartition.big];
17300
17316
  }
17301
- function getPartitionedChunks(chunkModulesBySignature, numberOfEntries, minChunkSize) {
17317
+ function getPartitionedChunks(initialChunks, numberOfEntries, minChunkSize) {
17302
17318
  const smallChunks = [];
17303
17319
  const bigChunks = [];
17304
17320
  const chunkByModule = new Map();
17305
- const sideEffectsByEntry = [];
17306
- for (let index = 0; index < numberOfEntries; index++) {
17307
- sideEffectsByEntry.push(new Set());
17308
- }
17309
- for (const [signature, { dependentEntries, modules }] of Object.entries(chunkModulesBySignature)) {
17321
+ const sizeByAtom = [];
17322
+ let sideEffectAtoms = 0n;
17323
+ let containedAtoms = 1n;
17324
+ for (const { dependentEntries, modules } of initialChunks) {
17310
17325
  const chunkDescription = {
17311
- correlatedSideEffects: new Set(),
17326
+ containedAtoms,
17327
+ correlatedAtoms: 0n,
17312
17328
  dependencies: new Set(),
17313
17329
  dependentChunks: new Set(),
17314
17330
  dependentEntries,
17315
17331
  modules,
17316
17332
  pure: true,
17317
- sideEffects: new Set(),
17318
17333
  size: 0
17319
17334
  };
17320
17335
  let size = 0;
17321
17336
  let pure = true;
17322
17337
  for (const module of modules) {
17323
17338
  chunkByModule.set(module, chunkDescription);
17324
- pure && (pure = !module.hasEffects());
17325
17339
  // Unfortunately, we cannot take tree-shaking into account here because
17326
- // rendering did not happen yet
17327
- size += module.originalCode.length;
17340
+ // rendering did not happen yet, but we can detect empty modules
17341
+ if (module.isIncluded()) {
17342
+ pure && (pure = !module.hasEffects());
17343
+ // we use a trivial size for the default minChunkSize to improve
17344
+ // performance
17345
+ size += minChunkSize > 1 ? module.estimateSize() : 1;
17346
+ }
17328
17347
  }
17329
17348
  chunkDescription.pure = pure;
17330
17349
  chunkDescription.size = size;
17350
+ sizeByAtom.push(size);
17331
17351
  if (!pure) {
17332
- for (const entryIndex of dependentEntries) {
17333
- sideEffectsByEntry[entryIndex].add(signature);
17334
- }
17335
- // In the beginning, each chunk is only its own side effect. After
17336
- // merging, additional side effects can accumulate.
17337
- chunkDescription.sideEffects.add(signature);
17352
+ sideEffectAtoms |= containedAtoms;
17338
17353
  }
17339
17354
  (size < minChunkSize ? smallChunks : bigChunks).push(chunkDescription);
17355
+ containedAtoms <<= 1n;
17340
17356
  }
17341
- sortChunksAndAddDependenciesAndEffects([bigChunks, smallChunks], chunkByModule, sideEffectsByEntry);
17357
+ // If there are no small chunks, we will not optimize
17358
+ if (smallChunks.length === 0) {
17359
+ return null;
17360
+ }
17361
+ sideEffectAtoms |= addChunkDependenciesAndAtomsAndGetSideEffectAtoms([bigChunks, smallChunks], chunkByModule, numberOfEntries, containedAtoms);
17342
17362
  return {
17343
17363
  big: new Set(bigChunks),
17364
+ sideEffectAtoms,
17365
+ sizeByAtom,
17344
17366
  small: new Set(smallChunks)
17345
17367
  };
17346
17368
  }
17347
- function sortChunksAndAddDependenciesAndEffects(chunkLists, chunkByModule, sideEffectsByEntry) {
17369
+ function mergeChunks(chunkPartition, minChunkSize) {
17370
+ const { small } = chunkPartition;
17371
+ for (const mergedChunk of small) {
17372
+ const bestTargetChunk = findBestMergeTarget(mergedChunk, chunkPartition,
17373
+ // In the default case, we do not accept size increases
17374
+ minChunkSize <= 1 ? 1 : Infinity);
17375
+ if (bestTargetChunk) {
17376
+ const { containedAtoms, correlatedAtoms, modules, pure, size } = mergedChunk;
17377
+ small.delete(mergedChunk);
17378
+ getChunksInPartition(bestTargetChunk, minChunkSize, chunkPartition).delete(bestTargetChunk);
17379
+ bestTargetChunk.modules.push(...modules);
17380
+ bestTargetChunk.size += size;
17381
+ bestTargetChunk.pure && (bestTargetChunk.pure = pure);
17382
+ const { dependencies, dependentChunks, dependentEntries } = bestTargetChunk;
17383
+ bestTargetChunk.correlatedAtoms &= correlatedAtoms;
17384
+ bestTargetChunk.containedAtoms |= containedAtoms;
17385
+ for (const entry of mergedChunk.dependentEntries) {
17386
+ dependentEntries.add(entry);
17387
+ }
17388
+ for (const dependency of mergedChunk.dependencies) {
17389
+ dependencies.add(dependency);
17390
+ dependency.dependentChunks.delete(mergedChunk);
17391
+ dependency.dependentChunks.add(bestTargetChunk);
17392
+ }
17393
+ for (const dependentChunk of mergedChunk.dependentChunks) {
17394
+ dependentChunks.add(dependentChunk);
17395
+ dependentChunk.dependencies.delete(mergedChunk);
17396
+ dependentChunk.dependencies.add(bestTargetChunk);
17397
+ }
17398
+ dependencies.delete(bestTargetChunk);
17399
+ dependentChunks.delete(bestTargetChunk);
17400
+ getChunksInPartition(bestTargetChunk, minChunkSize, chunkPartition).add(bestTargetChunk);
17401
+ }
17402
+ }
17403
+ }
17404
+ function addChunkDependenciesAndAtomsAndGetSideEffectAtoms(chunkLists, chunkByModule, numberOfEntries, nextAtomSignature) {
17405
+ const signatureByExternalModule = new Map();
17406
+ let sideEffectAtoms = 0n;
17407
+ const atomsByEntry = [];
17408
+ for (let index = 0; index < numberOfEntries; index++) {
17409
+ atomsByEntry.push(0n);
17410
+ }
17348
17411
  for (const chunks of chunkLists) {
17349
17412
  chunks.sort(compareChunkSize);
17350
17413
  for (const chunk of chunks) {
17351
- const { dependencies, modules, correlatedSideEffects, dependentEntries } = chunk;
17414
+ const { dependencies, dependentEntries, modules } = chunk;
17352
17415
  for (const module of modules) {
17353
17416
  for (const dependency of module.getDependenciesToBeIncluded()) {
17354
- const dependencyChunk = chunkByModule.get(dependency);
17355
- if (dependencyChunk && dependencyChunk !== chunk) {
17356
- dependencies.add(dependencyChunk);
17357
- dependencyChunk.dependentChunks.add(chunk);
17358
- }
17359
- }
17360
- }
17361
- let firstEntry = true;
17362
- // Correlated side effects is the intersection of all entry side effects
17363
- for (const entryIndex of dependentEntries) {
17364
- const entryEffects = sideEffectsByEntry[entryIndex];
17365
- if (firstEntry) {
17366
- for (const sideEffect of entryEffects) {
17367
- correlatedSideEffects.add(sideEffect);
17417
+ if (dependency instanceof ExternalModule) {
17418
+ if (dependency.info.moduleSideEffects) {
17419
+ chunk.containedAtoms |= getOrCreate(signatureByExternalModule, dependency, () => {
17420
+ const signature = nextAtomSignature;
17421
+ nextAtomSignature <<= 1n;
17422
+ sideEffectAtoms |= signature;
17423
+ return signature;
17424
+ });
17425
+ }
17368
17426
  }
17369
- firstEntry = false;
17370
- }
17371
- else {
17372
- for (const sideEffect of correlatedSideEffects) {
17373
- if (!entryEffects.has(sideEffect)) {
17374
- correlatedSideEffects.delete(sideEffect);
17427
+ else {
17428
+ const dependencyChunk = chunkByModule.get(dependency);
17429
+ if (dependencyChunk && dependencyChunk !== chunk) {
17430
+ dependencies.add(dependencyChunk);
17431
+ dependencyChunk.dependentChunks.add(chunk);
17375
17432
  }
17376
17433
  }
17377
17434
  }
17378
17435
  }
17436
+ const { containedAtoms } = chunk;
17437
+ for (const entryIndex of dependentEntries) {
17438
+ atomsByEntry[entryIndex] |= containedAtoms;
17439
+ }
17379
17440
  }
17380
17441
  }
17381
- }
17382
- function compareChunkSize({ size: sizeA }, { size: sizeB }) {
17383
- return sizeA - sizeB;
17384
- }
17385
- function mergeChunks(chunkPartition, minChunkSize) {
17386
- for (const allowArbitraryMerges of [false, true]) {
17387
- for (const mergedChunk of chunkPartition.small) {
17388
- let closestChunk = null;
17389
- let closestChunkDistance = Infinity;
17390
- const { modules, pure, size } = mergedChunk;
17391
- for (const targetChunk of concatLazy([chunkPartition.small, chunkPartition.big])) {
17392
- if (mergedChunk === targetChunk)
17393
- continue;
17394
- // If both chunks are small, we also allow for unrelated merges during
17395
- // the first pass
17396
- const onlySubsetMerge = !allowArbitraryMerges && targetChunk.size >= minChunkSize;
17397
- const distance = getChunkEntryDistance(mergedChunk, targetChunk, onlySubsetMerge);
17398
- if (distance < closestChunkDistance &&
17399
- isValidMerge(mergedChunk, targetChunk, onlySubsetMerge)) {
17400
- closestChunk = targetChunk;
17401
- closestChunkDistance = distance;
17402
- }
17403
- }
17404
- if (closestChunk) {
17405
- chunkPartition.small.delete(mergedChunk);
17406
- getChunksInPartition(closestChunk, minChunkSize, chunkPartition).delete(closestChunk);
17407
- closestChunk.modules.push(...modules);
17408
- closestChunk.size += size;
17409
- closestChunk.pure && (closestChunk.pure = pure);
17410
- const { correlatedSideEffects, dependencies, dependentChunks, dependentEntries, sideEffects } = closestChunk;
17411
- for (const sideEffect of correlatedSideEffects) {
17412
- if (!mergedChunk.correlatedSideEffects.has(sideEffect)) {
17413
- correlatedSideEffects.delete(sideEffect);
17414
- }
17415
- }
17416
- for (const entry of mergedChunk.dependentEntries) {
17417
- dependentEntries.add(entry);
17418
- }
17419
- for (const sideEffect of mergedChunk.sideEffects) {
17420
- sideEffects.add(sideEffect);
17421
- }
17422
- for (const dependency of mergedChunk.dependencies) {
17423
- dependencies.add(dependency);
17424
- dependency.dependentChunks.delete(mergedChunk);
17425
- dependency.dependentChunks.add(closestChunk);
17426
- }
17427
- for (const dependentChunk of mergedChunk.dependentChunks) {
17428
- dependentChunks.add(dependentChunk);
17429
- dependentChunk.dependencies.delete(mergedChunk);
17430
- dependentChunk.dependencies.add(closestChunk);
17431
- }
17432
- dependencies.delete(closestChunk);
17433
- dependentChunks.delete(closestChunk);
17434
- getChunksInPartition(closestChunk, minChunkSize, chunkPartition).add(closestChunk);
17442
+ for (const chunks of chunkLists) {
17443
+ for (const chunk of chunks) {
17444
+ const { dependentEntries } = chunk;
17445
+ // Correlated atoms are the intersection of all entry atoms
17446
+ chunk.correlatedAtoms = -1n;
17447
+ for (const entryIndex of dependentEntries) {
17448
+ chunk.correlatedAtoms &= atomsByEntry[entryIndex];
17435
17449
  }
17436
17450
  }
17437
17451
  }
17452
+ return sideEffectAtoms;
17438
17453
  }
17439
- // Merging will not produce cycles if none of the direct non-merged dependencies
17440
- // of a chunk have the other chunk as a transitive dependency
17441
- function isValidMerge(mergedChunk, targetChunk, onlySubsetMerge) {
17442
- return !(hasTransitiveDependencyOrNonCorrelatedSideEffect(mergedChunk, targetChunk, true) ||
17443
- hasTransitiveDependencyOrNonCorrelatedSideEffect(targetChunk, mergedChunk, !onlySubsetMerge));
17444
- }
17445
- function hasTransitiveDependencyOrNonCorrelatedSideEffect(dependentChunk, dependencyChunk, checkSideEffects) {
17446
- const { correlatedSideEffects } = dependencyChunk;
17447
- if (checkSideEffects) {
17448
- for (const sideEffect of dependentChunk.sideEffects) {
17449
- if (!correlatedSideEffects.has(sideEffect)) {
17450
- return true;
17451
- }
17454
+ function findBestMergeTarget(mergedChunk, { big, sideEffectAtoms, sizeByAtom, small }, smallestAdditionalSize) {
17455
+ let bestTargetChunk = null;
17456
+ // In the default case, we do not accept size increases
17457
+ for (const targetChunk of concatLazy([small, big])) {
17458
+ if (mergedChunk === targetChunk)
17459
+ continue;
17460
+ const additionalSizeAfterMerge = getAdditionalSizeAfterMerge(mergedChunk, targetChunk, smallestAdditionalSize, sideEffectAtoms, sizeByAtom);
17461
+ if (additionalSizeAfterMerge < smallestAdditionalSize) {
17462
+ bestTargetChunk = targetChunk;
17463
+ if (additionalSizeAfterMerge === 0)
17464
+ break;
17465
+ smallestAdditionalSize = additionalSizeAfterMerge;
17452
17466
  }
17453
17467
  }
17468
+ return bestTargetChunk;
17469
+ }
17470
+ function getChunksInPartition(chunk, minChunkSize, chunkPartition) {
17471
+ return chunk.size < minChunkSize ? chunkPartition.small : chunkPartition.big;
17472
+ }
17473
+ function compareChunkSize({ size: sizeA }, { size: sizeB }) {
17474
+ return sizeA - sizeB;
17475
+ }
17476
+ /**
17477
+ * Determine the additional unused code size that would be added by merging the
17478
+ * two chunks. This is not an exact measurement but rather an upper bound. If
17479
+ * the merge produces cycles or adds non-correlated side effects, `Infinity`
17480
+ * is returned.
17481
+ * Merging will not produce cycles if none of the direct non-merged
17482
+ * dependencies of a chunk have the other chunk as a transitive dependency.
17483
+ */
17484
+ function getAdditionalSizeAfterMerge(mergedChunk, targetChunk,
17485
+ // The maximum additional unused code size allowed to be added by the merge,
17486
+ // taking dependencies into account, needs to be below this number
17487
+ currentAdditionalSize, sideEffectAtoms, sizeByAtom) {
17488
+ const firstSize = getAdditionalSizeIfNoTransitiveDependencyOrNonCorrelatedSideEffect(mergedChunk, targetChunk, currentAdditionalSize, sideEffectAtoms, sizeByAtom);
17489
+ return firstSize < currentAdditionalSize
17490
+ ? firstSize +
17491
+ getAdditionalSizeIfNoTransitiveDependencyOrNonCorrelatedSideEffect(targetChunk, mergedChunk, currentAdditionalSize - firstSize, sideEffectAtoms, sizeByAtom)
17492
+ : Infinity;
17493
+ }
17494
+ function getAdditionalSizeIfNoTransitiveDependencyOrNonCorrelatedSideEffect(dependentChunk, dependencyChunk, currentAdditionalSize, sideEffectAtoms, sizeByAtom) {
17495
+ const { correlatedAtoms } = dependencyChunk;
17496
+ let dependencyAtoms = dependentChunk.containedAtoms;
17497
+ const dependentContainedSideEffects = dependencyAtoms & sideEffectAtoms;
17498
+ if ((correlatedAtoms & dependentContainedSideEffects) !== dependentContainedSideEffects) {
17499
+ return Infinity;
17500
+ }
17454
17501
  const chunksToCheck = new Set(dependentChunk.dependencies);
17455
- for (const { dependencies, sideEffects } of chunksToCheck) {
17502
+ for (const { dependencies, containedAtoms } of chunksToCheck) {
17503
+ dependencyAtoms |= containedAtoms;
17504
+ const containedSideEffects = containedAtoms & sideEffectAtoms;
17505
+ if ((correlatedAtoms & containedSideEffects) !== containedSideEffects) {
17506
+ return Infinity;
17507
+ }
17456
17508
  for (const dependency of dependencies) {
17457
17509
  if (dependency === dependencyChunk) {
17458
- return true;
17510
+ return Infinity;
17459
17511
  }
17460
17512
  chunksToCheck.add(dependency);
17461
17513
  }
17462
- if (checkSideEffects) {
17463
- for (const sideEffect of sideEffects) {
17464
- if (!correlatedSideEffects.has(sideEffect)) {
17465
- return true;
17466
- }
17467
- }
17468
- }
17469
17514
  }
17470
- return false;
17471
- }
17472
- function getChunksInPartition(chunk, minChunkSize, chunkPartition) {
17473
- return chunk.size < minChunkSize ? chunkPartition.small : chunkPartition.big;
17515
+ return getAtomsSizeIfBelowLimit(dependencyAtoms & ~correlatedAtoms, currentAdditionalSize, sizeByAtom);
17474
17516
  }
17475
- function getChunkEntryDistance({ dependentEntries: sourceEntries }, { dependentEntries: targetEntries }, enforceSubest) {
17476
- let distance = 0;
17477
- for (const entryIndex of targetEntries) {
17478
- if (!sourceEntries.has(entryIndex)) {
17479
- distance++;
17517
+ function getAtomsSizeIfBelowLimit(atoms, currentAdditionalSize, sizeByAtom) {
17518
+ let size = 0;
17519
+ let atomIndex = 0;
17520
+ let atomSignature = 1n;
17521
+ const { length } = sizeByAtom;
17522
+ for (; atomIndex < length; atomIndex++) {
17523
+ if ((atoms & atomSignature) === atomSignature) {
17524
+ size += sizeByAtom[atomIndex];
17480
17525
  }
17481
- }
17482
- for (const entryIndex of sourceEntries) {
17483
- if (!targetEntries.has(entryIndex)) {
17484
- if (enforceSubest) {
17485
- return Infinity;
17486
- }
17487
- distance++;
17526
+ atomSignature <<= 1n;
17527
+ if (size >= currentAdditionalSize) {
17528
+ return Infinity;
17488
17529
  }
17489
17530
  }
17490
- return distance;
17531
+ return size;
17491
17532
  }
17492
17533
 
17493
17534
  // ported from https://github.com/substack/node-commondir
@@ -25864,7 +25905,7 @@ async function normalizeOutputOptions(config, inputOptions, unsetInputOptions) {
25864
25905
  entryFileNames: getEntryFileNames(config, unsetOptions),
25865
25906
  esModule: config.esModule ?? 'if-default-prop',
25866
25907
  experimentalDeepDynamicChunkOptimization: getExperimentalDeepDynamicChunkOptimization(config, inputOptions),
25867
- experimentalMinChunkSize: config.experimentalMinChunkSize || 0,
25908
+ experimentalMinChunkSize: config.experimentalMinChunkSize ?? 1,
25868
25909
  exports: getExports(config, unsetOptions),
25869
25910
  extend: config.extend || false,
25870
25911
  externalImportAssertions: config.externalImportAssertions ?? true,
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.21.8
4
- Tue, 16 May 2023 07:30:04 GMT - commit 67f2416afb73734887d37e12ce5d7f00a511ac27
3
+ Rollup.js v3.22.0
4
+ Wed, 17 May 2023 04:19:47 GMT - commit 9f05b91e5e1862f7ea7a728fb63fb2750dfe7392
5
5
 
6
6
  https://github.com/rollup/rollup
7
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rollup",
3
- "version": "3.21.8",
3
+ "version": "3.22.0",
4
4
  "description": "Next-generation ES module bundler",
5
5
  "main": "dist/rollup.js",
6
6
  "module": "dist/es/rollup.js",