rollup 3.15.1-1 → 3.17.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.
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  @license
3
- Rollup.js v3.15.1-1
4
- Tue, 14 Feb 2023 09:30:15 GMT - commit 5e91b2d7a9f833cf9e11d98c96c4cba3fac195a4
3
+ Rollup.js v3.17.0
4
+ Sat, 18 Feb 2023 05:06:04 GMT - commit 0c33497a7de91e150a7d242125e8da9dd4e4a3ac
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.15.1-1";
19
+ var version$1 = "3.17.0";
20
20
 
21
21
  const comma = ','.charCodeAt(0);
22
22
  const semicolon = ';'.charCodeAt(0);
@@ -1798,7 +1798,7 @@ class DiscriminatedPathTracker {
1798
1798
  currentPaths[pathSegment] ||
1799
1799
  Object.create(null, { [EntitiesKey]: { value: new Map() } });
1800
1800
  }
1801
- const trackedEntities = getOrCreate(currentPaths[EntitiesKey], discriminator, getNewSet);
1801
+ const trackedEntities = getOrCreate(currentPaths[EntitiesKey], discriminator, (getNewSet));
1802
1802
  if (trackedEntities.has(entity))
1803
1803
  return true;
1804
1804
  trackedEntities.add(entity);
@@ -2071,6 +2071,7 @@ const URL_OUTPUT_EXPORTS = 'configuration-options/#output-exports';
2071
2071
  const URL_OUTPUT_EXTEND = 'configuration-options/#output-extend';
2072
2072
  const URL_OUTPUT_FORMAT = 'configuration-options/#output-format';
2073
2073
  const URL_OUTPUT_GENERATEDCODE = 'configuration-options/#output-generatedcode';
2074
+ const URL_OUTPUT_EXPERIMENTALDEEPCHUNKOPTIMIZATION = 'configuration-options/#output-experimentaldeepdynamicchunkoptimization';
2074
2075
  const URL_OUTPUT_GENERATEDCODE_CONSTBINDINGS = 'configuration-options/#output-generatedcode-constbindings';
2075
2076
  const URL_OUTPUT_GENERATEDCODE_SYMBOLS = 'configuration-options/#output-generatedcode-symbols';
2076
2077
  const URL_OUTPUT_GLOBALS = 'configuration-options/#output-globals';
@@ -12966,7 +12967,7 @@ function getVariableForExportNameRecursive(target, name, importerForSideEffects,
12966
12967
  });
12967
12968
  }
12968
12969
  function getAndExtendSideEffectModules(variable, module) {
12969
- const sideEffectModules = getOrCreate(module.sideEffectDependenciesByVariable, variable, getNewSet);
12970
+ const sideEffectModules = getOrCreate(module.sideEffectDependenciesByVariable, variable, (getNewSet));
12970
12971
  let currentVariable = variable;
12971
12972
  const referencedVariables = new Set([currentVariable]);
12972
12973
  while (true) {
@@ -13305,7 +13306,7 @@ class Module {
13305
13306
  searchedNamesAndModules
13306
13307
  });
13307
13308
  if (importerForSideEffects) {
13308
- getOrCreate(importerForSideEffects.sideEffectDependenciesByVariable, variable, getNewSet).add(this);
13309
+ getOrCreate(importerForSideEffects.sideEffectDependenciesByVariable, variable, (getNewSet)).add(this);
13309
13310
  setAlternativeExporterIfCyclic(variable, importerForSideEffects, this);
13310
13311
  }
13311
13312
  return [variable];
@@ -16059,7 +16060,137 @@ function* concatLazy(iterables) {
16059
16060
  }
16060
16061
  }
16061
16062
 
16062
- function getChunkAssignments(entries, manualChunkAliasByEntry, minChunkSize, deepChunkOptimization) {
16063
+ /**
16064
+ * At its core, the algorithm first starts from each static or dynamic entry
16065
+ * point and then assigns that entry point to all modules than can be reached
16066
+ * via static imports. We call this the *dependent entry points* of that
16067
+ * module.
16068
+ *
16069
+ * Then we group all modules with the same dependent entry points into chunks
16070
+ * as those modules will always be loaded together.
16071
+ *
16072
+ * One non-trivial optimization we can apply is that dynamic entries are
16073
+ * different from static entries in so far as when a dynamic import occurs,
16074
+ * some
16075
+ * modules are already in memory. If some of these modules are also
16076
+ * dependencies
16077
+ * of the dynamic entry, then it does not make sense to create a separate chunk
16078
+ * for them. Instead, the dynamic import target can load them from the
16079
+ * importing
16080
+ * chunk.
16081
+ *
16082
+ * With regard to chunking, if B is implicitly loaded after A, then this can be
16083
+ * handled the same way as if there was a dynamic import A => B.
16084
+ *
16085
+ * Example:
16086
+ * Assume A -> B (A imports B), A => C (A dynamically imports C) and C -> B.
16087
+ * Then the initial algorithm would assign A into the A chunk, C into the C
16088
+ * chunk and B into the AC chunk, i.e. the chunk with the dependent entry
16089
+ * points
16090
+ * A and C.
16091
+ * However we know that C can only be loaded from A, so A and its dependency B
16092
+ * must already be in memory when C is loaded. So it is enough to create only
16093
+ * two chunks A containing [AB] and C containing [C].
16094
+ *
16095
+ * So we do not assign the dynamic entry C as dependent entry point to modules
16096
+ * that are already loaded.
16097
+ *
16098
+ * In a more complex example, let us assume that we have entry points X and Y.
16099
+ * Further, let us assume
16100
+ * X -> A, X -> B, X -> C,
16101
+ * Y -> A, Y -> B,
16102
+ * A => D,
16103
+ * D -> B, D -> C
16104
+ * So without dynamic import optimization, the dependent entry points are
16105
+ * A: XY, B: DXY, C: DX, D: D, X: X, Y: Y,
16106
+ * so we would for now create six chunks.
16107
+ *
16108
+ * Now D is loaded only after A is loaded. But A is loaded if either X is
16109
+ * loaded
16110
+ * or Y is loaded. So the modules that are already in memory when D is loaded
16111
+ * are the intersection of all modules that X depends on with all modules that
16112
+ * Y
16113
+ * depends on, which in this case are the modules A and B.
16114
+ * We could also say they are all modules that have both X and Y as dependent
16115
+ * entry points.
16116
+ *
16117
+ * So we can remove D as dependent entry point from A and B, which means they
16118
+ * both now have only XY as dependent entry points and can be merged into the
16119
+ * same chunk.
16120
+ *
16121
+ * Now let us extend this to the most general case where we have several
16122
+ * dynamic
16123
+ * importers for one dynamic entry point.
16124
+ *
16125
+ * In the most general form, it works like this:
16126
+ * For each dynamic entry point, we have a number of dynamic importers, which
16127
+ * are the modules importing it. Using the previous ideas, we can determine
16128
+ * the modules already in memory for each dynamic importer by looking for all
16129
+ * modules that have all the dependent entry points of the dynamic importer as
16130
+ * dependent entry points.
16131
+ * So the modules that are guaranteed to be in memory when the dynamic entry
16132
+ * point is loaded are the intersection of the modules already in memory for
16133
+ * each dynamic importer.
16134
+ *
16135
+ * Assuming that A => D and B => D and A has dependent entry points XY and B
16136
+ * has
16137
+ * dependent entry points YZ, then the modules guaranteed to be in memory are
16138
+ * all modules that have at least XYZ as dependent entry points.
16139
+ * We call XYZ the *dynamically dependent entry points* of D.
16140
+ *
16141
+ * Now there is one last case to consider: If one of the dynamically dependent
16142
+ * entries is itself a dynamic entry, then any module is in memory that either
16143
+ * is a dependency of that dynamic entry or again has the dynamic dependent
16144
+ * entries of that dynamic entry as dependent entry points.
16145
+ *
16146
+ * A naive algorithm for this proved to be costly as it contained an O(n^3)
16147
+ * complexity with regard to dynamic entries that blew up for very large
16148
+ * projects.
16149
+ *
16150
+ * If we have an efficient way to do Set operations, an alternative approach
16151
+ * would be to instead collect already loaded modules per dynamic entry. And as
16152
+ * all chunks from the initial grouping would behave the same, we can instead
16153
+ * collect already loaded chunks for a performance improvement.
16154
+ *
16155
+ * To do that efficiently, need
16156
+ * - a Map of dynamic imports per dynamic entry, which contains all dynamic
16157
+ * imports that can be triggered by a dynamic entry
16158
+ * - a Map of static dependencies per entry
16159
+ * - a Map of already loaded chunks per entry that we initially populate with
16160
+ * empty Sets for static entries and Sets containing all entries for dynamic
16161
+ * entries
16162
+ *
16163
+ * For efficient operations, we assign each entry a numerical index and
16164
+ * represent Sets of Chunks as BigInt values where each chunk corresponds to a
16165
+ * bit index. Then thw last two maps can be represented as arrays of BigInt
16166
+ * values.
16167
+ *
16168
+ * Then we iterate through each dynamic entry. We set the already loaded modules
16169
+ * to the intersection of the previously already loaded modules with the union
16170
+ * of the already loaded modules of that chunk with its static dependencies.
16171
+ *
16172
+ * If the already loaded modules changed, then we use the Map of dynamic imports
16173
+ * per dynamic entry to marks all dynamic entry dependencies as "dirty" and put
16174
+ * them back into the iteration. As an additional optimization, we note for
16175
+ * each dynamic entry which dynamic dependent entries have changed and only
16176
+ * intersect those entries again on subsequent interations.
16177
+ *
16178
+ * Then we remove the dynamic entries from the list of dependent entries for
16179
+ * those chunks that are already loaded for that dynamic entry and create
16180
+ * another round of chunks.
16181
+ */
16182
+ function getChunkAssignments(entries, manualChunkAliasByEntry, minChunkSize) {
16183
+ const { chunkDefinitions, modulesInManualChunks } = getChunkDefinitionsFromManualChunks(manualChunkAliasByEntry);
16184
+ const { allEntries, dependentEntriesByModule, dynamicallyDependentEntriesByDynamicEntry, dynamicImportsByEntry } = analyzeModuleGraph(entries);
16185
+ // Each chunk is identified by its position in this array
16186
+ const initialChunks = Object.values(getChunksBySignature(getModulesWithDependentEntries(dependentEntriesByModule, modulesInManualChunks)));
16187
+ // This mutates initialChunks but also clears
16188
+ // dynamicallyDependentEntriesByDynamicEntry as side effect
16189
+ removeUnnecessaryDependentEntries(initialChunks, dynamicallyDependentEntriesByDynamicEntry, dynamicImportsByEntry, allEntries);
16190
+ chunkDefinitions.push(...createChunks(allEntries, getChunksBySignature(initialChunks), minChunkSize));
16191
+ return chunkDefinitions;
16192
+ }
16193
+ function getChunkDefinitionsFromManualChunks(manualChunkAliasByEntry) {
16063
16194
  const chunkDefinitions = [];
16064
16195
  const modulesInManualChunks = new Set(manualChunkAliasByEntry.keys());
16065
16196
  const manualChunkModulesByAlias = Object.create(null);
@@ -16069,16 +16200,7 @@ function getChunkAssignments(entries, manualChunkAliasByEntry, minChunkSize, dee
16069
16200
  for (const [alias, modules] of Object.entries(manualChunkModulesByAlias)) {
16070
16201
  chunkDefinitions.push({ alias, modules });
16071
16202
  }
16072
- const { allEntries, dependentEntriesByModule, dynamicallyDependentEntriesByDynamicEntry } = analyzeModuleGraph(entries);
16073
- const staticEntries = new Set(entries);
16074
- const assignedEntriesByModule = new Map();
16075
- for (const entry of allEntries) {
16076
- if (!modulesInManualChunks.has(entry)) {
16077
- assignEntryToStaticDependencies(entry, dependentEntriesByModule, assignedEntriesByModule, modulesInManualChunks, staticEntries, dynamicallyDependentEntriesByDynamicEntry, deepChunkOptimization);
16078
- }
16079
- }
16080
- chunkDefinitions.push(...createChunks(allEntries, assignedEntriesByModule, minChunkSize));
16081
- return chunkDefinitions;
16203
+ return { chunkDefinitions, modulesInManualChunks };
16082
16204
  }
16083
16205
  function addStaticDependenciesToManualChunk(entry, manualChunkModules, modulesInManualChunks) {
16084
16206
  const modulesToHandle = new Set([entry]);
@@ -16093,13 +16215,17 @@ function addStaticDependenciesToManualChunk(entry, manualChunkModules, modulesIn
16093
16215
  }
16094
16216
  }
16095
16217
  function analyzeModuleGraph(entries) {
16096
- const dynamicEntries = new Set();
16218
+ const dynamicEntryModules = new Set();
16097
16219
  const dependentEntriesByModule = new Map();
16098
- const allEntries = new Set(entries);
16099
- for (const currentEntry of allEntries) {
16220
+ const dynamicImportModulesByEntry = [];
16221
+ const allEntriesSet = new Set(entries);
16222
+ let entryIndex = 0;
16223
+ for (const currentEntry of allEntriesSet) {
16224
+ const dynamicImportsForCurrentEntry = new Set();
16225
+ dynamicImportModulesByEntry.push(dynamicImportsForCurrentEntry);
16100
16226
  const modulesToHandle = new Set([currentEntry]);
16101
16227
  for (const module of modulesToHandle) {
16102
- getOrCreate(dependentEntriesByModule, module, getNewSet).add(currentEntry);
16228
+ getOrCreate(dependentEntriesByModule, module, (getNewSet)).add(entryIndex);
16103
16229
  for (const dependency of module.getDependenciesToBeIncluded()) {
16104
16230
  if (!(dependency instanceof ExternalModule)) {
16105
16231
  modulesToHandle.add(dependency);
@@ -16108,33 +16234,58 @@ function analyzeModuleGraph(entries) {
16108
16234
  for (const { resolution } of module.dynamicImports) {
16109
16235
  if (resolution instanceof Module &&
16110
16236
  resolution.includedDynamicImporters.length > 0 &&
16111
- !allEntries.has(resolution)) {
16112
- dynamicEntries.add(resolution);
16113
- allEntries.add(resolution);
16237
+ !allEntriesSet.has(resolution)) {
16238
+ dynamicEntryModules.add(resolution);
16239
+ allEntriesSet.add(resolution);
16240
+ dynamicImportsForCurrentEntry.add(resolution);
16114
16241
  }
16115
16242
  }
16116
16243
  for (const dependency of module.implicitlyLoadedBefore) {
16117
- if (!allEntries.has(dependency)) {
16118
- dynamicEntries.add(dependency);
16119
- allEntries.add(dependency);
16244
+ if (!allEntriesSet.has(dependency)) {
16245
+ dynamicEntryModules.add(dependency);
16246
+ allEntriesSet.add(dependency);
16120
16247
  }
16121
16248
  }
16122
16249
  }
16250
+ entryIndex++;
16123
16251
  }
16252
+ const allEntries = [...allEntriesSet];
16253
+ const { dynamicEntries, dynamicImportsByEntry } = getDynamicEntries(allEntries, dynamicEntryModules, dynamicImportModulesByEntry);
16124
16254
  return {
16125
- allEntries: [...allEntries],
16255
+ allEntries,
16126
16256
  dependentEntriesByModule,
16127
- dynamicallyDependentEntriesByDynamicEntry: getDynamicallyDependentEntriesByDynamicEntry(dependentEntriesByModule, dynamicEntries)
16257
+ dynamicallyDependentEntriesByDynamicEntry: getDynamicallyDependentEntriesByDynamicEntry(dependentEntriesByModule, dynamicEntries, allEntries),
16258
+ dynamicImportsByEntry
16128
16259
  };
16129
16260
  }
16130
- function getDynamicallyDependentEntriesByDynamicEntry(dependentEntriesByModule, dynamicEntries) {
16261
+ function getDynamicEntries(allEntries, dynamicEntryModules, dynamicImportModulesByEntry) {
16262
+ const entryIndexByModule = new Map();
16263
+ const dynamicEntries = new Set();
16264
+ for (const [entryIndex, entry] of allEntries.entries()) {
16265
+ entryIndexByModule.set(entry, entryIndex);
16266
+ if (dynamicEntryModules.has(entry)) {
16267
+ dynamicEntries.add(entryIndex);
16268
+ }
16269
+ }
16270
+ const dynamicImportsByEntry = [];
16271
+ for (const dynamicImportModules of dynamicImportModulesByEntry) {
16272
+ const dynamicImports = new Set();
16273
+ for (const dynamicEntry of dynamicImportModules) {
16274
+ dynamicImports.add(entryIndexByModule.get(dynamicEntry));
16275
+ }
16276
+ dynamicImportsByEntry.push(dynamicImports);
16277
+ }
16278
+ return { dynamicEntries, dynamicImportsByEntry };
16279
+ }
16280
+ function getDynamicallyDependentEntriesByDynamicEntry(dependentEntriesByModule, dynamicEntries, allEntries) {
16131
16281
  const dynamicallyDependentEntriesByDynamicEntry = new Map();
16132
- for (const dynamicEntry of dynamicEntries) {
16133
- const dynamicallyDependentEntries = getOrCreate(dynamicallyDependentEntriesByDynamicEntry, dynamicEntry, getNewSet);
16134
- for (const importer of [
16135
- ...dynamicEntry.includedDynamicImporters,
16136
- ...dynamicEntry.implicitlyLoadedAfter
16137
- ]) {
16282
+ for (const dynamicEntryIndex of dynamicEntries) {
16283
+ const dynamicallyDependentEntries = getOrCreate(dynamicallyDependentEntriesByDynamicEntry, dynamicEntryIndex, (getNewSet));
16284
+ const dynamicEntry = allEntries[dynamicEntryIndex];
16285
+ for (const importer of concatLazy([
16286
+ dynamicEntry.includedDynamicImporters,
16287
+ dynamicEntry.implicitlyLoadedAfter
16288
+ ])) {
16138
16289
  for (const entry of dependentEntriesByModule.get(importer)) {
16139
16290
  dynamicallyDependentEntries.add(entry);
16140
16291
  }
@@ -16142,57 +16293,80 @@ function getDynamicallyDependentEntriesByDynamicEntry(dependentEntriesByModule,
16142
16293
  }
16143
16294
  return dynamicallyDependentEntriesByDynamicEntry;
16144
16295
  }
16145
- function assignEntryToStaticDependencies(entry, dependentEntriesByModule, assignedEntriesByModule, modulesInManualChunks, staticEntries, dynamicallyDependentEntriesByDynamicEntry, deepChunkOptimization) {
16146
- const dynamicallyDependentEntries = dynamicallyDependentEntriesByDynamicEntry.get(entry);
16147
- const modulesToHandle = new Set([entry]);
16148
- for (const module of modulesToHandle) {
16149
- const assignedEntries = getOrCreate(assignedEntriesByModule, module, getNewSet);
16150
- if (dynamicallyDependentEntries &&
16151
- isModuleAlreadyLoaded(dynamicallyDependentEntries, dependentEntriesByModule.get(module), staticEntries, dynamicallyDependentEntriesByDynamicEntry, deepChunkOptimization)) {
16152
- continue;
16153
- }
16154
- else {
16155
- assignedEntries.add(entry);
16156
- }
16157
- for (const dependency of module.getDependenciesToBeIncluded()) {
16158
- if (!(dependency instanceof ExternalModule || modulesInManualChunks.has(dependency))) {
16159
- modulesToHandle.add(dependency);
16160
- }
16296
+ function getChunksBySignature(modulesWithDependentEntries) {
16297
+ var _a;
16298
+ const chunkModules = Object.create(null);
16299
+ for (const { dependentEntries, modules } of modulesWithDependentEntries) {
16300
+ let chunkSignature = 0n;
16301
+ for (const entryIndex of dependentEntries) {
16302
+ chunkSignature |= 1n << BigInt(entryIndex);
16161
16303
  }
16304
+ (chunkModules[_a = String(chunkSignature)] || (chunkModules[_a] = {
16305
+ dependentEntries: new Set(dependentEntries),
16306
+ modules: []
16307
+ })).modules.push(...modules);
16162
16308
  }
16309
+ return chunkModules;
16163
16310
  }
16164
- const MAX_ENTRIES_TO_CHECK_FOR_SHARED_DEPENDENCIES = 3;
16165
- // An approach to further speed this up might be
16166
- // - first, create chunks without looking for modules already in memory
16167
- // - all modules that are in the same chunk after this will behave the same
16168
- // -> Do not iterate by module but by equivalence group and merge chunks
16169
- function isModuleAlreadyLoaded(dynamicallyDependentEntries, containedIn, staticEntries, dynamicallyDependentEntriesByDynamicEntry, deepChunkOptimization) {
16170
- if (!deepChunkOptimization &&
16171
- dynamicallyDependentEntries.size > MAX_ENTRIES_TO_CHECK_FOR_SHARED_DEPENDENCIES) {
16172
- return false;
16173
- }
16174
- const entriesToCheck = new Set(dynamicallyDependentEntries);
16175
- for (const entry of entriesToCheck) {
16176
- if (!containedIn.has(entry)) {
16177
- if (staticEntries.has(entry)) {
16178
- return false;
16179
- }
16180
- const dynamicallyDependentEntries = dynamicallyDependentEntriesByDynamicEntry.get(entry);
16181
- if (!deepChunkOptimization &&
16182
- dynamicallyDependentEntries.size > MAX_ENTRIES_TO_CHECK_FOR_SHARED_DEPENDENCIES) {
16183
- return false;
16184
- }
16185
- for (const dependentEntry of dynamicallyDependentEntries) {
16186
- entriesToCheck.add(dependentEntry);
16187
- }
16311
+ function* getModulesWithDependentEntries(dependentEntriesByModule, modulesInManualChunks) {
16312
+ for (const [module, dependentEntries] of dependentEntriesByModule) {
16313
+ if (!modulesInManualChunks.has(module)) {
16314
+ yield { dependentEntries, modules: [module] };
16188
16315
  }
16189
16316
  }
16190
- return true;
16191
16317
  }
16192
- function createChunks(allEntries, assignedEntriesByModule, minChunkSize) {
16193
- const chunkModulesBySignature = getChunkModulesBySignature(assignedEntriesByModule, allEntries);
16318
+ /**
16319
+ * This removes all unnecessary dynamic entries from the dependenEntries in its
16320
+ * first argument. It will also consume its second argument, so if
16321
+ * dynamicallyDependentEntriesByDynamicEntry is ever needed after this, we
16322
+ * should make a copy.
16323
+ */
16324
+ function removeUnnecessaryDependentEntries(chunks, dynamicallyDependentEntriesByDynamicEntry, dynamicImportsByEntry, allEntries) {
16325
+ // The indices correspond to the indices in allEntries. The chunks correspond
16326
+ // to bits in the bigint values where chunk 0 is the lowest bit.
16327
+ const staticDependenciesPerEntry = allEntries.map(() => 0n);
16328
+ const alreadyLoadedChunksPerEntry = allEntries.map((_entry, entryIndex) => dynamicallyDependentEntriesByDynamicEntry.has(entryIndex) ? -1n : 0n);
16329
+ // This toggles the bits for each chunk that is a dependency of an entry
16330
+ let chunkMask = 1n;
16331
+ for (const { dependentEntries } of chunks) {
16332
+ for (const entryIndex of dependentEntries) {
16333
+ staticDependenciesPerEntry[entryIndex] |= chunkMask;
16334
+ }
16335
+ chunkMask <<= 1n;
16336
+ }
16337
+ // Warning: This will consume dynamicallyDependentEntriesByDynamicEntry.
16338
+ // If we no longer want this, we should make a copy here.
16339
+ const updatedDynamicallyDependentEntriesByDynamicEntry = dynamicallyDependentEntriesByDynamicEntry;
16340
+ for (const [dynamicEntryIndex, updatedDynamicallyDependentEntries] of updatedDynamicallyDependentEntriesByDynamicEntry) {
16341
+ updatedDynamicallyDependentEntriesByDynamicEntry.delete(dynamicEntryIndex);
16342
+ const previousLoadedModules = alreadyLoadedChunksPerEntry[dynamicEntryIndex];
16343
+ let newLoadedModules = previousLoadedModules;
16344
+ for (const entryIndex of updatedDynamicallyDependentEntries) {
16345
+ newLoadedModules &=
16346
+ staticDependenciesPerEntry[entryIndex] | alreadyLoadedChunksPerEntry[entryIndex];
16347
+ }
16348
+ if (newLoadedModules !== previousLoadedModules) {
16349
+ alreadyLoadedChunksPerEntry[dynamicEntryIndex] = newLoadedModules;
16350
+ for (const dynamicImport of dynamicImportsByEntry[dynamicEntryIndex]) {
16351
+ getOrCreate(updatedDynamicallyDependentEntriesByDynamicEntry, dynamicImport, (getNewSet)).add(dynamicEntryIndex);
16352
+ }
16353
+ }
16354
+ }
16355
+ // Remove entries from dependent entries if a chunk is already loaded without
16356
+ // that entry.
16357
+ chunkMask = 1n;
16358
+ for (const { dependentEntries } of chunks) {
16359
+ for (const entryIndex of dependentEntries) {
16360
+ if ((alreadyLoadedChunksPerEntry[entryIndex] & chunkMask) === chunkMask) {
16361
+ dependentEntries.delete(entryIndex);
16362
+ }
16363
+ }
16364
+ chunkMask <<= 1n;
16365
+ }
16366
+ }
16367
+ function createChunks(allEntries, chunkModulesBySignature, minChunkSize) {
16194
16368
  return minChunkSize === 0
16195
- ? Object.values(chunkModulesBySignature).map(modules => ({
16369
+ ? Object.values(chunkModulesBySignature).map(({ modules }) => ({
16196
16370
  alias: null,
16197
16371
  modules
16198
16372
  }))
@@ -16201,23 +16375,6 @@ function createChunks(allEntries, assignedEntriesByModule, minChunkSize) {
16201
16375
  modules
16202
16376
  }));
16203
16377
  }
16204
- function getChunkModulesBySignature(assignedEntriesByModule, allEntries) {
16205
- const chunkModules = Object.create(null);
16206
- for (const [module, assignedEntries] of assignedEntriesByModule) {
16207
- let chunkSignature = '';
16208
- for (const entry of allEntries) {
16209
- chunkSignature += assignedEntries.has(entry) ? CHAR_DEPENDENT : CHAR_INDEPENDENT;
16210
- }
16211
- const chunk = chunkModules[chunkSignature];
16212
- if (chunk) {
16213
- chunk.push(module);
16214
- }
16215
- else {
16216
- chunkModules[chunkSignature] = [module];
16217
- }
16218
- }
16219
- return chunkModules;
16220
- }
16221
16378
  /**
16222
16379
  * This function tries to get rid of small chunks by merging them with other
16223
16380
  * chunks.
@@ -16289,17 +16446,20 @@ function getChunkModulesBySignature(assignedEntriesByModule, allEntries) {
16289
16446
  * following the above rules (a) and (b), starting with the smallest chunks
16290
16447
  * to look for possible merge targets.
16291
16448
  */
16449
+ // TODO instead of picking the "closest" chunk, we could actually use a
16450
+ // technique similar to what we do for side effects to compare the size of the
16451
+ // static dependencies that are not part of the correlated dependencies
16292
16452
  function getOptimizedChunks(chunkModulesBySignature, numberOfEntries, minChunkSize) {
16293
16453
  timeStart('optimize chunks', 3);
16294
16454
  const chunkPartition = getPartitionedChunks(chunkModulesBySignature, numberOfEntries, minChunkSize);
16455
+ console.log('Before eliminating small chunks, there were\n', Object.keys(chunkModulesBySignature).length, 'chunks, of which\n', chunkPartition.small.size, 'were below minChunkSize.');
16295
16456
  if (chunkPartition.small.size > 0) {
16296
16457
  mergeChunks(chunkPartition, minChunkSize);
16297
16458
  }
16459
+ console.log('After merging chunks,\n', chunkPartition.small.size + chunkPartition.big.size, 'chunks remain, of which\n', chunkPartition.small.size, 'are below minChunkSize.');
16298
16460
  timeEnd('optimize chunks', 3);
16299
16461
  return [...chunkPartition.small, ...chunkPartition.big];
16300
16462
  }
16301
- const CHAR_DEPENDENT = 'X';
16302
- const CHAR_INDEPENDENT = '_';
16303
16463
  function getPartitionedChunks(chunkModulesBySignature, numberOfEntries, minChunkSize) {
16304
16464
  const smallChunks = [];
16305
16465
  const bigChunks = [];
@@ -16308,13 +16468,7 @@ function getPartitionedChunks(chunkModulesBySignature, numberOfEntries, minChunk
16308
16468
  for (let index = 0; index < numberOfEntries; index++) {
16309
16469
  sideEffectsByEntry.push(new Set());
16310
16470
  }
16311
- for (const [signature, modules] of Object.entries(chunkModulesBySignature)) {
16312
- const dependentEntries = new Set();
16313
- for (let position = 0; position < numberOfEntries; position++) {
16314
- if (signature[position] === CHAR_DEPENDENT) {
16315
- dependentEntries.add(position);
16316
- }
16317
- }
16471
+ for (const [signature, { dependentEntries, modules }] of Object.entries(chunkModulesBySignature)) {
16318
16472
  const chunkDescription = {
16319
16473
  correlatedSideEffects: new Set(),
16320
16474
  dependencies: new Set(),
@@ -16391,8 +16545,6 @@ function compareChunkSize({ size: sizeA }, { size: sizeB }) {
16391
16545
  return sizeA - sizeB;
16392
16546
  }
16393
16547
  function mergeChunks(chunkPartition, minChunkSize) {
16394
- console.log('---- Initial chunks');
16395
- printConsistencyCheck(chunkPartition);
16396
16548
  for (const allowArbitraryMerges of [false, true]) {
16397
16549
  for (const mergedChunk of chunkPartition.small) {
16398
16550
  let closestChunk = null;
@@ -16440,11 +16592,10 @@ function mergeChunks(chunkPartition, minChunkSize) {
16440
16592
  dependentChunk.dependencies.add(closestChunk);
16441
16593
  }
16442
16594
  dependencies.delete(closestChunk);
16595
+ dependentChunks.delete(closestChunk);
16443
16596
  getChunksInPartition(closestChunk, minChunkSize, chunkPartition).add(closestChunk);
16444
16597
  }
16445
16598
  }
16446
- console.log('---- After run with arbitrary merges:', allowArbitraryMerges);
16447
- printConsistencyCheck(chunkPartition);
16448
16599
  }
16449
16600
  }
16450
16601
  // Merging will not produce cycles if none of the direct non-merged dependencies
@@ -16500,58 +16651,6 @@ function getChunkEntryDistance({ dependentEntries: sourceEntries }, { dependentE
16500
16651
  }
16501
16652
  return distance;
16502
16653
  }
16503
- function printConsistencyCheck(partition) {
16504
- console.log(`Chunks\n small: ${partition.small.size},\n large: ${partition.big.size}`);
16505
- const chunks = new Set([...partition.big, ...partition.small]);
16506
- console.log('Number of cycles:', getNumberOfCycles(chunks));
16507
- let missingDependencies = 0;
16508
- let missingDependentChunks = 0;
16509
- const seenModules = new Set();
16510
- for (const { modules, dependencies, dependentChunks } of chunks) {
16511
- for (const module of modules) {
16512
- if (seenModules.has(module)) {
16513
- console.log(`Module ${module.id} is duplicated between chunks.`);
16514
- }
16515
- seenModules.add(module);
16516
- }
16517
- for (const dependency of dependencies) {
16518
- if (!chunks.has(dependency)) {
16519
- missingDependencies++;
16520
- }
16521
- }
16522
- for (const dependency of dependentChunks) {
16523
- if (!chunks.has(dependency)) {
16524
- missingDependentChunks++;
16525
- }
16526
- }
16527
- }
16528
- console.log(`Missing\n dependencies: ${missingDependencies},\n dependent chunks: ${missingDependentChunks}\n`);
16529
- }
16530
- function getNumberOfCycles(chunks) {
16531
- const parents = new Set();
16532
- const analysedChunks = new Set();
16533
- let cycles = 0;
16534
- const analyseChunk = (chunk) => {
16535
- for (const dependency of chunk.dependencies) {
16536
- if (parents.has(dependency)) {
16537
- if (!analysedChunks.has(dependency)) {
16538
- cycles++;
16539
- }
16540
- continue;
16541
- }
16542
- parents.add(dependency);
16543
- analyseChunk(dependency);
16544
- }
16545
- analysedChunks.add(chunk);
16546
- };
16547
- for (const chunk of chunks) {
16548
- if (!parents.has(chunk)) {
16549
- parents.add(chunk);
16550
- analyseChunk(chunk);
16551
- }
16552
- }
16553
- return cycles;
16554
- }
16555
16654
 
16556
16655
  // ported from https://github.com/substack/node-commondir
16557
16656
  function commondir(files) {
@@ -16909,7 +17008,7 @@ async function transformChunk(magicString, fileName, usedModules, chunkGraph, op
16909
17008
  }
16910
17009
  return result.code;
16911
17010
  });
16912
- const { compact, dir, file, sourcemap, sourcemapExcludeSources, sourcemapFile, sourcemapPathTransform } = options;
17011
+ const { compact, dir, file, sourcemap, sourcemapExcludeSources, sourcemapFile, sourcemapPathTransform, sourcemapIgnoreList } = options;
16913
17012
  if (!compact && code[code.length - 1] !== '\n')
16914
17013
  code += '\n';
16915
17014
  if (sourcemap) {
@@ -16923,18 +17022,31 @@ async function transformChunk(magicString, fileName, usedModules, chunkGraph, op
16923
17022
  resultingFile = resolve(fileName);
16924
17023
  const decodedMap = magicString.generateDecodedMap({});
16925
17024
  map = collapseSourcemaps(resultingFile, decodedMap, usedModules, sourcemapChain, sourcemapExcludeSources, onwarn);
16926
- map.sources = map.sources
16927
- .map(sourcePath => {
17025
+ for (let sourcesIndex = 0; sourcesIndex < map.sources.length; ++sourcesIndex) {
17026
+ let sourcePath = map.sources[sourcesIndex];
17027
+ const sourcemapPath = `${resultingFile}.map`;
17028
+ if (sourcemapIgnoreList) {
17029
+ const ignoreList = sourcemapIgnoreList(sourcePath, sourcemapPath);
17030
+ if (typeof ignoreList !== 'boolean') {
17031
+ error(errorFailedValidation('sourcemapIgnoreList function must return a boolean.'));
17032
+ }
17033
+ if (ignoreList) {
17034
+ if (map.x_google_ignoreList === undefined) {
17035
+ map.x_google_ignoreList = [];
17036
+ }
17037
+ if (!map.x_google_ignoreList.includes(sourcesIndex)) {
17038
+ map.x_google_ignoreList.push(sourcesIndex);
17039
+ }
17040
+ }
17041
+ }
16928
17042
  if (sourcemapPathTransform) {
16929
- const newSourcePath = sourcemapPathTransform(sourcePath, `${resultingFile}.map`);
16930
- if (typeof newSourcePath !== 'string') {
17043
+ sourcePath = sourcemapPathTransform(sourcePath, sourcemapPath);
17044
+ if (typeof sourcePath !== 'string') {
16931
17045
  error(errorFailedValidation(`sourcemapPathTransform function must return a string.`));
16932
17046
  }
16933
- return newSourcePath;
16934
17047
  }
16935
- return sourcePath;
16936
- })
16937
- .map(normalize);
17048
+ map.sources[sourcesIndex] = normalize(sourcePath);
17049
+ }
16938
17050
  timeEnd('sourcemaps', 3);
16939
17051
  }
16940
17052
  return {
@@ -17152,7 +17264,7 @@ class Bundle {
17152
17264
  this.pluginDriver.finaliseAssets();
17153
17265
  }
17154
17266
  async generateChunks(bundle, getHashPlaceholder) {
17155
- const { experimentalDeepDynamicChunkOptimization, experimentalMinChunkSize, inlineDynamicImports, manualChunks, preserveModules } = this.outputOptions;
17267
+ const { experimentalMinChunkSize, inlineDynamicImports, manualChunks, preserveModules } = this.outputOptions;
17156
17268
  const manualChunkAliasByEntry = typeof manualChunks === 'object'
17157
17269
  ? await this.addManualChunks(manualChunks)
17158
17270
  : this.assignManualChunks(manualChunks);
@@ -17166,7 +17278,7 @@ class Bundle {
17166
17278
  ? [{ alias: null, modules: includedModules }]
17167
17279
  : preserveModules
17168
17280
  ? includedModules.map(module => ({ alias: null, modules: [module] }))
17169
- : getChunkAssignments(this.graph.entryModules, manualChunkAliasByEntry, experimentalMinChunkSize, experimentalDeepDynamicChunkOptimization)) {
17281
+ : getChunkAssignments(this.graph.entryModules, manualChunkAliasByEntry, experimentalMinChunkSize)) {
17170
17282
  sortByExecutionOrder(modules);
17171
17283
  const chunk = new Chunk(modules, this.inputOptions, this.outputOptions, this.unsetOptions, this.pluginDriver, this.graph.modulesById, chunkByModule, externalChunkByModule, this.facadeChunkByModule, this.includedNamespaces, alias, getHashPlaceholder, bundle, inputBase, snippets);
17172
17284
  chunks.push(chunk);
@@ -24301,7 +24413,8 @@ class Graph {
24301
24413
  }
24302
24414
  }
24303
24415
  includeStatements() {
24304
- for (const module of [...this.entryModules, ...this.implicitEntryModules]) {
24416
+ const entryModules = [...this.entryModules, ...this.implicitEntryModules];
24417
+ for (const module of entryModules) {
24305
24418
  markModuleAndImpureDependenciesAsExecuted(module);
24306
24419
  }
24307
24420
  if (this.options.treeshake) {
@@ -24322,7 +24435,7 @@ class Graph {
24322
24435
  if (treeshakingPass === 1) {
24323
24436
  // We only include exports after the first pass to avoid issues with
24324
24437
  // the TDZ detection logic
24325
- for (const module of [...this.entryModules, ...this.implicitEntryModules]) {
24438
+ for (const module of entryModules) {
24326
24439
  if (module.preserveSignature !== false) {
24327
24440
  module.includeAllExports(false);
24328
24441
  this.needsTreeshakingPass = true;
@@ -24810,7 +24923,9 @@ const getAcornInjectPlugins = (config) => [
24810
24923
  importAssertions,
24811
24924
  ...ensureArray(config.acornInjectPlugins)
24812
24925
  ];
24813
- const getCache = (config) => config.cache?.cache || config.cache;
24926
+ const getCache = (config) => config.cache === true // `true` is the default
24927
+ ? undefined
24928
+ : config.cache?.cache || config.cache;
24814
24929
  const getIdMatcher = (option) => {
24815
24930
  if (option === true) {
24816
24931
  return () => true;
@@ -24957,7 +25072,7 @@ async function normalizeOutputOptions(config, inputOptions, unsetInputOptions) {
24957
25072
  dynamicImportInCjs: config.dynamicImportInCjs ?? true,
24958
25073
  entryFileNames: getEntryFileNames(config, unsetOptions),
24959
25074
  esModule: config.esModule ?? 'if-default-prop',
24960
- experimentalDeepDynamicChunkOptimization: config.experimentalDeepDynamicChunkOptimization || false,
25075
+ experimentalDeepDynamicChunkOptimization: getExperimentalDeepDynamicChunkOptimization(config, inputOptions),
24961
25076
  experimentalMinChunkSize: config.experimentalMinChunkSize || 0,
24962
25077
  exports: getExports(config, unsetOptions),
24963
25078
  extend: config.extend || false,
@@ -24994,6 +25109,7 @@ async function normalizeOutputOptions(config, inputOptions, unsetInputOptions) {
24994
25109
  sourcemapBaseUrl: getSourcemapBaseUrl(config),
24995
25110
  sourcemapExcludeSources: config.sourcemapExcludeSources || false,
24996
25111
  sourcemapFile: config.sourcemapFile,
25112
+ sourcemapIgnoreList: config.sourcemapIgnoreList,
24997
25113
  sourcemapPathTransform: config.sourcemapPathTransform,
24998
25114
  strict: config.strict ?? true,
24999
25115
  systemNullSetters: config.systemNullSetters ?? true,
@@ -25134,6 +25250,13 @@ const getEntryFileNames = (config, unsetOptions) => {
25134
25250
  }
25135
25251
  return configEntryFileNames ?? '[name].js';
25136
25252
  };
25253
+ function getExperimentalDeepDynamicChunkOptimization(config, inputOptions) {
25254
+ const configExperimentalDeepDynamicChunkOptimization = config.experimentalDeepDynamicChunkOptimization;
25255
+ if (configExperimentalDeepDynamicChunkOptimization != null) {
25256
+ warnDeprecation(`The "output.experimentalDeepDynamicChunkOptimization" option is deprecated as Rollup always runs the full chunking algorithm now. The option should be removed.`, URL_OUTPUT_EXPERIMENTALDEEPCHUNKOPTIMIZATION, true, inputOptions);
25257
+ }
25258
+ return configExperimentalDeepDynamicChunkOptimization || false;
25259
+ }
25137
25260
  function getExports(config, unsetOptions) {
25138
25261
  const configExports = config.exports;
25139
25262
  if (configExports == null) {
@@ -25547,7 +25670,7 @@ async function mergeOptions(config, rawCommandOptions = EMPTY_COMMAND_OPTIONS, d
25547
25670
  const outputOptions = await Promise.all(outputOptionsArray.map(singleOutputOptions => mergeOutputOptions(singleOutputOptions, command, warn)));
25548
25671
  warnUnknownOptions(command, [
25549
25672
  ...Object.keys(inputOptions),
25550
- ...Object.keys(outputOptions[0]).filter(option => option !== 'sourcemapPathTransform'),
25673
+ ...Object.keys(outputOptions[0]).filter(option => option !== 'sourcemapIgnoreList' && option !== 'sourcemapPathTransform'),
25551
25674
  ...Object.keys(commandAliases),
25552
25675
  'bundleConfigAsCjs',
25553
25676
  'config',
@@ -25682,6 +25805,7 @@ async function mergeOutputOptions(config, overrides, warn) {
25682
25805
  sourcemapBaseUrl: getOption('sourcemapBaseUrl'),
25683
25806
  sourcemapExcludeSources: getOption('sourcemapExcludeSources'),
25684
25807
  sourcemapFile: getOption('sourcemapFile'),
25808
+ sourcemapIgnoreList: getOption('sourcemapIgnoreList'),
25685
25809
  sourcemapPathTransform: getOption('sourcemapPathTransform'),
25686
25810
  strict: getOption('strict'),
25687
25811
  systemNullSetters: getOption('systemNullSetters'),