@rollup/wasm-node 4.29.1 → 4.30.0-1

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 v4.29.1
4
- Sat, 21 Dec 2024 07:15:31 GMT - commit 5d3777803404c67ce14c62b8b05d6e26e46856f5
3
+ Rollup.js v4.30.0-1
4
+ Mon, 30 Dec 2024 06:51:45 GMT - commit 41ab39a6e4a5181e9be21e816dd6f11c57e1c52a
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 = "4.29.1";
34
+ var version = "4.30.0-1";
35
35
 
36
36
  function ensureArray$1(items) {
37
37
  if (Array.isArray(items)) {
@@ -1501,48 +1501,8 @@ const createColors = ({ useColor = isColorSupported } = {}) =>
1501
1501
  );
1502
1502
 
1503
1503
  const {
1504
- reset,
1505
- bold: bold$1,
1506
- dim: dim$1,
1507
- italic,
1508
- underline: underline$1,
1509
- inverse,
1510
- hidden,
1511
- strikethrough,
1512
- black,
1513
- red: red$1,
1514
- green: green$1,
1515
- yellow: yellow$1,
1516
1504
  blue,
1517
- magenta,
1518
- cyan: cyan$1,
1519
- white,
1520
- gray: gray$1,
1521
- bgBlack,
1522
- bgRed,
1523
- bgGreen,
1524
- bgYellow,
1525
- bgBlue,
1526
- bgMagenta,
1527
- bgCyan,
1528
- bgWhite,
1529
- blackBright,
1530
- redBright,
1531
- greenBright,
1532
- yellowBright,
1533
- blueBright,
1534
- magentaBright,
1535
- cyanBright,
1536
- whiteBright,
1537
- bgBlackBright,
1538
- bgRedBright,
1539
- bgGreenBright,
1540
- bgYellowBright,
1541
- bgBlueBright,
1542
- bgMagentaBright,
1543
- bgCyanBright,
1544
- bgWhiteBright,
1545
- } = createColors();
1505
+ cyan: cyan$1} = createColors();
1546
1506
 
1547
1507
  // @see https://no-color.org
1548
1508
  // @see https://www.npmjs.com/package/chalk
@@ -3539,71 +3499,6 @@ function renderSystemExportSequenceBeforeExpression(exportedVariable, expression
3539
3499
  }
3540
3500
  }
3541
3501
 
3542
- /** @import { Node } from 'estree' */
3543
-
3544
- /**
3545
- * @param {Node} node
3546
- * @param {Node} parent
3547
- * @returns {boolean}
3548
- */
3549
- function is_reference(node, parent) {
3550
- if (node.type === 'MemberExpression') {
3551
- return !node.computed && is_reference(node.object, node);
3552
- }
3553
-
3554
- if (node.type !== 'Identifier') return false;
3555
-
3556
- switch (parent?.type) {
3557
- // disregard `bar` in `foo.bar`
3558
- case 'MemberExpression':
3559
- return parent.computed || node === parent.object;
3560
-
3561
- // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
3562
- case 'MethodDefinition':
3563
- return parent.computed;
3564
-
3565
- // disregard the `meta` in `import.meta`
3566
- case 'MetaProperty':
3567
- return parent.meta === node;
3568
-
3569
- // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
3570
- case 'PropertyDefinition':
3571
- return parent.computed || node === parent.value;
3572
-
3573
- // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
3574
- case 'Property':
3575
- return parent.computed || node === parent.value;
3576
-
3577
- // disregard the `bar` in `export { foo as bar }` or
3578
- // the foo in `import { foo as bar }`
3579
- case 'ExportSpecifier':
3580
- case 'ImportSpecifier':
3581
- return node === parent.local;
3582
-
3583
- // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
3584
- case 'LabeledStatement':
3585
- case 'BreakStatement':
3586
- case 'ContinueStatement':
3587
- return false;
3588
-
3589
- default:
3590
- return true;
3591
- }
3592
- }
3593
-
3594
- const PureFunctionKey = Symbol('PureFunction');
3595
- const getPureFunctions = ({ treeshake }) => {
3596
- const pureFunctions = Object.create(null);
3597
- for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
3598
- let currentFunctions = pureFunctions;
3599
- for (const pathSegment of functionName.split('.')) {
3600
- currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
3601
- }
3602
- currentFunctions[PureFunctionKey] = true;
3603
- }
3604
- return pureFunctions;
3605
- };
3606
-
3607
3502
  const UnknownKey = Symbol('Unknown Key');
3608
3503
  const UnknownNonAccessorKey = Symbol('Unknown Non-Accessor Key');
3609
3504
  const UnknownInteger = Symbol('Unknown Integer');
@@ -3618,7 +3513,7 @@ const UNKNOWN_PATH = [UnknownKey];
3618
3513
  const UNKNOWN_NON_ACCESSOR_PATH = [UnknownNonAccessorKey];
3619
3514
  const UNKNOWN_INTEGER_PATH = [UnknownInteger];
3620
3515
  const EntitiesKey = Symbol('Entities');
3621
- class PathTracker {
3516
+ class EntityPathTracker {
3622
3517
  constructor() {
3623
3518
  this.entityPaths = Object.create(null, {
3624
3519
  [EntitiesKey]: { value: new Set() }
@@ -3643,14 +3538,14 @@ class PathTracker {
3643
3538
  getEntities(path) {
3644
3539
  let currentPaths = this.entityPaths;
3645
3540
  for (const pathSegment of path) {
3646
- currentPaths = currentPaths[pathSegment] =
3647
- currentPaths[pathSegment] ||
3648
- Object.create(null, { [EntitiesKey]: { value: new Set() } });
3541
+ currentPaths = currentPaths[pathSegment] ||= Object.create(null, {
3542
+ [EntitiesKey]: { value: new Set() }
3543
+ });
3649
3544
  }
3650
3545
  return currentPaths[EntitiesKey];
3651
3546
  }
3652
3547
  }
3653
- const SHARED_RECURSION_TRACKER = new PathTracker();
3548
+ const SHARED_RECURSION_TRACKER = new EntityPathTracker();
3654
3549
  class DiscriminatedPathTracker {
3655
3550
  constructor() {
3656
3551
  this.entityPaths = Object.create(null, {
@@ -3660,9 +3555,9 @@ class DiscriminatedPathTracker {
3660
3555
  trackEntityAtPathAndGetIfTracked(path, discriminator, entity) {
3661
3556
  let currentPaths = this.entityPaths;
3662
3557
  for (const pathSegment of path) {
3663
- currentPaths = currentPaths[pathSegment] =
3664
- currentPaths[pathSegment] ||
3665
- Object.create(null, { [EntitiesKey]: { value: new Map() } });
3558
+ currentPaths = currentPaths[pathSegment] ||= Object.create(null, {
3559
+ [EntitiesKey]: { value: new Map() }
3560
+ });
3666
3561
  }
3667
3562
  const trackedEntities = getOrCreate(currentPaths[EntitiesKey], discriminator, (getNewSet));
3668
3563
  if (trackedEntities.has(entity))
@@ -3671,6 +3566,137 @@ class DiscriminatedPathTracker {
3671
3566
  return false;
3672
3567
  }
3673
3568
  }
3569
+ const UNKNOWN_INCLUDED_PATH = Object.freeze({ [UnknownKey]: parseAst_js.EMPTY_OBJECT });
3570
+ class IncludedPathTracker {
3571
+ constructor() {
3572
+ this.includedPaths = null;
3573
+ }
3574
+ includePathAndGetIfIncluded(path) {
3575
+ let included = true;
3576
+ let parent = this;
3577
+ let parentSegment = 'includedPaths';
3578
+ let currentPaths = (this.includedPaths ||=
3579
+ ((included = false), Object.create(null)));
3580
+ for (const pathSegment of path) {
3581
+ // This means from here, all paths are included
3582
+ if (currentPaths[UnknownKey]) {
3583
+ return true;
3584
+ }
3585
+ // Including UnknownKey automatically includes all nested paths.
3586
+ // From above, we know that UnknownKey is not included yet.
3587
+ if (typeof pathSegment === 'symbol') {
3588
+ // Hopefully, this saves some memory over just setting
3589
+ // currentPaths[UnknownKey] = EMPTY_OBJECT
3590
+ parent[parentSegment] = UNKNOWN_INCLUDED_PATH;
3591
+ return false;
3592
+ }
3593
+ parent = currentPaths;
3594
+ parentSegment = pathSegment;
3595
+ currentPaths = currentPaths[pathSegment] ||= ((included = false), Object.create(null));
3596
+ }
3597
+ return included;
3598
+ }
3599
+ includeAllPaths(entity, context, basePath) {
3600
+ const { includedPaths } = this;
3601
+ if (includedPaths) {
3602
+ includeAllPaths(entity, context, basePath, includedPaths);
3603
+ }
3604
+ }
3605
+ }
3606
+ function includeAllPaths(entity, context, basePath, currentPaths) {
3607
+ if (currentPaths[UnknownKey]) {
3608
+ return entity.includePath([...basePath, UnknownKey], context);
3609
+ }
3610
+ const keys = Object.keys(currentPaths);
3611
+ if (keys.length === 0) {
3612
+ return entity.includePath(basePath, context);
3613
+ }
3614
+ for (const key of keys) {
3615
+ includeAllPaths(entity, context, [...basePath, key], currentPaths[key]);
3616
+ }
3617
+ }
3618
+
3619
+ /** @import { Node } from 'estree' */
3620
+
3621
+ /**
3622
+ * @param {Node} node
3623
+ * @param {Node} parent
3624
+ * @returns {boolean}
3625
+ */
3626
+ function is_reference(node, parent) {
3627
+ if (node.type === 'MemberExpression') {
3628
+ return !node.computed && is_reference(node.object, node);
3629
+ }
3630
+
3631
+ if (node.type !== 'Identifier') return false;
3632
+
3633
+ switch (parent?.type) {
3634
+ // disregard `bar` in `foo.bar`
3635
+ case 'MemberExpression':
3636
+ return parent.computed || node === parent.object;
3637
+
3638
+ // disregard the `foo` in `class {foo(){}}` but keep it in `class {[foo](){}}`
3639
+ case 'MethodDefinition':
3640
+ return parent.computed;
3641
+
3642
+ // disregard the `meta` in `import.meta`
3643
+ case 'MetaProperty':
3644
+ return parent.meta === node;
3645
+
3646
+ // disregard the `foo` in `class {foo=bar}` but keep it in `class {[foo]=bar}` and `class {bar=foo}`
3647
+ case 'PropertyDefinition':
3648
+ return parent.computed || node === parent.value;
3649
+
3650
+ // disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
3651
+ case 'Property':
3652
+ return parent.computed || node === parent.value;
3653
+
3654
+ // disregard the `bar` in `export { foo as bar }` or
3655
+ // the foo in `import { foo as bar }`
3656
+ case 'ExportSpecifier':
3657
+ case 'ImportSpecifier':
3658
+ return node === parent.local;
3659
+
3660
+ // disregard the `foo` in `foo: while (...) { ... break foo; ... continue foo;}`
3661
+ case 'LabeledStatement':
3662
+ case 'BreakStatement':
3663
+ case 'ContinueStatement':
3664
+ return false;
3665
+
3666
+ default:
3667
+ return true;
3668
+ }
3669
+ }
3670
+
3671
+ function createInclusionContext() {
3672
+ return {
3673
+ brokenFlow: false,
3674
+ hasBreak: false,
3675
+ hasContinue: false,
3676
+ includedCallArguments: new Set(),
3677
+ includedLabels: new Set()
3678
+ };
3679
+ }
3680
+ function createHasEffectsContext() {
3681
+ return {
3682
+ accessed: new EntityPathTracker(),
3683
+ assigned: new EntityPathTracker(),
3684
+ brokenFlow: false,
3685
+ called: new DiscriminatedPathTracker(),
3686
+ hasBreak: false,
3687
+ hasContinue: false,
3688
+ ignore: {
3689
+ breaks: false,
3690
+ continues: false,
3691
+ labels: new Set(),
3692
+ returnYield: false,
3693
+ this: false
3694
+ },
3695
+ includedLabels: new Set(),
3696
+ instantiated: new DiscriminatedPathTracker(),
3697
+ replacedVariableInits: new Map()
3698
+ };
3699
+ }
3674
3700
 
3675
3701
  function isFlagSet(flags, flag) {
3676
3702
  return (flags & flag) !== 0;
@@ -3710,12 +3736,25 @@ class ExpressionEntity {
3710
3736
  hasEffectsOnInteractionAtPath(_path, _interaction, _context) {
3711
3737
  return true;
3712
3738
  }
3713
- include(_context, _includeChildrenRecursively, _options) {
3739
+ include(context, _includeChildrenRecursively, _options) {
3740
+ if (!this.included)
3741
+ this.includeNode(context);
3742
+ }
3743
+ includeNode(_context) {
3714
3744
  this.included = true;
3715
3745
  }
3716
- includeCallArguments(context, parameters) {
3717
- for (const argument of parameters) {
3718
- argument.include(context, false);
3746
+ includePath(_path, context) {
3747
+ if (!this.included)
3748
+ this.includeNode(context);
3749
+ }
3750
+ /* We are both including and including an unknown path here as the former
3751
+ * ensures that nested nodes are included while the latter ensures that all
3752
+ * paths of the expression are included.
3753
+ * */
3754
+ includeCallArguments(context, interaction) {
3755
+ for (const argument of interaction.args) {
3756
+ argument?.includePath(UNKNOWN_PATH, context);
3757
+ argument?.include(context, false);
3719
3758
  }
3720
3759
  }
3721
3760
  shouldBeIncluded(_context) {
@@ -3754,6 +3793,19 @@ const NODE_INTERACTION_UNKNOWN_CALL = {
3754
3793
  withNew: false
3755
3794
  };
3756
3795
 
3796
+ const PureFunctionKey = Symbol('PureFunction');
3797
+ const getPureFunctions = ({ treeshake }) => {
3798
+ const pureFunctions = Object.create(null);
3799
+ for (const functionName of treeshake ? treeshake.manualPureFunctions : []) {
3800
+ let currentFunctions = pureFunctions;
3801
+ for (const pathSegment of functionName.split('.')) {
3802
+ currentFunctions = currentFunctions[pathSegment] ||= Object.create(null);
3803
+ }
3804
+ currentFunctions[PureFunctionKey] = true;
3805
+ }
3806
+ return pureFunctions;
3807
+ };
3808
+
3757
3809
  class Variable extends ExpressionEntity {
3758
3810
  markReassigned() {
3759
3811
  this.isReassigned = true;
@@ -3830,9 +3882,9 @@ class Variable extends ExpressionEntity {
3830
3882
  * has not been included previously. Once a variable is included, it should
3831
3883
  * take care all its declarations are included.
3832
3884
  */
3833
- include() {
3885
+ includePath(path, context) {
3834
3886
  this.included = true;
3835
- this.renderedLikeHoisted?.include();
3887
+ this.renderedLikeHoisted?.includePath(path, context);
3836
3888
  }
3837
3889
  /**
3838
3890
  * Links the rendered name of this variable to another variable and includes
@@ -3864,8 +3916,8 @@ class ExternalVariable extends Variable {
3864
3916
  hasEffectsOnInteractionAtPath(path, { type }) {
3865
3917
  return type !== INTERACTION_ACCESSED || path.length > (this.isNamespace ? 1 : 0);
3866
3918
  }
3867
- include() {
3868
- super.include();
3919
+ includePath(path, context) {
3920
+ super.includePath(path, context);
3869
3921
  this.module.used = true;
3870
3922
  }
3871
3923
  }
@@ -4164,36 +4216,6 @@ const childNodeKeys = {
4164
4216
  YieldExpression: ['argument']
4165
4217
  };
4166
4218
 
4167
- function createInclusionContext() {
4168
- return {
4169
- brokenFlow: false,
4170
- hasBreak: false,
4171
- hasContinue: false,
4172
- includedCallArguments: new Set(),
4173
- includedLabels: new Set()
4174
- };
4175
- }
4176
- function createHasEffectsContext() {
4177
- return {
4178
- accessed: new PathTracker(),
4179
- assigned: new PathTracker(),
4180
- brokenFlow: false,
4181
- called: new DiscriminatedPathTracker(),
4182
- hasBreak: false,
4183
- hasContinue: false,
4184
- ignore: {
4185
- breaks: false,
4186
- continues: false,
4187
- labels: new Set(),
4188
- returnYield: false,
4189
- this: false
4190
- },
4191
- includedLabels: new Set(),
4192
- instantiated: new DiscriminatedPathTracker(),
4193
- replacedVariableInits: new Map()
4194
- };
4195
- }
4196
-
4197
4219
  const INCLUDE_PARAMETERS = 'variables';
4198
4220
  const IS_SKIPPED_CHAIN = Symbol('IS_SKIPPED_CHAIN');
4199
4221
  class NodeBase extends ExpressionEntity {
@@ -4263,9 +4285,8 @@ class NodeBase extends ExpressionEntity {
4263
4285
  this.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.assignmentInteraction, context));
4264
4286
  }
4265
4287
  include(context, includeChildrenRecursively, _options) {
4266
- if (!this.deoptimized)
4267
- this.applyDeoptimizations();
4268
- this.included = true;
4288
+ if (!this.included)
4289
+ this.includeNode(context);
4269
4290
  for (const key of childNodeKeys[this.type]) {
4270
4291
  const value = this[key];
4271
4292
  if (value === null)
@@ -4280,6 +4301,24 @@ class NodeBase extends ExpressionEntity {
4280
4301
  }
4281
4302
  }
4282
4303
  }
4304
+ includeNode(context) {
4305
+ this.included = true;
4306
+ if (!this.deoptimized)
4307
+ this.applyDeoptimizations();
4308
+ for (const key of childNodeKeys[this.type]) {
4309
+ const value = this[key];
4310
+ if (value === null)
4311
+ continue;
4312
+ if (Array.isArray(value)) {
4313
+ for (const child of value) {
4314
+ child?.includePath(UNKNOWN_PATH, context);
4315
+ }
4316
+ }
4317
+ else {
4318
+ value.includePath(UNKNOWN_PATH, context);
4319
+ }
4320
+ }
4321
+ }
4283
4322
  includeAsAssignmentTarget(context, includeChildrenRecursively, _deoptimizeAccess) {
4284
4323
  this.include(context, includeChildrenRecursively);
4285
4324
  }
@@ -4383,6 +4422,17 @@ class NodeBase extends ExpressionEntity {
4383
4422
  function createChildNodeKeysForNode(esTreeNode) {
4384
4423
  return Object.keys(esTreeNode).filter(key => typeof esTreeNode[key] === 'object' && key.charCodeAt(0) !== 95 /* _ */);
4385
4424
  }
4425
+ function onlyIncludeSelf() {
4426
+ this.included = true;
4427
+ if (!this.deoptimized)
4428
+ this.applyDeoptimizations();
4429
+ }
4430
+ function onlyIncludeSelfNoDeoptimize() {
4431
+ this.included = true;
4432
+ }
4433
+ function doNotDeoptimize() {
4434
+ this.deoptimized = true;
4435
+ }
4386
4436
 
4387
4437
  function isObjectExpressionNode(node) {
4388
4438
  return node instanceof NodeBase && node.type === parseAst_js.ObjectExpression;
@@ -4395,8 +4445,8 @@ function assembleMemberDescriptions(memberDescriptions, inheritedDescriptions =
4395
4445
  return Object.create(inheritedDescriptions, memberDescriptions);
4396
4446
  }
4397
4447
  const UNDEFINED_EXPRESSION = new (class UndefinedExpression extends ExpressionEntity {
4398
- getLiteralValueAtPath() {
4399
- return undefined;
4448
+ getLiteralValueAtPath(path) {
4449
+ return path.length > 0 ? UnknownValue : undefined;
4400
4450
  }
4401
4451
  })();
4402
4452
  const returnsUnknown = {
@@ -4593,31 +4643,6 @@ function getMemberReturnExpressionWhenCalled(members, memberName) {
4593
4643
  return [members[memberName].returns, false];
4594
4644
  }
4595
4645
 
4596
- class SpreadElement extends NodeBase {
4597
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
4598
- if (path.length > 0) {
4599
- this.argument.deoptimizeArgumentsOnInteractionAtPath(interaction, UNKNOWN_PATH, recursionTracker);
4600
- }
4601
- }
4602
- hasEffects(context) {
4603
- if (!this.deoptimized)
4604
- this.applyDeoptimizations();
4605
- const { propertyReadSideEffects } = this.scope.context.options
4606
- .treeshake;
4607
- return (this.argument.hasEffects(context) ||
4608
- (propertyReadSideEffects &&
4609
- (propertyReadSideEffects === 'always' ||
4610
- this.argument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context))));
4611
- }
4612
- applyDeoptimizations() {
4613
- this.deoptimized = true;
4614
- // Only properties of properties of the argument could become subject to reassignment
4615
- // This will also reassign the return values of iterators
4616
- this.argument.deoptimizePath([UnknownKey, UnknownKey]);
4617
- this.scope.context.requestTreeshakingPass();
4618
- }
4619
- }
4620
-
4621
4646
  class Method extends ExpressionEntity {
4622
4647
  constructor(description) {
4623
4648
  super();
@@ -4743,6 +4768,7 @@ class ObjectEntity extends ExpressionEntity {
4743
4768
  this.unknownIntegerProps = [];
4744
4769
  this.unmatchableGetters = [];
4745
4770
  this.unmatchablePropertiesAndGetters = [];
4771
+ this.unmatchablePropertiesAndSetters = [];
4746
4772
  this.unmatchableSetters = [];
4747
4773
  if (Array.isArray(properties)) {
4748
4774
  this.buildPropertyMaps(properties);
@@ -4899,7 +4925,12 @@ class ObjectEntity extends ExpressionEntity {
4899
4925
  }
4900
4926
  getLiteralValueAtPath(path, recursionTracker, origin) {
4901
4927
  if (path.length === 0) {
4902
- return UnknownTruthyValue;
4928
+ // This should actually be "UnknownTruthyValue". However, this currently
4929
+ // causes an issue with TypeScript enums in files with moduleSideEffects:
4930
+ // false because we cannot properly track whether a "var" has been
4931
+ // initialized. This should be reverted once we can properly track this.
4932
+ // return UnknownTruthyValue;
4933
+ return UnknownValue;
4903
4934
  }
4904
4935
  const key = path[0];
4905
4936
  const expressionAtPath = this.getMemberExpressionAndTrackDeopt(key, origin);
@@ -4977,9 +5008,38 @@ class ObjectEntity extends ExpressionEntity {
4977
5008
  }
4978
5009
  return false;
4979
5010
  }
5011
+ include(context, includeChildrenRecursively) {
5012
+ this.included = true;
5013
+ for (const property of this.allProperties) {
5014
+ if (includeChildrenRecursively || property.shouldBeIncluded(context)) {
5015
+ property.include(context, includeChildrenRecursively);
5016
+ }
5017
+ }
5018
+ this.prototypeExpression?.include(context, includeChildrenRecursively);
5019
+ }
5020
+ includePath(path, context) {
5021
+ this.included = true;
5022
+ if (path.length === 0)
5023
+ return;
5024
+ const [key, ...subPath] = path;
5025
+ const [includedMembers, includedPath] = typeof key === 'string'
5026
+ ? [
5027
+ [
5028
+ ...new Set([
5029
+ ...(this.propertiesAndGettersByKey[key] || this.unmatchablePropertiesAndGetters),
5030
+ ...(this.propertiesAndSettersByKey[key] || this.unmatchablePropertiesAndSetters)
5031
+ ])
5032
+ ],
5033
+ subPath
5034
+ ]
5035
+ : [this.allProperties, UNKNOWN_PATH];
5036
+ for (const property of includedMembers) {
5037
+ property.includePath(includedPath, context);
5038
+ }
5039
+ this.prototypeExpression?.includePath(path, context);
5040
+ }
4980
5041
  buildPropertyMaps(properties) {
4981
- const { allProperties, propertiesAndGettersByKey, propertiesAndSettersByKey, settersByKey, gettersByKey, unknownIntegerProps, unmatchablePropertiesAndGetters, unmatchableGetters, unmatchableSetters } = this;
4982
- const unmatchablePropertiesAndSetters = [];
5042
+ const { allProperties, propertiesAndGettersByKey, propertiesAndSettersByKey, settersByKey, gettersByKey, unknownIntegerProps, unmatchablePropertiesAndGetters, unmatchablePropertiesAndSetters, unmatchableGetters, unmatchableSetters } = this;
4983
5043
  for (let index = properties.length - 1; index >= 0; index--) {
4984
5044
  const { key, kind, property } = properties[index];
4985
5045
  allProperties.push(property);
@@ -5249,6 +5309,37 @@ const ARRAY_PROTOTYPE = new ObjectEntity({
5249
5309
  values: METHOD_DEOPTS_SELF_RETURNS_UNKNOWN
5250
5310
  }, OBJECT_PROTOTYPE, true);
5251
5311
 
5312
+ class SpreadElement extends NodeBase {
5313
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
5314
+ if (path.length > 0) {
5315
+ this.argument.deoptimizeArgumentsOnInteractionAtPath(interaction, UNKNOWN_PATH, recursionTracker);
5316
+ }
5317
+ }
5318
+ hasEffects(context) {
5319
+ if (!this.deoptimized)
5320
+ this.applyDeoptimizations();
5321
+ const { propertyReadSideEffects } = this.scope.context.options
5322
+ .treeshake;
5323
+ return (this.argument.hasEffects(context) ||
5324
+ (propertyReadSideEffects &&
5325
+ (propertyReadSideEffects === 'always' ||
5326
+ this.argument.hasEffectsOnInteractionAtPath(UNKNOWN_PATH, NODE_INTERACTION_UNKNOWN_ACCESS, context))));
5327
+ }
5328
+ includeNode(context) {
5329
+ this.included = true;
5330
+ if (!this.deoptimized)
5331
+ this.applyDeoptimizations();
5332
+ this.argument.includePath(UNKNOWN_PATH, context);
5333
+ }
5334
+ applyDeoptimizations() {
5335
+ this.deoptimized = true;
5336
+ // Only properties of properties of the argument could become subject to reassignment
5337
+ // This will also reassign the return values of iterators
5338
+ this.argument.deoptimizePath([UnknownKey, UnknownKey]);
5339
+ this.scope.context.requestTreeshakingPass();
5340
+ }
5341
+ }
5342
+
5252
5343
  class ArrayExpression extends NodeBase {
5253
5344
  constructor() {
5254
5345
  super(...arguments);
@@ -5269,6 +5360,16 @@ class ArrayExpression extends NodeBase {
5269
5360
  hasEffectsOnInteractionAtPath(path, interaction, context) {
5270
5361
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
5271
5362
  }
5363
+ includeNode(context) {
5364
+ this.included = true;
5365
+ if (!this.deoptimized)
5366
+ this.applyDeoptimizations();
5367
+ for (const element of this.elements) {
5368
+ if (element) {
5369
+ element?.includePath(UNKNOWN_PATH, context);
5370
+ }
5371
+ }
5372
+ }
5272
5373
  applyDeoptimizations() {
5273
5374
  this.deoptimized = true;
5274
5375
  let hasSpread = false;
@@ -6336,17 +6437,37 @@ class GlobalVariable extends Variable {
6336
6437
  }
6337
6438
  }
6338
6439
 
6440
+ // To avoid infinite recursions
6441
+ const MAX_PATH_DEPTH = 6;
6442
+ // If a path is longer than MAX_PATH_DEPTH, it is truncated so that it is at
6443
+ // most MAX_PATH_DEPTH long. The last element is always UnknownKey
6444
+ const limitConcatenatedPathDepth = (path1, path2) => {
6445
+ const { length: length1 } = path1;
6446
+ const { length: length2 } = path2;
6447
+ return length1 === 0
6448
+ ? path2
6449
+ : length2 === 0
6450
+ ? path1
6451
+ : length1 + length2 > MAX_PATH_DEPTH
6452
+ ? [...path1, ...path2.slice(0, MAX_PATH_DEPTH - 1 - path1.length), 'UnknownKey']
6453
+ : [...path1, ...path2];
6454
+ };
6455
+
6339
6456
  class LocalVariable extends Variable {
6340
- constructor(name, declarator, init, context, kind) {
6457
+ constructor(name, declarator, init,
6458
+ /** if this is non-empty, the actual init is this path of this.init */
6459
+ initPath, context, kind) {
6341
6460
  super(name);
6342
6461
  this.init = init;
6462
+ this.initPath = initPath;
6463
+ this.kind = kind;
6343
6464
  this.calledFromTryStatement = false;
6344
6465
  this.additionalInitializers = null;
6466
+ this.includedPathTracker = new IncludedPathTracker();
6345
6467
  this.expressionsToBeDeoptimized = [];
6346
6468
  this.declarations = declarator ? [declarator] : [];
6347
6469
  this.deoptimizationTracker = context.deoptimizationTracker;
6348
6470
  this.module = context.module;
6349
- this.kind = kind;
6350
6471
  }
6351
6472
  addDeclaration(identifier, init) {
6352
6473
  this.declarations.push(identifier);
@@ -6357,15 +6478,16 @@ class LocalVariable extends Variable {
6357
6478
  for (const initializer of this.additionalInitializers) {
6358
6479
  initializer.deoptimizePath(UNKNOWN_PATH);
6359
6480
  }
6360
- this.additionalInitializers = null;
6361
6481
  }
6362
6482
  }
6363
6483
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6364
- if (this.isReassigned) {
6484
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
6365
6485
  deoptimizeInteraction(interaction);
6366
6486
  return;
6367
6487
  }
6368
- recursionTracker.withTrackedEntityAtPath(path, this.init, () => this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker), undefined);
6488
+ recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6489
+ this.init.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], recursionTracker);
6490
+ }, undefined);
6369
6491
  }
6370
6492
  deoptimizePath(path) {
6371
6493
  if (this.isReassigned ||
@@ -6379,37 +6501,40 @@ class LocalVariable extends Variable {
6379
6501
  for (const expression of expressionsToBeDeoptimized) {
6380
6502
  expression.deoptimizeCache();
6381
6503
  }
6382
- this.init.deoptimizePath(UNKNOWN_PATH);
6504
+ this.init.deoptimizePath([...this.initPath, UnknownKey]);
6383
6505
  }
6384
6506
  else {
6385
- this.init.deoptimizePath(path);
6507
+ this.init.deoptimizePath(limitConcatenatedPathDepth(this.initPath, path));
6386
6508
  }
6387
6509
  }
6388
6510
  getLiteralValueAtPath(path, recursionTracker, origin) {
6389
- if (this.isReassigned) {
6511
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
6390
6512
  return UnknownValue;
6391
6513
  }
6392
6514
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6393
6515
  this.expressionsToBeDeoptimized.push(origin);
6394
- return this.init.getLiteralValueAtPath(path, recursionTracker, origin);
6516
+ return this.init.getLiteralValueAtPath([...this.initPath, ...path], recursionTracker, origin);
6395
6517
  }, UnknownValue);
6396
6518
  }
6397
6519
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6398
- if (this.isReassigned) {
6520
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
6399
6521
  return UNKNOWN_RETURN_EXPRESSION;
6400
6522
  }
6401
6523
  return recursionTracker.withTrackedEntityAtPath(path, this.init, () => {
6402
6524
  this.expressionsToBeDeoptimized.push(origin);
6403
- return this.init.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
6525
+ return this.init.getReturnExpressionWhenCalledAtPath([...this.initPath, ...path], interaction, recursionTracker, origin);
6404
6526
  }, UNKNOWN_RETURN_EXPRESSION);
6405
6527
  }
6406
6528
  hasEffectsOnInteractionAtPath(path, interaction, context) {
6529
+ if (path.length + this.initPath.length > MAX_PATH_DEPTH) {
6530
+ return true;
6531
+ }
6407
6532
  switch (interaction.type) {
6408
6533
  case INTERACTION_ACCESSED: {
6409
6534
  if (this.isReassigned)
6410
6535
  return true;
6411
6536
  return (!context.accessed.trackEntityAtPathAndGetIfTracked(path, this) &&
6412
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6537
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
6413
6538
  }
6414
6539
  case INTERACTION_ASSIGNED: {
6415
6540
  if (this.included)
@@ -6419,44 +6544,63 @@ class LocalVariable extends Variable {
6419
6544
  if (this.isReassigned)
6420
6545
  return true;
6421
6546
  return (!context.assigned.trackEntityAtPathAndGetIfTracked(path, this) &&
6422
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6547
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
6423
6548
  }
6424
6549
  case INTERACTION_CALLED: {
6425
6550
  if (this.isReassigned)
6426
6551
  return true;
6427
6552
  return (!(interaction.withNew ? context.instantiated : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this) &&
6428
- this.init.hasEffectsOnInteractionAtPath(path, interaction, context));
6553
+ this.init.hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
6429
6554
  }
6430
6555
  }
6431
6556
  }
6432
- include() {
6433
- if (!this.included) {
6434
- super.include();
6557
+ includePath(path, context) {
6558
+ if (!this.includedPathTracker.includePathAndGetIfIncluded(path)) {
6559
+ this.module.scope.context.requestTreeshakingPass();
6560
+ if (!this.included) {
6561
+ // This will reduce the number of tree-shaking passes by eagerly
6562
+ // including inits. By pushing this here instead of directly including
6563
+ // we avoid deep call stacks.
6564
+ this.module.scope.context.newlyIncludedVariableInits.add(this.init);
6565
+ }
6566
+ super.includePath(path, context);
6435
6567
  for (const declaration of this.declarations) {
6436
6568
  // If node is a default export, it can save a tree-shaking run to include the full declaration now
6437
6569
  if (!declaration.included)
6438
- declaration.include(createInclusionContext(), false);
6570
+ declaration.include(context, false);
6439
6571
  let node = declaration.parent;
6440
6572
  while (!node.included) {
6441
6573
  // We do not want to properly include parents in case they are part of a dead branch
6442
6574
  // in which case .include() might pull in more dead code
6443
- node.included = true;
6575
+ node.includeNode(context);
6444
6576
  if (node.type === parseAst_js.Program)
6445
6577
  break;
6446
6578
  node = node.parent;
6447
6579
  }
6448
6580
  }
6581
+ // We need to make sure we include the correct path of the init
6582
+ if (path.length > 0) {
6583
+ this.init.includePath(limitConcatenatedPathDepth(this.initPath, path), context);
6584
+ this.additionalInitializers?.forEach(initializer => initializer.includePath(UNKNOWN_PATH, context));
6585
+ }
6449
6586
  }
6450
6587
  }
6451
- includeCallArguments(context, parameters) {
6452
- if (this.isReassigned || context.includedCallArguments.has(this.init)) {
6453
- for (const argument of parameters) {
6454
- argument.include(context, false);
6588
+ includeCallArguments(context, interaction) {
6589
+ if (this.isReassigned ||
6590
+ context.includedCallArguments.has(this.init) ||
6591
+ // This can be removed again once we can include arguments when called at
6592
+ // a specific path
6593
+ this.initPath.length > 0) {
6594
+ for (const argument of interaction.args) {
6595
+ if (argument) {
6596
+ argument.includePath(UNKNOWN_PATH, context);
6597
+ argument.include(context, false);
6598
+ }
6455
6599
  }
6456
6600
  }
6457
6601
  else {
6458
6602
  context.includedCallArguments.add(this.init);
6459
- this.init.includeCallArguments(context, parameters);
6603
+ this.init.includeCallArguments(context, interaction);
6460
6604
  context.includedCallArguments.delete(this.init);
6461
6605
  }
6462
6606
  }
@@ -6536,18 +6680,31 @@ class IdentifierBase extends NodeBase {
6536
6680
  }
6537
6681
  }
6538
6682
  }
6539
- include() {
6683
+ include(context) {
6684
+ if (!this.included)
6685
+ this.includeNode(context);
6686
+ }
6687
+ includeNode(context) {
6688
+ this.included = true;
6540
6689
  if (!this.deoptimized)
6541
6690
  this.applyDeoptimizations();
6691
+ if (this.variable !== null) {
6692
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
6693
+ }
6694
+ }
6695
+ includePath(path, context) {
6542
6696
  if (!this.included) {
6543
6697
  this.included = true;
6544
6698
  if (this.variable !== null) {
6545
- this.scope.context.includeVariableInModule(this.variable);
6699
+ this.scope.context.includeVariableInModule(this.variable, path, context);
6546
6700
  }
6547
6701
  }
6702
+ else if (path.length > 0) {
6703
+ this.variable?.includePath(path, context);
6704
+ }
6548
6705
  }
6549
- includeCallArguments(context, parameters) {
6550
- this.variable.includeCallArguments(context, parameters);
6706
+ includeCallArguments(context, interaction) {
6707
+ this.variable.includeCallArguments(context, interaction);
6551
6708
  }
6552
6709
  isPossibleTDZ() {
6553
6710
  // return cached value to avoid issues with the next tree-shaking pass
@@ -6630,11 +6787,40 @@ function closestParentFunctionOrProgram(node) {
6630
6787
  return node;
6631
6788
  }
6632
6789
 
6790
+ class ObjectMember extends ExpressionEntity {
6791
+ constructor(object, path) {
6792
+ super();
6793
+ this.object = object;
6794
+ this.path = path;
6795
+ }
6796
+ deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
6797
+ this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.path, ...path], recursionTracker);
6798
+ }
6799
+ deoptimizePath(path) {
6800
+ this.object.deoptimizePath([...this.path, ...path]);
6801
+ }
6802
+ getLiteralValueAtPath(path, recursionTracker, origin) {
6803
+ return this.object.getLiteralValueAtPath([...this.path, ...path], recursionTracker, origin);
6804
+ }
6805
+ getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
6806
+ return this.object.getReturnExpressionWhenCalledAtPath([...this.path, ...path], interaction, recursionTracker, origin);
6807
+ }
6808
+ hasEffectsOnInteractionAtPath(path, interaction, context) {
6809
+ return this.object.hasEffectsOnInteractionAtPath([...this.path, ...path], interaction, context);
6810
+ }
6811
+ }
6812
+
6633
6813
  class Identifier extends IdentifierBase {
6634
6814
  constructor() {
6635
6815
  super(...arguments);
6636
6816
  this.variable = null;
6637
6817
  }
6818
+ get isDestructuringDeoptimized() {
6819
+ return isFlagSet(this.flags, 16777216 /* Flag.destructuringDeoptimized */);
6820
+ }
6821
+ set isDestructuringDeoptimized(value) {
6822
+ this.flags = setFlag(this.flags, 16777216 /* Flag.destructuringDeoptimized */, value);
6823
+ }
6638
6824
  addExportedVariables(variables, exportNamesByVariable) {
6639
6825
  if (exportNamesByVariable.has(this.variable)) {
6640
6826
  variables.push(this.variable);
@@ -6647,43 +6833,53 @@ class Identifier extends IdentifierBase {
6647
6833
  this.isVariableReference = true;
6648
6834
  }
6649
6835
  }
6650
- declare(kind, init) {
6836
+ declare(kind, destructuredInitPath, init) {
6651
6837
  let variable;
6652
6838
  const { treeshake } = this.scope.context.options;
6653
- switch (kind) {
6654
- case 'var': {
6655
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6656
- if (treeshake && treeshake.correctVarValueBeforeDeclaration) {
6657
- // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
6658
- variable.markInitializersForDeoptimization();
6659
- }
6660
- break;
6661
- }
6662
- case 'function': {
6663
- // in strict mode, functions are only hoisted within a scope but not across block scopes
6664
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6665
- break;
6666
- }
6667
- case 'let':
6668
- case 'const':
6669
- case 'using':
6670
- case 'await using':
6671
- case 'class': {
6672
- variable = this.scope.addDeclaration(this, this.scope.context, init, kind);
6673
- break;
6674
- }
6675
- case 'parameter': {
6676
- variable = this.scope.addParameterDeclaration(this);
6677
- break;
6678
- }
6679
- /* istanbul ignore next */
6680
- default: {
6681
- /* istanbul ignore next */
6682
- throw new Error(`Internal Error: Unexpected identifier kind ${kind}.`);
6839
+ if (kind === 'parameter') {
6840
+ variable = this.scope.addParameterDeclaration(this, destructuredInitPath);
6841
+ }
6842
+ else {
6843
+ variable = this.scope.addDeclaration(this, this.scope.context, init, destructuredInitPath, kind);
6844
+ if (kind === 'var' && treeshake && treeshake.correctVarValueBeforeDeclaration) {
6845
+ // Necessary to make sure the init is deoptimized. We cannot call deoptimizePath here.
6846
+ variable.markInitializersForDeoptimization();
6683
6847
  }
6684
6848
  }
6685
6849
  return [(this.variable = variable)];
6686
6850
  }
6851
+ deoptimizeAssignment(destructuredInitPath, init) {
6852
+ this.deoptimizePath(EMPTY_PATH);
6853
+ init.deoptimizePath([...destructuredInitPath, UnknownKey]);
6854
+ }
6855
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
6856
+ return (destructuredInitPath.length > 0 &&
6857
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
6858
+ }
6859
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
6860
+ if (destructuredInitPath.length > 0 && !this.isDestructuringDeoptimized) {
6861
+ this.isDestructuringDeoptimized = true;
6862
+ init.deoptimizeArgumentsOnInteractionAtPath({
6863
+ args: [new ObjectMember(init, destructuredInitPath.slice(0, -1))],
6864
+ type: INTERACTION_ACCESSED
6865
+ }, destructuredInitPath, SHARED_RECURSION_TRACKER);
6866
+ }
6867
+ const { propertyReadSideEffects } = this.scope.context.options
6868
+ .treeshake;
6869
+ if ((this.included ||=
6870
+ destructuredInitPath.length > 0 &&
6871
+ !context.brokenFlow &&
6872
+ propertyReadSideEffects &&
6873
+ (propertyReadSideEffects === 'always' ||
6874
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext())))) {
6875
+ if (this.variable && !this.variable.included) {
6876
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
6877
+ }
6878
+ init.includePath(destructuredInitPath, context);
6879
+ return true;
6880
+ }
6881
+ return false;
6882
+ }
6687
6883
  markDeclarationReached() {
6688
6884
  this.variable.initReached = true;
6689
6885
  }
@@ -6736,18 +6932,17 @@ class Scope {
6736
6932
  - then the variable is still declared in the hoisted outer scope, but the initializer is assigned to the parameter
6737
6933
  - const, let, class, and function except in the cases above cannot redeclare anything
6738
6934
  */
6739
- addDeclaration(identifier, context, init, kind) {
6935
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
6740
6936
  const name = identifier.name;
6741
6937
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
6742
6938
  if (existingVariable) {
6743
- const existingKind = existingVariable.kind;
6744
- if (kind === 'var' && existingKind === 'var') {
6939
+ if (kind === 'var' && existingVariable.kind === 'var') {
6745
6940
  existingVariable.addDeclaration(identifier, init);
6746
6941
  return existingVariable;
6747
6942
  }
6748
6943
  context.error(parseAst_js.logRedeclarationError(name), identifier.start);
6749
6944
  }
6750
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
6945
+ const newVariable = new LocalVariable(identifier.name, identifier, init, destructuredInitPath, context, kind);
6751
6946
  this.variables.set(name, newVariable);
6752
6947
  return newVariable;
6753
6948
  }
@@ -6923,7 +7118,6 @@ class MethodBase extends NodeBase {
6923
7118
  }
6924
7119
  return this.getAccessedValue()[0].hasEffectsOnInteractionAtPath(path, interaction, context);
6925
7120
  }
6926
- applyDeoptimizations() { }
6927
7121
  getAccessedValue() {
6928
7122
  if (this.accessedValue === null) {
6929
7123
  if (this.kind === 'get') {
@@ -6937,19 +7131,20 @@ class MethodBase extends NodeBase {
6937
7131
  return this.accessedValue;
6938
7132
  }
6939
7133
  }
7134
+ MethodBase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7135
+ MethodBase.prototype.applyDeoptimizations = doNotDeoptimize;
6940
7136
 
6941
7137
  class MethodDefinition extends MethodBase {
6942
7138
  hasEffects(context) {
6943
7139
  return super.hasEffects(context) || checkEffectForNodes(this.decorators, context);
6944
7140
  }
6945
- applyDeoptimizations() { }
6946
7141
  }
6947
7142
 
6948
7143
  class BlockScope extends ChildScope {
6949
7144
  constructor(parent) {
6950
7145
  super(parent, parent.context);
6951
7146
  }
6952
- addDeclaration(identifier, context, init, kind) {
7147
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
6953
7148
  if (kind === 'var') {
6954
7149
  const name = identifier.name;
6955
7150
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
@@ -6961,7 +7156,7 @@ class BlockScope extends ChildScope {
6961
7156
  }
6962
7157
  return context.error(parseAst_js.logRedeclarationError(name), identifier.start);
6963
7158
  }
6964
- const declaredVariable = this.parent.addDeclaration(identifier, context, init, kind);
7159
+ const declaredVariable = this.parent.addDeclaration(identifier, context, init, destructuredInitPath, kind);
6965
7160
  // Necessary to make sure the init is deoptimized for conditional declarations.
6966
7161
  // We cannot call deoptimizePath here.
6967
7162
  declaredVariable.markInitializersForDeoptimization();
@@ -6969,7 +7164,7 @@ class BlockScope extends ChildScope {
6969
7164
  this.addHoistedVariable(name, declaredVariable);
6970
7165
  return declaredVariable;
6971
7166
  }
6972
- return super.addDeclaration(identifier, context, init, kind);
7167
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
6973
7168
  }
6974
7169
  }
6975
7170
 
@@ -7001,33 +7196,12 @@ class StaticBlock extends NodeBase {
7001
7196
  }
7002
7197
  }
7003
7198
  }
7199
+ StaticBlock.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7200
+ StaticBlock.prototype.applyDeoptimizations = doNotDeoptimize;
7004
7201
  function isStaticBlock(statement) {
7005
7202
  return statement.type === parseAst_js.StaticBlock;
7006
7203
  }
7007
7204
 
7008
- class ObjectMember extends ExpressionEntity {
7009
- constructor(object, key) {
7010
- super();
7011
- this.object = object;
7012
- this.key = key;
7013
- }
7014
- deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
7015
- this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [this.key, ...path], recursionTracker);
7016
- }
7017
- deoptimizePath(path) {
7018
- this.object.deoptimizePath([this.key, ...path]);
7019
- }
7020
- getLiteralValueAtPath(path, recursionTracker, origin) {
7021
- return this.object.getLiteralValueAtPath([this.key, ...path], recursionTracker, origin);
7022
- }
7023
- getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
7024
- return this.object.getReturnExpressionWhenCalledAtPath([this.key, ...path], interaction, recursionTracker, origin);
7025
- }
7026
- hasEffectsOnInteractionAtPath(path, interaction, context) {
7027
- return this.object.hasEffectsOnInteractionAtPath([this.key, ...path], interaction, context);
7028
- }
7029
- }
7030
-
7031
7205
  class ClassNode extends NodeBase {
7032
7206
  constructor() {
7033
7207
  super(...arguments);
@@ -7068,21 +7242,20 @@ class ClassNode extends NodeBase {
7068
7242
  : this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
7069
7243
  }
7070
7244
  include(context, includeChildrenRecursively) {
7071
- if (!this.deoptimized)
7072
- this.applyDeoptimizations();
7073
- this.included = true;
7245
+ if (!this.included)
7246
+ this.includeNode(context);
7074
7247
  this.superClass?.include(context, includeChildrenRecursively);
7075
7248
  this.body.include(context, includeChildrenRecursively);
7076
7249
  for (const decorator of this.decorators)
7077
7250
  decorator.include(context, includeChildrenRecursively);
7078
7251
  if (this.id) {
7079
7252
  this.id.markDeclarationReached();
7080
- this.id.include();
7253
+ this.id.include(context);
7081
7254
  }
7082
7255
  }
7083
7256
  initialise() {
7084
7257
  super.initialise();
7085
- this.id?.declare('class', this);
7258
+ this.id?.declare('class', EMPTY_PATH, this);
7086
7259
  for (const method of this.body.body) {
7087
7260
  if (method instanceof MethodDefinition && method.kind === 'constructor') {
7088
7261
  this.classConstructor = method;
@@ -7140,11 +7313,12 @@ class ClassNode extends NodeBase {
7140
7313
  staticProperties.unshift({
7141
7314
  key: 'prototype',
7142
7315
  kind: 'init',
7143
- property: new ObjectEntity(dynamicMethods, this.superClass ? new ObjectMember(this.superClass, 'prototype') : OBJECT_PROTOTYPE)
7316
+ property: new ObjectEntity(dynamicMethods, this.superClass ? new ObjectMember(this.superClass, ['prototype']) : OBJECT_PROTOTYPE)
7144
7317
  });
7145
7318
  return (this.objectEntity = new ObjectEntity(staticProperties, this.superClass || OBJECT_PROTOTYPE));
7146
7319
  }
7147
7320
  }
7321
+ ClassNode.prototype.includeNode = onlyIncludeSelf;
7148
7322
 
7149
7323
  class ClassDeclaration extends ClassNode {
7150
7324
  initialise() {
@@ -7197,7 +7371,7 @@ class ClassDeclaration extends ClassNode {
7197
7371
 
7198
7372
  class ArgumentsVariable extends LocalVariable {
7199
7373
  constructor(context) {
7200
- super('arguments', null, UNKNOWN_EXPRESSION, context, 'other');
7374
+ super('arguments', null, UNKNOWN_EXPRESSION, EMPTY_PATH, context, 'other');
7201
7375
  this.deoptimizedArguments = [];
7202
7376
  }
7203
7377
  addArgumentToBeDeoptimized(argument) {
@@ -7211,8 +7385,8 @@ class ArgumentsVariable extends LocalVariable {
7211
7385
  hasEffectsOnInteractionAtPath(path, { type }) {
7212
7386
  return type !== INTERACTION_ACCESSED || path.length > 1;
7213
7387
  }
7214
- include() {
7215
- super.include();
7388
+ includePath(path, context) {
7389
+ super.includePath(path, context);
7216
7390
  for (const argument of this.deoptimizedArguments) {
7217
7391
  argument.deoptimizePath(UNKNOWN_PATH);
7218
7392
  }
@@ -7223,27 +7397,28 @@ class ArgumentsVariable extends LocalVariable {
7223
7397
  const MAX_TRACKED_INTERACTIONS = 20;
7224
7398
  const NO_INTERACTIONS = parseAst_js.EMPTY_ARRAY;
7225
7399
  const UNKNOWN_DEOPTIMIZED_FIELD = new Set([UnknownKey]);
7226
- const EMPTY_PATH_TRACKER = new PathTracker();
7400
+ const EMPTY_PATH_TRACKER = new EntityPathTracker();
7227
7401
  const UNKNOWN_DEOPTIMIZED_ENTITY = new Set([UNKNOWN_EXPRESSION]);
7228
7402
  class ParameterVariable extends LocalVariable {
7229
- constructor(name, declarator, context) {
7230
- super(name, declarator, UNKNOWN_EXPRESSION, context, 'parameter');
7403
+ constructor(name, declarator, argumentPath, context) {
7404
+ super(name, declarator, UNKNOWN_EXPRESSION, argumentPath, context, 'parameter');
7231
7405
  this.deoptimizationInteractions = [];
7232
- this.deoptimizations = new PathTracker();
7406
+ this.deoptimizations = new EntityPathTracker();
7233
7407
  this.deoptimizedFields = new Set();
7234
- this.entitiesToBeDeoptimized = new Set();
7235
- this.expressionsUseTheKnownValue = [];
7408
+ this.argumentsToBeDeoptimized = new Set();
7409
+ this.expressionsDependingOnKnownValue = [];
7236
7410
  this.knownValue = null;
7237
7411
  this.knownValueLiteral = UnknownValue;
7238
7412
  this.frozenValue = null;
7239
7413
  }
7240
- addEntityToBeDeoptimized(entity) {
7414
+ addArgumentValue(entity) {
7415
+ this.updateKnownValue(entity);
7241
7416
  if (entity === UNKNOWN_EXPRESSION) {
7242
7417
  // As unknown expressions fully deoptimize all interactions, we can clear
7243
7418
  // the interaction cache at this point provided we keep this optimization
7244
7419
  // in mind when adding new interactions
7245
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7246
- this.entitiesToBeDeoptimized.add(UNKNOWN_EXPRESSION);
7420
+ if (!this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7421
+ this.argumentsToBeDeoptimized.add(UNKNOWN_EXPRESSION);
7247
7422
  for (const { interaction } of this.deoptimizationInteractions) {
7248
7423
  deoptimizeInteraction(interaction);
7249
7424
  }
@@ -7253,27 +7428,34 @@ class ParameterVariable extends LocalVariable {
7253
7428
  else if (this.deoptimizedFields.has(UnknownKey)) {
7254
7429
  // This means that we already deoptimized all interactions and no longer
7255
7430
  // track them
7256
- entity.deoptimizePath(UNKNOWN_PATH);
7431
+ entity.deoptimizePath([...this.initPath, UnknownKey]);
7257
7432
  }
7258
- else if (!this.entitiesToBeDeoptimized.has(entity)) {
7259
- this.entitiesToBeDeoptimized.add(entity);
7433
+ else if (!this.argumentsToBeDeoptimized.has(entity)) {
7434
+ this.argumentsToBeDeoptimized.add(entity);
7260
7435
  for (const field of this.deoptimizedFields) {
7261
- entity.deoptimizePath([field]);
7436
+ entity.deoptimizePath([...this.initPath, field]);
7262
7437
  }
7263
7438
  for (const { interaction, path } of this.deoptimizationInteractions) {
7264
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
7439
+ if (this.initPath.length + path.length > MAX_PATH_DEPTH) {
7440
+ deoptimizeInteraction(interaction);
7441
+ continue;
7442
+ }
7443
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], SHARED_RECURSION_TRACKER);
7265
7444
  }
7266
7445
  }
7267
7446
  }
7447
+ /** This says we should not make assumptions about the value of the parameter.
7448
+ * This is different from deoptimization that will also cause argument values
7449
+ * to be deoptimized. */
7268
7450
  markReassigned() {
7269
7451
  if (this.isReassigned) {
7270
7452
  return;
7271
7453
  }
7272
7454
  super.markReassigned();
7273
- for (const expression of this.expressionsUseTheKnownValue) {
7455
+ for (const expression of this.expressionsDependingOnKnownValue) {
7274
7456
  expression.deoptimizeCache();
7275
7457
  }
7276
- this.expressionsUseTheKnownValue = parseAst_js.EMPTY_ARRAY;
7458
+ this.expressionsDependingOnKnownValue = parseAst_js.EMPTY_ARRAY;
7277
7459
  }
7278
7460
  deoptimizeCache() {
7279
7461
  this.markReassigned();
@@ -7290,7 +7472,7 @@ class ParameterVariable extends LocalVariable {
7290
7472
  }
7291
7473
  if (this.knownValue === null) {
7292
7474
  this.knownValue = argument;
7293
- this.knownValueLiteral = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
7475
+ this.knownValueLiteral = argument.getLiteralValueAtPath(this.initPath, SHARED_RECURSION_TRACKER, this);
7294
7476
  return;
7295
7477
  }
7296
7478
  // the same literal or identifier, do nothing
@@ -7306,7 +7488,7 @@ class ParameterVariable extends LocalVariable {
7306
7488
  return;
7307
7489
  }
7308
7490
  // add tracking for the new argument
7309
- const newValue = argument.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
7491
+ const newValue = argument.getLiteralValueAtPath(this.initPath, SHARED_RECURSION_TRACKER, this);
7310
7492
  if (newValue !== oldValue) {
7311
7493
  this.markReassigned();
7312
7494
  }
@@ -7324,24 +7506,31 @@ class ParameterVariable extends LocalVariable {
7324
7506
  return this.frozenValue;
7325
7507
  }
7326
7508
  getLiteralValueAtPath(path, recursionTracker, origin) {
7327
- if (this.isReassigned) {
7509
+ if (this.isReassigned || path.length + this.initPath.length > MAX_PATH_DEPTH) {
7328
7510
  return UnknownValue;
7329
7511
  }
7330
7512
  const knownValue = this.getKnownValue();
7331
- this.expressionsUseTheKnownValue.push(origin);
7332
- return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath(path, recursionTracker, origin), UnknownValue);
7513
+ this.expressionsDependingOnKnownValue.push(origin);
7514
+ return recursionTracker.withTrackedEntityAtPath(path, knownValue, () => knownValue.getLiteralValueAtPath([...this.initPath, ...path], recursionTracker, origin), UnknownValue);
7333
7515
  }
7334
7516
  hasEffectsOnInteractionAtPath(path, interaction, context) {
7335
- if (this.isReassigned || interaction.type === INTERACTION_ASSIGNED) {
7517
+ const { type } = interaction;
7518
+ if (this.isReassigned ||
7519
+ type === INTERACTION_ASSIGNED ||
7520
+ path.length + this.initPath.length > MAX_PATH_DEPTH) {
7336
7521
  return super.hasEffectsOnInteractionAtPath(path, interaction, context);
7337
7522
  }
7338
- const knownValue = this.getKnownValue();
7339
- return knownValue.hasEffectsOnInteractionAtPath(path, interaction, context);
7523
+ return (!(type === INTERACTION_CALLED
7524
+ ? (interaction.withNew
7525
+ ? context.instantiated
7526
+ : context.called).trackEntityAtPathAndGetIfTracked(path, interaction.args, this)
7527
+ : context.accessed.trackEntityAtPathAndGetIfTracked(path, this)) &&
7528
+ this.getKnownValue().hasEffectsOnInteractionAtPath([...this.initPath, ...path], interaction, context));
7340
7529
  }
7341
7530
  deoptimizeArgumentsOnInteractionAtPath(interaction, path) {
7342
7531
  // For performance reasons, we fully deoptimize all deeper interactions
7343
7532
  if (path.length >= 2 ||
7344
- this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
7533
+ this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION) ||
7345
7534
  this.deoptimizationInteractions.length >= MAX_TRACKED_INTERACTIONS ||
7346
7535
  (path.length === 1 &&
7347
7536
  (this.deoptimizedFields.has(UnknownKey) ||
@@ -7350,10 +7539,10 @@ class ParameterVariable extends LocalVariable {
7350
7539
  return;
7351
7540
  }
7352
7541
  if (!this.deoptimizations.trackEntityAtPathAndGetIfTracked(path, interaction.args)) {
7353
- for (const entity of this.entitiesToBeDeoptimized) {
7354
- entity.deoptimizeArgumentsOnInteractionAtPath(interaction, path, SHARED_RECURSION_TRACKER);
7542
+ for (const entity of this.argumentsToBeDeoptimized) {
7543
+ entity.deoptimizeArgumentsOnInteractionAtPath(interaction, [...this.initPath, ...path], SHARED_RECURSION_TRACKER);
7355
7544
  }
7356
- if (!this.entitiesToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7545
+ if (!this.argumentsToBeDeoptimized.has(UNKNOWN_EXPRESSION)) {
7357
7546
  this.deoptimizationInteractions.push({
7358
7547
  interaction,
7359
7548
  path
@@ -7374,17 +7563,17 @@ class ParameterVariable extends LocalVariable {
7374
7563
  return;
7375
7564
  }
7376
7565
  this.deoptimizedFields.add(key);
7377
- for (const entity of this.entitiesToBeDeoptimized) {
7566
+ for (const entity of this.argumentsToBeDeoptimized) {
7378
7567
  // We do not need a recursion tracker here as we already track whether
7379
7568
  // this field is deoptimized
7380
- entity.deoptimizePath([key]);
7569
+ entity.deoptimizePath([...this.initPath, key]);
7381
7570
  }
7382
7571
  if (key === UnknownKey) {
7383
7572
  // save some memory
7384
7573
  this.deoptimizationInteractions = NO_INTERACTIONS;
7385
7574
  this.deoptimizations = EMPTY_PATH_TRACKER;
7386
7575
  this.deoptimizedFields = UNKNOWN_DEOPTIMIZED_FIELD;
7387
- this.entitiesToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
7576
+ this.argumentsToBeDeoptimized = UNKNOWN_DEOPTIMIZED_ENTITY;
7388
7577
  }
7389
7578
  }
7390
7579
  getReturnExpressionWhenCalledAtPath(path) {
@@ -7399,11 +7588,14 @@ class ParameterVariable extends LocalVariable {
7399
7588
  }
7400
7589
  return UNKNOWN_RETURN_EXPRESSION;
7401
7590
  }
7591
+ includeArgumentPaths(entity, context) {
7592
+ this.includedPathTracker.includeAllPaths(entity, context, this.initPath);
7593
+ }
7402
7594
  }
7403
7595
 
7404
7596
  class ThisVariable extends ParameterVariable {
7405
7597
  constructor(context) {
7406
- super('this', null, context);
7598
+ super('this', null, EMPTY_PATH, context);
7407
7599
  }
7408
7600
  hasEffectsOnInteractionAtPath(path, interaction, context) {
7409
7601
  return (context.replacedVariableInits.get(this) || UNKNOWN_EXPRESSION).hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -7415,7 +7607,7 @@ class CatchBodyScope extends ChildScope {
7415
7607
  super(parent, parent.context);
7416
7608
  this.parent = parent;
7417
7609
  }
7418
- addDeclaration(identifier, context, init, kind) {
7610
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
7419
7611
  if (kind === 'var') {
7420
7612
  const name = identifier.name;
7421
7613
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
@@ -7428,7 +7620,7 @@ class CatchBodyScope extends ChildScope {
7428
7620
  // the assignment actually goes to the parameter and the var is
7429
7621
  // hoisted without assignment. Locally, it is shadowed by the
7430
7622
  // parameter
7431
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, kind);
7623
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, UNDEFINED_EXPRESSION, destructuredInitPath, kind);
7432
7624
  // To avoid the need to rewrite the declaration, we link the variable
7433
7625
  // names. If we ever implement a logic that splits initialization and
7434
7626
  // assignment for hoisted vars, the "renderLikeHoisted" logic can be
@@ -7447,7 +7639,7 @@ class CatchBodyScope extends ChildScope {
7447
7639
  return context.error(parseAst_js.logRedeclarationError(name), identifier.start);
7448
7640
  }
7449
7641
  // We only add parameters to parameter scopes
7450
- const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, kind);
7642
+ const declaredVariable = this.parent.parent.addDeclaration(identifier, context, init, destructuredInitPath, kind);
7451
7643
  // Necessary to make sure the init is deoptimized for conditional declarations.
7452
7644
  // We cannot call deoptimizePath here.
7453
7645
  declaredVariable.markInitializersForDeoptimization();
@@ -7455,7 +7647,7 @@ class CatchBodyScope extends ChildScope {
7455
7647
  this.addHoistedVariable(name, declaredVariable);
7456
7648
  return declaredVariable;
7457
7649
  }
7458
- return super.addDeclaration(identifier, context, init, kind);
7650
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
7459
7651
  }
7460
7652
  }
7461
7653
 
@@ -7465,7 +7657,7 @@ class FunctionBodyScope extends ChildScope {
7465
7657
  }
7466
7658
  // There is stuff that is only allowed in function scopes, i.e. functions can
7467
7659
  // be redeclared, functions and var can redeclare each other
7468
- addDeclaration(identifier, context, init, kind) {
7660
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
7469
7661
  const name = identifier.name;
7470
7662
  const existingVariable = this.hoistedVariables?.get(name) || this.variables.get(name);
7471
7663
  if (existingVariable) {
@@ -7477,7 +7669,7 @@ class FunctionBodyScope extends ChildScope {
7477
7669
  }
7478
7670
  context.error(parseAst_js.logRedeclarationError(name), identifier.start);
7479
7671
  }
7480
- const newVariable = new LocalVariable(identifier.name, identifier, init, context, kind);
7672
+ const newVariable = new LocalVariable(identifier.name, identifier, init, destructuredInitPath, context, kind);
7481
7673
  this.variables.set(name, newVariable);
7482
7674
  return newVariable;
7483
7675
  }
@@ -7486,21 +7678,21 @@ class FunctionBodyScope extends ChildScope {
7486
7678
  class ParameterScope extends ChildScope {
7487
7679
  constructor(parent, isCatchScope) {
7488
7680
  super(parent, parent.context);
7489
- this.parameters = [];
7490
7681
  this.hasRest = false;
7682
+ this.parameters = [];
7491
7683
  this.bodyScope = isCatchScope ? new CatchBodyScope(this) : new FunctionBodyScope(this);
7492
7684
  }
7493
7685
  /**
7494
7686
  * Adds a parameter to this scope. Parameters must be added in the correct
7495
7687
  * order, i.e. from left to right.
7496
7688
  */
7497
- addParameterDeclaration(identifier) {
7689
+ addParameterDeclaration(identifier, argumentPath) {
7498
7690
  const { name, start } = identifier;
7499
7691
  const existingParameter = this.variables.get(name);
7500
7692
  if (existingParameter) {
7501
7693
  return this.context.error(parseAst_js.logDuplicateArgumentNameError(name), start);
7502
7694
  }
7503
- const variable = new ParameterVariable(name, identifier, this.context);
7695
+ const variable = new ParameterVariable(name, identifier, argumentPath, this.context);
7504
7696
  this.variables.set(name, variable);
7505
7697
  // We also add it to the body scope to detect name conflicts with local
7506
7698
  // variables. We still need the intermediate scope, though, as parameter
@@ -7518,42 +7710,56 @@ class ParameterScope extends ChildScope {
7518
7710
  }
7519
7711
  this.hasRest = hasRest;
7520
7712
  }
7521
- includeCallArguments(context, parameters) {
7713
+ includeCallArguments(context, interaction) {
7522
7714
  let calledFromTryStatement = false;
7523
7715
  let argumentIncluded = false;
7524
7716
  const restParameter = this.hasRest && this.parameters[this.parameters.length - 1];
7525
- for (const checkedArgument of parameters) {
7526
- if (checkedArgument instanceof SpreadElement) {
7527
- for (const argument of parameters) {
7528
- argument.include(context, false);
7529
- }
7530
- break;
7717
+ const { args } = interaction;
7718
+ let lastExplicitlyIncludedIndex = args.length - 1;
7719
+ // If there is a SpreadElement, we need to include all arguments after it
7720
+ // because we no longer know which argument corresponds to which parameter.
7721
+ for (let argumentIndex = 1; argumentIndex < args.length; argumentIndex++) {
7722
+ const argument = args[argumentIndex];
7723
+ if (argument instanceof SpreadElement && !argumentIncluded) {
7724
+ argumentIncluded = true;
7725
+ lastExplicitlyIncludedIndex = argumentIndex - 1;
7726
+ }
7727
+ if (argumentIncluded) {
7728
+ argument.includePath(UNKNOWN_PATH, context);
7729
+ argument.include(context, false);
7531
7730
  }
7532
7731
  }
7533
- for (let index = parameters.length - 1; index >= 0; index--) {
7534
- const parameterVariables = this.parameters[index] || restParameter;
7535
- const argument = parameters[index];
7732
+ // Now we go backwards either starting from the last argument or before the
7733
+ // first SpreadElement to ensure all arguments before are included as needed
7734
+ for (let index = lastExplicitlyIncludedIndex; index >= 1; index--) {
7735
+ const parameterVariables = this.parameters[index - 1] || restParameter;
7736
+ const argument = args[index];
7536
7737
  if (parameterVariables) {
7537
7738
  calledFromTryStatement = false;
7538
7739
  if (parameterVariables.length === 0) {
7539
- // handle empty destructuring
7740
+ // handle empty destructuring to avoid destructuring undefined
7540
7741
  argumentIncluded = true;
7541
7742
  }
7542
7743
  else {
7543
7744
  for (const variable of parameterVariables) {
7544
- if (variable.included) {
7545
- argumentIncluded = true;
7546
- }
7547
7745
  if (variable.calledFromTryStatement) {
7548
7746
  calledFromTryStatement = true;
7549
7747
  }
7748
+ if (variable.included) {
7749
+ argumentIncluded = true;
7750
+ if (calledFromTryStatement) {
7751
+ argument.include(context, true);
7752
+ }
7753
+ else {
7754
+ variable.includeArgumentPaths(argument, context);
7755
+ argument.include(context, false);
7756
+ }
7757
+ }
7550
7758
  }
7551
7759
  }
7552
7760
  }
7553
- if (!argumentIncluded && argument.shouldBeIncluded(context)) {
7761
+ if (!argument.included && (argumentIncluded || argument.shouldBeIncluded(context))) {
7554
7762
  argumentIncluded = true;
7555
- }
7556
- if (argumentIncluded) {
7557
7763
  argument.include(context, calledFromTryStatement);
7558
7764
  }
7559
7765
  }
@@ -7569,11 +7775,62 @@ class ReturnValueScope extends ParameterScope {
7569
7775
  addReturnExpression(expression) {
7570
7776
  this.returnExpressions.push(expression);
7571
7777
  }
7778
+ deoptimizeArgumentsOnCall(interaction) {
7779
+ const { parameters } = this;
7780
+ const { args } = interaction;
7781
+ let position = 0;
7782
+ for (; position < args.length - 1; position++) {
7783
+ // Only the "this" argument arg[0] can be null
7784
+ const argument = args[position + 1];
7785
+ if (argument instanceof SpreadElement) {
7786
+ // This deoptimizes the current and remaining parameters and arguments
7787
+ for (; position < parameters.length; position++) {
7788
+ args[position + 1]?.deoptimizePath(UNKNOWN_PATH);
7789
+ parameters[position].forEach(variable => variable.markReassigned());
7790
+ }
7791
+ break;
7792
+ }
7793
+ if (this.hasRest && position >= parameters.length - 1) {
7794
+ argument.deoptimizePath(UNKNOWN_PATH);
7795
+ }
7796
+ else {
7797
+ const variables = parameters[position];
7798
+ if (variables) {
7799
+ for (const variable of variables) {
7800
+ variable.addArgumentValue(argument);
7801
+ }
7802
+ }
7803
+ this.addArgumentToBeDeoptimized(argument);
7804
+ }
7805
+ }
7806
+ const nonRestParameterLength = this.hasRest ? parameters.length - 1 : parameters.length;
7807
+ for (; position < nonRestParameterLength; position++) {
7808
+ for (const variable of parameters[position]) {
7809
+ variable.addArgumentValue(UNDEFINED_EXPRESSION);
7810
+ }
7811
+ }
7812
+ }
7572
7813
  getReturnExpression() {
7573
7814
  if (this.returnExpression === null)
7574
7815
  this.updateReturnExpression();
7575
7816
  return this.returnExpression;
7576
7817
  }
7818
+ deoptimizeAllParameters() {
7819
+ for (const parameter of this.parameters) {
7820
+ for (const variable of parameter) {
7821
+ variable.deoptimizePath(UNKNOWN_PATH);
7822
+ variable.markReassigned();
7823
+ }
7824
+ }
7825
+ }
7826
+ reassignAllParameters() {
7827
+ for (const parameter of this.parameters) {
7828
+ for (const variable of parameter) {
7829
+ variable.markReassigned();
7830
+ }
7831
+ }
7832
+ }
7833
+ addArgumentToBeDeoptimized(_argument) { }
7577
7834
  updateReturnExpression() {
7578
7835
  if (this.returnExpressions.length === 1) {
7579
7836
  this.returnExpression = this.returnExpressions[0];
@@ -7589,24 +7846,30 @@ class ReturnValueScope extends ParameterScope {
7589
7846
 
7590
7847
  class FunctionScope extends ReturnValueScope {
7591
7848
  constructor(parent) {
7592
- const { context } = parent;
7593
7849
  super(parent, false);
7850
+ const { context } = parent;
7594
7851
  this.variables.set('arguments', (this.argumentsVariable = new ArgumentsVariable(context)));
7595
7852
  this.variables.set('this', (this.thisVariable = new ThisVariable(context)));
7596
7853
  }
7597
7854
  findLexicalBoundary() {
7598
7855
  return this;
7599
7856
  }
7600
- includeCallArguments(context, parameters) {
7601
- super.includeCallArguments(context, parameters);
7857
+ includeCallArguments(context, interaction) {
7858
+ super.includeCallArguments(context, interaction);
7602
7859
  if (this.argumentsVariable.included) {
7603
- for (const argument of parameters) {
7604
- if (!argument.included) {
7860
+ const { args } = interaction;
7861
+ for (let argumentIndex = 1; argumentIndex < args.length; argumentIndex++) {
7862
+ const argument = args[argumentIndex];
7863
+ if (argument) {
7864
+ argument.includePath(UNKNOWN_PATH, context);
7605
7865
  argument.include(context, false);
7606
7866
  }
7607
7867
  }
7608
7868
  }
7609
7869
  }
7870
+ addArgumentToBeDeoptimized(argument) {
7871
+ this.argumentsVariable.addArgumentToBeDeoptimized(argument);
7872
+ }
7610
7873
  }
7611
7874
 
7612
7875
  class ExpressionStatement extends NodeBase {
@@ -7634,8 +7897,9 @@ class ExpressionStatement extends NodeBase {
7634
7897
  return this.parent.type !== parseAst_js.Program;
7635
7898
  return super.shouldBeIncluded(context);
7636
7899
  }
7637
- applyDeoptimizations() { }
7638
7900
  }
7901
+ ExpressionStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7902
+ ExpressionStatement.prototype.applyDeoptimizations = doNotDeoptimize;
7639
7903
 
7640
7904
  class BlockStatement extends NodeBase {
7641
7905
  get deoptimizeBody() {
@@ -7700,6 +7964,8 @@ class BlockStatement extends NodeBase {
7700
7964
  }
7701
7965
  }
7702
7966
  }
7967
+ BlockStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
7968
+ BlockStatement.prototype.applyDeoptimizations = doNotDeoptimize;
7703
7969
 
7704
7970
  class RestElement extends NodeBase {
7705
7971
  constructor() {
@@ -7709,9 +7975,12 @@ class RestElement extends NodeBase {
7709
7975
  addExportedVariables(variables, exportNamesByVariable) {
7710
7976
  this.argument.addExportedVariables(variables, exportNamesByVariable);
7711
7977
  }
7712
- declare(kind, init) {
7978
+ declare(kind, destructuredInitPath, init) {
7713
7979
  this.declarationInit = init;
7714
- return this.argument.declare(kind, UNKNOWN_EXPRESSION);
7980
+ return this.argument.declare(kind, getIncludedPatternPath$1(destructuredInitPath), init);
7981
+ }
7982
+ deoptimizeAssignment(destructuredInitPath, init) {
7983
+ this.argument.deoptimizeAssignment(getIncludedPatternPath$1(destructuredInitPath), init);
7715
7984
  }
7716
7985
  deoptimizePath(path) {
7717
7986
  if (path.length === 0) {
@@ -7722,6 +7991,20 @@ class RestElement extends NodeBase {
7722
7991
  return (path.length > 0 ||
7723
7992
  this.argument.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
7724
7993
  }
7994
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
7995
+ return this.argument.hasEffectsWhenDestructuring(context, getIncludedPatternPath$1(destructuredInitPath), init);
7996
+ }
7997
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
7998
+ return (this.included =
7999
+ this.argument.includeDestructuredIfNecessary(context, getIncludedPatternPath$1(destructuredInitPath), init) || this.included);
8000
+ }
8001
+ include(context, includeChildrenRecursively) {
8002
+ if (!this.included)
8003
+ this.includeNode(context);
8004
+ // This should just include the identifier, its properties should be
8005
+ // included where the variable is used.
8006
+ this.argument.include(context, includeChildrenRecursively);
8007
+ }
7725
8008
  markDeclarationReached() {
7726
8009
  this.argument.markDeclarationReached();
7727
8010
  }
@@ -7733,12 +8016,16 @@ class RestElement extends NodeBase {
7733
8016
  }
7734
8017
  }
7735
8018
  }
8019
+ RestElement.prototype.includeNode = onlyIncludeSelf;
8020
+ const getIncludedPatternPath$1 = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
8021
+ ? destructuredInitPath
8022
+ : [...destructuredInitPath, UnknownKey];
7736
8023
 
7737
8024
  class FunctionBase extends NodeBase {
7738
8025
  constructor() {
7739
8026
  super(...arguments);
7740
- this.objectEntity = null;
7741
8027
  this.parameterVariableValuesDeoptimized = false;
8028
+ this.includeCallArguments = this.scope.includeCallArguments.bind(this.scope);
7742
8029
  }
7743
8030
  get async() {
7744
8031
  return isFlagSet(this.flags, 256 /* Flag.async */);
@@ -7758,53 +8045,9 @@ class FunctionBase extends NodeBase {
7758
8045
  set generator(value) {
7759
8046
  this.flags = setFlag(this.flags, 4194304 /* Flag.generator */, value);
7760
8047
  }
7761
- updateParameterVariableValues(_arguments) {
7762
- for (let position = 0; position < this.params.length; position++) {
7763
- const parameter = this.params[position];
7764
- if (!(parameter instanceof Identifier)) {
7765
- continue;
7766
- }
7767
- const parameterVariable = parameter.variable;
7768
- const argument = _arguments[position + 1] ?? UNDEFINED_EXPRESSION;
7769
- parameterVariable.updateKnownValue(argument);
7770
- }
7771
- }
7772
- deoptimizeParameterVariableValues() {
7773
- for (const parameter of this.params) {
7774
- if (parameter instanceof Identifier) {
7775
- const parameterVariable = parameter.variable;
7776
- parameterVariable.markReassigned();
7777
- }
7778
- }
7779
- }
7780
8048
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
7781
- if (interaction.type === INTERACTION_CALLED) {
7782
- const { parameters } = this.scope;
7783
- const { args } = interaction;
7784
- let hasRest = false;
7785
- for (let position = 0; position < args.length - 1; position++) {
7786
- const parameter = this.params[position];
7787
- // Only the "this" argument arg[0] can be null
7788
- const argument = args[position + 1];
7789
- if (argument instanceof SpreadElement) {
7790
- this.deoptimizeParameterVariableValues();
7791
- }
7792
- if (hasRest || parameter instanceof RestElement) {
7793
- hasRest = true;
7794
- argument.deoptimizePath(UNKNOWN_PATH);
7795
- }
7796
- else if (parameter instanceof Identifier) {
7797
- parameters[position][0].addEntityToBeDeoptimized(argument);
7798
- this.addArgumentToBeDeoptimized(argument);
7799
- }
7800
- else if (parameter) {
7801
- argument.deoptimizePath(UNKNOWN_PATH);
7802
- }
7803
- else {
7804
- this.addArgumentToBeDeoptimized(argument);
7805
- }
7806
- }
7807
- this.updateParameterVariableValues(args);
8049
+ if (interaction.type === INTERACTION_CALLED && path.length === 0) {
8050
+ this.scope.deoptimizeArgumentsOnCall(interaction);
7808
8051
  }
7809
8052
  else {
7810
8053
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -7816,12 +8059,7 @@ class FunctionBase extends NodeBase {
7816
8059
  // A reassignment of UNKNOWN_PATH is considered equivalent to having lost track
7817
8060
  // which means the return expression and parameters need to be reassigned
7818
8061
  this.scope.getReturnExpression().deoptimizePath(UNKNOWN_PATH);
7819
- for (const parameterList of this.scope.parameters) {
7820
- for (const parameter of parameterList) {
7821
- parameter.deoptimizePath(UNKNOWN_PATH);
7822
- parameter.markReassigned();
7823
- }
7824
- }
8062
+ this.scope.deoptimizeAllParameters();
7825
8063
  }
7826
8064
  }
7827
8065
  getLiteralValueAtPath(path, recursionTracker, origin) {
@@ -7859,8 +8097,13 @@ class FunctionBase extends NodeBase {
7859
8097
  return true;
7860
8098
  }
7861
8099
  }
7862
- for (const parameter of this.params) {
7863
- if (parameter.hasEffects(context))
8100
+ const { propertyReadSideEffects } = this.scope.context.options
8101
+ .treeshake;
8102
+ for (let index = 0; index < this.params.length; index++) {
8103
+ const parameter = this.params[index];
8104
+ if (parameter.hasEffects(context) ||
8105
+ (propertyReadSideEffects &&
8106
+ parameter.hasEffectsWhenDestructuring(context, EMPTY_PATH, interaction.args[index + 1] || UNDEFINED_EXPRESSION)))
7864
8107
  return true;
7865
8108
  }
7866
8109
  return false;
@@ -7879,21 +8122,17 @@ class FunctionBase extends NodeBase {
7879
8122
  return variable?.getOnlyFunctionCallUsed() ?? false;
7880
8123
  }
7881
8124
  include(context, includeChildrenRecursively) {
7882
- if (!this.parameterVariableValuesDeoptimized && !this.onlyFunctionCallUsed()) {
8125
+ if (!this.included)
8126
+ this.includeNode(context);
8127
+ if (!(this.parameterVariableValuesDeoptimized || this.onlyFunctionCallUsed())) {
7883
8128
  this.parameterVariableValuesDeoptimized = true;
7884
- this.deoptimizeParameterVariableValues();
8129
+ this.scope.reassignAllParameters();
7885
8130
  }
7886
- if (!this.deoptimized)
7887
- this.applyDeoptimizations();
7888
- this.included = true;
7889
8131
  const { brokenFlow } = context;
7890
8132
  context.brokenFlow = false;
7891
8133
  this.body.include(context, includeChildrenRecursively);
7892
8134
  context.brokenFlow = brokenFlow;
7893
8135
  }
7894
- includeCallArguments(context, parameters) {
7895
- this.scope.includeCallArguments(context, parameters);
7896
- }
7897
8136
  initialise() {
7898
8137
  super.initialise();
7899
8138
  if (this.body instanceof BlockStatement) {
@@ -7915,14 +8154,14 @@ class FunctionBase extends NodeBase {
7915
8154
  // so that the scope already knows all parameters and can detect conflicts
7916
8155
  // when parsing the body.
7917
8156
  const parameters = (this.params = params.map((parameter) => new (context.getNodeConstructor(parameter.type))(this, scope).parseNode(parameter)));
7918
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
8157
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
7919
8158
  this.body = new (context.getNodeConstructor(body.type))(this, bodyScope).parseNode(body);
7920
8159
  return super.parseNode(esTreeNode);
7921
8160
  }
7922
- addArgumentToBeDeoptimized(_argument) { }
7923
- applyDeoptimizations() { }
7924
8161
  }
7925
8162
  FunctionBase.prototype.preventChildBlockScope = true;
8163
+ FunctionBase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
8164
+ FunctionBase.prototype.applyDeoptimizations = doNotDeoptimize;
7926
8165
 
7927
8166
  class FunctionNode extends FunctionBase {
7928
8167
  constructor() {
@@ -7934,18 +8173,16 @@ class FunctionNode extends FunctionBase {
7934
8173
  this.constructedEntity = new ObjectEntity(Object.create(null), OBJECT_PROTOTYPE);
7935
8174
  // This makes sure that all deoptimizations of "this" are applied to the
7936
8175
  // constructed entity.
7937
- this.scope.thisVariable.addEntityToBeDeoptimized(this.constructedEntity);
8176
+ this.scope.thisVariable.addArgumentValue(this.constructedEntity);
7938
8177
  }
7939
8178
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
7940
8179
  super.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
7941
8180
  if (interaction.type === INTERACTION_CALLED && path.length === 0 && interaction.args[0]) {
7942
8181
  // args[0] is the "this" argument
7943
- this.scope.thisVariable.addEntityToBeDeoptimized(interaction.args[0]);
8182
+ this.scope.thisVariable.addArgumentValue(interaction.args[0]);
7944
8183
  }
7945
8184
  }
7946
8185
  hasEffects(context) {
7947
- if (!this.deoptimized)
7948
- this.applyDeoptimizations();
7949
8186
  if (this.annotationNoSideEffects) {
7950
8187
  return false;
7951
8188
  }
@@ -7983,7 +8220,7 @@ class FunctionNode extends FunctionBase {
7983
8220
  }
7984
8221
  include(context, includeChildrenRecursively) {
7985
8222
  super.include(context, includeChildrenRecursively);
7986
- this.id?.include();
8223
+ this.id?.include(context);
7987
8224
  const hasArguments = this.scope.argumentsVariable.included;
7988
8225
  for (const parameter of this.params) {
7989
8226
  if (!(parameter instanceof Identifier) || hasArguments) {
@@ -7991,12 +8228,18 @@ class FunctionNode extends FunctionBase {
7991
8228
  }
7992
8229
  }
7993
8230
  }
8231
+ includeNode(context) {
8232
+ this.included = true;
8233
+ const hasArguments = this.scope.argumentsVariable.included;
8234
+ for (const parameter of this.params) {
8235
+ if (!(parameter instanceof Identifier) || hasArguments) {
8236
+ parameter.includePath(UNKNOWN_PATH, context);
8237
+ }
8238
+ }
8239
+ }
7994
8240
  initialise() {
7995
8241
  super.initialise();
7996
- this.id?.declare('function', this);
7997
- }
7998
- addArgumentToBeDeoptimized(argument) {
7999
- this.scope.argumentsVariable.addArgumentToBeDeoptimized(argument);
8242
+ this.id?.declare('function', EMPTY_PATH, this);
8000
8243
  }
8001
8244
  getObjectEntity() {
8002
8245
  if (this.objectEntity !== null) {
@@ -8046,11 +8289,16 @@ function getFunctionIdInsertPosition(code, start) {
8046
8289
  }
8047
8290
  class ExportDefaultDeclaration extends NodeBase {
8048
8291
  include(context, includeChildrenRecursively) {
8049
- super.include(context, includeChildrenRecursively);
8292
+ this.included = true;
8293
+ this.declaration.include(context, includeChildrenRecursively);
8050
8294
  if (includeChildrenRecursively) {
8051
- this.scope.context.includeVariableInModule(this.variable);
8295
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, context);
8052
8296
  }
8053
8297
  }
8298
+ includePath(path, context) {
8299
+ this.included = true;
8300
+ this.declaration.includePath(path, context);
8301
+ }
8054
8302
  initialise() {
8055
8303
  super.initialise();
8056
8304
  const declaration = this.declaration;
@@ -8095,7 +8343,6 @@ class ExportDefaultDeclaration extends NodeBase {
8095
8343
  }
8096
8344
  this.declaration.render(code, options);
8097
8345
  }
8098
- applyDeoptimizations() { }
8099
8346
  renderNamedDeclaration(code, declarationStart, idInsertPosition, options) {
8100
8347
  const { exportNamesByVariable, format, snippets: { getPropertyAccess } } = options;
8101
8348
  const name = this.variable.getName(getPropertyAccess);
@@ -8126,6 +8373,8 @@ class ExportDefaultDeclaration extends NodeBase {
8126
8373
  }
8127
8374
  }
8128
8375
  ExportDefaultDeclaration.prototype.needsBoundaries = true;
8376
+ ExportDefaultDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
8377
+ ExportDefaultDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
8129
8378
 
8130
8379
  const needsEscapeRegEx = /[\n\r'\\\u2028\u2029]/;
8131
8380
  const quoteNewlineRegEx = /([\n\r'\u2028\u2029])/g;
@@ -8395,6 +8644,7 @@ class Literal extends NodeBase {
8395
8644
  }
8396
8645
  }
8397
8646
  }
8647
+ Literal.prototype.includeNode = onlyIncludeSelf;
8398
8648
 
8399
8649
  function getChainElementLiteralValueAtPath(element, object, path, recursionTracker, origin) {
8400
8650
  if ('getLiteralValueAtPathAsChainElement' in object) {
@@ -8410,8 +8660,6 @@ function getChainElementLiteralValueAtPath(element, object, path, recursionTrack
8410
8660
  return element.getLiteralValueAtPath(path, recursionTracker, origin);
8411
8661
  }
8412
8662
 
8413
- // To avoid infinite recursions
8414
- const MAX_PATH_DEPTH = 7;
8415
8663
  function getResolvablePropertyKey(memberExpression) {
8416
8664
  return memberExpression.computed
8417
8665
  ? getResolvableComputedPropertyKey(memberExpression.property)
@@ -8510,18 +8758,27 @@ class MemberExpression extends NodeBase {
8510
8758
  }
8511
8759
  else if (!this.isUndefined) {
8512
8760
  if (path.length < MAX_PATH_DEPTH) {
8513
- this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, [this.getPropertyKey(), ...path], recursionTracker);
8761
+ this.object.deoptimizeArgumentsOnInteractionAtPath(interaction, this.propertyKey === UnknownKey ? UNKNOWN_PATH : [this.propertyKey, ...path], recursionTracker);
8514
8762
  }
8515
8763
  else {
8516
8764
  deoptimizeInteraction(interaction);
8517
8765
  }
8518
8766
  }
8519
8767
  }
8768
+ deoptimizeAssignment(destructuredInitPath, init) {
8769
+ this.deoptimizePath(EMPTY_PATH);
8770
+ init.deoptimizePath([...destructuredInitPath, UnknownKey]);
8771
+ }
8520
8772
  deoptimizeCache() {
8773
+ if (this.propertyKey === this.dynamicPropertyKey)
8774
+ return;
8521
8775
  const { expressionsToBeDeoptimized, object } = this;
8522
8776
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
8523
- this.propertyKey = UnknownKey;
8777
+ this.dynamicPropertyKey = this.propertyKey;
8524
8778
  object.deoptimizePath(UNKNOWN_PATH);
8779
+ if (this.included) {
8780
+ object.includePath(UNKNOWN_PATH, createInclusionContext());
8781
+ }
8525
8782
  for (const expression of expressionsToBeDeoptimized) {
8526
8783
  expression.deoptimizeCache();
8527
8784
  }
@@ -8532,11 +8789,13 @@ class MemberExpression extends NodeBase {
8532
8789
  if (this.variable) {
8533
8790
  this.variable.deoptimizePath(path);
8534
8791
  }
8535
- else if (!this.isUndefined && path.length < MAX_PATH_DEPTH) {
8536
- const propertyKey = this.getPropertyKey();
8792
+ else if (!this.isUndefined) {
8793
+ const { propertyKey } = this;
8537
8794
  this.object.deoptimizePath([
8538
8795
  propertyKey === UnknownKey ? UnknownNonAccessorKey : propertyKey,
8539
- ...path
8796
+ ...(path.length < MAX_PATH_DEPTH
8797
+ ? path
8798
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
8540
8799
  ]);
8541
8800
  }
8542
8801
  }
@@ -8547,9 +8806,11 @@ class MemberExpression extends NodeBase {
8547
8806
  if (this.isUndefined) {
8548
8807
  return undefined;
8549
8808
  }
8550
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8551
- this.expressionsToBeDeoptimized.push(origin);
8552
- return this.object.getLiteralValueAtPath([this.getPropertyKey(), ...path], recursionTracker, origin);
8809
+ const propertyKey = this.getDynamicPropertyKey();
8810
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8811
+ if (propertyKey !== this.propertyKey)
8812
+ this.expressionsToBeDeoptimized.push(origin);
8813
+ return this.object.getLiteralValueAtPath([propertyKey, ...path], recursionTracker, origin);
8553
8814
  }
8554
8815
  return UnknownValue;
8555
8816
  }
@@ -8569,9 +8830,11 @@ class MemberExpression extends NodeBase {
8569
8830
  if (this.isUndefined) {
8570
8831
  return [UNDEFINED_EXPRESSION, false];
8571
8832
  }
8572
- if (this.propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8573
- this.expressionsToBeDeoptimized.push(origin);
8574
- return this.object.getReturnExpressionWhenCalledAtPath([this.getPropertyKey(), ...path], interaction, recursionTracker, origin);
8833
+ const propertyKey = this.getDynamicPropertyKey();
8834
+ if (propertyKey !== UnknownKey && path.length < MAX_PATH_DEPTH) {
8835
+ if (propertyKey !== this.propertyKey)
8836
+ this.expressionsToBeDeoptimized.push(origin);
8837
+ return this.object.getReturnExpressionWhenCalledAtPath([propertyKey, ...path], interaction, recursionTracker, origin);
8575
8838
  }
8576
8839
  return UNKNOWN_RETURN_EXPRESSION;
8577
8840
  }
@@ -8617,14 +8880,45 @@ class MemberExpression extends NodeBase {
8617
8880
  return true;
8618
8881
  }
8619
8882
  if (path.length < MAX_PATH_DEPTH) {
8620
- return this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey(), ...path], interaction, context);
8883
+ return this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey(), ...path], interaction, context);
8621
8884
  }
8622
8885
  return true;
8623
8886
  }
8887
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
8888
+ return (destructuredInitPath.length > 0 &&
8889
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, context));
8890
+ }
8624
8891
  include(context, includeChildrenRecursively) {
8892
+ if (!this.included)
8893
+ this.includeNode(context);
8894
+ this.object.include(context, includeChildrenRecursively);
8895
+ this.property.include(context, includeChildrenRecursively);
8896
+ }
8897
+ includeNode(context) {
8898
+ this.included = true;
8625
8899
  if (!this.deoptimized)
8626
8900
  this.applyDeoptimizations();
8627
- this.includeProperties(context, includeChildrenRecursively);
8901
+ if (this.variable) {
8902
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
8903
+ }
8904
+ else if (!this.isUndefined) {
8905
+ this.object.includePath([this.propertyKey], context);
8906
+ }
8907
+ }
8908
+ includePath(path, context) {
8909
+ if (!this.included)
8910
+ this.includeNode(context);
8911
+ if (this.variable) {
8912
+ this.variable?.includePath(path, context);
8913
+ }
8914
+ else if (!this.isUndefined) {
8915
+ this.object.includePath([
8916
+ this.propertyKey,
8917
+ ...(path.length < MAX_PATH_DEPTH
8918
+ ? path
8919
+ : [...path.slice(0, MAX_PATH_DEPTH), UnknownKey])
8920
+ ], context);
8921
+ }
8628
8922
  }
8629
8923
  includeAsAssignmentTarget(context, includeChildrenRecursively, deoptimizeAccess) {
8630
8924
  if (!this.assignmentDeoptimized)
@@ -8633,20 +8927,34 @@ class MemberExpression extends NodeBase {
8633
8927
  this.include(context, includeChildrenRecursively);
8634
8928
  }
8635
8929
  else {
8636
- this.includeProperties(context, includeChildrenRecursively);
8930
+ if (!this.included)
8931
+ this.includeNode(context);
8932
+ this.object.include(context, includeChildrenRecursively);
8933
+ this.property.include(context, includeChildrenRecursively);
8637
8934
  }
8638
8935
  }
8639
- includeCallArguments(context, parameters) {
8936
+ includeCallArguments(context, interaction) {
8640
8937
  if (this.variable) {
8641
- this.variable.includeCallArguments(context, parameters);
8938
+ this.variable.includeCallArguments(context, interaction);
8642
8939
  }
8643
8940
  else {
8644
- super.includeCallArguments(context, parameters);
8941
+ super.includeCallArguments(context, interaction);
8645
8942
  }
8646
8943
  }
8944
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
8945
+ if ((this.included ||=
8946
+ destructuredInitPath.length > 0 &&
8947
+ !context.brokenFlow &&
8948
+ init.hasEffectsOnInteractionAtPath(destructuredInitPath, NODE_INTERACTION_UNKNOWN_ACCESS, createHasEffectsContext()))) {
8949
+ init.include(context, false);
8950
+ return true;
8951
+ }
8952
+ return false;
8953
+ }
8647
8954
  initialise() {
8648
8955
  super.initialise();
8649
- this.propertyKey = getResolvablePropertyKey(this);
8956
+ this.dynamicPropertyKey = getResolvablePropertyKey(this);
8957
+ this.propertyKey = this.dynamicPropertyKey === null ? UnknownKey : this.dynamicPropertyKey;
8650
8958
  this.accessInteraction = { args: [this.object], type: INTERACTION_ACCESSED };
8651
8959
  }
8652
8960
  render(code, options, { renderedParentType, isCalleeOfRenderedParent, renderedSurroundingElement } = parseAst_js.BLANK) {
@@ -8683,8 +8991,7 @@ class MemberExpression extends NodeBase {
8683
8991
  this.bound &&
8684
8992
  propertyReadSideEffects &&
8685
8993
  !(this.variable || this.isUndefined)) {
8686
- const propertyKey = this.getPropertyKey();
8687
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [propertyKey], SHARED_RECURSION_TRACKER);
8994
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.accessInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
8688
8995
  this.scope.context.requestTreeshakingPass();
8689
8996
  }
8690
8997
  if (this.variable) {
@@ -8701,7 +9008,7 @@ class MemberExpression extends NodeBase {
8701
9008
  this.bound &&
8702
9009
  propertyReadSideEffects &&
8703
9010
  !(this.variable || this.isUndefined)) {
8704
- this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.getPropertyKey()], SHARED_RECURSION_TRACKER);
9011
+ this.object.deoptimizeArgumentsOnInteractionAtPath(this.assignmentInteraction, [this.propertyKey], SHARED_RECURSION_TRACKER);
8705
9012
  this.scope.context.requestTreeshakingPass();
8706
9013
  }
8707
9014
  }
@@ -8710,24 +9017,24 @@ class MemberExpression extends NodeBase {
8710
9017
  const variable = this.scope.findVariable(this.object.name);
8711
9018
  if (variable.isNamespace) {
8712
9019
  if (this.variable) {
8713
- this.scope.context.includeVariableInModule(this.variable);
9020
+ this.scope.context.includeVariableInModule(this.variable, UNKNOWN_PATH, createInclusionContext());
8714
9021
  }
8715
9022
  this.scope.context.log(parseAst_js.LOGLEVEL_WARN, parseAst_js.logIllegalImportReassignment(this.object.name, this.scope.context.module.id), this.start);
8716
9023
  }
8717
9024
  }
8718
9025
  }
8719
- getPropertyKey() {
8720
- if (this.propertyKey === null) {
8721
- this.propertyKey = UnknownKey;
9026
+ getDynamicPropertyKey() {
9027
+ if (this.dynamicPropertyKey === null) {
9028
+ this.dynamicPropertyKey = this.propertyKey;
8722
9029
  const value = this.property.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this);
8723
- return (this.propertyKey =
9030
+ return (this.dynamicPropertyKey =
8724
9031
  value === SymbolToStringTag
8725
9032
  ? value
8726
9033
  : typeof value === 'symbol'
8727
9034
  ? UnknownKey
8728
9035
  : String(value));
8729
9036
  }
8730
- return this.propertyKey;
9037
+ return this.dynamicPropertyKey;
8731
9038
  }
8732
9039
  hasAccessEffect(context) {
8733
9040
  const { propertyReadSideEffects } = this.scope.context.options
@@ -8735,17 +9042,7 @@ class MemberExpression extends NodeBase {
8735
9042
  return (!(this.variable || this.isUndefined) &&
8736
9043
  propertyReadSideEffects &&
8737
9044
  (propertyReadSideEffects === 'always' ||
8738
- this.object.hasEffectsOnInteractionAtPath([this.getPropertyKey()], this.accessInteraction, context)));
8739
- }
8740
- includeProperties(context, includeChildrenRecursively) {
8741
- if (!this.included) {
8742
- this.included = true;
8743
- if (this.variable) {
8744
- this.scope.context.includeVariableInModule(this.variable);
8745
- }
8746
- }
8747
- this.object.include(context, includeChildrenRecursively);
8748
- this.property.include(context, includeChildrenRecursively);
9045
+ this.object.hasEffectsOnInteractionAtPath([this.getDynamicPropertyKey()], this.accessInteraction, context)));
8749
9046
  }
8750
9047
  }
8751
9048
  function resolveNamespaceVariables(baseVariable, path, astContext) {
@@ -8789,18 +9086,20 @@ class MetaProperty extends NodeBase {
8789
9086
  return path.length > 1 || type !== INTERACTION_ACCESSED;
8790
9087
  }
8791
9088
  include() {
8792
- if (!this.included) {
8793
- this.included = true;
8794
- if (this.meta.name === IMPORT) {
8795
- this.scope.context.addImportMeta(this);
8796
- const parent = this.parent;
8797
- const metaProperty = (this.metaProperty =
8798
- parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
8799
- ? parent.propertyKey
8800
- : null);
8801
- if (metaProperty?.startsWith(FILE_PREFIX)) {
8802
- this.referenceId = metaProperty.slice(FILE_PREFIX.length);
8803
- }
9089
+ if (!this.included)
9090
+ this.includeNode();
9091
+ }
9092
+ includeNode() {
9093
+ this.included = true;
9094
+ if (this.meta.name === IMPORT) {
9095
+ this.scope.context.addImportMeta(this);
9096
+ const parent = this.parent;
9097
+ const metaProperty = (this.metaProperty =
9098
+ parent instanceof MemberExpression && typeof parent.propertyKey === 'string'
9099
+ ? parent.propertyKey
9100
+ : null);
9101
+ if (metaProperty?.startsWith(FILE_PREFIX)) {
9102
+ this.referenceId = metaProperty.slice(FILE_PREFIX.length);
8804
9103
  }
8805
9104
  }
8806
9105
  }
@@ -8907,7 +9206,7 @@ class UndefinedVariable extends Variable {
8907
9206
 
8908
9207
  class ExportDefaultVariable extends LocalVariable {
8909
9208
  constructor(name, exportDefaultDeclaration, context) {
8910
- super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, context, 'other');
9209
+ super(name, exportDefaultDeclaration, exportDefaultDeclaration.declaration, EMPTY_PATH, context, 'other');
8911
9210
  this.hasId = false;
8912
9211
  this.originalId = null;
8913
9212
  this.originalVariable = null;
@@ -9056,8 +9355,8 @@ class NamespaceVariable extends Variable {
9056
9355
  return (!memberVariable ||
9057
9356
  memberVariable.hasEffectsOnInteractionAtPath(path.slice(1), interaction, context));
9058
9357
  }
9059
- include() {
9060
- super.include();
9358
+ includePath(path, context) {
9359
+ super.includePath(path, context);
9061
9360
  this.context.includeAllExports();
9062
9361
  }
9063
9362
  prepare(accessedGlobalsByScope) {
@@ -9150,9 +9449,9 @@ class SyntheticNamedExportVariable extends Variable {
9150
9449
  getName(getPropertyAccess) {
9151
9450
  return `${this.syntheticNamespace.getName(getPropertyAccess)}${getPropertyAccess(this.name)}`;
9152
9451
  }
9153
- include() {
9154
- super.include();
9155
- this.context.includeVariableInModule(this.syntheticNamespace);
9452
+ includePath(path, context) {
9453
+ super.includePath(path, context);
9454
+ this.context.includeVariableInModule(this.syntheticNamespace, path, context);
9156
9455
  }
9157
9456
  setRenderNames(baseName, name) {
9158
9457
  super.setRenderNames(baseName, name);
@@ -12357,21 +12656,37 @@ class ArrayPattern extends NodeBase {
12357
12656
  element?.addExportedVariables(variables, exportNamesByVariable);
12358
12657
  }
12359
12658
  }
12360
- declare(kind) {
12659
+ declare(kind, destructuredInitPath, init) {
12361
12660
  const variables = [];
12661
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12362
12662
  for (const element of this.elements) {
12363
12663
  if (element !== null) {
12364
- variables.push(...element.declare(kind, UNKNOWN_EXPRESSION));
12664
+ variables.push(...element.declare(kind, includedPatternPath, init));
12365
12665
  }
12366
12666
  }
12367
12667
  return variables;
12368
12668
  }
12669
+ deoptimizeAssignment(destructuredInitPath, init) {
12670
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12671
+ for (const element of this.elements) {
12672
+ element?.deoptimizeAssignment(includedPatternPath, init);
12673
+ }
12674
+ }
12369
12675
  // Patterns can only be deoptimized at the empty path at the moment
12370
12676
  deoptimizePath() {
12371
12677
  for (const element of this.elements) {
12372
12678
  element?.deoptimizePath(EMPTY_PATH);
12373
12679
  }
12374
12680
  }
12681
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12682
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12683
+ for (const element of this.elements) {
12684
+ if (element?.hasEffectsWhenDestructuring(context, includedPatternPath, init)) {
12685
+ return true;
12686
+ }
12687
+ }
12688
+ return false;
12689
+ }
12375
12690
  // Patterns are only checked at the empty path at the moment
12376
12691
  hasEffectsOnInteractionAtPath(_path, interaction, context) {
12377
12692
  for (const element of this.elements) {
@@ -12380,12 +12695,38 @@ class ArrayPattern extends NodeBase {
12380
12695
  }
12381
12696
  return false;
12382
12697
  }
12698
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12699
+ let included = false;
12700
+ const includedPatternPath = getIncludedPatternPath(destructuredInitPath);
12701
+ for (const element of this.elements) {
12702
+ if (element) {
12703
+ element.included ||= included;
12704
+ included =
12705
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init) || included;
12706
+ }
12707
+ }
12708
+ if (included) {
12709
+ // This is necessary so that if any pattern element is included, all are
12710
+ // included for proper deconflicting
12711
+ for (const element of this.elements) {
12712
+ if (element && !element.included) {
12713
+ element.included = true;
12714
+ element.includeDestructuredIfNecessary(context, includedPatternPath, init);
12715
+ }
12716
+ }
12717
+ }
12718
+ return (this.included ||= included);
12719
+ }
12383
12720
  markDeclarationReached() {
12384
12721
  for (const element of this.elements) {
12385
12722
  element?.markDeclarationReached();
12386
12723
  }
12387
12724
  }
12388
12725
  }
12726
+ ArrayPattern.prototype.includeNode = onlyIncludeSelf;
12727
+ const getIncludedPatternPath = (destructuredInitPath) => destructuredInitPath.at(-1) === UnknownKey
12728
+ ? destructuredInitPath
12729
+ : [...destructuredInitPath, UnknownInteger];
12389
12730
 
12390
12731
  class ArrowFunctionExpression extends FunctionBase {
12391
12732
  constructor() {
@@ -12402,8 +12743,6 @@ class ArrowFunctionExpression extends FunctionBase {
12402
12743
  this.scope = new ReturnValueScope(parentScope, false);
12403
12744
  }
12404
12745
  hasEffects() {
12405
- if (!this.deoptimized)
12406
- this.applyDeoptimizations();
12407
12746
  return false;
12408
12747
  }
12409
12748
  hasEffectsOnInteractionAtPath(path, interaction, context) {
@@ -12442,6 +12781,15 @@ class ArrowFunctionExpression extends FunctionBase {
12442
12781
  }
12443
12782
  }
12444
12783
  }
12784
+ includeNode(context) {
12785
+ this.included = true;
12786
+ this.body.includePath(UNKNOWN_PATH, context);
12787
+ for (const parameter of this.params) {
12788
+ if (!(parameter instanceof Identifier)) {
12789
+ parameter.includePath(UNKNOWN_PATH, context);
12790
+ }
12791
+ }
12792
+ }
12445
12793
  getObjectEntity() {
12446
12794
  if (this.objectEntity !== null) {
12447
12795
  return this.objectEntity;
@@ -12461,13 +12809,18 @@ class ObjectPattern extends NodeBase {
12461
12809
  }
12462
12810
  }
12463
12811
  }
12464
- declare(kind, init) {
12812
+ declare(kind, destructuredInitPath, init) {
12465
12813
  const variables = [];
12466
12814
  for (const property of this.properties) {
12467
- variables.push(...property.declare(kind, init));
12815
+ variables.push(...property.declare(kind, destructuredInitPath, init));
12468
12816
  }
12469
12817
  return variables;
12470
12818
  }
12819
+ deoptimizeAssignment(destructuredInitPath, init) {
12820
+ for (const property of this.properties) {
12821
+ property.deoptimizeAssignment(destructuredInitPath, init);
12822
+ }
12823
+ }
12471
12824
  deoptimizePath(path) {
12472
12825
  if (path.length === 0) {
12473
12826
  for (const property of this.properties) {
@@ -12485,12 +12838,46 @@ class ObjectPattern extends NodeBase {
12485
12838
  }
12486
12839
  return false;
12487
12840
  }
12841
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
12842
+ for (const property of this.properties) {
12843
+ if (property.hasEffectsWhenDestructuring(context, destructuredInitPath, init))
12844
+ return true;
12845
+ }
12846
+ return false;
12847
+ }
12848
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
12849
+ let included = false;
12850
+ for (const property of this.properties) {
12851
+ included =
12852
+ property.includeDestructuredIfNecessary(context, destructuredInitPath, init) || included;
12853
+ }
12854
+ return (this.included ||= included);
12855
+ }
12488
12856
  markDeclarationReached() {
12489
12857
  for (const property of this.properties) {
12490
12858
  property.markDeclarationReached();
12491
12859
  }
12492
12860
  }
12861
+ render(code, options) {
12862
+ if (this.properties.length > 0) {
12863
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
12864
+ let lastSeparatorPos = null;
12865
+ for (const { node, separator, start, end } of separatedNodes) {
12866
+ if (!node.included) {
12867
+ treeshakeNode(node, code, start, end);
12868
+ continue;
12869
+ }
12870
+ lastSeparatorPos = separator;
12871
+ node.render(code, options);
12872
+ }
12873
+ if (lastSeparatorPos) {
12874
+ code.remove(lastSeparatorPos, this.end - 1);
12875
+ }
12876
+ }
12877
+ }
12493
12878
  }
12879
+ ObjectPattern.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
12880
+ ObjectPattern.prototype.applyDeoptimizations = doNotDeoptimize;
12494
12881
 
12495
12882
  class AssignmentExpression extends NodeBase {
12496
12883
  hasEffects(context) {
@@ -12499,7 +12886,9 @@ class AssignmentExpression extends NodeBase {
12499
12886
  this.applyDeoptimizations();
12500
12887
  // MemberExpressions do not access the property before assignments if the
12501
12888
  // operator is '='.
12502
- return (right.hasEffects(context) || left.hasEffectsAsAssignmentTarget(context, operator !== '='));
12889
+ return (right.hasEffects(context) ||
12890
+ left.hasEffectsAsAssignmentTarget(context, operator !== '=') ||
12891
+ this.left.hasEffectsWhenDestructuring?.(context, EMPTY_PATH, right));
12503
12892
  }
12504
12893
  hasEffectsOnInteractionAtPath(path, interaction, context) {
12505
12894
  return this.right.hasEffectsOnInteractionAtPath(path, interaction, context);
@@ -12508,15 +12897,24 @@ class AssignmentExpression extends NodeBase {
12508
12897
  const { deoptimized, left, right, operator } = this;
12509
12898
  if (!deoptimized)
12510
12899
  this.applyDeoptimizations();
12511
- this.included = true;
12900
+ if (!this.included)
12901
+ this.includeNode(context);
12902
+ const hasEffectsContext = createHasEffectsContext();
12512
12903
  if (includeChildrenRecursively ||
12513
12904
  operator !== '=' ||
12514
12905
  left.included ||
12515
- left.hasEffectsAsAssignmentTarget(createHasEffectsContext(), false)) {
12906
+ left.hasEffectsAsAssignmentTarget(hasEffectsContext, false) ||
12907
+ left.hasEffectsWhenDestructuring?.(hasEffectsContext, EMPTY_PATH, right)) {
12516
12908
  left.includeAsAssignmentTarget(context, includeChildrenRecursively, operator !== '=');
12517
12909
  }
12518
12910
  right.include(context, includeChildrenRecursively);
12519
12911
  }
12912
+ includeNode(context) {
12913
+ this.included = true;
12914
+ if (!this.deoptimized)
12915
+ this.applyDeoptimizations();
12916
+ this.right.includePath(UNKNOWN_PATH, context);
12917
+ }
12520
12918
  initialise() {
12521
12919
  super.initialise();
12522
12920
  if (this.left instanceof Identifier) {
@@ -12577,8 +12975,7 @@ class AssignmentExpression extends NodeBase {
12577
12975
  }
12578
12976
  applyDeoptimizations() {
12579
12977
  this.deoptimized = true;
12580
- this.left.deoptimizePath(EMPTY_PATH);
12581
- this.right.deoptimizePath(UNKNOWN_PATH);
12978
+ this.left.deoptimizeAssignment(EMPTY_PATH, this.right);
12582
12979
  this.scope.context.requestTreeshakingPass();
12583
12980
  }
12584
12981
  }
@@ -12587,8 +12984,11 @@ class AssignmentPattern extends NodeBase {
12587
12984
  addExportedVariables(variables, exportNamesByVariable) {
12588
12985
  this.left.addExportedVariables(variables, exportNamesByVariable);
12589
12986
  }
12590
- declare(kind, init) {
12591
- return this.left.declare(kind, init);
12987
+ declare(kind, destructuredInitPath, init) {
12988
+ return this.left.declare(kind, destructuredInitPath, init);
12989
+ }
12990
+ deoptimizeAssignment(destructuredInitPath, init) {
12991
+ this.left.deoptimizeAssignment(destructuredInitPath, init);
12592
12992
  }
12593
12993
  deoptimizePath(path) {
12594
12994
  if (path.length === 0) {
@@ -12598,6 +12998,29 @@ class AssignmentPattern extends NodeBase {
12598
12998
  hasEffectsOnInteractionAtPath(path, interaction, context) {
12599
12999
  return (path.length > 0 || this.left.hasEffectsOnInteractionAtPath(EMPTY_PATH, interaction, context));
12600
13000
  }
13001
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
13002
+ return this.left.hasEffectsWhenDestructuring(context, destructuredInitPath, init);
13003
+ }
13004
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
13005
+ let included = this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init) ||
13006
+ this.included;
13007
+ if ((included ||= this.right.shouldBeIncluded(context))) {
13008
+ this.right.include(context, false);
13009
+ if (!this.left.included) {
13010
+ this.left.included = true;
13011
+ // Unfortunately, we need to include the left side again now, so that
13012
+ // any declared variables are properly included.
13013
+ this.left.includeDestructuredIfNecessary(context, destructuredInitPath, init);
13014
+ }
13015
+ }
13016
+ return (this.included = included);
13017
+ }
13018
+ includeNode(context) {
13019
+ this.included = true;
13020
+ if (!this.deoptimized)
13021
+ this.applyDeoptimizations();
13022
+ this.right.includePath(UNKNOWN_PATH, context);
13023
+ }
12601
13024
  markDeclarationReached() {
12602
13025
  this.left.markDeclarationReached();
12603
13026
  }
@@ -12620,22 +13043,34 @@ class AwaitExpression extends NodeBase {
12620
13043
  return true;
12621
13044
  }
12622
13045
  include(context, includeChildrenRecursively) {
13046
+ if (!this.included)
13047
+ this.includeNode(context);
13048
+ this.argument.include(context, includeChildrenRecursively);
13049
+ }
13050
+ includeNode(context) {
13051
+ this.included = true;
12623
13052
  if (!this.deoptimized)
12624
13053
  this.applyDeoptimizations();
12625
- if (!this.included) {
12626
- this.included = true;
12627
- checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
12628
- let parent = this.parent;
12629
- do {
12630
- if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
12631
- break checkTopLevelAwait;
12632
- } while ((parent = parent.parent));
12633
- this.scope.context.usesTopLevelAwait = true;
12634
- }
13054
+ checkTopLevelAwait: if (!this.scope.context.usesTopLevelAwait) {
13055
+ let parent = this.parent;
13056
+ do {
13057
+ if (parent instanceof FunctionNode || parent instanceof ArrowFunctionExpression)
13058
+ break checkTopLevelAwait;
13059
+ } while ((parent = parent.parent));
13060
+ this.scope.context.usesTopLevelAwait = true;
12635
13061
  }
12636
- this.argument.include(context, includeChildrenRecursively);
13062
+ // Thenables need to be included
13063
+ this.argument.includePath(THEN_PATH, context);
13064
+ }
13065
+ includePath(path, context) {
13066
+ if (!this.deoptimized)
13067
+ this.applyDeoptimizations();
13068
+ if (!this.included)
13069
+ this.includeNode(context);
13070
+ this.argument.includePath(path, context);
12637
13071
  }
12638
13072
  }
13073
+ const THEN_PATH = ['then'];
12639
13074
 
12640
13075
  const binaryOperators = {
12641
13076
  '!=': (left, right) => left != right,
@@ -12691,6 +13126,12 @@ class BinaryExpression extends NodeBase {
12691
13126
  hasEffectsOnInteractionAtPath(path, { type }) {
12692
13127
  return type !== INTERACTION_ACCESSED || path.length > 1;
12693
13128
  }
13129
+ includeNode(context) {
13130
+ this.included = true;
13131
+ if (this.operator === 'in') {
13132
+ this.right.includePath(UNKNOWN_PATH, context);
13133
+ }
13134
+ }
12694
13135
  removeAnnotations(code) {
12695
13136
  this.left.removeAnnotations(code);
12696
13137
  }
@@ -12699,6 +13140,7 @@ class BinaryExpression extends NodeBase {
12699
13140
  this.right.render(code, options);
12700
13141
  }
12701
13142
  }
13143
+ BinaryExpression.prototype.applyDeoptimizations = doNotDeoptimize;
12702
13144
 
12703
13145
  class BreakStatement extends NodeBase {
12704
13146
  hasEffects(context) {
@@ -12718,7 +13160,7 @@ class BreakStatement extends NodeBase {
12718
13160
  include(context) {
12719
13161
  this.included = true;
12720
13162
  if (this.label) {
12721
- this.label.include();
13163
+ this.label.include(context);
12722
13164
  context.includedLabels.add(this.label.name);
12723
13165
  }
12724
13166
  else {
@@ -12727,6 +13169,8 @@ class BreakStatement extends NodeBase {
12727
13169
  context.brokenFlow = true;
12728
13170
  }
12729
13171
  }
13172
+ BreakStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13173
+ BreakStatement.prototype.applyDeoptimizations = doNotDeoptimize;
12730
13174
 
12731
13175
  function renderCallArguments(code, options, node) {
12732
13176
  if (node.arguments.length > 0) {
@@ -12913,10 +13357,14 @@ class CallExpression extends CallExpressionBase {
12913
13357
  this.callee.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context)));
12914
13358
  }
12915
13359
  include(context, includeChildrenRecursively) {
12916
- if (!this.deoptimized)
12917
- this.applyDeoptimizations();
13360
+ if (!this.included)
13361
+ this.includeNode(context);
12918
13362
  if (includeChildrenRecursively) {
12919
- super.include(context, includeChildrenRecursively);
13363
+ this.callee.include(context, true);
13364
+ for (const argument of this.arguments) {
13365
+ argument.includePath(UNKNOWN_PATH, context);
13366
+ argument.include(context, true);
13367
+ }
12920
13368
  if (includeChildrenRecursively === INCLUDE_PARAMETERS &&
12921
13369
  this.callee instanceof Identifier &&
12922
13370
  this.callee.variable) {
@@ -12924,10 +13372,24 @@ class CallExpression extends CallExpressionBase {
12924
13372
  }
12925
13373
  }
12926
13374
  else {
12927
- this.included = true;
12928
- this.callee.include(context, false);
13375
+ // If the callee is a member expression and does not have a variable, its
13376
+ // object will already be included via the first argument of the
13377
+ // interaction in includeCallArguments. Including it again can lead to
13378
+ // severe performance problems.
13379
+ if (this.callee instanceof MemberExpression && !this.callee.variable) {
13380
+ this.callee.property.include(context, false);
13381
+ }
13382
+ else {
13383
+ this.callee.include(context, false);
13384
+ }
13385
+ this.callee.includeCallArguments(context, this.interaction);
12929
13386
  }
12930
- this.callee.includeCallArguments(context, this.arguments);
13387
+ }
13388
+ includeNode(context) {
13389
+ this.included = true;
13390
+ if (!this.deoptimized)
13391
+ this.applyDeoptimizations();
13392
+ this.callee.includePath(UNKNOWN_PATH, context);
12931
13393
  }
12932
13394
  initialise() {
12933
13395
  super.initialise();
@@ -12966,13 +13428,14 @@ class CatchClause extends NodeBase {
12966
13428
  this.type = type;
12967
13429
  if (param) {
12968
13430
  this.param = new (this.scope.context.getNodeConstructor(param.type))(this, this.scope).parseNode(param);
12969
- this.param.declare('parameter', UNKNOWN_EXPRESSION);
13431
+ this.param.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
12970
13432
  }
12971
13433
  this.body = new BlockStatement(this, this.scope.bodyScope).parseNode(body);
12972
13434
  return super.parseNode(esTreeNode);
12973
13435
  }
12974
13436
  }
12975
13437
  CatchClause.prototype.preventChildBlockScope = true;
13438
+ CatchClause.prototype.includeNode = onlyIncludeSelf;
12976
13439
 
12977
13440
  class ChainExpression extends NodeBase {
12978
13441
  // deoptimizations are not relevant as we are not caching values
@@ -12984,17 +13447,22 @@ class ChainExpression extends NodeBase {
12984
13447
  hasEffects(context) {
12985
13448
  return this.expression.hasEffectsAsChainElement(context) === true;
12986
13449
  }
13450
+ includePath(path, context) {
13451
+ this.included = true;
13452
+ this.expression.includePath(path, context);
13453
+ }
12987
13454
  removeAnnotations(code) {
12988
13455
  this.expression.removeAnnotations(code);
12989
13456
  }
12990
- applyDeoptimizations() { }
12991
13457
  }
13458
+ ChainExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13459
+ ChainExpression.prototype.applyDeoptimizations = doNotDeoptimize;
12992
13460
 
12993
13461
  class ClassBodyScope extends ChildScope {
12994
13462
  constructor(parent, classNode) {
12995
13463
  const { context } = parent;
12996
13464
  super(parent, context);
12997
- this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, context, 'other')));
13465
+ this.variables.set('this', (this.thisVariable = new LocalVariable('this', null, classNode, EMPTY_PATH, context, 'other')));
12998
13466
  this.instanceScope = new ChildScope(this, context);
12999
13467
  this.instanceScope.variables.set('this', new ThisVariable(context));
13000
13468
  }
@@ -13009,7 +13477,7 @@ class ClassBody extends NodeBase {
13009
13477
  }
13010
13478
  include(context, includeChildrenRecursively) {
13011
13479
  this.included = true;
13012
- this.scope.context.includeVariableInModule(this.scope.thisVariable);
13480
+ this.scope.context.includeVariableInModule(this.scope.thisVariable, UNKNOWN_PATH, context);
13013
13481
  for (const definition of this.body) {
13014
13482
  definition.include(context, includeChildrenRecursively);
13015
13483
  }
@@ -13022,8 +13490,9 @@ class ClassBody extends NodeBase {
13022
13490
  }
13023
13491
  return super.parseNode(esTreeNode);
13024
13492
  }
13025
- applyDeoptimizations() { }
13026
13493
  }
13494
+ ClassBody.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13495
+ ClassBody.prototype.applyDeoptimizations = doNotDeoptimize;
13027
13496
 
13028
13497
  class ClassExpression extends ClassNode {
13029
13498
  render(code, options, { renderedSurroundingElement } = parseAst_js.BLANK) {
@@ -13094,6 +13563,9 @@ class ConditionalExpression extends NodeBase {
13094
13563
  const unusedBranch = this.usedBranch === this.consequent ? this.alternate : this.consequent;
13095
13564
  this.usedBranch = null;
13096
13565
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
13566
+ if (this.included) {
13567
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
13568
+ }
13097
13569
  const { expressionsToBeDeoptimized } = this;
13098
13570
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
13099
13571
  for (const expression of expressionsToBeDeoptimized) {
@@ -13151,7 +13623,7 @@ class ConditionalExpression extends NodeBase {
13151
13623
  include(context, includeChildrenRecursively) {
13152
13624
  this.included = true;
13153
13625
  const usedBranch = this.getUsedBranch();
13154
- if (includeChildrenRecursively || this.test.shouldBeIncluded(context) || usedBranch === null) {
13626
+ if (usedBranch === null || includeChildrenRecursively || this.test.shouldBeIncluded(context)) {
13155
13627
  this.test.include(context, includeChildrenRecursively);
13156
13628
  this.consequent.include(context, includeChildrenRecursively);
13157
13629
  this.alternate.include(context, includeChildrenRecursively);
@@ -13160,27 +13632,38 @@ class ConditionalExpression extends NodeBase {
13160
13632
  usedBranch.include(context, includeChildrenRecursively);
13161
13633
  }
13162
13634
  }
13163
- includeCallArguments(context, parameters) {
13635
+ includePath(path, context) {
13636
+ this.included = true;
13637
+ const usedBranch = this.getUsedBranch();
13638
+ if (usedBranch === null || this.test.shouldBeIncluded(context)) {
13639
+ this.consequent.includePath(path, context);
13640
+ this.alternate.includePath(path, context);
13641
+ }
13642
+ else {
13643
+ usedBranch.includePath(path, context);
13644
+ }
13645
+ }
13646
+ includeCallArguments(context, interaction) {
13164
13647
  const usedBranch = this.getUsedBranch();
13165
13648
  if (usedBranch) {
13166
- usedBranch.includeCallArguments(context, parameters);
13649
+ usedBranch.includeCallArguments(context, interaction);
13167
13650
  }
13168
13651
  else {
13169
- this.consequent.includeCallArguments(context, parameters);
13170
- this.alternate.includeCallArguments(context, parameters);
13652
+ this.consequent.includeCallArguments(context, interaction);
13653
+ this.alternate.includeCallArguments(context, interaction);
13171
13654
  }
13172
13655
  }
13173
13656
  removeAnnotations(code) {
13174
13657
  this.test.removeAnnotations(code);
13175
13658
  }
13176
13659
  render(code, options, { isCalleeOfRenderedParent, preventASI, renderedParentType, renderedSurroundingElement } = parseAst_js.BLANK) {
13177
- const usedBranch = this.getUsedBranch();
13178
13660
  if (this.test.included) {
13179
13661
  this.test.render(code, options, { renderedSurroundingElement });
13180
13662
  this.consequent.render(code, options);
13181
13663
  this.alternate.render(code, options);
13182
13664
  }
13183
13665
  else {
13666
+ const usedBranch = this.getUsedBranch();
13184
13667
  const colonPos = findFirstOccurrenceOutsideComment(code.original, ':', this.consequent.end);
13185
13668
  const inclusionStart = findNonWhiteSpace(code.original, (this.consequent.included
13186
13669
  ? findFirstOccurrenceOutsideComment(code.original, '?', this.test.end)
@@ -13212,6 +13695,8 @@ class ConditionalExpression extends NodeBase {
13212
13695
  : (this.usedBranch = testValue ? this.consequent : this.alternate);
13213
13696
  }
13214
13697
  }
13698
+ ConditionalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13699
+ ConditionalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
13215
13700
 
13216
13701
  class ContinueStatement extends NodeBase {
13217
13702
  hasEffects(context) {
@@ -13231,7 +13716,7 @@ class ContinueStatement extends NodeBase {
13231
13716
  include(context) {
13232
13717
  this.included = true;
13233
13718
  if (this.label) {
13234
- this.label.include();
13719
+ this.label.include(context);
13235
13720
  context.includedLabels.add(this.label.name);
13236
13721
  }
13237
13722
  else {
@@ -13240,12 +13725,15 @@ class ContinueStatement extends NodeBase {
13240
13725
  context.brokenFlow = true;
13241
13726
  }
13242
13727
  }
13728
+ ContinueStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13729
+ ContinueStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13243
13730
 
13244
13731
  class DebuggerStatement extends NodeBase {
13245
13732
  hasEffects() {
13246
13733
  return true;
13247
13734
  }
13248
13735
  }
13736
+ DebuggerStatement.prototype.includeNode = onlyIncludeSelf;
13249
13737
 
13250
13738
  class Decorator extends NodeBase {
13251
13739
  hasEffects(context) {
@@ -13253,6 +13741,7 @@ class Decorator extends NodeBase {
13253
13741
  this.expression.hasEffectsOnInteractionAtPath(EMPTY_PATH, NODE_INTERACTION_UNKNOWN_CALL, context));
13254
13742
  }
13255
13743
  }
13744
+ Decorator.prototype.includeNode = onlyIncludeSelf;
13256
13745
 
13257
13746
  function hasLoopBodyEffects(context, body) {
13258
13747
  const { brokenFlow, hasBreak, hasContinue, ignore } = context;
@@ -13292,12 +13781,15 @@ class DoWhileStatement extends NodeBase {
13292
13781
  includeLoopBody(context, this.body, includeChildrenRecursively);
13293
13782
  }
13294
13783
  }
13784
+ DoWhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13785
+ DoWhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13295
13786
 
13296
13787
  class EmptyStatement extends NodeBase {
13297
13788
  hasEffects() {
13298
13789
  return false;
13299
13790
  }
13300
13791
  }
13792
+ EmptyStatement.prototype.includeNode = onlyIncludeSelf;
13301
13793
 
13302
13794
  class ExportAllDeclaration extends NodeBase {
13303
13795
  hasEffects() {
@@ -13310,9 +13802,10 @@ class ExportAllDeclaration extends NodeBase {
13310
13802
  render(code, _options, nodeRenderOptions) {
13311
13803
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
13312
13804
  }
13313
- applyDeoptimizations() { }
13314
13805
  }
13315
13806
  ExportAllDeclaration.prototype.needsBoundaries = true;
13807
+ ExportAllDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13808
+ ExportAllDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13316
13809
 
13317
13810
  class ExportNamedDeclaration extends NodeBase {
13318
13811
  bind() {
@@ -13339,13 +13832,15 @@ class ExportNamedDeclaration extends NodeBase {
13339
13832
  this.declaration.render(code, options, { end, start });
13340
13833
  }
13341
13834
  }
13342
- applyDeoptimizations() { }
13343
13835
  }
13344
13836
  ExportNamedDeclaration.prototype.needsBoundaries = true;
13837
+ ExportNamedDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13838
+ ExportNamedDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13345
13839
 
13346
13840
  class ExportSpecifier extends NodeBase {
13347
- applyDeoptimizations() { }
13348
13841
  }
13842
+ ExportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13843
+ ExportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
13349
13844
 
13350
13845
  class ForInStatement extends NodeBase {
13351
13846
  createScope(parentScope) {
@@ -13363,11 +13858,18 @@ class ForInStatement extends NodeBase {
13363
13858
  const { body, deoptimized, left, right } = this;
13364
13859
  if (!deoptimized)
13365
13860
  this.applyDeoptimizations();
13366
- this.included = true;
13861
+ if (!this.included)
13862
+ this.includeNode(context);
13367
13863
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
13368
13864
  right.include(context, includeChildrenRecursively);
13369
13865
  includeLoopBody(context, body, includeChildrenRecursively);
13370
13866
  }
13867
+ includeNode(context) {
13868
+ this.included = true;
13869
+ if (!this.deoptimized)
13870
+ this.applyDeoptimizations();
13871
+ this.right.includePath(UNKNOWN_PATH, context);
13872
+ }
13371
13873
  initialise() {
13372
13874
  super.initialise();
13373
13875
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -13408,11 +13910,18 @@ class ForOfStatement extends NodeBase {
13408
13910
  const { body, deoptimized, left, right } = this;
13409
13911
  if (!deoptimized)
13410
13912
  this.applyDeoptimizations();
13411
- this.included = true;
13913
+ if (!this.included)
13914
+ this.includeNode(context);
13412
13915
  left.includeAsAssignmentTarget(context, includeChildrenRecursively || true, false);
13413
13916
  right.include(context, includeChildrenRecursively);
13414
13917
  includeLoopBody(context, body, includeChildrenRecursively);
13415
13918
  }
13919
+ includeNode(context) {
13920
+ this.included = true;
13921
+ if (!this.deoptimized)
13922
+ this.applyDeoptimizations();
13923
+ this.right.includePath(UNKNOWN_PATH, context);
13924
+ }
13416
13925
  initialise() {
13417
13926
  super.initialise();
13418
13927
  this.left.setAssignedValue(UNKNOWN_EXPRESSION);
@@ -13448,7 +13957,9 @@ class ForStatement extends NodeBase {
13448
13957
  }
13449
13958
  include(context, includeChildrenRecursively) {
13450
13959
  this.included = true;
13451
- this.init?.include(context, includeChildrenRecursively, { asSingleStatement: true });
13960
+ this.init?.include(context, includeChildrenRecursively, {
13961
+ asSingleStatement: true
13962
+ });
13452
13963
  this.test?.include(context, includeChildrenRecursively);
13453
13964
  this.update?.include(context, includeChildrenRecursively);
13454
13965
  includeLoopBody(context, this.body, includeChildrenRecursively);
@@ -13460,6 +13971,8 @@ class ForStatement extends NodeBase {
13460
13971
  this.body.render(code, options);
13461
13972
  }
13462
13973
  }
13974
+ ForStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
13975
+ ForStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13463
13976
 
13464
13977
  class FunctionExpression extends FunctionNode {
13465
13978
  createScope(parentScope) {
@@ -13491,9 +14004,9 @@ class TrackingScope extends BlockScope {
13491
14004
  super(...arguments);
13492
14005
  this.hoistedDeclarations = [];
13493
14006
  }
13494
- addDeclaration(identifier, context, init, kind) {
14007
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
13495
14008
  this.hoistedDeclarations.push(identifier);
13496
- return super.addDeclaration(identifier, context, init, kind);
14009
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
13497
14010
  }
13498
14011
  }
13499
14012
 
@@ -13592,7 +14105,6 @@ class IfStatement extends NodeBase {
13592
14105
  }
13593
14106
  this.renderHoistedDeclarations(hoistedDeclarations, code, getPropertyAccess);
13594
14107
  }
13595
- applyDeoptimizations() { }
13596
14108
  getTestValue() {
13597
14109
  if (this.testValue === unset) {
13598
14110
  return (this.testValue = tryCastLiteralValueToBoolean(this.test.getLiteralValueAtPath(EMPTY_PATH, SHARED_RECURSION_TRACKER, this)));
@@ -13661,6 +14173,8 @@ class IfStatement extends NodeBase {
13661
14173
  return false;
13662
14174
  }
13663
14175
  }
14176
+ IfStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14177
+ IfStatement.prototype.applyDeoptimizations = doNotDeoptimize;
13664
14178
 
13665
14179
  class ImportAttribute extends NodeBase {
13666
14180
  }
@@ -13678,13 +14192,15 @@ class ImportDeclaration extends NodeBase {
13678
14192
  render(code, _options, nodeRenderOptions) {
13679
14193
  code.remove(nodeRenderOptions.start, nodeRenderOptions.end);
13680
14194
  }
13681
- applyDeoptimizations() { }
13682
14195
  }
13683
14196
  ImportDeclaration.prototype.needsBoundaries = true;
14197
+ ImportDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14198
+ ImportDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
13684
14199
 
13685
14200
  class ImportDefaultSpecifier extends NodeBase {
13686
- applyDeoptimizations() { }
13687
14201
  }
14202
+ ImportDefaultSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14203
+ ImportDefaultSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
13688
14204
 
13689
14205
  function isReassignedExportsMember(variable, exportNamesByVariable) {
13690
14206
  return (variable.renderBaseName !== null && exportNamesByVariable.has(variable) && variable.isReassigned);
@@ -13693,28 +14209,33 @@ function isReassignedExportsMember(variable, exportNamesByVariable) {
13693
14209
  class VariableDeclarator extends NodeBase {
13694
14210
  declareDeclarator(kind, isUsingDeclaration) {
13695
14211
  this.isUsingDeclaration = isUsingDeclaration;
13696
- this.id.declare(kind, this.init || UNDEFINED_EXPRESSION);
14212
+ this.id.declare(kind, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION);
13697
14213
  }
13698
14214
  deoptimizePath(path) {
13699
14215
  this.id.deoptimizePath(path);
13700
14216
  }
13701
14217
  hasEffects(context) {
13702
- if (!this.deoptimized)
13703
- this.applyDeoptimizations();
13704
14218
  const initEffect = this.init?.hasEffects(context);
13705
14219
  this.id.markDeclarationReached();
13706
- return initEffect || this.id.hasEffects(context) || this.isUsingDeclaration;
14220
+ return (initEffect ||
14221
+ this.isUsingDeclaration ||
14222
+ this.id.hasEffects(context) ||
14223
+ (this.scope.context.options.treeshake
14224
+ .propertyReadSideEffects &&
14225
+ this.id.hasEffectsWhenDestructuring(context, EMPTY_PATH, this.init || UNDEFINED_EXPRESSION)));
13707
14226
  }
13708
14227
  include(context, includeChildrenRecursively) {
13709
- const { deoptimized, id, init } = this;
13710
- if (!deoptimized)
13711
- this.applyDeoptimizations();
13712
- this.included = true;
14228
+ const { id, init } = this;
14229
+ if (!this.included)
14230
+ this.includeNode();
13713
14231
  init?.include(context, includeChildrenRecursively);
13714
14232
  id.markDeclarationReached();
13715
- if (includeChildrenRecursively || id.shouldBeIncluded(context)) {
14233
+ if (includeChildrenRecursively) {
13716
14234
  id.include(context, includeChildrenRecursively);
13717
14235
  }
14236
+ else {
14237
+ id.includeDestructuredIfNecessary(context, EMPTY_PATH, init || UNDEFINED_EXPRESSION);
14238
+ }
13718
14239
  }
13719
14240
  removeAnnotations(code) {
13720
14241
  this.init?.removeAnnotations(code);
@@ -13744,8 +14265,8 @@ class VariableDeclarator extends NodeBase {
13744
14265
  code.appendLeft(end, `${_}=${_}void 0`);
13745
14266
  }
13746
14267
  }
13747
- applyDeoptimizations() {
13748
- this.deoptimized = true;
14268
+ includeNode() {
14269
+ this.included = true;
13749
14270
  const { id, init } = this;
13750
14271
  if (init && id instanceof Identifier && init instanceof ClassExpression && !init.id) {
13751
14272
  const { name, variable } = id;
@@ -13757,11 +14278,14 @@ class VariableDeclarator extends NodeBase {
13757
14278
  }
13758
14279
  }
13759
14280
  }
14281
+ VariableDeclarator.prototype.applyDeoptimizations = doNotDeoptimize;
13760
14282
 
13761
14283
  class ImportExpression extends NodeBase {
13762
14284
  constructor() {
13763
14285
  super(...arguments);
13764
14286
  this.inlineNamespace = null;
14287
+ this.hasUnknownAccessedKey = false;
14288
+ this.accessedPropKey = new Set();
13765
14289
  this.attributes = null;
13766
14290
  this.mechanism = null;
13767
14291
  this.namespaceExportName = undefined;
@@ -13794,12 +14318,15 @@ class ImportExpression extends NodeBase {
13794
14318
  if (parent2 instanceof ExpressionStatement) {
13795
14319
  return parseAst_js.EMPTY_ARRAY;
13796
14320
  }
13797
- // Case 1: const { foo } = await import('bar')
14321
+ // Case 1: const { foo } / module = await import('bar')
13798
14322
  if (parent2 instanceof VariableDeclarator) {
13799
14323
  const declaration = parent2.id;
13800
- return declaration instanceof ObjectPattern
13801
- ? getDeterministicObjectDestructure(declaration)
13802
- : undefined;
14324
+ if (declaration instanceof Identifier) {
14325
+ return this.hasUnknownAccessedKey ? undefined : [...this.accessedPropKey];
14326
+ }
14327
+ if (declaration instanceof ObjectPattern) {
14328
+ return getDeterministicObjectDestructure(declaration);
14329
+ }
13803
14330
  }
13804
14331
  // Case 2: (await import('bar')).foo
13805
14332
  if (parent2 instanceof MemberExpression) {
@@ -13849,13 +14376,30 @@ class ImportExpression extends NodeBase {
13849
14376
  return true;
13850
14377
  }
13851
14378
  include(context, includeChildrenRecursively) {
13852
- if (!this.included) {
13853
- this.included = true;
13854
- this.scope.context.includeDynamicImport(this);
13855
- this.scope.addAccessedDynamicImport(this);
13856
- }
14379
+ if (!this.included)
14380
+ this.includeNode();
13857
14381
  this.source.include(context, includeChildrenRecursively);
13858
14382
  }
14383
+ includeNode() {
14384
+ this.included = true;
14385
+ this.scope.context.includeDynamicImport(this);
14386
+ this.scope.addAccessedDynamicImport(this);
14387
+ }
14388
+ includePath(path) {
14389
+ if (!this.included)
14390
+ this.includeNode();
14391
+ // Technically, this is not correct as dynamic imports return a Promise.
14392
+ if (this.hasUnknownAccessedKey)
14393
+ return;
14394
+ if (path[0] === UnknownKey) {
14395
+ this.hasUnknownAccessedKey = true;
14396
+ }
14397
+ else if (typeof path[0] === 'string') {
14398
+ this.accessedPropKey.add(path[0]);
14399
+ }
14400
+ // Update included paths
14401
+ this.scope.context.includeDynamicImport(this);
14402
+ }
13859
14403
  initialise() {
13860
14404
  super.initialise();
13861
14405
  this.scope.context.addDynamicImport(this);
@@ -13924,7 +14468,6 @@ class ImportExpression extends NodeBase {
13924
14468
  setInternalResolution(inlineNamespace) {
13925
14469
  this.inlineNamespace = inlineNamespace;
13926
14470
  }
13927
- applyDeoptimizations() { }
13928
14471
  getDynamicImportMechanismAndHelper(resolution, exportMode, { compact, dynamicImportInCjs, format, generatedCode: { arrowFunctions }, interop }, { _, getDirectReturnFunction, getDirectReturnIifeLeft }, pluginDriver) {
13929
14472
  const mechanism = pluginDriver.hookFirstSync('renderDynamicImport', [
13930
14473
  {
@@ -14014,6 +14557,7 @@ class ImportExpression extends NodeBase {
14014
14557
  return { helper: null, mechanism: null };
14015
14558
  }
14016
14559
  }
14560
+ ImportExpression.prototype.applyDeoptimizations = doNotDeoptimize;
14017
14561
  function getInteropHelper(resolution, exportMode, interop) {
14018
14562
  return exportMode === 'external'
14019
14563
  ? namespaceInteropHelpersByInteropType[interop(resolution instanceof ExternalModule ? resolution.id : null)]
@@ -14037,12 +14581,14 @@ function getDeterministicObjectDestructure(objectPattern) {
14037
14581
  }
14038
14582
 
14039
14583
  class ImportNamespaceSpecifier extends NodeBase {
14040
- applyDeoptimizations() { }
14041
14584
  }
14585
+ ImportNamespaceSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14586
+ ImportNamespaceSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
14042
14587
 
14043
14588
  class ImportSpecifier extends NodeBase {
14044
- applyDeoptimizations() { }
14045
14589
  }
14590
+ ImportSpecifier.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
14591
+ ImportSpecifier.prototype.applyDeoptimizations = doNotDeoptimize;
14046
14592
 
14047
14593
  class JSXIdentifier extends IdentifierBase {
14048
14594
  constructor() {
@@ -14059,6 +14605,29 @@ class JSXIdentifier extends IdentifierBase {
14059
14605
  this.isNativeElement = true;
14060
14606
  }
14061
14607
  }
14608
+ include(context) {
14609
+ if (!this.included)
14610
+ this.includeNode(context);
14611
+ }
14612
+ includeNode(context) {
14613
+ this.included = true;
14614
+ if (!this.deoptimized)
14615
+ this.applyDeoptimizations();
14616
+ if (this.variable !== null) {
14617
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
14618
+ }
14619
+ }
14620
+ includePath(path, context) {
14621
+ if (!this.included) {
14622
+ this.included = true;
14623
+ if (this.variable !== null) {
14624
+ this.scope.context.includeVariableInModule(this.variable, path, context);
14625
+ }
14626
+ }
14627
+ else if (path.length > 0) {
14628
+ this.variable?.includePath(path, context);
14629
+ }
14630
+ }
14062
14631
  render(code, { snippets: { getPropertyAccess }, useOriginalName }) {
14063
14632
  if (this.variable) {
14064
14633
  const name = this.variable.getName(getPropertyAccess, useOriginalName);
@@ -14120,6 +14689,7 @@ class JSXAttribute extends NodeBase {
14120
14689
  }
14121
14690
  }
14122
14691
  }
14692
+ JSXAttribute.prototype.includeNode = onlyIncludeSelf;
14123
14693
 
14124
14694
  class JSXClosingBase extends NodeBase {
14125
14695
  render(code, options) {
@@ -14132,6 +14702,7 @@ class JSXClosingBase extends NodeBase {
14132
14702
  }
14133
14703
  }
14134
14704
  }
14705
+ JSXClosingBase.prototype.includeNode = onlyIncludeSelf;
14135
14706
 
14136
14707
  class JSXClosingElement extends JSXClosingBase {
14137
14708
  }
@@ -14152,8 +14723,15 @@ class JSXSpreadAttribute extends NodeBase {
14152
14723
 
14153
14724
  class JSXEmptyExpression extends NodeBase {
14154
14725
  }
14726
+ JSXEmptyExpression.prototype.includeNode = onlyIncludeSelf;
14155
14727
 
14156
14728
  class JSXExpressionContainer extends NodeBase {
14729
+ includeNode(context) {
14730
+ this.included = true;
14731
+ if (!this.deoptimized)
14732
+ this.applyDeoptimizations();
14733
+ this.expression.includePath(UNKNOWN_PATH, context);
14734
+ }
14157
14735
  render(code, options) {
14158
14736
  const { mode } = this.scope.context.options.jsx;
14159
14737
  if (mode !== 'preserve') {
@@ -14174,7 +14752,7 @@ function getRenderedJsxChildren(children) {
14174
14752
  return renderedChildren;
14175
14753
  }
14176
14754
 
14177
- function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14755
+ function getAndIncludeFactoryVariable(factory, preserve, importSource, node, context) {
14178
14756
  const [baseName, nestedName] = factory.split('.');
14179
14757
  let factoryVariable;
14180
14758
  if (importSource) {
@@ -14182,7 +14760,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14182
14760
  if (preserve) {
14183
14761
  // This pretends we are accessing an included global variable of the same name
14184
14762
  const globalVariable = node.scope.findGlobal(baseName);
14185
- globalVariable.include();
14763
+ globalVariable.includePath(UNKNOWN_PATH, context);
14186
14764
  // This excludes this variable from renaming
14187
14765
  factoryVariable.globalName = baseName;
14188
14766
  }
@@ -14190,7 +14768,7 @@ function getAndIncludeFactoryVariable(factory, preserve, importSource, node) {
14190
14768
  else {
14191
14769
  factoryVariable = node.scope.findGlobal(baseName);
14192
14770
  }
14193
- node.scope.context.includeVariableInModule(factoryVariable);
14771
+ node.scope.context.includeVariableInModule(factoryVariable, UNKNOWN_PATH, context);
14194
14772
  if (factoryVariable instanceof LocalVariable) {
14195
14773
  factoryVariable.consolidateInitializers();
14196
14774
  factoryVariable.addUsedPlace(node);
@@ -14213,16 +14791,20 @@ class JSXElementBase extends NodeBase {
14213
14791
  }
14214
14792
  }
14215
14793
  include(context, includeChildrenRecursively) {
14216
- if (!this.included) {
14217
- const { factory, importSource, mode } = this.jsxMode;
14218
- if (factory) {
14219
- this.factory = factory;
14220
- this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this);
14221
- }
14794
+ if (!this.included)
14795
+ this.includeNode(context);
14796
+ for (const child of this.children) {
14797
+ child.include(context, includeChildrenRecursively);
14798
+ }
14799
+ }
14800
+ includeNode(context) {
14801
+ this.included = true;
14802
+ const { factory, importSource, mode } = this.jsxMode;
14803
+ if (factory) {
14804
+ this.factory = factory;
14805
+ this.factoryVariable = getAndIncludeFactoryVariable(factory, mode === 'preserve', importSource, this, context);
14222
14806
  }
14223
- super.include(context, includeChildrenRecursively);
14224
14807
  }
14225
- applyDeoptimizations() { }
14226
14808
  getRenderingMode() {
14227
14809
  const jsx = this.scope.context.options.jsx;
14228
14810
  const { mode, factory, importSource } = jsx;
@@ -14260,8 +14842,14 @@ class JSXElementBase extends NodeBase {
14260
14842
  return { childrenEnd, firstChild, hasMultipleChildren };
14261
14843
  }
14262
14844
  }
14845
+ JSXElementBase.prototype.applyDeoptimizations = doNotDeoptimize;
14263
14846
 
14264
14847
  class JSXElement extends JSXElementBase {
14848
+ include(context, includeChildrenRecursively) {
14849
+ super.include(context, includeChildrenRecursively);
14850
+ this.openingElement.include(context, includeChildrenRecursively);
14851
+ this.closingElement?.include(context, includeChildrenRecursively);
14852
+ }
14265
14853
  render(code, options) {
14266
14854
  switch (this.jsxMode.mode) {
14267
14855
  case 'classic': {
@@ -14413,6 +15001,11 @@ class JSXElement extends JSXElementBase {
14413
15001
  }
14414
15002
 
14415
15003
  class JSXFragment extends JSXElementBase {
15004
+ include(context, includeChildrenRecursively) {
15005
+ super.include(context, includeChildrenRecursively);
15006
+ this.openingFragment.include(context, includeChildrenRecursively);
15007
+ this.closingFragment.include(context, includeChildrenRecursively);
15008
+ }
14416
15009
  render(code, options) {
14417
15010
  switch (this.jsxMode.mode) {
14418
15011
  case 'classic': {
@@ -14462,10 +15055,22 @@ class JSXFragment extends JSXElementBase {
14462
15055
  }
14463
15056
 
14464
15057
  class JSXMemberExpression extends NodeBase {
15058
+ includeNode(context) {
15059
+ this.included = true;
15060
+ if (!this.deoptimized)
15061
+ this.applyDeoptimizations();
15062
+ this.object.includePath([this.property.name], context);
15063
+ }
15064
+ includePath(path, context) {
15065
+ if (!this.included)
15066
+ this.includeNode(context);
15067
+ this.object.includePath([this.property.name, ...path], context);
15068
+ }
14465
15069
  }
14466
15070
 
14467
15071
  class JSXNamespacedName extends NodeBase {
14468
15072
  }
15073
+ JSXNamespacedName.prototype.includeNode = onlyIncludeSelf;
14469
15074
 
14470
15075
  class JSXOpeningElement extends NodeBase {
14471
15076
  render(code, options, { jsxMode = this.scope.context.options.jsx.mode } = {}) {
@@ -14475,6 +15080,7 @@ class JSXOpeningElement extends NodeBase {
14475
15080
  }
14476
15081
  }
14477
15082
  }
15083
+ JSXOpeningElement.prototype.includeNode = onlyIncludeSelf;
14478
15084
 
14479
15085
  class JSXOpeningFragment extends NodeBase {
14480
15086
  constructor() {
@@ -14482,22 +15088,22 @@ class JSXOpeningFragment extends NodeBase {
14482
15088
  this.fragment = null;
14483
15089
  this.fragmentVariable = null;
14484
15090
  }
14485
- include(context, includeChildrenRecursively) {
14486
- if (!this.included) {
14487
- const jsx = this.scope.context.options.jsx;
14488
- if (jsx.mode === 'automatic') {
14489
- this.fragment = 'Fragment';
14490
- this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this);
14491
- }
14492
- else {
14493
- const { fragment, importSource, mode } = jsx;
14494
- if (fragment != null) {
14495
- this.fragment = fragment;
14496
- this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this);
14497
- }
15091
+ includeNode(context) {
15092
+ this.included = true;
15093
+ if (!this.deoptimized)
15094
+ this.applyDeoptimizations();
15095
+ const jsx = this.scope.context.options.jsx;
15096
+ if (jsx.mode === 'automatic') {
15097
+ this.fragment = 'Fragment';
15098
+ this.fragmentVariable = getAndIncludeFactoryVariable('Fragment', false, jsx.jsxImportSource, this, context);
15099
+ }
15100
+ else {
15101
+ const { fragment, importSource, mode } = jsx;
15102
+ if (fragment != null) {
15103
+ this.fragment = fragment;
15104
+ this.fragmentVariable = getAndIncludeFactoryVariable(fragment, mode === 'preserve', importSource, this, context);
14498
15105
  }
14499
15106
  }
14500
- super.include(context, includeChildrenRecursively);
14501
15107
  }
14502
15108
  render(code, options) {
14503
15109
  const { mode } = this.scope.context.options.jsx;
@@ -14534,6 +15140,7 @@ class JSXText extends NodeBase {
14534
15140
  }
14535
15141
  }
14536
15142
  }
15143
+ JSXText.prototype.includeNode = onlyIncludeSelf;
14537
15144
 
14538
15145
  class LabeledStatement extends NodeBase {
14539
15146
  hasEffects(context) {
@@ -14555,17 +15162,22 @@ class LabeledStatement extends NodeBase {
14555
15162
  return bodyHasEffects;
14556
15163
  }
14557
15164
  include(context, includeChildrenRecursively) {
14558
- this.included = true;
15165
+ if (!this.included)
15166
+ this.includeNode(context);
14559
15167
  const { brokenFlow, includedLabels } = context;
14560
15168
  context.includedLabels = new Set();
14561
15169
  this.body.include(context, includeChildrenRecursively);
14562
15170
  if (includeChildrenRecursively || context.includedLabels.has(this.label.name)) {
14563
- this.label.include();
15171
+ this.label.include(context);
14564
15172
  context.includedLabels.delete(this.label.name);
14565
15173
  context.brokenFlow = brokenFlow;
14566
15174
  }
14567
15175
  context.includedLabels = new Set([...includedLabels, ...context.includedLabels]);
14568
15176
  }
15177
+ includeNode(context) {
15178
+ this.included = true;
15179
+ this.body.includePath(UNKNOWN_PATH, context);
15180
+ }
14569
15181
  render(code, options) {
14570
15182
  if (this.label.included) {
14571
15183
  this.label.render(code, options);
@@ -14576,6 +15188,7 @@ class LabeledStatement extends NodeBase {
14576
15188
  this.body.render(code, options);
14577
15189
  }
14578
15190
  }
15191
+ LabeledStatement.prototype.applyDeoptimizations = doNotDeoptimize;
14579
15192
 
14580
15193
  class LogicalExpression extends NodeBase {
14581
15194
  constructor() {
@@ -14592,10 +15205,10 @@ class LogicalExpression extends NodeBase {
14592
15205
  this.flags = setFlag(this.flags, 65536 /* Flag.isBranchResolutionAnalysed */, value);
14593
15206
  }
14594
15207
  get hasDeoptimizedCache() {
14595
- return isFlagSet(this.flags, 16777216 /* Flag.hasDeoptimizedCache */);
15208
+ return isFlagSet(this.flags, 33554432 /* Flag.hasDeoptimizedCache */);
14596
15209
  }
14597
15210
  set hasDeoptimizedCache(value) {
14598
- this.flags = setFlag(this.flags, 16777216 /* Flag.hasDeoptimizedCache */, value);
15211
+ this.flags = setFlag(this.flags, 33554432 /* Flag.hasDeoptimizedCache */, value);
14599
15212
  }
14600
15213
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
14601
15214
  this.left.deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -14608,6 +15221,10 @@ class LogicalExpression extends NodeBase {
14608
15221
  const unusedBranch = this.usedBranch === this.left ? this.right : this.left;
14609
15222
  this.usedBranch = null;
14610
15223
  unusedBranch.deoptimizePath(UNKNOWN_PATH);
15224
+ if (this.included) {
15225
+ // As we are not tracking inclusions, we just include everything
15226
+ unusedBranch.includePath(UNKNOWN_PATH, createInclusionContext());
15227
+ }
14611
15228
  }
14612
15229
  const { scope: { context }, expressionsToBeDeoptimized } = this;
14613
15230
  this.expressionsToBeDeoptimized = parseAst_js.EMPTY_ARRAY;
@@ -14653,16 +15270,17 @@ class LogicalExpression extends NodeBase {
14653
15270
  }
14654
15271
  getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin) {
14655
15272
  const usedBranch = this.getUsedBranch();
14656
- if (!usedBranch)
14657
- return [
14658
- new MultiExpression([
14659
- this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
14660
- this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
14661
- ]),
14662
- false
14663
- ];
14664
- this.expressionsToBeDeoptimized.push(origin);
14665
- return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
15273
+ if (usedBranch) {
15274
+ this.expressionsToBeDeoptimized.push(origin);
15275
+ return usedBranch.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin);
15276
+ }
15277
+ return [
15278
+ new MultiExpression([
15279
+ this.left.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0],
15280
+ this.right.getReturnExpressionWhenCalledAtPath(path, interaction, recursionTracker, origin)[0]
15281
+ ]),
15282
+ false
15283
+ ];
14666
15284
  }
14667
15285
  hasEffects(context) {
14668
15286
  if (this.left.hasEffects(context)) {
@@ -14675,18 +15293,18 @@ class LogicalExpression extends NodeBase {
14675
15293
  }
14676
15294
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14677
15295
  const usedBranch = this.getUsedBranch();
14678
- if (!usedBranch) {
14679
- return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
14680
- this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
15296
+ if (usedBranch) {
15297
+ return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
14681
15298
  }
14682
- return usedBranch.hasEffectsOnInteractionAtPath(path, interaction, context);
15299
+ return (this.left.hasEffectsOnInteractionAtPath(path, interaction, context) ||
15300
+ this.right.hasEffectsOnInteractionAtPath(path, interaction, context));
14683
15301
  }
14684
15302
  include(context, includeChildrenRecursively) {
14685
15303
  this.included = true;
14686
15304
  const usedBranch = this.getUsedBranch();
14687
15305
  if (includeChildrenRecursively ||
14688
- (usedBranch === this.right && this.left.shouldBeIncluded(context)) ||
14689
- !usedBranch) {
15306
+ !usedBranch ||
15307
+ (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
14690
15308
  this.left.include(context, includeChildrenRecursively);
14691
15309
  this.right.include(context, includeChildrenRecursively);
14692
15310
  }
@@ -14694,6 +15312,17 @@ class LogicalExpression extends NodeBase {
14694
15312
  usedBranch.include(context, includeChildrenRecursively);
14695
15313
  }
14696
15314
  }
15315
+ includePath(path, context) {
15316
+ this.included = true;
15317
+ const usedBranch = this.getUsedBranch();
15318
+ if (!usedBranch || (usedBranch === this.right && this.left.shouldBeIncluded(context))) {
15319
+ this.left.includePath(path, context);
15320
+ this.right.includePath(path, context);
15321
+ }
15322
+ else {
15323
+ usedBranch.includePath(path, context);
15324
+ }
15325
+ }
14697
15326
  removeAnnotations(code) {
14698
15327
  this.left.removeAnnotations(code);
14699
15328
  }
@@ -14746,6 +15375,8 @@ class LogicalExpression extends NodeBase {
14746
15375
  return this.usedBranch;
14747
15376
  }
14748
15377
  }
15378
+ LogicalExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15379
+ LogicalExpression.prototype.applyDeoptimizations = doNotDeoptimize;
14749
15380
 
14750
15381
  class NewExpression extends NodeBase {
14751
15382
  hasEffects(context) {
@@ -14765,16 +15396,21 @@ class NewExpression extends NodeBase {
14765
15396
  return path.length > 0 || type !== INTERACTION_ACCESSED;
14766
15397
  }
14767
15398
  include(context, includeChildrenRecursively) {
14768
- if (!this.deoptimized)
14769
- this.applyDeoptimizations();
14770
15399
  if (includeChildrenRecursively) {
14771
15400
  super.include(context, includeChildrenRecursively);
14772
15401
  }
14773
15402
  else {
14774
- this.included = true;
15403
+ if (!this.included)
15404
+ this.includeNode(context);
14775
15405
  this.callee.include(context, false);
14776
15406
  }
14777
- this.callee.includeCallArguments(context, this.arguments);
15407
+ this.callee.includeCallArguments(context, this.interaction);
15408
+ }
15409
+ includeNode(context) {
15410
+ this.included = true;
15411
+ if (!this.deoptimized)
15412
+ this.applyDeoptimizations();
15413
+ this.callee.includePath(UNKNOWN_PATH, context);
14778
15414
  }
14779
15415
  initialise() {
14780
15416
  super.initialise();
@@ -14803,6 +15439,7 @@ class ObjectExpression extends NodeBase {
14803
15439
  constructor() {
14804
15440
  super(...arguments);
14805
15441
  this.objectEntity = null;
15442
+ this.protoProp = null;
14806
15443
  }
14807
15444
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
14808
15445
  this.getObjectEntity().deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker);
@@ -14822,15 +15459,43 @@ class ObjectExpression extends NodeBase {
14822
15459
  hasEffectsOnInteractionAtPath(path, interaction, context) {
14823
15460
  return this.getObjectEntity().hasEffectsOnInteractionAtPath(path, interaction, context);
14824
15461
  }
15462
+ include(context, includeChildrenRecursively) {
15463
+ if (!this.included)
15464
+ this.includeNode(context);
15465
+ this.getObjectEntity().include(context, includeChildrenRecursively);
15466
+ this.protoProp?.include(context, includeChildrenRecursively);
15467
+ }
15468
+ includeNode(context) {
15469
+ this.included = true;
15470
+ this.protoProp?.includePath(UNKNOWN_PATH, context);
15471
+ }
15472
+ includePath(path, context) {
15473
+ if (!this.included)
15474
+ this.includeNode(context);
15475
+ this.getObjectEntity().includePath(path, context);
15476
+ }
14825
15477
  render(code, options, { renderedSurroundingElement } = parseAst_js.BLANK) {
14826
- super.render(code, options);
14827
15478
  if (renderedSurroundingElement === parseAst_js.ExpressionStatement ||
14828
15479
  renderedSurroundingElement === parseAst_js.ArrowFunctionExpression) {
14829
15480
  code.appendRight(this.start, '(');
14830
15481
  code.prependLeft(this.end, ')');
14831
15482
  }
15483
+ if (this.properties.length > 0) {
15484
+ const separatedNodes = getCommaSeparatedNodesWithBoundaries(this.properties, code, this.start + 1, this.end - 1);
15485
+ let lastSeparatorPos = null;
15486
+ for (const { node, separator, start, end } of separatedNodes) {
15487
+ if (!node.included) {
15488
+ treeshakeNode(node, code, start, end);
15489
+ continue;
15490
+ }
15491
+ lastSeparatorPos = separator;
15492
+ node.render(code, options);
15493
+ }
15494
+ if (lastSeparatorPos) {
15495
+ code.remove(lastSeparatorPos, this.end - 1);
15496
+ }
15497
+ }
14832
15498
  }
14833
- applyDeoptimizations() { }
14834
15499
  getObjectEntity() {
14835
15500
  if (this.objectEntity !== null) {
14836
15501
  return this.objectEntity;
@@ -14859,6 +15524,7 @@ class ObjectExpression extends NodeBase {
14859
15524
  ? property.key.name
14860
15525
  : String(property.key.value);
14861
15526
  if (key === '__proto__' && property.kind === 'init') {
15527
+ this.protoProp = property;
14862
15528
  prototype =
14863
15529
  property.value instanceof Literal && property.value.value === null
14864
15530
  ? null
@@ -14871,6 +15537,7 @@ class ObjectExpression extends NodeBase {
14871
15537
  return (this.objectEntity = new ObjectEntity(properties, prototype));
14872
15538
  }
14873
15539
  }
15540
+ ObjectExpression.prototype.applyDeoptimizations = doNotDeoptimize;
14874
15541
 
14875
15542
  class PanicError extends NodeBase {
14876
15543
  initialise() {
@@ -14897,6 +15564,7 @@ class ParseError extends NodeBase {
14897
15564
 
14898
15565
  class PrivateIdentifier extends NodeBase {
14899
15566
  }
15567
+ PrivateIdentifier.prototype.includeNode = onlyIncludeSelf;
14900
15568
 
14901
15569
  class Program extends NodeBase {
14902
15570
  constructor() {
@@ -14964,14 +15632,11 @@ class Program extends NodeBase {
14964
15632
  super.render(code, options);
14965
15633
  }
14966
15634
  }
14967
- applyDeoptimizations() { }
14968
15635
  }
15636
+ Program.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15637
+ Program.prototype.applyDeoptimizations = doNotDeoptimize;
14969
15638
 
14970
15639
  class Property extends MethodBase {
14971
- constructor() {
14972
- super(...arguments);
14973
- this.declarationInit = null;
14974
- }
14975
15640
  //declare method: boolean;
14976
15641
  get method() {
14977
15642
  return isFlagSet(this.flags, 262144 /* Flag.method */);
@@ -14986,17 +15651,41 @@ class Property extends MethodBase {
14986
15651
  set shorthand(value) {
14987
15652
  this.flags = setFlag(this.flags, 524288 /* Flag.shorthand */, value);
14988
15653
  }
14989
- declare(kind, init) {
14990
- this.declarationInit = init;
14991
- return this.value.declare(kind, UNKNOWN_EXPRESSION);
15654
+ declare(kind, destructuredInitPath, init) {
15655
+ return this.value.declare(kind, this.getPathInProperty(destructuredInitPath), init);
15656
+ }
15657
+ deoptimizeAssignment(destructuredInitPath, init) {
15658
+ this.value.deoptimizeAssignment?.(this.getPathInProperty(destructuredInitPath), init);
14992
15659
  }
14993
15660
  hasEffects(context) {
14994
- if (!this.deoptimized)
14995
- this.applyDeoptimizations();
14996
- const propertyReadSideEffects = this.scope.context.options.treeshake.propertyReadSideEffects;
14997
- return ((this.parent.type === 'ObjectPattern' && propertyReadSideEffects === 'always') ||
14998
- this.key.hasEffects(context) ||
14999
- this.value.hasEffects(context));
15661
+ return this.key.hasEffects(context) || this.value.hasEffects(context);
15662
+ }
15663
+ hasEffectsWhenDestructuring(context, destructuredInitPath, init) {
15664
+ return this.value.hasEffectsWhenDestructuring?.(context, this.getPathInProperty(destructuredInitPath), init);
15665
+ }
15666
+ includeDestructuredIfNecessary(context, destructuredInitPath, init) {
15667
+ const path = this.getPathInProperty(destructuredInitPath);
15668
+ let included = this.value.includeDestructuredIfNecessary(context, path, init) ||
15669
+ this.included;
15670
+ if ((included ||= this.key.hasEffects(createHasEffectsContext()))) {
15671
+ this.key.include(context, false);
15672
+ if (!this.value.included) {
15673
+ this.value.included = true;
15674
+ // Unfortunately, we need to include the value again now, so that any
15675
+ // declared variables are properly included.
15676
+ this.value.includeDestructuredIfNecessary(context, path, init);
15677
+ }
15678
+ }
15679
+ return (this.included = included);
15680
+ }
15681
+ include(context, includeChildrenRecursively) {
15682
+ this.included = true;
15683
+ this.key.include(context, includeChildrenRecursively);
15684
+ this.value.include(context, includeChildrenRecursively);
15685
+ }
15686
+ includePath(path, context) {
15687
+ this.included = true;
15688
+ this.value.includePath(path, context);
15000
15689
  }
15001
15690
  markDeclarationReached() {
15002
15691
  this.value.markDeclarationReached();
@@ -15007,14 +15696,20 @@ class Property extends MethodBase {
15007
15696
  }
15008
15697
  this.value.render(code, options, { isShorthandProperty: this.shorthand });
15009
15698
  }
15010
- applyDeoptimizations() {
15011
- this.deoptimized = true;
15012
- if (this.declarationInit !== null) {
15013
- this.declarationInit.deoptimizePath([UnknownKey, UnknownKey]);
15014
- this.scope.context.requestTreeshakingPass();
15015
- }
15699
+ getPathInProperty(destructuredInitPath) {
15700
+ return destructuredInitPath.at(-1) === UnknownKey
15701
+ ? destructuredInitPath
15702
+ : // For now, we only consider static paths as we do not know how to
15703
+ // deoptimize the path in the dynamic case.
15704
+ this.computed
15705
+ ? [...destructuredInitPath, UnknownKey]
15706
+ : this.key instanceof Identifier
15707
+ ? [...destructuredInitPath, this.key.name]
15708
+ : [...destructuredInitPath, String(this.key.value)];
15016
15709
  }
15017
15710
  }
15711
+ Property.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15712
+ Property.prototype.applyDeoptimizations = doNotDeoptimize;
15018
15713
 
15019
15714
  class PropertyDefinition extends NodeBase {
15020
15715
  get computed() {
@@ -15047,8 +15742,15 @@ class PropertyDefinition extends NodeBase {
15047
15742
  hasEffectsOnInteractionAtPath(path, interaction, context) {
15048
15743
  return !this.value || this.value.hasEffectsOnInteractionAtPath(path, interaction, context);
15049
15744
  }
15050
- applyDeoptimizations() { }
15745
+ includeNode(context) {
15746
+ this.included = true;
15747
+ this.value?.includePath(UNKNOWN_PATH, context);
15748
+ for (const decorator of this.decorators) {
15749
+ decorator.includePath(UNKNOWN_PATH, context);
15750
+ }
15751
+ }
15051
15752
  }
15753
+ PropertyDefinition.prototype.applyDeoptimizations = doNotDeoptimize;
15052
15754
 
15053
15755
  class ReturnStatement extends NodeBase {
15054
15756
  hasEffects(context) {
@@ -15058,10 +15760,15 @@ class ReturnStatement extends NodeBase {
15058
15760
  return false;
15059
15761
  }
15060
15762
  include(context, includeChildrenRecursively) {
15061
- this.included = true;
15763
+ if (!this.included)
15764
+ this.includeNode(context);
15062
15765
  this.argument?.include(context, includeChildrenRecursively);
15063
15766
  context.brokenFlow = true;
15064
15767
  }
15768
+ includeNode(context) {
15769
+ this.included = true;
15770
+ this.argument?.includePath(UNKNOWN_PATH, context);
15771
+ }
15065
15772
  initialise() {
15066
15773
  super.initialise();
15067
15774
  this.scope.addReturnExpression(this.argument || UNKNOWN_EXPRESSION);
@@ -15075,6 +15782,7 @@ class ReturnStatement extends NodeBase {
15075
15782
  }
15076
15783
  }
15077
15784
  }
15785
+ ReturnStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15078
15786
 
15079
15787
  class SequenceExpression extends NodeBase {
15080
15788
  deoptimizeArgumentsOnInteractionAtPath(interaction, path, recursionTracker) {
@@ -15102,10 +15810,15 @@ class SequenceExpression extends NodeBase {
15102
15810
  for (const expression of this.expressions) {
15103
15811
  if (includeChildrenRecursively ||
15104
15812
  (expression === lastExpression && !(this.parent instanceof ExpressionStatement)) ||
15105
- expression.shouldBeIncluded(context))
15813
+ expression.shouldBeIncluded(context)) {
15106
15814
  expression.include(context, includeChildrenRecursively);
15815
+ }
15107
15816
  }
15108
15817
  }
15818
+ includePath(path, context) {
15819
+ this.included = true;
15820
+ this.expressions[this.expressions.length - 1].includePath(path, context);
15821
+ }
15109
15822
  removeAnnotations(code) {
15110
15823
  this.expressions[0].removeAnnotations(code);
15111
15824
  }
@@ -15140,6 +15853,8 @@ class SequenceExpression extends NodeBase {
15140
15853
  }
15141
15854
  }
15142
15855
  }
15856
+ SequenceExpression.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15857
+ SequenceExpression.prototype.applyDeoptimizations = doNotDeoptimize;
15143
15858
 
15144
15859
  class Super extends NodeBase {
15145
15860
  bind() {
@@ -15151,11 +15866,15 @@ class Super extends NodeBase {
15151
15866
  deoptimizePath(path) {
15152
15867
  this.variable.deoptimizePath(path);
15153
15868
  }
15154
- include() {
15155
- if (!this.included) {
15156
- this.included = true;
15157
- this.scope.context.includeVariableInModule(this.variable);
15158
- }
15869
+ include(context) {
15870
+ if (!this.included)
15871
+ this.includeNode(context);
15872
+ }
15873
+ includeNode(context) {
15874
+ this.included = true;
15875
+ if (!this.deoptimized)
15876
+ this.applyDeoptimizations();
15877
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
15159
15878
  }
15160
15879
  }
15161
15880
 
@@ -15196,6 +15915,8 @@ class SwitchCase extends NodeBase {
15196
15915
  }
15197
15916
  }
15198
15917
  SwitchCase.prototype.needsBoundaries = true;
15918
+ SwitchCase.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
15919
+ SwitchCase.prototype.applyDeoptimizations = doNotDeoptimize;
15199
15920
 
15200
15921
  class SwitchStatement extends NodeBase {
15201
15922
  createScope(parentScope) {
@@ -15278,6 +15999,8 @@ class SwitchStatement extends NodeBase {
15278
15999
  }
15279
16000
  }
15280
16001
  }
16002
+ SwitchStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16003
+ SwitchStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15281
16004
 
15282
16005
  class TaggedTemplateExpression extends CallExpressionBase {
15283
16006
  bind() {
@@ -15301,8 +16024,8 @@ class TaggedTemplateExpression extends CallExpressionBase {
15301
16024
  this.tag.hasEffectsOnInteractionAtPath(EMPTY_PATH, this.interaction, context));
15302
16025
  }
15303
16026
  include(context, includeChildrenRecursively) {
15304
- if (!this.deoptimized)
15305
- this.applyDeoptimizations();
16027
+ if (!this.included)
16028
+ this.includeNode(context);
15306
16029
  if (includeChildrenRecursively) {
15307
16030
  super.include(context, includeChildrenRecursively);
15308
16031
  }
@@ -15311,7 +16034,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
15311
16034
  this.tag.include(context, includeChildrenRecursively);
15312
16035
  this.quasi.include(context, includeChildrenRecursively);
15313
16036
  }
15314
- this.tag.includeCallArguments(context, this.args);
16037
+ this.tag.includeCallArguments(context, this.interaction);
15315
16038
  const [returnExpression] = this.getReturnExpression();
15316
16039
  if (!returnExpression.included) {
15317
16040
  returnExpression.include(context, false);
@@ -15346,6 +16069,7 @@ class TaggedTemplateExpression extends CallExpressionBase {
15346
16069
  return this.returnExpression;
15347
16070
  }
15348
16071
  }
16072
+ TaggedTemplateExpression.prototype.includeNode = onlyIncludeSelf;
15349
16073
 
15350
16074
  class TemplateElement extends NodeBase {
15351
16075
  get tail() {
@@ -15359,15 +16083,13 @@ class TemplateElement extends NodeBase {
15359
16083
  hasEffects() {
15360
16084
  return false;
15361
16085
  }
15362
- include() {
15363
- this.included = true;
15364
- }
15365
16086
  parseNode(esTreeNode) {
15366
16087
  this.value = esTreeNode.value;
15367
16088
  return super.parseNode(esTreeNode);
15368
16089
  }
15369
16090
  render() { }
15370
16091
  }
16092
+ TemplateElement.prototype.includeNode = onlyIncludeSelf;
15371
16093
 
15372
16094
  class TemplateLiteral extends NodeBase {
15373
16095
  deoptimizeArgumentsOnInteractionAtPath() { }
@@ -15392,6 +16114,14 @@ class TemplateLiteral extends NodeBase {
15392
16114
  }
15393
16115
  return true;
15394
16116
  }
16117
+ includeNode(context) {
16118
+ this.included = true;
16119
+ if (!this.deoptimized)
16120
+ this.applyDeoptimizations();
16121
+ for (const node of this.expressions) {
16122
+ node.includePath(UNKNOWN_PATH, context);
16123
+ }
16124
+ }
15395
16125
  render(code, options) {
15396
16126
  code.indentExclusionRanges.push([this.start, this.end]);
15397
16127
  super.render(code, options);
@@ -15401,13 +16131,13 @@ class TemplateLiteral extends NodeBase {
15401
16131
  class ModuleScope extends ChildScope {
15402
16132
  constructor(parent, context) {
15403
16133
  super(parent, context);
15404
- this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, context, 'other'));
16134
+ this.variables.set('this', new LocalVariable('this', null, UNDEFINED_EXPRESSION, EMPTY_PATH, context, 'other'));
15405
16135
  }
15406
- addDeclaration(identifier, context, init, kind) {
16136
+ addDeclaration(identifier, context, init, destructuredInitPath, kind) {
15407
16137
  if (this.context.module.importDescriptions.has(identifier.name)) {
15408
16138
  context.error(parseAst_js.logRedeclarationError(identifier.name), identifier.start);
15409
16139
  }
15410
- return super.addDeclaration(identifier, context, init, kind);
16140
+ return super.addDeclaration(identifier, context, init, destructuredInitPath, kind);
15411
16141
  }
15412
16142
  addExportDefaultDeclaration(name, exportDefaultDeclaration, context) {
15413
16143
  const variable = new ExportDefaultVariable(name, exportDefaultDeclaration, context);
@@ -15452,10 +16182,23 @@ class ThisExpression extends NodeBase {
15452
16182
  }
15453
16183
  return this.variable.hasEffectsOnInteractionAtPath(path, interaction, context);
15454
16184
  }
15455
- include() {
16185
+ include(context) {
16186
+ if (!this.included)
16187
+ this.includeNode(context);
16188
+ }
16189
+ includeNode(context) {
16190
+ this.included = true;
16191
+ if (!this.deoptimized)
16192
+ this.applyDeoptimizations();
16193
+ this.scope.context.includeVariableInModule(this.variable, EMPTY_PATH, context);
16194
+ }
16195
+ includePath(path, context) {
15456
16196
  if (!this.included) {
15457
16197
  this.included = true;
15458
- this.scope.context.includeVariableInModule(this.variable);
16198
+ this.scope.context.includeVariableInModule(this.variable, path, context);
16199
+ }
16200
+ else if (path.length > 0) {
16201
+ this.variable.includePath(path, context);
15459
16202
  }
15460
16203
  }
15461
16204
  initialise() {
@@ -15483,7 +16226,8 @@ class ThrowStatement extends NodeBase {
15483
16226
  return true;
15484
16227
  }
15485
16228
  include(context, includeChildrenRecursively) {
15486
- this.included = true;
16229
+ if (!this.included)
16230
+ this.includeNode(context);
15487
16231
  this.argument.include(context, includeChildrenRecursively);
15488
16232
  context.brokenFlow = true;
15489
16233
  }
@@ -15494,6 +16238,7 @@ class ThrowStatement extends NodeBase {
15494
16238
  }
15495
16239
  }
15496
16240
  }
16241
+ ThrowStatement.prototype.includeNode = onlyIncludeSelf;
15497
16242
 
15498
16243
  class TryStatement extends NodeBase {
15499
16244
  constructor() {
@@ -15530,6 +16275,8 @@ class TryStatement extends NodeBase {
15530
16275
  this.finalizer?.include(context, includeChildrenRecursively);
15531
16276
  }
15532
16277
  }
16278
+ TryStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16279
+ TryStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15533
16280
 
15534
16281
  const unaryOperators = {
15535
16282
  '!': value => !value,
@@ -15575,6 +16322,7 @@ class UnaryExpression extends NodeBase {
15575
16322
  }
15576
16323
  }
15577
16324
  }
16325
+ UnaryExpression.prototype.includeNode = onlyIncludeSelf;
15578
16326
 
15579
16327
  class UpdateExpression extends NodeBase {
15580
16328
  hasEffects(context) {
@@ -15586,9 +16334,8 @@ class UpdateExpression extends NodeBase {
15586
16334
  return path.length > 1 || type !== INTERACTION_ACCESSED;
15587
16335
  }
15588
16336
  include(context, includeChildrenRecursively) {
15589
- if (!this.deoptimized)
15590
- this.applyDeoptimizations();
15591
- this.included = true;
16337
+ if (!this.included)
16338
+ this.includeNode(context);
15592
16339
  this.argument.includeAsAssignmentTarget(context, includeChildrenRecursively, true);
15593
16340
  }
15594
16341
  initialise() {
@@ -15627,6 +16374,7 @@ class UpdateExpression extends NodeBase {
15627
16374
  this.scope.context.requestTreeshakingPass();
15628
16375
  }
15629
16376
  }
16377
+ UpdateExpression.prototype.includeNode = onlyIncludeSelf;
15630
16378
 
15631
16379
  function areAllDeclarationsIncludedAndNotExported(declarations, exportNamesByVariable) {
15632
16380
  for (const declarator of declarations) {
@@ -15657,8 +16405,9 @@ class VariableDeclaration extends NodeBase {
15657
16405
  include(context, includeChildrenRecursively, { asSingleStatement } = parseAst_js.BLANK) {
15658
16406
  this.included = true;
15659
16407
  for (const declarator of this.declarations) {
15660
- if (includeChildrenRecursively || declarator.shouldBeIncluded(context))
16408
+ if (includeChildrenRecursively || declarator.shouldBeIncluded(context)) {
15661
16409
  declarator.include(context, includeChildrenRecursively);
16410
+ }
15662
16411
  const { id, init } = declarator;
15663
16412
  if (asSingleStatement) {
15664
16413
  id.include(context, includeChildrenRecursively);
@@ -15696,7 +16445,6 @@ class VariableDeclaration extends NodeBase {
15696
16445
  this.renderReplacedDeclarations(code, options);
15697
16446
  }
15698
16447
  }
15699
- applyDeoptimizations() { }
15700
16448
  renderDeclarationEnd(code, separatorString, lastSeparatorPos, actualContentEnd, renderedContentEnd, systemPatternExports, options) {
15701
16449
  if (code.original.charCodeAt(this.end - 1) === 59 /*";"*/) {
15702
16450
  code.remove(this.end - 1, this.end);
@@ -15739,8 +16487,7 @@ class VariableDeclaration extends NodeBase {
15739
16487
  const singleSystemExport = gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregatedSystemExports);
15740
16488
  for (const { node, start, separator, contentEnd, end } of separatedNodes) {
15741
16489
  if (!node.included) {
15742
- code.remove(start, end);
15743
- node.removeAnnotations(code);
16490
+ treeshakeNode(node, code, start, end);
15744
16491
  continue;
15745
16492
  }
15746
16493
  node.render(code, options);
@@ -15810,6 +16557,8 @@ function gatherSystemExportsAndGetSingleExport(separatedNodes, options, aggregat
15810
16557
  }
15811
16558
  return singleSystemExport;
15812
16559
  }
16560
+ VariableDeclaration.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16561
+ VariableDeclaration.prototype.applyDeoptimizations = doNotDeoptimize;
15813
16562
 
15814
16563
  class WhileStatement extends NodeBase {
15815
16564
  hasEffects(context) {
@@ -15823,13 +16572,25 @@ class WhileStatement extends NodeBase {
15823
16572
  includeLoopBody(context, this.body, includeChildrenRecursively);
15824
16573
  }
15825
16574
  }
16575
+ WhileStatement.prototype.includeNode = onlyIncludeSelfNoDeoptimize;
16576
+ WhileStatement.prototype.applyDeoptimizations = doNotDeoptimize;
15826
16577
 
15827
16578
  class YieldExpression extends NodeBase {
16579
+ applyDeoptimizations() {
16580
+ this.deoptimized = true;
16581
+ this.argument?.deoptimizePath(UNKNOWN_PATH);
16582
+ }
15828
16583
  hasEffects(context) {
15829
16584
  if (!this.deoptimized)
15830
16585
  this.applyDeoptimizations();
15831
16586
  return !(context.ignore.returnYield && !this.argument?.hasEffects(context));
15832
16587
  }
16588
+ includeNode(context) {
16589
+ this.included = true;
16590
+ if (!this.deoptimized)
16591
+ this.applyDeoptimizations();
16592
+ this.argument?.includePath(UNKNOWN_PATH, context);
16593
+ }
15833
16594
  render(code, options) {
15834
16595
  if (this.argument) {
15835
16596
  this.argument.render(code, options, { preventASI: true });
@@ -16063,7 +16824,7 @@ const bufferParsers = [
16063
16824
  const annotations = (node.annotations = parseAst_js.convertAnnotations(buffer[position + 1], buffer));
16064
16825
  node.annotationNoSideEffects = annotations.some(comment => comment.type === 'noSideEffects');
16065
16826
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 2], buffer));
16066
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16827
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16067
16828
  node.body = convertNode(node, scope.bodyScope, buffer[position + 3], buffer);
16068
16829
  },
16069
16830
  function assignmentExpression(node, position, buffer) {
@@ -16109,7 +16870,7 @@ const bufferParsers = [
16109
16870
  const parameterPosition = buffer[position];
16110
16871
  const parameter = (node.param =
16111
16872
  parameterPosition === 0 ? null : convertNode(node, scope, parameterPosition, buffer));
16112
- parameter?.declare('parameter', UNKNOWN_EXPRESSION);
16873
+ parameter?.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION);
16113
16874
  node.body = convertNode(node, scope.bodyScope, buffer[position + 1], buffer);
16114
16875
  },
16115
16876
  function chainExpression(node, position, buffer) {
@@ -16247,7 +17008,7 @@ const bufferParsers = [
16247
17008
  node.id =
16248
17009
  idPosition === 0 ? null : convertNode(node, scope.parent, idPosition, buffer);
16249
17010
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 3], buffer));
16250
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
17011
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16251
17012
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
16252
17013
  },
16253
17014
  function functionExpression(node, position, buffer) {
@@ -16260,7 +17021,7 @@ const bufferParsers = [
16260
17021
  const idPosition = buffer[position + 2];
16261
17022
  node.id = idPosition === 0 ? null : convertNode(node, node.idScope, idPosition, buffer);
16262
17023
  const parameters = (node.params = convertNodeList(node, scope, buffer[position + 3], buffer));
16263
- scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
17024
+ scope.addParameterVariables(parameters.map(parameter => parameter.declare('parameter', EMPTY_PATH, UNKNOWN_EXPRESSION)), parameters[parameters.length - 1] instanceof RestElement);
16264
17025
  node.body = convertNode(node, scope.bodyScope, buffer[position + 4], buffer);
16265
17026
  },
16266
17027
  function identifier(node, position, buffer) {
@@ -16724,8 +17485,8 @@ class ExportShimVariable extends Variable {
16724
17485
  super(MISSING_EXPORT_SHIM_VARIABLE);
16725
17486
  this.module = module;
16726
17487
  }
16727
- include() {
16728
- super.include();
17488
+ includePath(path, context) {
17489
+ super.includePath(path, context);
16729
17490
  this.module.needsExportShim = true;
16730
17491
  }
16731
17492
  }
@@ -17416,16 +18177,15 @@ class Module {
17416
18177
  markModuleAndImpureDependenciesAsExecuted(this);
17417
18178
  this.graph.needsTreeshakingPass = true;
17418
18179
  }
18180
+ const inclusionContext = createInclusionContext();
17419
18181
  for (const exportName of this.exports.keys()) {
17420
18182
  if (includeNamespaceMembers || exportName !== this.info.syntheticNamedExports) {
17421
18183
  const variable = this.getVariableForExportName(exportName)[0];
17422
18184
  if (!variable) {
17423
18185
  return parseAst_js.error(parseAst_js.logMissingEntryExport(exportName, this.id));
17424
18186
  }
18187
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17425
18188
  variable.deoptimizePath(UNKNOWN_PATH);
17426
- if (!variable.included) {
17427
- this.includeVariable(variable);
17428
- }
17429
18189
  }
17430
18190
  }
17431
18191
  for (const name of this.getReexports()) {
@@ -17433,7 +18193,7 @@ class Module {
17433
18193
  if (variable) {
17434
18194
  variable.deoptimizePath(UNKNOWN_PATH);
17435
18195
  if (!variable.included) {
17436
- this.includeVariable(variable);
18196
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17437
18197
  }
17438
18198
  if (variable instanceof ExternalVariable) {
17439
18199
  variable.module.reexported = true;
@@ -17454,13 +18214,12 @@ class Module {
17454
18214
  this.graph.needsTreeshakingPass = true;
17455
18215
  }
17456
18216
  let includeNamespaceMembers = false;
18217
+ const inclusionContext = createInclusionContext();
17457
18218
  for (const name of names) {
17458
18219
  const variable = this.getVariableForExportName(name)[0];
17459
18220
  if (variable) {
17460
18221
  variable.deoptimizePath(UNKNOWN_PATH);
17461
- if (!variable.included) {
17462
- this.includeVariable(variable);
17463
- }
18222
+ this.includeVariable(variable, UNKNOWN_PATH, inclusionContext);
17464
18223
  }
17465
18224
  if (!this.exports.has(name) && !this.reexportDescriptions.has(name)) {
17466
18225
  includeNamespaceMembers = true;
@@ -17561,6 +18320,7 @@ class Module {
17561
18320
  manualPureFunctions: this.graph.pureFunctions,
17562
18321
  module: this,
17563
18322
  moduleContext: this.context,
18323
+ newlyIncludedVariableInits: this.graph.newlyIncludedVariableInits,
17564
18324
  options: this.options,
17565
18325
  requestTreeshakingPass: () => (this.graph.needsTreeshakingPass = true),
17566
18326
  traceExport: (name) => this.getVariableForExportName(name)[0],
@@ -17901,13 +18661,13 @@ class Module {
17901
18661
  for (const module of [this, ...this.exportAllModules]) {
17902
18662
  if (module instanceof ExternalModule) {
17903
18663
  const [externalVariable] = module.getVariableForExportName('*');
17904
- externalVariable.include();
18664
+ externalVariable.includePath(UNKNOWN_PATH, createInclusionContext());
17905
18665
  this.includedImports.add(externalVariable);
17906
18666
  externalNamespaces.add(externalVariable);
17907
18667
  }
17908
18668
  else if (module.info.syntheticNamedExports) {
17909
18669
  const syntheticNamespace = module.getSyntheticNamespace();
17910
- syntheticNamespace.include();
18670
+ syntheticNamespace.includePath(UNKNOWN_PATH, createInclusionContext());
17911
18671
  this.includedImports.add(syntheticNamespace);
17912
18672
  syntheticNamespaces.add(syntheticNamespace);
17913
18673
  }
@@ -17917,7 +18677,9 @@ class Module {
17917
18677
  includeDynamicImport(node) {
17918
18678
  const resolution = this.dynamicImports.find(dynamicImport => dynamicImport.node === node).resolution;
17919
18679
  if (resolution instanceof Module) {
17920
- resolution.includedDynamicImporters.push(this);
18680
+ if (!resolution.includedDynamicImporters.includes(this)) {
18681
+ resolution.includedDynamicImporters.push(this);
18682
+ }
17921
18683
  const importedNames = this.options.treeshake
17922
18684
  ? node.getDeterministicImportedNames()
17923
18685
  : undefined;
@@ -17929,15 +18691,15 @@ class Module {
17929
18691
  }
17930
18692
  }
17931
18693
  }
17932
- includeVariable(variable) {
17933
- const variableModule = variable.module;
17934
- if (variable.included) {
18694
+ includeVariable(variable, path, context) {
18695
+ const { included, module: variableModule } = variable;
18696
+ variable.includePath(path, context);
18697
+ if (included) {
17935
18698
  if (variableModule instanceof Module && variableModule !== this) {
17936
18699
  getAndExtendSideEffectModules(variable, this);
17937
18700
  }
17938
18701
  }
17939
18702
  else {
17940
- variable.include();
17941
18703
  this.graph.needsTreeshakingPass = true;
17942
18704
  if (variableModule instanceof Module) {
17943
18705
  if (!variableModule.isExecuted) {
@@ -17954,8 +18716,8 @@ class Module {
17954
18716
  }
17955
18717
  }
17956
18718
  }
17957
- includeVariableInModule(variable) {
17958
- this.includeVariable(variable);
18719
+ includeVariableInModule(variable, path, context) {
18720
+ this.includeVariable(variable, path, context);
17959
18721
  const variableModule = variable.module;
17960
18722
  if (variableModule && variableModule !== this) {
17961
18723
  this.includedImports.add(variable);
@@ -21458,10 +22220,11 @@ class Graph {
21458
22220
  this.options = options;
21459
22221
  this.astLru = flru(5);
21460
22222
  this.cachedModules = new Map();
21461
- this.deoptimizationTracker = new PathTracker();
22223
+ this.deoptimizationTracker = new EntityPathTracker();
21462
22224
  this.entryModules = [];
21463
22225
  this.modulesById = new Map();
21464
22226
  this.needsTreeshakingPass = false;
22227
+ this.newlyIncludedVariableInits = new Set();
21465
22228
  this.phase = BuildPhase.LOAD_AND_PARSE;
21466
22229
  this.scope = new GlobalScope();
21467
22230
  this.watchFiles = Object.create(null);
@@ -21555,6 +22318,7 @@ class Graph {
21555
22318
  }
21556
22319
  if (this.options.treeshake) {
21557
22320
  let treeshakingPass = 1;
22321
+ this.newlyIncludedVariableInits.clear();
21558
22322
  do {
21559
22323
  timeStart(`treeshaking pass ${treeshakingPass}`, 3);
21560
22324
  this.needsTreeshakingPass = false;
@@ -21579,6 +22343,10 @@ class Graph {
21579
22343
  }
21580
22344
  }
21581
22345
  }
22346
+ for (const entity of this.newlyIncludedVariableInits) {
22347
+ this.newlyIncludedVariableInits.delete(entity);
22348
+ entity.include(createInclusionContext(), false);
22349
+ }
21582
22350
  timeEnd(`treeshaking pass ${treeshakingPass++}`, 3);
21583
22351
  } while (this.needsTreeshakingPass);
21584
22352
  }