rollup 3.4.0 → 3.5.0-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.4.0
4
- Tue, 22 Nov 2022 05:15:54 GMT - commit 780e3421e8a498f3248fd7d8506e97fcee8dd1e6
3
+ Rollup.js v3.5.0-0
4
+ Fri, 25 Nov 2022 05:53:50 GMT - commit b8beb21aa83e193ed6ef82f06127e95a7ef5fe22
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.4.0";
34
+ var version$1 = "3.5.0-0";
35
35
 
36
36
  function ensureArray$1(items) {
37
37
  if (Array.isArray(items)) {
@@ -50,6 +50,10 @@ async function asyncFlatten(array) {
50
50
  return array;
51
51
  }
52
52
 
53
+ const BLANK = Object.freeze(Object.create(null));
54
+ const EMPTY_OBJECT = Object.freeze({});
55
+ const EMPTY_ARRAY = Object.freeze([]);
56
+
53
57
  function getLocator$1(source, options) {
54
58
  if (options === void 0) { options = {}; }
55
59
  var offsetLine = options.offsetLine || 0;
@@ -814,6 +818,7 @@ const treeshakePresets = {
814
818
  recommended: {
815
819
  annotations: true,
816
820
  correctVarValueBeforeDeclaration: false,
821
+ manualPureFunctions: EMPTY_ARRAY,
817
822
  moduleSideEffects: () => true,
818
823
  propertyReadSideEffects: true,
819
824
  tryCatchDeoptimization: true,
@@ -822,6 +827,7 @@ const treeshakePresets = {
822
827
  safest: {
823
828
  annotations: true,
824
829
  correctVarValueBeforeDeclaration: true,
830
+ manualPureFunctions: EMPTY_ARRAY,
825
831
  moduleSideEffects: () => true,
826
832
  propertyReadSideEffects: true,
827
833
  tryCatchDeoptimization: true,
@@ -830,6 +836,7 @@ const treeshakePresets = {
830
836
  smallest: {
831
837
  annotations: true,
832
838
  correctVarValueBeforeDeclaration: false,
839
+ manualPureFunctions: EMPTY_ARRAY,
833
840
  moduleSideEffects: () => false,
834
841
  propertyReadSideEffects: false,
835
842
  tryCatchDeoptimization: false,
@@ -2916,7 +2923,7 @@ class ExpressionEntity {
2916
2923
  return UnknownValue;
2917
2924
  }
2918
2925
  getReturnExpressionWhenCalledAtPath(_path, _interaction, _recursionTracker, _origin) {
2919
- return UNKNOWN_EXPRESSION;
2926
+ return UNKNOWN_RETURN_EXPRESSION;
2920
2927
  }
2921
2928
  hasEffectsOnInteractionAtPath(_path, _interaction, _context) {
2922
2929
  return true;
@@ -2935,6 +2942,10 @@ class ExpressionEntity {
2935
2942
  }
2936
2943
  const UNKNOWN_EXPRESSION = new (class UnknownExpression extends ExpressionEntity {
2937
2944
  })();
2945
+ const UNKNOWN_RETURN_EXPRESSION = [
2946
+ UNKNOWN_EXPRESSION,
2947
+ false
2948
+ ];
2938
2949
 
2939
2950
  const INTERACTION_ACCESSED = 0;
2940
2951
  const INTERACTION_ASSIGNED = 1;
@@ -3035,10 +3046,6 @@ class ExternalVariable extends Variable {
3035
3046
  }
3036
3047
  }
3037
3048
 
3038
- const BLANK = Object.freeze(Object.create(null));
3039
- const EMPTY_OBJECT = Object.freeze({});
3040
- const EMPTY_ARRAY = Object.freeze([]);
3041
-
3042
3049
  const RESERVED_NAMES = new Set([
3043
3050
  'await',
3044
3051
  'break',
@@ -5442,7 +5449,7 @@ const UNKNOWN_LITERAL_BOOLEAN = new (class UnknownBoolean extends ExpressionEnti
5442
5449
  if (path.length === 1) {
5443
5450
  return getMemberReturnExpressionWhenCalled(literalBooleanMembers, path[0]);
5444
5451
  }
5445
- return UNKNOWN_EXPRESSION;
5452
+ return UNKNOWN_RETURN_EXPRESSION;
5446
5453
  }
5447
5454
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5448
5455
  if (interaction.type === INTERACTION_ACCESSED) {
@@ -5465,7 +5472,7 @@ const UNKNOWN_LITERAL_NUMBER = new (class UnknownNumber extends ExpressionEntity
5465
5472
  if (path.length === 1) {
5466
5473
  return getMemberReturnExpressionWhenCalled(literalNumberMembers, path[0]);
5467
5474
  }
5468
- return UNKNOWN_EXPRESSION;
5475
+ return UNKNOWN_RETURN_EXPRESSION;
5469
5476
  }
5470
5477
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5471
5478
  if (interaction.type === INTERACTION_ACCESSED) {
@@ -5488,7 +5495,7 @@ const UNKNOWN_LITERAL_STRING = new (class UnknownString extends ExpressionEntity
5488
5495
  if (path.length === 1) {
5489
5496
  return getMemberReturnExpressionWhenCalled(literalStringMembers, path[0]);
5490
5497
  }
5491
- return UNKNOWN_EXPRESSION;
5498
+ return UNKNOWN_RETURN_EXPRESSION;
5492
5499
  }
5493
5500
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5494
5501
  if (interaction.type === INTERACTION_ACCESSED) {
@@ -5609,8 +5616,8 @@ function hasMemberEffectWhenCalled(members, memberName, interaction, context) {
5609
5616
  }
5610
5617
  function getMemberReturnExpressionWhenCalled(members, memberName) {
5611
5618
  if (typeof memberName !== 'string' || !members[memberName])
5612
- return UNKNOWN_EXPRESSION;
5613
- return members[memberName].returns;
5619
+ return UNKNOWN_RETURN_EXPRESSION;
5620
+ return [members[memberName].returns, false];
5614
5621
  }
5615
5622
 
5616
5623
  // AST walker module for Mozilla Parser API compatible trees
@@ -6260,12 +6267,15 @@ class Method extends ExpressionEntity {
6260
6267
  }
6261
6268
  getReturnExpressionWhenCalledAtPath(path, { thisArg }) {
6262
6269
  if (path.length > 0) {
6263
- return UNKNOWN_EXPRESSION;
6270
+ return UNKNOWN_RETURN_EXPRESSION;
6264
6271
  }
6265
- return (this.description.returnsPrimitive ||
6266
- (this.description.returns === 'self'
6267
- ? thisArg || UNKNOWN_EXPRESSION
6268
- : this.description.returns()));
6272
+ return [
6273
+ this.description.returnsPrimitive ||
6274
+ (this.description.returns === 'self'
6275
+ ? thisArg || UNKNOWN_EXPRESSION
6276
+ : this.description.returns()),
6277
+ false
6278
+ ];
6269
6279
  }
6270
6280
  hasEffectsOnInteractionAtPath(path, interaction, context) {
6271
6281
  const { type } = interaction;
@@ -6508,7 +6518,7 @@ class ObjectEntity extends ExpressionEntity {
6508
6518
  }
6509
6519
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6510
6520
  if (path.length === 0) {
6511
- return UNKNOWN_EXPRESSION;
6521
+ return UNKNOWN_RETURN_EXPRESSION;
6512
6522
  }
6513
6523
  const [key, ...subPath] = path;
6514
6524
  const expressionAtPath = this.getMemberExpressionAndTrackDeopt(key, origin);
@@ -6518,7 +6528,7 @@ class ObjectEntity extends ExpressionEntity {
6518
6528
  if (this.prototypeExpression) {
6519
6529
  return this.prototypeExpression.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
6520
6530
  }
6521
- return UNKNOWN_EXPRESSION;
6531
+ return UNKNOWN_RETURN_EXPRESSION;
6522
6532
  }
6523
6533
  hasEffectsOnInteractionAtPath(path, interaction, context) {
6524
6534
  const [key, ...subPath] = path;
@@ -6990,12 +7000,12 @@ class LocalVariable extends Variable {
6990
7000
  }
6991
7001
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6992
7002
  if (this.isReassigned || !this.init) {
6993
- return UNKNOWN_EXPRESSION;
7003
+ return UNKNOWN_RETURN_EXPRESSION;
6994
7004
  }
6995
7005
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6996
7006
  this.expressionsToBeDeoptimized.push(origin);
6997
7007
  return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
6998
- }, UNKNOWN_EXPRESSION);
7008
+ }, UNKNOWN_RETURN_EXPRESSION);
6999
7009
  }
7000
7010
  hasEffectsOnInteractionAtPath(path, interaction, context) {
7001
7011
  switch (interaction.type) {
@@ -7352,6 +7362,19 @@ function is_reference (node, parent) {
7352
7362
  return false;
7353
7363
  }
7354
7364
 
7365
+ const PureFunctionKey = Symbol('PureFunction');
7366
+ const getPureFunctions = ({ treeshake }) => {
7367
+ const pureFunctions = Object.create(null);
7368
+ for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
7369
+ let currentFunctions = pureFunctions;
7370
+ for (const pathSegment of functionName.split('.')) {
7371
+ currentFunctions = currentFunctions[pathSegment] || (currentFunctions[pathSegment] = Object.create(null));
7372
+ }
7373
+ currentFunctions[PureFunctionKey] = true;
7374
+ }
7375
+ return pureFunctions;
7376
+ };
7377
+
7355
7378
  /* eslint sort-keys: "off" */
7356
7379
  const ValueProperties = Symbol('Value Properties');
7357
7380
  const getTruthyLiteralValue = () => UnknownTruthyValue;
@@ -8330,7 +8353,8 @@ class Identifier extends NodeBase {
8330
8353
  return this.getVariableRespectingTDZ().getLiteralValueAtPath(path, recursionTracker, origin);
8331
8354
  }
8332
8355
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
8333
- return this.getVariableRespectingTDZ().getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
8356
+ const [expression, isPure] = this.getVariableRespectingTDZ().getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
8357
+ return [expression, isPure || this.isPureFunction(path)];
8334
8358
  }
8335
8359
  hasEffects(context) {
8336
8360
  if (!this.deoptimized)
@@ -8340,19 +8364,22 @@ class Identifier extends NodeBase {
8340
8364
  }
8341
8365
  return (this.context.options.treeshake.unknownGlobalSideEffects &&
8342
8366
  this.variable instanceof GlobalVariable &&
8367
+ !this.isPureFunction(EMPTY_PATH) &&
8343
8368
  this.variable.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context));
8344
8369
  }
8345
8370
  hasEffectsOnInteractionAtPath(path, interaction, context) {
8346
8371
  switch (interaction.type) {
8347
8372
  case INTERACTION_ACCESSED: {
8348
8373
  return (this.variable !== null &&
8374
+ !this.isPureFunction(path) &&
8349
8375
  this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
8350
8376
  }
8351
8377
  case INTERACTION_ASSIGNED: {
8352
8378
  return (path.length > 0 ? this.getVariableRespectingTDZ() : this.variable).hasEffectsOnInteractionAtPath(path, interaction, context);
8353
8379
  }
8354
8380
  case INTERACTION_CALLED: {
8355
- return this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context);
8381
+ return (!this.isPureFunction(path) &&
8382
+ this.getVariableRespectingTDZ().hasEffectsOnInteractionAtPath(path, interaction, context));
8356
8383
  }
8357
8384
  }
8358
8385
  }
@@ -8434,6 +8461,21 @@ class Identifier extends NodeBase {
8434
8461
  }
8435
8462
  return this.variable;
8436
8463
  }
8464
+ isPureFunction(path) {
8465
+ let currentPureFunction = this.context.manualPureFunctions[this.name];
8466
+ for (const segment of path) {
8467
+ if (currentPureFunction) {
8468
+ if (currentPureFunction[PureFunctionKey]) {
8469
+ return true;
8470
+ }
8471
+ currentPureFunction = currentPureFunction[segment];
8472
+ }
8473
+ else {
8474
+ return false;
8475
+ }
8476
+ }
8477
+ return currentPureFunction?.[PureFunctionKey];
8478
+ }
8437
8479
  }
8438
8480
  function closestParentFunctionOrProgram(node) {
8439
8481
  while (node && !/^Program|Function/.test(node.type)) {
@@ -8755,9 +8797,9 @@ class FunctionBase extends NodeBase {
8755
8797
  this.scope.getReturnExpression().deoptimizePath(UNKNOWN_PATH);
8756
8798
  this.context.requestTreeshakingPass();
8757
8799
  }
8758
- return UNKNOWN_EXPRESSION;
8800
+ return UNKNOWN_RETURN_EXPRESSION;
8759
8801
  }
8760
- return this.scope.getReturnExpression();
8802
+ return [this.scope.getReturnExpression(), false];
8761
8803
  }
8762
8804
  hasEffectsOnInteractionAtPath(path, interaction, context) {
8763
8805
  if (path.length > 0 || interaction.type !== INTERACTION_CALLED) {
@@ -9356,7 +9398,7 @@ class Literal extends NodeBase {
9356
9398
  }
9357
9399
  getReturnExpressionWhenCalledAtPath(path) {
9358
9400
  if (path.length !== 1)
9359
- return UNKNOWN_EXPRESSION;
9401
+ return UNKNOWN_RETURN_EXPRESSION;
9360
9402
  return getMemberReturnExpressionWhenCalled(this.members, path[0]);
9361
9403
  }
9362
9404
  hasEffectsOnInteractionAtPath(path, interaction, context) {
@@ -9509,13 +9551,13 @@ class MemberExpression extends NodeBase {
9509
9551
  return this.variable.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
9510
9552
  }
9511
9553
  if (this.isUndefined) {
9512
- return UNDEFINED_EXPRESSION;
9554
+ return [UNDEFINED_EXPRESSION, false];
9513
9555
  }
9514
9556
  this.expressionsToBeDeoptimized.push(origin);
9515
9557
  if (path.length < MAX_PATH_DEPTH) {
9516
9558
  return this.object.getReturnExpressionWhenCalledAtPath([this.getPropertyKey(), ...path], interaction, recursionTracker, origin);
9517
9559
  }
9518
- return UNKNOWN_EXPRESSION;
9560
+ return UNKNOWN_RETURN_EXPRESSION;
9519
9561
  }
9520
9562
  hasEffects(context) {
9521
9563
  if (!this.deoptimized)
@@ -9692,8 +9734,8 @@ class CallExpressionBase extends NodeBase {
9692
9734
  this.expressionsToBeDeoptimized = new Set();
9693
9735
  }
9694
9736
  deoptimizeCache() {
9695
- if (this.returnExpression !== UNKNOWN_EXPRESSION) {
9696
- this.returnExpression = UNKNOWN_EXPRESSION;
9737
+ if (this.returnExpression?.[0] !== UNKNOWN_EXPRESSION) {
9738
+ this.returnExpression = UNKNOWN_RETURN_EXPRESSION;
9697
9739
  for (const expression of this.deoptimizableDependentExpressions) {
9698
9740
  expression.deoptimizeCache();
9699
9741
  }
@@ -9707,13 +9749,15 @@ class CallExpressionBase extends NodeBase {
9707
9749
  this.context.deoptimizationTracker.trackEntityAtPathAndGetIfTracked(path, this)) {
9708
9750
  return;
9709
9751
  }
9710
- const returnExpression = this.getReturnExpression();
9752
+ const [returnExpression] = this.getReturnExpression();
9711
9753
  if (returnExpression !== UNKNOWN_EXPRESSION) {
9712
9754
  returnExpression.deoptimizePath(path);
9713
9755
  }
9714
9756
  }
9715
9757
  deoptimizeThisOnInteractionAtPath(interaction, path, recursionTracker) {
9716
- const returnExpression = this.getReturnExpression(recursionTracker);
9758
+ const [returnExpression, isPure] = this.getReturnExpression(recursionTracker);
9759
+ if (isPure)
9760
+ return;
9717
9761
  if (returnExpression === UNKNOWN_EXPRESSION) {
9718
9762
  interaction.thisArg.deoptimizePath(UNKNOWN_PATH);
9719
9763
  }
@@ -9725,7 +9769,7 @@ class CallExpressionBase extends NodeBase {
9725
9769
  }
9726
9770
  }
9727
9771
  getLiteralValueAtPath(path, recursionTracker, origin) {
9728
- const returnExpression = this.getReturnExpression(recursionTracker);
9772
+ const [returnExpression] = this.getReturnExpression(recursionTracker);
9729
9773
  if (returnExpression === UNKNOWN_EXPRESSION) {
9730
9774
  return UnknownValue;
9731
9775
  }
@@ -9736,13 +9780,14 @@ class CallExpressionBase extends NodeBase {
9736
9780
  }
9737
9781
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
9738
9782
  const returnExpression = this.getReturnExpression(recursionTracker);
9739
- if (this.returnExpression === UNKNOWN_EXPRESSION) {
9740
- return UNKNOWN_EXPRESSION;
9783
+ if (returnExpression[0] === UNKNOWN_EXPRESSION) {
9784
+ return returnExpression;
9741
9785
  }
9742
9786
  return recursionTracker.withTrackedEntityAtPath(path, returnExpression, () => {
9743
9787
  this.deoptimizableDependentExpressions.push(origin);
9744
- return returnExpression.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
9745
- }, UNKNOWN_EXPRESSION);
9788
+ const [expression, isPure] = returnExpression[0].getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
9789
+ return [expression, isPure || returnExpression[1]];
9790
+ }, UNKNOWN_RETURN_EXPRESSION);
9746
9791
  }
9747
9792
  hasEffectsOnInteractionAtPath(path, interaction, context) {
9748
9793
  const { type } = interaction;
@@ -9757,7 +9802,9 @@ class CallExpressionBase extends NodeBase {
9757
9802
  : context.accessed).trackEntityAtPathAndGetIfTracked(path, this)) {
9758
9803
  return false;
9759
9804
  }
9760
- return this.getReturnExpression().hasEffectsOnInteractionAtPath(path, interaction, context);
9805
+ const [returnExpression, isPure] = this.getReturnExpression();
9806
+ return ((type === INTERACTION_ASSIGNED || !isPure) &&
9807
+ returnExpression.hasEffectsOnInteractionAtPath(path, interaction, context));
9761
9808
  }
9762
9809
  }
9763
9810
 
@@ -9836,7 +9883,7 @@ class CallExpression extends CallExpressionBase {
9836
9883
  }
9837
9884
  getReturnExpression(recursionTracker = SHARED_RECURSION_TRACKER) {
9838
9885
  if (this.returnExpression === null) {
9839
- this.returnExpression = UNKNOWN_EXPRESSION;
9886
+ this.returnExpression = UNKNOWN_RETURN_EXPRESSION;
9840
9887
  return (this.returnExpression = this.callee.getReturnExpressionWhenCalledAtPath(EMPTY_PATH, this.interaction, recursionTracker, this));
9841
9888
  }
9842
9889
  return this.returnExpression;
@@ -9920,7 +9967,7 @@ class MethodBase extends NodeBase {
9920
9967
  // expressions, there is no known situation where a getter is deoptimized.
9921
9968
  deoptimizeCache() { }
9922
9969
  deoptimizePath(path) {
9923
- this.getAccessedValue().deoptimizePath(path);
9970
+ this.getAccessedValue()[0].deoptimizePath(path);
9924
9971
  }
9925
9972
  deoptimizeThisOnInteractionAtPath(interaction, path, recursionTracker) {
9926
9973
  if (interaction.type === INTERACTION_ACCESSED && this.kind === 'get' && path.length === 0) {
@@ -9939,13 +9986,13 @@ class MethodBase extends NodeBase {
9939
9986
  withNew: false
9940
9987
  }, EMPTY_PATH, recursionTracker);
9941
9988
  }
9942
- this.getAccessedValue().deoptimizeThisOnInteractionAtPath(interaction, path, recursionTracker);
9989
+ this.getAccessedValue()[0].deoptimizeThisOnInteractionAtPath(interaction, path, recursionTracker);
9943
9990
  }
9944
9991
  getLiteralValueAtPath(path, recursionTracker, origin) {
9945
- return this.getAccessedValue().getLiteralValueAtPath(path, recursionTracker, origin);
9992
+ return this.getAccessedValue()[0].getLiteralValueAtPath(path, recursionTracker, origin);
9946
9993
  }
9947
9994
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
9948
- return this.getAccessedValue().getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
9995
+ return this.getAccessedValue()[0].getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
9949
9996
  }
9950
9997
  hasEffects(context) {
9951
9998
  return this.key.hasEffects(context);
@@ -9968,17 +10015,17 @@ class MethodBase extends NodeBase {
9968
10015
  withNew: false
9969
10016
  }, context);
9970
10017
  }
9971
- return this.getAccessedValue().hasEffectsOnInteractionAtPath(path, interaction, context);
10018
+ return this.getAccessedValue()[0].hasEffectsOnInteractionAtPath(path, interaction, context);
9972
10019
  }
9973
10020
  applyDeoptimizations() { }
9974
10021
  getAccessedValue() {
9975
10022
  if (this.accessedValue === null) {
9976
10023
  if (this.kind === 'get') {
9977
- this.accessedValue = UNKNOWN_EXPRESSION;
10024
+ this.accessedValue = UNKNOWN_RETURN_EXPRESSION;
9978
10025
  return (this.accessedValue = this.value.getReturnExpressionWhenCalledAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_CALL, SHARED_RECURSION_TRACKER, this));
9979
10026
  }
9980
10027
  else {
9981
- return (this.accessedValue = this.value);
10028
+ return (this.accessedValue = [this.value, false]);
9982
10029
  }
9983
10030
  }
9984
10031
  return this.accessedValue;
@@ -10191,7 +10238,10 @@ class MultiExpression extends ExpressionEntity {
10191
10238
  }
10192
10239
  }
10193
10240
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
10194
- return new MultiExpression(this.expressions.map(expression => expression.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)));
10241
+ return [
10242
+ new MultiExpression(this.expressions.map(expression => expression.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0])),
10243
+ false
10244
+ ];
10195
10245
  }
10196
10246
  hasEffectsOnInteractionAtPath(path, interaction, context) {
10197
10247
  for (const expression of this.expressions) {
@@ -10243,10 +10293,13 @@ class ConditionalExpression extends NodeBase {
10243
10293
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
10244
10294
  const usedBranch = this.getUsedBranch();
10245
10295
  if (!usedBranch)
10246
- return new MultiExpression([
10247
- this.consequent.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin),
10248
- this.alternate.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)
10249
- ]);
10296
+ return [
10297
+ new MultiExpression([
10298
+ this.consequent.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
10299
+ this.alternate.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
10300
+ ]),
10301
+ false
10302
+ ];
10250
10303
  this.expressionsToBeDeoptimized.push(origin);
10251
10304
  return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
10252
10305
  }
@@ -11371,10 +11424,13 @@ class LogicalExpression extends NodeBase {
11371
11424
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
11372
11425
  const usedBranch = this.getUsedBranch();
11373
11426
  if (!usedBranch)
11374
- return new MultiExpression([
11375
- this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin),
11376
- this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)
11377
- ]);
11427
+ return [
11428
+ new MultiExpression([
11429
+ this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
11430
+ this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
11431
+ ]),
11432
+ false
11433
+ ];
11378
11434
  this.expressionsToBeDeoptimized.push(origin);
11379
11435
  return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
11380
11436
  }
@@ -11712,7 +11768,12 @@ class PrivateIdentifier extends NodeBase {
11712
11768
  class Program extends NodeBase {
11713
11769
  constructor() {
11714
11770
  super(...arguments);
11715
- this.hasCachedEffect = false;
11771
+ this.hasCachedEffect = null;
11772
+ }
11773
+ hasCachedEffects() {
11774
+ return this.hasCachedEffect === null
11775
+ ? (this.hasCachedEffect = this.hasEffects(createHasEffectsContext()))
11776
+ : this.hasCachedEffect;
11716
11777
  }
11717
11778
  hasEffects(context) {
11718
11779
  // We are caching here to later more efficiently identify side-effect-free modules
@@ -11800,7 +11861,7 @@ class PropertyDefinition extends NodeBase {
11800
11861
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
11801
11862
  return this.value
11802
11863
  ? this.value.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)
11803
- : UNKNOWN_EXPRESSION;
11864
+ : UNKNOWN_RETURN_EXPRESSION;
11804
11865
  }
11805
11866
  hasEffects(context) {
11806
11867
  return this.key.hasEffects(context) || (this.static && !!this.value?.hasEffects(context));
@@ -12091,7 +12152,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
12091
12152
  this.quasi.include(context, includeChildrenRecursively);
12092
12153
  }
12093
12154
  this.tag.includeCallArguments(context, this.interaction.args);
12094
- const returnExpression = this.getReturnExpression();
12155
+ const [returnExpression] = this.getReturnExpression();
12095
12156
  if (!returnExpression.included) {
12096
12157
  returnExpression.include(context, false);
12097
12158
  }
@@ -12121,7 +12182,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
12121
12182
  }
12122
12183
  getReturnExpression(recursionTracker = SHARED_RECURSION_TRACKER) {
12123
12184
  if (this.returnExpression === null) {
12124
- this.returnExpression = UNKNOWN_EXPRESSION;
12185
+ this.returnExpression = UNKNOWN_RETURN_EXPRESSION;
12125
12186
  return (this.returnExpression = this.tag.getReturnExpressionWhenCalledAtPath(EMPTY_PATH, this.interaction, recursionTracker, this));
12126
12187
  }
12127
12188
  return this.returnExpression;
@@ -12154,7 +12215,7 @@ class TemplateLiteral extends NodeBase {
12154
12215
  }
12155
12216
  getReturnExpressionWhenCalledAtPath(path) {
12156
12217
  if (path.length !== 1) {
12157
- return UNKNOWN_EXPRESSION;
12218
+ return UNKNOWN_RETURN_EXPRESSION;
12158
12219
  }
12159
12220
  return getMemberReturnExpressionWhenCalled(literalStringMembers, path[0]);
12160
12221
  }
@@ -13555,8 +13616,7 @@ class Module {
13555
13616
  return [null];
13556
13617
  }
13557
13618
  hasEffects() {
13558
- return (this.info.moduleSideEffects === 'no-treeshake' ||
13559
- (this.ast.included && this.ast.hasEffects(createHasEffectsContext())));
13619
+ return this.info.moduleSideEffects === 'no-treeshake' || this.ast.hasCachedEffects();
13560
13620
  }
13561
13621
  include() {
13562
13622
  const context = createInclusionContext();
@@ -13668,6 +13728,7 @@ class Module {
13668
13728
  includeDynamicImport: this.includeDynamicImport.bind(this),
13669
13729
  includeVariableInModule: this.includeVariableInModule.bind(this),
13670
13730
  magicString: this.magicString,
13731
+ manualPureFunctions: this.graph.pureFunctions,
13671
13732
  module: this,
13672
13733
  moduleContext: this.context,
13673
13734
  options: this.options,
@@ -16152,12 +16213,132 @@ function getImportedBindingsPerDependency(renderedDependencies, resolveFileName)
16152
16213
  const QUERY_HASH_REGEX = /[#?]/;
16153
16214
  const resolveFileName = (dependency) => dependency.getFileName();
16154
16215
 
16216
+ const BYTE_UNITS = [
16217
+ 'B',
16218
+ 'kB',
16219
+ 'MB',
16220
+ 'GB',
16221
+ 'TB',
16222
+ 'PB',
16223
+ 'EB',
16224
+ 'ZB',
16225
+ 'YB',
16226
+ ];
16227
+
16228
+ const BIBYTE_UNITS = [
16229
+ 'B',
16230
+ 'kiB',
16231
+ 'MiB',
16232
+ 'GiB',
16233
+ 'TiB',
16234
+ 'PiB',
16235
+ 'EiB',
16236
+ 'ZiB',
16237
+ 'YiB',
16238
+ ];
16239
+
16240
+ const BIT_UNITS = [
16241
+ 'b',
16242
+ 'kbit',
16243
+ 'Mbit',
16244
+ 'Gbit',
16245
+ 'Tbit',
16246
+ 'Pbit',
16247
+ 'Ebit',
16248
+ 'Zbit',
16249
+ 'Ybit',
16250
+ ];
16251
+
16252
+ const BIBIT_UNITS = [
16253
+ 'b',
16254
+ 'kibit',
16255
+ 'Mibit',
16256
+ 'Gibit',
16257
+ 'Tibit',
16258
+ 'Pibit',
16259
+ 'Eibit',
16260
+ 'Zibit',
16261
+ 'Yibit',
16262
+ ];
16263
+
16264
+ /*
16265
+ Formats the given number using `Number#toLocaleString`.
16266
+ - If locale is a string, the value is expected to be a locale-key (for example: `de`).
16267
+ - If locale is true, the system default locale is used for translation.
16268
+ - If no value for locale is specified, the number is returned unmodified.
16269
+ */
16270
+ const toLocaleString = (number, locale, options) => {
16271
+ let result = number;
16272
+ if (typeof locale === 'string' || Array.isArray(locale)) {
16273
+ result = number.toLocaleString(locale, options);
16274
+ } else if (locale === true || options !== undefined) {
16275
+ result = number.toLocaleString(undefined, options);
16276
+ }
16277
+
16278
+ return result;
16279
+ };
16280
+
16281
+ function prettyBytes(number, options) {
16282
+ if (!Number.isFinite(number)) {
16283
+ throw new TypeError(`Expected a finite number, got ${typeof number}: ${number}`);
16284
+ }
16285
+
16286
+ options = {
16287
+ bits: false,
16288
+ binary: false,
16289
+ ...options,
16290
+ };
16291
+
16292
+ const UNITS = options.bits
16293
+ ? (options.binary ? BIBIT_UNITS : BIT_UNITS)
16294
+ : (options.binary ? BIBYTE_UNITS : BYTE_UNITS);
16295
+
16296
+ if (options.signed && number === 0) {
16297
+ return ` 0 ${UNITS[0]}`;
16298
+ }
16299
+
16300
+ const isNegative = number < 0;
16301
+ const prefix = isNegative ? '-' : (options.signed ? '+' : '');
16302
+
16303
+ if (isNegative) {
16304
+ number = -number;
16305
+ }
16306
+
16307
+ let localeOptions;
16308
+
16309
+ if (options.minimumFractionDigits !== undefined) {
16310
+ localeOptions = {minimumFractionDigits: options.minimumFractionDigits};
16311
+ }
16312
+
16313
+ if (options.maximumFractionDigits !== undefined) {
16314
+ localeOptions = {maximumFractionDigits: options.maximumFractionDigits, ...localeOptions};
16315
+ }
16316
+
16317
+ if (number < 1) {
16318
+ const numberString = toLocaleString(number, options.locale, localeOptions);
16319
+ return prefix + numberString + ' ' + UNITS[0];
16320
+ }
16321
+
16322
+ const exponent = Math.min(Math.floor(options.binary ? Math.log(number) / Math.log(1024) : Math.log10(number) / 3), UNITS.length - 1);
16323
+ number /= (options.binary ? 1024 : 1000) ** exponent;
16324
+
16325
+ if (!localeOptions) {
16326
+ number = number.toPrecision(3);
16327
+ }
16328
+
16329
+ const numberString = toLocaleString(Number(number), options.locale, localeOptions);
16330
+
16331
+ const unit = UNITS[exponent];
16332
+
16333
+ return prefix + numberString + ' ' + unit;
16334
+ }
16335
+
16155
16336
  /**
16156
16337
  * Concatenate a number of iterables to a new iterable without fully evaluating
16157
16338
  * their iterators. Useful when e.g. working with large sets or lists and when
16158
16339
  * there is a chance that the iterators will not be fully exhausted.
16159
16340
  */
16160
- function* concatLazy(...iterables) {
16341
+ function* concatLazy(iterables) {
16161
16342
  for (const iterable of iterables) {
16162
16343
  yield* iterable;
16163
16344
  }
@@ -16283,43 +16464,37 @@ function createChunks(allEntryPoints, assignedEntryPointsByModule, minChunkSize)
16283
16464
  alias: null,
16284
16465
  modules
16285
16466
  }))
16286
- : getOptimizedChunks(chunkModulesBySignature, minChunkSize);
16467
+ : getOptimizedChunks(chunkModulesBySignature, minChunkSize).map(({ modules }) => ({
16468
+ alias: null,
16469
+ modules
16470
+ }));
16287
16471
  }
16288
16472
  function getOptimizedChunks(chunkModulesBySignature, minChunkSize) {
16289
16473
  timeStart('optimize chunks', 3);
16290
- const { chunksToBeMerged, unmergeableChunks } = getMergeableChunks(chunkModulesBySignature, minChunkSize);
16291
- for (const sourceChunk of chunksToBeMerged) {
16292
- chunksToBeMerged.delete(sourceChunk);
16293
- let closestChunk = null;
16294
- let closestChunkDistance = Infinity;
16295
- const { signature, size, modules } = sourceChunk;
16296
- for (const targetChunk of concatLazy(chunksToBeMerged, unmergeableChunks)) {
16297
- const distance = getSignatureDistance(signature, targetChunk.signature, !chunksToBeMerged.has(targetChunk));
16298
- if (distance === 1) {
16299
- closestChunk = targetChunk;
16300
- break;
16301
- }
16302
- else if (distance < closestChunkDistance) {
16303
- closestChunk = targetChunk;
16304
- closestChunkDistance = distance;
16305
- }
16306
- }
16307
- if (closestChunk) {
16308
- closestChunk.modules.push(...modules);
16309
- if (chunksToBeMerged.has(closestChunk)) {
16310
- closestChunk.signature = mergeSignatures(signature, closestChunk.signature);
16311
- if ((closestChunk.size += size) > minChunkSize) {
16312
- chunksToBeMerged.delete(closestChunk);
16313
- unmergeableChunks.push(closestChunk);
16314
- }
16315
- }
16316
- }
16317
- else {
16318
- unmergeableChunks.push(sourceChunk);
16319
- }
16320
- }
16474
+ const chunkPartition = getPartitionedChunks(chunkModulesBySignature, minChunkSize);
16475
+ console.log(`Created ${chunkPartition.big.pure.size +
16476
+ chunkPartition.big.sideEffect.size +
16477
+ chunkPartition.small.pure.size +
16478
+ chunkPartition.small.sideEffect.size} chunks
16479
+ ----- pure side effects
16480
+ small ${`${chunkPartition.small.pure.size}`.padEnd(5, ' ')} ${chunkPartition.small.sideEffect.size}
16481
+ big ${`${chunkPartition.big.pure.size}`.padEnd(5, ' ')} ${chunkPartition.big.sideEffect.size}
16482
+ `);
16483
+ console.log(`Trying to find merge targets for ${chunkPartition.small.sideEffect.size} chunks smaller than ${prettyBytes(minChunkSize)} with side effects...`);
16484
+ mergeChunks(chunkPartition.small.sideEffect, [chunkPartition.small.pure, chunkPartition.big.pure], minChunkSize, chunkPartition);
16485
+ console.log(`${chunkPartition.small.sideEffect.size} chunks smaller than ${prettyBytes(minChunkSize)} with side effects remaining.\n`);
16486
+ console.log(`Trying to find merge targets for ${chunkPartition.small.pure.size} pure chunks smaller than ${prettyBytes(minChunkSize)}...`);
16487
+ mergeChunks(chunkPartition.small.pure, [chunkPartition.small.pure, chunkPartition.big.sideEffect, chunkPartition.big.pure], minChunkSize, chunkPartition);
16488
+ console.log(`${chunkPartition.small.pure.size} pure chunks smaller than ${prettyBytes(minChunkSize)} remaining.\n`);
16321
16489
  timeEnd('optimize chunks', 3);
16322
- return unmergeableChunks;
16490
+ const result = [
16491
+ ...chunkPartition.small.sideEffect,
16492
+ ...chunkPartition.small.pure,
16493
+ ...chunkPartition.big.sideEffect,
16494
+ ...chunkPartition.big.pure
16495
+ ];
16496
+ console.log(`${result.length} chunks remaining.`);
16497
+ return result;
16323
16498
  }
16324
16499
  const CHAR_DEPENDENT = 'X';
16325
16500
  const CHAR_INDEPENDENT = '_';
@@ -16341,28 +16516,76 @@ function getChunkModulesBySignature(assignedEntryPointsByModule, allEntryPoints)
16341
16516
  }
16342
16517
  return chunkModules;
16343
16518
  }
16344
- function getMergeableChunks(chunkModulesBySignature, minChunkSize) {
16345
- const chunksToBeMerged = new Set();
16346
- const unmergeableChunks = [];
16347
- const alias = null;
16519
+ function getPartitionedChunks(chunkModulesBySignature, minChunkSize) {
16520
+ const smallPureChunks = [];
16521
+ const bigPureChunks = [];
16522
+ const smallSideEffectChunks = [];
16523
+ const bigSideEffectChunks = [];
16348
16524
  for (const [signature, modules] of Object.entries(chunkModulesBySignature)) {
16349
16525
  let size = 0;
16350
- checkModules: {
16351
- for (const module of modules) {
16352
- if (module.hasEffects()) {
16353
- break checkModules;
16354
- }
16355
- size += module.magicString.toString().length;
16356
- if (size > minChunkSize) {
16357
- break checkModules;
16358
- }
16526
+ let pure = true;
16527
+ for (const module of modules) {
16528
+ pure && (pure = !module.hasEffects());
16529
+ size += module.magicString.toString().length;
16530
+ }
16531
+ (size < minChunkSize
16532
+ ? pure
16533
+ ? smallPureChunks
16534
+ : smallSideEffectChunks
16535
+ : pure
16536
+ ? bigPureChunks
16537
+ : bigSideEffectChunks).push({ modules, pure, signature, size });
16538
+ }
16539
+ for (const chunks of [
16540
+ bigPureChunks,
16541
+ bigSideEffectChunks,
16542
+ smallPureChunks,
16543
+ smallSideEffectChunks
16544
+ ]) {
16545
+ chunks.sort(compareChunks);
16546
+ }
16547
+ return {
16548
+ big: { pure: new Set(bigPureChunks), sideEffect: new Set(bigSideEffectChunks) },
16549
+ small: { pure: new Set(smallPureChunks), sideEffect: new Set(smallSideEffectChunks) }
16550
+ };
16551
+ }
16552
+ function compareChunks({ size: sizeA }, { size: sizeB }) {
16553
+ return sizeA - sizeB;
16554
+ }
16555
+ function mergeChunks(chunksToBeMerged, targetChunks, minChunkSize, chunkPartition) {
16556
+ for (const mergedChunk of chunksToBeMerged) {
16557
+ let closestChunk = null;
16558
+ let closestChunkDistance = Infinity;
16559
+ const { signature, modules, pure, size } = mergedChunk;
16560
+ for (const targetChunk of concatLazy(targetChunks)) {
16561
+ if (mergedChunk === targetChunk)
16562
+ continue;
16563
+ const distance = pure
16564
+ ? getSignatureDistance(signature, targetChunk.signature, !targetChunk.pure)
16565
+ : getSignatureDistance(targetChunk.signature, signature, true);
16566
+ if (distance === 1) {
16567
+ closestChunk = targetChunk;
16568
+ break;
16569
+ }
16570
+ else if (distance < closestChunkDistance) {
16571
+ closestChunk = targetChunk;
16572
+ closestChunkDistance = distance;
16359
16573
  }
16360
- chunksToBeMerged.add({ alias, modules, signature, size });
16361
- continue;
16362
16574
  }
16363
- unmergeableChunks.push({ alias, modules, signature, size: null });
16575
+ if (closestChunk) {
16576
+ chunksToBeMerged.delete(mergedChunk);
16577
+ getChunksInPartition(closestChunk, minChunkSize, chunkPartition).delete(closestChunk);
16578
+ closestChunk.modules.push(...modules);
16579
+ closestChunk.size += size;
16580
+ closestChunk.pure && (closestChunk.pure = pure);
16581
+ closestChunk.signature = mergeSignatures(signature, closestChunk.signature);
16582
+ getChunksInPartition(closestChunk, minChunkSize, chunkPartition).add(closestChunk);
16583
+ }
16364
16584
  }
16365
- return { chunksToBeMerged, unmergeableChunks };
16585
+ }
16586
+ function getChunksInPartition(chunk, minChunkSize, chunkPartition) {
16587
+ const subPartition = chunk.size < minChunkSize ? chunkPartition.small : chunkPartition.big;
16588
+ return chunk.pure ? subPartition.pure : subPartition.sideEffect;
16366
16589
  }
16367
16590
  function getSignatureDistance(sourceSignature, targetSignature, enforceSubset) {
16368
16591
  let distance = 0;
@@ -23989,6 +24212,7 @@ class Graph {
23989
24212
  this.acornParser = Parser.extend(...options.acornInjectPlugins);
23990
24213
  this.moduleLoader = new ModuleLoader(this, this.modulesById, this.options, this.pluginDriver);
23991
24214
  this.fileOperationQueue = new Queue(options.maxParallelFileOps);
24215
+ this.pureFunctions = getPureFunctions(options);
23992
24216
  }
23993
24217
  async build() {
23994
24218
  timeStart('generate module graph', 2);
@@ -24606,6 +24830,7 @@ const getTreeshake = (config) => {
24606
24830
  return {
24607
24831
  annotations: configWithPreset.annotations !== false,
24608
24832
  correctVarValueBeforeDeclaration: configWithPreset.correctVarValueBeforeDeclaration === true,
24833
+ manualPureFunctions: configWithPreset.manualPureFunctions ?? EMPTY_ARRAY,
24609
24834
  moduleSideEffects: getHasModuleSideEffects(configWithPreset.moduleSideEffects),
24610
24835
  propertyReadSideEffects: configWithPreset.propertyReadSideEffects === 'always'
24611
24836
  ? 'always'
@@ -25194,6 +25419,7 @@ exports.loadFsEvents = loadFsEvents;
25194
25419
  exports.mergeOptions = mergeOptions;
25195
25420
  exports.normalizePluginOption = normalizePluginOption;
25196
25421
  exports.picomatch = picomatch$1;
25422
+ exports.prettyBytes = prettyBytes;
25197
25423
  exports.printQuotedStringList = printQuotedStringList;
25198
25424
  exports.relativeId = relativeId;
25199
25425
  exports.rollup = rollup;